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