backup
[lcr.git] / admin_server.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** Socket link                                                               **
9 **                                                                           **
10 \*****************************************************************************/
11
12 #include <stdio.h>
13 //#include <stdlib.h>
14 //#include <string.h>
15 #include <sys/types.h>
16 //#include <sys/stat.h>
17 //#include <unistd.h>
18 //#include <signal.h>
19 //#include <stdarg.h>
20 //#include <fcntl.h>
21 #include <sys/ioctl.h>
22 //#include <sys/file.h>
23 //#include <errno.h>
24 //#include <sys/mman.h>
25 //#include <sys/resource.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <curses.h>
29 #include "main.h"
30
31
32 char *socket_name = SOCKET_NAME;
33 int sock = -1;
34 struct sockaddr_un sock_address;
35
36 struct admin_list *admin_list = NULL;
37
38 /*
39  * initialize admin socket 
40  */
41 int admin_init(void)
42 {
43         unsigned long on = 1;
44
45         /* open and bind socket */
46         if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
47         {
48                 PERROR("Failed to create admin socket. (errno=%d)\n", errno);
49                 return(-1);
50         }
51         fhuse++;
52         memset(&sock_address, 0, sizeof(sock_address));
53         sock_address.sun_family = AF_UNIX;
54         UCPY(sock_address.sun_path, socket_name);
55         unlink(socket_name);
56         if (bind(sock, (struct sockaddr *)(&sock_address), SUN_LEN(&sock_address)) < 0)
57         {
58                 close(sock);
59                 unlink(socket_name);
60                 fhuse--;
61                 sock = -1;
62                 PERROR("Failed to bind admin socket to \"%s\". (errno=%d)\n", sock_address.sun_path, errno);
63                 return(-1);
64         }
65         if (listen(sock, 5) < 0)
66         {
67                 close(sock);
68                 unlink(socket_name);
69                 fhuse--;
70                 sock = -1;
71                 PERROR("Failed to listen to socket \"%s\". (errno=%d)\n", sock_address.sun_path, errno);
72                 return(-1);
73         }
74         if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0)
75         {
76                 close(sock);
77                 unlink(socket_name);
78                 fhuse--;
79                 sock = -1;
80                 PERROR("Failed to set socket \"%s\" into non-blocking mode. (errno=%d)\n", sock_address.sun_path, errno);
81                 return(-1);
82         }
83         return(0);
84 }
85
86
87 /*
88  * free connection
89  */
90 void free_connection(struct admin_list *admin)
91 {
92         struct admin_queue *response;
93         void *temp;
94
95         if (admin->sock >= 0)
96         {
97                 close(admin->sock);
98                 fhuse--;
99         }
100 //      printf("new\n", response);
101         response = admin->response;
102         while (response)
103         {
104 //#warning
105 //      printf("%x\n", response);
106                 temp = response->next;
107                 free(response);
108                 memuse--;
109                 response = (struct admin_queue *)temp;
110         }
111 //      printf("new2\n", response);
112         free(admin);
113 //      printf("new3\n", response);
114         memuse--;
115 }
116
117
118 /*
119  * cleanup admin socket 
120  */
121 void admin_cleanup(void)
122 {
123         struct admin_list *admin, *next;;
124
125         admin = admin_list;
126         while(admin)
127         {
128 //printf("clean\n");
129                 next = admin->next;
130                 free_connection(admin);
131                 admin = next;
132         }
133
134         if (sock >= 0)
135         {
136                 close(sock);
137                 fhuse--;
138         }
139 }
140
141
142 /*
143  * do interface reload
144  */
145 int admin_interface(struct admin_queue **responsep)
146 {
147         struct admin_queue      *response;      /* response pointer */
148         char                    *err_txt = "";
149         int                     err = 0;
150
151         if (read_interfaces())
152         {
153                 relink_interfaces();
154                 free_interfaces(interface_first);
155                 interface_first = interface_newlist;
156                 interface_newlist = NULL;
157         } else
158         {
159                 err_txt = interface_error;
160                 err = -1;
161         }
162         /* create state response */
163         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
164         if (!response)
165                 return(-1);
166         memuse++;
167         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
168         response->num = 1;
169         /* message */
170         response->am[0].message = ADMIN_RESPONSE_CMD_INTERFACE;
171         /* error */
172         response->am[0].u.x.error = err;
173         /* message */
174         SCPY(response->am[0].u.x.message, err_txt);
175         /* attach to response chain */
176         *responsep = response;
177         responsep = &response->next;
178
179         return(0);
180 }
181
182
183 /*
184  * do route reload
185  */
186 int admin_route(struct admin_queue **responsep)
187 {
188         struct route_ruleset    *ruleset_new;
189         struct admin_queue      *response;      /* response pointer */
190         char                    err_txt[256] = "";
191         int                     err = 0;
192 #if 0
193         int                     n;
194 #endif
195         class EndpointAppPBX    *apppbx;
196
197 #if 0
198         n = 0;
199         apppbx = apppbx_first;
200         while(apppbx)
201         {
202                 n++;
203                 apppbx = apppbx->next;
204         }
205         if (apppbx_first)
206         {
207                 SPRINT(err_txt, "Cannot reload routing, because %d endpoints active\n", n);
208                 err = -1;
209                 goto response;
210         }
211 #endif
212         if (!(ruleset_new = ruleset_parse()))
213         {
214                 SPRINT(err_txt, ruleset_error);
215                 err = -1;
216                 goto response;
217         }
218         ruleset_free(ruleset_first);
219         ruleset_first = ruleset_new;
220         ruleset_main = getrulesetbyname("main");
221         if (!ruleset_main)
222         {
223                 SPRINT(err_txt, "Ruleset reloaded, but rule 'main' not found.\n");
224                 err = -1;
225         }
226         apppbx = apppbx_first;
227         while(apppbx)
228         {
229                 if (apppbx->e_action)
230                 {
231                         switch(apppbx->e_action->index)
232                         {
233                                 case ACTION_INTERNAL:
234                                 apppbx->e_action = &action_internal;
235                                 break;
236                                 case ACTION_EXTERNAL:
237                                 apppbx->e_action = &action_external;
238                                 break;
239                                 case ACTION_CHAN:
240                                 apppbx->e_action = &action_chan;
241                                 break;
242                                 case ACTION_VBOX_RECORD:
243                                 apppbx->e_action = &action_vbox;
244                                 break;
245                                 case ACTION_PARTYLINE:
246                                 apppbx->e_action = &action_partyline;
247                                 break;
248                                 default:
249                                 goto release;
250                         }
251                 } else if (apppbx->e_state != EPOINT_STATE_CONNECT)
252                 {
253                         release:
254                         apppbx->e_callback = 0;
255                         apppbx->e_action = NULL;
256                         apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
257                         start_trace(0,
258                                 NULL,
259                                 numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype),
260                                 apppbx->e_dialinginfo.id,
261                                 DIRECTION_NONE,
262                                 CATEGORY_EP,
263                                 apppbx->ea_endpoint->ep_serial,
264                                 "KICK (reload routing)");
265                 }
266
267                 apppbx->e_action_timeout = NULL;
268                 apppbx->e_rule = NULL;
269                 apppbx->e_ruleset = NULL;
270
271                 apppbx = apppbx->next;
272         }
273
274         response:
275         /* create state response */
276         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
277         if (!response)
278                 return(-1);
279         memuse++;
280         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
281         response->num = 1;
282         /* message */
283         response->am[0].message = ADMIN_RESPONSE_CMD_ROUTE;
284         /* error */
285         response->am[0].u.x.error = err;
286         /* message */
287         SCPY(response->am[0].u.x.message, err_txt);
288         /* attach to response chain */
289         *responsep = response;
290         responsep = &response->next;
291
292         return(0);
293 }
294
295
296 /*
297  * do dialing
298  */
299 int admin_dial(struct admin_queue **responsep, char *message)
300 {
301         struct extension        ext;            /* temporary extension's settings */
302         struct admin_queue      *response;      /* response pointer */
303         char                    *p;             /* pointer to dialing digits */
304
305         /* create state response */
306         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
307         if (!response)
308                 return(-1);
309         memuse++;
310         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
311         response->num = 1;
312         /* message */
313         response->am[0].message = ADMIN_RESPONSE_CMD_DIAL;
314
315         /* process request */
316         if (!(p = strchr(message,':')))
317         {
318                 response->am[0].u.x.error = -EINVAL;
319                 SPRINT(response->am[0].u.x.message, "no seperator ':' in message to seperate number from extension");
320                 goto out;
321         }
322         *p++ = 0;
323
324         /* modify extension */
325         if (!read_extension(&ext, message))
326         {
327                 response->am[0].u.x.error = -EINVAL;
328                 SPRINT(response->am[0].u.x.message, "extension doesn't exist");
329                 goto out;
330         }
331         SCPY(ext.next, p);
332         write_extension(&ext, message);
333
334         out:
335         /* attach to response chain */
336         *responsep = response;
337         responsep = &response->next;
338         return(0);
339 }
340
341
342 /*
343  * do blocking
344  * 
345  * 0 = make port available
346  * 1 = make port administratively blocked
347  * 2 = unload port
348  * the result is returned:
349  * 0 = port is now available
350  * 1 = port is now blocked
351  * 2 = port cannot be loaded or has been unloaded
352  * -1 = port doesn't exist
353  */
354 int admin_block(struct admin_queue **responsep, int portnum, int block)
355 {
356         struct admin_queue      *response;      /* response pointer */
357         struct interface        *interface;
358         struct interface_port   *ifport;
359
360         /* create block response */
361         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
362         if (!response)
363                 return(-1);
364         memuse++;
365         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
366         response->num = 1;
367         /* message */
368         response->am[0].message = ADMIN_RESPONSE_CMD_BLOCK;
369         response->am[0].u.x.portnum = portnum;
370
371         /* search for port */
372         interface = interface_first;
373         while(interface)
374         {
375                 ifport = interface->ifport;
376                 while(ifport)
377                 {
378                         if (ifport->portnum == portnum)
379                                 break;
380                         ifport = ifport->next;
381                 }
382                 if (ifport)
383                         break;
384                 interface = interface->next;
385         }
386         /* not found, we return -1 */
387         if (!ifport)
388         {
389                 response->am[0].u.x.block = -1;
390                 response->am[0].u.x.error = 1;
391                 SPRINT(response->am[0].u.x.message, "Port %d does not exist.", portnum);
392                 goto out;
393         }
394
395         /* no interface */
396         if (!ifport->mISDNport)
397         {
398                 /* not loaded anyway */
399                 if (block >= 2)
400                 {
401                         response->am[0].u.x.block = 2;
402                         goto out;
403                 }
404
405                 /* try loading interface */
406                 ifport->block = block;
407                 load_port(ifport);
408
409                 /* port cannot load */
410                 if (ifport->block >= 2)
411                 {
412                         response->am[0].u.x.block = 2;
413                         response->am[0].u.x.error = 1;
414                         SPRINT(response->am[0].u.x.message, "Port %d will not load.", portnum);
415                         goto out;
416                 }
417
418                 /* port loaded */
419                 response->am[0].u.x.block = ifport->block;
420                 goto out;
421         }
422
423         /* if we shall unload interface */
424         if (block >= 2)
425         {
426                 mISDNport_close(ifport->mISDNport);
427                 ifport->mISDNport = 0;
428                 ifport->block = 2;
429                 goto out;
430         }
431         
432         /* port new blocking state */
433         ifport->block = response->am[0].u.x.block = block;
434
435         out:
436         /* attach to response chain */
437         *responsep = response;
438         responsep = &response->next;
439         return(0);
440 }
441
442
443 /*
444  * do release
445  */
446 int admin_release(struct admin_queue **responsep, char *message)
447 {
448         unsigned long           id;
449         struct admin_queue      *response;      /* response pointer */
450         class EndpointAppPBX    *apppbx;
451
452         /* create state response */
453         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
454         if (!response)
455                 return(-1);
456         memuse++;
457         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
458         response->num = 1;
459         /* message */
460         response->am[0].message = ADMIN_RESPONSE_CMD_RELEASE;
461
462         id = atoi(message);
463         apppbx = apppbx_first;
464         while(apppbx)
465         {
466                 if (apppbx->ea_endpoint->ep_serial == id)
467                         break;
468                 apppbx = apppbx->next;
469         }
470         if (!apppbx)
471         {
472                 response->am[0].u.x.error = -EINVAL;
473                 SPRINT(response->am[0].u.x.message, "Given endpoint %d doesn't exist.", id);
474                 goto out;
475         }
476
477         apppbx->e_callback = 0;
478         apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
479
480         out:
481         /* attach to response chain */
482         *responsep = response;
483         responsep = &response->next;
484         return(0);
485 }
486
487
488 /*
489  * do call
490  */
491 int admin_call(struct admin_list *admin, struct admin_message *msg)
492 {
493         class Endpoint          *epoint;
494         class EndpointAppPBX    *apppbx;
495
496         if (!(epoint = new Endpoint(0,0)))
497                 return(-1);
498
499         if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint)))
500         {
501                 PERROR("no memory for application\n");
502                 exit(-1);
503         }
504         apppbx->e_adminid = admin->sockserial;
505         admin->epointid = epoint->ep_serial;
506         SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype));
507         if (msg->u.call.present)
508                 apppbx->e_callerinfo.present = INFO_PRESENT_ALLOWED;
509         else
510                 apppbx->e_callerinfo.present = INFO_PRESENT_RESTRICTED;
511         apppbx->e_callerinfo.screen = INFO_SCREEN_NETWORK;
512
513 //printf("hh=%d\n", apppbx->e_capainfo.hlc);
514
515         apppbx->e_capainfo.bearer_capa = msg->u.call.bc_capa;
516         apppbx->e_capainfo.bearer_mode = msg->u.call.bc_mode;
517         apppbx->e_capainfo.bearer_info1 = msg->u.call.bc_info1;
518         apppbx->e_capainfo.hlc = msg->u.call.hlc;
519         apppbx->e_capainfo.exthlc = msg->u.call.exthlc;
520         SCPY(apppbx->e_dialinginfo.id, msg->u.call.dialing);
521         SCPY(apppbx->e_dialinginfo.interfaces, msg->u.call.interface);
522         apppbx->e_dialinginfo.sending_complete = 1;
523
524         apppbx->new_state(PORT_STATE_OUT_SETUP);
525         apppbx->out_setup();
526         return(0);
527 }
528
529
530 /*
531  * this function is called for response whenever a call state changes.
532  */
533 void admin_call_response(int adminid, int message, char *connected, int cause, int location, int notify)
534 {
535         struct admin_list       *admin;
536         struct admin_queue      *response, **responsep; /* response pointer */
537
538         /* searching for admin id
539          * maybe there is no admin instance, because the calling port was not
540          * initiated by admin_call */
541         admin = admin_list;
542         while(admin)
543         {
544                 if (adminid == admin->sockserial)
545                         break;
546                 admin = admin->next;
547         }
548         if (!admin)
549                 return;
550
551         /* seek to end of response list */
552         response = admin->response;
553         responsep = &admin->response;
554         while(response)
555         {
556                 responsep = &response->next;
557                 response = response->next;
558         }
559
560         /* create state response */
561         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
562         if (!response)
563                 return;
564         memuse++;
565         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
566         response->num = 1;
567         /* message */
568         response->am[0].message = message;
569 //      printf("MESSAGE: %d\n", message);
570
571         SCPY(response->am[0].u.call.callerid, connected);
572         response->am[0].u.call.cause = cause;
573         response->am[0].u.call.location = location;
574         response->am[0].u.call.notify = notify;
575
576         /* attach to response chain */
577         *responsep = response;
578         responsep = &response->next;
579 }
580
581
582 /*
583  * do state debugging
584  */
585 int admin_state(struct admin_queue **responsep)
586 {
587
588         class Port              *port;
589         class EndpointAppPBX    *apppbx;
590         class Call              *call;
591         class Pdss1             *pdss1;
592         struct interface        *interface;
593         struct interface_port   *ifport;
594         struct mISDNport        *mISDNport;
595         int                     i;
596         int                     num;
597         int                     anybusy;
598         struct admin_queue      *response;
599
600         /* create state response */
601         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
602         if (!response)
603                 return(-1);
604         memuse++;
605         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
606         response->num = 1;
607         /* message */
608         response->am[0].message = ADMIN_RESPONSE_STATE;
609         /* version */
610         SCPY(response->am[0].u.s.version_string, VERSION_STRING);
611         /* time */
612         memcpy(&response->am[0].u.s.tm, now_tm, sizeof(struct tm));
613         /* log file */
614         SCPY(response->am[0].u.s.logfile, options.log);
615         /* interface count */
616         i = 0;
617         interface = interface_first;
618         while(interface)
619         {
620                 ifport = interface->ifport;
621                 while(ifport)
622                 {
623                         i++;
624                         ifport = ifport->next;
625                 }
626                 interface = interface->next;
627         }
628         response->am[0].u.s.interfaces = i;
629         /* call count */
630         call = call_first;
631         i = 0;
632         while(call)
633         {
634                 i++;
635                 call = call->next;
636         }
637         response->am[0].u.s.calls = i;
638         /* apppbx count */
639         apppbx = apppbx_first;
640         i = 0;
641         while(apppbx)
642         {
643                 i++;
644                 apppbx = apppbx->next;
645         }
646         response->am[0].u.s.epoints = i;
647         /* port count */
648         i = 0;
649         port = port_first;
650         while(port)
651         {
652                 i++;
653                 port = port->next;
654         }
655         response->am[0].u.s.ports = i;
656         /* attach to response chain */
657         *responsep = response;
658         responsep = &response->next;
659
660         /* create response for all interfaces */
661         num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.calls)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports);
662         if (num == 0)
663                 return(0);
664         response = (struct admin_queue *)malloc(sizeof(admin_queue)+(num*sizeof(admin_message)));
665         if (!response)
666                 return(-1);
667         memuse++;
668         memset(response, 0, sizeof(admin_queue)+(num*sizeof(admin_message)));
669         response->num = num;
670         *responsep = response;
671         responsep = &response->next;
672         interface = interface_first;
673         num = 0;
674         while(interface)
675         {
676                 ifport = interface->ifport;
677                 while(ifport)
678                 {
679                         /* message */
680                         response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
681                         /* interface */
682                         SCPY(response->am[num].u.i.interface_name, interface->name);
683                         /* portnum */
684                         response->am[num].u.i.portnum = ifport->portnum;
685                         /* iftype */
686                         response->am[num].u.i.extension = interface->extension;
687                         /* block */
688                         response->am[num].u.i.block = ifport->block;
689                         if (ifport->mISDNport)
690                         {
691                                 mISDNport = ifport->mISDNport;
692
693                                 /* ptp */
694                                 response->am[num].u.i.ptp = mISDNport->ptp;
695                                 /* ntmode */
696                                 response->am[num].u.i.ntmode = mISDNport->ntmode;
697                                 /* pri */
698                                 response->am[num].u.i.pri = mISDNport->pri;
699                                 /* use */
700                                 response->am[num].u.i.use = mISDNport->use;
701                                 /* l1link */
702                                 response->am[num].u.i.l1link = mISDNport->l1link;
703                                 /* l2link */
704                                 response->am[num].u.i.l2link = mISDNport->l2link;
705                                 /* channels */
706                                 response->am[num].u.i.channels = mISDNport->b_num;
707                                 /* channel info */
708                                 i = 0;
709                                 anybusy = 0;
710                                 while(i < mISDNport->b_num)
711                                 {
712                                         response->am[num].u.i.busy[i] = mISDNport->b_state[i];
713                                         if (mISDNport->b_port[i])
714                                                 response->am[num].u.i.port[i] = mISDNport->b_port[i]->p_serial;
715                                         i++;
716                                 }
717                         }
718                         num++;
719
720                         ifport = ifport->next;
721                 }
722                 interface = interface->next;
723         }
724
725         /* create response for all calls */
726         call = call_first;
727         while(call)
728         {
729                 /* message */
730                 response->am[num].message = ADMIN_RESPONSE_S_CALL;
731                 /* serial */
732                 response->am[num].u.c.serial = call->c_serial;
733                 /* partyline */
734                 if (call->c_type == CALL_TYPE_PBX)
735                         response->am[num].u.c.partyline = ((class CallPBX *)call)->c_partyline;
736                 /* */
737                 call = call->next;
738                 num++;
739         }
740
741         /* create response for all endpoint */
742         apppbx = apppbx_first;
743         while(apppbx)
744         {
745                 /* message */
746                 response->am[num].message = ADMIN_RESPONSE_S_EPOINT;
747                 /* serial */
748                 response->am[num].u.e.serial = apppbx->ea_endpoint->ep_serial;
749                 /* call */
750                 response->am[num].u.e.call = apppbx->ea_endpoint->ep_call_id;
751                 /* rx notification */
752                 response->am[num].u.e.rx_state = apppbx->e_rx_state;
753                 /* tx notification */
754                 response->am[num].u.e.tx_state = apppbx->e_tx_state;
755                 /* state */
756                 switch(apppbx->e_state)
757                 {
758                         case EPOINT_STATE_IN_SETUP:
759                         response->am[num].u.e.state = ADMIN_STATE_IN_SETUP;
760                         break;
761                         case EPOINT_STATE_OUT_SETUP:
762                         response->am[num].u.e.state = ADMIN_STATE_OUT_SETUP;
763                         break;
764                         case EPOINT_STATE_IN_OVERLAP:
765                         response->am[num].u.e.state = ADMIN_STATE_IN_OVERLAP;
766                         break;
767                         case EPOINT_STATE_OUT_OVERLAP:
768                         response->am[num].u.e.state = ADMIN_STATE_OUT_OVERLAP;
769                         break;
770                         case EPOINT_STATE_IN_PROCEEDING:
771                         response->am[num].u.e.state = ADMIN_STATE_IN_PROCEEDING;
772                         break;
773                         case EPOINT_STATE_OUT_PROCEEDING:
774                         response->am[num].u.e.state = ADMIN_STATE_OUT_PROCEEDING;
775                         break;
776                         case EPOINT_STATE_IN_ALERTING:
777                         response->am[num].u.e.state = ADMIN_STATE_IN_ALERTING;
778                         break;
779                         case EPOINT_STATE_OUT_ALERTING:
780                         response->am[num].u.e.state = ADMIN_STATE_OUT_ALERTING;
781                         break;
782                         case EPOINT_STATE_CONNECT:
783                         response->am[num].u.e.state = ADMIN_STATE_CONNECT;
784                         break;
785                         case EPOINT_STATE_IN_DISCONNECT:
786                         response->am[num].u.e.state = ADMIN_STATE_IN_DISCONNECT;
787                         break;
788                         case EPOINT_STATE_OUT_DISCONNECT:
789                         response->am[num].u.e.state = ADMIN_STATE_OUT_DISCONNECT;
790                         break;
791                         default:
792                         response->am[num].u.e.state = ADMIN_STATE_IDLE;
793                 }
794                 /* terminal */
795                 SCPY(response->am[num].u.e.terminal, apppbx->e_ext.number);
796                 /* callerid */
797                 SCPY(response->am[num].u.e.callerid, apppbx->e_callerinfo.id);
798                 /* dialing */
799                 SCPY(response->am[num].u.e.dialing, apppbx->e_dialinginfo.id);
800                 /* action string */
801                 if (apppbx->e_action)
802                         SCPY(response->am[num].u.e.action, action_defs[apppbx->e_action->index].name);
803 //              if (apppbx->e_action)
804 //              printf("action=%s\n",action_defs[apppbx->e_action->index].name);
805                 /* park */
806                 response->am[num].u.e.park = apppbx->ea_endpoint->ep_park;
807                 if (apppbx->ea_endpoint->ep_park && apppbx->ea_endpoint->ep_park_len && apppbx->ea_endpoint->ep_park_len<=(int)sizeof(response->am[num].u.e.park_callid))
808                         memcpy(response->am[num].u.e.park_callid, apppbx->ea_endpoint->ep_park_callid, apppbx->ea_endpoint->ep_park_len);
809                 response->am[num].u.e.park_len = apppbx->ea_endpoint->ep_park_len;
810                 /* crypt */
811                 if (apppbx->e_crypt == CRYPT_ON)
812                         response->am[num].u.e.crypt = 1;
813                 /* */
814                 apppbx = apppbx->next;
815                 num++;
816         }
817
818         /* create response for all ports */
819         port = port_first;
820         while(port)
821         {
822                 /* message */
823                 response->am[num].message = ADMIN_RESPONSE_S_PORT;
824                 /* serial */
825                 response->am[num].u.p.serial = port->p_serial;
826                 /* name */
827                 SCPY(response->am[num].u.p.name, port->p_name);
828                 /* epoint */
829                 response->am[num].u.p.epoint = ACTIVE_EPOINT(port->p_epointlist);
830                 /* state */
831                 switch(port->p_state)
832                 {
833                         case PORT_STATE_IN_SETUP:
834                         response->am[num].u.p.state = ADMIN_STATE_IN_SETUP;
835                         break;
836                         case PORT_STATE_OUT_SETUP:
837                         response->am[num].u.p.state = ADMIN_STATE_OUT_SETUP;
838                         break;
839                         case PORT_STATE_IN_OVERLAP:
840                         response->am[num].u.p.state = ADMIN_STATE_IN_OVERLAP;
841                         break;
842                         case PORT_STATE_OUT_OVERLAP:
843                         response->am[num].u.p.state = ADMIN_STATE_OUT_OVERLAP;
844                         break;
845                         case PORT_STATE_IN_PROCEEDING:
846                         response->am[num].u.p.state = ADMIN_STATE_IN_PROCEEDING;
847                         break;
848                         case PORT_STATE_OUT_PROCEEDING:
849                         response->am[num].u.p.state = ADMIN_STATE_OUT_PROCEEDING;
850                         break;
851                         case PORT_STATE_IN_ALERTING:
852                         response->am[num].u.p.state = ADMIN_STATE_IN_ALERTING;
853                         break;
854                         case PORT_STATE_OUT_ALERTING:
855                         response->am[num].u.p.state = ADMIN_STATE_OUT_ALERTING;
856                         break;
857                         case PORT_STATE_CONNECT:
858                         response->am[num].u.p.state = ADMIN_STATE_CONNECT;
859                         break;
860                         case PORT_STATE_IN_DISCONNECT:
861                         response->am[num].u.p.state = ADMIN_STATE_IN_DISCONNECT;
862                         break;
863                         case PORT_STATE_OUT_DISCONNECT:
864                         response->am[num].u.p.state = ADMIN_STATE_OUT_DISCONNECT;
865                         break;
866                         default:
867                         response->am[num].u.p.state = ADMIN_STATE_IDLE;
868                 }
869                 /* isdn */
870                 if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1)
871                 {
872                         response->am[num].u.p.isdn = 1;
873                         pdss1 = (class Pdss1 *)port;
874                         response->am[num].u.p.isdn_chan = pdss1->p_m_b_channel;
875                         response->am[num].u.p.isdn_hold = pdss1->p_m_hold;
876                         response->am[num].u.p.isdn_ces = pdss1->p_m_d_ces;
877                 }
878                 /* */
879                 port = port->next;
880                 num++;
881         }
882         return(0);
883 }
884
885 int sockserial = 1; // must start with 1, because 0 is used if no serial is set
886 /*
887  * handle admin socket (non blocking)
888  */
889 int admin_handle(void)
890 {
891         struct admin_list       *admin, **adminp;
892         void                    *temp;
893         struct admin_message    msg;
894         int                     len;
895         int                     new_sock;
896         socklen_t               sock_len = sizeof(sock_address);
897         unsigned long           on = 1;
898         int                     work = 0; /* if work was done */
899         struct Endpoint         *epoint;
900
901         if (sock < 0)
902                 return(0);
903
904         /* check for new incomming connections */
905         if ((new_sock = accept(sock, (struct sockaddr *)&sock_address, &sock_len)) >= 0)
906         {
907                 work = 1;
908                 /* insert new socket */
909                 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
910                 if (admin)
911                 {
912                         if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0)
913                         {
914 //#warning
915 //      PERROR("DEBUG incomming socket %d, serial=%d\n", new_sock, sockserial);
916                                 memuse++;
917                                 fhuse++;
918                                 memset(admin, 0, sizeof(struct admin_list));
919                                 admin->sockserial = sockserial++;
920                                 admin->next = admin_list;
921                                 admin_list = admin;
922                                 admin->sock = new_sock;
923                         } else {
924                                 close(new_sock);
925                                 free(admin);
926                         }
927                 } else
928                         close(new_sock);
929         } else
930         {
931                 if (errno != EWOULDBLOCK)
932                 {
933                         PERROR("Failed to accept connection from socket \"%s\". (errno=%d) Closing socket.\n", sock_address.sun_path, errno);
934                         admin_cleanup();
935                         return(1);
936                 }
937         }
938
939         /* loop all current socket connections */
940         admin = admin_list;
941         adminp = &admin_list;
942         while(admin)
943         {
944                 /* read command */
945                 len = read(admin->sock, &msg, sizeof(msg));
946                 if (len < 0)
947                 {
948                         if (errno != EWOULDBLOCK)
949                         {
950                                 work = 1;
951                                 brokenpipe:
952                                 printf("Broken pipe on socket %d. (errno=%d).\n", admin->sock, errno);
953                                 PDEBUG(DEBUG_LOG, "Broken pipe on socket %d. (errno=%d).\n", admin->sock, errno);
954                                 *adminp = admin->next;
955                                 free_connection(admin);
956                                 admin = *adminp;
957                                 continue;
958                         }
959                         goto send_data;
960                 }
961                 work = 1;
962 //#warning
963 //PERROR("DEBUG socket %d got data. serial=%d\n", admin->sock, admin->sockserial);
964                 if (len == 0)
965                 {
966                         end:
967
968                         /*release endpoint if exists */
969                         if (admin->epointid)
970                         {
971                                 epoint = find_epoint_id(admin->epointid);
972                                 if (epoint)
973                                 {
974                                         ((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)->
975                                                 release(RELEASE_ALL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0, 0);
976                                 }
977                         }
978
979 //#warning
980 //PERROR("DEBUG socket %d closed by remote.\n", admin->sock);
981                         *adminp = admin->next;
982                         free_connection(admin);
983                         admin = *adminp;
984 //PERROR("DEBUG (admin_list=%x)\n", admin_list);
985                         continue;
986                 }
987                 if (len != sizeof(msg))
988                 {
989                         PERROR("Short/long read on socket %d. (len=%d != size=%d).\n", admin->sock, len, sizeof(msg));
990                         *adminp = admin->next;
991                         free_connection(admin);
992                         admin = *adminp;
993                         continue;
994                 }
995                 /* process socket command */
996                 if (admin->response)
997                 {
998                         PERROR("Data from socket %d while sending response.\n", admin->sock);
999                         *adminp = admin->next;
1000                         free_connection(admin);
1001                         admin = *adminp;
1002                         continue;
1003                 }
1004                 switch (msg.message)
1005                 {
1006                         case ADMIN_REQUEST_CMD_INTERFACE:
1007                         if (admin_interface(&admin->response) < 0)
1008                         {
1009                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1010                                 goto response_error;
1011                         }
1012                         break;
1013
1014                         case ADMIN_REQUEST_CMD_ROUTE:
1015                         if (admin_route(&admin->response) < 0)
1016                         {
1017                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1018                                 goto response_error;
1019                         }
1020                         break;
1021
1022                         case ADMIN_REQUEST_CMD_DIAL:
1023                         if (admin_dial(&admin->response, msg.u.x.message) < 0)
1024                         {
1025                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1026                                 goto response_error;
1027                         }
1028                         break;
1029
1030                         case ADMIN_REQUEST_CMD_RELEASE:
1031                         if (admin_release(&admin->response, msg.u.x.message) < 0)
1032                         {
1033                                 PERROR("Failed to create release response for socket %d.\n", admin->sock);
1034                                 goto response_error;
1035                         }
1036                         break;
1037
1038                         case ADMIN_REQUEST_STATE:
1039                         if (admin_state(&admin->response) < 0)
1040                         {
1041                                 PERROR("Failed to create state response for socket %d.\n", admin->sock);
1042                                 goto response_error;
1043                         }
1044                         break;
1045
1046                         case ADMIN_REQUEST_CMD_BLOCK:
1047                         if (admin_block(&admin->response, msg.u.x.portnum, msg.u.x.block) < 0)
1048                         {
1049                                 PERROR("Failed to create block response for socket %d.\n", admin->sock);
1050                                 goto response_error;
1051                         }
1052                         break;
1053
1054 #warning interface tbd
1055 #if 0
1056                         case ADMIN_MESSAGE:
1057                         if (admin_message(&admin->response) < 0)
1058                         {
1059                                 PERROR("Failed to create message response for socket %d.\n", admin->sock);
1060                                 goto response_error;
1061                         }
1062 #endif
1063 #if 0
1064 #warning DEBUGGING
1065 {
1066         struct admin_queue      *response;
1067         printf("Chain: ");
1068         response = admin->response;
1069         while(response)
1070         {
1071                 printf("%c", '0'+response->am[0].message);
1072                 response=response->next;
1073         }
1074         printf("\n");
1075 }
1076 #endif
1077                         break;
1078
1079                         case ADMIN_CALL_SETUP:
1080                         if (admin_call(admin, &msg))
1081                         {
1082                                 PERROR("Failed to create call for socket %d.\n", admin->sock);
1083                                 response_error:
1084                                 *adminp = admin->next;
1085                                 free_connection(admin);
1086                                 admin = *adminp;
1087                                 continue;
1088                         }
1089                         break;
1090
1091                         default:
1092                         PERROR("Invalid message %d from socket %d.\n", msg.message, admin->sock);
1093                         *adminp = admin->next;
1094                         free_connection(admin);
1095                         admin = *adminp;
1096                         continue;
1097                 }
1098                 /* write queue */
1099                 send_data:
1100                 if (admin->response)
1101                 {
1102 //#warning
1103 //PERROR("DEBUG socket %d sending data.\n", admin->sock);
1104                         len = write(admin->sock, ((unsigned char *)(admin->response->am))+admin->response->offset, sizeof(struct admin_message)*(admin->response->num)-admin->response->offset);
1105                         if (len < 0)
1106                         {
1107                                 if (errno != EWOULDBLOCK)
1108                                 {
1109                                         work = 1;
1110                                         goto brokenpipe;
1111                                 }
1112                                 goto next;
1113                         }
1114                         work = 1;
1115                         if (len == 0)
1116                                 goto end;
1117                         if (len < (int)(sizeof(struct admin_message)*(admin->response->num)-admin->response->offset))
1118                         {
1119                                 admin->response->offset+=len;
1120                                 goto next;
1121                         } else
1122                         {
1123                                 temp = admin->response;
1124                                 admin->response = admin->response->next;
1125                                 free(temp);
1126                                 memuse--;
1127                         }
1128                 }
1129                 /* done with socket instance */
1130                 next:
1131                 adminp = &admin->next;
1132                 admin = admin->next;
1133         }
1134
1135         return(work);
1136 }
1137