fixup register
[lcr.git] / sip.cpp
diff --git a/sip.cpp b/sip.cpp
index e136579..21e24d5 100644 (file)
--- a/sip.cpp
+++ b/sip.cpp
@@ -60,7 +60,8 @@ struct sip_inst {
        nua_handle_t            *register_handle;
        struct lcr_timer        register_retry_timer;
        struct lcr_timer        register_option_timer;
-       int                     options_timeout;
+       int                     register_interval;
+       int                     options_interval;
        char                    auth_user[128];
        char                    auth_password[128];
        su_root_t               *root;
@@ -1604,8 +1605,9 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        message_put(message);
 
        PDEBUG(DEBUG_SIP, "Invite received, scheduling option timer\n");
-       if (inst->options_timeout)
-               schedule_timer(&p_s_invite_option_timer, inst->options_timeout, 0);
+       /* start option timer */
+       if (inst->options_interval)
+               schedule_timer(&p_s_invite_option_timer, inst->options_interval, 0);
        p_s_invite_direction = DIRECTION_IN;
 
        /* send progress, if tones are available and if we don't bridge */
@@ -1809,8 +1811,9 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        }
 
        PDEBUG(DEBUG_SIP, "Invite response, scheduling option timer\n");
-       if (inst->options_timeout)
-               schedule_timer(&p_s_invite_option_timer, inst->options_timeout, 0);
+       /* start option timer */
+       if (inst->options_interval)
+               schedule_timer(&p_s_invite_option_timer, inst->options_interval, 0);
 
        switch (status) {
        case 100:
@@ -1899,7 +1902,8 @@ void Psip::r_options(int status, char const *phrase, nua_t *nua, nua_magic_t *ma
 
        if (status >= 200 && status <= 299) {
                PDEBUG(DEBUG_SIP, "options ok, scheduling timer\n");
-               schedule_timer(&p_s_invite_option_timer, inst->options_timeout, 0);
+               /* restart option timer */
+               schedule_timer(&p_s_invite_option_timer, inst->options_interval, 0);
                return;
        }
 
@@ -1924,7 +1928,7 @@ void Psip::r_options(int status, char const *phrase, nua_t *nua, nua_magic_t *ma
        trigger_work(&p_s_delete);
 }
 
-static void 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[])
+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;
@@ -1932,9 +1936,16 @@ static void challenge(struct sip_inst *inst, class Psip *psip, int status, char
        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) {
@@ -1944,7 +1955,7 @@ static void challenge(struct sip_inst *inst, class Psip *psip, int status, char
                sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
                add_trace("error", NULL, "Authentication method unknwon");
                end_trace();
-               return;
+               return -1;
        }
 
        scheme = (char const *) authenticate->au_scheme;
@@ -1962,7 +1973,7 @@ static void challenge(struct sip_inst *inst, class Psip *psip, int status, char
                sip_trace_header(psip, inst->interface_name, "AUTHENTICATE", DIRECTION_OUT);
                add_trace("error", NULL, "Authentication header has no realm or scheme");
                end_trace();
-               return;
+               return -1;
        }
 
        SPRINT(authentication, "%s:%s:%s:%s", scheme, realm, inst->auth_user, inst->auth_password);
@@ -1976,6 +1987,8 @@ static void challenge(struct sip_inst *inst, class Psip *psip, int status, char
        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[])
@@ -1983,6 +1996,7 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
        struct sip_inst *inst = (struct sip_inst *) magic;
        class Port *port;
        class Psip *psip = NULL;
+       int rc;
 
        PDEBUG(DEBUG_SIP, "Event %d from SIP stack received (handle=%p)\n", event, nh);
        if (!nh)
@@ -1997,24 +2011,35 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
                switch (status) {
                case 200:
                        status_200:
-                       inst->register_state = REGISTER_STATE_REGISTERED;
-                       if (inst->options_timeout)
-                               schedule_timer(&inst->register_option_timer, inst->options_timeout, 0);
+                       /* 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");
-                       challenge(inst, NULL, status, phrase, nua, magic, nh, hmagic, sip, tags);
+                       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(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;
@@ -2068,8 +2093,9 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
        switch (status) {
        case 401:
        case 407:
-               challenge(inst, psip, status, phrase, nua, magic, nh, hmagic, sip, tags);
-               return;
+               rc = challenge(inst, psip, status, phrase, nua, magic, nh, hmagic, sip, tags);
+               if (rc >= 0)
+                       return;
        }
 
        switch (event) {
@@ -2138,6 +2164,7 @@ static void stun_bind_cb(stun_discovery_magic_t *magic, stun_handle_t *sh, stun_
                }
                su_inet_ntop(sa.su_family, SU_ADDR(&sa), inst->public_ip, sizeof(inst->public_ip));
                inst->stun_state = STUN_STATE_RESOLVED;
+               /* start timer for next stun request with inst->stun_interval */
                schedule_timer(&inst->stun_retry_timer, inst->stun_interval, 0);
                sip_trace_header(NULL, inst->interface_name, "STUN resolved", DIRECTION_OUT);
                add_trace("ip", "addr", "%s", inst->public_ip);
@@ -2147,6 +2174,7 @@ static void stun_bind_cb(stun_discovery_magic_t *magic, stun_handle_t *sh, stun_
 failed:
                PDEBUG(DEBUG_SIP, "STUN failed, starting timer\n");
                inst->stun_state = STUN_STATE_FAILED;
+               /* start timer for next stun request (after failing) with STUN_RETRY_TIMER */
                schedule_timer(&inst->stun_retry_timer, STUN_RETRY_TIMER);
                sip_trace_header(NULL, inst->interface_name, "STUN failed", DIRECTION_OUT);
                end_trace();
@@ -2191,8 +2219,6 @@ static int invite_option_timer(struct lcr_timer *timer, void *instance, int inde
        nua_options(psip->p_s_handle,
                TAG_END());
 
-//     schedule_timer(&psip->p_s_invite_option_timer, inst->options_timeout, 0);
-
        return 0;
 }
 
@@ -2211,6 +2237,14 @@ static int register_retry_timer(struct lcr_timer *timer, void *instance, int ind
        struct sip_inst *inst = (struct sip_inst *)instance;
 
        PDEBUG(DEBUG_SIP, "timeout, restart register\n");
+       /* if we have a handle, destroy it and becom unregistered, so registration is
+        * triggered next */
+       if (inst->register_handle) {
+               /* stop option timer */
+               unsched_timer(&inst->register_option_timer);
+               nua_handle_destroy(inst->register_handle);
+               inst->register_handle = NULL;
+       }
        inst->register_state = REGISTER_STATE_UNREGISTERED;
 
        return 0;
@@ -2225,8 +2259,6 @@ static int register_option_timer(struct lcr_timer *timer, void *instance, int in
        nua_options(inst->register_handle,
                TAG_END());
 
-//     schedule_timer(&inst->register_option_timer, inst->options_timeout, 0);
-
        return 0;
 }
 
@@ -2246,7 +2278,8 @@ int sip_init_inst(struct interface *interface)
        }
        SCPY(inst->auth_user, interface->sip_auth_user);
        SCPY(inst->auth_password, interface->sip_auth_password);
-       inst->options_timeout = interface->sip_options_timer;
+       inst->register_interval = interface->sip_register_interval;
+       inst->options_interval = interface->sip_options_interval;
 
        inst->rtp_port_from = interface->rtp_port_from;
        inst->rtp_port_to = interface->rtp_port_to;