unsigned char flip[256];
+int any_sip_interface = 0;
+
//pthread_mutex_t mutex_msg;
su_home_t sip_home[1];
struct sip_inst {
char interface_name[64];
- char local_ip[16];
- char remote_ip[16];
+ char local_peer[32];
+ char remote_peer[32];
su_root_t *root;
nua_t *nua;
};
/*
* initialize SIP port
*/
-Psip::Psip(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
+Psip::Psip(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings, interface)
{
p_s_rtp_bridge = 0;
if (interface->rtp_bridge)
p_s_rtp_tx_action = 0;
PDEBUG(DEBUG_SIP, "Created new Psip(%s).\n", portname);
+ if (!p_s_sip_inst)
+ FATAL("No SIP instance for interface\n");
}
rtp_close();
}
-const char *media_type2name(uint8_t media_type) {
+static const char *media_type2name(uint8_t media_type) {
switch (media_type) {
case MEDIA_TYPE_ULAW:
return "PCMU";
return 0;
}
+ /* record audio */
+ if (psip->p_record)
+ psip->record(payload, payload_len, 0); // from down
+ if (psip->p_tap)
+ psip->tap(payload, payload_len, 0); // from down
+
n = payload_len;
from = payload;
to = payload;
+ if (psip->p_echotest) {
+ /* echo rtp data we just received */
+ psip->rtp_send_frame(from, n, (options.law=='a')?PAYLOAD_TYPE_ALAW:PAYLOAD_TYPE_ULAW);
+ return 0;
+ }
while(n--)
*to++ = flip[*from++];
psip->bridge_tx(payload, payload_len);
// psip->rtp_shutdown();
return len;
}
- rc = rtp_decode(psip, buffer, len);
+ if (psip->p_s_rtp_is_connected)
+ rc = rtp_decode(psip, buffer, len);
}
return rc;
}
#define RTP_PORT_BASE 30000
-static unsigned int next_udp_port = RTP_PORT_BASE;
+#define RTP_PORT_MAX 39998
+static unsigned short next_udp_port = RTP_PORT_BASE;
static int rtp_sub_socket_bind(int fd, struct sockaddr_in *sin_local, uint32_t ip, uint16_t port)
{
int Psip::rtp_open(void)
{
- int rc;
+ int rc, rc2;
struct in_addr ia;
unsigned int ip;
+ unsigned short start_port;
/* create socket */
rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (!rc) {
+ if (rc < 0) {
rtp_close();
return -EIO;
}
register_fd(&p_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (!rc) {
+ if (rc < 0) {
rtp_close();
return -EIO;
}
/* 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) {
+ start_port = next_udp_port;
+ while (1) {
rc = rtp_sub_socket_bind(p_s_rtp_fd.fd, &p_s_rtp_sin_local, ip, next_udp_port);
if (rc != 0)
- continue;
+ goto try_next_port;
- rc = rtp_sub_socket_bind(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, ip, next_udp_port+1);
- if (rc == 0)
+ rc = rtp_sub_socket_bind(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, ip, next_udp_port + 1);
+ if (rc == 0) {
+ p_s_rtp_port_local = next_udp_port;
+ next_udp_port = (next_udp_port + 2 > RTP_PORT_MAX) ? RTP_PORT_BASE : next_udp_port + 2;
break;
+ }
+ /* reopen rtp socket and try again with next udp port */
+ unregister_fd(&p_s_rtp_fd);
+ close(p_s_rtp_fd.fd);
+ p_s_rtp_fd.fd = 0;
+ rc2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (rc2 < 0) {
+ rtp_close();
+ return -EIO;
+ }
+ p_s_rtp_fd.fd = rc2;
+ register_fd(&p_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
+
+try_next_port:
+ next_udp_port = (next_udp_port + 2 > RTP_PORT_MAX) ? RTP_PORT_BASE : next_udp_port + 2;
+ if (next_udp_port == start_port)
+ break;
+ /* we must use rc2, in order to preserve rc */
}
if (rc < 0) {
PDEBUG(DEBUG_SIP, "failed to find port\n");
rtp_close();
return rc;
}
- 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);
int duration; /* in samples */
unsigned char buffer[256];
+ /* record audio */
+ if (p_record)
+ record(data, len, 1); // from up
+ if (p_tap)
+ tap(data, len, 1); // from up
+
if (!p_s_rtp_is_connected) {
/* drop silently */
return 0;
struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
char from[128];
char to[128];
- const char *local = inst->local_ip;
- const char *remote = inst->remote_ip;
+ const char *local = inst->local_peer;
+ char local_ip[16];
+ const char *remote = inst->remote_peer;
char sdp_str[512], pt_str[32];
struct in_addr ia;
struct epoint_list *epointlist;
end_trace();
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);
+ char *p;
+
+ /* extract IP from local peer */
+ SCPY(local_ip, local);
+ p = strchr(local_ip, ':');
+ if (p)
+ *p = '\0';
+ PDEBUG(DEBUG_SIP, "RTP local IP not known, so we use our local SIP ip %s\n", local_ip);
+ inet_pton(AF_INET, local_ip, &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);
int sip_init_inst(struct interface *interface)
{
struct sip_inst *inst = (struct sip_inst *) MALLOC(sizeof(*inst));
+ char local[64];
interface->sip_inst = inst;
SCPY(inst->interface_name, interface->name);
- SCPY(inst->local_ip, interface->sip_local_ip);
- SCPY(inst->remote_ip, interface->sip_remote_ip);
+ SCPY(inst->local_peer, interface->sip_local_peer);
+ SCPY(inst->remote_peer, interface->sip_remote_peer);
/* init root object */
inst->root = su_root_create(inst);
return -EINVAL;
}
- inst->nua = nua_create(inst->root, sip_callback, inst, TAG_NULL());
+ SPRINT(local, "sip:%s",inst->local_peer);
+ if (!strchr(inst->local_peer, ':'))
+ SCAT(local, ":5060");
+ inst->nua = nua_create(inst->root, sip_callback, inst, NUTAG_URL(local), TAG_END());
if (!inst->nua) {
PERROR("Failed to create SIP stack object\n");
sip_exit_inst(interface);
PDEBUG(DEBUG_SIP, "SIP interface created (inst=%p)\n", inst);
+ any_sip_interface = 1;
+
return 0;
}
interface->sip_inst = NULL;
PDEBUG(DEBUG_SIP, "SIP interface removed\n");
+
+ /* check if there is any other SIP interface left */
+ interface = interface_first;
+ while (interface) {
+ if (interface->sip_inst)
+ break;
+ interface = interface->next;
+ }
+ if (!interface)
+ any_sip_interface = 0;
}
extern su_log_t su_log_default[];