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