SIP: Fix incoming re-invite
[lcr.git] / endpoint.cpp
index 1e66143..3c59f53 100644 (file)
@@ -1,18 +1,17 @@
 /*****************************************************************************\
 **                                                                           **
-** PBX4Linux                                                                 **
+** Linux Call Router                                                         **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
 **                                                                           **
-** The Endpoint is the link between the call and the port.                   **
+** The Endpoint is the link between the join and the port.                   **
 **                                                                           **
 \*****************************************************************************/ 
 
-#include <stdio.h>
 #include "main.h"
 
-unsigned long epoint_serial = 1; /* initial value must be 1, because 0== no epoint */
+unsigned int epoint_serial = 1; /* initial value must be 1, because 0== no epoint */
 
 class Endpoint *epoint_first = NULL;
 
@@ -20,12 +19,11 @@ class Endpoint *epoint_first = NULL;
 /*
  * find the epoint with epoint_id
  */ 
-class Endpoint *find_epoint_id(unsigned long epoint_id)
+class Endpoint *find_epoint_id(unsigned int epoint_id)
 {
        class Endpoint *epoint = epoint_first;
 
-       while(epoint)
-       {
+       while(epoint) {
 //printf("comparing: '%s' with '%s'\n", name, epoint->name);
                if (epoint->ep_serial == epoint_id)
                        return(epoint);
@@ -35,21 +33,24 @@ class Endpoint *find_epoint_id(unsigned long epoint_id)
        return(NULL);
 }
 
+int delete_endpoint(struct lcr_work *work, void *instance, int index);
 
 /*
- * endpoint constructor (link with either port or call id)
+ * endpoint constructor (link with either port or join id)
  */
-Endpoint::Endpoint(int port_id, int call_id)
+Endpoint::Endpoint(unsigned int port_id, unsigned int join_id)
 {
        class Port *port;
        class Endpoint **epointpointer;
        int earlyb = 0;
 
        /* epoint structure */
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Allocating enpoint %d and connecting it with:%s%s\n", epoint_serial, epoint_serial, (port_id)?" ioport":"", (call_id)?" call":"");
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Allocating enpoint %d and connecting it with:%s%s\n", epoint_serial, epoint_serial, (port_id)?" ioport":"", (join_id)?" join":"");
 
         ep_portlist = NULL;
        ep_app = NULL;
+       memset(&ep_delete, 0, sizeof(ep_delete));
+       add_work(&ep_delete, delete_endpoint, this, 0);
        ep_use = 1;
 
        /* add endpoint to chain */
@@ -62,22 +63,21 @@ Endpoint::Endpoint(int port_id, int call_id)
        /* serial */
        ep_serial = epoint_serial++;
 
-       /* link to call or port */
-       if (port_id)
-       {
+       /* link to join or port */
+       if (port_id) {
                port = find_port_id(port_id);
-               if (port)
-               {
-                       if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1)
-                               earlyb = ((class PmISDN *)port)->p_m_mISDNport->is_earlyb;
+               if (port) {
+#ifdef WITH_MISDN
+                       if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
+                               earlyb = ((class PmISDN *)port)->p_m_mISDNport->earlyb;
+#else
+                               earlyb = 0;
+#endif
                        if (!portlist_new(port_id, port->p_type, earlyb))
-                       {
-                               PERROR("no mem for portlist, exitting...\n");
-                               exit(-1);
-                       }
+                               FATAL("No memory for portlist.\n");
                }
        }
-       ep_call_id = call_id;
+       ep_join_id = join_id;
 
        ep_park = 0;
        ep_park_len = 0;
@@ -101,31 +101,27 @@ Endpoint::~Endpoint(void)
                delete ep_app;
        
        /* free relations */
-       if (ep_call_id)
-       {
-               PERROR("warning: still relation to call.\n");
+       if (ep_join_id) {
+               PERROR("warning: still relation to join.\n");
        }
 
        /* free portlist */
        portlist = ep_portlist;
-       while(portlist)
-       {
-               if (portlist->port_id)
-               {
-                       PERROR("warning: still relation to port (portlist list)\n");
+       while(portlist) {
+               if (portlist->port_id) {
+                       PERROR("Endpoint(%d) warning: still relation to port %d (portlist list)\n", ep_serial, portlist->port_id);
                }
                mtemp = portlist;
                portlist = portlist->next;
                memset(mtemp, 0, sizeof(struct port_list));
-               free(mtemp);
+               FREE(mtemp, sizeof(struct port_list));
                ememuse--;
        }
 
        /* detach */
        temp =epoint_first;
        tempp = &epoint_first;
-       while(temp)
-       {
+       while(temp) {
                if (temp == this)
                        break;
 
@@ -133,32 +129,25 @@ Endpoint::~Endpoint(void)
                temp = temp->next;
        }
        if (temp == 0)
-       {
-               PERROR("error: endpoint not in endpoint's list, exitting.\n");
-               exit(-1);
-       }
+               FATAL("Endpoint not in Endpoint's list.\n");
        *tempp = next;
 
+       del_work(&ep_delete);
+
        /* free */
        PDEBUG(DEBUG_EPOINT, "removed endpoint %d.\n", ep_serial);
 }
 
 /* create new portlist relation
  */
-struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type, int earlyb)
+struct port_list *Endpoint::portlist_new(unsigned int port_id, int port_type, int earlyb)
 {
        struct port_list *portlist, **portlistpointer;
 
        /* portlist structure */
-       portlist = (struct port_list *)calloc(1, sizeof(struct port_list));
-       if (!portlist)
-       {
-               PERROR("no mem for allocating port_list\n");
-               return(0);
-       }
+       portlist = (struct port_list *)MALLOC(sizeof(struct port_list));
        ememuse++;
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocating port_list.\n", ep_serial);
-       memset(portlist, 0, sizeof(struct port_list));
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocating port_list, attaching to port %d\n", ep_serial, port_id);
 
        /* add port_list to chain */
        portlist->next = NULL;
@@ -167,7 +156,7 @@ struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type, i
                portlistpointer = &((*portlistpointer)->next);
        *portlistpointer = portlist;
 
-       /* link to call or port */
+       /* link to join or port */
        portlist->port_id = port_id;
        portlist->port_type = port_type;
        portlist->early_b = earlyb;
@@ -184,42 +173,32 @@ void Endpoint::free_portlist(struct port_list *portlist)
 
        temp = ep_portlist;
        tempp = &ep_portlist;
-       while(temp)
-       {
+       while(temp) {
                if (temp == portlist)
                        break;
 
                tempp = &temp->next;
                temp = temp->next;
        }
-       if (temp == 0)
-       {
-               PERROR("port_list not in endpoint's list, exitting.\n");
-               exit(-1);
-       }
+       if (!temp)
+               FATAL("port_list not in Endpoint's list.\n");
        /* detach */
        *tempp=portlist->next;
 
        /* free */
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removed port_list from endpoint\n", ep_serial);
-       memset(portlist, 0, sizeof(struct port_list));
-       free(portlist);
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removed port %d from port_list of endpoint\n", ep_serial, portlist->port_id);
+       FREE(portlist, sizeof(struct port_list));
        ememuse--;
 }
 
 
-/* handler for endpoint
- */
-int Endpoint::handler(void)
+int delete_endpoint(struct lcr_work *work, void *instance, int index)
 {
-       if (ep_use <= 0)
-       {
-               delete this;
-               return(-1);
-       }
+       class Endpoint *ep = (class Endpoint *)instance;
 
-       /* call application handler */
-       if (ep_app)
-               return(ep_app->handler());
-       return(0);
+       if (ep->ep_use <= 0)
+               delete ep;
+
+       return 0;
 }
+