1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppBridge implements direct bridge between interfaces **
10 \*****************************************************************************/
15 class EndpointAppBridge *appbridge_first = NULL;
18 * EndpointAppBridge constructor
20 EndpointAppBridge::EndpointAppBridge(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin, EAPP_TYPE_BRIDGE)
22 class EndpointAppBridge **apppointer;
24 /* add application to chain */
26 apppointer = &appbridge_first;
28 apppointer = &((*apppointer)->next);
31 PDEBUG(DEBUG_EPOINT, "Bridge endpoint created\n");
35 * EpointAppBridge destructor
37 EndpointAppBridge::~EndpointAppBridge(void)
39 class EndpointAppBridge *temp, **tempp;
42 temp =appbridge_first;
43 tempp = &appbridge_first;
52 FATAL("Endpoint not in endpoint's list.\n");
55 PDEBUG(DEBUG_EPOINT, "Bridge endpoint destroyed\n");
60 * trace header for application
62 void EndpointAppBridge::trace_header(const char *name, int direction)
66 char msgtext[sizeof(_trace.name)];
70 /* init trace with given values */
73 "", //numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
74 "", // e_dialinginfo.id,
77 ea_endpoint->ep_serial,
81 /* port MESSAGE_SETUP */
82 void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type, union parameter *param)
84 struct interface *interface_in = interface_first;
85 struct interface *interface_out = interface_first;
86 struct port_settings port_settings;
87 class Port *port = NULL;
88 struct lcr_msg *message;
89 unsigned int bridge_id;
90 unsigned int source_port_id = portlist->port_id;
94 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from='%s' to='%s'\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
96 if (!ea_endpoint->ep_portlist) {
97 PERROR("Endpoint has no port in portlist\n");
100 if (ea_endpoint->ep_portlist->next) {
101 PDEBUG(DEBUG_EPOINT, "Endpoint already received setup, ignoring.\n");
105 while (interface_in) {
106 if (!strcmp(interface_in->name, param->setup.callerinfo.interface))
108 interface_in = interface_in->next;
111 PERROR("Cannot find source interface %s.\n", param->setup.callerinfo.interface);
113 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
114 message->param.disconnectinfo.cause = cause;
115 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
116 message_put(message);
117 ea_endpoint->free_portlist(portlist);
119 /* destroy endpoint */
120 ea_endpoint->ep_use = 0;
121 trigger_work(&ea_endpoint->ep_delete);
125 while (interface_out) {
126 if (!strcmp(interface_out->name, interface_in->bridge_if))
128 interface_out = interface_out->next;
130 if (!interface_out) {
131 PERROR("Cannot find destination interface %s.\n", interface_in->bridge_if);
136 /* create port for interface */
137 SPRINT(portname, "%s-%d-out", interface_out->name, 0);
138 memset(&port_settings, 0, sizeof(port_settings));
140 if (interface_out->remote) {
141 struct admin_list *admin;
144 if (admin->remote_name[0] && !strcmp(admin->remote_name, interface_out->remote_app))
149 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
150 add_trace("application", NULL, "%s", interface_out->remote_app);
154 port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface_out, admin->sock);
158 if (interface_out->sip) {
159 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface_out);
163 if (interface_out->gsm_bs) {
164 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface_out);
168 if (interface_out->gsm_ms) {
169 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface_out);
173 char *ifname = interface_out->name;
175 struct mISDNport *mISDNport;
178 int mode = B_MODE_TRANSPARENT;
180 /* hunt for mISDNport and create Port */
181 mISDNport = hunt_port(ifname, &channel);
183 trace_header("INTERFACE (busy)", DIRECTION_NONE);
184 add_trace("interface", NULL, "%s", ifname);
190 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
193 port = ss5_hunt_line(mISDNport);
196 earlyb = mISDNport->earlyb;
197 #ifdef ISDN_P_FXS_POTS
199 port = new Pfxs(PORT_TYPE_POTS_FXS_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, mode);
202 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
204 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
205 add_trace("interface", NULL, "%s", ifname);
212 FATAL("Remote interface, but not supported???\n");
213 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface_out->is_earlyb == IS_YES);
215 FATAL("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
217 message_forward(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, param);
219 /* apply bridge to interfaces */
220 /* FIXME: use mISDN bridge for mISDN ports */
221 bridge_id = join_serial++;
222 message = message_create(ea_endpoint->ep_serial, source_port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
223 message->param.bridge_id = bridge_id;
224 message_put(message);
225 message = message_create(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, MESSAGE_BRIDGE);
226 message->param.bridge_id = bridge_id;
227 message_put(message);
230 /* port MESSAGE_RELEASE */
231 void EndpointAppBridge::port_release(struct port_list *portlist, int message_type, union parameter *param)
233 struct port_list *remote;
235 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received release from port\n");
237 if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
239 if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
240 remote = ea_endpoint->ep_portlist->next;
242 remote = ea_endpoint->ep_portlist;
243 /* forward release */
244 message_forward(ea_endpoint->ep_serial, remote->port_id, EPOINT_TO_PORT, param);
246 /* remove relations to in and out port */
247 ea_endpoint->free_portlist(portlist);
248 ea_endpoint->free_portlist(remote);
251 /* destroy endpoint */
252 ea_endpoint->ep_use = 0;
253 trigger_work(&ea_endpoint->ep_delete);
256 /* port other messages */
257 void EndpointAppBridge::port_other(struct port_list *portlist, int message_type, union parameter *param)
261 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received message %d from port\n", message_type);
263 if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
265 if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
266 remote = ea_endpoint->ep_portlist->next->port_id;
268 remote = ea_endpoint->ep_portlist->port_id;
269 /* forward release */
270 message_forward(ea_endpoint->ep_serial, remote, EPOINT_TO_PORT, param);
273 /* port sends message to the endpoint
275 void EndpointAppBridge::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
277 struct port_list *portlist;
279 portlist = ea_endpoint->ep_portlist;
281 if (port_id == portlist->port_id)
283 portlist = portlist->next;
286 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
290 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
291 switch(message_type) {
292 /* PORT sends SETUP message */
294 port_setup(portlist, message_type, param);
297 /* PORT sends RELEASE message */
298 case MESSAGE_RELEASE:
299 port_release(portlist, message_type, param);
303 port_other(portlist, message_type, param);
306 /* Note: this endpoint may be destroyed, so we MUST return */