1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointApp represents the application for the Endpoint. **
10 \*****************************************************************************/
15 * EndpointApp constructor
17 EndpointApp::EndpointApp(class Endpoint *epoint, int origin, int type)
27 EndpointApp::~EndpointApp(void)
32 /* mini application for test purpose only */
34 void EndpointApp::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
36 PDEBUG(DEBUG_EPOINT, "%s: Spare function.\n", __FUNCTION__);
39 void EndpointApp::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
41 PDEBUG(DEBUG_EPOINT, "%s: Spare function.\n", __FUNCTION__);
45 /* create endpoint app */
46 class EndpointApp *new_endpointapp(class Endpoint *epoint, int origin, int type)
48 class EndpointApp *app = NULL;
52 app = new EndpointAppPBX(epoint, origin);
54 case EAPP_TYPE_BRIDGE:
55 app = new EndpointAppBridge(epoint, origin);
60 FATAL("Failed to create endpoint APP (type %d)\n", type);
62 epoint->ep_app_type = type;
70 * hunts an mISDNport that is available for an outgoing call
71 * if no ifname was given, any interface that is not an extension
74 struct mISDNport *EndpointApp::hunt_port(char *ifname, int *channel)
76 struct interface *interface;
77 struct interface_port *ifport, *ifport_start;
78 struct select_channel *selchannel;
79 struct mISDNport *mISDNport;
81 int there_is_an_external = 0;
83 interface = interface_first;
85 /* first find the given interface or, if not given, one with no extension */
88 if (!there_is_an_external && !(ifname && ifname[0])) {
89 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
90 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
96 /* check for given interface */
97 if (ifname && ifname[0]) {
98 if (!strcasecmp(interface->name, ifname)) {
99 /* found explicit interface */
100 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
101 add_trace("interface", NULL, "%s", ifname);
107 if (interface->external) {
108 there_is_an_external = 1;
109 /* found non extension */
110 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
111 add_trace("interface", NULL, "%s", interface->name);
117 interface = interface->next;
121 /* see if interface has ports */
122 if (!interface->ifport) {
124 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
125 add_trace("interface", NULL, "%s", interface->name);
127 interface = interface->next;
131 /* select port by algorithm */
132 ifport_start = interface->ifport;
134 if (interface->hunt == HUNT_ROUNDROBIN) {
135 while(ifport_start->next && index<interface->hunt_next) {
136 ifport_start = ifport_start->next;
139 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
140 add_trace("port", NULL, "%d", ifport_start->portnum);
141 add_trace("position", NULL, "%d", index);
146 ifport = ifport_start;
149 /* see if port is available */
150 if (!ifport->mISDNport) {
151 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
152 add_trace("port", NULL, "%d", ifport->portnum);
153 add_trace("position", NULL, "%d", index);
157 mISDNport = ifport->mISDNport;
159 /* see if port is administratively blocked */
161 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
162 add_trace("port", NULL, "%d", ifport->portnum);
163 add_trace("position", NULL, "%d", index);
168 /* see if link is up on PTP*/
169 if (mISDNport->l2hold && mISDNport->l2link<1) {
170 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
171 add_trace("port", NULL, "%d", ifport->portnum);
172 add_trace("position", NULL, "%d", index);
177 /* check for channel form selection list */
180 if (mISDNport->ss5) {
182 port = ss5_hunt_line(mISDNport);
184 *channel = port->p_m_b_channel;
185 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
186 add_trace("port", NULL, "%d", ifport->portnum);
187 add_trace("position", NULL, "%d", index);
188 add_trace("channel", NULL, "%d", *channel);
194 selchannel = ifport->out_channel;
196 switch(selchannel->channel) {
197 case CHANNEL_FREE: /* free channel */
198 if (mISDNport->b_reserved >= mISDNport->b_num)
199 break; /* all channel in use or reserverd */
202 while(i < mISDNport->b_num) {
203 if (mISDNport->b_port[i] == NULL) {
204 *channel = i+1+(i>=15);
205 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
206 add_trace("port", NULL, "%d", ifport->portnum);
207 add_trace("position", NULL, "%d", index);
208 add_trace("channel", NULL, "%d", *channel);
216 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
217 add_trace("port", NULL, "%d", ifport->portnum);
218 add_trace("position", NULL, "%d", index);
222 case CHANNEL_ANY: /* don't ask for channel */
223 if (mISDNport->b_reserved >= mISDNport->b_num) {
224 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
225 add_trace("port", NULL, "%d", ifport->portnum);
226 add_trace("position", NULL, "%d", index);
227 add_trace("total", NULL, "%d", mISDNport->b_num);
228 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
230 break; /* all channel in use or reserverd */
232 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
233 add_trace("port", NULL, "%d", ifport->portnum);
234 add_trace("position", NULL, "%d", index);
236 *channel = CHANNEL_ANY;
239 case CHANNEL_NO: /* call waiting */
240 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
241 add_trace("port", NULL, "%d", ifport->portnum);
242 add_trace("position", NULL, "%d", index);
244 *channel = CHANNEL_NO;
248 if (selchannel->channel<1 || selchannel->channel==16) {
249 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
250 add_trace("port", NULL, "%d", ifport->portnum);
251 add_trace("position", NULL, "%d", index);
252 add_trace("channel", NULL, "%d", selchannel->channel);
254 break; /* invalid channels */
256 i = selchannel->channel-1-(selchannel->channel>=17);
257 if (i >= mISDNport->b_num) {
258 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
259 add_trace("port", NULL, "%d", ifport->portnum);
260 add_trace("position", NULL, "%d", index);
261 add_trace("channel", NULL, "%d", selchannel->channel);
262 add_trace("channels", NULL, "%d", mISDNport->b_num);
264 break; /* channel not in port */
266 if (mISDNport->b_port[i] == NULL) {
267 *channel = selchannel->channel;
268 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
269 add_trace("port", NULL, "%d", ifport->portnum);
270 add_trace("position", NULL, "%d", index);
271 add_trace("channel", NULL, "%d", *channel);
278 break; /* found channel */
279 selchannel = selchannel->next;
283 /* if channel was found, return mISDNport and channel */
285 /* setting next port to start next time */
286 if (interface->hunt == HUNT_ROUNDROBIN) {
290 interface->hunt_next = index;
296 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
297 add_trace("port", NULL, "%d", ifport->portnum);
298 add_trace("position", NULL, "%d", index);
302 /* go next port, until all ports are checked */
304 ifport = ifport->next;
307 ifport = interface->ifport;
309 if (ifport != ifport_start)
313 interface = interface->next;
317 return(NULL); /* no port found */
321 /* hunts for the given interface
322 * it does not need to have an mISDNport instance */
323 struct interface *EndpointApp::hunt_interface(char *ifname)
325 struct interface *interface;
326 int there_is_an_external = 0;
328 interface = interface_first;
330 /* first find the given interface or, if not given, one with no extension */
333 if (!there_is_an_external && !(ifname && ifname[0])) {
334 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
335 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
341 /* check for given interface */
342 if (ifname && ifname[0]) {
343 if (!strcasecmp(interface->name, ifname)) {
344 /* found explicit interface */
345 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
346 add_trace("interface", NULL, "%s", ifname);
351 if (interface->external) {
352 there_is_an_external = 1;
353 /* found non extension */
354 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
355 add_trace("interface", NULL, "%s", interface->name);
361 interface = interface->next;
368 /* must be overloaded by specific app */
369 void EndpointApp::trace_header(const char *name, int direction)