Exemplo n.º 1
0
/*
 * Callback from TURN session to send outgoing packet.
 */
static pj_status_t turn_on_send_pkt(pj_turn_session *sess,
				    const pj_uint8_t *pkt,
				    unsigned pkt_len,
				    const pj_sockaddr_t *dst_addr,
				    unsigned dst_addr_len)
{
    pj_turn_sock *turn_sock = (pj_turn_sock*) 
			      pj_turn_session_get_user_data(sess);
    pj_ssize_t len = pkt_len;
    pj_status_t status;

    if (turn_sock == NULL || turn_sock->is_destroying) {
	/* We've been destroyed */
	// https://trac.pjsip.org/repos/ticket/1316
	//pj_assert(!"We should shutdown gracefully");
	return PJ_EINVALIDOP;
    }

    PJ_UNUSED_ARG(dst_addr);
    PJ_UNUSED_ARG(dst_addr_len);

    status = pj_activesock_send(turn_sock->active_sock, &turn_sock->send_key,
				pkt, &len, 0);
    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
	show_err(turn_sock, "socket send()", status);
    }

    return status;
}
Exemplo n.º 2
0
/* Flush all delayed transmision once the socket is connected. */
static void tcp_flush_pending_tx(struct tcp_transport *tcp)
{
    pj_lock_acquire(tcp->base.lock);
    while (!pj_list_empty(&tcp->delayed_list)) {
	struct delayed_tdata *pending_tx;
	pjsip_tx_data *tdata;
	pj_ioqueue_op_key_t *op_key;
	pj_ssize_t size;
	pj_status_t status;

	pending_tx = tcp->delayed_list.next;
	pj_list_erase(pending_tx);

	tdata = pending_tx->tdata_op_key->tdata;
	op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;

	/* send! */
	size = tdata->buf.cur - tdata->buf.start;
	status = pj_activesock_send(tcp->asock, op_key, tdata->buf.start, 
				    &size, 0);
	if (status != PJ_EPENDING) {
	    on_data_sent(tcp->asock, op_key, size);
	}

    }
    pj_lock_release(tcp->base.lock);
}
Exemplo n.º 3
0
/*
 * Callback from TURN session to send outgoing packet.
 */
