/* open local RTP peer (if not bridging) */
if (rtp_connect() < 0) {
nua_cancel(p_s_handle, TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", p_s_handle);
nua_handle_destroy(p_s_handle);
p_s_handle = NULL;
sip_trace_header(this, inst->interface_name, "CANCEL", DIRECTION_OUT);
add_trace("respond", "value", "%d %s", status, status_text);
end_trace();
nua_respond(p_s_handle, status, status_text, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", p_s_handle);
nua_handle_destroy(p_s_handle);
p_s_handle = NULL;
trigger_work(&p_s_delete);
PDEBUG(DEBUG_SIP, "Using SDP for invite: %s\n", sdp_str);
SPRINT(from, "sip:%s@%s", p_callerinfo.id, remote);
+// SPRINT(from, "\"%s\" <sip:%s@%s>", /*p_callerinfo.id*/ "4946448519988", p_callerinfo.id, remote);
SPRINT(to, "sip:%s@%s", p_dialinginfo.id, remote);
if (inst->asserted_id[0]) {
SPRINT(asserted_id, "sip:%s@%s", inst->asserted_id, remote);
end_trace();
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
- nua_handle_destroy(nh);
- inst->register_handle = NULL;
}
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[])
add_trace("error", NULL, "forbidden, because we don't accept registration");
end_trace();
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
inst->register_handle = NULL;
return;
end_trace();
nua_respond(nh, status, auth_text, SIPTAG_CONTACT(sip->sip_contact), NUTAG_WITH_THIS_MSG(data->e_msg), TAG_IF(auth_str[0], SIPTAG_WWW_AUTHENTICATE_STR(auth_str)), TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
inst->register_handle = NULL;
}
inst->register_state = REGISTER_STATE_REGISTERED;
}
/* start option timer */
- if (inst->options_interval)
+ if (inst->options_interval) {
PDEBUG(DEBUG_SIP, "register ok, scheduling option timer with %d seconds\n", inst->options_interval);
schedule_timer(&inst->register_option_timer, inst->options_interval, 0);
+ }
break;
case 401:
case 407:
status_400:
PDEBUG(DEBUG_SIP, "Register failed, starting register timer\n");
inst->register_state = REGISTER_STATE_FAILED;
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
inst->register_handle = NULL;
/* stop option timer */
}
}
+static void r_options(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[])
+{
+ PDEBUG(DEBUG_SIP, "options result %d received\n", status);
+
+// if (status >= 200 && status <= 299) {
+ PDEBUG(DEBUG_SIP, "options ok, scheduling option timer with %d seconds\n", inst->options_interval);
+ /* restart option timer */
+ schedule_timer(&inst->register_option_timer, inst->options_interval, 0);
+ return;
+/// }
+
+ PDEBUG(DEBUG_SIP, "Register options failed, starting register timer\n");
+ inst->register_state = REGISTER_STATE_FAILED;
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
+ nua_handle_destroy(nh);
+ inst->register_handle = NULL;
+ /* 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;
PDEBUG(DEBUG_SIP, "invite received (%s->%s)\n", from, to);
sip_trace_header(this, inst->interface_name, "Authorization", DIRECTION_IN);
- if (inst->auth_realm[0] || p_state != PORT_STATE_IDLE) {
+ if (inst->auth_realm[0] && p_state == PORT_STATE_IDLE) {
/* only authenticate remote, if we have a realm set and we don't have re-invite */
authorization = sip->sip_proxy_authorization;
status = check_authorization(authorization, "INVITE", inst->auth_user, inst->auth_password, inst->auth_realm, inst->auth_nonce, &auth_text);
nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END());
else
nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
/* open local RTP peer (if not bridging) */
if (!p_s_rtp_bridge && rtp_open() < 0) {
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
if (rtp_connect() < 0) {
rtp_failed:
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
nua_respond(nh, SIP_200_OK, TAG_END());
}
+// code stolen from freeswitch....
+static char RFC2833_CHARS[] = "0123456789*#ABCDF";
+
+static char switch_rfc2833_to_char(int event)
+{
+ if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {
+ return RFC2833_CHARS[event];
+ }
+ return '\0';
+}
+
+void Psip::i_info(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;
+ char digit = '\0';
+
+ PDEBUG(DEBUG_SIP, "options received\n");
+
+ // code stolen from freeswitch....
+
+ if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype && sip->sip_payload && sip->sip_payload->pl_data) {
+ if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf-relay")) {
+ const char *signal_ptr;
+ if ((signal_ptr = strstr(sip->sip_payload->pl_data, "Signal="))) {
+ int tmp;
+ /* move signal_ptr where we need it (right past Signal=) */
+ signal_ptr = signal_ptr + 7;
+
+ /* handle broken devices with spaces after the = (cough) VegaStream (cough) */
+ while (*signal_ptr && *signal_ptr == ' ')
+ signal_ptr++;
+
+ if (*signal_ptr
+ && (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C'
+ || *signal_ptr == 'D')) {
+ digit = *signal_ptr;
+ } else {
+ tmp = atoi(signal_ptr);
+ digit = switch_rfc2833_to_char(tmp);
+ }
+ }
+
+ } else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf")) {
+ int tmp = atoi(sip->sip_payload->pl_data);
+ digit = switch_rfc2833_to_char(tmp);
+ }
+ }
+
+ sip_trace_header(this, inst->interface_name, "INFO", DIRECTION_IN);
+ if (digit) {
+ char digitstr[2] = { digit, '\0' };
+ struct lcr_msg *message;
+ add_trace("dtmf", "digit", digitstr);
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
+ message->param.dtmf = digit;
+ PDEBUG(DEBUG_SIP, "Psip(%s) INFO WITH DTMF digit '%c'\n", p_name, message->param.dtmf);
+ message_put(message);
+ }
+ end_trace();
+
+ nua_respond(nh, SIP_200_OK, TAG_END());
+}
+
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;
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
add_trace("respond", "value", "200 OK");
end_trace();
+ PDEBUG(DEBUG_SIP, "just remove nua_handle without destruction %x\n", nh);
// nua_handle_destroy(nh);
p_s_handle = NULL;
sip_trace_header(this, inst->interface_name, "CANCEL", DIRECTION_IN);
end_trace();
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
{
PDEBUG(DEBUG_SIP, "bye response received\n");
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
{
PDEBUG(DEBUG_SIP, "cancel response received\n");
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
return;
}
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
nua_handle_destroy(nh);
p_s_handle = NULL;
/* new handle */
switch (event) {
case nua_i_options:
- if (!inst->register_handle) {
- PDEBUG(DEBUG_SIP, "New options instance\n");
- inst->register_handle = nh;
+ if (!psip) {
+ i_options(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+ if (inst->register_handle != nh) {
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
+ nua_handle_destroy(nh);
+ }
+ return;
+ }
+ break;
+ case nua_r_options:
+ if (!psip) {
+ r_options(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+ return;
}
break;
case nua_i_register:
- if (!inst->register_handle) {
+ if (!psip && !inst->register_handle) {
PDEBUG(DEBUG_SIP, "New register instance\n");
inst->register_handle = nh;
}
+ if (!psip) {
+ i_register(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+ return;
+ }
+ break;
+ case nua_r_register:
+ if (!psip) {
+ r_register(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+ return;
+ }
break;
case nua_i_invite:
if (!psip) {
FATAL("Cannot create Port instance.\n");
}
break;
+ case nua_i_outbound:
+ PDEBUG(DEBUG_SIP, "Outbound status\n");
+ break;
default:
- if (!psip && !inst->register_handle) {
- PDEBUG(DEBUG_SIP, "Destroying unknown instance\n");
- nua_handle_destroy(nh);
- return;
- }
- }
-
- /* handle register process */
- if (inst->register_handle == nh) {
- switch (event) {
- case nua_i_options:
- i_options(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
- break;
- 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());
- nua_handle_destroy(nh);
+ if (nh != inst->register_handle) {
+ PERROR("no SIP Port found for handel %p\n", nh);
+ nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", nh);
+ nua_handle_destroy(nh);
+ }
return;
}
case nua_i_options:
psip->i_options(status, phrase, nua, magic, nh, hmagic, sip, tags);
break;
+ case nua_i_info:
+ psip->i_info(status, phrase, nua, magic, nh, hmagic, sip, tags);
+ break;
case nua_i_bye:
psip->i_bye(status, phrase, nua, magic, nh, hmagic, sip, tags);
break;
sip_trace_header(this, inst->interface_name, "RTP terminated", DIRECTION_IN);
end_trace();
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", p_s_handle);
nua_handle_destroy(p_s_handle);
p_s_handle = NULL;
class Psip *psip = (class Psip *)instance;
struct sip_inst *inst = (struct sip_inst *) psip->p_s_sip_inst;
+ PDEBUG(DEBUG_SIP, "invite options timer fired\n");
+
sip_trace_header(psip, inst->interface_name, "OPTIONS", psip->p_s_invite_direction);
end_trace();
if (inst->register_handle) {
/* stop option timer */
unsched_timer(&inst->register_option_timer);
+ PDEBUG(DEBUG_SIP, "nua_handle_destroy %x\n", inst->register_handle);
nua_handle_destroy(inst->register_handle);
inst->register_handle = NULL;
}
static int register_option_timer(struct lcr_timer *timer, void *instance, int index)
{
struct sip_inst *inst = (struct sip_inst *)instance;
+
+ PDEBUG(DEBUG_SIP, "register options timer fired\n");
+
sip_trace_header(NULL, inst->interface_name, "OPTIONS", DIRECTION_OUT);
end_trace();
char from[128] = "";
char to[128] = "";
char contact[128] = "";
+ char expires[128] = "";
switch (inst->register_state) {
case REGISTER_STATE_UNREGISTERED:
SCAT(contact, p);
}
+ if (inst->register_interval) {
+ SPRINT(expires, "%d", inst->register_interval + 60);
+ }
+
sip_trace_header(NULL, inst->interface_name, "REGISTER", DIRECTION_OUT);
add_trace("from", "uri", "%s", from);
add_trace("to", "uri", "%s", to);
+ if (expires[0])
+ add_trace("expires", NULL, "%s", expires);
end_trace();
nua_register(inst->register_handle,
TAG_IF(from[0], SIPTAG_FROM_STR(from)),
TAG_IF(to[0], SIPTAG_TO_STR(to)),
TAG_IF(contact[0], SIPTAG_CONTACT_STR(contact)),
+ TAG_IF(expires[0], SIPTAG_EXPIRES_STR(expires)),
TAG_END());
inst->register_state = REGISTER_STATE_REGISTERING;