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