static pj_status_t turn_on_send_pkt(pj_turn_session *sess,
				    const pj_uint8_t *pkt,
				    unsigned pkt_len,
				    const pj_sockaddr_t *dst_addr,
				    unsigned dst_addr_len)
{
    pj_turn_sock *turn_sock = (pj_turn_sock*) 
			      pj_turn_session_get_user_data(sess);
    pj_ssize_t len = pkt_len;
    pj_status_t status;
    pj_bool_t is_stun = PJ_FALSE;
    pj_bool_t is_tnl_data = PJ_FALSE;

    if (turn_sock == NULL) {
	/* We've been destroyed */
	// https://trac.pjsip.org/repos/ticket/1316
	//pj_assert(!"We should shutdown gracefully");
	return PJ_EINVALIDOP;
    }

    PJ_UNUSED_ARG(dst_addr);
    PJ_UNUSED_ARG(dst_addr_len);

    /* Check that this is STUN message */
    status = pj_stun_msg_check((const pj_uint8_t*)pkt, pkt_len, 
    			       PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET);
    if (status == PJ_SUCCESS) 
        is_stun = PJ_TRUE;
	else
		is_tnl_data = (((pj_uint8_t*)pkt)[pkt_len] == 1);

    if(is_stun || !is_tnl_data) {
        pj_ioqueue_op_key_t *op_key = (pj_ioqueue_op_key_t*)malloc(sizeof(pj_ioqueue_op_key_t));
        pj_ioqueue_op_key_init(op_key, sizeof(pj_ioqueue_op_key_t));
	    status = pj_activesock_send(turn_sock->active_sock, op_key,
			        pkt, &len, PJ_IOQUEUE_URGENT_DATA);
     } else {
	    status = pj_activesock_send(turn_sock->active_sock, &turn_sock->send_key,
		        	pkt, &len, 0);
    }

    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
	show_err(turn_sock, "socket send()", status);
    }

    return status;
}
Exemplo n.º 4
0
/* Flush all delayed transmision once the socket is connected. */
static void tcp_flush_pending_tx(struct tcp_transport *tcp)
{
    pj_time_val now;

    pj_gettickcount(&now);
    pj_lock_acquire(tcp->base.lock);
    while (!pj_list_empty(&tcp->delayed_list)) {
	struct delayed_tdata *pending_tx;
	pjsip_tx_data *tdata;
	pj_ioqueue_op_key_t *op_key;
	pj_ssize_t size;
	pj_status_t status;

	pending_tx = tcp->delayed_list.next;
	pj_list_erase(pending_tx);

	tdata = pending_tx->tdata_op_key->tdata;
	op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;

        if (pending_tx->timeout.sec > 0 &&
            PJ_TIME_VAL_GT(now, pending_tx->timeout))
        {
            continue;
        }

	/* send! */
	size = tdata->buf.cur - tdata->buf.start;
	status = pj_activesock_send(tcp->asock, op_key, tdata->buf.start, 
				    &size, 0);
	if (status != PJ_EPENDING) {
            pj_lock_release(tcp->base.lock);
	    on_data_sent(tcp->asock, op_key, size);
            pj_lock_acquire(tcp->base.lock);
	}

    }
    pj_lock_release(tcp->base.lock);
}
Exemplo n.º 5
0
/* This callback is called by the STUN session to send packet */
static pj_status_t sess_on_send_msg(pj_stun_session *sess,
				    void *token,
				    const void *pkt,
				    pj_size_t pkt_size,
				    const pj_sockaddr_t *dst_addr,
				    unsigned addr_len)
{
    pj_stun_sock *stun_sock;
    pj_ssize_t size;

    stun_sock = (pj_stun_sock *) pj_stun_session_get_user_data(sess);
    if (!stun_sock || !stun_sock->active_sock) {
	/* We have been shutdown, but this callback may still get called
	 * by retransmit timer.
	 */
	return PJ_EINVALIDOP;
    }

    pj_assert(token==INTERNAL_MSG_TOKEN);
    PJ_UNUSED_ARG(token);

    size = pkt_size;
    if( stun_sock->stunProtocol == 1 )
    {
	    pj_status_t status;
	    status = pj_activesock_send(stun_sock->active_sock, &stun_sock->int_send_key,
		pkt, &size, 0);
	    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
		    printf("err: in activesock send status=%d\n", status);
	    }
	    return status;
    }
    return pj_activesock_sendto(stun_sock->active_sock,
				&stun_sock->int_send_key,
				pkt, &size, 0, dst_addr, addr_len);
}
Exemplo n.º 6
0
static int tcp_perf_test(void)
{
    enum { COUNT=100000 };
    pj_pool_t *pool = NULL;
    pj_ioqueue_t *ioqueue = NULL;
    pj_sock_t sock1=PJ_INVALID_SOCKET, sock2=PJ_INVALID_SOCKET;
    pj_activesock_t *asock1 = NULL, *asock2 = NULL;
    pj_activesock_cb cb;
    struct tcp_state *state1, *state2;
    unsigned i;
    pj_status_t status;

    pool = pj_pool_create(mem, "tcpperf", 256, 256, NULL);

    status = app_socketpair(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock1, 
			    &sock2);
    if (status != PJ_SUCCESS) {
	status = -100;
	goto on_return;
    }

    status = pj_ioqueue_create(pool, 4, &ioqueue);
    if (status != PJ_SUCCESS) {
	status = -110;
	goto on_return;
    }

    pj_bzero(&cb, sizeof(cb));
    cb.on_data_read = &tcp_on_data_read;
    cb.on_data_sent = &tcp_on_data_sent;

    state1 = PJ_POOL_ZALLOC_T(pool, struct tcp_state);
    status = pj_activesock_create(pool, sock1, pj_SOCK_STREAM(), NULL, ioqueue,
				  &cb, state1, &asock1);
    if (status != PJ_SUCCESS) {
	status = -120;
	goto on_return;
    }

    state2 = PJ_POOL_ZALLOC_T(pool, struct tcp_state);
    status = pj_activesock_create(pool, sock2, pj_SOCK_STREAM(), NULL, ioqueue,
				  &cb, state2, &asock2);
    if (status != PJ_SUCCESS) {
	status = -130;
	goto on_return;
    }

    status = pj_activesock_start_read(asock1, pool, 1000, 0);
    if (status != PJ_SUCCESS) {
	status = -140;
	goto on_return;
    }

    /* Send packet as quickly as possible */
    for (i=0; i<COUNT && !state1->err && !state2->err; ++i) {
	struct tcp_pkt *pkt;
	struct send_key send_key[2], *op_key;
	pj_ssize_t len;

	pkt = (struct tcp_pkt*)state2->pkt;
	pkt->signature = SIGNATURE;
	pkt->seq = i;
	pj_memset(pkt->fill, 'a', sizeof(pkt->fill));

	op_key = &send_key[i%2];
	pj_ioqueue_op_key_init(&op_key->op_key, sizeof(*op_key));

	state2->sent = PJ_FALSE;
	len = sizeof(*pkt);
	status = pj_activesock_send(asock2, &op_key->op_key, pkt, &len, 0);
	if (status == PJ_EPENDING) {
	    do {
#if PJ_SYMBIAN
		pj_symbianos_poll(-1, -1);
#else
		pj_ioqueue_poll(ioqueue, NULL);
#endif
	    } while (!state2->sent);
	} else {
#if PJ_SYMBIAN
		/* The Symbian socket always returns PJ_SUCCESS for TCP send,
		 * eventhough the remote end hasn't received the data yet.
		 * If we continue sending, eventually send() will block,
		 * possibly because the send buffer is full. So we need to
		 * poll the ioqueue periodically, to let receiver gets the 
		 * data.
		 */
		pj_symbianos_poll(-1, 0);
#endif
		if (status != PJ_SUCCESS) {
		    PJ_LOG(1,("", "   err: send status=%d", status));
		    status = -180;
		    break;
		} else if (status == PJ_SUCCESS) {
		    if (len != sizeof(*pkt)) {
			PJ_LOG(1,("", "   err: shouldn't report partial sent"));
			status = -190;
			break;
		    }
		}
	}
    }

    /* Wait until everything has been sent/received */
    if (state1->next_recv_seq < COUNT) {
#ifdef PJ_SYMBIAN
	while (pj_symbianos_poll(-1, 1000) == PJ_TRUE)
	    ;
#else
	pj_time_val delay = {0, 100};
	while (pj_ioqueue_poll(ioqueue, &delay) > 0)
	    ;
#endif
    }

    if (status == PJ_EPENDING)
	status = PJ_SUCCESS;

    if (status != 0)
	goto on_return;

    if (state1->err) {
	status = -183;
	goto on_return;
    }
    if (state2->err) {
	status = -186;
	goto on_return;
    }
    if (state1->next_recv_seq != COUNT) {
	PJ_LOG(3,("", "   err: only %u packets received, expecting %u", 
		      state1->next_recv_seq, COUNT));
	status = -195;
	goto on_return;
    }

on_return:
    if (asock2)
	pj_activesock_close(asock2);
    if (asock1)
	pj_activesock_close(asock1);
    if (ioqueue)
	pj_ioqueue_destroy(ioqueue);
    if (pool)
	pj_pool_release(pool);

    return status;
}