X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=sip.cpp;h=4def0a1cbeb3b35141c315a8376205051337cf22;hp=c6ddde3655a49dc5419b81573ab6140bfe6e9472;hb=cde9a763b10ce9fb98be413ded983fb1816ea258;hpb=e1e9da7d24ccce07ae54d671cde5e07dfc827e25 diff --git a/sip.cpp b/sip.cpp index c6ddde3..4def0a1 100644 --- a/sip.cpp +++ b/sip.cpp @@ -19,13 +19,15 @@ 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; }; @@ -35,7 +37,7 @@ static int delete_event(struct lcr_work *work, void *instance, int index); /* * 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) @@ -62,6 +64,8 @@ Psip::Psip(int type, char *portname, struct port_settings *settings, struct inte 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"); } @@ -77,7 +81,7 @@ Psip::~Psip() 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"; @@ -256,6 +260,11 @@ we only support alaw and ulaw! 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); @@ -278,7 +287,8 @@ static int rtp_sock_callback(struct lcr_fd *fd, unsigned int what, void *instanc // 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; @@ -305,7 +315,8 @@ static int rtcp_sock_callback(struct lcr_fd *fd, unsigned int what, void *instan } #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) { @@ -345,13 +356,14 @@ static int rtp_sub_socket_connect(int fd, struct sockaddr_in *sin_local, struct 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; } @@ -359,7 +371,7 @@ int Psip::rtp_open(void) 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; } @@ -369,15 +381,34 @@ int Psip::rtp_open(void) /* 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) + if (rc == 0) { + 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"); @@ -872,8 +903,9 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter 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; @@ -941,8 +973,15 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter 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); @@ -1810,11 +1849,12 @@ void Psip::rtp_shutdown(void) 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); @@ -1824,7 +1864,10 @@ int sip_init_inst(struct interface *interface) 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); @@ -1849,6 +1892,8 @@ int sip_init_inst(struct interface *interface) PDEBUG(DEBUG_SIP, "SIP interface created (inst=%p)\n", inst); + any_sip_interface = 1; + return 0; } @@ -1867,6 +1912,16 @@ void sip_exit_inst(struct interface *interface) 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[];