Version 0.1.2 from FTP
[asterisk/asterisk.git] / channels / chan_vofr.c
index ea17df9..f8f171c 100755 (executable)
@@ -3,7 +3,7 @@
  *
  * Implementation of Voice over Frame Relay, Adtran Style
  * 
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
  *
  * Mark Spencer <markster@linux-support.net>
  *
@@ -28,6 +28,7 @@
 #include <arpa/inet.h>
 #include <linux/if_packet.h>
 #include <linux/if_ether.h>
+#include <sys/signal.h>
 #include "adtranvofr.h"
 
 #define G723_MAX_BUF 2048
@@ -53,9 +54,9 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
 
 /* This is the thread for the monitor which checks for input on the channels
    which are not currently in use.  */
-static pthread_t monitor_thread = -1;
+static pthread_t monitor_thread = 0;
 
-static int restart_monitor();
+static int restart_monitor(void);
 
 /* The private structures of the Adtran VoFR channels are linked for
    selecting outgoing channels */
@@ -558,6 +559,9 @@ static struct ast_frame  *vofr_read(struct ast_channel *ast)
                                fr->subclass = 0;
                                break;
                        }
+               case VOFR_SIGNAL_RING:
+                       ast->rings++;
+                       break;
                case VOFR_SIGNAL_UNKNOWN:
                        switch(vh->data[1]) {
                        case 0x1:
@@ -766,6 +770,7 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
                        if (ast_pbx_start(tmp)) {
                                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
                                ast_hangup(tmp);
+                               tmp = NULL;
                        }
                }
        } else
@@ -783,7 +788,21 @@ static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len)
                switch(pkt->data[0]) {
                case VOFR_SIGNAL_RING:
                        /* If we get a RING, we definitely want to start a new thread */
-                       vofr_new(i, AST_STATE_RING);
+                       if (!i->owner)
+                               vofr_new(i, AST_STATE_RING);
+                       else
+                               ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n");
+                       break;
+               case VOFR_SIGNAL_OFF_HOOK:
+                       /* Network termination, go off hook */
+#if 0
+                       ast_log(LOG_DEBUG, "Off hook\n");
+#endif
+                       vofr_xmit_signal(i, 0x10, 2);
+                       if (!i->owner)
+                               vofr_new(i, AST_STATE_UP);
+                       else
+                               ast_log(LOG_WARNING, "Got an offhook, but there's an owner?\n");
                        break;
                case VOFR_SIGNAL_ON_HOOK:
                        break;
@@ -822,10 +841,12 @@ static void *do_monitor(void *data)
        /* This thread monitors all the frame relay interfaces which are not yet in use
           (and thus do not have a separate thread) indefinitely */
        /* From here on out, we die whenever asked */
+#if 0
        if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
                ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
                return NULL;
        }
+#endif
        for(;;) {
                /* Don't let anybody kill us right away.  Nobody should lock the interface list
                   and wait for the monitor list, but the other way around is okay. */
@@ -860,11 +881,14 @@ static void *do_monitor(void *data)
                
                /* And from now on, we're okay to be killed, so release the monitor lock as well */
                pthread_mutex_unlock(&monlock);
+               pthread_testcancel();
                /* Wait indefinitely for something to happen */
                res = select(n + 1, &rfds, NULL, NULL, NULL);
+               pthread_testcancel();
                /* Okay, select has finished.  Let's see what happened.  */
                if (res < 0) {
-                       ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
+                       if ((errno != EAGAIN) && (errno != EINTR))
+                               ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
                        continue;
                }
                /* Alright, lock the interface list again, and let's look and see what has
@@ -896,7 +920,7 @@ static void *do_monitor(void *data)
        
 }
 
-static int restart_monitor()
+static int restart_monitor(void)
 {
        /* If we're supposed to be stopped -- stay stopped */
        if (monitor_thread == -2)
@@ -910,12 +934,16 @@ static int restart_monitor()
                ast_log(LOG_WARNING, "Cannot kill myself\n");
                return -1;
        }
-       if (monitor_thread != -1) {
+       if (monitor_thread) {
+#if 0
                pthread_cancel(monitor_thread);
+#endif
+               pthread_kill(monitor_thread, SIGURG);
 #if 0
                pthread_join(monitor_thread, NULL);
 #endif
        }
+       if (!monitor_thread)
        /* Start a new monitor */
        if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
                pthread_mutex_unlock(&monlock);
@@ -926,7 +954,7 @@ static int restart_monitor()
        return 0;
 }
 
-struct vofr_pvt *mkif(char *type, char *iface)
+static struct vofr_pvt *mkif(char *type, char *iface)
 {
        /* Make a vofr_pvt structure for this interface */
        struct vofr_pvt *tmp;
@@ -1067,8 +1095,6 @@ int load_module()
        return 0;
 }
 
-
-
 int unload_module()
 {
        struct vofr_pvt *p, *pl;
@@ -1089,8 +1115,9 @@ int unload_module()
                return -1;
        }
        if (!pthread_mutex_lock(&monlock)) {
-               if (monitor_thread > -1) {
+               if (monitor_thread) {
                        pthread_cancel(monitor_thread);
+                       pthread_kill(monitor_thread, SIGURG);
                        pthread_join(monitor_thread, NULL);
                }
                monitor_thread = -2;