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 /* hunts for the given interface
82 * it does not need to have an mISDNport instance */
83 struct interface *EndpointAppBridge::hunt_interface(char *ifname)
85 struct interface *interface;
86 int there_is_an_external = 0;
88 interface = interface_first;
90 /* first find the given interface or, if not given, one with no extension */
93 if (!there_is_an_external && !(ifname && ifname[0])) {
94 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
95 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
101 /* check for given interface */
102 if (ifname && ifname[0]) {
103 if (!strcasecmp(interface->name, ifname)) {
104 /* found explicit interface */
105 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
106 add_trace("interface", NULL, "%s", ifname);
112 if (interface->external) {
113 there_is_an_external = 1;
114 /* found non extension */
115 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
116 add_trace("interface", NULL, "%s", interface->name);
122 interface = interface->next;
130 /* port MESSAGE_SETUP */
131 void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type, union parameter *param)
133 struct interface *interface_in = interface_first;
134 struct interface *interface_out = interface_first;
135 struct port_settings port_settings;
136 class Port *port = NULL;
137 struct lcr_msg *message;
138 unsigned int bridge_id;
139 unsigned int source_port_id = portlist->port_id;
142 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);
144 if (!ea_endpoint->ep_portlist) {
145 PERROR("Endpoint has no port in portlist\n");
148 if (ea_endpoint->ep_portlist->next) {
149 PDEBUG(DEBUG_EPOINT, "Endpoint already received setup, ignoring.\n");
153 while (interface_in) {
154 if (!strcmp(interface_in->name, param->setup.callerinfo.interface))
156 interface_in = interface_in->next;
160 PERROR("Cannot find source interface %s.\n", param->setup.callerinfo.interface);
161 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
162 message->param.disconnectinfo.cause = 47;
163 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
164 message_put(message);
166 /* destroy endpoint */
167 ea_endpoint->ep_use = 0;
168 trigger_work(&ea_endpoint->ep_delete);
172 while (interface_out) {
173 if (!strcmp(interface_out->name, interface_in->bridge_if))
175 interface_out = interface_out->next;
177 if (!interface_out) {
178 PERROR("Cannot find destination interface %s.\n", interface_in->bridge_if);
183 /* create port for interface */
184 SPRINT(portname, "%s-%d-out", interface_out->name, 0);
185 memset(&port_settings, 0, sizeof(port_settings));
187 if (interface_out->sip) {
188 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface_out);
192 if (interface_out->gsm_bs) {
193 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface_out);
197 if (interface_out->gsm_ms) {
198 port = new Pgsm_bs(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface_out);
202 FATAL("Remote interface, but not supported???\n");
203 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface_out->is_earlyb == IS_YES);
205 FATAL("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
207 message_forward(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, param);
209 /* apply bridge to interfaces */
210 /* FIXME: use mISDN bridge for mISDN ports */
211 bridge_id = join_serial++;
212 message = message_create(ea_endpoint->ep_serial, source_port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
213 message->param.bridge_id = bridge_id;
214 message_put(message);
215 message = message_create(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, MESSAGE_BRIDGE);
216 message->param.bridge_id = bridge_id;
217 message_put(message);
220 /* port MESSAGE_RELEASE */
221 void EndpointAppBridge::port_release(struct port_list *portlist, int message_type, union parameter *param)
225 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received release from port\n");
227 if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
229 if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
230 remote = ea_endpoint->ep_portlist->next->port_id;
232 remote = ea_endpoint->ep_portlist->port_id;
233 /* forward release */
234 message_forward(ea_endpoint->ep_serial, remote, EPOINT_TO_PORT, param);
237 /* destroy endpoint */
238 ea_endpoint->ep_use = 0;
239 trigger_work(&ea_endpoint->ep_delete);
242 /* port other messages */
243 void EndpointAppBridge::port_other(struct port_list *portlist, int message_type, union parameter *param)
247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received message %d from port\n", message_type);
249 if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
251 if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
252 remote = ea_endpoint->ep_portlist->next->port_id;
254 remote = ea_endpoint->ep_portlist->port_id;
255 /* forward release */
256 message_forward(ea_endpoint->ep_serial, remote, EPOINT_TO_PORT, param);
259 /* port sends message to the endpoint
261 void EndpointAppBridge::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
263 struct port_list *portlist;
265 portlist = ea_endpoint->ep_portlist;
267 if (port_id == portlist->port_id)
269 portlist = portlist->next;
272 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);
276 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
277 switch(message_type) {
278 /* PORT sends SETUP message */
280 port_setup(portlist, message_type, param);
283 /* PORT sends RELEASE message */
284 case MESSAGE_RELEASE:
285 port_release(portlist, message_type, param);
289 port_other(portlist, message_type, param);
292 /* Note: this endpoint may be destroyed, so we MUST return */