struct capa_info capainfo;
struct caller_info callerinfo;
struct redir_info redirinfo;
+ struct rtp_info rtpinfo;
struct dialing_info dialinginfo;
struct port_list *portlist = ea_endpoint->ep_portlist;
struct lcr_msg *message;
memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+ memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
memset(&dialinginfo, 0, sizeof(dialinginfo));
dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
SCPY(dialinginfo.id, e_dialinginfo.id);
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
message_put(message);
}
struct capa_info capainfo;
struct caller_info callerinfo;
struct redir_info redirinfo;
+ struct rtp_info rtpinfo;
struct dialing_info dialinginfo;
char *p;
struct port_list *portlist = ea_endpoint->ep_portlist;
memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+ memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
memset(&dialinginfo, 0, sizeof(dialinginfo));
dialinginfo.itype = INFO_ITYPE_ISDN;
// dialinginfo.sending_complete = 0;
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
message_put(message);
}
memset(&e_connectinfo, 0, sizeof(struct connect_info));
memset(&e_redirinfo, 0, sizeof(struct redir_info));
memset(&e_capainfo, 0, sizeof(struct capa_info));
+ memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
e_start = e_stop = 0;
e_origin = origin;
e_ruleset = ruleset_main;
}
}
+/* hunts for the given interface
+ * it does not need to have an mISDNport instance */
+struct interface *EndpointAppPBX::hunt_interface(char *ifname)
+{
+ struct interface *interface;
+ int there_is_an_external = 0;
+
+ interface = interface_first;
+
+ /* first find the given interface or, if not given, one with no extension */
+ checknext:
+ if (!interface) {
+ if (!there_is_an_external && !(ifname && ifname[0])) {
+ trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
+ add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
+ end_trace();
+ }
+ return(NULL);
+ }
+
+ /* check for given interface */
+ if (ifname && ifname[0]) {
+ if (!strcasecmp(interface->name, ifname)) {
+ /* found explicit interface */
+ trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ goto foundif;
+ }
+ } else {
+ if (interface->external) {
+ there_is_an_external = 1;
+ /* found non extension */
+ trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", interface->name);
+ end_trace();
+ goto foundif;
+ }
+ }
+
+ interface = interface->next;
+ goto checknext;
+foundif:
+
+ return interface;
+}
+
/*
* hunts an mISDNport that is available for an outgoing call
int cause = CAUSE_RESSOURCEUNAVAIL;
const char *p;
char cfp[64];
+ struct interface *interface;
struct mISDNport *mISDNport;
char portname[32];
char *dirname;
SCCAT(ifname, *p++);
if (*p == ',')
p++;
- /* found interface */
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
- /* hunt for mISDNport and create Port */
- mISDNport = hunt_port(ifname, &channel);
- if (!mISDNport) {
- trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
+ /* search interface */
+ interface = hunt_interface(ifname);
+ if (!interface) {
+ trace_header("INTERFACE (not found)", DIRECTION_NONE);
add_trace("interface", NULL, "%s", ifname);
end_trace();
continue;
}
- /* creating INTERNAL port */
- SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-#ifdef WITH_SS5
- if (mISDNport->ss5)
- port = ss5_hunt_line(mISDNport);
- else
-#endif
+ /* found interface */
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
#ifdef WITH_GSM_BS
- if (mISDNport->gsm_bs)
- port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
+ if (interface->gsm_bs) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+ } else
#endif
#ifdef WITH_GSM_MS
- if (mISDNport->gsm_ms)
- port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
+ if (interface->gsm_ms) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+ } else
#endif
-#ifdef WITH_SIP
- if (mISDNport->ifport->interface->sip)
- port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
- else
+#ifdef WITH_GSM_MS
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ } else
#endif
- if (mISDNport->ifport->remote) {
- admin = admin_first;
- while(admin) {
- if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
- break;
- admin = admin->next;
- }
- if (!admin) {
- trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
- add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ {
+ /* hunt for mISDNport and create Port */
+ mISDNport = hunt_port(ifname, &channel);
+ if (!mISDNport) {
+ trace_header("INTERFACE (busy)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
end_trace();
continue;
}
- port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
- } else
- port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+
+ SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+ if (mISDNport->ss5)
+ port = ss5_hunt_line(mISDNport);
+ else
+#endif
+ if (mISDNport->ifport->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ end_trace();
+ continue;
+ }
+ port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+ } else
+ port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+ }
if (!port)
FATAL("Failed to create Port instance\n");
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
dialinginfo.ntype = e_dialinginfo.ntype;
/* create port_list relation */
- portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+ portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface->is_earlyb == IS_YES);
if (!portlist) {
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
//terminal SCPY(message->param.setup.from_terminal, e_ext.number);
//terminal if (e_dialinginfo.id)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
p++;
/* found number */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
- /* hunt for mISDNport and create Port */
- /* hunt for mISDNport and create Port */
- mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
- if (!mISDNport) {
- trace_header("INTERFACE (too busy)", DIRECTION_NONE);
- add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+ /* search interface */
+ interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
+ if (!interface) {
+ trace_header("INTERFACE (not found)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
end_trace();
goto check_anycall_extern;
}
- /* creating EXTERNAL port*/
- SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-#ifdef WITH_SS5
- if (mISDNport->ss5)
- port = ss5_hunt_line(mISDNport);
- else
-#endif
+ /* found interface */
#ifdef WITH_GSM_BS
- if (mISDNport->gsm_bs)
- port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
+ if (interface->gsm_bs) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+ } else
#endif
#ifdef WITH_GSM_MS
- if (mISDNport->gsm_ms)
- port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
+ if (interface->gsm_ms) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+ } else
#endif
-#ifdef WITH_SIP
- if (mISDNport->ifport->interface->sip)
- port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
- else
+#ifdef WITH_GSM_MS
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ } else
#endif
- if (mISDNport->ifport->remote) {
- admin = admin_first;
- while(admin) {
- if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
- break;
- admin = admin->next;
- }
- if (!admin) {
- trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
- add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ {
+ /* hunt for mISDNport and create Port */
+ mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
+ if (!mISDNport) {
+ trace_header("INTERFACE (too busy)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
end_trace();
- continue;
+ goto check_anycall_extern;
}
- port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
- } else
- port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+ /* creating EXTERNAL port*/
+ SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+ if (mISDNport->ss5)
+ port = ss5_hunt_line(mISDNport);
+ else
+#endif
+ if (mISDNport->ifport->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ end_trace();
+ continue;
+ }
+ port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+ } else
+ port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+ }
if (!port)
FATAL("No memory for Port instance\n");
- earlyb = mISDNport->earlyb;
+ earlyb = (interface->is_earlyb == IS_YES);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
if (e_dialinginfo.keypad[0])
dialinginfo.itype = INFO_ITYPE_ISDN;
dialinginfo.ntype = e_dialinginfo.ntype;
dialinginfo.sending_complete = e_dialinginfo.sending_complete;
- portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+ portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
if (!portlist) {
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
//terminal SCPY(message->param.setup.from_terminal, e_ext.number);
//terminal if (e_dialinginfo.id)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
char buffer[256];
int writeext; /* flags need to write extension after modification */
class Port *port;
- struct interface *interface;
logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
+ memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
/* convert (inter-)national number type */
SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
// e_dtmf = param->setup.dtmf;
/* screen incoming caller id */
- interface = interface_first;
- while(interface) {
- if (!strcmp(e_callerinfo.interface, interface->name)) {
- break;
- }
- interface = interface->next;
- }
- if (interface) {
- do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
- do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
+ if (e_callerinfo.interface[0]) {
+ do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
+ do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
}
/* process extension */
unsigned int port_id = portlist->port_id;
struct port_list *tportlist;
class Port *port;
- struct interface *interface;
time_t now;
logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
time(&now);
e_start = now;
- /* screen incoming connected id */
- interface = interface_first;
- while(interface) {
- if (!strcmp(e_connectinfo.interface, interface->name)) {
- break;
- }
- interface = interface->next;
- }
- if (interface)
- do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
+ if (e_callerinfo.interface[0])
+ do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
/* screen connected name */
if (e_ext.name[0])
memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
+ memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
/* process (voice over) data calls */
if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
struct caller_info e_callerinfo; /* information about the caller */
struct dialing_info e_dialinginfo; /* information about dialing */
struct connect_info e_connectinfo; /* information about connected line */
- struct redir_info e_redirinfo; /* info on redirection (to the calling user) */
- struct capa_info e_capainfo; /* info on l3,l2 capacity */
+ struct redir_info e_redirinfo; /* info about redirection (to the calling user) */
+ struct capa_info e_capainfo; /* info about l3,l2 capacity */
+ struct rtp_info e_rtpinfo; /* info about rtp port forwarding and payload type */
time_t e_start, e_stop; /* time */
int e_origin; /* origin of call 0=incoming 1=outgoing */
struct route_ruleset *e_ruleset; /* current ruleset pointer (NULL=no ruleset) */
void set_tone(struct port_list *portlist, const char *tone);
void out_setup(int cfnr);
struct mISDNport *hunt_port(char *ifname, int *channel);
+ struct interface *hunt_interface(char *ifname);
char *apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name);
void auth(int job, int bit_num);
# A special case for GSM Network interface.
-# Don't remove/change the settings, they will cause undefined behaviour
-# of LCR. It uses the loopback interface as defined in options.conf.
# You may add 'extension' and 'msn' keywords to turn all your subscribers
# in you GSM network to internal 'extensions'.
# The MSN numbers will equal the subscriber number.
#[GSM]
#gsm-bs
-#nt
-#layer1hold no
-#layer2hold no
#tones yes
#earlyb no
-#channel-in free
-#channel-out any
-#nodtmf
# A special case for GSM Mobile Station interface.
# give "gsm-ms <name of mobile instance>".
-# Don't remove/change the settings, they will cause undefined behaviour
-# of LCR. It uses the loopback interface as defined in options.conf.
# You may add 'extern' to make this interface the external line by default.
#[GSM]
#gsm-ms 1
-#layer1hold no
-#layer2hold no
#tones no
#earlyb yes
-#channel-in free
-#channel-out any
-#nodtmf
##extern
#tones yes
+# Use Sofia-SIP as SIP point-to-point interface
+#[sip]
+#sip <local ip> <remote ip>
+#sip 10.0.0.12 10.0.0.34
+#earlyb no
+#tones no
+
+
# Hint: Enter "lcr interface" for quick help on interface options.
#define DEBUG_GSM 0x0120
#define DEBUG_SS5 0x0140
#define DEBUG_VBOX 0x0180
+#define DEBUG_SIP 0x10000
#define DEBUG_EPOINT 0x0200
#define DEBUG_JOIN 0x0400
#define DEBUG_CRYPT 0x1000
#define DEBUG_ROUTE 0x2000
#define DEBUG_IDLETIME 0x4000
-#define DEBUG_LOG 0x7fff
+#define DEBUG_LOG 0x7fffff
#debug 0x0000
memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
/* screen outgoing caller id */
- do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
- do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
+ do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name);
+ do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name);
/* only display at connect state: this case happens if endpoint is in connected mode */
if (p_state==PORT_STATE_CONNECT) {
/* copy connected information */
memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
/* screen outgoing caller id */
- do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
+ do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface->name);
/* only display at connect state */
if (p_state == PORT_STATE_CONNECT)
int msg_type;
const char *name;
} mncc_names[] = {
+ { 0, "New call ref" },
{ MNCC_SETUP_REQ, "MNCC_SETUP_REQ" },
{ MNCC_SETUP_IND, "MNCC_SETUP_IND" },
{ MNCC_SETUP_RSP, "MNCC_SETUP_RSP" },
/*
* constructor
*/
-Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
{
- p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
- memset(&p_m_g_delete, 0, sizeof(p_m_g_delete));
- add_work(&p_m_g_delete, delete_event, this, 0);
- p_m_g_lcr_gsm = NULL;
- p_m_g_callref = 0;
- p_m_g_mode = 0;
- p_m_g_gsm_b_sock = -1;
- p_m_g_gsm_b_index = -1;
- p_m_g_gsm_b_active = 0;
- p_m_g_notify_pending = NULL;
- p_m_g_decoder = gsm_audio_create();
- p_m_g_encoder = gsm_audio_create();
- if (!p_m_g_encoder || !p_m_g_decoder) {
+ p_g_tones = 0;
+ if (interface->is_tones == IS_YES)
+ p_g_tones = 1;
+ p_g_earlyb = 0;
+ if (interface->is_earlyb == IS_YES)
+ p_g_earlyb = 1;
+ p_g_rtp_bridge = 0;
+ if (interface->rtp_bridge)
+ p_g_rtp_bridge = 1;
+ SCPY(p_g_interface_name, interface->name);
+ p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
+ memset(&p_g_delete, 0, sizeof(p_g_delete));
+ add_work(&p_g_delete, delete_event, this, 0);
+ p_g_lcr_gsm = NULL;
+ p_g_callref = 0;
+ p_g_mode = 0;
+ p_g_gsm_b_sock = -1;
+ p_g_gsm_b_index = -1;
+ p_g_gsm_b_active = 0;
+ p_g_notify_pending = NULL;
+ p_g_setup_pending = NULL;
+ p_g_connect_pending = NULL;
+ p_g_decoder = gsm_audio_create();
+ p_g_encoder = gsm_audio_create();
+ if (!p_g_encoder || !p_g_decoder) {
PERROR("Failed to create GSM audio codec instance\n");
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
}
- p_m_g_rxpos = 0;
- p_m_g_tch_connected = 0;
+ p_g_rxpos = 0;
+ p_g_tch_connected = 0;
PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
}
{
PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
- del_work(&p_m_g_delete);
+ del_work(&p_g_delete);
/* remove queued message */
- if (p_m_g_notify_pending)
- message_free(p_m_g_notify_pending);
-
- /* close audio transfer socket */
- if (p_m_g_gsm_b_sock > -1)
- bchannel_close();
+ if (p_g_notify_pending)
+ message_free(p_g_notify_pending);
+ if (p_g_setup_pending)
+ message_free(p_g_setup_pending);
+ if (p_g_connect_pending)
+ message_free(p_g_connect_pending);
/* close codec */
- if (p_m_g_encoder)
- gsm_audio_destroy(p_m_g_encoder);
- if (p_m_g_decoder)
- gsm_audio_destroy(p_m_g_decoder);
+ if (p_g_encoder)
+ gsm_audio_destroy(p_g_encoder);
+ if (p_g_decoder)
+ gsm_audio_destroy(p_g_decoder);
}
-/* close bsc side bchannel */
-void Pgsm::bchannel_close(void)
-{
- if (p_m_g_gsm_b_sock > -1) {
- unregister_fd(&p_m_g_gsm_b_fd);
- close(p_m_g_gsm_b_sock);
- }
- p_m_g_gsm_b_sock = -1;
- p_m_g_gsm_b_index = -1;
- p_m_g_gsm_b_active = 0;
-}
-
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index);
-
-/* open external side bchannel */
-int Pgsm::bchannel_open(int index)
+/* receive encoded frame from gsm */
+void Pgsm::frame_receive(void *arg)
{
- int ret;
- struct sockaddr_mISDN addr;
- struct mISDNhead act;
+ struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
+ signed short samples[160];
+ unsigned char data[160];
+ int i;
- if (p_m_g_gsm_b_sock > -1) {
- PERROR("Socket already created for index %d\n", index);
- return(-EIO);
- }
+ if (!p_g_decoder)
+ return;
- /* open socket */
- ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
- if (ret < 0) {
- PERROR("Failed to open bchannel-socket for index %d\n", index);
- bchannel_close();
- return(ret);
- }
- memset(&p_m_g_gsm_b_fd, 0, sizeof(p_m_g_gsm_b_fd));
- p_m_g_gsm_b_fd.fd = p_m_g_gsm_b_sock;
- register_fd(&p_m_g_gsm_b_fd, LCR_FD_READ, b_handler, this, 0);
-
-
- /* bind socket to bchannel */
- addr.family = AF_ISDN;
- addr.dev = mISDNloop.port;
- addr.channel = index+1+(index>15);
- ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
- if (ret < 0) {
- PERROR("Failed to bind bchannel-socket for index %d\n", index);
- bchannel_close();
- return(ret);
- }
- /* activate bchannel */
- PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
- act.prim = PH_ACTIVATE_REQ;
- act.id = 0;
- ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
- if (ret < 0) {
- PERROR("Failed to activate index %d\n", index);
- bchannel_close();
- return(ret);
+ if ((frame->data[0]>>4) != 0xd)
+ PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
+
+ /* decode */
+ gsm_audio_decode(p_g_decoder, frame->data, samples);
+ for (i = 0; i < 160; i++) {
+ data[i] = audio_s16_to_law[samples[i] & 0xffff];
}
- p_m_g_gsm_b_index = index;
-
- return(0);
+ /* send to remote*/
+ bridge_tx(data, 160);
}
-/* receive from bchannel */
-void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+/* send traffic to gsm */
+int Pgsm::bridge_rx(unsigned char *data, int len)
{
unsigned char frame[33];
/* encoder init failed */
- if (!p_m_g_encoder)
- return;
+ if (!p_g_encoder)
+ return -EINVAL;
/* (currently) not connected, so don't flood tch! */
- if (!p_m_g_tch_connected)
- return;
+ if (!p_g_tch_connected)
+ return -EINVAL;
/* write to rx buffer */
while(len--) {
- p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
- if (p_m_g_rxpos == 160) {
- p_m_g_rxpos = 0;
+ p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
+ if (p_g_rxpos == 160) {
+ p_g_rxpos = 0;
/* encode data */
- gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
+ gsm_audio_encode(p_g_encoder, p_g_rxdata, frame);
frame_send(frame);
}
}
-}
-
-/* transmit to bchannel */
-void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
-{
- unsigned char buf[MISDN_HEADER_LEN+len];
- struct mISDNhead *hh = (struct mISDNhead *)buf;
- int ret;
-
- if (!p_m_g_gsm_b_active)
- return;
- /* make and send frame */
- hh->prim = PH_DATA_REQ;
- hh->id = 0;
- memcpy(buf+MISDN_HEADER_LEN, data, len);
- ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
- if (ret <= 0)
- PERROR("Failed to send to socket index %d\n", p_m_g_gsm_b_index);
+ return 0;
}
void Pgsm::frame_send(void *_frame)
struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
frame->msg_type = GSM_TCHF_FRAME;
- frame->callref = p_m_g_callref;
+ frame->callref = p_g_callref;
memcpy(frame->data, _frame, 33);
- if (p_m_g_lcr_gsm) {
- mncc_send(p_m_g_lcr_gsm, frame->msg_type, frame);
- }
-}
-
-
-void Pgsm::frame_receive(void *arg)
-{
- struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
- signed short samples[160];
- unsigned char data[160];
- int i;
-
- if (!p_m_g_decoder)
- return;
-
- if ((frame->data[0]>>4) != 0xd)
- PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
-
- /* decode */
- gsm_audio_decode(p_m_g_decoder, frame->data, samples);
- for (i = 0; i < 160; i++) {
- data[i] = audio_s16_to_law[samples[i] & 0xffff];
+ if (p_g_lcr_gsm) {
+ mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
}
-
- /* send */
- bchannel_send(PH_DATA_REQ, 0, data, 160);
}
-
/*
* create trace
*/
-void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
+void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
{
char msgtext[64];
+ struct interface *interface = interface_first;
+
+ while (interface) {
+ if (!strcmp(interface->name, interface_name))
+ break;
+ interface = interface->next;
+ }
+ if (!interface)
+ return;
/* select message and primitive text */
SCPY(msgtext, mncc_name(msg_type));
SCAT(msgtext, " ----");
/* init trace with given values */
- start_trace(mISDNport?mISDNport->portnum:-1,
- mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
+ start_trace(0,
+ interface,
port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
port?port->p_dialinginfo.id:NULL,
direction,
msgtext);
}
-/* select free bchannel from loopback interface */
-int Pgsm::hunt_bchannel(void)
-{
- return loop_hunt_bchannel(this, p_m_mISDNport);
-}
-
/* PROCEEDING INDICATION */
void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
struct gsm_mncc *mode;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
if (mncc->fields & MNCC_F_CAUSE) {
add_trace("cause", "coding", "%d", mncc->cause.coding);
add_trace("cause", "location", "%", mncc->cause.location);
end_trace();
/* modify lchan to GSM codec V1 */
- gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
- mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+ mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
mode->lchan_mode = 0x01; /* GSM V1 */
mode->lchan_type = 0x02;
add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+ send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
}
struct lcr_msg *message;
struct gsm_mncc *frame;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
end_trace();
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
new_state(PORT_STATE_OUT_PROCEEDING);
- if (p_m_mISDNport->earlyb && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
}
struct lcr_msg *message;
struct gsm_mncc *frame;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
end_trace();
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
new_state(PORT_STATE_OUT_ALERTING);
- if (p_m_mISDNport->earlyb && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
}
p_connectinfo.present = INFO_PRESENT_ALLOWED;
p_connectinfo.screen = INFO_SCREEN_NETWORK;
p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
- p_connectinfo.isdn_port = p_m_portnum;
- SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
+ SCPY(p_connectinfo.interface, p_g_interface_name);
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
if (p_connectinfo.id[0])
add_trace("connect", "number", "%s", p_connectinfo.id);
else if (mncc->imsi[0])
end_trace();
/* send resp */
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
- resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
+ resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
-
- message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
- memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
- message_put(message);
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
new_state(PORT_STATE_CONNECT);
- if (!p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (!p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
+
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
+ memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
+ message->param.connectinfo.rtpinfo.payload_type = 3; /* FIXME: receive payload type from peer */
+
+ if (p_g_rtp_bridge) {
+ struct gsm_mncc_rtp *rtp;
+
+ PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
+ p_g_connect_pending = message;
+ rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+ } else
+ message_put(message);
}
/* CONNECT ACK INDICATION */
{
struct gsm_mncc *frame;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
end_trace();
new_state(PORT_STATE_CONNECT);
- if (!p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (!p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
}
int cause = 16, location = 0;
struct gsm_mncc *resp;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
if (mncc->fields & MNCC_F_CAUSE) {
location = mncc->cause.location;
cause = mncc->cause.value;
end_trace();
/* send release */
- resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+ resp = create_mncc(MNCC_REL_REQ, p_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
#if 0
resp->fields |= MNCC_F_CAUSE;
resp->cause.coding = 3;
add_trace("cause", "value", "%d", resp->cause.value);
#endif
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
/* sending release to endpoint */
while(p_epointlist) {
free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
}
/* CC_RELEASE INDICATION */
int location = 0, cause = 16;
struct lcr_msg *message;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
if (mncc->fields & MNCC_F_CAUSE) {
location = mncc->cause.location;
cause = mncc->cause.value;
free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
}
/* NOTIFY INDICATION */
{
struct lcr_msg *message;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
add_trace("notify", NULL, "%d", mncc->notify);
end_trace();
notify = param->notifyinfo.notify & 0x7f;
if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
/* queue notification */
- if (p_m_g_notify_pending)
- message_free(p_m_g_notify_pending);
- p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
- memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
+ if (p_g_notify_pending)
+ message_free(p_g_notify_pending);
+ p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
+ memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
} else {
/* sending notification */
- gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
add_trace("notify", NULL, "%d", notify);
end_trace();
- mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
+ mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
mncc->notify = notify;
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
}
}
}
+/* RTP create indication */
+void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+ struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
+
+ /* send queued setup, as we received remote RTP info */
+ if (p_g_setup_pending) {
+ struct lcr_msg *message;
+
+ message = p_g_setup_pending;
+ PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
+ message->param.setup.rtpinfo.ip = rtp->ip;
+ message->param.setup.rtpinfo.port = rtp->port;
+ message_put(message);
+ p_g_setup_pending = NULL;
+ }
+ if (p_g_connect_pending) {
+ struct gsm_mncc_rtp *nrtp;
+
+ PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
+ nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+ nrtp->ip = p_g_rtp_ip_remote;
+ nrtp->port = p_g_rtp_port_remote;
+ send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
+ }
+}
+
+/* RTP connect indication */
+void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+ struct lcr_msg *message;
+ struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
+
+ if (p_g_connect_pending) {
+ message = p_g_connect_pending;
+ PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
+ message->param.connectinfo.rtpinfo.ip = rtp->ip;
+ message->param.connectinfo.rtpinfo.port = rtp->port;
+ message_put(message);
+ p_g_connect_pending = NULL;
+ }
+}
+
+/* MESSAGE_PROGRESS */
+void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
+{
+ if (param->progressinfo.progress == 8) {
+ PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
+ p_g_tones = 1;
+ }
+
+ if (param->progressinfo.rtpinfo.port) {
+ struct gsm_mncc_rtp *rtp;
+
+ PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->progressinfo.rtpinfo.ip, param->progressinfo.rtpinfo.port);
+ rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+ rtp->ip = param->progressinfo.rtpinfo.ip;
+ rtp->port = param->progressinfo.rtpinfo.port;
+ send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+ }
+}
+
/* MESSAGE_ALERTING */
void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
{
struct gsm_mncc *mncc;
/* send alert */
- gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
- mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
- if (p_m_mISDNport->tones) {
+ gsm_trace_header(p_g_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
+ mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
+ if (p_g_tones) {
mncc->fields |= MNCC_F_PROGRESS;
mncc->progress.coding = 3; /* GSM */
mncc->progress.location = 1;
add_trace("progress", "descr", "%d", mncc->progress.descr);
}
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_IN_ALERTING);
- if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- p_m_g_tch_connected = 1;
+ mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+ p_g_tch_connected = 1;
}
}
/* copy connected information */
memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
/* screen outgoing caller id */
- do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
+ do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_g_interface_name);
/* send connect */
- mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
+ mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
/* caller information */
mncc->fields |= MNCC_F_CONNECTED;
mncc->connected.plan = 1;
add_trace("connected", "number", "%s", mncc->connected.number);
}
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_CONNECT_WAITING);
+
+ if (param->connectinfo.rtpinfo.port) {
+ struct gsm_mncc_rtp *rtp;
+
+ PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
+ rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+ rtp->ip = param->connectinfo.rtpinfo.ip;
+ rtp->port = param->connectinfo.rtpinfo.port;
+ send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+ }
+
}
/* MESSAGE_DISCONNECT */
struct gsm_mncc *mncc;
/* send disconnect */
- mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
- if (p_m_mISDNport->tones) {
+ mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
+ if (p_g_tones) {
mncc->fields |= MNCC_F_PROGRESS;
mncc->progress.coding = 3; /* GSM */
mncc->progress.location = 1;
add_trace("cause", "location", "%d", mncc->cause.location);
add_trace("cause", "value", "%d", mncc->cause.value);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_OUT_DISCONNECT);
- if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- p_m_g_tch_connected = 1;
+ mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+ p_g_tch_connected = 1;
}
}
struct gsm_mncc *mncc;
/* send release */
- mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+ mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
mncc->fields |= MNCC_F_CAUSE;
mncc->cause.coding = 3;
mncc->cause.location = param->disconnectinfo.location;
add_trace("cause", "location", "%d", mncc->cause.location);
add_trace("cause", "value", "%d", mncc->cause.value);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
*/
int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
{
- if (PmISDN::message_epoint(epoint_id, message_id, param))
- return(1);
+ int ret = 0;
+
+ if (Port::message_epoint(epoint_id, message_id, param))
+ return 1;
switch(message_id) {
case MESSAGE_NOTIFY: /* display and notifications */
+ ret = 1;
message_notify(epoint_id, message_id, param);
break;
// break;
case MESSAGE_PROCEEDING: /* message not handles */
+ ret = 1;
+ break;
+
+ case MESSAGE_PROGRESS:
+ ret = 1;
+ message_progress(epoint_id, message_id, param);
break;
case MESSAGE_ALERTING: /* call of endpoint is ringing */
+ ret = 1;
if (p_state!=PORT_STATE_IN_PROCEEDING)
break;
message_alerting(epoint_id, message_id, param);
- if (p_m_g_notify_pending) {
+ if (p_g_notify_pending) {
/* send pending notify message during connect */
- message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
- message_free(p_m_g_notify_pending);
- p_m_g_notify_pending = NULL;
+ message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
+ message_free(p_g_notify_pending);
+ p_g_notify_pending = NULL;
}
break;
case MESSAGE_CONNECT: /* call of endpoint is connected */
+ ret = 1;
if (p_state!=PORT_STATE_IN_PROCEEDING
&& p_state!=PORT_STATE_IN_ALERTING)
break;
message_connect(epoint_id, message_id, param);
- if (p_m_g_notify_pending) {
+ if (p_g_notify_pending) {
/* send pending notify message during connect */
- message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
- message_free(p_m_g_notify_pending);
- p_m_g_notify_pending = NULL;
+ message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
+ message_free(p_g_notify_pending);
+ p_g_notify_pending = NULL;
}
break;
case MESSAGE_DISCONNECT: /* call has been disconnected */
+ ret = 1;
if (p_state!=PORT_STATE_IN_PROCEEDING
&& p_state!=PORT_STATE_IN_ALERTING
&& p_state!=PORT_STATE_OUT_SETUP
break;
case MESSAGE_RELEASE: /* release isdn port */
+ ret = 1;
if (p_state==PORT_STATE_RELEASE)
break;
message_release(epoint_id, message_id, param);
}
- return(0);
+ return ret;
}
/* deletes only if l3id is release, otherwhise it will be triggered then */
return 0;
}
-/*
- * handler of bchannel events
- */
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index)
-{
- class Pgsm *gsmport = (class Pgsm *)instance;
- int ret;
- unsigned char buffer[2048+MISDN_HEADER_LEN];
- struct mISDNhead *hh = (struct mISDNhead *)buffer;
-
- /* handle message from bchannel */
- if (gsmport->p_m_g_gsm_b_sock > -1) {
- ret = recv(gsmport->p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
- if (ret >= (int)MISDN_HEADER_LEN) {
- switch(hh->prim) {
- /* we don't care about confirms, we use rx data to sync tx */
- case PH_DATA_CNF:
- break;
- /* we receive audio data, we respond to it AND we send tones */
- case PH_DATA_IND:
- gsmport->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
- break;
- case PH_ACTIVATE_IND:
- gsmport->p_m_g_gsm_b_active = 1;
- break;
- case PH_DEACTIVATE_IND:
- gsmport->p_m_g_gsm_b_active = 0;
- break;
- }
- } else {
- if (ret < 0 && errno != EWOULDBLOCK)
- PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
- }
- }
-
- return 0;
-}
-
int gsm_exit(int rc)
{
return(rc);
while(port) {
if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
pgsm = (class Pgsm *)port;
- if (pgsm->p_m_g_lcr_gsm == lcr_gsm) {
+ if (pgsm->p_g_lcr_gsm == lcr_gsm) {
message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = 27; // temp. unavail.
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
pgsm->new_state(PORT_STATE_RELEASE);
- trigger_work(&pgsm->p_m_g_delete);
+ trigger_work(&pgsm->p_g_delete);
}
}
port = port->next;
};
struct lcr_gsm {
+ struct interface *interface; /* interface this instance is associated to */
struct lcr_gsm *gsm_ms_next; /* list of MS instances, in case of MS */
char name[16]; /* name of MS instance, in case of MS */
int type; /* LCR_GSM_TYPE_*/
};
/* GSM port class */
-class Pgsm : public PmISDN
+class Pgsm : public Port
{
public:
- Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+ Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface);
~Pgsm();
- struct lcr_gsm *p_m_g_lcr_gsm; /* pointer to network/ms instance */
- unsigned int p_m_g_callref; /* ref by OpenBSC/Osmocom-BB */
- struct lcr_work p_m_g_delete; /* queue destruction of GSM port instance */
- unsigned int p_m_g_mode; /* data/transparent mode */
- int p_m_g_gsm_b_sock; /* gsm bchannel socket */
- struct lcr_fd p_m_g_gsm_b_fd; /* event node */
- int p_m_g_gsm_b_index; /* gsm bchannel socket index to use */
- int p_m_g_gsm_b_active; /* gsm bchannel socket is activated */
- struct lcr_msg *p_m_g_notify_pending; /* queue for NOTIFY if not connected */
- void *p_m_g_encoder, *p_m_g_decoder; /* gsm handle */
- signed short p_m_g_rxdata[160]; /* receive audio buffer */
- int p_m_g_rxpos; /* position in audio buffer 0..159 */
- int p_m_g_tch_connected; /* indicates if audio is connected */
+ char p_g_interface_name[64];
+ int p_g_tones; /* set, if tones are to be generated */
+ int p_g_earlyb; /* set, if patterns are available */
+ struct lcr_gsm *p_g_lcr_gsm; /* pointer to network/ms instance */
+ unsigned int p_g_callref; /* ref by OpenBSC/Osmocom-BB */
+ struct lcr_work p_g_delete; /* queue destruction of GSM port instance */
+ unsigned int p_g_mode; /* data/transparent mode */
+ int p_g_gsm_b_sock; /* gsm bchannel socket */
+ struct lcr_fd p_g_gsm_b_fd; /* event node */
+ int p_g_gsm_b_index; /* gsm bchannel socket index to use */
+ int p_g_gsm_b_active; /* gsm bchannel socket is activated */
+ struct lcr_msg *p_g_notify_pending; /* queue for NOTIFY if not connected */
+ struct lcr_msg *p_g_setup_pending; /* queue SETUP until RTP is created */
+ struct lcr_msg *p_g_connect_pending; /* queue CONNECT until RTP is created and connected */
+ void *p_g_encoder, *p_g_decoder; /* gsm handle */
+ signed short p_g_rxdata[160]; /* receive audio buffer */
+ int p_g_rxpos; /* position in audio buffer 0..159 */
+ int p_g_tch_connected; /* indicates if audio is connected */
- void bchannel_close(void);
- int bchannel_open(int index);
- void bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len);
- void bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len);
+ int p_g_rtp_bridge; /* if we use a bridge */
+ unsigned int p_g_rtp_ip_remote; /* stores ip */
+ unsigned short p_g_rtp_port_remote; /* stores port */
void frame_send(void *_frame);
void frame_receive(void *_frame);
+ int bridge_rx(unsigned char *data, int len);
int hunt_bchannel(void);
void call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *gsm);
void disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
void rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
void notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
+ void rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
+ void rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
+ void message_progress(unsigned int epoint_id, int message_id, union parameter *param);
void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
void message_connect(unsigned int epoint_id, int message_id, union parameter *param);
void message_disconnect(unsigned int epoint_id, int message_id, union parameter *param);
struct gsm_mncc *create_mncc(int msg_type, unsigned int callref);
int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data);
-void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction);
+void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction);
int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
int gsm_exit(int rc);
int gsm_init(void);
/*
* constructor
*/
-Pgsm_bs::Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
{
- p_m_g_lcr_gsm = gsm_bs;
- p_m_g_dtmf = NULL;
- p_m_g_dtmf_index = 0;
+ p_g_lcr_gsm = gsm_bs;
+ p_g_dtmf = NULL;
+ p_g_dtmf_index = 0;
PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
}
/* DTMF INDICATION */
void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
-// struct lcr_msg *message;
+ struct lcr_msg *message;
struct gsm_mncc *resp;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
add_trace("keypad", NULL, "%c", mncc->keypad);
end_trace();
SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
/* send resp */
- gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
add_trace("keypad", NULL, "%c", mncc->keypad);
end_trace();
- resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
+ resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
resp->fields |= MNCC_F_KEYPAD;
resp->keypad = mncc->keypad;
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
-
-#if 0
- /* send dialing information */
- message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
- memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
- message_put(message);
-#endif
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
- /* generate DTMF tones */
- switch (mncc->keypad) {
- case '1': p_m_g_dtmf = dtmf_samples[0]; break;
- case '2': p_m_g_dtmf = dtmf_samples[1]; break;
- case '3': p_m_g_dtmf = dtmf_samples[2]; break;
- case 'a':
- case 'A': p_m_g_dtmf = dtmf_samples[3]; break;
- case '4': p_m_g_dtmf = dtmf_samples[4]; break;
- case '5': p_m_g_dtmf = dtmf_samples[5]; break;
- case '6': p_m_g_dtmf = dtmf_samples[6]; break;
- case 'b':
- case 'B': p_m_g_dtmf = dtmf_samples[7]; break;
- case '7': p_m_g_dtmf = dtmf_samples[8]; break;
- case '8': p_m_g_dtmf = dtmf_samples[9]; break;
- case '9': p_m_g_dtmf = dtmf_samples[10]; break;
- case 'c':
- case 'C': p_m_g_dtmf = dtmf_samples[11]; break;
- case '*': p_m_g_dtmf = dtmf_samples[12]; break;
- case '0': p_m_g_dtmf = dtmf_samples[13]; break;
- case '#': p_m_g_dtmf = dtmf_samples[14]; break;
- case 'd':
- case 'D': p_m_g_dtmf = dtmf_samples[15]; break;
+ if (p_g_rtp_bridge) {
+ /* send dtmf information, because we bridge RTP directly */
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
+ message->param.dtmf = mncc->keypad;
+ message_put(message);
+ } else {
+ /* generate DTMF tones, since we do audio forwarding inside LCR */
+ switch (mncc->keypad) {
+ case '1': p_g_dtmf = dtmf_samples[0]; break;
+ case '2': p_g_dtmf = dtmf_samples[1]; break;
+ case '3': p_g_dtmf = dtmf_samples[2]; break;
+ case 'a':
+ case 'A': p_g_dtmf = dtmf_samples[3]; break;
+ case '4': p_g_dtmf = dtmf_samples[4]; break;
+ case '5': p_g_dtmf = dtmf_samples[5]; break;
+ case '6': p_g_dtmf = dtmf_samples[6]; break;
+ case 'b':
+ case 'B': p_g_dtmf = dtmf_samples[7]; break;
+ case '7': p_g_dtmf = dtmf_samples[8]; break;
+ case '8': p_g_dtmf = dtmf_samples[9]; break;
+ case '9': p_g_dtmf = dtmf_samples[10]; break;
+ case 'c':
+ case 'C': p_g_dtmf = dtmf_samples[11]; break;
+ case '*': p_g_dtmf = dtmf_samples[12]; break;
+ case '0': p_g_dtmf = dtmf_samples[13]; break;
+ case '#': p_g_dtmf = dtmf_samples[14]; break;
+ case 'd':
+ case 'D': p_g_dtmf = dtmf_samples[15]; break;
+ }
+ p_g_dtmf_index = 0;
}
- p_m_g_dtmf_index = 0;
}
void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
struct gsm_mncc *resp;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
add_trace("keypad", NULL, "%c", mncc->keypad);
end_trace();
/* send resp */
- gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
add_trace("keypad", NULL, "%c", mncc->keypad);
end_trace();
- resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
+ resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
resp->keypad = mncc->keypad;
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
/* stop DTMF */
- p_m_g_dtmf = NULL;
+ p_g_dtmf = NULL;
}
/* HOLD INDICATION */
struct lcr_msg *message;
struct gsm_mncc *resp, *frame;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
end_trace();
/* notify the hold of call */
message_put(message);
/* acknowledge hold */
- gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
end_trace();
- resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+ resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
/* disable audio */
- if (p_m_g_tch_connected) { /* it should be true */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
+ if (p_g_tch_connected) { /* it should be true */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 0;
+ frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 0;
}
}
struct lcr_msg *message;
struct gsm_mncc *resp, *frame;
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
end_trace();
/* notify the retrieve of call */
message_put(message);
/* acknowledge retr */
- gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
end_trace();
- resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+ resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
/* enable audio */
- if (!p_m_g_tch_connected) { /* it should be true */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (!p_g_tch_connected) { /* it should be true */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
}
/* SETUP INDICATION */
void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
- int ret;
class Endpoint *epoint;
struct lcr_msg *message;
- int channel;
struct gsm_mncc *mode, *proceeding, *frame;
/* process given callref */
- l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
add_trace("callref", "new", "0x%x", callref);
- if (p_m_g_callref) {
+ if (p_g_callref) {
/* release in case the ID is already in use */
add_trace("error", NULL, "callref already in use");
end_trace();
mncc = create_mncc(MNCC_REJ_REQ, callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
mncc->fields |= MNCC_F_CAUSE;
mncc->cause.coding = 3;
mncc->cause.location = 1;
add_trace("cause", "value", "%d", mncc->cause.value);
add_trace("reason", NULL, "callref already in use");
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
- p_m_g_callref = callref;
+ p_g_callref = callref;
end_trace();
- /* if blocked, release call with MT_RELEASE_COMPLETE */
- if (p_m_mISDNport->ifport->block) {
- mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.coding = 3;
- mncc->cause.location = 1;
- mncc->cause.value = 27;
- add_trace("cause", "coding", "%d", mncc->cause.coding);
- add_trace("cause", "location", "%d", mncc->cause.location);
- add_trace("cause", "value", "%d", mncc->cause.value);
- add_trace("reason", NULL, "port is blocked");
- end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
-
/* caller info */
if (mncc->clir.inv)
p_callerinfo.present = INFO_PRESENT_RESTRICTED;
SCPY(p_callerinfo.imsi, mncc->imsi);
p_callerinfo.screen = INFO_SCREEN_NETWORK;
p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
- p_callerinfo.isdn_port = p_m_portnum;
- SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+ SCPY(p_callerinfo.interface, p_g_interface_name);
/* dialing information */
SCAT(p_dialinginfo.id, mncc->called.number);
p_capainfo.bearer_info1 = (options.law=='a')?3:2;
p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
p_capainfo.source_mode = B_MODE_TRANSPARENT;
- p_m_g_mode = p_capainfo.source_mode;
+ p_g_mode = p_capainfo.source_mode;
/* useruser */
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
-
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.coding = 3;
- mncc->cause.location = 1;
- mncc->cause.value = 34;
- add_trace("cause", "coding", "%d", mncc->cause.coding);
- add_trace("cause", "location", "%d", mncc->cause.location);
- add_trace("cause", "value", "%d", mncc->cause.value);
- add_trace("reason", NULL, "no channel");
- end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
-
/* what infos did we got ... */
- gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
if (p_callerinfo.id[0])
add_trace("calling", "number", "%s", p_callerinfo.id);
else
epointlist_new(epoint->ep_serial);
/* modify lchan to GSM codec V1 */
- gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
- mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+ mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
mode->lchan_mode = 0x01; /* GSM V1 */
mode->lchan_type = 0x02;
add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+ send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
/* send call proceeding */
- gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
- proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
- if (p_m_mISDNport->tones) {
+ gsm_trace_header(p_g_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
+ proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
+ if (p_g_tones) {
proceeding->fields |= MNCC_F_PROGRESS;
proceeding->progress.coding = 3; /* GSM */
proceeding->progress.location = 1;
add_trace("progress", "descr", "%d", proceeding->progress.descr);
}
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
+ send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
new_state(PORT_STATE_IN_PROCEEDING);
- if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
/* send setup message to endpoit */
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
- message->param.setup.isdn_port = p_m_portnum;
message->param.setup.port_type = p_type;
// message->param.setup.dtmf = 0;
memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
message->param.setup.useruser.len = strlen(mncc->useruser.info);
message->param.setup.useruser.protocol = mncc->useruser.proto;
- message_put(message);
+ message->param.setup.rtpinfo.payload_type = 3; /* FIXME: receive payload type from peer */
+
+ if (p_g_rtp_bridge) {
+ struct gsm_mncc_rtp *rtp;
+
+ PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
+ p_g_setup_pending = message;
+ rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+ } else
+ message_put(message);
+
}
/*
*/
int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
{
+ struct interface *interface = lcr_gsm->interface;
struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
unsigned int callref = mncc->callref;
class Port *port;
class Pgsm_bs *pgsm_bs = NULL;
char name[64];
- struct mISDNport *mISDNport;
+// struct mISDNport *mISDNport;
/* Special messages */
switch(msg_type) {
while(port) {
if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
pgsm_bs = (class Pgsm_bs *)port;
- if (pgsm_bs->p_m_g_callref == callref) {
+ if (pgsm_bs->p_g_callref == callref) {
break;
}
}
if (msg_type == GSM_TCHF_FRAME) {
if (port) {
/* inject DTMF, if enabled */
- if (pgsm_bs->p_m_g_dtmf) {
+ if (pgsm_bs->p_g_dtmf) {
unsigned char data[160];
int i;
for (i = 0; i < 160; i++) {
- data[i] = pgsm_bs->p_m_g_dtmf[pgsm_bs->p_m_g_dtmf_index++];
- if (pgsm_bs->p_m_g_dtmf_index == 8000)
- pgsm_bs->p_m_g_dtmf_index = 0;
+ data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
+ if (pgsm_bs->p_g_dtmf_index == 8000)
+ pgsm_bs->p_g_dtmf_index = 0;
}
/* send */
- pgsm_bs->bchannel_send(PH_DATA_REQ, 0, data, 160);
+ pgsm_bs->bridge_tx(data, 160);
} else
pgsm_bs->frame_receive(arg);
+ /* if we do not bridge we need to inject audio, if available */
+ if (!pgsm_bs->p_bridge) {
+ unsigned char data[160];
+ int i;
+
+ i = pgsm_bs->read_audio(data, 160);
+ if (i)
+ pgsm_bs->bridge_rx(data, i);
+ }
}
return 0;
}
if (!port) {
if (msg_type != MNCC_SETUP_IND)
return(0);
+#if 0
/* find gsm port */
mISDNport = mISDNport_first;
while(mISDNport) {
send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
return 0;
}
+#endif
/* creating port object, transparent until setup with hdlc */
- SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
- if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
-
+ SPRINT(name, "%s-%d-in", interface->name, 0);
+ if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
FATAL("Cannot create Port instance.\n");
}
pgsm_bs->setup_ind(msg_type, callref, mncc);
break;
+ case MNCC_RTP_CREATE:
+ pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
+ break;
+
+ case MNCC_RTP_CONNECT:
+ pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
+ break;
+
case MNCC_START_DTMF_IND:
pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
break;
void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
{
struct lcr_msg *message;
- int ret;
struct epoint_list *epointlist;
struct gsm_mncc *mncc;
- int channel;
/* copy setup infos to port */
memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
/* no GSM MNCC connection */
- if (p_m_g_lcr_gsm->mncc_lfd.fd < 0) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
add_trace("failure", NULL, "No MNCC connection.");
end_trace();
message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
/* no number */
if (!p_dialinginfo.id[0]) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
add_trace("failure", NULL, "No dialed subscriber given.");
end_trace();
message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
-
- /* release if port is blocked */
- if (p_m_mISDNport->ifport->block) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- add_trace("failure", NULL, "Port blocked.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 27; // temp. unavail.
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- add_trace("failure", NULL, "No internal audio channel available.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 34;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
-
// SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
/* screen outgoing caller id */
- do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
+ do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_g_interface_name);
/* attach only if not already */
epointlist = p_epointlist;
epointlist_new(epoint_id);
/* creating l3id */
- l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
- p_m_g_callref = new_callref++;
- add_trace("callref", "new", "0x%x", p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
+ p_g_callref = new_callref++;
+ add_trace("callref", "new", "0x%x", p_g_callref);
end_trace();
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
/* caller information */
mncc->fields |= MNCC_F_CALLING;
mncc->calling.plan = 1;
//todo
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_OUT_SETUP);
message_put(message);
new_state(PORT_STATE_OUT_PROCEEDING);
+
+ /* RTP bridge */
+ if (param->setup.rtpinfo.port) {
+ p_g_rtp_bridge = 1;
+ p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
+ p_g_rtp_port_remote = param->setup.rtpinfo.port;
+ } else
+ p_g_rtp_bridge = 0;
}
/*
return(rc);
}
-int gsm_bs_init(void)
+int gsm_bs_init(struct interface *interface)
{
/* create gsm instance */
gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
+ gsm_bs->interface = interface;
gsm_bs->type = LCR_GSM_TYPE_NETWORK;
gsm_bs->sun.sun_family = AF_UNIX;
SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
class Pgsm_bs : public Pgsm
{
public:
- Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+ Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface);
~Pgsm_bs();
- unsigned char *p_m_g_dtmf; /* DTMF tone generation (MS only) */
- int p_m_g_dtmf_index; /* DTMF tone generation index */
+ unsigned char *p_g_dtmf; /* DTMF tone generation (MS only) */
+ int p_g_dtmf_index; /* DTMF tone generation index */
void setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
void start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
int gsm_bs_conf(struct gsm_conf *gsm_conf, char *conf_error);
int gsm_bs_exit(int rc);
-int gsm_bs_init(void);
+int gsm_bs_init(struct interface *interface);
int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
/*
* constructor
*/
-Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm_ms::Pgsm_ms(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
{
struct lcr_gsm *gsm_ms = gsm_ms_first;
- char *ms_name = mISDNport->ifport->gsm_ms_name;
- p_m_g_lcr_gsm = NULL;
+ p_g_lcr_gsm = NULL;
+ SCPY(p_g_ms_name, interface->gsm_ms_name);
while (gsm_ms) {
- if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, ms_name)) {
- p_m_g_lcr_gsm = gsm_ms;
+ if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, p_g_ms_name)) {
+ p_g_lcr_gsm = gsm_ms;
break;
}
gsm_ms = gsm_ms->gsm_ms_next;
}
- p_m_g_dtmf_state = DTMF_ST_IDLE;
- p_m_g_dtmf_index = 0;
- p_m_g_dtmf[0] = '\0';
- memset(&p_m_g_dtmf_timer, 0, sizeof(p_m_g_dtmf_timer));
- add_timer(&p_m_g_dtmf_timer, dtmf_timeout, this, 0);
+ p_g_dtmf_state = DTMF_ST_IDLE;
+ p_g_dtmf_index = 0;
+ p_g_dtmf[0] = '\0';
+ memset(&p_g_dtmf_timer, 0, sizeof(p_g_dtmf_timer));
+ add_timer(&p_g_dtmf_timer, dtmf_timeout, this, 0);
- PDEBUG(DEBUG_GSM, "Created new GSMMSPort(%s %s).\n", portname, ms_name);
+ PDEBUG(DEBUG_GSM, "Created new GSMMSPort(%s %s).\n", portname, p_g_ms_name);
}
/*
Pgsm_ms::~Pgsm_ms()
{
PDEBUG(DEBUG_GSM, "Destroyed GSM MS process(%s).\n", p_name);
- del_timer(&p_m_g_dtmf_timer);
+ del_timer(&p_g_dtmf_timer);
}
/*
/* SETUP INDICATION */
void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
- int ret;
class Endpoint *epoint;
struct lcr_msg *message;
- int channel;
struct gsm_mncc *mode, *proceeding, *frame;
/* process given callref */
- l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
add_trace("callref", "new", "0x%x", callref);
- if (p_m_g_callref) {
+ if (p_g_callref) {
/* release in case the ID is already in use */
add_trace("error", NULL, "callref already in use");
end_trace();
mncc = create_mncc(MNCC_REJ_REQ, callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
mncc->fields |= MNCC_F_CAUSE;
mncc->cause.coding = 3;
mncc->cause.location = 1;
add_trace("cause", "value", "%d", mncc->cause.value);
add_trace("reason", NULL, "callref already in use");
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
- p_m_g_callref = callref;
+ p_g_callref = callref;
end_trace();
- /* if blocked, release call with MT_RELEASE_COMPLETE */
- if (p_m_mISDNport->ifport->block) {
- mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.coding = 3;
- mncc->cause.location = 1;
- mncc->cause.value = 27;
- add_trace("cause", "coding", "%d", mncc->cause.coding);
- add_trace("cause", "location", "%d", mncc->cause.location);
- add_trace("cause", "value", "%d", mncc->cause.value);
- add_trace("reason", NULL, "port is blocked");
- end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
-
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_IND, DIRECTION_IN);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_IND, DIRECTION_IN);
/* caller information */
p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
if (mncc->fields & MNCC_F_CALLING) {
add_trace("calling", "screen", "%d", mncc->calling.screen);
add_trace("calling", "number", "%s", mncc->calling.number);
}
- p_callerinfo.isdn_port = p_m_portnum;
- SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+ SCPY(p_callerinfo.interface, p_g_interface_name);
/* dialing information */
if (mncc->fields & MNCC_F_CALLED) {
SCAT(p_dialinginfo.id, mncc->called.number);
add_trace("redir", "present", "%d", mncc->redirecting.present);
add_trace("redir", "screen", "%d", mncc->redirecting.screen);
add_trace("redir", "number", "%s", mncc->redirecting.number);
- p_redirinfo.isdn_port = p_m_portnum;
}
/* bearer capability */
if (mncc->fields & MNCC_F_BEARER_CAP) {
end_trace();
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
-
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
- gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.coding = 3;
- mncc->cause.location = 1;
- mncc->cause.value = 34;
- add_trace("cause", "coding", "%d", mncc->cause.coding);
- add_trace("cause", "location", "%d", mncc->cause.location);
- add_trace("cause", "value", "%d", mncc->cause.value);
- add_trace("reason", NULL, "no channel");
- end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
-
/* create endpoint */
if (p_epointlist)
FATAL("Incoming call but already got an endpoint.\n");
epointlist_new(epoint->ep_serial);
/* modify lchan to GSM codec V1 */
- gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
- mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+ mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
mode->lchan_mode = 0x01; /* GSM V1 */
mode->lchan_type = 0x02;
add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+ send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
/* send call proceeding */
- gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
- proceeding = create_mncc(MNCC_CALL_CONF_REQ, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
+ proceeding = create_mncc(MNCC_CALL_CONF_REQ, p_g_callref);
// FIXME: bearer
/* DTMF supported */
proceeding->fields |= MNCC_F_CCCAP;
proceeding->cccap.dtmf = 1;
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
+ send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
new_state(PORT_STATE_IN_PROCEEDING);
- if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
- gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+ gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
end_trace();
- frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
- send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
- p_m_g_tch_connected = 1;
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
}
/* send setup message to endpoit */
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
- message->param.setup.isdn_port = p_m_portnum;
message->param.setup.port_type = p_type;
// message->param.setup.dtmf = 0;
memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
*/
int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
{
+ struct interface *interface = gsm_ms->interface;
struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
unsigned int callref = mncc->callref;
class Port *port;
class Pgsm_ms *pgsm_ms = NULL;
char name[64];
- struct mISDNport *mISDNport;
+// struct mISDNport *mISDNport;
/* Special messages */
switch (msg_type) {
while(port) {
if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
pgsm_ms = (class Pgsm_ms *)port;
- if (pgsm_ms->p_m_g_callref == callref) {
+ if (pgsm_ms->p_g_callref == callref) {
break;
}
}
if (!port) {
if (msg_type != MNCC_SETUP_IND)
return(0);
+#if 0
/* find gsm ms port */
mISDNport = mISDNport_first;
while(mISDNport) {
send_and_free_mncc(gsm_ms, rej->msg_type, rej);
return 0;
}
+#endif
/* creating port object, transparent until setup with hdlc */
- SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
- if (!(pgsm_ms = new Pgsm_ms(PORT_TYPE_GSM_MS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
-
+ SPRINT(name, "%s-%d-in", interface->name, 0);
+ if (!(pgsm_ms = new Pgsm_ms(PORT_TYPE_GSM_MS_IN, name, NULL, interface)))
FATAL("Cannot create Port instance.\n");
}
void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
{
struct lcr_msg *message;
- int ret;
struct epoint_list *epointlist;
struct gsm_mncc *mncc;
- int channel;
/* copy setup infos to port */
memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
/* no instance */
- if (!p_m_g_lcr_gsm || p_m_g_lcr_gsm->mncc_lfd.fd < 0) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- add_trace("failure", NULL, "MS %s instance is unavailable", p_m_mISDNport->ifport->gsm_ms_name);
+ if (!p_g_lcr_gsm || p_g_lcr_gsm->mncc_lfd.fd < 0) {
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ add_trace("failure", NULL, "MS %s instance is unavailable", p_g_ms_name);
end_trace();
message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = 41;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
/* no number */
if (!p_dialinginfo.id[0]) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
add_trace("failure", NULL, "No dialed subscriber given.");
end_trace();
message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
+ trigger_work(&p_g_delete);
return;
}
-
- /* release if port is blocked */
- if (p_m_mISDNport->ifport->block) {
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- add_trace("failure", NULL, "Port blocked.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 27; // temp. unavail.
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
-
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- add_trace("failure", NULL, "No internal audio channel available.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 34;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_g_delete);
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
/* attach only if not already */
epointlist = p_epointlist;
epointlist_new(epoint_id);
/* creating l3id */
- l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
- p_m_g_callref = new_callref++;
- add_trace("callref", "new", "0x%x", p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
+ p_g_callref = new_callref++;
+ add_trace("callref", "new", "0x%x", p_g_callref);
end_trace();
- gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
- mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
+ gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+ mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
if (!strncasecmp(p_dialinginfo.id, "emerg", 5)) {
mncc->emergency = 1;
} else {
}
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+ send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
new_state(PORT_STATE_OUT_SETUP);
message_put(message);
new_state(PORT_STATE_OUT_PROCEEDING);
+
+ p_g_rtp_bridge = 0;
}
void Pgsm_ms::dtmf_statemachine(struct gsm_mncc *mncc)
{
struct gsm_mncc *dtmf;
- switch (p_m_g_dtmf_state) {
+ switch (p_g_dtmf_state) {
case DTMF_ST_SPACE:
case DTMF_ST_IDLE:
/* end of string */
- if (!p_m_g_dtmf[p_m_g_dtmf_index]) {
+ if (!p_g_dtmf[p_g_dtmf_index]) {
PDEBUG(DEBUG_GSM, "done with DTMF\n");
- p_m_g_dtmf_state = DTMF_ST_IDLE;
+ p_g_dtmf_state = DTMF_ST_IDLE;
return;
}
- gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_REQ, DIRECTION_OUT);
- dtmf = create_mncc(MNCC_START_DTMF_REQ, p_m_g_callref);
- dtmf->keypad = p_m_g_dtmf[p_m_g_dtmf_index++];
- p_m_g_dtmf_state = DTMF_ST_START;
+ gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_REQ, DIRECTION_OUT);
+ dtmf = create_mncc(MNCC_START_DTMF_REQ, p_g_callref);
+ dtmf->keypad = p_g_dtmf[p_g_dtmf_index++];
+ p_g_dtmf_state = DTMF_ST_START;
PDEBUG(DEBUG_GSM, "start DTMF (keypad %c)\n",
dtmf->keypad);
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
+ send_and_free_mncc(p_g_lcr_gsm, dtmf->msg_type, dtmf);
return;
case DTMF_ST_START:
if (mncc->msg_type != MNCC_START_DTMF_RSP) {
PDEBUG(DEBUG_GSM, "DTMF was rejected\n");
return;
}
- schedule_timer(&p_m_g_dtmf_timer, 0, 70 * 1000);
- p_m_g_dtmf_state = DTMF_ST_MARK;
+ schedule_timer(&p_g_dtmf_timer, 0, 70 * 1000);
+ p_g_dtmf_state = DTMF_ST_MARK;
PDEBUG(DEBUG_GSM, "DTMF is on\n");
break;
case DTMF_ST_MARK:
- gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_REQ, DIRECTION_OUT);
- dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_m_g_callref);
- p_m_g_dtmf_state = DTMF_ST_STOP;
+ gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_REQ, DIRECTION_OUT);
+ dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_g_callref);
+ p_g_dtmf_state = DTMF_ST_STOP;
end_trace();
- send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
+ send_and_free_mncc(p_g_lcr_gsm, dtmf->msg_type, dtmf);
return;
case DTMF_ST_STOP:
- schedule_timer(&p_m_g_dtmf_timer, 0, 120 * 1000);
- p_m_g_dtmf_state = DTMF_ST_SPACE;
+ schedule_timer(&p_g_dtmf_timer, 0, 120 * 1000);
+ p_g_dtmf_state = DTMF_ST_SPACE;
PDEBUG(DEBUG_GSM, "DTMF is off\n");
break;
}
return;
/* schedule */
- if (p_m_g_dtmf_state == DTMF_ST_IDLE) {
- p_m_g_dtmf_index = 0;
- p_m_g_dtmf[0] = '\0';
+ if (p_g_dtmf_state == DTMF_ST_IDLE) {
+ p_g_dtmf_index = 0;
+ p_g_dtmf[0] = '\0';
}
- SCCAT(p_m_g_dtmf, digit);
- if (p_m_g_dtmf_state == DTMF_ST_IDLE)
+ SCCAT(p_g_dtmf, digit);
+ if (p_g_dtmf_state == DTMF_ST_IDLE)
dtmf_statemachine(NULL);
}
continue;
/* schedule */
- if (p_m_g_dtmf_state == DTMF_ST_IDLE) {
- p_m_g_dtmf_index = 0;
- p_m_g_dtmf[0] = '\0';
+ if (p_g_dtmf_state == DTMF_ST_IDLE) {
+ p_g_dtmf_index = 0;
+ p_g_dtmf[0] = '\0';
}
- SCCAT(p_m_g_dtmf, digit);
- if (p_m_g_dtmf_state == DTMF_ST_IDLE)
+ SCCAT(p_g_dtmf, digit);
+ if (p_g_dtmf_state == DTMF_ST_IDLE)
dtmf_statemachine(NULL);
}
}
}
/* add a new GSM mobile instance */
-int gsm_ms_new(const char *name)
+int gsm_ms_new(struct interface *interface)
{
struct lcr_gsm *gsm_ms = gsm_ms_first, **gsm_ms_p = &gsm_ms_first;
gsm_ms = gsm_ms->gsm_ms_next;
}
- PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is created\n", name);
+ PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is created\n", interface->gsm_ms_name);
/* create gsm instance */
gsm_ms = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
+ gsm_ms->interface = interface;
gsm_ms->type = LCR_GSM_TYPE_MS;
- SCPY(gsm_ms->name, name);
+ SCPY(gsm_ms->name, interface->gsm_ms_name);
gsm_ms->sun.sun_family = AF_UNIX;
- SPRINT(gsm_ms->sun.sun_path, "/tmp/ms_mncc_%s", name);
+ SPRINT(gsm_ms->sun.sun_path, "/tmp/ms_mncc_%s", gsm_ms->name);
memset(&gsm_ms->socket_retry, 0, sizeof(gsm_ms->socket_retry));
add_timer(&gsm_ms->socket_retry, mncc_socket_retry_cb, gsm_ms, 0);
while(port) {
if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
pgsm_ms = (class Pgsm_ms *)port;
- if (pgsm_ms->p_m_g_lcr_gsm == gsm_ms && pgsm_ms->p_m_g_callref) {
+ if (pgsm_ms->p_g_lcr_gsm == gsm_ms && pgsm_ms->p_g_callref) {
struct gsm_mncc *rej;
- rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
+ rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_g_callref);
rej->fields |= MNCC_F_CAUSE;
rej->cause.coding = 3;
rej->cause.location = 1;
end_trace();
send_and_free_mncc(gsm_ms, rej->msg_type, rej);
pgsm_ms->new_state(PORT_STATE_RELEASE);
- trigger_work(&pgsm_ms->p_m_g_delete);
+ trigger_work(&pgsm_ms->p_g_delete);
}
}
}
class Pgsm_ms : public Pgsm
{
public:
- Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+ Pgsm_ms(int type, char *portname, struct port_settings *settings, struct interface *interface);
~Pgsm_ms();
- int p_m_g_dtmf_state;
- int p_m_g_dtmf_index;
- char p_m_g_dtmf[128];
- struct lcr_timer p_m_g_dtmf_timer;
+ char p_g_ms_name[32];
+ int p_g_dtmf_state;
+ int p_g_dtmf_index;
+ char p_g_dtmf[128];
+ struct lcr_timer p_g_dtmf_timer;
void dtmf_statemachine(struct gsm_mncc *mncc);
void setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
int gsm_ms_conf(struct gsm_conf *gsm_conf, char *conf_error);
int gsm_ms_exit(int rc);
int gsm_ms_init(void);
-int gsm_ms_new(const char *name);
+int gsm_ms_new(struct interface *interface);
int gsm_ms_delete(const char *name);
int message_ms(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
return(-1);
#else
- struct interface_port *ifport;
struct interface *searchif;
searchif = interface_newlist;
while(searchif) {
- ifport = searchif->ifport;
- while(ifport) {
- if (ifport->gsm_bs) {
- SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm BS side.\n", filename, line, ifport->portname);
- return(-1);
- }
- ifport = ifport->next;
+ if (searchif->gsm_bs) {
+ SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses gsm BS side.\n", filename, line, searchif->name);
+ return(-1);
}
searchif = searchif->next;
}
- /* set portname */
- if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
- return(-1);
-
/* goto end of chain again to set gsmflag */
- ifport = interface->ifport;
- while(ifport->next)
- ifport = ifport->next;
- ifport->gsm_bs = 1;
+ interface->gsm_bs = 1;
return(0);
#endif
SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
return(-1);
#else
- struct interface_port *ifport, *searchifport;
struct interface *searchif;
- /* set portname */
- if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
- return(-1);
-
- /* goto end of chain again to set gsmflag and socket */
- ifport = interface->ifport;
- while(ifport->next)
- ifport = ifport->next;
- ifport->gsm_ms = 1;
+ interface->gsm_ms = 1;
/* copy values */
if (!value || !value[0]) {
SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
return(-1);
}
- SCPY(ifport->gsm_ms_name, value);
+ SCPY(interface->gsm_ms_name, value);
/* check if name is used multiple times */
searchif = interface_newlist;
while(searchif) {
- searchifport = searchif->ifport;
- while(searchifport) {
- if (searchifport != ifport
- && !strcmp(searchifport->gsm_ms_name, ifport->gsm_ms_name)) {
- SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_name);
- return(-1);
- }
- searchifport = searchifport->next;
+ if (!strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
+ SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_ms_name, searchif->gsm_ms_name);
+ return(-1);
}
searchif = searchif->next;
}
#else
char *p;
- /* set portname */
- if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
- return(-1);
-
interface->sip = 1;
/* copy values */
return(0);
#endif
}
+static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ interface->rtp_bridge = 1;
+
+ return(0);
+}
static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
{
struct interface_port *ifport;
{"sip", &inter_sip, "<local IP> <remote IP>",
"Sets up SIP interface that represents one SIP endpoint.\n"
"Give SIP configuration file."},
+ {"rtp-bridge", &inter_rtp_bridge, "",
+ "Sets up SIP interface that represents one SIP endpoint.\n"
+ "Give SIP configuration file."},
{"nonotify", &inter_nonotify, "",
"Prevents sending notify messages to this interface. A call placed on hold will\n"
"Not affect the remote end (phone or telcom switch).\n"
void relink_interfaces(void)
{
struct mISDNport *mISDNport;
- struct interface *interface;
+ struct interface *interface, *temp;
struct interface_port *ifport;
+ int found;
- /* unlink all mISDNports */
- mISDNport = mISDNport_first;
- while(mISDNport) {
- if (mISDNport->ifport) {
- ifport = mISDNport->ifport;
+ interface = interface_first;
+ while(interface) {
+ found = 0;
+ temp = interface_newlist;
+ while(temp) {
+ if (!strcmp(temp->name, interface->name))
+ found = 1;
+ temp = temp->next;
+ }
+ if (!found) {
#ifdef WITH_GSM_MS
- if (ifport->gsm_ms)
- gsm_ms_delete(ifport->gsm_ms_name);
+ if (interface->gsm_ms)
+ gsm_ms_delete(interface->gsm_ms_name);
#endif
#ifdef WITH_GSM_BS
- if (ifport->gsm_bs)
+ if (interface->gsm_bs)
gsm_bs_exit(0);
#endif
#ifdef WITH_SIP
-#warning FIXME: get out of mISDNport
- if (ifport->interface->sip)
- sip_exit_inst(mISDNport->ifport->interface);
+ if (interface->sip)
+ sip_exit_inst(interface);
+#endif
+ }
+ interface = interface->next;
+ }
+
+ interface = interface_newlist;
+ while(interface) {
+ found = 0;
+ temp = interface_first;
+ while(temp) {
+ if (!strcmp(temp->name, interface->name))
+ found = 1;
+ temp = temp->next;
+ }
+ if (!found) {
+#ifdef WITH_GSM_MS
+ if (interface->gsm_ms)
+ gsm_ms_new(interface);
+#endif
+#ifdef WITH_GSM_BS
+ if (interface->gsm_bs)
+ gsm_bs_init(interface);
+#endif
+#ifdef WITH_SIP
+ if (interface->sip)
+ sip_init_inst(interface);
#endif
}
+ interface = interface->next;
+ }
+
+ /* unlink all mISDNports */
+ mISDNport = mISDNport_first;
+ while(mISDNport) {
mISDNport->ifport = NULL;
mISDNport = mISDNport->next;
}
set_defaults(ifport);
/* load static port instances */
mISDNport_static(mISDNport);
-#ifdef WITH_GSM_MS
- if (ifport->gsm_ms)
- gsm_ms_new(ifport->gsm_ms_name);
-#endif
-#ifdef WITH_GSM_BS
- if (ifport->gsm_bs)
- gsm_bs_init();
-#endif
-#ifdef WITH_SIP
- if (ifport->interface->sip)
- if (sip_init_inst(ifport->interface))
- ifport->block = 2; /* not available */
-#endif
} else {
ifport->block = 2; /* not available */
}
/* screen caller id
* out==0: incoming caller id, out==1: outgoing caller id
*/
-void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
+void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
{
char *msn1;
struct interface_msn *ifmsn;
struct interface_screen *ifscreen;
char suffix[64];
+ struct interface *interface = interface_first;
+
+ while (interface) {
+ if (!strcmp(interface->name, interface_name))
+ break;
+ interface = interface->next;
+ }
+ if (!interface)
+ return;
/* screen incoming caller id */
if (!out) {
int tespecial; /* special TE-mode behavior */
int l1hold; /* hold layer 1 (1=on, 0=off) */
int l2hold; /* hold layer 2 (1=force, -1=disable, 0=default) */
-#ifdef WITH_GSM_BS
- int gsm_bs; /* interface is an GSM BS interface */
-#endif
-#ifdef WITH_GSM_MS
- int gsm_ms; /* interface is an GSM MS interface */
- char gsm_ms_name[32]; /* name of ms */
-#endif
unsigned int ss5; /* set, if SS5 signalling enabled, also holds feature bits */
int remote; /* interface is a remote app interface */
char remote_app[32]; /* name of remote application */
char pipeline[256]; /* filter pipeline */
unsigned char bf_key[56]; /* filter blowfish */
int bf_len; /* filter length of blowfish */
+#ifdef WITH_GSM_BS
+ int gsm_bs; /* interface is an GSM BS interface */
+#endif
+#ifdef WITH_GSM_MS
+ int gsm_ms; /* interface is an GSM MS interface */
+ char gsm_ms_name[32]; /* name of ms */
+#endif
#ifdef WITH_SIP
int sip; /* interface is a SIP interface */
char sip_local_ip[16];
char sip_remote_ip[16];
void *sip_inst; /* sip instance */
#endif
+ int rtp_bridge; /* bridge RTP directly (for calls comming from interface) */
};
struct interface_param {
void relink_interfaces(void);
void load_port(struct interface_port *ifport);
void doc_interface(void);
-void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface);
+void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name);
/* show interface summary */
move(++line>1?line:1, 0);
color(white);
- if (m[i].u.i.block >= 2) {
+ if (m[i].u.i.portnum == -100) {
+ SPRINT(buffer, "%s %s", m[i].u.i.interface_name, (m[i].u.i.extension)?" exten":"");
+ addstr(buffer);
+ } else if (m[i].u.i.block >= 2) {
if (m[i].u.i.portnum < 0)
SPRINT(buffer, "%s (port ?: %s)%s", m[i].u.i.interface_name, m[i].u.i.portname, (m[i].u.i.extension)?" exten":"");
else
static int b_timer_timeout(struct lcr_timer *timer, void *instance, int i)
{
struct mISDNport *mISDNport = (struct mISDNport *)instance;
-puts("fires");
bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
unsigned int protocol, prop;
loop = 0;
-#ifdef WITH_GSM_BS
- loop |= ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
- loop |= ifport->gsm_ms;
-#endif
-#ifdef WITH_SIP
- loop |= ifport->interface->sip;
-#endif
//printf("%s == %s\n", ifport->portname, options.loopback_int);
if (!strcmp(ifport->portname, options.loopback_lcr))
loop = 1;
mISDNport->l1link = -1;
mISDNport->l2link = -1;
}
-#ifdef WITH_GSM_BS
- mISDNport->gsm_bs = ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
- mISDNport->gsm_ms = ifport->gsm_ms;
-#endif
mISDNport->isloopback = loop;
pmemuse++;
*mISDNportp = mISDNport;
int locally; /* local causes are sent as local causes not remote */
int los, ais, rdi, slip_rx, slip_tx;
- /* gsm */
-#ifdef WITH_GSM_BS
- int gsm_bs; /* this is the (only) GSM BS interface */
-#endif
-#ifdef WITH_GSM_MS
- int gsm_ms; /* this is an GSM MS interface */
-#endif
int lcr_sock; /* socket of loopback on LCR side */
int isloopback; /* will be set on open, in case it is a loopback if */
B_MODE_HDLC, /* hdlc data mode */
};
+/* rtp-info structure */
+struct rtp_info {
+ int payload_type;
+ unsigned int ip;
+ unsigned short port;
+};
+
/* call-info structure CALLER */
struct caller_info {
char id[32]; /* id of caller (user number) */
int screen; /* who provided the number */
char display[84]; /* display information */
char imsi[16]; /* IMSI for gsm terminated calls */
+ struct rtp_info rtpinfo; /* info about RTP peer */
};
/* call-info structure DISCONNECT */
struct progress_info {
int progress; /* progress indicator */
int location; /* progress location */
+ struct rtp_info rtpinfo; /* info about RTP peer */
};
/* call-info structure FACILITY */
struct redir_info redirinfo; /* info on redirection (to the calling user) */
struct capa_info capainfo; /* info on l2,l3 capability */
struct useruser_info useruser; /* user-user */
-// struct progress_info progress; /* info on call progress */
+ struct progress_info progress; /* info on call progress */
+ struct rtp_info rtpinfo; /* info about RTP peer */
char context[128]; /* asterisk context */
};
#define MNCC_FRAME_RECV 0x0201
#define MNCC_FRAME_DROP 0x0202
#define MNCC_LCHAN_MODIFY 0x0203
+#define MNCC_RTP_CREATE 0x0204
+#define MNCC_RTP_CONNECT 0x0205
+#define MNCC_RTP_FREE 0x0206
#define GSM_TCHF_FRAME 0x0300
#define GSM_TCHF_FRAME_EFR 0x0301
unsigned char data[0];
};
+struct gsm_mncc_rtp {
+ uint32_t msg_type;
+ uint32_t callref;
+ uint32_t ip;
+ uint16_t port;
+};
+
+
{
class Port *temp, **tempp;
- PDEBUG(DEBUG_PORT, "new port of type 0x%x, name '%s'\n", type, portname);
-
/* initialize object */
if (settings)
memcpy(&p_settings, settings, sizeof(struct port_settings));
*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 of type 0x%x, name '%s'\n", p_type, p_name);
+ 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);
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 */
#define PORT_CLASS_DSS1 0x1100
#define PORT_CLASS_DSS1_NT 0x1110
#define PORT_CLASS_DSS1_TE 0x1120
-#define PORT_CLASS_GSM 0x1200
-#define PORT_CLASS_GSM_BS 0x1210
-#define PORT_CLASS_GSM_MS 0x1220
#define PORT_CLASS_SS5 0x1300
#define PORT_CLASS_REMOTE 0x1400
-#define PORT_CLASS_SIP 0x1500
+#define PORT_CLASS_SIP 0x2000
+#define PORT_CLASS_GSM 0x3000
+#define PORT_CLASS_GSM_BS 0x3100
+#define PORT_CLASS_GSM_MS 0x3200
#define PORT_CLASS_MASK 0xf000
#define PORT_CLASS_mISDN_MASK 0xff00
#define PORT_CLASS_DSS1_MASK 0xfff0
-#define PORT_CLASS_GSM_MASK 0xfff0
+#define PORT_CLASS_GSM_MASK 0xff00
#define PORT_CLASS_DIR_MASK 0x000f
#define PORT_CLASS_DIR_IN 0x0001
#define PORT_CLASS_DIR_OUT 0x0002
#define PORT_TYPE_DSS1_TE_IN 0x1121
#define PORT_TYPE_DSS1_TE_OUT 0x1122
/* gsm */
-#define PORT_TYPE_GSM_BS_IN 0x1211
-#define PORT_TYPE_GSM_BS_OUT 0x1212
-#define PORT_TYPE_GSM_MS_IN 0x1221
-#define PORT_TYPE_GSM_MS_OUT 0x1222
+#define PORT_TYPE_GSM_BS_IN 0x3101
+#define PORT_TYPE_GSM_BS_OUT 0x3102
+#define PORT_TYPE_GSM_MS_IN 0x3201
+#define PORT_TYPE_GSM_MS_OUT 0x3202
/* ss5 */
#define PORT_TYPE_SS5_IN 0x1311
#define PORT_TYPE_SS5_OUT 0x1312
#define PORT_TYPE_REMOTE_IN 0x1411
#define PORT_TYPE_REMOTE_OUT 0x1412
/* SIP */
-#define PORT_TYPE_SIP_IN 0x1511
-#define PORT_TYPE_SIP_OUT 0x1512
+#define PORT_TYPE_SIP_IN 0x2001
+#define PORT_TYPE_SIP_OUT 0x2002
/* answering machine */
-#define PORT_TYPE_VBOX_OUT 0x3111
+#define PORT_TYPE_VBOX_OUT 0xf111
enum { /* states of call */
su_home_t sip_home[1];
struct sip_inst {
- struct interface *interface;
+ char interface_name[64];
+ char local_ip[16];
+ char remote_ip[16];
su_root_t *root;
nua_t *nua;
};
/*
* initialize SIP port
*/
-Psip::Psip(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, struct interface *interface) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Psip::Psip(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
{
- p_m_s_sip_inst = interface->sip_inst;
- memset(&p_m_s_delete, 0, sizeof(p_m_s_delete));
- add_work(&p_m_s_delete, delete_event, this, 0);
- p_m_s_handle = 0;
- p_m_s_magic = 0;
- memset(&p_m_s_rtp_fd, 0, sizeof(p_m_s_rtp_fd));
- memset(&p_m_s_rtcp_fd, 0, sizeof(p_m_s_rtcp_fd));
- memset(&p_m_s_rtp_sin_local, 0, sizeof(p_m_s_rtp_sin_local));
- memset(&p_m_s_rtcp_sin_local, 0, sizeof(p_m_s_rtcp_sin_local));
- memset(&p_m_s_rtp_sin_remote, 0, sizeof(p_m_s_rtp_sin_remote));
- memset(&p_m_s_rtcp_sin_remote, 0, sizeof(p_m_s_rtcp_sin_remote));
- p_m_s_rtp_ip_local = 0;
- p_m_s_rtp_ip_remote = 0;
- p_m_s_rtp_port_local = 0;
- p_m_s_rtp_port_remote = 0;
- p_m_s_b_sock = -1;
- p_m_s_b_index = -1;
- p_m_s_b_active = 0;
- p_m_s_rxpos = 0;
- p_m_s_rtp_tx_action = 0;
+ p_s_rtp_bridge = 0;
+ if (interface->rtp_bridge)
+ p_s_rtp_bridge = 1;
+ p_s_sip_inst = interface->sip_inst;
+ memset(&p_s_delete, 0, sizeof(p_s_delete));
+ add_work(&p_s_delete, delete_event, this, 0);
+ p_s_handle = 0;
+ p_s_magic = 0;
+ memset(&p_s_rtp_fd, 0, sizeof(p_s_rtp_fd));
+ memset(&p_s_rtcp_fd, 0, sizeof(p_s_rtcp_fd));
+ memset(&p_s_rtp_sin_local, 0, sizeof(p_s_rtp_sin_local));
+ memset(&p_s_rtcp_sin_local, 0, sizeof(p_s_rtcp_sin_local));
+ memset(&p_s_rtp_sin_remote, 0, sizeof(p_s_rtp_sin_remote));
+ memset(&p_s_rtcp_sin_remote, 0, sizeof(p_s_rtcp_sin_remote));
+ p_s_rtp_payload_type = 0;
+ p_s_rtp_ip_local = 0;
+ p_s_rtp_ip_remote = 0;
+ p_s_rtp_port_local = 0;
+ p_s_rtp_port_remote = 0;
+ p_s_b_sock = -1;
+ p_s_b_index = -1;
+ p_s_b_active = 0;
+ p_s_rxpos = 0;
+ p_s_rtp_tx_action = 0;
PDEBUG(DEBUG_SIP, "Created new Psip(%s).\n", portname);
}
{
PDEBUG(DEBUG_SIP, "Destroyed SIP process(%s).\n", p_name);
- del_work(&p_m_s_delete);
-
- /* close audio transfer socket */
- if (p_m_s_b_sock > -1)
- bchannel_close();
+ del_work(&p_s_delete);
rtp_close();
}
+const char *payload_type2name(uint8_t payload_type) {
+ switch (payload_type) {
+ case 0:
+ return "PCMU";
+ case 8:
+ return "PCMA";
+ case 3:
+ case 96:
+ case 97:
+ case 98:
+ return "GSM";
+ }
+
+ return "UKN";
+}
static void sip_trace_header(class Psip *sip, const char *message, int direction)
{
uint8_t *payload;
int payload_len;
int x_len;
+ unsigned char *from, *to;
+ int n;
if (len < 12) {
PDEBUG(DEBUG_SIP, "received RTP frame too short (len = %d)\n", len);
return 0;
}
- psip->bchannel_send(PH_DATA_REQ, 0, payload, payload_len);
+ n = payload_len;
+ from = payload;
+ to = payload;
+ while(n--)
+ *to++ = flip[*from++];
+ psip->bridge_tx(payload, payload_len);
return 0;
}
rtp_close();
return -EIO;
}
- p_m_s_rtp_fd.fd = rc;
- register_fd(&p_m_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
+ p_s_rtp_fd.fd = rc;
+ register_fd(&p_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!rc) {
rtp_close();
return -EIO;
}
- p_m_s_rtcp_fd.fd = rc;
- register_fd(&p_m_s_rtcp_fd, LCR_FD_READ, rtcp_sock_callback, this, 0);
+ p_s_rtcp_fd.fd = rc;
+ register_fd(&p_s_rtcp_fd, LCR_FD_READ, rtcp_sock_callback, this, 0);
/* bind socket */
ip = htonl(INADDR_ANY);
ia.s_addr = ip;
for (next_udp_port = next_udp_port % 0xffff;
next_udp_port < 0xffff; next_udp_port += 2) {
- rc = rtp_sub_socket_bind(p_m_s_rtp_fd.fd, &p_m_s_rtp_sin_local, ip, next_udp_port);
+ rc = rtp_sub_socket_bind(p_s_rtp_fd.fd, &p_s_rtp_sin_local, ip, next_udp_port);
if (rc != 0)
continue;
- rc = rtp_sub_socket_bind(p_m_s_rtcp_fd.fd, &p_m_s_rtcp_sin_local, ip, next_udp_port+1);
+ rc = rtp_sub_socket_bind(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, ip, next_udp_port+1);
if (rc == 0)
break;
}
rtp_close();
return rc;
}
- p_m_s_rtp_port_local = next_udp_port;
- p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_sin_local.sin_addr.s_addr);
- PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_m_s_rtp_ip_local, p_m_s_rtp_port_local);
- PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
+ p_s_rtp_port_local = next_udp_port;
+ p_s_rtp_ip_local = ntohl(p_s_rtp_sin_local.sin_addr.s_addr);
+ PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+ PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
- return p_m_s_rtp_port_local;
+ return p_s_rtp_port_local;
}
int Psip::rtp_connect(void)
int rc;
struct in_addr ia;
- ia.s_addr = htonl(p_m_s_rtp_ip_remote);
- PDEBUG(DEBUG_SIP, "rtp_connect(ip=%s, port=%u)\n", inet_ntoa(ia), p_m_s_rtp_port_remote);
+ ia.s_addr = htonl(p_s_rtp_ip_remote);
+ PDEBUG(DEBUG_SIP, "rtp_connect(ip=%s, port=%u)\n", inet_ntoa(ia), p_s_rtp_port_remote);
- rc = rtp_sub_socket_connect(p_m_s_rtp_fd.fd, &p_m_s_rtp_sin_local, &p_m_s_rtp_sin_remote, p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
+ rc = rtp_sub_socket_connect(p_s_rtp_fd.fd, &p_s_rtp_sin_local, &p_s_rtp_sin_remote, p_s_rtp_ip_remote, p_s_rtp_port_remote);
if (rc < 0)
return rc;
- rc = rtp_sub_socket_connect(p_m_s_rtcp_fd.fd, &p_m_s_rtcp_sin_local, &p_m_s_rtcp_sin_remote, p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote + 1);
+ rc = rtp_sub_socket_connect(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, &p_s_rtcp_sin_remote, p_s_rtp_ip_remote, p_s_rtp_port_remote + 1);
if (rc < 0)
return rc;
- p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_sin_local.sin_addr.s_addr);
- PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_m_s_rtp_ip_local, p_m_s_rtp_port_local);
- PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
- p_m_s_rtp_is_connected = 1;
+ p_s_rtp_ip_local = ntohl(p_s_rtp_sin_local.sin_addr.s_addr);
+ PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+ PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
+ p_s_rtp_is_connected = 1;
return 0;
}
void Psip::rtp_close(void)
{
- if (p_m_s_rtp_fd.fd > 0) {
- unregister_fd(&p_m_s_rtp_fd);
- close(p_m_s_rtp_fd.fd);
- p_m_s_rtp_fd.fd = 0;
+ if (p_s_rtp_fd.fd > 0) {
+ unregister_fd(&p_s_rtp_fd);
+ close(p_s_rtp_fd.fd);
+ p_s_rtp_fd.fd = 0;
}
- if (p_m_s_rtcp_fd.fd > 0) {
- unregister_fd(&p_m_s_rtcp_fd);
- close(p_m_s_rtcp_fd.fd);
- p_m_s_rtcp_fd.fd = 0;
+ if (p_s_rtcp_fd.fd > 0) {
+ unregister_fd(&p_s_rtcp_fd);
+ close(p_s_rtcp_fd.fd);
+ p_s_rtcp_fd.fd = 0;
}
- if (p_m_s_rtp_is_connected) {
+ if (p_s_rtp_is_connected) {
PDEBUG(DEBUG_SIP, "rtp closed\n");
- p_m_s_rtp_is_connected = 0;
+ p_s_rtp_is_connected = 0;
}
}
}
/* encode and send a rtp frame */
-int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type)
+int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_type)
{
struct rtp_hdr *rtph;
int payload_len;
int duration; /* in samples */
unsigned char buffer[256];
- if (!p_m_s_rtp_is_connected) {
+ if (!p_s_rtp_is_connected) {
/* drop silently */
return 0;
}
- if (!p_m_s_rtp_tx_action) {
+ if (!p_s_rtp_tx_action) {
/* initialize sequences */
- p_m_s_rtp_tx_action = 1;
- p_m_s_rtp_tx_ssrc = rand();
- p_m_s_rtp_tx_sequence = random();
- p_m_s_rtp_tx_timestamp = random();
- memset(&p_m_s_rtp_tx_last_tv, 0, sizeof(p_m_s_rtp_tx_last_tv));
+ p_s_rtp_tx_action = 1;
+ p_s_rtp_tx_ssrc = rand();
+ p_s_rtp_tx_sequence = random();
+ p_s_rtp_tx_timestamp = random();
+ memset(&p_s_rtp_tx_last_tv, 0, sizeof(p_s_rtp_tx_last_tv));
}
switch (payload_type) {
long int usec_diff, frame_diff;
gettimeofday(&tv, NULL);
- tv_difference(&tv_diff, &p_m_s_rtp_tx_last_tv, &tv);
- p_m_s_rtp_tx_last_tv = tv;
+ tv_difference(&tv_diff, &p_s_rtp_tx_last_tv, &tv);
+ p_s_rtp_tx_last_tv = tv;
usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec;
frame_diff = (usec_diff / 20000);
long int frame_diff_excess = frame_diff - 1;
PDEBUG(DEBUG_SIP, "Correcting frame difference of %ld frames\n", frame_diff_excess);
- p_m_s_rtp_tx_sequence += frame_diff_excess;
- p_m_s_rtp_tx_timestamp += frame_diff_excess * duration;
+ p_s_rtp_tx_sequence += frame_diff_excess;
+ p_s_rtp_tx_timestamp += frame_diff_excess * duration;
}
}
#endif
rtph->csrc_count = 0;
rtph->marker = 0;
rtph->payload_type = payload_type;
- rtph->sequence = htons(p_m_s_rtp_tx_sequence++);
- rtph->timestamp = htonl(p_m_s_rtp_tx_timestamp);
- p_m_s_rtp_tx_timestamp += duration;
- rtph->ssrc = htonl(p_m_s_rtp_tx_ssrc);
+ rtph->sequence = htons(p_s_rtp_tx_sequence++);
+ rtph->timestamp = htonl(p_s_rtp_tx_timestamp);
+ p_s_rtp_tx_timestamp += duration;
+ rtph->ssrc = htonl(p_s_rtp_tx_ssrc);
memcpy(buffer + sizeof(struct rtp_hdr), data, payload_len);
- if (p_m_s_rtp_fd.fd > 0) {
- len = write(p_m_s_rtp_fd.fd, &buffer, sizeof(struct rtp_hdr) + payload_len);
+ if (p_s_rtp_fd.fd > 0) {
+ len = write(p_s_rtp_fd.fd, &buffer, sizeof(struct rtp_hdr) + payload_len);
if (len != sizeof(struct rtp_hdr) + payload_len) {
PDEBUG(DEBUG_SIP, "write result=%d\n", len);
// rtp_close();
return 0;
}
-/*
- * bchannel handling
- */
-
-/* select free bchannel from loopback interface */
-int Psip::hunt_bchannel(void)
-{
- return loop_hunt_bchannel(this, p_m_mISDNport);
-}
-
-/* close SIP side bchannel */
-void Psip::bchannel_close(void)
-{
- if (p_m_s_b_sock > -1) {
- unregister_fd(&p_m_s_b_fd);
- close(p_m_s_b_sock);
- }
- p_m_s_b_sock = -1;
- p_m_s_b_index = -1;
- p_m_s_b_active = 0;
-}
-
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index);
-
-/* open external side bchannel */
-int Psip::bchannel_open(int index)
-{
- int ret;
- struct sockaddr_mISDN addr;
- struct mISDNhead act;
-
- if (p_m_s_b_sock > -1) {
- PERROR("Socket already created for index %d\n", index);
- return(-EIO);
- }
-
- /* open socket */
- ret = p_m_s_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
- if (ret < 0) {
- PERROR("Failed to open bchannel-socket for index %d\n", index);
- bchannel_close();
- return(ret);
- }
- memset(&p_m_s_b_fd, 0, sizeof(p_m_s_b_fd));
- p_m_s_b_fd.fd = p_m_s_b_sock;
- register_fd(&p_m_s_b_fd, LCR_FD_READ, b_handler, this, 0);
-
-
- /* bind socket to bchannel */
- addr.family = AF_ISDN;
- addr.dev = mISDNloop.port;
- addr.channel = index+1+(index>15);
- ret = bind(p_m_s_b_sock, (struct sockaddr *)&addr, sizeof(addr));
- if (ret < 0) {
- PERROR("Failed to bind bchannel-socket for index %d\n", index);
- bchannel_close();
- return(ret);
- }
- /* activate bchannel */
- PDEBUG(DEBUG_SIP, "Activating SIP side channel index %i.\n", index);
- act.prim = PH_ACTIVATE_REQ;
- act.id = 0;
- ret = sendto(p_m_s_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
- if (ret < 0) {
- PERROR("Failed to activate index %d\n", index);
- bchannel_close();
- return(ret);
- }
-
- p_m_s_b_index = index;
-
- return(0);
-}
-
-/* receive from bchannel */
-void Psip::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+/* receive from remote */
+int Psip::bridge_rx(unsigned char *data, int len)
{
/* write to rx buffer */
while(len--) {
- p_m_s_rxdata[p_m_s_rxpos++] = flip[*data++];
- if (p_m_s_rxpos == 160) {
- p_m_s_rxpos = 0;
+ p_s_rxdata[p_s_rxpos++] = flip[*data++];
+ if (p_s_rxpos == 160) {
+ p_s_rxpos = 0;
/* transmit data via rtp */
- rtp_send_frame(p_m_s_rxdata, 160, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW);
- }
- }
-}
-
-/* transmit to bchannel */
-void Psip::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
-{
- unsigned char buf[MISDN_HEADER_LEN+len];
- struct mISDNhead *hh = (struct mISDNhead *)buf;
- unsigned char *to = buf + MISDN_HEADER_LEN;
- int n = len;
- int ret;
-
- if (!p_m_s_b_active)
- return;
-
- /* make and send frame */
- hh->prim = prim;
- hh->id = 0;
- while(n--)
- *to++ = flip[*data++];
- ret = sendto(p_m_s_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
- if (ret <= 0)
- PERROR("Failed to send to socket index %d\n", p_m_s_b_index);
-}
-
-/* handle socket input */
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index)
-{
- class Psip *psip = (class Psip *)instance;
- int ret;
- unsigned char buffer[2048+MISDN_HEADER_LEN];
- struct mISDNhead *hh = (struct mISDNhead *)buffer;
-
- /* handle message from bchannel */
- if (psip->p_m_s_b_sock > -1) {
- ret = recv(psip->p_m_s_b_sock, buffer, sizeof(buffer), 0);
- if (ret >= (int)MISDN_HEADER_LEN) {
- switch(hh->prim) {
- /* we don't care about confirms, we use rx data to sync tx */
- case PH_DATA_CNF:
- break;
- /* we receive audio data, we respond to it AND we send tones */
- case PH_DATA_IND:
- psip->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
- break;
- case PH_ACTIVATE_IND:
- psip->p_m_s_b_active = 1;
- break;
- case PH_DEACTIVATE_IND:
- psip->p_m_s_b_active = 0;
- break;
- }
- } else {
- if (ret < 0 && errno != EWOULDBLOCK)
- PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
+ rtp_send_frame(p_s_rxdata, 160, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW);
}
}
struct in_addr ia;
struct lcr_msg *message;
- if (rtp_connect() < 0) {
- nua_cancel(p_m_s_handle, TAG_END());
- nua_handle_destroy(p_m_s_handle);
- p_m_s_handle = NULL;
- sip_trace_header(this, "CANCEL", DIRECTION_OUT);
- add_trace("reason", NULL, "failed to connect RTP/RTCP sockts");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 41;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return 0;
+ if (param->connectinfo.rtpinfo.port) {
+ PDEBUG(DEBUG_SIP, "RTP info given by remote, forward that\n");
+ p_s_rtp_bridge = 1;
+ p_s_rtp_payload_type = param->connectinfo.rtpinfo.payload_type;
+ p_s_rtp_ip_local = param->connectinfo.rtpinfo.ip;
+ p_s_rtp_port_local = param->connectinfo.rtpinfo.port;
+ PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+ PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
+ } else {
+ PDEBUG(DEBUG_SIP, "RTP info not given by remote, so we do our own RTP\n");
+ p_s_rtp_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
+ /* open local RTP peer (if not bridging) */
+ if (rtp_connect() < 0) {
+ nua_cancel(p_s_handle, TAG_END());
+ nua_handle_destroy(p_s_handle);
+ p_s_handle = NULL;
+ sip_trace_header(this, "CANCEL", DIRECTION_OUT);
+ add_trace("reason", NULL, "failed to connect RTP/RTCP sockts");
+ end_trace();
+ message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+ message->param.disconnectinfo.cause = 41;
+ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ message_put(message);
+ new_state(PORT_STATE_RELEASE);
+ trigger_work(&p_s_delete);
+ return 0;
+ }
}
- ia.s_addr = htonl(p_m_s_rtp_ip_local);
+
+ ia.s_addr = htonl(p_s_rtp_ip_local);
SPRINT(sdp_str,
"v=0\n"
"t=0 0\n"
"m=audio %d RTP/AVP %d\n"
"a=rtpmap:%d %s/8000\n"
- , inet_ntoa(ia), inet_ntoa(ia), p_m_s_rtp_port_local, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?"PCMA":"PCMU");
+ , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
- nua_respond(p_m_s_handle, SIP_200_OK,
+ nua_respond(p_s_handle, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
if (cause_str[0])
add_trace("cause", "value", "%d", cause);
end_trace();
- nua_cancel(p_m_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+ nua_cancel(p_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
break;
case PORT_STATE_IN_SETUP:
case PORT_STATE_IN_PROCEEDING:
add_trace("cause", "value", "%d", cause);
add_trace("respond", "value", "%d %s", status, status_text);
end_trace();
- nua_respond(p_m_s_handle, status, status_text, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
- nua_handle_destroy(p_m_s_handle);
- p_m_s_handle = NULL;
- trigger_work(&p_m_s_delete);
+ nua_respond(p_s_handle, status, status_text, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+ nua_handle_destroy(p_s_handle);
+ p_s_handle = NULL;
+ trigger_work(&p_s_delete);
break;
default:
PDEBUG(DEBUG_SIP, "RELEASE/DISCONNECT will perform nua_bye\n");
if (cause_str[0])
add_trace("cause", "value", "%d", cause);
end_trace();
- nua_bye(p_m_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+ nua_bye(p_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
}
if (message_id == MESSAGE_DISCONNECT) {
int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
{
- struct sip_inst *inst = (struct sip_inst *) p_m_s_sip_inst;
+ struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
char from[128];
char to[128];
- const char *local = inst->interface->sip_local_ip;
- const char *remote = inst->interface->sip_remote_ip;
+ const char *local = inst->local_ip;
+ const char *remote = inst->remote_ip;
char sdp_str[256];
struct in_addr ia;
struct epoint_list *epointlist;
sip_cseq_t *cseq = NULL;
- int ret;
- int channel;
PDEBUG(DEBUG_SIP, "Doing Setup (inst %p)\n", inst);
- /* release if port is blocked */
- if (p_m_mISDNport->ifport->block) {
- struct lcr_msg *message;
-
- sip_trace_header(this, "INVITE", DIRECTION_OUT);
- add_trace("failure", NULL, "Port blocked.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 27; // temp. unavail.
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return 0;
- }
-
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- struct lcr_msg *message;
-
- no_channel:
- sip_trace_header(this, "INVITE", DIRECTION_OUT);
- add_trace("failure", NULL, "No internal audio channel available.");
- end_trace();
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 34;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return 0;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
-
memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
- /* connect to remote RTP */
- if (rtp_open() < 0) {
- struct lcr_msg *message;
-
- PERROR("Failed to open RTP sockets\n");
- /* send release message to endpoit */
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 41;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return 0;
+ if (param->setup.rtpinfo.port) {
+ PDEBUG(DEBUG_SIP, "RTP info given by remote, forward that\n");
+ p_s_rtp_bridge = 1;
+ p_s_rtp_payload_type = param->setup.rtpinfo.payload_type;
+ p_s_rtp_ip_local = param->setup.rtpinfo.ip;
+ p_s_rtp_port_local = param->setup.rtpinfo.port;
+ PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+ PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
+ } else {
+ PDEBUG(DEBUG_SIP, "RTP info not given by remote, so we do our own RTP\n");
+ p_s_rtp_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
+
+ /* open local RTP peer (if not bridging) */
+ if (rtp_open() < 0) {
+ struct lcr_msg *message;
+
+ PERROR("Failed to open RTP sockets\n");
+ /* send release message to endpoit */
+ message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+ message->param.disconnectinfo.cause = 41;
+ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ message_put(message);
+ new_state(PORT_STATE_RELEASE);
+ trigger_work(&p_s_delete);
+ return 0;
+ }
}
SPRINT(from, "sip:%s@%s", param->setup.callerinfo.id, local);
SPRINT(to, "sip:%s@%s", param->setup.dialinginfo.id, remote);
sip_trace_header(this, "INVITE", DIRECTION_OUT);
add_trace("from", "uri", "%s", from);
add_trace("to", "uri", "%s", to);
- add_trace("rtp", "port", "%d,%d", p_m_s_rtp_port_local, p_m_s_rtp_port_local + 1);
+ add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
end_trace();
- p_m_s_handle = nua_handle(inst->nua, NULL, TAG_END());
- if (!p_m_s_handle) {
+ p_s_handle = nua_handle(inst->nua, NULL, TAG_END());
+ if (!p_s_handle) {
struct lcr_msg *message;
PERROR("Failed to create handle\n");
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
return 0;
}
/* apply handle */
sip_trace_header(this, "NEW handle", DIRECTION_IN);
- add_trace("handle", "new", "0x%x", p_m_s_handle);
+ add_trace("handle", "new", "0x%x", p_s_handle);
end_trace();
- inet_pton(AF_INET, local, &p_m_s_rtp_ip_local);
- p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_ip_local);
- ia.s_addr = htonl(p_m_s_rtp_ip_local);
+ if (!p_s_rtp_ip_local) {
+ PDEBUG(DEBUG_SIP, "RTP local IP not known, so we use our local SIP ip %s\n", local);
+ inet_pton(AF_INET, local, &p_s_rtp_ip_local);
+ p_s_rtp_ip_local = ntohl(p_s_rtp_ip_local);
+ }
+ ia.s_addr = htonl(p_s_rtp_ip_local);
SPRINT(sdp_str,
"v=0\n"
"o=LCR-Sofia-SIP 0 0 IN IP4 %s\n"
"t=0 0\n"
"m=audio %d RTP/AVP %d\n"
"a=rtpmap:%d %s/8000\n"
- , inet_ntoa(ia), inet_ntoa(ia), p_m_s_rtp_port_local, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?"PCMA":"PCMU");
+ , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
PDEBUG(DEBUG_SIP, "Using SDP for invite: %s\n", sdp_str);
// cseq = sip_cseq_create(sip_home, 123, SIP_METHOD_INVITE);
- nua_invite(p_m_s_handle,
+ nua_invite(p_s_handle,
TAG_IF(from[0], SIPTAG_FROM_STR(from)),
TAG_IF(to[0], SIPTAG_TO_STR(to)),
TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
return 0;
}
+int Psip::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
+{
+// char sdp_str[256];
+// struct in_addr ia;
+
+ switch (param->notifyinfo.notify) {
+ case INFO_NOTIFY_REMOTE_HOLD:
+#if 0
+ SPRINT(sdp_str,
+ "v=0\n"
+ "o=LCR-Sofia-SIP 0 0 IN IP4 0.0.0.0\n"
+ "s=SIP Call\n"
+ "c=IN IP4 0.0.0.0\n"
+ "t=0 0\n"
+ );
+ PDEBUG(DEBUG_SIP, "Using SDP for hold: %s\n", sdp_str);
+ nua_info(p_s_handle,
+// TAG_IF(from[0], SIPTAG_FROM_STR(from)),
+// TAG_IF(to[0], SIPTAG_TO_STR(to)),
+// TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
+ NUTAG_MEDIA_ENABLE(0),
+ SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+ SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+#endif
+ break;
+ case INFO_NOTIFY_REMOTE_RETRIEVAL:
+#if 0
+ ia.s_addr = htonl(p_s_rtp_ip_local);
+ SPRINT(sdp_str,
+ "v=0\n"
+ "o=LCR-Sofia-SIP 0 0 IN IP4 %s\n"
+ "s=SIP Call\n"
+ "c=IN IP4 %s\n"
+ "t=0 0\n"
+ "m=audio %d RTP/AVP %d\n"
+ "a=rtpmap:%d %s/8000\n"
+ , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
+ PDEBUG(DEBUG_SIP, "Using SDP for rertieve: %s\n", sdp_str);
+ nua_info(p_s_handle,
+// TAG_IF(from[0], SIPTAG_FROM_STR(from)),
+// TAG_IF(to[0], SIPTAG_TO_STR(to)),
+// TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
+ NUTAG_MEDIA_ENABLE(0),
+ SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+ SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+#endif
+ break;
+ }
+
+ return 0;
+}
+
+int Psip::message_dtmf(unsigned int epoint_id, int message_id, union parameter *param)
+{
+ char dtmf_str[64];
+
+ /* prepare DTMF info payload */
+ SPRINT(dtmf_str,
+ "Signal=%c\n"
+ "Duration=160\n"
+ , param->dtmf);
+
+ /* start invite to handle DTMF */
+ nua_info(p_s_handle,
+ NUTAG_MEDIA_ENABLE(0),
+ SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"),
+ SIPTAG_PAYLOAD_STR(dtmf_str), TAG_END());
+
+ return 0;
+}
+
int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
{
class Endpoint *epoint;
- if (PmISDN::message_epoint(epoint_id, message_id, param))
+ if (Port::message_epoint(epoint_id, message_id, param))
return 1;
epoint = find_epoint_id(epoint_id);
if (p_state != PORT_STATE_IN_SETUP
&& p_state != PORT_STATE_IN_PROCEEDING)
return 0;
- nua_respond(p_m_s_handle, SIP_180_RINGING, TAG_END());
+ nua_respond(p_s_handle, SIP_180_RINGING, TAG_END());
sip_trace_header(this, "RESPOND", DIRECTION_OUT);
add_trace("respond", "value", "180 Ringing");
end_trace();
message_setup(epoint_id, message_id, param);
return 1;
+ case MESSAGE_DTMF: /* DTMF info to be transmitted via INFO transaction */
+ if (p_state == PORT_STATE_CONNECT)
+ message_dtmf(epoint_id, message_id, param);
+ case MESSAGE_NOTIFY: /* notification about remote hold/retrieve */
+ if (p_state == PORT_STATE_CONNECT)
+ message_notify(epoint_id, message_id, param);
+ return(1);
+
default:
PDEBUG(DEBUG_SIP, "PORT(%s) SP port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
}
return 0;
}
-int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
+int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t payload_type)
{
int codec_supported = 0;
conn = m->m_connections;
PDEBUG(DEBUG_SIP, "CONN: address:'%s'\n", conn->c_address);
inet_pton(AF_INET, conn->c_address, ip);
- *ip = ntohl(p_m_s_rtp_ip_remote);
+ *ip = ntohl(p_s_rtp_ip_remote);
} else {
char *p = sip->sip_payload->pl_data;
char addr[16];
if ((p = strchr(addr, '\r'))) *p = '\0';
PDEBUG(DEBUG_SIP, "CONN: address:'%s'\n", addr);
inet_pton(AF_INET, addr, ip);
- *ip = ntohl(p_m_s_rtp_ip_remote);
+ *ip = ntohl(p_s_rtp_ip_remote);
}
for (map = m->m_rtpmaps; map; map = map->rm_next) {
- PDEBUG(DEBUG_SIP, "RTPMAP: coding:'%s' rate='%d'\n", map->rm_encoding, map->rm_rate);
- if (!strcmp(map->rm_encoding, (options.law=='a')?"PCMA":"PCMU") && map->rm_rate == 8000) {
+ PDEBUG(DEBUG_SIP, "RTPMAP: coding:'%s' rate='%d' pt='%d'\n", map->rm_encoding, map->rm_rate, map->rm_pt);
+ if (map->rm_pt == payload_type) {
PDEBUG(DEBUG_SIP, "supported codec found\n");
codec_supported = 1;
goto done_codec;
void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
{
+ struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
const char *from = "", *to = "";
int ret;
class Endpoint *epoint;
struct lcr_msg *message;
- int channel;
+ uint8_t payload_type;
if (sip->sip_from && sip->sip_from->a_url)
from = sip->sip_from->a_url->url_user;
to = sip->sip_to->a_url->url_user;
PDEBUG(DEBUG_SIP, "invite received (%s->%s)\n", from, to);
- ret = parse_sdp(sip, &p_m_s_rtp_ip_remote, &p_m_s_rtp_port_remote);
+ if (p_s_rtp_bridge)
+ payload_type = 3; // FIXME: use list and forward list to remote side
+ else
+ payload_type = (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW;
+ ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_type);
if (ret) {
if (ret == 400)
nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END());
else
nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, TAG_END());
nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
sip_trace_header(this, "RESPOND", DIRECTION_OUT);
if (ret == 400)
add_trace("respond", "value", "415 Unsupported Media");
add_trace("reason", NULL, "offered codec does not match");
end_trace();
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
return;
}
- /* connect to remote RTP */
- if (rtp_open() < 0) {
+ /* open local RTP peer (if not bridging) */
+ if (!p_s_rtp_bridge && rtp_open() < 0) {
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
sip_trace_header(this, "RESPOND", DIRECTION_OUT);
add_trace("respond", "value", "500 Internal Server Error");
add_trace("reason", NULL, "failed to open RTP/RTCP sockts");
end_trace();
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
return;
}
/* apply handle */
sip_trace_header(this, "NEW handle", DIRECTION_IN);
add_trace("handle", "new", "0x%x", nh);
- p_m_s_handle = nh;
+ p_s_handle = nh;
end_trace();
- /* if blocked, release call */
- if (p_m_mISDNport->ifport->block) {
- nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, TAG_END());
- nua_handle_destroy(nh);
- p_m_s_handle = NULL;
- sip_trace_header(this, "RESPOND", DIRECTION_OUT);
- add_trace("respond", "value", "503 Service Unavailable");
- add_trace("reason", NULL, "port is blocked");
- end_trace();
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return;
- }
sip_trace_header(this, "INVITE", DIRECTION_IN);
- add_trace("RTP", "port", "%d", p_m_s_rtp_port_remote);
+ add_trace("RTP", "port", "%d", p_s_rtp_port_remote);
/* caller information */
if (!from[0]) {
p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
SCPY(p_callerinfo.id, from);
add_trace("calling", "number", "%s", from);
}
- p_callerinfo.isdn_port = p_m_portnum;
- SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+ SCPY(p_callerinfo.interface, inst->interface_name);
/* dialing information */
if (to[0]) {
p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
end_trace();
- /* hunt channel */
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
-
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- nua_respond(nh, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());
- nua_handle_destroy(nh);
- p_m_s_handle = NULL;
- sip_trace_header(this, "RESPOND", DIRECTION_OUT);
- add_trace("respond", "value", "480 Temporarily Unavailable");
- add_trace("reason", NULL, "no channel");
- end_trace();
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
- if (bchannel_open(p_m_b_index))
- goto no_channel;
-
/* create endpoint */
if (p_epointlist)
FATAL("Incoming call but already got an endpoint.\n");
/* send setup message to endpoit */
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
- message->param.setup.isdn_port = p_m_portnum;
message->param.setup.port_type = p_type;
// message->param.setup.dtmf = 0;
memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
// SCPY((char *)message->param.setup.useruser.data, useruser.info);
// message->param.setup.useruser.len = strlen(mncc->useruser.info);
// message->param.setup.useruser.protocol = mncc->useruser.proto;
+ if (p_s_rtp_bridge) {
+ PDEBUG(DEBUG_SIP, "sending setup with RTP info\n");
+ message->param.setup.rtpinfo.payload_type = payload_type;
+ message->param.setup.rtpinfo.ip = p_s_rtp_ip_remote;
+ message->param.setup.rtpinfo.port = p_s_rtp_port_remote;
+ }
message_put(message);
}
add_trace("respond", "value", "200 OK");
end_trace();
// nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
rtp_close();
free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
void Psip::i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
end_trace();
nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
rtp_close();
free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
void Psip::r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
PDEBUG(DEBUG_SIP, "bye response received\n");
nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
rtp_close();
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
void Psip::r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
PDEBUG(DEBUG_SIP, "cancel response received\n");
nua_handle_destroy(nh);
- p_m_s_handle = NULL;
+ p_s_handle = NULL;
rtp_close();
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
add_trace("respond", "value", "%d", status);
end_trace();
- /* process 1xx */
- switch (status) {
- case 100:
- PDEBUG(DEBUG_SIP, "do proceeding\n");
- new_state(PORT_STATE_OUT_PROCEEDING);
- message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
- message_put(message);
- return;
- case 180:
- PDEBUG(DEBUG_SIP, "do alerting\n");
- new_state(PORT_STATE_OUT_ALERTING);
- message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
- message_put(message);
- return;
- default:
- if (status < 100 || status > 199)
- break;
- PDEBUG(DEBUG_SIP, "skipping 1xx message\n");
-
- return;
- }
-
- /* process 2xx */
- if (status >= 200 && status <= 299) {
+ /* connect audio */
+ if (status == 183 || (status >= 200 && status <= 299)) {
int ret;
+ uint8_t payload_type;
- ret = parse_sdp(sip, &p_m_s_rtp_ip_remote, &p_m_s_rtp_port_remote);
+ if (p_s_rtp_bridge)
+ payload_type = p_s_rtp_payload_type;
+ else
+ payload_type = (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW;
+ ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_type);
if (ret) {
if (ret == 400)
nua_cancel(nh, TAG_END());
goto release_with_cause;
}
- /* connect to remote RTP */
- if (rtp_connect() < 0) {
+ /* connect to remote RTP (if not bridging) */
+ if (!p_s_rtp_bridge && rtp_connect() < 0) {
nua_cancel(nh, TAG_END());
sip_trace_header(this, "CANCEL", DIRECTION_OUT);
add_trace("reason", NULL, "failed to open RTP/RTCP sockts");
location = LOCATION_PRIVATE_LOCAL;
goto release_with_cause;
}
+ }
+
+ /* process 1xx */
+ switch (status) {
+ case 100:
+ PDEBUG(DEBUG_SIP, "do proceeding\n");
+ new_state(PORT_STATE_OUT_PROCEEDING);
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
+ message_put(message);
+ return;
+ case 180:
+ PDEBUG(DEBUG_SIP, "do alerting\n");
+ new_state(PORT_STATE_OUT_ALERTING);
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
+ message_put(message);
+ return;
+ case 183:
+ PDEBUG(DEBUG_SIP, "do progress\n");
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROGRESS);
+ message->param.progressinfo.progress = 8;
+ message->param.progressinfo.location = 10;
+ if (p_s_rtp_bridge) {
+ message->param.progressinfo.rtpinfo.payload_type = p_s_rtp_payload_type;
+ message->param.progressinfo.rtpinfo.ip = p_s_rtp_ip_remote;
+ message->param.progressinfo.rtpinfo.port = p_s_rtp_port_remote;
+ }
+ message_put(message);
+ return;
+ default:
+ if (status < 100 || status > 199)
+ break;
+ PDEBUG(DEBUG_SIP, "skipping 1xx message\n");
+ return;
+ }
+
+ /* process 2xx */
+ if (status >= 200 && status <= 299) {
PDEBUG(DEBUG_SIP, "do connect\n");
nua_ack(nh, TAG_END());
new_state(PORT_STATE_CONNECT);
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
+ if (p_s_rtp_bridge) {
+ message->param.connectinfo.rtpinfo.payload_type = p_s_rtp_payload_type;
+ message->param.connectinfo.rtpinfo.ip = p_s_rtp_ip_remote;
+ message->param.connectinfo.rtpinfo.port = p_s_rtp_port_remote;
+ }
message_put(message);
-
return;
}
-
cause = status2cause(status);
location = LOCATION_BEYOND;
rtp_close();
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
static void sip_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
if (event == nua_i_invite)
{
char name[64];
+ struct interface *interface = interface_first;
+
/* create call instance */
- SPRINT(name, "%s-%d-in", inst->interface->name, 0);
- if (!(psip = new Psip(PORT_TYPE_SIP_IN, (inst->interface->ifport) ? inst->interface->ifport->mISDNport : NULL, name, NULL, 0, 0, B_MODE_TRANSPARENT, inst->interface)))
+ SPRINT(name, "%s-%d-in", inst->interface_name, 0);
+ while (interface) {
+ if (!strcmp(interface->name, inst->interface_name))
+ break;
+ interface = interface->next;
+ }
+ if (!interface) {
+ PERROR("Cannot find interface %s.\n", inst->interface_name);
+ return;
+ }
+ if (!(psip = new Psip(PORT_TYPE_SIP_IN, name, NULL, interface)))
FATAL("Cannot create Port instance.\n");
} else {
port = port_first;
while(port) {
if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_SIP) {
psip = (class Psip *)port;
- if (psip->p_m_s_handle == nh) {
+ if (psip->p_s_handle == nh) {
break;
}
}
sip_trace_header(this, "RTP terminated", DIRECTION_IN);
end_trace();
- nua_handle_destroy(p_m_s_handle);
- p_m_s_handle = NULL;
+ nua_handle_destroy(p_s_handle);
+ p_s_handle = NULL;
while(p_epointlist) {
/* send setup message to endpoit */
free_epointlist(p_epointlist);
}
new_state(PORT_STATE_RELEASE);
- trigger_work(&p_m_s_delete);
+ trigger_work(&p_s_delete);
}
int sip_init_inst(struct interface *interface)
struct sip_inst *inst = (struct sip_inst *) MALLOC(sizeof(*inst));
interface->sip_inst = inst;
- inst->interface = interface;
+ SCPY(inst->interface_name, interface->name);
+ SCPY(inst->local_ip, interface->sip_local_ip);
+ SCPY(inst->remote_ip, interface->sip_remote_ip);
/* init root object */
inst->root = su_root_create(inst);
#include <sofia-sip/nua.h>
/* SIP port class */
-class Psip : public PmISDN
+class Psip : public Port
{
public:
- Psip(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, struct interface *interface);
+ Psip(int type, char *portname, struct port_settings *settings, struct interface *interface);
~Psip();
int message_epoint(unsigned int epoint_id, int message, union parameter *param);
int message_connect(unsigned int epoint_id, int message, union parameter *param);
int message_release(unsigned int epoint_id, int message, union parameter *param);
int message_setup(unsigned int epoint_id, int message, union parameter *param);
+ int message_notify(unsigned int epoint_id, int message, union parameter *param);
+ int message_dtmf(unsigned int epoint_id, int message, union parameter *param);
void i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
void i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
void i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
void r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
void r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
void r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
- void *p_m_s_sip_inst;
- struct lcr_work p_m_s_delete;
- nua_handle_t *p_m_s_handle;
- nua_magic_t *p_m_s_magic;
- unsigned short p_m_s_rtp_port_local;
- unsigned short p_m_s_rtp_port_remote;
- unsigned int p_m_s_rtp_ip_local;
- unsigned int p_m_s_rtp_ip_remote;
- struct sockaddr_in p_m_s_rtp_sin_local;
- struct sockaddr_in p_m_s_rtp_sin_remote;
- struct sockaddr_in p_m_s_rtcp_sin_local;
- struct sockaddr_in p_m_s_rtcp_sin_remote;
- struct lcr_fd p_m_s_rtp_fd;
- struct lcr_fd p_m_s_rtcp_fd;
- int p_m_s_rtp_is_connected; /* if RTP session is connected, so we may send frames */
- int p_m_s_rtp_tx_action;
- uint16_t p_m_s_rtp_tx_sequence;
- uint32_t p_m_s_rtp_tx_timestamp;
- uint32_t p_m_s_rtp_tx_ssrc;
- struct timeval p_m_s_rtp_tx_last_tv;
+ void *p_s_sip_inst;
+ struct lcr_work p_s_delete;
+ nua_handle_t *p_s_handle;
+ nua_magic_t *p_s_magic;
+ int p_s_rtp_bridge; /* bridge RTP instead of having a local RTP peer */
+ uint8_t p_s_rtp_payload_type;
+ unsigned short p_s_rtp_port_local;
+ unsigned short p_s_rtp_port_remote;
+ unsigned int p_s_rtp_ip_local;
+ unsigned int p_s_rtp_ip_remote;
+ struct sockaddr_in p_s_rtp_sin_local;
+ struct sockaddr_in p_s_rtp_sin_remote;
+ struct sockaddr_in p_s_rtcp_sin_local;
+ struct sockaddr_in p_s_rtcp_sin_remote;
+ struct lcr_fd p_s_rtp_fd;
+ struct lcr_fd p_s_rtcp_fd;
+ int p_s_rtp_is_connected; /* if RTP session is connected, so we may send frames */
+ int p_s_rtp_tx_action;
+ uint16_t p_s_rtp_tx_sequence;
+ uint32_t p_s_rtp_tx_timestamp;
+ uint32_t p_s_rtp_tx_ssrc;
+ struct timeval p_s_rtp_tx_last_tv;
int rtp_open(void);
int rtp_connect(void);
void rtp_close(void);
- int rtp_send_frame(unsigned char *data, unsigned int len, int payload_type);
- int p_m_s_b_sock; /* SIP bchannel socket */
- struct lcr_fd p_m_s_b_fd; /* event node */
- int p_m_s_b_index; /* SIP bchannel socket index to use */
- int p_m_s_b_active; /* SIP bchannel socket is activated */
- unsigned char p_m_s_rxdata[160]; /* receive audio buffer */
- int p_m_s_rxpos; /* position in audio buffer 0..159 */
- int hunt_bchannel(void);
- void bchannel_close(void);
- int bchannel_open(int);
- void bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len);
- void bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len);
- int parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port);
+ int rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_type);
+ int p_s_b_sock; /* SIP bchannel socket */
+ struct lcr_fd p_s_b_fd; /* event node */
+ int p_s_b_index; /* SIP bchannel socket index to use */
+ int p_s_b_active; /* SIP bchannel socket is activated */
+ unsigned char p_s_rxdata[160]; /* receive audio buffer */
+ int p_s_rxpos; /* position in audio buffer 0..159 */
+ int bridge_rx(unsigned char *data, int len);
+ int parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t payload_type);
void rtp_shutdown(void);
};
interface = interface_first;
while(interface) {
ifport = interface->ifport;
+ if (!ifport)
+ i++;
while(ifport) {
i++;
ifport = ifport->next;
num = 0;
while(interface) {
ifport = interface->ifport;
+ if (!ifport) {
+ /* message */
+ response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
+ /* interface */
+ SCPY(response->am[num].u.i.interface_name, interface->name);
+ /* portnum */
+ response->am[num].u.i.portnum = -100; /* indicate: no ifport */
+ /* iftype */
+ response->am[num].u.i.extension = interface->extension;
+ /* block */
+ num++;
+ }
while(ifport) {
/* message */
response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
/* screen outgoing caller id */
- do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
- do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
+ do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name);
+ do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name);
/* parse dial string */
dash = 0; /* dash must be used next time */