Data-Over-Voice
[lcr.git] / sip.cpp
diff --git a/sip.cpp b/sip.cpp
index 94e9760..6dbb4b3 100644 (file)
--- a/sip.cpp
+++ b/sip.cpp
 #include <sofia-sip/sdp.h>
 #include <sofia-sip/sip_header.h>
 
+#undef NUTAG_AUTO100
+
 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;
 };
 
 static int delete_event(struct lcr_work *work, void *instance, int index);
+static int load_timer(struct lcr_timer *timer, 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)
@@ -49,7 +54,6 @@ Psip::Psip(int type, char *portname, struct port_settings *settings, struct inte
        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;
@@ -60,7 +64,14 @@ Psip::Psip(int type, char *portname, struct port_settings *settings, struct inte
        p_s_rxpos = 0;
        p_s_rtp_tx_action = 0;
 
+       /* audio */
+       memset(&p_s_loadtimer, 0, sizeof(p_s_loadtimer));
+       add_timer(&p_s_loadtimer, load_timer, this, 0);
+       p_s_next_tv_sec = 0;
+
        PDEBUG(DEBUG_SIP, "Created new Psip(%s).\n", portname);
+       if (!p_s_sip_inst)
+               FATAL("No SIP instance for interface\n");
 }
 
 
@@ -71,22 +82,26 @@ Psip::~Psip()
 {
        PDEBUG(DEBUG_SIP, "Destroyed SIP process(%s).\n", p_name);
 
+       del_timer(&p_s_loadtimer);
        del_work(&p_s_delete);
 
        rtp_close();
 }
 
-const char *payload_type2name(uint8_t payload_type) {
-       switch (payload_type) {
-       case 0:
+static const char *media_type2name(uint8_t media_type) {
+       switch (media_type) {
+       case MEDIA_TYPE_ULAW:
                return "PCMU";
-       case 8:
+       case MEDIA_TYPE_ALAW:
                return "PCMA";
-       case 3:
-       case 96:
-       case 97:
-       case 98:
+       case MEDIA_TYPE_GSM:
                return "GSM";
+       case MEDIA_TYPE_GSM_HR:
+               return "GSM-HR";
+       case MEDIA_TYPE_GSM_EFR:
+               return "GSM-EFR";
+       case MEDIA_TYPE_AMR:
+               return "AMR";
        }
 
        return "UKN";
@@ -138,12 +153,9 @@ struct rtp_x_hdr {
 
 #define RTP_VERSION    2
 
-#define RTP_PT_ULAW 0
-#define RTP_PT_ALAW 8
-#define RTP_PT_GSM_FULL 3
-#define RTP_PT_GSM_HALF 96
-#define RTP_PT_GSM_EFR 97
-#define RTP_PT_AMR 98
+#define PAYLOAD_TYPE_ULAW 0
+#define PAYLOAD_TYPE_ALAW 8
+#define PAYLOAD_TYPE_GSM 3
 
 /* decode an rtp frame  */
 static int rtp_decode(class Psip *psip, unsigned char *data, int len)
@@ -202,6 +214,8 @@ static int rtp_decode(class Psip *psip, unsigned char *data, int len)
        }
 
        switch (rtph->payload_type) {
+#if 0
+we only support alaw and ulaw!
        case RTP_PT_GSM_FULL:
                if (payload_len != 33) {
                        PDEBUG(DEBUG_SIP, "received RTP full rate frame with "
@@ -218,13 +232,22 @@ static int rtp_decode(class Psip *psip, unsigned char *data, int len)
                        return -EINVAL;
                }
                break;
-       case RTP_PT_ALAW:
+       case RTP_PT_GSM_HALF:
+               if (payload_len != 14) {
+                       PDEBUG(DEBUG_SIP, "received RTP half rate frame with "
+                               "payload length != 14 (len = %d)\n",
+                               payload_len);
+                       return -EINVAL;
+               }
+               break;
+#endif
+       case PAYLOAD_TYPE_ALAW:
                if (options.law != 'a') {
                        PDEBUG(DEBUG_SIP, "received Alaw, but we don't do Alaw\n");
                        return -EINVAL;
                }
                break;
-       case RTP_PT_ULAW:
+       case PAYLOAD_TYPE_ULAW:
                if (options.law == 'a') {
                        PDEBUG(DEBUG_SIP, "received Ulaw, but we don't do Ulaw\n");
                        return -EINVAL;
@@ -241,11 +264,24 @@ static int rtp_decode(class Psip *psip, unsigned char *data, int len)
                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++];
+       if (psip->p_dov_rx)
+               psip->dov_rx(payload, payload_len);
        psip->bridge_tx(payload, payload_len);
 
        return 0;
@@ -266,7 +302,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;
@@ -286,14 +323,15 @@ static int rtcp_sock_callback(struct lcr_fd *fd, unsigned int what, void *instan
 //                     psip->rtp_shutdown();
                        return len;
                }
-               PDEBUG(DEBUG_SIP, "rtcp!");
+               PDEBUG(DEBUG_SIP, "rtcp!\n");
        }
 
        return 0;
 }
 
 #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)
 {
@@ -333,13 +371,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;
        }
@@ -347,7 +386,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;
        }
@@ -357,22 +396,41 @@ 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) {
+                       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);
 
-               rc = rtp_sub_socket_bind(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, ip, next_udp_port+1);
-               if (rc == 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);
@@ -444,6 +502,12 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_
        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;
@@ -459,6 +523,8 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_
        }
 
        switch (payload_type) {
+#if 0
+we only support alaw and ulaw!
        case RTP_PT_GSM_FULL:
                payload_len = 33;
                duration = 160;
@@ -467,8 +533,13 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_
                payload_len = 31;
                duration = 160;
                break;
-       case RTP_PT_ALAW:
-       case RTP_PT_ULAW:
+       case RTP_PT_GSM_HALF:
+               payload_len = 14;
+               duration = 160;
+               break;
+#endif
+       case PAYLOAD_TYPE_ALAW:
+       case PAYLOAD_TYPE_ULAW:
                payload_len = len;
                duration = len;
                break;
@@ -528,6 +599,18 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_
 /* receive from remote */
 int Psip::bridge_rx(unsigned char *data, int len)
 {
+       int ret;
+
+       /* don't bridge, if tones are provided */
+       if (p_tone_name[0] || p_dov_tx)
+               return -EBUSY;
+
+       if (p_dov_tx)
+               return -EBUSY;
+
+       if ((ret = Port::bridge_rx(data, len)))
+               return ret;
+
        /* write to rx buffer */
        while(len--) {
                p_s_rxdata[p_s_rxpos++] = flip[*data++];
@@ -535,7 +618,7 @@ int Psip::bridge_rx(unsigned char *data, int len)
                        p_s_rxpos = 0;
 
                        /* transmit data via rtp */
-                       rtp_send_frame(p_s_rxdata, 160, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW);
+                       rtp_send_frame(p_s_rxdata, 160, (options.law=='a')?PAYLOAD_TYPE_ALAW:PAYLOAD_TYPE_ULAW);
                }
        }
 
@@ -720,20 +803,25 @@ int Psip::message_connect(unsigned int epoint_id, int message_id, union paramete
        char sdp_str[256];
        struct in_addr ia;
        struct lcr_msg *message;
+       int media_type;
+       unsigned char payload_type;
 
        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;
+               media_type = param->connectinfo.rtpinfo.media_types[0];
+               payload_type = param->connectinfo.rtpinfo.payload_types[0];
                p_s_rtp_ip_local = param->connectinfo.rtpinfo.ip;
                p_s_rtp_port_local = param->connectinfo.rtpinfo.port;
+               PDEBUG(DEBUG_SIP, "payload type %d\n", payload_type);
                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;
+               media_type = (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW;
+               payload_type = (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW;
                /* open local RTP peer (if not bridging) */
-               if (rtp_connect() < 0) {
+               if (!p_s_rtp_is_connected && rtp_connect() < 0) {
                        nua_cancel(p_s_handle, TAG_END());
                        nua_handle_destroy(p_s_handle);
                        p_s_handle = NULL;
@@ -760,7 +848,7 @@ int Psip::message_connect(unsigned int epoint_id, int message_id, union paramete
                "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));
+               , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, payload_type, payload_type, media_type2name(media_type));
        PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
 
        nua_respond(p_s_handle, SIP_200_OK,
@@ -771,6 +859,9 @@ int Psip::message_connect(unsigned int epoint_id, int message_id, union paramete
        sip_trace_header(this, "RESPOND", DIRECTION_OUT);
        add_trace("respond", "value", "200 OK");
        add_trace("reason", NULL, "call connected");
+       add_trace("rtp", "ip", "%s", inet_ntoa(ia));
+       add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
+       add_trace("rtp", "payload", "%s:%d", media_type2name(media_type), payload_type);
        end_trace();
 
        return 0;
@@ -845,12 +936,20 @@ 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;
-       char sdp_str[256];
+       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;
        sip_cseq_t *cseq = NULL;
+       struct lcr_msg *message;
+       int lcr_media = { (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW };
+       unsigned char lcr_payload = { (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW };
+       int *media_types;
+       unsigned char *payload_types;
+       int payloads = 0;
+       int i;
 
        PDEBUG(DEBUG_SIP, "Doing Setup (inst %p)\n", inst);
 
@@ -861,7 +960,9 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
        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;
+               media_types = param->setup.rtpinfo.media_types;
+               payload_types = param->setup.rtpinfo.payload_types;
+               payloads = param->setup.rtpinfo.payloads;
                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);
@@ -869,12 +970,12 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
        } else {
                PDEBUG(DEBUG_SIP, "RTP info not given by remote, so we do our own RTP\n");
                p_s_rtp_bridge = 0;
-               p_s_rtp_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
+               media_types = &lcr_media;
+               payload_types = &lcr_payload;
+               payloads = 1;
 
                /* 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);
@@ -886,19 +987,9 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                        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_s_rtp_port_local, p_s_rtp_port_local + 1);
-       end_trace();
 
        p_s_handle = nua_handle(inst->nua, NULL, TAG_END());
        if (!p_s_handle) {
-               struct lcr_msg *message;
-
                PERROR("Failed to create handle\n");
                /* send release message to endpoit */
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -915,8 +1006,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);
@@ -926,11 +1024,31 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                "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));
+               "m=audio %d RTP/AVP"
+               , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local);
+       for (i = 0; i < payloads; i++) {
+               SPRINT(pt_str, " %d", payload_types[i]);
+               SCAT(sdp_str, pt_str);
+       }
+       SCAT(sdp_str, "\n");
+       for (i = 0; i < payloads; i++) {
+               SPRINT(pt_str, "a=rtpmap:%d %s/8000\n", payload_types[i], media_type2name(media_types[i]));
+               SCAT(sdp_str, pt_str);
+       }
        PDEBUG(DEBUG_SIP, "Using SDP for invite: %s\n", sdp_str);
 
+       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", "ip", "%s", inet_ntoa(ia));
+       add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
+       for (i = 0; i < payloads; i++)
+               add_trace("rtp", "payload", "%s:%d", media_type2name(media_types[i]), payload_types[i]);
+       end_trace();
+
 //     cseq = sip_cseq_create(sip_home, 123, SIP_METHOD_INVITE);
 
        nua_invite(p_s_handle,
@@ -942,6 +1060,18 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
        new_state(PORT_STATE_OUT_SETUP);
 
+#if 0
+       PDEBUG(DEBUG_SIP, "do overlap\n");
+       new_state(PORT_STATE_OUT_OVERLAP);
+       message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_OVERLAP);
+       message_put(message);
+#else
+       PDEBUG(DEBUG_SIP, "do proceeding\n");
+       new_state(PORT_STATE_OUT_PROCEEDING);
+       message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_PROCEEDING);
+       message_put(message);
+#endif
+
        /* attach only if not already */
        epointlist = p_epointlist;
        while(epointlist) {
@@ -991,7 +1121,7 @@ int Psip::message_notify(unsigned int epoint_id, int message_id, union parameter
                        "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));
+                       , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, media_type2name(p_s_rtp_media_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)),
@@ -1026,6 +1156,26 @@ int Psip::message_dtmf(unsigned int epoint_id, int message_id, union parameter *
        return 0;
 }
 
+/* NOTE: incomplete and not working */
+int Psip::message_information(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       char dtmf_str[64];
+       
+       /* prepare DTMF info payload */
+       SPRINT(dtmf_str,
+               "Signal=%s\n"
+               "Duration=160\n"
+               , param->information.id);
+
+       /* 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)
 {
        if (Port::message_epoint(epoint_id, message_id, param))
@@ -1060,6 +1210,12 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
                message_setup(epoint_id, message_id, param);
                return 1;
 
+               case MESSAGE_INFORMATION: /* overlap dialing */
+               if (p_state != PORT_STATE_OUT_OVERLAP)
+                       return 0;
+               message_information(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);
@@ -1075,9 +1231,9 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
        return 0;
 }
 
-int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t payload_type)
+int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t *payload_types, int *media_types, int *payloads, int max_payloads)
 {
-       int codec_supported = 0;
+       *payloads = 0;
 
        if (!sip->sip_payload) {
                PDEBUG(DEBUG_SIP, "no payload given\n");
@@ -1135,55 +1291,93 @@ int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, ui
                        *ip = ntohl(p_s_rtp_ip_remote);
                }
                for (map = m->m_rtpmaps; map; map = map->rm_next) {
+                       int media_type = 0;
+
                        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;
+                       /* append to payload list, if there is space */
+                       add_trace("rtp", "payload", "%s:%d", map->rm_encoding, map->rm_pt);
+                       if (map->rm_pt == PAYLOAD_TYPE_ALAW)
+                               media_type = MEDIA_TYPE_ALAW;
+                       else if (map->rm_pt == PAYLOAD_TYPE_ULAW)
+                               media_type = MEDIA_TYPE_ULAW;
+                       else if (map->rm_pt == PAYLOAD_TYPE_GSM)
+                               media_type = MEDIA_TYPE_GSM;
+                       else if (!strcmp(map->rm_encoding, "GSM-EFR"))
+                               media_type = MEDIA_TYPE_GSM_EFR;
+                       else if (!strcmp(map->rm_encoding, "AMR"))
+                               media_type = MEDIA_TYPE_AMR;
+                       else if (!strcmp(map->rm_encoding, "GSM-HR"))
+                               media_type = MEDIA_TYPE_GSM_HR;
+                       if (media_type && *payloads <= max_payloads) {
+                               *payload_types++ = map->rm_pt;
+                               *media_types++ = media_type;
+                               (*payloads)++;
                        }
                }
        }
-       done_codec:
 
        sdp_parser_free(parser);
 
-       if (!codec_supported)
-               return 415;
-
        return 0;
 }
 
 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 = "";
+       const char *from = "", *to = "", *name = "";
+       char imsi[16] = "";
        int ret;
        class Endpoint *epoint;
        struct lcr_msg *message;
-       uint8_t payload_type;
-       struct interface *interface = interface_first;
+       struct interface *interface;
+       int media_types[32];
+       uint8_t payload_types[32];
+       int payloads = 0;
+       int media_type;
 
-       while (interface) {
-               if (!strcmp(interface->name, inst->interface_name))
-                       break;
-               interface = interface->next;
-       }
+       interface = getinterfacebyname(inst->interface_name);
        if (!interface) {
                PERROR("Cannot find interface %s.\n", inst->interface_name);
                return;
        }
 
-       if (sip->sip_from && sip->sip_from->a_url)
-               from = sip->sip_from->a_url->url_user;
-       if (sip->sip_to && sip->sip_to->a_url)
-               to = sip->sip_to->a_url->url_user;
+       if (sip->sip_from) {
+               if (sip->sip_from->a_url)
+                       from = sip->sip_from->a_url->url_user;
+               if (sip->sip_from->a_display) {
+                       name = sip->sip_from->a_display;
+                       if (!strncmp(name, "\"IMSI", 5)) {
+                               strncpy(imsi, name + 5, 15);
+                               imsi[15] = '\0';
+                               name = "";
+                       }
+               }
+       }
+       if (sip->sip_to) {
+               if (sip->sip_to->a_url)
+                       to = sip->sip_to->a_url->url_user;
+       }
        PDEBUG(DEBUG_SIP, "invite received (%s->%s)\n", from, to);
 
-       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);
+       sip_trace_header(this, "Payload received", DIRECTION_NONE);
+       ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_types, media_types, &payloads, sizeof(payload_types));
+       if (!ret) {
+               /* if no RTP bridge, we must support LAW codec, otherwise we forward what we have */
+               if (!p_s_rtp_bridge) {
+                       int i;
+
+                       /* check if supported payload type exists */
+                       for (i = 0; i < payloads; i++) {
+                               if (media_types[i] == ((options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW))
+                                       break;
+                       }
+                       if (i == payloads) {
+                               add_trace("error", NULL, "Expected LAW payload type (not bridged)");
+                               ret = 415;
+                       }
+               }
+       }
+       end_trace();
        if (ret) {
                if (ret == 400)
                        nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END());
@@ -1224,7 +1418,7 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        end_trace();
 
        sip_trace_header(this, "INVITE", DIRECTION_IN);
-       add_trace("RTP", "port", "%d", p_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;
@@ -1237,6 +1431,12 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
                SCPY(p_callerinfo.id, from);
                add_trace("calling", "number", "%s", from);
+               SCPY(p_callerinfo.name, name);
+               if (name[0])
+                       add_trace("calling", "name", "%s", name);
+               SCPY(p_callerinfo.imsi, imsi);
+               if (imsi[0])
+                       add_trace("calling", "imsi", "%s", imsi);
        }
        SCPY(p_callerinfo.interface, inst->interface_name);
        /* dialing information */
@@ -1265,11 +1465,13 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
        epointlist_new(epoint->ep_serial);
 
+#ifdef NUTAG_AUTO100
        /* send trying (proceeding) */
        nua_respond(nh, SIP_100_TRYING, TAG_END());
        sip_trace_header(this, "RESPOND", DIRECTION_OUT);
        add_trace("respond", "value", "100 Trying");
        end_trace();
+#endif
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
@@ -1284,12 +1486,76 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
 //     message->param.setup.useruser.len = strlen(mncc->useruser.info);
 //     message->param.setup.useruser.protocol = mncc->useruser.proto;
        if (p_s_rtp_bridge) {
+               int i;
+
                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;
+               /* add codecs to setup message */
+               for (i = 0; i < payloads; i++) {
+                       message->param.setup.rtpinfo.media_types[i] = media_types[i];
+                       message->param.setup.rtpinfo.payload_types[i] = payload_types[i];
+                       if (i == sizeof(message->param.setup.rtpinfo.payload_types))
+                               break;
+               }
+               message->param.setup.rtpinfo.payloads = i;
        }
        message_put(message);
+
+       /* send progress, if tones are available and if we don't bridge */
+       if (!p_s_rtp_bridge && interface->is_tones == IS_YES) {
+               char sdp_str[256];
+               struct in_addr ia;
+               unsigned char payload_type;
+
+               PDEBUG(DEBUG_SIP, "Connecting audio, since we have tones available\n");
+               media_type = (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW;
+               payload_type = (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW;
+               /* open local RTP peer (if not bridging) */
+               if (rtp_connect() < 0) {
+                       nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
+                       nua_handle_destroy(nh);
+                       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 connect RTP/RTCP sockts");
+                       end_trace();
+                       new_state(PORT_STATE_RELEASE);
+                       trigger_work(&p_s_delete);
+                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), 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;
+               }
+
+               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, payload_type, payload_type, media_type2name(media_type));
+               PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
+
+               nua_respond(p_s_handle, SIP_183_SESSION_PROGRESS,
+                       NUTAG_MEDIA_ENABLE(0),
+                       SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+                       SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+               sip_trace_header(this, "RESPOND", DIRECTION_OUT);
+               add_trace("respond", "value", "183 SESSION PROGRESS");
+               add_trace("reason", NULL, "audio available");
+               add_trace("rtp", "ip", "%s", inet_ntoa(ia));
+               add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
+               add_trace("rtp", "payload", "%s:%d", media_type2name(media_type), payload_type);
+               end_trace();
+       }
 }
 
 void Psip::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 tagss[])
@@ -1384,6 +1650,9 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
 {
        struct lcr_msg *message;
        int cause = 0, location = 0;
+       int media_types[32];
+       uint8_t payload_types[32];
+       int payloads = 0;
 
        PDEBUG(DEBUG_SIP, "response to invite received (status = %d)\n", status);
 
@@ -1394,20 +1663,24 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        /* connect audio */
        if (status == 183 || (status >= 200 && status <= 299)) {
                int ret;
-               uint8_t payload_type;
 
-               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);
+               sip_trace_header(this, "Payload received", DIRECTION_NONE);
+               ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_types, media_types, &payloads, sizeof(payload_types));
+               if (!ret) {
+                       if (payloads != 1)
+                               ret = 415;
+                       else if (!p_s_rtp_bridge) {
+                               if (media_types[0] != ((options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW)) {
+                                       add_trace("error", NULL, "Expected LAW payload type (not bridged)");
+                                       ret = 415;
+                               }
+                       }
+               }
+               end_trace();
                if (ret) {
-                       if (ret == 400)
-                               nua_cancel(nh, TAG_END());
-                       else
-                               nua_cancel(nh, TAG_END());
+                       nua_cancel(nh, TAG_END());
                        sip_trace_header(this, "CANCEL", DIRECTION_OUT);
-                       add_trace("reason", NULL, "offered codec does not match");
+                       add_trace("reason", NULL, "accepted codec does not match");
                        end_trace();
                        cause = 88;
                        location = LOCATION_PRIVATE_LOCAL;
@@ -1429,10 +1702,12 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        /* process 1xx */
        switch (status) {
        case 100:
+#if 0
                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);
+#endif
                return;
        case 180:
                PDEBUG(DEBUG_SIP, "do alerting\n");
@@ -1446,9 +1721,11 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                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->param.progressinfo.rtpinfo.media_types[0] = media_types[0];
+                       message->param.progressinfo.rtpinfo.payload_types[0] = payload_types[0];
+                       message->param.progressinfo.rtpinfo.payloads = 1;
                }
                message_put(message);
                return;
@@ -1467,9 +1744,11 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                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->param.connectinfo.rtpinfo.media_types[0] = media_types[0];
+                       message->param.connectinfo.rtpinfo.payload_types[0] = payload_types[0];
+                       message->param.connectinfo.rtpinfo.payloads = 1;
                }
                message_put(message);
                return;
@@ -1619,11 +1898,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);
@@ -1633,7 +1913,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);
@@ -1649,13 +1932,17 @@ int sip_init_inst(struct interface *interface)
                NUTAG_APPL_METHOD("NOTIFY"),
                NUTAG_APPL_METHOD("INFO"),
                NUTAG_AUTOACK(0),
+#ifdef NUTAG_AUTO100
                NUTAG_AUTO100(0),
+#endif
                NUTAG_AUTOALERT(0),
                NUTAG_AUTOANSWER(0),
                TAG_NULL());
 
        PDEBUG(DEBUG_SIP, "SIP interface created (inst=%p)\n", inst);
 
