fixup register
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 11 Nov 2017 09:04:13 +0000 (10:04 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 11 Nov 2017 09:04:13 +0000 (10:04 +0100)
interface.c
sip.cpp

index 7d5d7a5..7556a18 100644 (file)
@@ -974,14 +974,10 @@ static int inter_sip(struct interface *interface, char *filename, int line, char
 
        /* copy values */
        if (!value || !value[0]) {
-               SPRINT(interface_error, "Error in %s (line %d): Missing SIP local IP.\n", filename, line);
+               SPRINT(interface_error, "Error in %s (line %d): Missing SIP local peer.\n", filename, line);
                return(-1);
        }
        p = get_seperated(value);
-       if (!p[0]) {
-               SPRINT(interface_error, "Error in %s (line %d): Missing SIP remote IP.\n", filename, line);
-               return(-1);
-       }
        SCPY(interface->sip_local_peer, value);
        SCPY(interface->sip_remote_peer, p);
 
@@ -1477,7 +1473,7 @@ struct interface_param interface_param[] = {
        {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
        "Timeout values for call states. They are both for incoming and outgoing states.\n"
        "The default is 120 seconds for all states. Use 0 to disable.\n"
-       "This parameter must follow a 'port' parameter.\n"},
+       "This parameter must follow a 'port' parameter."},
 
        {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
        "Incoming caller ID is checked against given MSN numbers.\n"
@@ -1515,12 +1511,11 @@ struct interface_param interface_param[] = {
        {"dialmax", &inter_dialmax, "<digits>",
        "Limits the number of digits in setup/information message."},
 
-       {"tones_dir", &inter_tones_dir, "<path>",
-       "Overrides the given tone_dir in options.conf.\n"
-       "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
        {"tones-dir", &inter_tones_dir, "<path>",
        "Overrides the given tone_dir in options.conf.\n"
        "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
+       {"tones_dir", &inter_tones_dir, "<path>",
+       "Same as tones-dir"},
 
        {"gsm", &inter_gsm, "",
        ""},
@@ -1533,8 +1528,10 @@ struct interface_param interface_param[] = {
        {"gsm-ms", &inter_gsm_ms, "<socket name>",
        "Sets up GSM mobile station interface for using Osmocom-BB.\n"
        "The socket will be /tmp/ms_mncc_<socket name>."},
-       {"sip", &inter_sip, "<local IP/host> <remote IP/host>",
-       "Sets up SIP interface that represents one SIP endpoint."},
+
+       {"sip", &inter_sip, "<local IP/host>[:port] [<remote IP/host>[port]]",
+       "Sets up SIP interface that represents one SIP endpoint.\n"
+       "If the remote IP/host is omitted, a client must register first to us."},
        {"register", &inter_register, "<user> <host>",
        "Registers to given SIP registrar."},
        {"authenticate", &inter_authenticate, "<user> <password>",
@@ -1548,21 +1545,24 @@ struct interface_param interface_param[] = {
        "The interval is used to check if IP has changed. (use 300)"},
        {"rtp-ports", &inter_rtp_ports, "<port from> <port to>",
        "Defines the range of ports to be used for RTP. This overrides the default."},
+
        {"rtp-bridge", &inter_rtp_bridge, "",
        "Enables RTP bridging directly from this interface.\n"
        "This only works if both bridged interfaces use RTP, e.g. between gsm-bs and sip.\n"
-       "This parameter must follow a 'bridge' parameter.\n"},
+       "This parameter must follow a 'bridge' parameter."},
 #if 0
        not needed, since ms defines what is supports and remote (sip) tells what is selected
        {"rtp-payload", &inter_rtp_payload, "<codec>",
        "Define RTP payload to use. Only valid in conjuntion with gsm-bs!\n"
        "If multiple payloads are defined, the first has highest priority.\n"
-       "If none are defined, GSM fullrate V1 (type 3) is assumed.\n"},
+       "If none are defined, GSM fullrate V1 (type 3) is assumed."},
 #endif
+
        {"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"
        "This parameter must follow a 'port' parameter."},
+
        {"bridge", &inter_bridge, "<destination interface>",
        "Define bridge application for this interface. All calls received on this\n"
        "interface will be directly bridged to the given destination interface.\n"
@@ -1594,17 +1594,17 @@ struct interface_param interface_param[] = {
        {"pots-flash", &inter_pots_flash, "",
        "Allow flash button to hold an active call and setup a new call.\n"
        "Ihis parameter only appies to POTS type of interfaces\n"
-       "This parameter must follow a 'port' parameter.\n"},
+       "This parameter must follow a 'port' parameter."},
        {"pots-ring-after-hangup", &inter_pots_ring, "",
        "Allow ringing of last hold call after hangup. Other calls on hold will not be\n"
        "released.\n"
        "Ihis parameter only appies to POTS type of interfaces\n"
-       "This parameter must follow a 'port' parameter.\n"},
+       "This parameter must follow a 'port' parameter."},
        {"pots-transfer-after-hangup", &inter_pots_transfer, "",
        "If two calls on hold, both are connected after hangup.\n"
        "If one call is on hold and another one alerting, call on hold is tranfered.\n"
        "Ihis parameter only appies to POTS type of interfaces\n"
-       "This parameter must follow a 'port' parameter.\n"},
+       "This parameter must follow a 'port' parameter."},
 
        {"shutdown", &inter_shutdown, "",
        "Interface will not be loaded when processing interface.conf"},
diff --git a/sip.cpp b/sip.cpp
index 21e24d5..3537dd0 100644 (file)
--- a/sip.cpp
+++ b/sip.cpp
@@ -1042,6 +1042,19 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
        int payloads = 0;
        int i;
 
+       if (!remote[0]) {
+               sip_trace_header(this, inst->interface_name, "INVITE", DIRECTION_OUT);
+               add_trace("failed", "reason", "No remote peer set or no peer has registered to us.");
+               end_trace();
+               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = 27;
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               message_put(message);
+               new_state(PORT_STATE_RELEASE);
+               trigger_work(&p_s_delete);
+               return 0;
+       }
+       
        PDEBUG(DEBUG_SIP, "Doing Setup (inst %p)\n", inst);
 
        memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
@@ -1108,9 +1121,9 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                return 0;
        }
        /* apply handle to trace */
-       sip_trace_header(this, inst->interface_name, "NEW handle", DIRECTION_IN);
-       add_trace("handle", "new", "0x%x", p_s_handle);
-       end_trace();
+//     sip_trace_header(this, inst->interface_name, "NEW handle", DIRECTION_IN);
+//     add_trace("handle", "new", "0x%x", p_s_handle);
+//     end_trace();
 
        SPRINT(sdp_str,
                "v=0\r\n"
@@ -1423,7 +1436,146 @@ int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, ui
        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[])
+static int challenge(struct sip_inst *inst, class Psip *psip, 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[])
+{
+       sip_www_authenticate_t const *authenticate = NULL;
+       char const *realm = NULL;
+       char const *scheme = NULL;
+       int i;
+       char *cur;
+       char authentication[256] = "";
+       PDEBUG(DEBUG_SIP, "challenge order received\n");
+
+       if (!inst->auth_user[0]) {
+               PDEBUG(DEBUG_SIP, "No credentials available\n");
+               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
+               add_trace("error", NULL, "There are no credentials given for interface");
+               end_trace();
+               return -1;
+       }
+
+       if (sip->sip_www_authenticate) {
+               authenticate = sip->sip_www_authenticate;
+       } else if (sip->sip_proxy_authenticate) {
+               authenticate = sip->sip_proxy_authenticate;
+       } else {
+               PDEBUG(DEBUG_SIP, "No authentication header found\n");
+               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
+               add_trace("error", NULL, "Authentication method unknwon");
+               end_trace();
+               return -1;
+       }
+
+       scheme = (char const *) authenticate->au_scheme;
+       if (authenticate->au_params) {
+               for (i = 0; (cur = (char *) authenticate->au_params[i]); i++) {
+                       if ((realm = strstr(cur, "realm="))) {
+                               realm += 6;
+                               break;
+                       }
+               }
+       }
+
+       if (!scheme || !realm) {
+               PDEBUG(DEBUG_SIP, "No scheme or no realm in authentication header found\n");
+               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
+               add_trace("error", NULL, "Authentication header has no realm or scheme");
+               end_trace();
+               return -1;
+       }
+
+       SPRINT(authentication, "%s:%s:%s:%s", scheme, realm, inst->auth_user, inst->auth_password);
+       PDEBUG(DEBUG_SIP, "auth: '%s'\n", authentication);
+
+       sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
+       add_trace("scheme", NULL, "%s", scheme);
+       add_trace("realm", NULL, "%s", realm);
+       add_trace("user", NULL, "%s", inst->auth_user);
+       add_trace("pass", NULL, "%s", inst->auth_password);
+       end_trace();
+
+       nua_authenticate(nh, /*SIPTAG_EXPIRES_STR("3600"),*/ NUTAG_AUTH(authentication), TAG_END());
+
+       return 0;
+}
+
+static void i_register(struct sip_inst *inst, 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[])
+{
+       #define NUTAG_WITH_THIS_MSG(msg) nutag_with, tag_ptr_v(msg)
+       nua_saved_event_t saved[1];
+       sip_contact_t const *contact = NULL;
+       contact = sip->sip_contact;
+       nua_save_event(nua, saved);
+       nua_event_data_t const *data = nua_event_data(saved);
+
+       if (contact->m_url->url_host)
+               SCPY(inst->remote_peer, contact->m_url->url_host);
+       if (contact->m_url->url_port && contact->m_url->url_port[0]) {
+               SCAT(inst->remote_peer, ":");
+               SCAT(inst->remote_peer, contact->m_url->url_port);
+       }
+
+       sip_trace_header(NULL, inst->interface_name, "REGISTER", DIRECTION_IN);
+       add_trace("contact", "uri", "%s", inst->remote_peer);
+       end_trace();
+
+       sip_trace_header(NULL, inst->interface_name, "RESPOND", DIRECTION_OUT);
+       add_trace("respond", "value", "200 OK");
+       add_trace("reason", NULL, "peer registered");
+       end_trace();
+
+       nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(sip->sip_contact), NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
+       nua_handle_destroy(nh);
+       inst->register_handle = NULL;
+}
+
+static void r_register(struct sip_inst *inst, 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[])
+{
+       int rc;
+
+       sip_trace_header(NULL, inst->interface_name, "STATUS", DIRECTION_IN);
+       add_trace("value", NULL, "%d", status);
+       add_trace("phrase", NULL, "%s", phrase);
+       end_trace();
+
+       switch (status) {
+       case 200:
+               status_200:
+               /* if not registered, become registered and start register interval timer */
+               if (inst->register_state != REGISTER_STATE_REGISTERED) {
+                       if (inst->register_interval)
+                               schedule_timer(&inst->register_retry_timer, inst->register_interval, 0);
+                       inst->register_state = REGISTER_STATE_REGISTERED;
+               }
+               /* start option timer */
+               if (inst->options_interval)
+                       schedule_timer(&inst->register_option_timer, inst->options_interval, 0);
+               break;
+       case 401:
+       case 407:
+               PDEBUG(DEBUG_SIP, "Register challenge received\n");
+               rc = challenge(inst, NULL, status, phrase, nua, magic, nh, hmagic, sip, tags);
+               if (rc < 0)
+                       goto status_400;
+               break;
+       default:
+               if (status >= 200 && status <= 299)
+                       goto status_200;
+               if (status < 400)
+                       break;
+               status_400:
+               PDEBUG(DEBUG_SIP, "Register failed, starting register timer\n");
+               inst->register_state = REGISTER_STATE_FAILED;
+               nua_handle_destroy(nh);
+               inst->register_handle = NULL;
+               /* stop option timer */
+               unsched_timer(&inst->register_option_timer);
+               /* if failed, start register interval timer with REGISTER_RETRY_TIMER */
+               schedule_timer(&inst->register_retry_timer, REGISTER_RETRY_TIMER);
+       }
+}
+
+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 tags[])
 {
        struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        const char *from = "", *to = "", *name = "";
@@ -1514,10 +1666,11 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        }
 
        /* apply handle */
-       sip_trace_header(this, inst->interface_name, "NEW handle", DIRECTION_IN);
-       add_trace("handle", "new", "0x%x", nh);
+//     sip_trace_header(this, inst->interface_name, "NEW handle", DIRECTION_IN);
+//     add_trace("handle", "new", "0x%x", nh);
+//     end_trace();
+//
        p_s_handle = nh;
-       end_trace();
 
        sip_trace_header(this, inst->interface_name, "INVITE", DIRECTION_IN);
        add_trace("rtp", "port", "%d", p_s_rtp_port_remote);
@@ -1666,7 +1819,7 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        }
 }
 
-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[])
+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 tags[])
 {
        struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        struct lcr_msg *message;
@@ -1704,7 +1857,7 @@ void Psip::i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic,
        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[])
