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);
}
示例#2
0
/*# 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;
}
示例#3
0
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;
}
示例#4
0
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);
}
示例#5
0
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;
  }
}
示例#6
0
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;
}
示例#7
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;
}
示例#8
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);
}
示例#9
0
/**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);
}
示例#10
0
/* 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);
}
示例#11
0
/** 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;
}