unsigned int port_serial = 1; /* must be 1, because 0== no port */
+struct port_bridge *p_bridge_first;
+
+static void remove_bridge(struct port_bridge *bridge, class Port *port);
/* free epointlist relation
*/
{
class Port *temp, **tempp;
- PDEBUG(DEBUG_PORT, "new port of type %d, name '%s'\n", type, portname);
-
/* initialize object */
if (settings)
memcpy(&p_settings, settings, sizeof(struct port_settings));
memset(&p_redirinfo, 0, sizeof(p_redirinfo));
memset(&p_capainfo, 0, sizeof(p_capainfo));
p_echotest = 0;
+ p_bridge = 0;
/* call recording */
p_record = NULL;
*tempp = this;
classuse++;
+
+ PDEBUG(DEBUG_PORT, "new port (%d) of type 0x%x, name '%s'\n", p_serial, type, portname);
}
class Port *temp, **tempp;
struct lcr_msg *message;
+ PDEBUG(DEBUG_PORT, "removing port (%d) of type 0x%x, name '%s'\n", p_serial, p_type, p_name);
+
+ if (p_bridge) {
+ PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id);
+ remove_bridge(p_bridge, this);
+ }
+
if (p_record)
close_record(0, 0);
classuse--;
- PDEBUG(DEBUG_PORT, "removing port of type %d, name '%s'\n", p_type, p_name);
-
/* disconnect port from endpoint */
while(p_epointlist) {
/* send disconnect */
if (name == NULL)
name = "";
- if (!dir && !dir[0])
+ if (!dir || !dir[0])
dir = options.tones_dir; /* just in case we have no PmISDN instance */
/* no counter, no eof, normal speed */
}
-/* endpoint sends messages to the port
- * this is called by the message_epoint inherited by child classes
- * therefor a return=1 means: stop, no more processing
+/* Endpoint sends messages to the port
+ * This is called by the message_epoint, inherited by child classes.
+ * Therefor a return 1 means: "already handled here"
*/
//extern struct lcr_msg *dddebug;
int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
{
/* check if we got audio data from one remote port */
switch(message_id) {
- case MESSAGE_TONE: /* play tone */
- PDEBUG(DEBUG_PORT, "PORT(%s) isdn port with (caller id %s) setting tone '%s' dir '%s'\n", p_name, p_callerinfo.id, param->tone.name, param->tone.dir);
+ case MESSAGE_TONE: /* play tone */
+ PDEBUG(DEBUG_PORT, "PORT(%s) setting tone '%s' dir '%s'\n", p_name, param->tone.name, param->tone.dir);
set_tone(param->tone.dir,param->tone.name);
- return(1);
+ return 1;
- case MESSAGE_VBOX_TONE: /* play tone of answering machine */
+ case MESSAGE_VBOX_TONE: /* play tone of answering machine */
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine tone '%s' '%s'\n", p_name, param->tone.dir, param->tone.name);
set_vbox_tone(param->tone.dir, param->tone.name);
- return(1);
+ return 1;
- case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
+ case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine file to play '%s' (offset %d seconds)\n", p_name, param->play.file, param->play.offset);
set_vbox_play(param->play.file, param->play.offset);
- return(1);
+ return 1;
- case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
+ case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine playback speed %d (times)\n", p_name, param->speed);
set_vbox_speed(param->speed);
- return(1);
+ return 1;
+ case MESSAGE_BRIDGE: /* create / join / leave / destroy bridge */
+ PDEBUG(DEBUG_PORT, "PORT(%s) bridging to id %d\n", p_name, param->bridge_id);
+ bridge(param->bridge_id);
+ return 1;
}
- return(0);
+ return 0;
}
{
}
+
+/*
+ * bridge handling
+ */
+
+static void remove_bridge(struct port_bridge *bridge, class Port *port)
+{
+ struct port_bridge **temp = &p_bridge_first;
+ while (*temp) {
+ if (*temp == bridge) {
+ struct port_bridge_member **memberp = &bridge->first, *member;
+
+ /* loop until we are found */
+ while(*memberp) {
+ if ((*memberp)->port == port) {
+ member = *memberp;
+ *memberp = member->next;
+ FREE(member, sizeof(struct port_bridge_member));
+ memuse--;
+ break;
+ }
+ memberp = &((*memberp)->next);
+ }
+ /* if bridge is empty, remove it */
+ if (bridge->first == NULL) {
+ PDEBUG(DEBUG_PORT, "Remove bridge %u\n", bridge->bridge_id);
+ *temp = bridge->next;
+ FREE(bridge, sizeof(struct port_bridge));
+ memuse--;
+ }
+ return;
+ }
+ temp = &((*temp)->next);
+ }
+ PERROR("Bridge %p not found in list\n", bridge);
+}
+
+void Port::bridge(unsigned int bridge_id)
+{
+ struct port_bridge_member **memberp;
+
+ /* Remove bridge, if we leave bridge or if we join a different bridge. */
+ if (p_bridge && bridge_id != p_bridge->bridge_id) {
+ PDEBUG(DEBUG_PORT, "Remove port %u from bridge %u, because out new bridge is %u\n", p_serial, p_bridge->bridge_id, bridge_id);
+ remove_bridge(p_bridge, this);
+ p_bridge = NULL;
+ }
+
+ /* if we leave bridge */
+ if (!bridge_id)
+ return;
+
+ /* find bridge */
+ if (!p_bridge) {
+ struct port_bridge *temp = p_bridge_first;
+
+ while (temp) {
+ if (temp->bridge_id == bridge_id)
+ break;
+ temp = temp->next;
+ }
+ p_bridge = temp;
+ if (p_bridge)
+ PDEBUG(DEBUG_PORT, "Port %d found existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+ }
+
+ /* create bridge */
+ if (!p_bridge) {
+ struct port_bridge **temp = &p_bridge_first;
+
+ p_bridge = (struct port_bridge *) MALLOC(sizeof(struct port_bridge));
+ memuse++;
+ p_bridge->bridge_id = bridge_id;
+
+ /* attach bridge instance to list */
+ while (*temp)
+ temp = &((*temp)->next);
+ *temp = p_bridge;
+ PDEBUG(DEBUG_PORT, "Port %d creating not existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+ }
+
+ /* attach to bridge */
+ memberp = &p_bridge->first;
+ while(*memberp) {
+ if ((*memberp)->port == this) {
+ /* already joined */
+ return;
+ }
+ memberp = &((*memberp)->next);
+ }
+ *memberp = (struct port_bridge_member *) MALLOC(sizeof(struct port_bridge_member));
+ memuse++;
+ (*memberp)->port = this;
+}
+
+class Port *Port::bridge_remote(void)
+{
+ class Port *remote = NULL;
+
+ /* get remote port from bridge */
+ if (!p_bridge || !p_bridge->first || !p_bridge->first->next)
+ return NULL;
+ if (p_bridge->first->port == this)
+ remote = p_bridge->first->next->port;
+ if (p_bridge->first->next->port == this)
+ remote = p_bridge->first->port;
+
+ return remote;
+}
+
+/* send data to remote Port */
+int Port::bridge_tx(unsigned char *data, int len)
+{
+ class Port *remote = bridge_remote();
+
+ if (!remote)
+ return -EINVAL;
+
+// printf("Traffic: %u -> %u (bridge %u)\n", p_serial, remote->p_serial, p_bridge->bridge_id);
+ return remote->bridge_rx(data, len);
+}
+
+/* receive data from remote Port (dummy, needs to be inherited) */
+int Port::bridge_rx(unsigned char *data, int len)
+{
+ return 0; /* datenklo */
+}
+