Version 0.1.4 from FTP
[asterisk/asterisk.git] / channels / chan_vofr.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Implementation of Voice over Frame Relay, Adtran Style
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <pthread.h>
16 #include <string.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/channel_pvt.h>
19 #include <asterisk/config.h>
20 #include <asterisk/logger.h>
21 #include <asterisk/module.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/options.h>
24 #include <sys/socket.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <arpa/inet.h>
30 #include <linux/if_packet.h>
31 #include <linux/if_ether.h>
32 #ifndef OLD_SANGOMA_API
33 #include <linux/if_wanpipe.h>
34 #include <linux/wanpipe.h>
35 #endif
36 #include <sys/signal.h>
37 #include "adtranvofr.h"
38
39 /* #define VOFRDUMPER */
40
41 #define G723_MAX_BUF 2048
42
43 #define FR_API_MESS 16
44
45 static char *desc = "Adtran Voice over Frame Relay";
46 static char *type = "AdtranVoFR";
47 static char *tdesc = "Voice over Frame Relay/Adtran style";
48 static char *config = "adtranvofr.conf";
49
50 static char context[AST_MAX_EXTENSION] = "default";
51
52 static char language[MAX_LANGUAGE] = "";
53
54 static int usecnt =0;
55 static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
56
57 /* Protect the interface list (of vofr_pvt's) */
58 static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER;
59
60 /* Protect the monitoring thread, so only one process can kill or start it, and not
61    when it's doing something critical. */
62 static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
63
64 /* This is the thread for the monitor which checks for input on the channels
65    which are not currently in use.  */
66 static pthread_t monitor_thread = 0;
67
68 static int restart_monitor(void);
69
70 /* The private structures of the Adtran VoFR channels are linked for
71    selecting outgoing channels */
72    
73 static struct vofr_pvt {
74         int s;                                                  /* Raw socket for this DLCI */
75 #ifdef OLD_SANGOMA_API
76         struct sockaddr_pkt sa;                 /* Sockaddr needed for sending, also has iface name */
77 #else
78         struct wan_sockaddr_ll sa;              /* Wanpipe sockaddr */
79 #endif
80         struct ast_channel *owner;              /* Channel we belong to, possibly NULL */
81         int outgoing;                                   /* Does this channel support outgoing calls? */
82         struct vofr_pvt *next;                  /* Next channel in list */
83         struct vofr_hdr *hdr;                           /* VOFR header version of buf */
84         struct vofr_hdr *ohdr;
85         u_int8_t dlcih;                                 /* High two bits of DLCI */
86         u_int8_t dlcil;                                 /* Bottom two bits of DLCI */
87         u_int8_t cid;                                   /* Call ID */
88         char buf[G723_MAX_BUF];                                 /* Static buffer for reading frames */
89         char obuf[G723_MAX_BUF];                                /* Output buffer */
90         char context[AST_MAX_EXTENSION];
91         char language[MAX_LANGUAGE];
92         int ringgothangup;                              /* Have we received exactly one hangup after a ring */
93 } *iflist = NULL;
94
95 #ifdef VOFRDUMPER
96
97 /* Some useful debugging routines */
98
99 static char *set(int val)
100 {
101         return (val ? "Set  " : "Unset");
102 }
103
104 static char *controlstr(int control)
105 {
106         switch(control) {
107         case VOFR_CONTROL_ADTRAN:
108                 return "Adtran Proprietary";
109         case VOFR_CONTROL_VOICE:
110                 return "Voice";
111         case VOFR_CONTROL_RFC1490:
112                 return "RFC 1490";
113         }
114         return "Unknown";
115 }
116
117 static char *dtypestr(int control)
118 {
119         switch(control) {
120         case VOFR_TYPE_SIGNAL:
121                 return "Signal Frame";
122         case VOFR_TYPE_VOICE:
123                 return "Voice Frame";
124         case VOFR_TYPE_ANSWER:
125                 return "Answer Tone";
126         case VOFR_TYPE_FAX:     
127                 return "FAX";
128         case VOFR_TYPE_DTMF:
129                 return "DTMF Digit";
130         }
131         return "Unknown";
132 }
133
134 static char *vflagsstr(int flags)
135 {
136         static char buf[80];
137         buf[0] = '\0';
138         if (!flags)
139                 return "(None)";
140         if (flags & VOFR_ROUTE_LOCAL)
141                 strcat(buf, "Local ");
142         if (flags & VOFR_ROUTE_VOICE)
143                 strcat(buf, "Voice ");
144         if (flags & VOFR_ROUTE_DTE)
145                 strcat(buf, "DTE ");
146         else if (flags & VOFR_ROUTE_DTE1)
147                 strcat(buf, "DTE1 ");
148         else if (flags & VOFR_ROUTE_DTE2)       
149                 strcat(buf, "DTE2 ");
150         return buf;
151 }
152
153 static char *remidstr(int remid)
154 {
155         switch(remid) {
156         case VOFR_CARD_TYPE_UNSPEC:
157                 return "Unspecified";
158         case VOFR_CARD_TYPE_FXS:
159                 return "FXS";
160         case VOFR_CARD_TYPE_FXO:
161                 return "FXO";
162         case VOFR_CARD_TYPE_ENM:        
163                 return "E&M";
164         case VOFR_CARD_TYPE_VCOM:       
165                 return "Atlas/VCOM";
166         }
167         return "Unknown";
168 }
169
170 static char *modulationstr(int modulation)
171 {
172         switch(modulation) {
173         case VOFR_MODULATION_SINGLE:
174                 return "Single Frequency";
175         case VOFR_MODULATION_V21:
176                 return "V.21";
177         case VOFR_MODULATION_V27ter_2:
178                 return "V.27 (2400bps)";
179         case VOFR_MODULATION_V27ter_4:
180                 return "V.27 (4800bps)";
181         case VOFR_MODULATION_V29_7:
182                 return "V.29 (7200bps)";
183         case VOFR_MODULATION_V29_9:
184                 return "V.29 (9600bps)";
185         case VOFR_MODULATION_V33_12:
186                 return "V.33 (12000bps)";
187         case VOFR_MODULATION_V33_14:
188                 return "V.33 (14400BPS)";
189         }
190         return "Unknown";
191 }
192
193 static char *signalstr(int signal)
194 {
195         switch(signal) {
196         case VOFR_SIGNAL_ON_HOOK:
197                 return "On Hook";
198         case VOFR_SIGNAL_OFF_HOOK:
199                 return "Off Hook";
200         case VOFR_SIGNAL_RING:
201                 return "Ring";
202         case VOFR_SIGNAL_SWITCHED_DIAL:
203                 return "Switched Dial";
204         case VOFR_SIGNAL_BUSY:
205                 return "Busy";
206         case VOFR_SIGNAL_TRUNK_BUSY:
207                 return "Trunk Busy";
208         }
209         return "Unknown";
210 }
211
212 static char *vofr_digitstr(int val)
213 {
214         static char num[5];
215         if (val < 10) {
216                 snprintf(num, sizeof(num), "%d", val);
217                 return num;
218         }
219         switch(val) {
220         case 10:
221                 return "*";
222         case 11:
223                 return "#";
224         }
225         return "Unknown";
226 }
227
228
229 static void vofr_dump_packet(struct vofr_hdr *vh, int len)
230 {
231         printf("VoFR Packet Dump\n");
232         printf("================\n");
233         printf("EI: %s ", set(vh->control & VOFR_MASK_EI));
234         printf("LI: %s\n", set(vh->control & VOFR_MASK_LI));
235         printf("Control: %s (0x%02x)\n", 
236                 controlstr(vh->control & VOFR_MASK_CONTROL), vh->control & VOFR_MASK_CONTROL);
237         printf("Data Type: %s (0x%02x)\n", dtypestr(vh->dtype), vh->dtype);
238         if (vh->dtype == VOFR_TYPE_SIGNAL) {
239                 printf(" \\--Signal: %s (0x%02x)\n", signalstr(vh->data[0]), vh->data[0]);
240         }
241         if (vh->dtype == VOFR_TYPE_DTMF) {
242                 printf(" \\--Digit: %s (0x%02x)\n", vofr_digitstr(vh->data[0]), vh->data[0]);
243         }
244         printf("Connect Tag: 0x%02x\n", vh->ctag);
245         printf("Voice Rt Flags: %s\n", vflagsstr(vh->vflags));
246         printf("DLCI X-Ref: %d\n", (vh->dlcih << 8) | (vh->dlcil));
247         printf("Channel ID: %d\n", vh->cid);
248         printf("Remote ID: %s (0x%02x)\n", remidstr(vh->remid), vh->remid);
249         printf("Modulation: %s (0x%02x)\n", modulationstr(vh->mod), vh->mod);
250         printf("\n");
251         fflush(stdout);
252 }
253
254 #endif
255
256 static int vofr_xmit(struct vofr_pvt *p, char *data, int len)
257 {
258         int res;
259 #ifdef OLD_SANGOMA_API
260     res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_pkt));
261 #else
262     res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct wan_sockaddr_ll));
263 #endif
264         if (res != len) {
265                 ast_log(LOG_WARNING, "vofr_xmit returned %d\n", res);
266         }
267         return res;
268 }
269
270 static int vofr_digit(struct ast_channel *ast, char digit)
271 {
272         /*
273          * T H I S   I S   T O T A L L Y   U N D O C U M E N T E D
274          *     A N D   D O E S   N O T   S O U N D   R I G H T
275          *   XXX Figure out how to really send a decent digit XXX
276          */
277         struct vofr_pvt *p;
278         struct vofr_hdr *vh;
279         p = ast->pvt->pvt;
280         vh = p->ohdr;
281         vh->control = VOFR_CONTROL_VOICE;
282         vh->dtype = VOFR_TYPE_DTMF;
283         vh->vflags = VOFR_ROUTE_NONE;
284         vh->dlcih = p->dlcih;
285         vh->dlcil = p->dlcil;
286         vh->cid = p->cid;
287         vh->remid = VOFR_CARD_TYPE_ASTERISK;
288         vh->mod = VOFR_MODULATION_SINGLE;
289         if ((digit >= '0') && (digit <= '9'))
290                 vh->data[0] = digit - '0';
291         else if (digit == '*')
292                 vh->data[0] = 10;
293         else if (digit == '#')
294                 vh->data[0] = 11;
295         else {
296                 ast_log(LOG_WARNING, "%s: tried to dial a non digit '%c'\n", ast->name, digit);
297                 return -1;
298         }
299         vh->data[1] = 0x14;
300         vh->data[2] = 0x1f;
301         vh->data[3] = 0x70;
302                 /* We sorta start the digit */
303         vofr_xmit(p, p->obuf, VOFR_HDR_SIZE + 4 + FR_API_MESS);
304         usleep(30000);
305                 /* And terminate with an empty voice frame */
306         vh->control = VOFR_CONTROL_VOICE;
307         vh->dtype = VOFR_TYPE_VOICE;
308         vh->vflags = VOFR_ROUTE_NONE;
309         vh->dlcih = p->dlcih;
310         vh->dlcil = p->dlcil;
311         vh->cid = p->cid;
312         vh->remid = VOFR_CARD_TYPE_ASTERISK;
313         vh->mod = VOFR_MODULATION_SINGLE;
314         vofr_xmit(p, p->obuf, VOFR_HDR_SIZE + FR_API_MESS);
315         return 0;
316 }
317
318 static int vofr_xmit_signal(struct vofr_pvt *p, int signal, int pad)
319 {
320         /* Prepare and transmit outgoing buffer with given signal and
321            pad the end with *pad* bytes of data presumed to already
322            be in the buffer (like DTMF tones, etc) */
323         struct vofr_hdr *vh = p->ohdr;
324         int res;
325     vh->control = VOFR_CONTROL_VOICE;
326     vh->dtype = VOFR_TYPE_SIGNAL;
327     vh->vflags = VOFR_ROUTE_NONE;
328     vh->dlcih = p->dlcih;
329     vh->dlcil = p->dlcil;
330     vh->cid = p->cid;
331     vh->remid = VOFR_CARD_TYPE_ASTERISK;
332     vh->mod = VOFR_MODULATION_SINGLE;
333     vh->data[0] = signal;
334         if (FR_API_MESS)
335                 memset(p->obuf, 0, FR_API_MESS);
336         res = vofr_xmit(p, p->obuf,  VOFR_HDR_SIZE + pad + 1 + FR_API_MESS);
337         return res;
338
339 }
340
341 static int vofr_call(struct ast_channel *ast, char *dest, int timeout)
342 {
343         int res;
344         int otimeout;
345         struct ast_frame *f;
346         struct vofr_pvt *p;
347         p = ast->pvt->pvt;
348         if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
349                 ast_log(LOG_WARNING, "vofr_call called on %s, neither down nor reserved\n", ast->name);
350                 return -1;
351         }
352         /* Take the system off hook */
353         vofr_xmit_signal(p, VOFR_SIGNAL_OFFHOOK, 0);
354         /* Wait for an acknowledgement */
355         otimeout = 1000;
356         while(otimeout) {
357                 otimeout = ast_waitfor(ast, 1000);
358                 if (otimeout < 1) {
359                         ast_log(LOG_WARNING, "Unable to take line '%s' off hook\n", ast->name);
360                         /* Musta gotten hung up, or no ack on off hook */
361                         return -1;      
362                 }
363                 f = ast_read(ast);
364                 if (!f)
365                         return -1;
366                 if ((f->frametype == AST_FRAME_CONTROL) &&
367                     (f->subclass == AST_CONTROL_OFFHOOK)) 
368                         /* Off hook */
369                                 break;
370         }
371         if (!otimeout) {
372                 ast_log(LOG_WARNING, "Unable to take line off hook\n");
373                 return -1;
374         }
375         /* Send the digits */
376         while(*dest) {
377                 ast->state = AST_STATE_DIALING;
378                 vofr_digit(ast, *dest);
379                 /* Wait .1 seconds before dialing next digit */
380                 usleep(100000);
381                 dest++;
382         }
383         if (timeout) {
384                 /* Wait for the ack that it's ringing */
385                 otimeout = 1000;
386                 while(otimeout) {
387                         otimeout = ast_waitfor(ast, 1000);
388                         if (otimeout < 1) {
389                                 ast_log(LOG_WARNING, "No acknowledgement for ringing\n");
390                                 /* Musta gotten hung up, or no ack on off hook */
391                                 return -1;      
392                         }
393                         f = ast_read(ast);
394                         if (!f) 
395                                 return -1;
396                         
397                         if (f->frametype == AST_FRAME_CONTROL) {
398                             if (f->subclass == AST_CONTROL_RINGING) {
399                                         ast->state = AST_STATE_RINGING;
400                                         /* We're ringing -- good enough */
401                                         break;
402                                 }
403                                 if (f->subclass == AST_CONTROL_BUSY)
404                                 /* It's busy */
405                                         return -1;
406                         }
407                         ast_frfree(f);
408                 }               
409         }
410         otimeout = timeout;
411         while(timeout) {
412                 /* Wait for an answer, up to timeout... */
413                 res = ast_waitfor(ast, timeout);
414                 if (res < 0)
415                         /* Musta gotten hung up */
416                         return -1;
417                 else
418                         timeout = res;
419                 if (res) {
420                         /* Ooh, read what's there. */
421                         f = ast_read(ast);
422                         if (!f)
423                                 return -1;
424                         if ((f->frametype == AST_FRAME_CONTROL) && 
425                             (f->subclass == AST_CONTROL_ANSWER)) 
426                                 /* Got an answer -- return the # of ms it took */
427                                 return otimeout - res;
428                                 
429                 }
430         }
431         return 0;
432 }
433
434 static int send_hangup(struct vofr_pvt *p)
435 {
436         /* Just send the hangup sequence */
437         return vofr_xmit_signal(p, 0x80, 0);
438 }
439
440 static int vofr_hangup(struct ast_channel *ast)
441 {
442         int res;
443         if (option_debug)
444                 ast_log(LOG_DEBUG, "vofr_hangup(%s)\n", ast->name);
445         if (!ast->pvt->pvt) {
446                 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
447                 return 0;
448         }
449         res = send_hangup(ast->pvt->pvt);
450         if (res < 0) {
451                 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
452                 return -1;
453         }
454         ast->state = AST_STATE_DOWN;
455         ((struct vofr_pvt *)(ast->pvt->pvt))->owner = NULL;
456         ((struct vofr_pvt *)(ast->pvt->pvt))->ringgothangup = 0;
457         pthread_mutex_lock(&usecnt_lock);
458         usecnt--;
459         if (usecnt < 0) 
460                 ast_log(LOG_WARNING, "Usecnt < 0???\n");
461         pthread_mutex_unlock(&usecnt_lock);
462         ast_update_use_count();
463         if (option_verbose > 2) 
464                 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
465         ast->pvt->pvt = NULL;
466         ast->state = AST_STATE_DOWN;
467         restart_monitor();
468         return 0;
469 }
470
471 static int vofr_answer(struct ast_channel *ast)
472 {
473         int res;
474         int cnt = 1000;
475         char buf[2048];
476         struct vofr_hdr *vh;
477         ast->rings = 0;
478         if (option_debug)
479                 ast_log(LOG_DEBUG, "vofr_answer(%s)\n", ast->name);
480         res = vofr_xmit_signal(ast->pvt->pvt, VOFR_SIGNAL_OFFHOOK, 0);
481         if (res < 0)
482                 ast_log(LOG_WARNING, "Unable to anaswer line %s\n", ast->name);
483         ast->state = AST_STATE_UP;
484         while(cnt > 0) {
485                 cnt = ast_waitfor(ast, cnt);
486                 if (cnt > 0) {
487                         res = read(ast->fd, buf, sizeof(buf));
488 #ifdef VOFRDUMPER
489                                 vofr_dump_packet((void *)(buf +FR_API_MESS), res - FR_API_MESS);
490 #endif
491                         res -= FR_API_MESS;
492                         if (res < 0)
493                                 ast_log(LOG_WARNING, "Warning:  read failed (%s) on %s\n", strerror(errno), ast->name);
494                         else {
495                                 /* We're looking for an answer */
496                                 vh = (struct vofr_hdr *)(buf + FR_API_MESS);
497                                 switch(vh->dtype) {
498                                 case VOFR_TYPE_SIGNAL:
499                                         switch(vh->data[0]) {
500                                         case VOFR_SIGNAL_UNKNOWN:
501                                                 switch(vh->data[1]) {
502                                                 case 0x1:
503                                                         if (option_debug) 
504                                                                 ast_log(LOG_DEBUG, "Answered '%s'\n", ast->name);
505                                                         else if (option_verbose > 2) 
506                                                                 ast_verbose( VERBOSE_PREFIX_3 "Answered '%s'\n", ast->name);
507                                                         ast->state = AST_STATE_UP;
508                                                         return 0;
509                                                         break;
510                                                 default:
511                                                         ast_log(LOG_WARNING, "Unexpected 'unknown' frame type %d\n", vh->data[1]);
512                                                 }
513                                                 break;
514                                         case VOFR_SIGNAL_ON_HOOK:
515                                                 /* Ignore onhooks.  */
516                                                 break;
517                                         default:
518                                                 ast_log(LOG_WARNING, "Unexpected signal type %d\n", vh->data[0]);
519                                         }
520                                         break;
521                                 default:
522                                         ast_log(LOG_WARNING, "Unexpected data type %d\n", vh->dtype);
523                                 }
524                         }
525                 }
526         }
527         ast_log(LOG_WARNING, "Did not get acknowledged answer\n");
528         return -1;
529 }
530
531 static char vofr_2digit(char c)
532 {
533         if (c == 11)
534                 return '#';
535         else if (c == 10)
536                 return '*';
537         else if ((c < 10) && (c >= 0))
538                 return '0' + c;
539         else
540                 return '?';
541 }
542
543 static struct ast_frame  *vofr_read(struct ast_channel *ast)
544 {
545         int res;
546         char tone;
547         int timeout,x;
548         struct vofr_pvt *p = ast->pvt->pvt;
549         short *swapping;
550         struct ast_frame *fr = (struct ast_frame *)(p->buf);
551         struct vofr_hdr *vh = (struct vofr_hdr *)(p->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET - sizeof(struct vofr_hdr));
552         /* Read into the right place in the buffer, in case we send this
553            as a voice frame. */
554         CHECK_BLOCKING(ast);
555 retry:
556         res = read(p->s, ((char *)vh)  - FR_API_MESS, 
557                                 G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
558         if (res < 0) {
559                 /*  XXX HUGE BUG IN SANGOMA'S STACK: IT IGNORES O_NONBLOCK XXX */
560                 if (errno == EAGAIN) {
561                         fd_set fds;
562                         FD_ZERO(&fds);
563                         FD_SET(p->s, &fds);
564                         select(p->s + 1, &fds, NULL, NULL, NULL);
565                         goto retry;
566                 }
567                 ast->blocking = 0;
568                 ast_log(LOG_WARNING, "Read error on %s: %s (%d)\n", ast->name, strerror(errno));
569                 return NULL;
570         }
571         ast->blocking = 0;
572                 
573 #ifdef VOFRDUMPER
574         vofr_dump_packet((void *)(vh), res);
575 #endif
576         res -= FR_API_MESS;             
577         if (res < sizeof(struct vofr_hdr)) {
578                 ast_log(LOG_WARNING, "Nonsense frame on %s\n", ast->name);
579                 return NULL;
580         }
581         /* Some nice norms */
582         fr->datalen = 0;
583         fr->timelen = 0;
584         fr->data =  NULL;
585         fr->src = type;
586         fr->offset = 0;
587         fr->mallocd=0;
588         
589         /* Now, what we do depends on what we read */
590         switch(vh->dtype) {
591         case VOFR_TYPE_SIGNAL:
592                 switch(vh->data[0]) {
593                 case VOFR_SIGNAL_ON_HOOK:
594                         /* Hang up this line */
595                         if ((ast->state == AST_STATE_UP) || (p->ringgothangup)) {
596                                 return NULL;
597                         } else {
598                                 fr->frametype = AST_FRAME_NULL;
599                                 fr->subclass = 0;
600                                 p->ringgothangup=1;
601                         }
602                         break;
603                 case VOFR_SIGNAL_RING:
604                         ast->rings++;
605                         p->ringgothangup = 0;
606                         break;
607                 case VOFR_SIGNAL_UNKNOWN:
608                         switch(vh->data[1]) {
609                         case 0x1:
610                                 /* This is a little tricky, because it depends
611                                    on the context of what state we're in */
612                                 switch(ast->state) {
613                                 case AST_STATE_RINGING:
614                                         fr->frametype = AST_FRAME_CONTROL;
615                                         fr->subclass = AST_CONTROL_ANSWER;
616                                         ast->state = AST_STATE_UP;
617                                         break;
618                                 case AST_STATE_DOWN:
619                                 case AST_STATE_UP:
620                                         fr->frametype = AST_FRAME_NULL;
621                                         fr->subclass = 0;
622                                         break;
623                                 }
624                                 break;
625                         case 0x2:
626                                 /* Remote acknowledged off hook */
627                                 fr->frametype = AST_FRAME_CONTROL;
628                                 fr->subclass = AST_CONTROL_OFFHOOK;
629                                 ast->state = AST_STATE_OFFHOOK;
630                                 break;
631                         case 0x3:
632                                 /* Busy signal */
633                                 fr->frametype = AST_FRAME_CONTROL;
634                                 fr->subclass = AST_CONTROL_BUSY;
635                                 ast->state = AST_STATE_BUSY;
636                                 break;
637                         case 0x5:
638                                 /* Ringing -- acknowledged */
639                                 fr->frametype = AST_FRAME_CONTROL;
640                                 fr->subclass = AST_CONTROL_RINGING;
641                                 ast->state = AST_STATE_RINGING;
642                                 break;
643                         case 0x6:
644                                 /* Hang up detected.  Return NULL */
645                                 return NULL;
646                         default:
647                                 ast_log(LOG_WARNING, "Don't know what to do with 'unknown' signal '%d'\n", vh->data[1]);
648                                 fr->frametype = AST_FRAME_NULL;
649                                 fr->subclass = 0;
650                         }
651                         return fr;
652                         break;
653                 default:
654                         ast_log(LOG_WARNING, "Don't know what to do with signal '%d'\n", vh->data[0]);
655                 }
656                 break;
657         case VOFR_TYPE_DTMF:
658                 /* If it's a DTMF tone, then we want to wait until we don't get any more dtmf tones or
659                    the DTMF tone changes.  
660                        XXX Note: We will drop at least one frame here though XXX */
661                 
662                 tone = vofr_2digit(vh->data[0]);
663                 timeout = 50;
664                 do {
665                         if ((timeout = ast_waitfor(ast, timeout)) < 1)
666                                 break;
667                         CHECK_BLOCKING(ast);
668                         res = read(p->s, ((char *)vh)  - FR_API_MESS, 
669                                         G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
670                         ast->blocking = 0;
671                         res -= FR_API_MESS;             
672                         if (res < sizeof(struct vofr_hdr *)) {
673                                 ast_log(LOG_WARNING, "Nonsense frame on %s\n", ast->name);
674                                 return NULL;
675                         }
676                         if (vh->dtype == VOFR_TYPE_DTMF) {
677                                 /* Reset the timeout */
678                                 timeout = 50;
679                                 if ((tone != vofr_2digit(vh->data[0])) )
680                                         /* Or not...  Something else now.. Just send our first frame */
681                                         break;
682                         }
683                         
684                 } while (timeout);
685                 fr->frametype = AST_FRAME_DTMF;
686                 fr->subclass = tone;
687                 fr->datalen = 0;
688                 fr->data = NULL;
689                 fr->offset = 0;
690                 return fr;
691         case VOFR_TYPE_VOICE:
692                 /* XXX Bug in the Adtran: Sometimes we don't know when calls are picked up, so if we
693                        get voice frames, go ahead and consider it answered even though it probably has
694                            not been answered XXX */
695                 if ((ast->state == AST_STATE_RINGING) || (ast->state == AST_STATE_DIALING))  {
696                         ast_log(LOG_DEBUG, "Adtran bug! (state = %d)\n", ast->state);
697                         fr->frametype = AST_FRAME_CONTROL;
698                         fr->subclass = AST_CONTROL_ANSWER;
699                         ast->state = AST_STATE_UP;
700                         return fr;
701                 } else if (ast->state !=  AST_STATE_UP) {
702                         ast_log(LOG_WARNING, "%s: Voice in weird state %d\n", ast->name, ast->state);
703                 }
704                 fr->frametype = AST_FRAME_VOICE;
705                 fr->subclass = AST_FORMAT_G723_1;
706                 fr->datalen = res - sizeof(struct vofr_hdr);
707                 fr->data = ((char *)vh) + sizeof(struct vofr_hdr);
708                 fr->src = type;
709                 /* XXX Byte swapping is a bug XXX */
710                 swapping = fr->data;
711                 for (x=0;x<fr->datalen/2;x++)
712                         swapping[x] = ntohs(swapping[x]);
713                 fr->offset = AST_FRIENDLY_OFFSET;
714                 /* Thirty ms of sound per frame */
715                 fr->timelen = 30;
716                 return fr;
717         default:
718                 ast_log(LOG_WARNING, "Don't know what to do with data type %d frames\n", vh->dtype);
719         }
720         /* If we don't know what it is, send a NULL frame */
721         fr->frametype = AST_FRAME_NULL;
722         fr->subclass = 0;
723         return fr;
724 }
725
726 static int vofr_write(struct ast_channel *ast, struct ast_frame *frame)
727 {
728         struct vofr_hdr *vh;
729         struct vofr_pvt *p = ast->pvt->pvt;
730         short *swapping;
731     int x;
732         char *start;
733         int res;
734         /* Write a frame of (presumably voice) data */
735         if (frame->frametype != AST_FRAME_VOICE) {
736                 ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
737                 return -1;
738         }
739         if (frame->subclass != AST_FORMAT_G723_1) {
740                 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
741                 return -1;
742         }
743         /* If we get here, we have a voice frame of G.723.1 data.  First check to be
744            sure we have enough headroom for the vofr header.  If there isn't enough
745            headroom, we're lazy and just error out rather than copying it into the
746            output buffer, because applications should always leave AST_FRIENDLY_OFFSET
747            bytes just for this reason. */
748         if (frame->offset < sizeof(struct vofr_hdr) + FR_API_MESS) {
749                 ast_log(LOG_WARNING, "Frame source '%s' didn't provide a friendly enough offset\n", (frame->src ? frame->src : "**Unknown**"));
750                 return -1;
751         }
752         /* XXX Byte swapping is a bug XXX */
753         swapping = frame->data;
754         for (x=0;x<frame->datalen/2;x++)
755                 swapping[x] = ntohs(swapping[x]);
756         vh = (struct vofr_hdr *)(frame->data - sizeof(struct vofr_hdr));
757         /* Some versions of the API have some header mess that needs to be
758            zero'd out and acounted for..  */
759         start = ((void *)vh) - FR_API_MESS;
760         if (start)
761                 memset(start, 0, FR_API_MESS);
762         /* Now we fill in the vofr header */
763         vh->control = VOFR_CONTROL_VOICE;
764         vh->dtype = VOFR_TYPE_VOICE;
765         vh->vflags = VOFR_ROUTE_NONE;
766         vh->dlcih = p->dlcih;
767         vh->dlcil = p->dlcil;
768         vh->cid = p->cid;
769         vh->remid = VOFR_CARD_TYPE_ASTERISK;
770         vh->mod = VOFR_MODULATION_SINGLE;
771         res = vofr_xmit(p, start, 
772                                 VOFR_HDR_SIZE + frame->datalen + FR_API_MESS);
773         res -= FR_API_MESS;
774         /* XXX Byte swapping is a bug, but get it back to the right format XXX */
775         swapping = frame->data;
776         for (x=0;x<frame->datalen/2;x++)
777                 swapping[x] = htons(swapping[x]);
778         if (res != VOFR_HDR_SIZE + frame->datalen) {
779                 ast_log(LOG_WARNING, "Unable to write frame correctly\n");
780                 return -1;
781         }
782         return 0;
783 }
784
785 static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
786 {
787         struct ast_channel *tmp;
788         tmp = ast_channel_alloc();
789         if (tmp) {
790 #ifdef OLD_SANGOMA_API
791                 snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.spkt_device);
792 #else
793                 snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.sll_device);
794 #endif
795                 tmp->type = type;
796                 tmp->fd = i->s;
797                 /* Adtran VoFR supports only G723.1 format data.  G711 (ulaw) would be nice too */
798                 tmp->format = AST_FORMAT_G723_1;
799                 tmp->state = state;
800                 if (state == AST_STATE_RING)
801                         tmp->rings = 1;
802                 tmp->pvt->pvt = i;
803                 tmp->pvt->send_digit = vofr_digit;
804                 tmp->pvt->call = vofr_call;
805                 tmp->pvt->hangup = vofr_hangup;
806                 tmp->pvt->answer = vofr_answer;
807                 tmp->pvt->read = vofr_read;
808                 tmp->pvt->write = vofr_write;
809                 if (strlen(i->language))
810                         strncpy(tmp->language, i->language, sizeof(tmp->language));
811                 i->owner = tmp;
812                 pthread_mutex_lock(&usecnt_lock);
813                 usecnt++;
814                 pthread_mutex_unlock(&usecnt_lock);
815                 ast_update_use_count();
816                 strncpy(tmp->context, i->context, sizeof(tmp->context));
817                 if (state != AST_STATE_DOWN) {
818                         if (ast_pbx_start(tmp)) {
819                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
820                                 ast_hangup(tmp);
821                                 tmp = NULL;
822                         }
823                 }
824         } else
825                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
826         return tmp;
827 }
828
829 static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len)
830 {
831         /* Here, we're looking for rings or off hooks -- signals that
832            something is about to happen and we need to start the 
833            PBX thread */
834         switch(pkt->dtype) {
835         case VOFR_TYPE_SIGNAL:
836                 switch(pkt->data[0]) {
837                 case VOFR_SIGNAL_RING:
838                         /* If we get a RING, we definitely want to start a new thread */
839                         if (!i->owner) {
840                                 i->ringgothangup = 0;
841                                 vofr_new(i, AST_STATE_RING);
842                         } else
843                                 ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n");
844                         break;
845                 case VOFR_SIGNAL_OFF_HOOK:
846                         /* Network termination, go off hook */
847 #if 0
848                         ast_log(LOG_DEBUG, "Off hook\n");
849 #endif
850                         vofr_xmit_signal(i, 0x10, 2);
851                         if (!i->owner)
852                                 vofr_new(i, AST_STATE_UP);
853                         else
854                                 ast_log(LOG_WARNING, "Got an offhook, but there's an owner?\n");
855                         break;
856                 case VOFR_SIGNAL_ON_HOOK:
857                         break;
858                 case VOFR_SIGNAL_UNKNOWN:
859                         switch(pkt->data[1]) {
860                         case 0x1:
861                                 /* ignore */
862                                 break;
863                         case 0x6:
864                                 /* A remote hangup request */
865                                 if (option_debug)
866                                         ast_log(LOG_DEBUG, "Sending hangup reply\n");
867                                 send_hangup(i);
868                                 break;
869                         default:
870                                 ast_log(LOG_WARNING, "Unexected 'unknown' signal '%d'\n", pkt->data[1]);
871                         }
872                         break;
873                 default:
874                         ast_log(LOG_DEBUG, "Unknown signal type '%d'\n", pkt->data[0]);
875                 }                       
876                 break;
877         case VOFR_TYPE_VOICE:
878                 break;
879         default:
880                 ast_log(LOG_DEBUG, "Unknown packet type '%d'\n", pkt->dtype);
881         }
882         return 0;
883 }
884
885 static void *do_monitor(void *data)
886 {
887         fd_set rfds;
888         int n, res;
889         struct vofr_pvt *i;
890         /* This thread monitors all the frame relay interfaces which are not yet in use
891            (and thus do not have a separate thread) indefinitely */
892         /* From here on out, we die whenever asked */
893 #if 0
894         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
895                 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
896                 return NULL;
897         }
898 #endif
899         for(;;) {
900                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
901                    and wait for the monitor list, but the other way around is okay. */
902                 if (pthread_mutex_lock(&monlock)) {
903                         ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
904                         return NULL;
905                 }
906                 /* Lock the interface list */
907                 if (pthread_mutex_lock(&iflock)) {
908                         ast_log(LOG_ERROR, "Unable to grab interface lock\n");
909                         pthread_mutex_unlock(&monlock);
910                         return NULL;
911                 }
912                 /* Build the stuff we're going to select on, that is the socket of every
913                    vofr_pvt that does not have an associated owner channel */
914                 n = -1;
915                 FD_ZERO(&rfds);
916                 i = iflist;
917                 while(i) {
918                         if (FD_ISSET(i->s, &rfds)) 
919 #ifdef OLD_SANGOMA_API
920                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.spkt_device);
921 #else
922                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.sll_device);
923 #endif
924                         if (!i->owner) {
925                                 /* This needs to be watched, as it lacks an owner */
926                                 FD_SET(i->s, &rfds);
927                                 if (i->s > n)
928                                         n = i->s;
929                         }
930                         i = i->next;
931                 }
932                 /* Okay, now that we know what to do, release the interface lock */
933                 pthread_mutex_unlock(&iflock);
934                 
935                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
936                 pthread_mutex_unlock(&monlock);
937                 pthread_testcancel();
938                 /* Wait indefinitely for something to happen */
939                 res = select(n + 1, &rfds, NULL, NULL, NULL);
940                 pthread_testcancel();
941                 /* Okay, select has finished.  Let's see what happened.  */
942                 if (res < 0) {
943                         if ((errno != EAGAIN) && (errno != EINTR))
944                                 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
945                         continue;
946                 }
947                 /* Alright, lock the interface list again, and let's look and see what has
948                    happened */
949                 if (pthread_mutex_lock(&iflock)) {
950                         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
951                         continue;
952                 }
953                 i = iflist;
954                 while(i) {
955                         if (FD_ISSET(i->s, &rfds)) {
956                                 if (i->owner) {
957 #ifdef OLD_SANGOMA_API
958                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->s, i->sa.spkt_device);
959 #else
960                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->s, i->sa.sll_device);
961 #endif
962                                         continue;
963                                 }
964                                 res = read(i->s, i->buf, sizeof(i->buf));
965                                 res -= FR_API_MESS;
966 #ifdef VOFRDUMPER
967                                 vofr_dump_packet(i->hdr, res);
968 #endif
969                                 vofr_mini_packet(i, i->hdr, res);
970                         }
971                         i=i->next;
972                 }
973                 pthread_mutex_unlock(&iflock);
974         }
975         /* Never reached */
976         return NULL;
977         
978 }
979
980 static int restart_monitor(void)
981 {
982         /* If we're supposed to be stopped -- stay stopped */
983         if (monitor_thread == -2)
984                 return 0;
985         if (pthread_mutex_lock(&monlock)) {
986                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
987                 return -1;
988         }
989         if (monitor_thread == pthread_self()) {
990                 pthread_mutex_unlock(&monlock);
991                 ast_log(LOG_WARNING, "Cannot kill myself\n");
992                 return -1;
993         }
994         if (monitor_thread) {
995 #if 0
996                 pthread_cancel(monitor_thread);
997 #endif
998                 pthread_kill(monitor_thread, SIGURG);
999 #if 0
1000                 pthread_join(monitor_thread, NULL);
1001 #endif
1002         }
1003         if (!monitor_thread)
1004         /* Start a new monitor */
1005         if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
1006                 pthread_mutex_unlock(&monlock);
1007                 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
1008                 return -1;
1009         }
1010         pthread_mutex_unlock(&monlock);
1011         return 0;
1012 }
1013
1014 static struct vofr_pvt *mkif(char *type, char *iface)
1015 {
1016         /* Make a vofr_pvt structure for this interface */
1017         struct vofr_pvt *tmp;
1018         int sndbuf = 4096;
1019
1020         tmp = malloc(sizeof(struct vofr_pvt));
1021         if (tmp) {
1022
1023                 /* Allocate a packet socket */
1024 #ifdef OLD_SANGOMA_API
1025                 tmp->s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
1026 #else
1027                 /* Why the HELL does Sangoma change their API every damn time
1028                    they make a new driver release?!?!?!  Leave it the hell
1029                    alone this time.  */
1030                 tmp->s = socket(AF_WANPIPE, SOCK_RAW, 0);
1031 #endif          
1032
1033                 if (tmp->s < 0) {
1034                         ast_log(LOG_ERROR, "Unable to create socket: %s\n", strerror(errno));
1035                         free(tmp);
1036                         return NULL;
1037                 }
1038
1039 #ifdef OLD_SANGOMA_API
1040                 /* Prepare sockaddr for binding */
1041                 memset(&tmp->sa, 0, sizeof(tmp->sa));
1042                 strncpy(tmp->sa.spkt_device, iface, sizeof(tmp->sa.spkt_device));
1043                 tmp->sa.spkt_protocol = htons(0x16);
1044                 tmp->sa.spkt_family = AF_PACKET;
1045                 if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct sockaddr))) {
1046 #else
1047                 /* Prepare sockaddr for binding */
1048                 memset(&tmp->sa, 0, sizeof(tmp->sa));
1049                 tmp->sa.sll_family = AF_WANPIPE;
1050                 tmp->sa.sll_protocol = htons(ETH_P_IP);
1051                 strncpy(tmp->sa.sll_device, iface, sizeof(tmp->sa.sll_device));
1052                 strncpy(tmp->sa.sll_card, "wanpipe1", sizeof(tmp->sa.sll_card));
1053                 tmp->sa.sll_ifindex = 0;
1054                 if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct wan_sockaddr_ll))) {
1055 #endif          
1056                 /* Bind socket to specific interface */
1057 #ifdef OLD_SANGOMA_API
1058                         ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.spkt_device, 
1059 #else
1060                         ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.sll_device, 
1061 #endif
1062                                                                                 strerror(errno));
1063                         free(tmp);
1064                         return NULL;
1065                 }
1066                 
1067                 /* Set magic send buffer size */
1068                 if (setsockopt(tmp->s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
1069                         ast_log(LOG_ERROR, "Unable to set send buffer size to %d: %s\n", sndbuf, strerror(errno));
1070                         free(tmp);
1071                         return NULL;
1072                 }
1073                 tmp->owner =  NULL;
1074                 tmp->hdr = (struct vofr_hdr *)(tmp->buf + FR_API_MESS);
1075                 tmp->ohdr = (struct vofr_hdr *)(tmp->obuf + FR_API_MESS);
1076                 tmp->dlcil = 0;
1077                 tmp->dlcih = 0;
1078                 tmp->cid = 1;
1079                 tmp->ringgothangup = 0;
1080                 strncpy(tmp->language, language, sizeof(tmp->language));
1081                 strncpy(tmp->context, context, sizeof(tmp->context));
1082                 /* User terminations are game for outgoing connections */
1083                 if (!strcasecmp(type, "user")) 
1084                         tmp->outgoing = 1;
1085                 else
1086                         tmp->outgoing = 0;
1087                 tmp->next = NULL;
1088                 /* Hang it up to be sure it's good */
1089                 send_hangup(tmp);
1090                 
1091         }
1092         return tmp;
1093 }
1094
1095 static struct ast_channel *vofr_request(char *type, int format, void *data)
1096 {
1097         int oldformat;
1098         struct vofr_pvt *p;
1099         struct ast_channel *tmp = NULL;
1100         /* We can only support G.723.1 formatted frames, but we should never
1101            be asked to support anything else anyway, since we've published
1102            our capabilities when we registered. */
1103         oldformat = format;
1104         format &= AST_FORMAT_G723_1;
1105         if (!format) {
1106                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
1107                 return NULL;
1108         }
1109         /* Search for an unowned channel */
1110         if (pthread_mutex_lock(&iflock)) {
1111                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1112                 return NULL;
1113         }
1114         p = iflist;
1115         while(p) {
1116                 if (!p->owner && p->outgoing) {
1117                         tmp = vofr_new(p, AST_STATE_DOWN);
1118                         break;
1119                 }
1120                 p = p->next;
1121         }
1122         pthread_mutex_unlock(&iflock);
1123         restart_monitor();
1124         return tmp;
1125 }
1126
1127 int load_module()
1128 {
1129         struct ast_config *cfg;
1130         struct ast_variable *v;
1131         struct vofr_pvt *tmp;
1132         cfg = ast_load(config);
1133
1134         /* We *must* have a config file otherwise stop immediately */
1135         if (!cfg) {
1136                 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
1137                 return -1;
1138         }
1139         if (pthread_mutex_lock(&iflock)) {
1140                 /* It's a little silly to lock it, but we mind as well just to be sure */
1141                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1142                 return -1;
1143         }
1144         v = ast_variable_browse(cfg, "interfaces");
1145         while(v) {
1146                 /* Create the interface list */
1147                 if (!strcasecmp(v->name, "user") ||
1148                         !strcasecmp(v->name, "network")) {
1149                                 tmp = mkif(v->name, v->value);
1150                                 if (tmp) {
1151                                         tmp->next = iflist;
1152                                         iflist = tmp;
1153                                 } else {
1154                                         ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
1155                                         ast_destroy(cfg);
1156                                         pthread_mutex_unlock(&iflock);
1157                                         unload_module();
1158                                         return -1;
1159                                 }
1160                 } else if (!strcasecmp(v->name, "context")) {
1161                         strncpy(context, v->value, sizeof(context));
1162                 } else if (!strcasecmp(v->name, "language")) {
1163                         strncpy(language, v->value, sizeof(language));
1164                 }
1165                 v = v->next;
1166         }
1167         pthread_mutex_unlock(&iflock);
1168         /* Make sure we can register our AdtranVoFR channel type */
1169         if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, vofr_request)) {
1170                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1171                 ast_destroy(cfg);
1172                 unload_module();
1173                 return -1;
1174         }
1175         ast_destroy(cfg);
1176         /* And start the monitor for the first time */
1177         restart_monitor();
1178         return 0;
1179 }
1180
1181 int unload_module()
1182 {
1183         struct vofr_pvt *p, *pl;
1184         /* First, take us out of the channel loop */
1185         ast_channel_unregister(type);
1186         if (!pthread_mutex_lock(&iflock)) {
1187                 /* Hangup all interfaces if they have an owner */
1188                 p = iflist;
1189                 while(p) {
1190                         if (p->owner)
1191                                 ast_softhangup(p->owner);
1192                         p = p->next;
1193                 }
1194                 iflist = NULL;
1195                 pthread_mutex_unlock(&iflock);
1196         } else {
1197                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1198                 return -1;
1199         }
1200         if (!pthread_mutex_lock(&monlock)) {
1201                 if (monitor_thread) {
1202                         pthread_cancel(monitor_thread);
1203                         pthread_kill(monitor_thread, SIGURG);
1204                         pthread_join(monitor_thread, NULL);
1205                 }
1206                 monitor_thread = -2;
1207                 pthread_mutex_unlock(&monlock);
1208         } else {
1209                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1210                 return -1;
1211         }
1212
1213         if (!pthread_mutex_lock(&iflock)) {
1214                 /* Destroy all the interfaces and free their memory */
1215                 p = iflist;
1216                 while(p) {
1217                         /* Close the socket, assuming it's real */
1218                         if (p->s > -1)
1219                                 close(p->s);
1220                         pl = p;
1221                         p = p->next;
1222                         /* Free associated memory */
1223                         free(pl);
1224                 }
1225                 iflist = NULL;
1226                 pthread_mutex_unlock(&iflock);
1227         } else {
1228                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1229                 return -1;
1230         }
1231                 
1232         return 0;
1233 }
1234
1235 int usecount()
1236 {
1237         int res;
1238         pthread_mutex_lock(&usecnt_lock);
1239         res = usecnt;
1240         pthread_mutex_unlock(&usecnt_lock);
1241         return res;
1242 }
1243
1244 char *description()
1245 {
1246         return desc;
1247 }
1248