+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 tags[])
 {
        struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        struct lcr_msg *message;
@@ -1732,7 +1885,7 @@ void Psip::i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        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[])
+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 tags[])
 {
        PDEBUG(DEBUG_SIP, "bye response received\n");
 
@@ -1744,7 +1897,7 @@ void Psip::r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic,
        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[])
+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 tags[])
 {
        PDEBUG(DEBUG_SIP, "cancel response received\n");
 
@@ -1756,7 +1909,7 @@ void Psip::r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        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[])
+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 tags[])
 {
        struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        struct lcr_msg *message;
@@ -1892,7 +2045,7 @@ release_with_cause:
        trigger_work(&p_s_delete);
 }
 
-void Psip::r_options(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[])
+void Psip::r_options(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[])
 {
        struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        int cause = 0, location = 0;
@@ -1928,69 +2081,6 @@ void Psip::r_options(int status, char const *phrase, nua_t *nua, nua_magic_t *ma
        trigger_work(&p_s_delete);
 }
 
-static int challenge(struct sip_inst *inst, class Psip *psip, 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[])
-{
-       sip_www_authenticate_t const *authenticate = NULL;
-       char const *realm = NULL;
-       char const *scheme = NULL;
-       int i;
-       char *cur;
-       char authentication[256] = "";
-       PDEBUG(DEBUG_SIP, "challenge order received\n");
-
-       if (!inst->auth_user[0]) {
-               PDEBUG(DEBUG_SIP, "No credentials available\n");
-               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
-               add_trace("error", NULL, "There are no credentials given for interface");
-               end_trace();
-               return -1;
-       }
-
-       if (sip->sip_www_authenticate) {
-               authenticate = sip->sip_www_authenticate;
-       } else if (sip->sip_proxy_authenticate) {
-               authenticate = sip->sip_proxy_authenticate;
-       } else {
-               PDEBUG(DEBUG_SIP, "No authentication header found\n");
-               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
-               add_trace("error", NULL, "Authentication method unknwon");
-               end_trace();
-               return -1;
-       }
-
-       scheme = (char const *) authenticate->au_scheme;
-       if (authenticate->au_params) {
-               for (i = 0; (cur = (char *) authenticate->au_params[i]); i++) {
-                       if ((realm = strstr(cur, "realm="))) {
-                               realm += 6;
-                               break;
-                       }
-               }
-       }
-
-       if (!scheme || !realm) {
-               PDEBUG(DEBUG_SIP, "No scheme or no realm in authentication header found\n");
-               sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
-               add_trace("error", NULL, "Authentication header has no realm or scheme");
-               end_trace();
-               return -1;
-       }
-
-       SPRINT(authentication, "%s:%s:%s:%s", scheme, realm, inst->auth_user, inst->auth_password);
-       PDEBUG(DEBUG_SIP, "auth: '%s'\n", authentication);
-
-       sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
-       add_trace("scheme", NULL, "%s", scheme);
-       add_trace("realm", NULL, "%s", realm);
-       add_trace("user", NULL, "%s", inst->auth_user);
-       add_trace("pass", NULL, "%s", inst->auth_password);
-       end_trace();
-
-       nua_authenticate(nh, /*SIPTAG_EXPIRES_STR("3600"),*/ NUTAG_AUTH(authentication), TAG_END());
-
-       return 0;
-}
-
 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[])
 {
        struct sip_inst *inst = (struct sip_inst *) magic;
@@ -2002,82 +2092,69 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
        if (!nh)
                return;
 
-       if (inst->register_handle == nh) {
-               sip_trace_header(NULL, inst->interface_name, "STATUS", DIRECTION_OUT);
-               add_trace("value", NULL, "%d", status);
-               add_trace("phrase", NULL, "%s", phrase);
-               end_trace();
-
-               switch (status) {
-               case 200:
-                       status_200:
-                       /* if not registered, become registered and start register interval timer */
-                       if (inst->register_state != REGISTER_STATE_REGISTERED) {
-                               if (inst->register_interval)
-                                       schedule_timer(&inst->register_retry_timer, inst->register_interval, 0);
-                               inst->register_state = REGISTER_STATE_REGISTERED;
-                       }
-                       /* start option timer */
-                       if (inst->options_interval)
-                               schedule_timer(&inst->register_option_timer, inst->options_interval, 0);
-                       break;
-               case 401:
-               case 407:
-                       PDEBUG(DEBUG_SIP, "Register challenge received\n");
-                       rc = challenge(inst, NULL, status, phrase, nua, magic, nh, hmagic, sip, tags);
-                       if (rc < 0)
-                               goto status_400;
-                       break;
-               default:
-                       if (status >= 200 && status <= 299)
-                               goto status_200;
-                       if (status < 400)
+       /* hunt for existing handles */
+       port = port_first;
+       while(port) {
+               if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_SIP) {
+                       psip = (class Psip *)port;
+                       if (psip->p_s_handle == nh) {
                                break;
-                       status_400:
-                       PDEBUG(DEBUG_SIP, "Register failed, starting register timer\n");
-                       inst->register_state = REGISTER_STATE_FAILED;
-                       nua_handle_destroy(inst->register_handle);
-                       /* stop option timer */
-                       unsched_timer(&inst->register_option_timer);
-                       /* if failed, start register interval timer with REGISTER_RETRY_TIMER */
-                       schedule_timer(&inst->register_retry_timer, REGISTER_RETRY_TIMER);
-                       inst->register_handle = NULL;
-                       break;
+                       }
                }
-               return;
+               port = port->next;
        }
 
-       /* create or find port instance */
-       if (event == nua_i_invite)
-       {
-               char name[64];
-               struct interface *interface = interface_first;
+       /* new handle */
+       if (!port && !inst->register_handle) {
+               switch (event) {
+               case nua_i_register:
+                       PDEBUG(DEBUG_SIP, "New register instance\n");
+                       inst->register_handle = nh;
+                       break;
+               case nua_i_invite:
+                   {
+                       char name[64];
+                       struct interface *interface = interface_first;
 
-               /* create call instance */
-               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_s_handle == nh) {
+                       PDEBUG(DEBUG_SIP, "New psip instance\n");
+
+                       /* create call instance */
+                       SPRINT(name, "%s-%d-in", inst->interface_name, 0);
+                       while (interface) {
+                               if (!strcmp(interface->name, inst->interface_name))
                                        break;
-                               }
+                               interface = interface->next;
                        }
-                       port = port->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");
+                       break;
+                   }
+               default:
+                       PDEBUG(DEBUG_SIP, "Destroying unknown instance\n");
+                       nua_handle_destroy(nh);
+               }
+       }
+
+       /* handle register process */
+       if (inst->register_handle == nh) {
+               switch (event) {
+               case nua_i_register:
+                       i_register(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+                       break;
+               case nua_r_register:
+                       r_register(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+                       break;
+               default:
+                       PDEBUG(DEBUG_SIP, "Event %d not handled\n", event);
                }
+               return;
        }
+
+       /* handle port process */
        if (!psip) {
                PERROR("no SIP Port found for handel %p\n", nh);
                nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
@@ -2085,6 +2162,7 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
                return;
        }
 
+#warning fixme: wann eine response
        sip_trace_header(psip, inst->interface_name, "STATUS", DIRECTION_OUT);
        add_trace("value", NULL, "%d", status);
        add_trace("phrase", NULL, "%s", phrase);
@@ -2111,9 +2189,6 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
        case nua_i_state:
                PDEBUG(DEBUG_SIP, "state change received\n");
                break;
-       case nua_i_register:
-               PDEBUG(DEBUG_SIP, "register received\n");
-               break;
        case nua_i_invite:
                psip->i_invite(status, phrase, nua, magic, nh, hmagic, sip, tags);
                break;
@@ -2315,7 +2390,8 @@ int sip_init_inst(struct interface *interface)
                return -EINVAL;
        }
        nua_set_params(inst->nua,
-               SIPTAG_ALLOW_STR("INVITE,ACK,BYE,CANCEL,OPTIONS,NOTIFY,INFO"),
+               SIPTAG_ALLOW_STR("REGISTER,INVITE,ACK,BYE,CANCEL,OPTIONS,NOTIFY,INFO"),
+               NUTAG_APPL_METHOD("REGISTER"),
                NUTAG_APPL_METHOD("INVITE"),
                NUTAG_APPL_METHOD("ACK"),
 //             NUTAG_APPL_METHOD("BYE"), /* we must reply to BYE */
@@ -2481,9 +2557,9 @@ static void sip_handle_register(struct sip_inst *inst)
                        break;
                }
                /* apply handle to trace */
-               sip_trace_header(NULL, inst->interface_name, "NEW handle", DIRECTION_NONE);
-               add_trace("handle", "new", "0x%x", inst->register_handle);
-               end_trace();
+//             sip_trace_header(NULL, inst->interface_name, "NEW handle", DIRECTION_NONE);
+//             add_trace("handle", "new", "0x%x", inst->register_handle);
+//             end_trace();
 
                SPRINT(from, "sip:%s@%s", inst->register_user, inst->register_host);
                SPRINT(to, "sip:%s@%s", inst->register_user, inst->register_host);
@@ -2637,3 +2713,4 @@ void Psip::load_tx(void)
        rtp_send_frame(buf, SEND_SIP_LEN, (options.law=='a')?PAYLOAD_TYPE_ALAW:PAYLOAD_TYPE_ULAW);
 }
 
+#warning den source-port beim registrieren einstellen