3f67f41596515a7b19aec2d89025e0e9e17c2f14
[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(int port_id, int call_id)
43 {
44         class Port *port;
45         class Endpoint **epointpointer;
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":"", (call_id)?" call":"");
49
50         ep_portlist = NULL;
51         ep_app = NULL;
52         ep_use = 1;
53
54         /* add endpoint to chain */
55         next = NULL;
56         epointpointer = &epoint_first;
57         while(*epointpointer)
58                 epointpointer = &((*epointpointer)->next);
59         *epointpointer = this;
60
61         /* serial */
62         ep_serial = epoint_serial++;
63
64         /* link to call or port */
65         if (port_id)
66         {
67                 port = find_port_id(port_id);
68                 if (port)
69                 if (!portlist_new(port_id, port->p_type))
70                 {
71                         PERROR("no mem for portlist, exitting...\n");
72                         exit(-1);
73                 }
74         }
75         ep_call_id = call_id;
76
77         ep_park = 0;
78         ep_park_len = 0;
79
80         classuse++;
81 }
82
83
84 /*
85  * endpoint destructor
86  */
87 Endpoint::~Endpoint(void)
88 {
89         class Endpoint *temp, **tempp;
90         struct port_list *portlist, *mtemp;
91
92         classuse--;
93
94         /* remote application */
95         if (ep_app)
96                 delete ep_app;
97         
98         /* free relations */
99         if (ep_call_id)
100         {
101                 PERROR("warning: still relation to call.\n");
102         }
103
104         /* free portlist */
105         portlist = ep_portlist;
106         while(portlist)
107         {
108                 if (portlist->port_id)
109                 {
110                         PERROR("warning: still relation to port (portlist list)\n");
111                 }
112                 mtemp = portlist;
113                 portlist = portlist->next;
114                 memset(mtemp, 0, sizeof(struct port_list));
115                 free(mtemp);
116                 ememuse--;
117         }
118
119         /* detach */
120         temp =epoint_first;
121         tempp = &epoint_first;
122         while(temp)
123         {
124                 if (temp == this)
125                         break;
126
127                 tempp = &temp->next;
128                 temp = temp->next;
129         }
130         if (temp == 0)
131         {
132                 PERROR("error: endpoint not in endpoint's list, exitting.\n");
133                 exit(-1);
134         }
135         *tempp = next;
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 long port_id, int port_type)
144 {
145         struct port_list *portlist, **portlistpointer;
146
147         /* portlist structure */
148         portlist = (struct port_list *)calloc(1, sizeof(struct port_list));
149         if (!portlist)
150         {
151                 PERROR("no mem for allocating port_list\n");
152                 return(0);
153         }
154         ememuse++;
155         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocating port_list.\n", ep_serial);
156         memset(portlist, 0, sizeof(struct port_list));
157
158         /* add port_list to chain */
159         portlist->next = NULL;
160         portlistpointer = &ep_portlist;
161         while(*portlistpointer)
162                 portlistpointer = &((*portlistpointer)->next);
163         *portlistpointer = portlist;
164
165         /* link to call or port */
166         portlist->port_id = port_id;
167         portlist->port_type = port_type;
168
169         return(portlist);
170 }
171
172
173 /* free portlist relation
174  */
175 void Endpoint::free_portlist(struct port_list *portlist)
176 {
177         struct port_list *temp, **tempp;
178
179         temp = ep_portlist;
180         tempp = &ep_portlist;
181         while(temp)
182         {
183                 if (temp == portlist)
184                         break;
185
186                 tempp = &temp->next;
187                 temp = temp->next;
188         }
189         if (temp == 0)
190         {
191                 PERROR("port_list not in endpoint's list, exitting.\n");
192                 exit(-1);
193         }
194         /* detach */
195         *tempp=portlist->next;
196
197         /* free */
198         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removed port_list from endpoint\n", ep_serial);
199         memset(portlist, 0, sizeof(struct port_list));
200         free(portlist);
201         ememuse--;
202 }
203
204
205 /* handler for endpoint
206  */
207 int Endpoint::handler(void)
208 {
209         if (ep_use <= 0)
210         {
211                 delete this;
212                 return(-1);
213         }
214
215         /* call application handler */
216         if (ep_app)
217                 return(ep_app->handler());
218         return(0);
219 }