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