SIP: Fix incoming re-invite
[lcr.git] / endpoint.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** The Endpoint is the link between the join and the port.                   **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 unsigned int epoint_serial = 1; /* initial value must be 1, because 0== no epoint */
15
16 class Endpoint *epoint_first = NULL;
17
18
19 /*
20  * find the epoint with epoint_id
21  */ 
22 class Endpoint *find_epoint_id(unsigned int epoint_id)
23 {
24         class Endpoint *epoint = epoint_first;
25
26         while(epoint) {
27 //printf("comparing: '%s' with '%s'\n", name, epoint->name);
28                 if (epoint->ep_serial == epoint_id)
29                         return(epoint);
30                 epoint = epoint->next;
31         }
32
33         return(NULL);
34 }
35
36 int delete_endpoint(struct lcr_work *work, void *instance, int index);
37
38 /*
39  * endpoint constructor (link with either port or join id)
40  */
41 Endpoint::Endpoint(unsigned int port_id, unsigned int join_id)
42 {
43         class Port *port;
44         class Endpoint **epointpointer;
45         int earlyb = 0;
46
47         /* epoint structure */
48         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":"");
49
50         ep_portlist = NULL;
51         ep_app = NULL;
52         memset(&ep_delete, 0, sizeof(ep_delete));
53         add_work(&ep_delete, delete_endpoint, this, 0);
54         ep_use = 1;
55
56         /* add endpoint to chain */
57         next = NULL;
58         epointpointer = &epoint_first;
59         while(*epointpointer)
60                 epointpointer = &((*epointpointer)->next);
61         *epointpointer = this;
62
63         /* serial */
64         ep_serial = epoint_serial++;
65
66         /* link to join or port */
67         if (port_id) {
68                 port = find_port_id(port_id);
69                 if (port) {
70 #ifdef WITH_MISDN
71                         if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
72                                 earlyb = ((class PmISDN *)port)->p_m_mISDNport->earlyb;
73 #else
74                                 earlyb = 0;
75 #endif
76                         if (!portlist_new(port_id, port->p_type, earlyb))
77                                 FATAL("No memory for portlist.\n");
78                 }
79         }
80         ep_join_id = join_id;
81
82         ep_park = 0;
83         ep_park_len = 0;
84
85         classuse++;
86 }
87
88
89 /*
90  * endpoint destructor
91  */
92 Endpoint::~Endpoint(void)
93 {
94         class Endpoint *temp, **tempp;
95         struct port_list *portlist, *mtemp;
96
97         classuse--;
98
99         /* remote application */
100         if (ep_app)
101                 delete ep_app;
102         
103         /* free relations */
104         if (ep_join_id) {
105                 PERROR("warning: still relation to join.\n");
106         }
107
108         /* free portlist */
109         portlist = ep_portlist;
110         while(portlist) {
111                 if (portlist->port_id) {
112                         PERROR("Endpoint(%d) warning: still relation to port %d (portlist list)\n", ep_serial, portlist->port_id);
113                 }
114                 mtemp = portlist;
115                 portlist = portlist->next;
116                 memset(mtemp, 0, sizeof(struct port_list));
117                 FREE(mtemp, sizeof(struct port_list));
118                 ememuse--;
119         }
120
121         /* detach */
122         temp =epoint_first;
123         tempp = &epoint_first;
124         while(temp) {
125                 if (temp == this)
126                         break;
127
128                 tempp = &temp->next;
129                 temp = temp->next;
130         }
131         if (temp == 0)
132                 FATAL("Endpoint not in Endpoint's list.\n");
133         *tempp = next;
134
135         del_work(&ep_delete);
136
137         /* free */
138         PDEBUG(DEBUG_EPOINT, "removed endpoint %d.\n", ep_serial);
139 }
140
141 /* create new portlist relation
142  */
143 struct port_list *Endpoint::portlist_new(unsigned int port_id, int port_type, int earlyb)
144 {
145         struct port_list *portlist, **portlistpointer;
146
147         /* portlist structure */
148         portlist = (struct port_list *)MALLOC(sizeof(struct port_list));
149         ememuse++;
150         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocating port_list, attaching to port %d\n", ep_serial, port_id);
151
152         /* add port_list to chain */
153         portlist->next = NULL;
154         portlistpointer = &ep_portlist;
155         while(*portlistpointer)
156                 portlistpointer = &((*portlistpointer)->next);
157         *portlistpointer = portlist;
158
159         /* link to join or port */
160         portlist->port_id = port_id;
161         portlist->port_type = port_type;
162         portlist->early_b = earlyb;
163
164         return(portlist);
165 }
166
167
168 /* free portlist relation
169  */
170 void Endpoint::free_portlist(struct port_list *portlist)
171 {
172         struct port_list *temp, **tempp;
173
174         temp = ep_portlist;
175         tempp = &ep_portlist;
176         while(temp) {
177                 if (temp == portlist)
178                         break;
179
180                 tempp = &temp->next;
181                 temp = temp->next;
182         }
183         if (!temp)
184                 FATAL("port_list not in Endpoint's list.\n");
185         /* detach */
186         *tempp=portlist->next;
187
188         /* free */
189         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removed port %d from port_list of endpoint\n", ep_serial, portlist->port_id);
190         FREE(portlist, sizeof(struct port_list));
191         ememuse--;
192 }
193
194
195 int delete_endpoint(struct lcr_work *work, void *instance, int index)
196 {
197         class Endpoint *ep = (class Endpoint *)instance;
198
199         if (ep->ep_use <= 0)
200                 delete ep;
201
202         return 0;
203 }
204