return(0);
#endif
}
-static int options_timer(struct interface *interface, char *filename, int line, char *parameter, char *value)
+static int options_interval(struct interface *interface, char *filename, int line, char *parameter, char *value)
{
#ifndef WITH_SIP
SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
}
if (!value || !value[0]) {
- SPRINT(interface_error, "Error in %s (line %d): Missing timer value.\n", filename, line);
+ SPRINT(interface_error, "Error in %s (line %d): Missing options interval.\n", filename, line);
return(-1);
}
- interface->sip_options_timer = atoi(value);
+ interface->sip_options_interval = atoi(value);
return(0);
#endif
SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
return(-1);
#else
- char *p;
+ char *p, *q;
if (!interface->sip) {
SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
SPRINT(interface_error, "Error in %s (line %d): Missing SIP host\n", filename, line);
return(-1);
}
+ q = get_seperated(p);
+ if (!q[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing register interval\n", filename, line);
+ return(-1);
+ }
interface->sip_register = 1;
SCPY(interface->sip_register_user, value);
SCPY(interface->sip_register_host, p);
+ interface->sip_register_interval = atoi(q);
return(0);
#endif
"Registers to given SIP registrar."},
{"authenticate", &inter_authenticate, "<user> <password>",
"Defines SIP user and password for authentication."},
- {"options-timer", &options_timer, "<timer> | 0",
+ {"options-interval", &options_interval, "<interval> | 0",
"Defines SIP timer to send OPTIONS messages to keepalive SIP sessions."},
{"public", &options_public, "<server> <interval>",
"Defines public IP, if this endpoint is behind NAT firewall."},
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;
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 */
}
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:
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;
}
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;
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) {
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;
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);
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;
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)
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;
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) {
}
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);
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();
nua_options(psip->p_s_handle,
TAG_END());
-// schedule_timer(&psip->p_s_invite_option_timer, inst->options_timeout, 0);
-
return 0;
}
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;
nua_options(inst->register_handle,
TAG_END());
-// schedule_timer(&inst->register_option_timer, inst->options_timeout, 0);
-
return 0;
}
}
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;