+static void i_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[])
+{
+ #define NUTAG_WITH_THIS_MSG(msg) nutag_with, tag_ptr_v(msg)
+ nua_saved_event_t saved[1];
+ nua_save_event(nua, saved);
+ nua_event_data_t const *data = nua_event_data(saved);
+
+ sip_trace_header(NULL, inst->interface_name, "OPTIONS", DIRECTION_IN);
+ end_trace();
+
+ sip_trace_header(NULL, inst->interface_name, "RESPOND", DIRECTION_OUT);
+ add_trace("respond", "value", "200 OK");
+ end_trace();
+
+ nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
+ nua_handle_destroy(nh);
+ inst->options_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[])
+{
+ #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);
+ sip_authorization_t const *authorization;
+ char uri[256] = "";
+ const char *auth_text = NULL;
+ char auth_str[256] = "";
+
+ if (contact->m_url->url_host)
+ SCPY(uri, contact->m_url->url_host);
+ if (contact->m_url->url_port && contact->m_url->url_port[0]) {
+ SCAT(uri, ":");
+ SCAT(uri, contact->m_url->url_port);
+ }
+
+ if (!inst->allow_register) {
+ sip_trace_header(NULL, inst->interface_name, "REGISTER", DIRECTION_IN);
+ 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());
+ nua_handle_destroy(nh);
+ inst->register_handle = NULL;
+ return;
+ }
+
+ sip_trace_header(NULL, inst->interface_name, "REGISTER", DIRECTION_IN);
+ add_trace("contact", "uri", "%s", uri);
+ end_trace();
+
+ sip_trace_header(NULL, inst->interface_name, "Authorization", DIRECTION_IN);
+ if (inst->auth_realm[0]) {
+ authorization = sip->sip_authorization;
+ status = check_authorization(authorization, "REGISTER", inst->auth_user, inst->auth_password, inst->auth_realm, inst->auth_nonce, &auth_text);
+ if (status == 401) {
+ if (!inst->auth_nonce[0])
+ generate_nonce(inst->auth_nonce);
+ SPRINT(auth_str, "Digest realm=\"%s\", nonce=\"%s\", algorithm=MD5, qop=\"auth\"", inst->auth_realm, inst->auth_nonce);
+ }
+ } else {
+ status = 200;
+ auth_text = "Authentication not required";
+ }
+ add_trace("result", NULL, "%s", auth_text);
+ end_trace();
+
+ if (status == 200) {
+ SCPY(inst->remote_peer, uri);
+ }
+
+ sip_trace_header(NULL, inst->interface_name, "RESPOND", DIRECTION_OUT);
+ add_trace("respond", "value", "%d", status);
+ add_trace("reason", NULL, "peer registers");
+ 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());
+ 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)
+ 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:
+ 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[])