static void tport_http_deliver(tport_t *self, msg_t *msg, su_time_t now) { tport_http_connect_instance_t *thci = (tport_http_connect_instance_t*)self; if (msg && thci->thci_response == msg) { tport_http_connect_t *thc = (tport_http_connect_t *)self->tp_pri; http_t *http = http_object(msg); if (http && http->http_status) { SU_DEBUG_0(("tport_http_connect: %u %s\n", http->http_status->st_status, http->http_status->st_phrase)); if (http->http_status->st_status < 300) { msg_buf_move(thci->thci_stackmsg, msg); thci->thci_response = NULL; thci->thci_stackmsg = NULL; return; } } msg_destroy(msg); thci->thci_response = NULL; tport_error_report(self, EPROTO, (void *)thc->thc_proxy->ai_addr); tport_close(self); return; } tport_base_deliver(self, msg, now); }
/*# Send a request to the protocol thread */ int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...) { su_msg_r sumsg = SU_MSG_R_INIT; size_t len, xtra, ee_len, l_len = 0, l_xtra = 0; ta_list ta; int retval = -1; if (nua == NULL) return -1; if (nua->nua_shutdown_started && event != nua_r_shutdown) return -1; ta_start(ta, tag, value); ee_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(ta_args(ta)); xtra = tl_xtra(ta_args(ta), len); if (su_msg_new(sumsg, ee_len + len + l_len + xtra + l_xtra) == 0) { nua_ee_data_t *ee = su_msg_data(sumsg); nua_event_data_t *e = ee->ee_data; tagi_t *t = e->e_tags; void *b = (char *)t + len + l_len; tagi_t *tend = (tagi_t *)b; char *bend = (char *)b + xtra + l_xtra; t = tl_dup(t, ta_args(ta), &b); assert(tend == t); (void)tend; assert(b == bend); (void)bend; e->e_always = event == nua_r_destroy || event == nua_r_shutdown; e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = phrase; su_msg_deinitializer(sumsg, nua_event_deinit); retval = su_msg_send_to(sumsg, nua->nua_server, nua_stack_signal); if (retval == 0){ SU_DEBUG_7(("nua(%p): %s signal %s\n", (void *)nh, "sent", nua_event_name(event) + 4)); } else { SU_DEBUG_0(("nua(%p): %s signal %s\n", (void *)nh, "FAILED TO SEND", nua_event_name(event) + 4)); } } ta_end(ta); return retval; }
nua_client_request_t * nua_client_request_ref_by(nua_client_request_t *cr, char const *where, unsigned line, char const *who) { SU_DEBUG_0(("%p ref %s to %u by %s:%u: %s()\n", cr, cr->cr_methods->crm_method_name, ++(cr->cr_refs), where, line, who)); return cr; }
su_home_t * _su_home_ref_by(su_home_t *home, char const *file, unsigned line, char const *function) { #ifdef DEBUG if (home) SU_DEBUG_0(("%ld %p - su_home_ref() => "MOD_ZU" by %s:%u: %s()\n", pthread_self(), home, su_home_refcount(home) + 1, file, line, function)); #endif return (su_home_t *)real_su_home_ref(home); }
int nua_client_request_unref_by(nua_client_request_t *cr, char const *where, unsigned line, char const *who) { SU_DEBUG_0(("%p unref %s to %u by %s:%u: %s()\n", cr, cr->cr_methods->crm_method_name, cr->cr_refs - 1, where, line, who)); if (cr->cr_refs > 1) { cr->cr_refs--; return 0; } else { cr->cr_refs = 0; nua_client_request_destroy(cr); return 1; } }
int _su_home_unref_by(su_home_t *home, char const *file, unsigned line, char const *function) { if (home) { size_t refcount = su_home_refcount(home) - 1; int freed = real_su_home_unref(home); if (freed) refcount = 0; #ifdef DEBUG SU_DEBUG_0(("%ld %p - su_home_unref() => "MOD_ZU" by %s:%u: %s()\n", pthread_self(), home, refcount, file, line, function)); #endif return freed; } return 0; }
static int nta_agent_message_callback(nta_agent_magic_t *context, nta_agent_t *agent, msg_t *msg, sip_t *sip) { int error; luasofia_nta_agent_t* u_nta_agent = (luasofia_nta_agent_t*) context; lua_State *L = u_nta_agent->L; SU_DEBUG_9(("nta_agent_message_callback: context[%p] agent[%p] msg[%p] sip[%p]\n", context, agent, msg, sip)); /* put nta_agent userdatum at stack and check if it is ok. */ luasofia_userdata_table_get(L, agent); luaL_checkudata(L, -1, NTA_AGENT_MTABLE); /* put callback function at stack */ lua_rawgeti(L, LUA_REGISTRYINDEX, u_nta_agent->callback_ref); if (lua_isnil(L, -1)) { lua_pop(L, 2); SU_DEBUG_1(("nta_agent_message_callback: callback function not found!\n")); return -1; //error, lets not return 0 (should always return 0). } // Lets pass the nta_agent userdata as the first parameter of the callback. lua_pushvalue(L, -2); lua_pushlightuserdata(L, msg); lua_pushlightuserdata(L, sip); SU_DEBUG_9(("nta_agent_message_callback: calling lua callback\n")); if ((error = lua_pcall(L, 3, 0, 0)) != 0) { if (error == LUA_ERRMEM) SU_DEBUG_0(("nta_agent_message_callback: memory allocation error! error[%s]\n", lua_tostring(L, -1))); else SU_DEBUG_1(("nta_agent_message_callback: error on calling callback! error[%s]\n", lua_tostring(L, -1))); lua_pop(L, 1); } lua_pop(L, 1); return 0; }
static void nua_client_request_destroy(nua_client_request_t *cr) { nua_handle_t *nh; if (cr == NULL) return; /* Possible references: */ assert(cr->cr_prev == NULL); /* queue */ assert(cr->cr_orq == NULL); /* transaction callback */ assert(cr->cr_timer == NULL); /* timer callback */ nh = cr->cr_owner; nua_destroy_signal(cr->cr_signal); nua_client_bind(cr, NULL); #if HAVE_MEMLEAK_LOG SU_DEBUG_0(("%p %s for %s\n", cr, __func__, cr->cr_methods->crm_method_name)); #endif if (cr->cr_msg) msg_destroy(cr->cr_msg); cr->cr_msg = NULL, cr->cr_sip = NULL; if (cr->cr_orq) nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; if (cr->cr_target) su_free(nh->nh_home, cr->cr_target); su_free(nh->nh_home, cr); nua_handle_unref(nh); }
/**Create a client request. * * @retval 0 if request is pending * @retval > 0 if error event has been sent * @retval < 0 upon an error */ int nua_client_create(nua_handle_t *nh, int event, nua_client_methods_t const *methods, tagi_t const * const tags) { su_home_t *home = nh->nh_home; nua_client_request_t *cr; sip_method_t method; char const *name; method = methods->crm_method, name = methods->crm_method_name; if (!name) { tagi_t const *t = tl_find_last(tags, nutag_method); if (t) name = (char const *)t->t_value; } cr = su_zalloc(home, sizeof *cr + methods->crm_extra); if (!cr) { return nua_stack_event(nh->nh_nua, nh, NULL, (enum nua_event_e)event, NUA_ERROR_AT(__FILE__, __LINE__), NULL); } cr->cr_methods = methods; cr->cr_event = event; cr->cr_method = method; cr->cr_method_name = name; cr->cr_contactize = methods->crm_flags.target_refresh; cr->cr_dialog = methods->crm_flags.create_dialog; cr->cr_auto = 1; if (su_msg_is_non_null(nh->nh_nua->nua_signal)) { nua_event_data_t *e = su_msg_data(nh->nh_nua->nua_signal)->ee_data; if (tags == e->e_tags && event == e->e_event) { cr->cr_auto = 0; if (tags) { nua_move_signal(cr->cr_signal, nh->nh_nua->nua_signal); if (cr->cr_signal) { /* Steal reference from signal */ cr->cr_owner = e->e_nh, e->e_nh = NULL; cr->cr_tags = tags; } } } } if (cr->cr_owner == NULL) cr->cr_owner = nua_handle_ref(nh); if (tags && cr->cr_tags == NULL) cr->cr_tags = tl_tlist(nh->nh_home, TAG_NEXT(tags)); #if HAVE_MEMLEAK_LOG SU_DEBUG_0(("%p %s() for %s\n", cr, __func__, cr->cr_methods->crm_method_name)); #endif if (nua_client_request_queue(cr)) return 0; return nua_client_init_request(cr); }
/* NUA event callback */ static void nua_event_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[]) { int error; lua_State *L = (lua_State *)magic; SU_DEBUG_9(("nua_event_callback: event[%s] status[%d] phrase[%s] " "nua[%p] magic[%p] nh[%p] hmagic[%p] sip[%p] tags[%p]\n", nua_event_name(event), status, phrase, nua, magic, nh, hmagic, sip, tags)); /* put nua userdatum at stack and check if it is ok. */ luasofia_userdata_table_get(L, nua); if (lua_isnil(L, -1)) { SU_DEBUG_1(("nua_event_callback: nua userdata not found on userdata_table!\n")); return; } luaL_checkudata(L, -1, NUA_MTABLE); /* put env table at stack */ lua_getfenv(L, -1); /* put callback table at stack */ lua_rawgeti(L, -1, ENV_CALLBACK_INDEX); if (lua_isnil(L, -1)) { lua_pop(L, 3); SU_DEBUG_1(("nua_event_callback: callback table not found!\n")); return; } /* get event callback */ lua_rawgeti(L, -1, event); if (lua_isnil(L, -1)) { lua_pop(L, 1); /* get event default callback */ lua_rawgeti(L, -1, NUA_EVENT_DEFAULT_INDEX); if (lua_isnil(L, -1)) { lua_pop(L, 4); SU_DEBUG_9(("nua_event_callback: event[%s] callback not found!\n", nua_event_name(event))); return; } } lua_pushinteger(L, event); lua_pushinteger(L, status); lua_pushstring(L, phrase); lua_pushvalue(L, -7); /* get magic field */ lua_rawgeti(L, -7, ENV_MAGIC_INDEX); if (nh) { /* put nua_handle userdatum at stack */ luasofia_userdata_table_get(L, nh); if (lua_isnil(L, -1)) { /* create a new nua_handle userdatum */ lua_pop(L, 1); luasofia_nua_handle_create_userdata(L, nh); lua_pushnil(L); } else { /* check if it is a nua_handle */ luaL_checkudata(L, -1, NUA_HANDLE_MTABLE); /* put env table at stack */ lua_getfenv(L, -1); } } else { lua_pushnil(L); lua_pushnil(L); } sip ? lua_pushlightuserdata(L, (void*)sip) : lua_pushnil(L); tags ? lua_pushlightuserdata(L, (void*)tags) : lua_pushnil(L); SU_DEBUG_9(("nua_event_callback: calling lua callback\n")); if ((error = lua_pcall(L, 9, 0, 0)) != 0) { if (error == LUA_ERRMEM) SU_DEBUG_0(("nua_event_callback: memory allocation error! error[%s]\n", lua_tostring(L, -1))); else SU_DEBUG_1(("nua_event_callback: error on calling callback! error[%s]\n", lua_tostring(L, -1))); lua_pop(L, 1); } lua_pop(L, 3); }
/** Read authentication database */ static int auth_readdb_internal(auth_mod_t *am, int always) { FILE *f; char *data, *s; size_t len, i, n, N; ssize_t slen; auth_passwd_t *apw; if (!am->am_stat) am->am_stat = su_zalloc(am->am_home, sizeof (*am->am_stat)); f = fopen(am->am_db, "rb"); if (f) { void *buffer = NULL; auth_passwd_t *fresh = NULL; #if HAVE_FLOCK int locked; /* Obtain shared lock on the database file */ if (flock(fileno(f), LOCK_SH | (always ? 0 : LOCK_NB)) == 0) { locked = 1; } else { locked = 0; if (errno == ENOLCK) { ; } else if (errno == EWOULDBLOCK) { SU_DEBUG_3(("auth(%s): user file \"%s\" is busy, trying again later\n", am->am_scheme->asch_method, am->am_db)); fclose(f); return always ? -1 : 0; } else { SU_DEBUG_3(("auth(%s): flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return always ? -1 : 0; } } #endif if (am->am_stat) stat(am->am_db, am->am_stat); /* too bad if this fails */ slen = readfile(am->am_home, f, &buffer, 1); #if HAVE_FLOCK /* Release shared lock on the database file */ if (locked && flock(fileno(f), LOCK_UN) == -1) { SU_DEBUG_0(("auth(%s): un-flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return -1; } #endif fclose(f); if (slen < 0) return -1; len = (size_t)slen; /* Count number of entries in new buffer */ for (i = am->am_anonymous, s = data = buffer; s < data + len; s += n + strspn(s + n, "\r\n")) { n = strcspn(s, "\r\n"); if (*s != '#' && *s != '\n' && *s != '\r') i++; } N = i, i = 0; if (N > 0) { size_t size = (N * 5 + 3) / 4; if (auth_htable_resize(am->am_home, am->am_users, size) < 0 || !(fresh = su_zalloc(am->am_home, sizeof(*fresh) * N))) { su_free(am->am_home, buffer); return -1; } } if (am->am_anonymous) { assert(i < N); apw = fresh + i++; apw->apw_index = msg_hash_string("anonymous"); apw->apw_user = "******"; apw->apw_pass = ""; apw->apw_realm = ""; am->am_anon_user = apw; if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } apw = NULL; for (data = buffer, s = data; s < data + len && i < N; s += n + strspn(s + n, "\r\n")) { char *user, *pass, *realm, *ident; n = strcspn(s, "\r\n"); if (*s == '#') continue; user = s; s[n++] = '\0'; if (!(pass = strchr(user, ':'))) continue; *pass++ = '\0'; if (!*pass || !*user) continue; if ((realm = strchr(pass, ':'))) *realm++ = '\0'; else realm = ""; if ((ident = strchr(realm, ':'))) *ident++ = '\0'; else ident = ""; apw = fresh + i++; apw->apw_index = msg_hash_string(user); apw->apw_user = user; apw->apw_ident = ident; /* Check for htdigest format */ if (span_hexdigit(realm) == 32 && realm[32] == '\0') { apw->apw_realm = pass; apw->apw_hash = realm; } else { apw->apw_pass = pass; apw->apw_realm = realm; } if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } assert(i <= N); N = i; /* Remove from hash those entries that were read from old passwd file */ for (i = 0; i < am->am_local_count; i++) { if (am->am_locals[i].apw_type == auth_apw_local) auth_htable_remove(am->am_users, &am->am_locals[i]); } if (am->am_locals) su_free(am->am_home, am->am_locals); /* Free old entries */ if (am->am_buffer) su_free(am->am_home, am->am_buffer); /* Free old passwd file contents */ SU_DEBUG_5(("auth(%s): read %u entries from \"%s\"\n", am->am_scheme->asch_method, (unsigned)N, am->am_db)); am->am_locals = fresh; am->am_local_count = N; am->am_buffer = buffer; return 0; } return -1; }
/**Process stun messagee. * * @retval -1 error * @retval 3 stun message received, ignore */ int tport_recv_stun_dgram(tport_t const *self, msg_t **in_out_msg, su_sockaddr_t *from, socklen_t fromlen) { int retval = -1; msg_t *msg; uint8_t *request; size_t n; assert(in_out_msg); assert(*in_out_msg); msg = *in_out_msg; request = msg_buf_committed_data(msg); n = msg_buf_committed(msg); if (n < 20 || request == NULL) { su_seterrno(EBADMSG); retval = -1; } else if (request[0] == 1) { /* This is a response. */ if (self->tp_pri->pri_vtable->vtp_stun_response) { if (self->tp_pri->pri_vtable->vtp_stun_response(self, request, n, from, fromlen) < 0) retval = -1; } else SU_DEBUG_7(("tport(%p): recv_stun_dgram(): " "ignoring request with "MOD_ZU" bytes\n", (void *)self, n)); } else if (request[0] == 0 && self->tp_master->mr_stun_server) { tport_stun_server_vtable_t const *vst = tport_stun_server_vtable; vst->vst_request(self->tp_master->mr_stun_server, self->tp_socket, request, n, (void *)from, fromlen); } else if (request[0] == 0) { /* Respond to stun request with a simple error message. */ int const status = 600; char const *error = "Not Implemented"; size_t unpadded = strlen(error); uint16_t elen; uint8_t dgram[128]; if (unpadded > sizeof(dgram) - 28) unpadded = sizeof(dgram) - 28; elen = (uint16_t)unpadded; elen = (elen + 3) & -4; /* Round up to 4 */ SU_DEBUG_7(("tport(%p): recv_stun_dgram(): " "responding %u %s\n", (void *)self, status, error)); /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | STUN Message Type | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Transaction ID +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ #define set16(b, offset, value) \ (((b)[(offset) + 0] = ((value) >> 8) & 255), \ ((b)[(offset) + 1] = (value) & 255)) /* Respond to request */ dgram[0] = 1; /* Mark as response */ dgram[1] = request[1] | 0x10; /* Mark as error response */ set16(dgram, 2, elen + 4 + 4); /* TransactionID is there at bytes 4..19 */ memcpy(dgram + 4, request + 4, 16); /* TLV At 20: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ set16(dgram, 20, 0x0009); /* ERROR-CODE */ set16(dgram, 22, elen + 4); /* ERROR-CODE at 24: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0 |Class| Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reason Phrase (variable) .. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ dgram[24] = 0, dgram[25] = 0; dgram[26] = status / 100, dgram[27] = status % 100; memcpy(dgram + 28, error, unpadded); memset(dgram + 28 + unpadded, 0, elen - unpadded); sendto(self->tp_socket, (void *)dgram, 28 + elen, 0, (void *)from, fromlen); #undef set16 } else { SU_DEBUG_0(("tport(%p): recv_stun_dgram(): internal error\n", (void *)self)); su_seterrno(EBADMSG); retval = -1; } *in_out_msg = NULL, msg_destroy(msg); return retval; }