1bb07af19a060572e264f1e74c3cdd7953a7e1be
[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                         end_trace();
266                 }
267
268                 apppbx->e_action_timeout = NULL;
269                 apppbx->e_rule = NULL;
270                 apppbx->e_ruleset = NULL;
271
272                 apppbx = apppbx->next;
273         }
274
275         response:
276         /* create state response */
277         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
278         if (!response)
279                 return(-1);
280         memuse++;
281         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
282         response->num = 1;
283         /* message */
284         response->am[0].message = ADMIN_RESPONSE_CMD_ROUTE;
285         /* error */
286         response->am[0].u.x.error = err;
287         /* message */
288         SCPY(response->am[0].u.x.message, err_txt);
289         /* attach to response chain */
290         *responsep = response;
291         responsep = &response->next;
292
293         return(0);
294 }
295
296
297 /*
298  * do dialing
299  */
300 int admin_dial(struct admin_queue **responsep, char *message)
301 {
302         struct extension        ext;            /* temporary extension's settings */
303         struct admin_queue      *response;      /* response pointer */
304         char                    *p;             /* pointer to dialing digits */
305
306         /* create state response */
307         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
308         if (!response)
309                 return(-1);
310         memuse++;
311         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
312         response->num = 1;
313         /* message */
314         response->am[0].message = ADMIN_RESPONSE_CMD_DIAL;
315
316         /* process request */
317         if (!(p = strchr(message,':')))
318         {
319                 response->am[0].u.x.error = -EINVAL;
320                 SPRINT(response->am[0].u.x.message, "no seperator ':' in message to seperate number from extension");
321                 goto out;
322         }
323         *p++ = 0;
324
325         /* modify extension */
326         if (!read_extension(&ext, message))
327         {
328                 response->am[0].u.x.error = -EINVAL;
329                 SPRINT(response->am[0].u.x.message, "extension doesn't exist");
330                 goto out;
331         }
332         SCPY(ext.next, p);
333         write_extension(&ext, message);
334
335         out:
336         /* attach to response chain */
337         *responsep = response;
338         responsep = &response->next;
339         return(0);
340 }
341
342
343 /*
344  * do tracing
345  */
346 int admin_trace(struct admin_list *admin, struct admin_trace_req *trace)
347 {
348         memcpy(&admin->trace, trace, sizeof(struct admin_trace_req));
349         return(0);
350 }
351
352
353 /*
354  * do blocking
355  * 
356  * 0 = make port available
357  * 1 = make port administratively blocked
358  * 2 = unload port
359  * the result is returned:
360  * 0 = port is now available
361  * 1 = port is now blocked
362  * 2 = port cannot be loaded or has been unloaded
363  * -1 = port doesn't exist
364  */
365 int admin_block(struct admin_queue **responsep, int portnum, int block)
366 {
367         struct admin_queue      *response;      /* response pointer */
368         struct interface        *interface;
369         struct interface_port   *ifport;
370
371         /* create block response */
372         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
373         if (!response)
374                 return(-1);
375         memuse++;
376         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
377         response->num = 1;
378         /* message */
379         response->am[0].message = ADMIN_RESPONSE_CMD_BLOCK;
380         response->am[0].u.x.portnum = portnum;
381
382         /* search for port */
383         interface = interface_first;
384         while(interface)
385         {
386                 ifport = interface->ifport;
387                 while(ifport)
388                 {
389                         if (ifport->portnum == portnum)
390                                 break;
391                         ifport = ifport->next;
392                 }
393                 if (ifport)
394                         break;
395                 interface = interface->next;
396         }
397         /* not found, we return -1 */
398         if (!ifport)
399         {
400                 response->am[0].u.x.block = -1;
401                 response->am[0].u.x.error = 1;
402                 SPRINT(response->am[0].u.x.message, "Port %d does not exist.", portnum);
403                 goto out;
404         }
405
406         /* no interface */
407         if (!ifport->mISDNport)
408         {
409                 /* not loaded anyway */
410                 if (block >= 2)
411                 {
412                         response->am[0].u.x.block = 2;
413                         goto out;
414                 }
415
416                 /* try loading interface */
417                 ifport->block = block;
418                 load_port(ifport);
419
420                 /* port cannot load */
421                 if (ifport->block >= 2)
422                 {
423                         response->am[0].u.x.block = 2;
424                         response->am[0].u.x.error = 1;
425                         SPRINT(response->am[0].u.x.message, "Port %d will not load.", portnum);
426                         goto out;
427                 }
428
429                 /* port loaded */
430                 response->am[0].u.x.block = ifport->block;
431                 goto out;
432         }
433
434         /* if we shall unload interface */
435         if (block >= 2)
436         {
437                 mISDNport_close(ifport->mISDNport);
438                 ifport->mISDNport = 0;
439                 ifport->block = 2;
440                 goto out;
441         }
442         
443         /* port new blocking state */
444         ifport->block = response->am[0].u.x.block = block;
445
446         out:
447         /* attach to response chain */
448         *responsep = response;
449         responsep = &response->next;
450         return(0);
451 }
452
453
454 /*
455  * do release
456  */
457 int admin_release(struct admin_queue **responsep, char *message)
458 {
459         unsigned long           id;
460         struct admin_queue      *response;      /* response pointer */
461         class EndpointAppPBX    *apppbx;
462
463         /* create state response */
464         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
465         if (!response)
466                 return(-1);
467         memuse++;
468         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
469         response->num = 1;
470         /* message */
471         response->am[0].message = ADMIN_RESPONSE_CMD_RELEASE;
472
473         id = atoi(message);
474         apppbx = apppbx_first;
475         while(apppbx)
476         {
477                 if (apppbx->ea_endpoint->ep_serial == id)
478                         break;
479                 apppbx = apppbx->next;
480         }
481         if (!apppbx)
482         {
483                 response->am[0].u.x.error = -EINVAL;
484                 SPRINT(response->am[0].u.x.message, "Given endpoint %d doesn't exist.", id);
485                 goto out;
486         }
487
488         apppbx->e_callback = 0;
489         apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
490
491         out:
492         /* attach to response chain */
493         *responsep = response;
494         responsep = &response->next;
495         return(0);
496 }
497
498
499 /*
500  * do call
501  */
502 int admin_call(struct admin_list *admin, struct admin_message *msg)
503 {
504         class Endpoint          *epoint;
505         class EndpointAppPBX    *apppbx;
506
507         if (!(epoint = new Endpoint(0,0)))
508                 return(-1);
509
510         if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint)))
511         {
512                 PERROR("no memory for application\n");
513                 exit(-1);
514         }
515         apppbx->e_adminid = admin->sockserial;
516         admin->epointid = epoint->ep_serial;
517         SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype));
518         if (msg->u.call.present)
519                 apppbx->e_callerinfo.present = INFO_PRESENT_ALLOWED;
520         else
521                 apppbx->e_callerinfo.present = INFO_PRESENT_RESTRICTED;
522         apppbx->e_callerinfo.screen = INFO_SCREEN_NETWORK;
523
524 //printf("hh=%d\n", apppbx->e_capainfo.hlc);
525
526         apppbx->e_capainfo.bearer_capa = msg->u.call.bc_capa;
527         apppbx->e_capainfo.bearer_mode = msg->u.call.bc_mode;
528         apppbx->e_capainfo.bearer_info1 = msg->u.call.bc_info1;
529         apppbx->e_capainfo.hlc = msg->u.call.hlc;
530         apppbx->e_capainfo.exthlc = msg->u.call.exthlc;
531         SCPY(apppbx->e_dialinginfo.id, msg->u.call.dialing);
532         SCPY(apppbx->e_dialinginfo.interfaces, msg->u.call.interface);
533         apppbx->e_dialinginfo.sending_complete = 1;
534
535         apppbx->new_state(PORT_STATE_OUT_SETUP);
536         apppbx->out_setup();
537         return(0);
538 }
539
540
541 /*
542  * this function is called for response whenever a call state changes.
543  */
544 void admin_call_response(int adminid, int message, char *connected, int cause, int location, int notify)
545 {
546         struct admin_list       *admin;
547         struct admin_queue      *response, **responsep; /* response pointer */
548
549         /* searching for admin id
550          * maybe there is no admin instance, because the calling port was not
551          * initiated by admin_call */
552         admin = admin_list;
553         while(admin)
554         {
555                 if (adminid == admin->sockserial)
556                         break;
557                 admin = admin->next;
558         }
559         if (!admin)
560                 return;
561
562         /* seek to end of response list */
563         response = admin->response;
564         responsep = &admin->response;
565         while(response)
566         {
567                 responsep = &response->next;
568                 response = response->next;
569         }
570
571         /* create state response */
572         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
573         if (!response)
574                 return;
575         memuse++;
576         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
577         response->num = 1;
578         /* message */
579         response->am[0].message = message;
580 //      printf("MESSAGE: %d\n", message);
581
582         SCPY(response->am[0].u.call.callerid, connected);
583         response->am[0].u.call.cause = cause;
584         response->am[0].u.call.location = location;
585         response->am[0].u.call.notify = notify;
586
587         /* attach to response chain */
588         *responsep = response;
589         responsep = &response->next;
590 }
591
592
593 /*
594  * do state debugging
595  */
596 int admin_state(struct admin_queue **responsep)
597 {
598
599         class Port              *port;
600         class EndpointAppPBX    *apppbx;
601         class Call              *call;
602         class Pdss1             *pdss1;
603         struct interface        *interface;
604         struct interface_port   *ifport;
605         struct mISDNport        *mISDNport;
606         int                     i;
607         int                     num;
608         int                     anybusy;
609         struct admin_queue      *response;
610
611         /* create state response */
612         response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message));
613         if (!response)
614                 return(-1);
615         memuse++;
616         memset(response, 0, sizeof(admin_queue)+sizeof(admin_message));
617         response->num = 1;
618         /* message */
619         response->am[0].message = ADMIN_RESPONSE_STATE;
620         /* version */
621         SCPY(response->am[0].u.s.version_string, VERSION_STRING);
622         /* time */
623         memcpy(&response->am[0].u.s.tm, now_tm, sizeof(struct tm));
624         /* log file */
625         SCPY(response->am[0].u.s.logfile, options.log);
626         /* interface count */
627         i = 0;
628         interface = interface_first;
629         while(interface)
630         {
631                 ifport = interface->ifport;
632                 while(ifport)
633                 {
634                         i++;
635                         ifport = ifport->next;
636                 }
637                 interface = interface->next;
638         }
639         response->am[0].u.s.interfaces = i;
640         /* call count */
641         call = call_first;
642         i = 0;
643         while(call)
644         {
645                 i++;
646                 call = call->next;
647         }
648         response->am[0].u.s.calls = i;
649         /* apppbx count */
650         apppbx = apppbx_first;
651         i = 0;
652         while(apppbx)
653         {
654                 i++;
655                 apppbx = apppbx->next;
656         }
657         response->am[0].u.s.epoints = i;
658         /* port count */
659         i = 0;
660         port = port_first;
661         while(port)
662         {
663                 i++;
664                 port = port->next;
665         }
666         response->am[0].u.s.ports = i;
667         /* attach to response chain */
668         *responsep = response;
669         responsep = &response->next;
670
671         /* create response for all interfaces */
672         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);
673         if (num == 0)
674                 return(0);
675         response = (struct admin_queue *)malloc(sizeof(admin_queue)+(num*sizeof(admin_message)));
676         if (!response)
677                 return(-1);
678         memuse++;
679         memset(response, 0, sizeof(admin_queue)+(num*sizeof(admin_message)));
680         response->num = num;
681         *responsep = response;
682         responsep = &response->next;
683         interface = interface_first;
684         num = 0;
685         while(interface)
686         {
687                 ifport = interface->ifport;
688                 while(ifport)
689                 {
690                         /* message */
691                         response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
692                         /* interface */
693                         SCPY(response->am[num].u.i.interface_name, interface->name);
694                         /* portnum */
695                         response->am[num].u.i.portnum = ifport->portnum;
696                         /* iftype */
697                         response->am[num].u.i.extension = interface->extension;
698                         /* block */
699                         response->am[num].u.i.block = ifport->block;
700                         if (ifport->mISDNport)
701                         {
702                                 mISDNport = ifport->mISDNport;
703
704                                 /* ptp */
705                                 response->am[num].u.i.ptp = mISDNport->ptp;
706                                 /* ntmode */
707                                 response->am[num].u.i.ntmode = mISDNport->ntmode;
708                                 /* pri */
709                                 response->am[num].u.i.pri = mISDNport->pri;
710                                 /* use */
711                                 response->am[num].u.i.use = mISDNport->use;
712                                 /* l1link */
713                                 response->am[num].u.i.l1link = mISDNport->l1link;
714                                 /* l2link */
715                                 response->am[num].u.i.l2link = mISDNport->l2link;
716                                 /* channels */
717                                 response->am[num].u.i.channels = mISDNport->b_num;
718                                 /* channel info */
719                                 i = 0;
720                                 anybusy = 0;
721                                 while(i < mISDNport->b_num)
722                                 {
723                                         response->am[num].u.i.busy[i] = mISDNport->b_state[i];
724                                         if (mISDNport->b_port[i])
725                                                 response->am[num].u.i.port[i] = mISDNport->b_port[i]->p_serial;
726                                         i++;
727                                 }
728                         }
729                         num++;
730
731                         ifport = ifport->next;
732                 }
733                 interface = interface->next;
734         }
735
736         /* create response for all calls */
737         call = call_first;
738         while(call)
739         {
740                 /* message */
741                 response->am[num].message = ADMIN_RESPONSE_S_CALL;
742                 /* serial */
743                 response->am[num].u.c.serial = call->c_serial;
744                 /* partyline */
745                 if (call->c_type == CALL_TYPE_PBX)
746                         response->am[num].u.c.partyline = ((class CallPBX *)call)->c_partyline;
747                 /* */
748                 call = call->next;
749                 num++;
750         }
751
752         /* create response for all endpoint */
753         apppbx = apppbx_first;
754         while(apppbx)
755         {
756                 /* message */
757                 response->am[num].message = ADMIN_RESPONSE_S_EPOINT;
758                 /* serial */
759                 response->am[num].u.e.serial = apppbx->ea_endpoint->ep_serial;
760                 /* call */
761                 response->am[num].u.e.call = apppbx->ea_endpoint->ep_call_id;
762                 /* rx notification */
763                 response->am[num].u.e.rx_state = apppbx->e_rx_state;
764                 /* tx notification */
765                 response->am[num].u.e.tx_state = apppbx->e_tx_state;
766                 /* state */
767                 switch(apppbx->e_state)
768                 {
769                         case EPOINT_STATE_IN_SETUP:
770                         response->am[num].u.e.state = ADMIN_STATE_IN_SETUP;
771                         break;
772                         case EPOINT_STATE_OUT_SETUP:
773                         response->am[num].u.e.state = ADMIN_STATE_OUT_SETUP;
774                         break;
775                         case EPOINT_STATE_IN_OVERLAP:
776                         response->am[num].u.e.state = ADMIN_STATE_IN_OVERLAP;
777                         break;
778                         case EPOINT_STATE_OUT_OVERLAP:
779                         response->am[num].u.e.state = ADMIN_STATE_OUT_OVERLAP;
780                         break;
781                         case EPOINT_STATE_IN_PROCEEDING:
782                         response->am[num].u.e.state = ADMIN_STATE_IN_PROCEEDING;
783                         break;
784                         case EPOINT_STATE_OUT_PROCEEDING:
785                         response->am[num].u.e.state = ADMIN_STATE_OUT_PROCEEDING;
786                         break;
787                         case EPOINT_STATE_IN_ALERTING:
788                         response->am[num].u.e.state = ADMIN_STATE_IN_ALERTING;
789                         break;
790                         case EPOINT_STATE_OUT_ALERTING:
791                         response->am[num].u.e.state = ADMIN_STATE_OUT_ALERTING;
792                         break;
793                         case EPOINT_STATE_CONNECT:
794                         response->am[num].u.e.state = ADMIN_STATE_CONNECT;
795                         break;
796                         case EPOINT_STATE_IN_DISCONNECT:
797                         response->am[num].u.e.state = ADMIN_STATE_IN_DISCONNECT;
798                         break;
799                         case EPOINT_STATE_OUT_DISCONNECT:
800                         response->am[num].u.e.state = ADMIN_STATE_OUT_DISCONNECT;
801                         break;
802                         default:
803                         response->am[num].u.e.state = ADMIN_STATE_IDLE;
804                 }
805                 /* terminal */
806                 SCPY(response->am[num].u.e.terminal, apppbx->e_ext.number);
807                 /* callerid */
808                 SCPY(response->am[num].u.e.callerid, apppbx->e_callerinfo.id);
809                 /* dialing */
810                 SCPY(response->am[num].u.e.dialing, apppbx->e_dialinginfo.id);
811                 /* action string */
812                 if (apppbx->e_action)
813                         SCPY(response->am[num].u.e.action, action_defs[apppbx->e_action->index].name);
814 //              if (apppbx->e_action)
815 //              printf("action=%s\n",action_defs[apppbx->e_action->index].name);
816                 /* park */
817                 response->am[num].u.e.park = apppbx->ea_endpoint->ep_park;
818                 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))
819                         memcpy(response->am[num].u.e.park_callid, apppbx->ea_endpoint->ep_park_callid, apppbx->ea_endpoint->ep_park_len);
820                 response->am[num].u.e.park_len = apppbx->ea_endpoint->ep_park_len;
821                 /* crypt */
822                 if (apppbx->e_crypt == CRYPT_ON)
823                         response->am[num].u.e.crypt = 1;
824                 /* */
825                 apppbx = apppbx->next;
826                 num++;
827         }
828
829         /* create response for all ports */
830         port = port_first;
831         while(port)
832         {
833                 /* message */
834                 response->am[num].message = ADMIN_RESPONSE_S_PORT;
835                 /* serial */
836                 response->am[num].u.p.serial = port->p_serial;
837                 /* name */
838                 SCPY(response->am[num].u.p.name, port->p_name);
839                 /* epoint */
840                 response->am[num].u.p.epoint = ACTIVE_EPOINT(port->p_epointlist);
841                 /* state */
842                 switch(port->p_state)
843                 {
844                         case PORT_STATE_IN_SETUP:
845                         response->am[num].u.p.state = ADMIN_STATE_IN_SETUP;
846                         break;
847                         case PORT_STATE_OUT_SETUP:
848                         response->am[num].u.p.state = ADMIN_STATE_OUT_SETUP;
849                         break;
850                         case PORT_STATE_IN_OVERLAP:
851                         response->am[num].u.p.state = ADMIN_STATE_IN_OVERLAP;
852                         break;
853                         case PORT_STATE_OUT_OVERLAP:
854                         response->am[num].u.p.state = ADMIN_STATE_OUT_OVERLAP;
855                         break;
856                         case PORT_STATE_IN_PROCEEDING:
857                         response->am[num].u.p.state = ADMIN_STATE_IN_PROCEEDING;
858                         break;
859                         case PORT_STATE_OUT_PROCEEDING:
860                         response->am[num].u.p.state = ADMIN_STATE_OUT_PROCEEDING;
861                         break;
862                         case PORT_STATE_IN_ALERTING:
863                         response->am[num].u.p.state = ADMIN_STATE_IN_ALERTING;
864                         break;
865                         case PORT_STATE_OUT_ALERTING:
866                         response->am[num].u.p.state = ADMIN_STATE_OUT_ALERTING;
867                         break;
868                         case PORT_STATE_CONNECT:
869                         response->am[num].u.p.state = ADMIN_STATE_CONNECT;
870                         break;
871                         case PORT_STATE_IN_DISCONNECT:
872                         response->am[num].u.p.state = ADMIN_STATE_IN_DISCONNECT;
873                         break;
874                         case PORT_STATE_OUT_DISCONNECT:
875                         response->am[num].u.p.state = ADMIN_STATE_OUT_DISCONNECT;
876                         break;
877                         default:
878                         response->am[num].u.p.state = ADMIN_STATE_IDLE;
879                 }
880                 /* isdn */
881                 if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1)
882                 {
883                         response->am[num].u.p.isdn = 1;
884                         pdss1 = (class Pdss1 *)port;
885                         response->am[num].u.p.isdn_chan = pdss1->p_m_b_channel;
886                         response->am[num].u.p.isdn_hold = pdss1->p_m_hold;
887                         response->am[num].u.p.isdn_ces = pdss1->p_m_d_ces;
888                 }
889                 /* */
890                 port = port->next;
891                 num++;
892         }
893         return(0);
894 }
895
896 int sockserial = 1; // must start with 1, because 0 is used if no serial is set
897 /*
898  * handle admin socket (non blocking)
899  */
900 int admin_handle(void)
901 {
902         struct admin_list       *admin, **adminp;
903         void                    *temp;
904         struct admin_message    msg;
905         int                     len;
906         int                     new_sock;
907         socklen_t               sock_len = sizeof(sock_address);
908         unsigned long           on = 1;
909         int                     work = 0; /* if work was done */
910         struct Endpoint         *epoint;
911
912         if (sock < 0)
913                 return(0);
914
915         /* check for new incomming connections */
916         if ((new_sock = accept(sock, (struct sockaddr *)&sock_address, &sock_len)) >= 0)
917         {
918                 work = 1;
919                 /* insert new socket */
920                 admin = (struct admin_list *)malloc(sizeof(struct admin_list));
921                 if (admin)
922                 {
923                         if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0)
924                         {
925 //#warning
926 //      PERROR("DEBUG incomming socket %d, serial=%d\n", new_sock, sockserial);
927                                 memuse++;
928                                 fhuse++;
929                                 memset(admin, 0, sizeof(struct admin_list));
930                                 admin->sockserial = sockserial++;
931                                 admin->next = admin_list;
932                                 admin_list = admin;
933                                 admin->sock = new_sock;
934                         } else {
935                                 close(new_sock);
936                                 free(admin);
937                         }
938                 } else
939                         close(new_sock);
940         } else
941         {
942                 if (errno != EWOULDBLOCK)
943                 {
944                         PERROR("Failed to accept connection from socket \"%s\". (errno=%d) Closing socket.\n", sock_address.sun_path, errno);
945                         admin_cleanup();
946                         return(1);
947                 }
948         }
949
950         /* loop all current socket connections */
951         admin = admin_list;
952         adminp = &admin_list;
953         while(admin)
954         {
955                 /* read command */
956                 len = read(admin->sock, &msg, sizeof(msg));
957                 if (len < 0)
958                 {
959                         if (errno != EWOULDBLOCK)
960                         {
961                                 work = 1;
962                                 brokenpipe:
963                                 printf("Broken pipe on socket %d. (errno=%d).\n", admin->sock, errno);
964                                 PDEBUG(DEBUG_LOG, "Broken pipe on socket %d. (errno=%d).\n", admin->sock, errno);
965                                 *adminp = admin->next;
966                                 free_connection(admin);
967                                 admin = *adminp;
968                                 continue;
969                         }
970                         goto send_data;
971                 }
972                 work = 1;
973 //#warning
974 //PERROR("DEBUG socket %d got data. serial=%d\n", admin->sock, admin->sockserial);
975                 if (len == 0)
976                 {
977                         end:
978
979                         /*release endpoint if exists */
980                         if (admin->epointid)
981                         {
982                                 epoint = find_epoint_id(admin->epointid);
983                                 if (epoint)
984                                 {
985                                         ((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)->
986                                                 release(RELEASE_ALL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0, 0);
987                                 }
988                         }
989
990 //#warning
991 //PERROR("DEBUG socket %d closed by remote.\n", admin->sock);
992                         *adminp = admin->next;
993                         free_connection(admin);
994                         admin = *adminp;
995 //PERROR("DEBUG (admin_list=%x)\n", admin_list);
996                         continue;
997                 }
998                 if (len != sizeof(msg))
999                 {
1000                         PERROR("Short/long read on socket %d. (len=%d != size=%d).\n", admin->sock, len, sizeof(msg));
1001                         *adminp = admin->next;
1002                         free_connection(admin);
1003                         admin = *adminp;
1004                         continue;
1005                 }
1006                 /* process socket command */
1007                 if (admin->response)
1008                 {
1009                         PERROR("Data from socket %d while sending response.\n", admin->sock);
1010                         *adminp = admin->next;
1011                         free_connection(admin);
1012                         admin = *adminp;
1013                         continue;
1014                 }
1015                 switch (msg.message)
1016                 {
1017                         case ADMIN_REQUEST_CMD_INTERFACE:
1018                         if (admin_interface(&admin->response) < 0)
1019                         {
1020                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1021                                 goto response_error;
1022                         }
1023                         break;
1024
1025                         case ADMIN_REQUEST_CMD_ROUTE:
1026                         if (admin_route(&admin->response) < 0)
1027                         {
1028                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1029                                 goto response_error;
1030                         }
1031                         break;
1032
1033                         case ADMIN_REQUEST_CMD_DIAL:
1034                         if (admin_dial(&admin->response, msg.u.x.message) < 0)
1035                         {
1036                                 PERROR("Failed to create dial response for socket %d.\n", admin->sock);
1037                                 goto response_error;
1038                         }
1039                         break;
1040
1041                         case ADMIN_REQUEST_CMD_RELEASE:
1042                         if (admin_release(&admin->response, msg.u.x.message) < 0)
1043                         {
1044                                 PERROR("Failed to create release response for socket %d.\n", admin->sock);
1045                                 goto response_error;
1046                         }
1047                         break;
1048
1049                         case ADMIN_REQUEST_STATE:
1050                         if (admin_state(&admin->response) < 0)
1051                         {
1052                                 PERROR("Failed to create state response for socket %d.\n", admin->sock);
1053                                 goto response_error;
1054                         }
1055                         break;
1056
1057                         case ADMIN_TRACE_REQUEST:
1058                         if (admin_trace(admin, &msg.u.trace_req) < 0)
1059                         {
1060                                 PERROR("Failed to create trace response for socket %d.\n", admin->sock);
1061                                 goto response_error;
1062                         }
1063                         break;
1064
1065                         case ADMIN_REQUEST_CMD_BLOCK:
1066                         if (admin_block(&admin->response, msg.u.x.portnum, msg.u.x.block) < 0)
1067                         {
1068                                 PERROR("Failed to create block response for socket %d.\n", admin->sock);
1069                                 goto response_error;
1070                         }
1071                         break;
1072
1073 #warning interface tbd
1074 #if 0
1075                         case ADMIN_MESSAGE:
1076                         if (admin_message(&admin->response) < 0)
1077                         {
1078                                 PERROR("Failed to create message response for socket %d.\n", admin->sock);
1079                                 goto response_error;
1080                         }
1081 #endif
1082 #if 0
1083 #warning DEBUGGING
1084 {
1085         struct admin_queue      *response;
1086         printf("Chain: ");
1087         response = admin->response;
1088         while(response)
1089         {
1090                 printf("%c", '0'+response->am[0].message);
1091                 response=response->next;
1092         }
1093         printf("\n");
1094 }
1095 #endif
1096                         break;
1097
1098                         case ADMIN_CALL_SETUP:
1099                         if (admin_call(admin, &msg) < 0)
1100                         {
1101                                 PERROR("Failed to create call for socket %d.\n", admin->sock);
1102                                 response_error:
1103                                 *adminp = admin->next;
1104                                 free_connection(admin);
1105                                 admin = *adminp;
1106                                 continue;
1107                         }
1108                         break;
1109
1110                         default:
1111                         PERROR("Invalid message %d from socket %d.\n", msg.message, admin->sock);
1112                         *adminp = admin->next;
1113                         free_connection(admin);
1114                         admin = *adminp;
1115                         continue;
1116                 }
1117                 /* write queue */
1118                 send_data:
1119                 if (admin->response)
1120                 {
1121 //#warning
1122 //PERROR("DEBUG socket %d sending data.\n", admin->sock);
1123                         len = write(admin->sock, ((unsigned char *)(admin->response->am))+admin->response->offset, sizeof(struct admin_message)*(admin->response->num)-admin->response->offset);
1124                         if (len < 0)
1125                         {
1126                                 if (errno != EWOULDBLOCK)
1127                                 {
1128                                         work = 1;
1129                                         goto brokenpipe;
1130                                 }
1131                                 goto next;
1132                         }
1133                         work = 1;
1134                         if (len == 0)
1135                                 goto end;
1136                         if (len < (int)(sizeof(struct admin_message)*(admin->response->num)-admin->response->offset))
1137                         {
1138                                 admin->response->offset+=len;
1139                                 goto next;
1140                         } else
1141                         {
1142                                 temp = admin->response;
1143                                 admin->response = admin->response->next;
1144                                 free(temp);
1145                                 memuse--;
1146                         }
1147                 }
1148                 /* done with socket instance */
1149                 next:
1150                 adminp = &admin->next;
1151                 admin = admin->next;
1152         }
1153
1154         return(work);
1155 }
1156