+       any_sip_interface = 1;
+
        return 0;
 }
 
@@ -1674,6 +1961,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[];
@@ -1734,3 +2031,106 @@ static int delete_event(struct lcr_work *work, void *instance, int index)
        return 0;
 }
 
+
+/*
+ * generate audio, if no data is received from bridge
+ */
+
+void Psip::set_tone(const char *dir, const char *tone)
+{
+       Port::set_tone(dir, tone);
+
+       update_load();
+}
+
+void Psip::update_load(void)
+{
+       /* don't trigger load event if event already active */
+       if (p_s_loadtimer.active)
+               return;
+
+       /* don't start timer if ... */
+       if (!p_tone_name[0] && !p_dov_tx)
+               return;
+
+       p_s_next_tv_sec = 0;
+       schedule_timer(&p_s_loadtimer, 0, 0); /* no delay the first time */
+}
+
+static int load_timer(struct lcr_timer *timer, void *instance, int index)
+{
+       class Psip *psip = (class Psip *)instance;
+
+       /* stop timer if ... */
+       if (!psip->p_tone_name[0] && !psip->p_dov_tx)
+               return 0;
+
+       psip->load_tx();
+
+       return 0;
+}
+
+#define SEND_SIP_LEN 160
+
+void Psip::load_tx(void)
+{
+       int diff;
+       struct timeval current_time;
+       int tosend = SEND_SIP_LEN, i;
+       unsigned char buf[SEND_SIP_LEN], *p = buf;
+
+       /* get elapsed */
+       gettimeofday(&current_time, NULL);
+       if (!p_s_next_tv_sec) {
+               /* if timer expired the first time, set next expected timeout 160 samples in advance */
+               p_s_next_tv_sec = current_time.tv_sec;
+               p_s_next_tv_usec = current_time.tv_usec + SEND_SIP_LEN * 125;
+               if (p_s_next_tv_usec >= 1000000) {
+                       p_s_next_tv_usec -= 1000000;
+                       p_s_next_tv_sec++;
+               }
+               schedule_timer(&p_s_loadtimer, 0, SEND_SIP_LEN * 125);
+       } else {
+               diff = 1000000 * (current_time.tv_sec - p_s_next_tv_sec)
+                       + (current_time.tv_usec - p_s_next_tv_usec);
+               if (diff < -SEND_SIP_LEN * 125 || diff > SEND_SIP_LEN * 125) {
+                       /* if clock drifts too much, set next timeout event to current timer + 160 */
+                       diff = 0;
+                       p_s_next_tv_sec = current_time.tv_sec;
+                       p_s_next_tv_usec = current_time.tv_usec + SEND_SIP_LEN * 125;
+                       if (p_s_next_tv_usec >= 1000000) {
+                               p_s_next_tv_usec -= 1000000;
+                               p_s_next_tv_sec++;
+                       }
+               } else {
+                       /* if diff is positive, it took too long, so next timeout will be earlier */
+                       p_s_next_tv_usec += SEND_SIP_LEN * 125;
+                       if (p_s_next_tv_usec >= 1000000) {
+                               p_s_next_tv_usec -= 1000000;
+                               p_s_next_tv_sec++;
+                       }
+               }
+               schedule_timer(&p_s_loadtimer, 0, SEND_SIP_LEN * 125 - diff);
+       }
+
+       /* copy tones */
+       if (p_tone_name[0]) {
+               tosend -= read_audio(p, tosend);
+       } else
+       if (p_dov_tx) {
+               tosend -= dov_tx(p, tosend);
+       }
+       if (tosend) {
+               PERROR("buffer is not completely filled\n");
+               return;
+       }
+
+       p = buf;
+       for (i = 0; i < SEND_SIP_LEN; i++) {
+               *p = flip[*p];
+               p++;
+       }
+       /* transmit data via rtp */
+       rtp_send_frame(buf, SEND_SIP_LEN, (options.law=='a')?PAYLOAD_TYPE_ALAW:PAYLOAD_TYPE_ULAW);
+}
+