/*
 * Initiate overlapped connect() operation (well, it's non-blocking actually,
 * since there's no overlapped version of connect()).
 */
PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_t *ioqueue,
					pj_ioqueue_key_t *key,
					const pj_sockaddr_t *addr,
					int addrlen )
{
    int status;
    
    /* check parameters. All must be specified! */
    pj_assert(ioqueue && key && addr && addrlen);

    /* Connecting socket must have no other operation! */
    pj_assert(key->op == 0);
    
    status = pj_sock_connect(key->fd, addr, addrlen);
    if (status == 0) {
	/* Connected! */
	return 0;
    } else {
	pj_status_t oserr = pj_getlasterror();
	if (oserr == PJ_EINPROGRESS || oserr == PJ_EWOULDBLOCK) {
	    /* Pending! */
	    pj_mutex_lock(ioqueue->mutex);
	    key->op = PJ_IOQUEUE_OP_CONNECT;
	    PJ_FD_SET(key->fd, &ioqueue->wfdset);
	    PJ_FD_SET(key->fd, &ioqueue->xfdset);
	    pj_mutex_unlock(ioqueue->mutex);
	    return PJ_IOQUEUE_PENDING;
	} else {
	    /* Error! */
	    return oserr;
	}
    }
}
Exemple #2
0
/*
 * do_select()
 *
 * Perform pj_sock_select() and find out which sockets
 * are signalled.
 */    
static int do_select( pj_sock_t sock1, pj_sock_t sock2,
		      int setcount[])
{
    pj_fd_set_t fds[3];
    pj_time_val timeout;
    int i, n;
    
    for (i=0; i<3; ++i) {
        PJ_FD_ZERO(&fds[i]);
        PJ_FD_SET(sock1, &fds[i]);
        PJ_FD_SET(sock2, &fds[i]);
        setcount[i] = 0;
    }

    timeout.sec = 1;
    timeout.msec = 0;

    n = pj_sock_select(PJ_IOQUEUE_MAX_HANDLES, &fds[0], &fds[1], &fds[2],
		       &timeout);
    if (n < 0)
        return n;
    if (n == 0)
        return 0;

    for (i=0; i<3; ++i) {
        if (PJ_FD_ISSET(sock1, &fds[i]))
            setcount[i]++;
        if (PJ_FD_ISSET(sock2, &fds[i]))
	    setcount[i]++;
    }

    return n;
}
/*
 * Initiate overlapped accept() operation.
 */
PJ_DEF(int) pj_ioqueue_accept( pj_ioqueue_t *ioqueue,
			       pj_ioqueue_key_t *key,
			       pj_sock_t *new_sock,
			       pj_sockaddr_t *local,
			       pj_sockaddr_t *remote,
			       int *addrlen)
{
    /* check parameters. All must be specified! */
    pj_assert(ioqueue && key && new_sock && local && remote && addrlen);

    /* Server socket must have no other operation! */
    pj_assert(key->op == 0);
    
    pj_mutex_lock(ioqueue->mutex);

    key->op = PJ_IOQUEUE_OP_ACCEPT;
    key->accept_fd = new_sock;
    key->rmt_addr = remote;
    key->rmt_addrlen = addrlen;
    key->local_addr = local;
    key->local_addrlen = addrlen;   /* use same addr. as rmt_addrlen */

    PJ_FD_SET(key->fd, &ioqueue->rfdset);

    pj_mutex_unlock(ioqueue->mutex);
    return PJ_IOQUEUE_PENDING;
}
Exemple #4
0
/*
 * ioqueue_add_to_set()
 * This function is called from pj_ioqueue_recv(), pj_ioqueue_send() etc
 * to instruct the ioqueue to add the specified handle to ioqueue's descriptor
 * set for the specified event.
 */
static void ioqueue_add_to_set( pj_ioqueue_t *ioqueue,
                                pj_ioqueue_key_t *key,
                                enum ioqueue_event_type event_type )
{
    pj_lock_acquire(ioqueue->lock);

    if (event_type == READABLE_EVENT)
        PJ_FD_SET((pj_sock_t)key->fd, &ioqueue->rfdset);
    else if (event_type == WRITEABLE_EVENT)
        PJ_FD_SET((pj_sock_t)key->fd, &ioqueue->wfdset);
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP!=0
    else if (event_type == EXCEPTION_EVENT)
        PJ_FD_SET((pj_sock_t)key->fd, &ioqueue->xfdset);
#endif
    else
        pj_assert(0);

    pj_lock_release(ioqueue->lock);
}
PJ_DEF(int) pj_ioqueue_read( pj_ioqueue_t *ioque,
			     pj_ioqueue_key_t *key,
			     void *buffer,
			     pj_size_t buflen)
{
    pj_mutex_lock(ioque->mutex);

    key->op |= PJ_IOQUEUE_OP_READ;
    key->rd_buf = buffer;
    key->rd_buflen = buflen;
    PJ_FD_SET(key->fd, &ioque->rfdset);

    pj_mutex_unlock(ioque->mutex);
    return PJ_IOQUEUE_PENDING;
}
Exemple #6
0
static int client_thread(void *unused)
{
    PJ_UNUSED_ARG(unused);

    while (!client->quit) {
	pj_fd_set_t readset;
	pj_time_val delay = {0, 10};

	/* Also poll the timer heap */
	pj_timer_heap_poll(stun_cfg.timer_heap, NULL);

	/* Poll client socket */
	PJ_FD_ZERO(&readset);
	PJ_FD_SET(client->sock, &readset);

	if (pj_sock_select((int)client->sock+1, &readset, NULL, NULL, &delay)==1 
	    && PJ_FD_ISSET(client->sock, &readset)) 
	{
	    char pkt[1000];
	    pj_ssize_t len;
	    pj_status_t status;
	    pj_sockaddr src_addr;
	    int src_addr_len;

	    len = sizeof(pkt);
	    src_addr_len = sizeof(src_addr);

	    status = pj_sock_recvfrom(client->sock, pkt, &len, 0, &src_addr, &src_addr_len);
	    if (status != PJ_SUCCESS)
		continue;

	    /* Increment client's receive count */
	    client->recv_count++;

	    /* Only pass to client if we allow to respond */
	    if (!client->responding)
		continue;

	    pj_stun_session_on_rx_pkt(client->sess, pkt, len, 
				      PJ_STUN_CHECK_PACKET | PJ_STUN_IS_DATAGRAM,
				      NULL, NULL, &src_addr, src_addr_len);
	}
 
    }

    return 0;
}
Exemple #7
0
static int server_thread(void *unused)
{
    PJ_UNUSED_ARG(unused);

    PJ_LOG(5,("", "    server thread started"));

    while (!server->quit) {
	pj_fd_set_t readset;
	pj_time_val delay = {0, 10};

	PJ_FD_ZERO(&readset);
	PJ_FD_SET(server->sock, &readset);

	if (pj_sock_select((int)server->sock+1, &readset, NULL, NULL, &delay)==1 
	    && PJ_FD_ISSET(server->sock, &readset)) 
	{
	    char pkt[1000];
	    pj_ssize_t len;
	    pj_status_t status;
	    pj_sockaddr src_addr;
	    int src_addr_len;

	    len = sizeof(pkt);
	    src_addr_len = sizeof(src_addr);

	    status = pj_sock_recvfrom(server->sock, pkt, &len, 0, &src_addr, &src_addr_len);
	    if (status != PJ_SUCCESS)
		continue;

	    /* Increment server's receive count */
	    server->recv_count++;

	    /* Only pass to server if we allow to respond */
	    if (!server->responding)
		continue;

	    pj_stun_session_on_rx_pkt(server->sess, pkt, len, 
				      PJ_STUN_CHECK_PACKET | PJ_STUN_IS_DATAGRAM,
				      NULL, NULL, &src_addr, src_addr_len);
	}
    }

    return 0;
}
PJ_DEF(int) pj_ioqueue_write( pj_ioqueue_t *ioque,
			      pj_ioqueue_key_t *key,
			      const void *data,
			      pj_size_t datalen)
{
    if (pj_sock_send(key->fd, data, datalen, 0) != (pj_ssize_t)datalen)
	return -1;

    pj_mutex_lock(ioque->mutex);

    key->op |= PJ_IOQUEUE_OP_WRITE;
    key->wr_buf = NULL;
    key->wr_buflen = datalen;
    PJ_FD_SET(key->fd, &ioque->wfdset);

    pj_mutex_unlock(ioque->mutex);

    return PJ_IOQUEUE_PENDING;
}
PJ_DEF(int) pj_ioqueue_recvfrom( pj_ioqueue_t *ioque,
				 pj_ioqueue_key_t *key,
				 void *buffer,
				 pj_size_t buflen,
				 pj_sockaddr_t *addr,
				 int *addrlen)
{
    pj_mutex_lock(ioque->mutex);

    key->op |= PJ_IOQUEUE_OP_RECV_FROM;
    key->rd_buf = buffer;
    key->rd_buflen = buflen;
    key->rmt_addr = addr;
    key->rmt_addrlen = addrlen;
    PJ_FD_SET(key->fd, &ioque->rfdset);

    pj_mutex_unlock(ioque->mutex);
    return PJ_IOQUEUE_PENDING;
}
Exemple #10
0
PJ_DEF(int) pj_ioqueue_sendto( pj_ioqueue_t *ioque,
			       pj_ioqueue_key_t *key,
			       const void *data,
			       pj_size_t datalen,
			       const pj_sockaddr_t *addr,
			       int addrlen)
{
    if (pj_sock_sendto(key->fd, data, datalen, 0, addr, addrlen) != (pj_ssize_t)datalen)
	return -1;

    pj_mutex_lock(ioque->mutex);

    key->op |= PJ_IOQUEUE_OP_SEND_TO;
    key->wr_buf = NULL;
    key->wr_buflen = datalen;
    PJ_FD_SET(key->fd, &ioque->wfdset);

    pj_mutex_unlock(ioque->mutex);
    return PJ_IOQUEUE_PENDING;
}
Exemple #11
0
static int server_thread_proc(void *p)
{
    struct stun_test_session *test_sess = (struct stun_test_session*)p;
    pj_pool_t *pool;
    pj_status_t status;

    PJ_LOG(4,(THIS_FILE, "Server thread running"));

    pool = pj_pool_create(test_sess->stun_cfg.pf, "server", 512, 512, NULL);

    while (!test_sess->thread_quit_flag) {
	pj_time_val timeout = {0, 10};
	pj_fd_set_t rdset;
	int n;

	/* Serve client */
	PJ_FD_ZERO(&rdset);
	PJ_FD_SET(test_sess->server_sock, &rdset);
	n = pj_sock_select(test_sess->server_sock+1, &rdset,
	                   NULL, NULL, &timeout);
	if (n==1 && PJ_FD_ISSET(test_sess->server_sock, &rdset)) {
	    pj_uint8_t pkt[512];
	    pj_ssize_t pkt_len;
	    pj_size_t res_len;
	    pj_sockaddr client_addr;
	    int addr_len;

	    pj_stun_msg	*stun_req, *stun_res;

	    pj_pool_reset(pool);

	    /* Got query */
	    pkt_len = sizeof(pkt);
	    addr_len = sizeof(client_addr);
	    status = pj_sock_recvfrom(test_sess->server_sock, pkt, &pkt_len,
	                              0, &client_addr, &addr_len);
	    if (status != PJ_SUCCESS) {
		continue;
	    }

	    status = pj_stun_msg_decode(pool, pkt, pkt_len,
	                                PJ_STUN_IS_DATAGRAM,
	                                &stun_req, NULL, NULL);
	    if (status != PJ_SUCCESS) {
		PJ_PERROR(1,(THIS_FILE, status, "STUN request decode error"));
		continue;
	    }

	    status = pj_stun_msg_create_response(pool, stun_req,
	                                         PJ_STUN_SC_BAD_REQUEST, NULL,
	                                         &stun_res);
	    if (status != PJ_SUCCESS) {
		PJ_PERROR(1,(THIS_FILE, status, "STUN create response error"));
		continue;
	    }

	    status = pj_stun_msg_encode(stun_res, pkt, sizeof(pkt), 0,
	                                NULL, &res_len);
	    if (status != PJ_SUCCESS) {
		PJ_PERROR(1,(THIS_FILE, status, "STUN encode error"));
		continue;
	    }

	    /* Ignore request */
	    if (test_sess->param.server_drop_request)
		continue;

	    /* Wait for signal to continue */
	    if (test_sess->param.server_wait_for_event)
		pj_event_wait(test_sess->server_event);

	    pkt_len = res_len;
	    pj_sock_sendto(test_sess->server_sock, pkt, &pkt_len, 0,
	                   &client_addr, pj_sockaddr_get_len(&client_addr));
	}
    }

    pj_pool_release(pool);

    PJ_LOG(4,(THIS_FILE, "Server thread quitting"));
    return 0;
}
Exemple #12
0
static int server_thread(void *p)
{
    struct server_t *srv = (struct server_t*)p;
    char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size);
    pj_sock_t newsock = PJ_INVALID_SOCKET;

    while (!thread_quit) {
	pj_ssize_t pkt_len;
	int rc;
        pj_fd_set_t rset;
	pj_time_val timeout = {0, 500};

	while (!thread_quit) {
	    PJ_FD_ZERO(&rset);
	    PJ_FD_SET(srv->sock, &rset);
	    rc = pj_sock_select((int)srv->sock+1, &rset, NULL, NULL, &timeout);
	    if (rc != 1) {
		continue;
	    }

	    rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL);
	    if (rc == PJ_SUCCESS) {
		break;
	    }
	}

	if (thread_quit)
	    break;

	while (!thread_quit) {
            PJ_FD_ZERO(&rset);
            PJ_FD_SET(newsock, &rset);
            rc = pj_sock_select((int)newsock+1, &rset, NULL, NULL, &timeout);
            if (rc != 1) {
        	PJ_LOG(3,("http test", "client timeout"));
                continue;
            }

            pkt_len = srv->buf_size;
            rc = pj_sock_recv(newsock, pkt, &pkt_len, 0);
            if (rc == PJ_SUCCESS) {
                break;
            }
        }

	if (thread_quit)
	    break;

	/* Simulate network RTT */
	pj_thread_sleep(50);

	if (srv->action == ACTION_IGNORE) {
	    continue;
	} else if (srv->action == ACTION_REPLY) {
            pj_size_t send_size = 0;
	    unsigned ctr = 0;
            pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n");
            if (srv->send_content_length) {
                pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), 
                                "Content-Length: %d\r\n",
                                srv->data_size);
            }
            pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n");
            pkt_len = pj_ansi_strlen(pkt);
            rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
            if (rc != PJ_SUCCESS) {
        	pj_sock_close(newsock);
        	continue;
            }
            while (send_size < srv->data_size) {
                pkt_len = srv->data_size - send_size;
                if (pkt_len > (signed)srv->buf_size)
                    pkt_len = srv->buf_size;
                send_size += pkt_len;
                pj_create_random_string(pkt, pkt_len);
                pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr);
                pkt[pj_ansi_strlen(pkt)] = '\n';
		rc = pj_sock_send(newsock, pkt, &pkt_len, 0);
		if (rc != PJ_SUCCESS)
		    break;
            }
            pj_sock_close(newsock);
	}
    }

    return 0;
}
PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
					    int sock_cnt, pj_sock_t sock[],
					    const pj_str_t *srv1, int port1,
					    const pj_str_t *srv2, int port2,
					    pj_sockaddr_in mapped_addr[])
{
    unsigned srv_cnt;
    pj_sockaddr_in srv_addr[2];
    int i, j, send_cnt = 0, nfds;
    pj_pool_t *pool;
    struct query_rec {
	struct {
	    pj_uint32_t	mapped_addr;
	    pj_uint32_t	mapped_port;
	} srv[2];
    } *rec;
    void       *out_msg;
    pj_size_t	out_msg_len;
    int wait_resp = 0;
    pj_status_t status;

    PJ_CHECK_STACK();

    TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()"));

    /* Create pool. */
    pool = pj_pool_create(pf, "stun%p", 400, 400, NULL);
    if (!pool)
	return PJ_ENOMEM;


    /* Allocate client records */
    rec = (struct query_rec*) pj_pool_calloc(pool, sock_cnt, sizeof(*rec));
    if (!rec) {
	status = PJ_ENOMEM;
	goto on_error;
    }

    TRACE_((THIS_FILE, "  Memory allocated."));

    /* Create the outgoing BIND REQUEST message template */
    status = pjstun_create_bind_req( pool, &out_msg, &out_msg_len, 
				      pj_rand(), pj_rand());
    if (status != PJ_SUCCESS)
	goto on_error;

    TRACE_((THIS_FILE, "  Binding request created."));

    /* Resolve servers. */
    status = pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1);
    if (status != PJ_SUCCESS)
		goto on_error;

    srv_cnt = 1;

    if (srv2 && port2) {
	status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2);
	if (status != PJ_SUCCESS)
		goto on_error;

	if (srv_addr[1].sin_addr.s_addr != srv_addr[0].sin_addr.s_addr &&
	    srv_addr[1].sin_port != srv_addr[0].sin_port)
	{
	    srv_cnt++;
	}
    }

    TRACE_((THIS_FILE, "  Server initialized, using %d server(s)", srv_cnt));

    /* Init mapped addresses to zero */
    pj_memset(mapped_addr, 0, sock_cnt * sizeof(pj_sockaddr_in));

    /* We need these many responses */
    wait_resp = sock_cnt * srv_cnt;

    TRACE_((THIS_FILE, "  Done initialization."));

#if defined(PJ_SELECT_NEEDS_NFDS) && PJ_SELECT_NEEDS_NFDS!=0
    nfds = -1;
    for (i=0; i<sock_cnt; ++i) {
	if (sock[i] > nfds) {
	    nfds = sock[i];
	}
    }
#else
    nfds = FD_SETSIZE-1;
#endif

    /* Main retransmission loop. */
    for (send_cnt=0; send_cnt<MAX_REQUEST; ++send_cnt) {
	pj_time_val next_tx, now;
	pj_fd_set_t r;
	int select_rc;

	PJ_FD_ZERO(&r);

	/* Send messages to servers that has not given us response. */
	for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) {
	    for (j=0; j<srv_cnt && status==PJ_SUCCESS; ++j) {
		pjstun_msg_hdr *msg_hdr = (pjstun_msg_hdr*) out_msg;
                pj_ssize_t sent_len;

		if (rec[i].srv[j].mapped_port != 0)
		    continue;

		/* Modify message so that we can distinguish response. */
		msg_hdr->tsx[2] = pj_htonl(i);
		msg_hdr->tsx[3] = pj_htonl(j);

		/* Send! */
                sent_len = out_msg_len;
		status = pj_sock_sendto(sock[i], out_msg, &sent_len, 0,
					(pj_sockaddr_t*)&srv_addr[j],
					sizeof(pj_sockaddr_in));
	    }
	}

	/* All requests sent.
	 * The loop below will wait for responses until all responses have
	 * been received (i.e. wait_resp==0) or timeout occurs, which then
	 * we'll go to the next retransmission iteration.
	 */
	TRACE_((THIS_FILE, "  Request(s) sent, counter=%d", send_cnt));

	/* Calculate time of next retransmission. */
	pj_gettimeofday(&next_tx);
	next_tx.sec += (stun_timer[send_cnt]/1000);
	next_tx.msec += (stun_timer[send_cnt]%1000);
	pj_time_val_normalize(&next_tx);
	
	for (pj_gettimeofday(&now), select_rc=1; 
	     status==PJ_SUCCESS && select_rc>=1 && wait_resp>0 
	       && PJ_TIME_VAL_LT(now, next_tx); 
	     pj_gettimeofday(&now)) 
	{
	    pj_time_val timeout;

	    timeout = next_tx;
	    PJ_TIME_VAL_SUB(timeout, now);

	    for (i=0; i<sock_cnt; ++i) {
		PJ_FD_SET(sock[i], &r);
	    }

	    select_rc = pj_sock_select(nfds+1, &r, NULL, NULL, &timeout);
	    TRACE_((THIS_FILE, "  select() rc=%d", select_rc));
	    if (select_rc < 1)
		continue;

	    for (i=0; i<sock_cnt; ++i) {
		int sock_idx, srv_idx;
                pj_ssize_t len;
		pjstun_msg msg;
		pj_sockaddr_in addr;
		int addrlen = sizeof(addr);
		pjstun_mapped_addr_attr *attr;
		char recv_buf[128];

		if (!PJ_FD_ISSET(sock[i], &r))
		    continue;

                len = sizeof(recv_buf);
		status = pj_sock_recvfrom( sock[i], recv_buf, 
				           &len, 0,
				           (pj_sockaddr_t*)&addr,
						   &addrlen);

		if (status != PJ_SUCCESS) {
		    char errmsg[PJ_ERR_MSG_SIZE];

		    PJ_LOG(4,(THIS_FILE, "recvfrom() error ignored: %s",
			      pj_strerror(status, errmsg,sizeof(errmsg)).ptr));

		    /* Ignore non-PJ_SUCCESS status.
		     * It possible that other SIP entity is currently 
		     * sending SIP request to us, and because SIP message
		     * is larger than STUN, we could get EMSGSIZE when
		     * we call recvfrom().
		     */
		    status = PJ_SUCCESS;
		    continue;
		}

		status = pjstun_parse_msg(recv_buf, len, &msg);
		if (status != PJ_SUCCESS) {
		    char errmsg[PJ_ERR_MSG_SIZE];

		    PJ_LOG(4,(THIS_FILE, "STUN parsing error ignored: %s",
			      pj_strerror(status, errmsg,sizeof(errmsg)).ptr));

		    /* Also ignore non-successful parsing. This may not
		     * be STUN response at all. See the comment above.
		     */
		    status = PJ_SUCCESS;
		    continue;
		}

		sock_idx = pj_ntohl(msg.hdr->tsx[2]);
		srv_idx = pj_ntohl(msg.hdr->tsx[3]);

		if (sock_idx<0 || sock_idx>=sock_cnt || sock_idx!=i ||
			srv_idx<0 || srv_idx>=2)
		{
		    status = PJLIB_UTIL_ESTUNININDEX;
		    continue;
		}

		if (pj_ntohs(msg.hdr->type) != PJSTUN_BINDING_RESPONSE) {
		    status = PJLIB_UTIL_ESTUNNOBINDRES;
		    continue;
		}

		if (rec[sock_idx].srv[srv_idx].mapped_port != 0) {
		    /* Already got response */
		    continue;
		}

		/* From this part, we consider the packet as a valid STUN
		 * response for our request.
		 */
		--wait_resp;

		if (pjstun_msg_find_attr(&msg, PJSTUN_ATTR_ERROR_CODE) != NULL) {
		    status = PJLIB_UTIL_ESTUNRECVERRATTR;
		    continue;
		}

		attr = (pjstun_mapped_addr_attr*) 
		       pjstun_msg_find_attr(&msg, PJSTUN_ATTR_MAPPED_ADDR);
		if (!attr) {
		    attr = (pjstun_mapped_addr_attr*) 
			   pjstun_msg_find_attr(&msg, PJSTUN_ATTR_XOR_MAPPED_ADDR);
		    if (!attr || attr->family != 1) {
			status = PJLIB_UTIL_ESTUNNOMAP;
			continue;
		    }
		}

		rec[sock_idx].srv[srv_idx].mapped_addr = attr->addr;
		rec[sock_idx].srv[srv_idx].mapped_port = attr->port;
		if (pj_ntohs(attr->hdr.type) == PJSTUN_ATTR_XOR_MAPPED_ADDR) {
		    rec[sock_idx].srv[srv_idx].mapped_addr ^= pj_htonl(STUN_MAGIC);
		    rec[sock_idx].srv[srv_idx].mapped_port ^= pj_htons(STUN_MAGIC >> 16);
		}
	    }
	}

	/* The best scenario is if all requests have been replied.
	 * Then we don't need to go to the next retransmission iteration.
	 */
	if (wait_resp <= 0)
	    break;
    }
Exemple #14
0
static int thread_proc(void *data) {
    dupsock_t *p_dupsock = (dupsock_t *)data;
    pj_thread_t *thread;
    pj_thread_desc desc;
    struct pj_time_val tv;
    int ret;
    pj_ssize_t ntemp;
    int sock_len;

//    pj_bzero(desc, sizeof(desc));
//    CHECK(__FILE__, pj_thread_register("dupsock", desc, &thread));

    PJ_FD_ZERO(&(p_dupsock->rfds));
    PJ_FD_ZERO(&(p_dupsock->wfds));

    PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->rfds));

    tv.sec = 0;
    tv.msec = 20;
    // MAIN LOOP
    p_dupsock->b_quit = 0;
    while( (!p_dupsock->b_quit) || (p_dupsock->wait_cnt > 0) || (p_dupsock->to_send != NULL) ) {
        if(p_dupsock->wait_cnt > 0) {
            p_dupsock->wait_cnt--;
            pj_event_pulse(p_dupsock->p_event);
        }

        pj_thread_sleep(10);

        PJ_FD_ZERO(&(p_dupsock->rfds));
        PJ_FD_ZERO(&(p_dupsock->wfds));

        PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->rfds));
        if(p_dupsock->to_send != NULL)
            PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->wfds));

        ret = pj_sock_select(*(p_dupsock->p_sock) + 1, &(p_dupsock->rfds), &(p_dupsock->wfds), NULL, &tv);
        if( ret < 0 ) {
            PJ_LOG(2, (__FILE__, "Error in select"));
        }
        else if (ret > 0) {
            if( PJ_FD_ISSET( *(p_dupsock->p_sock), &(p_dupsock->rfds)) ) {
                ntemp = sizeof(p_dupsock->in_buffer);
                sock_len = sizeof(p_dupsock->in_packet.addr);
                pj_sock_recvfrom(*(p_dupsock->p_sock), p_dupsock->in_packet.data, &ntemp, 0, (pj_sockaddr_t *)(&(p_dupsock->in_packet.addr)), &sock_len);
                p_dupsock->in_packet.len = ntemp;
                if(p_dupsock->recv_callback != NULL) {
                    p_dupsock->recv_callback(p_dupsock);
                }
                p_dupsock->in_packet.len = 0;
            }
            if( PJ_FD_ISSET( *(p_dupsock->p_sock), &(p_dupsock->wfds)) ) {
                ntemp = p_dupsock->to_send->len - p_dupsock->to_send->sent;
                pj_sock_sendto(*(p_dupsock->p_sock),
                               p_dupsock->to_send->data + p_dupsock->to_send->sent,
                               &ntemp, 0, (pj_sockaddr_t *)(&(p_dupsock->to_send->addr)), sizeof(p_dupsock->to_send->addr));
                p_dupsock->to_send->sent += ntemp;

                if(p_dupsock->to_send->len == p_dupsock->to_send->sent) {
                    if(p_dupsock->send_callback != NULL) {
                        p_dupsock->send_callback(p_dupsock);
                    }
                    p_dupsock->to_send = NULL;
                    PJ_FD_CLR(*(p_dupsock->p_sock), &(p_dupsock->wfds));
                }
            }
        }
        //PJ_LOG(5, (__FILE__, "end of a loop"));
    }
    pj_event_destroy(p_dupsock->p_event);
    pj_sock_close(*(p_dupsock->p_sock));
    return 0;
}
Exemple #15
0
PJ_DECL(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
					      int sock_cnt, pj_sock_t sock[],
					      const pj_str_t *srv1, int port1,
					      const pj_str_t *srv2, int port2,
					      pj_sockaddr_in mapped_addr[])
{
    pj_sockaddr_in srv_addr[2];
    int i, j, send_cnt = 0;
    pj_pool_t *pool;
    struct {
	struct {
	    pj_uint32_t	mapped_addr;
	    pj_uint32_t	mapped_port;
	} srv[2];
    } *rec;
    void       *out_msg;
    pj_size_t	out_msg_len;
    int wait_resp = 0;
    pj_status_t status;

    PJ_CHECK_STACK();

    /* Create pool. */
    pool = pj_pool_create(pf, "stun%p", 1024, 1024, NULL);
    if (!pool)
	return PJ_ENOMEM;


    /* Allocate client records */
    rec = pj_pool_calloc(pool, sock_cnt, sizeof(*rec));
    if (!rec) {
	status = PJ_ENOMEM;
	goto on_error;
    }


    /* Create the outgoing BIND REQUEST message template */
    status = pjstun_create_bind_req( pool, &out_msg, &out_msg_len, 
				      pj_rand(), pj_rand());
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Resolve servers. */
    status = pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Init mapped addresses to zero */
    pj_memset(mapped_addr, 0, sock_cnt * sizeof(pj_sockaddr_in));

    /* Main retransmission loop. */
    for (send_cnt=0; send_cnt<MAX_REQUEST; ++send_cnt) {
	pj_time_val next_tx, now;
	pj_fd_set_t r;
	int select_rc;

	PJ_FD_ZERO(&r);

	/* Send messages to servers that has not given us response. */
	for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) {
	    for (j=0; j<2 && status==PJ_SUCCESS; ++j) {
		pjstun_msg_hdr *msg_hdr = out_msg;
                pj_ssize_t sent_len;

		if (rec[i].srv[j].mapped_port != 0)
		    continue;

		/* Modify message so that we can distinguish response. */
		msg_hdr->tsx[2] = pj_htonl(i);
		msg_hdr->tsx[3] = pj_htonl(j);

		/* Send! */
                sent_len = out_msg_len;
		status = pj_sock_sendto(sock[i], out_msg, &sent_len, 0,
					(pj_sockaddr_t*)&srv_addr[j], 
					sizeof(pj_sockaddr_in));
		if (status == PJ_SUCCESS)
		    ++wait_resp;
	    }
	}

	/* All requests sent.
	 * The loop below will wait for responses until all responses have
	 * been received (i.e. wait_resp==0) or timeout occurs, which then
	 * we'll go to the next retransmission iteration.
	 */

	/* Calculate time of next retransmission. */
	pj_gettimeofday(&next_tx);
	next_tx.sec += (stun_timer[send_cnt]/1000);
	next_tx.msec += (stun_timer[send_cnt]%1000);
	pj_time_val_normalize(&next_tx);

	for (pj_gettimeofday(&now), select_rc=1; 
	     status==PJ_SUCCESS && select_rc==1 && wait_resp>0 
	       && PJ_TIME_VAL_LT(now, next_tx); 
	     pj_gettimeofday(&now)) 
	{
	    pj_time_val timeout;

	    timeout = next_tx;
	    PJ_TIME_VAL_SUB(timeout, now);

	    for (i=0; i<sock_cnt; ++i) {
		PJ_FD_SET(sock[i], &r);
	    }

	    select_rc = pj_sock_select(FD_SETSIZE, &r, NULL, NULL, &timeout);
	    if (select_rc < 1)
		continue;

	    for (i=0; i<sock_cnt; ++i) {
		int sock_idx, srv_idx;
                pj_ssize_t len;
		pjstun_msg msg;
		pj_sockaddr_in addr;
		int addrlen = sizeof(addr);
		pjstun_mapped_addr_attr *attr;
		char recv_buf[128];

		if (!PJ_FD_ISSET(sock[i], &r))
		    continue;

                len = sizeof(recv_buf);
		status = pj_sock_recvfrom( sock[i], recv_buf, 
				           &len, 0,
				           (pj_sockaddr_t*)&addr,
					   &addrlen);

		--wait_resp;

		if (status != PJ_SUCCESS)
		    continue;

		status = pjstun_parse_msg(recv_buf, len, &msg);
		if (status != PJ_SUCCESS) {
		    continue;
		}


		sock_idx = pj_ntohl(msg.hdr->tsx[2]);
		srv_idx = pj_ntohl(msg.hdr->tsx[3]);

		if (sock_idx<0 || sock_idx>=sock_cnt || srv_idx<0 || srv_idx>=2) {
		    status = PJLIB_UTIL_ESTUNININDEX;
		    continue;
		}

		if (pj_ntohs(msg.hdr->type) != PJSTUN_BINDING_RESPONSE) {
		    status = PJLIB_UTIL_ESTUNNOBINDRES;
		    continue;
		}

		if (pjstun_msg_find_attr(&msg, PJSTUN_ATTR_ERROR_CODE) != NULL) {
		    status = PJLIB_UTIL_ESTUNRECVERRATTR;
		    continue;
		}

		attr = (void*)pjstun_msg_find_attr(&msg, PJSTUN_ATTR_MAPPED_ADDR);
		if (!attr) {
		    status = PJLIB_UTIL_ESTUNNOMAP;
		    continue;
		}

		rec[sock_idx].srv[srv_idx].mapped_addr = attr->addr;
		rec[sock_idx].srv[srv_idx].mapped_port = attr->port;
	    }
	}

	/* The best scenario is if all requests have been replied.
	 * Then we don't need to go to the next retransmission iteration.
	 */
	if (wait_resp <= 0)
	    break;
    }

    for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) {
	if (rec[i].srv[0].mapped_addr == rec[i].srv[1].mapped_addr &&
	    rec[i].srv[0].mapped_port == rec[i].srv[1].mapped_port)
	{
	    mapped_addr[i].sin_family = PJ_AF_INET;
	    mapped_addr[i].sin_addr.s_addr = rec[i].srv[0].mapped_addr;
	    mapped_addr[i].sin_port = (pj_uint16_t)rec[i].srv[0].mapped_port;

	    if (rec[i].srv[0].mapped_addr == 0 || rec[i].srv[0].mapped_port == 0) {
		status = PJLIB_UTIL_ESTUNNOTRESPOND;
		break;
	    }
	} else {
	    status = PJLIB_UTIL_ESTUNSYMMETRIC;
	    break;
	}
    }

    pj_pool_release(pool);

    return status;

on_error:
    if (pool) pj_pool_release(pool);
    return status;
}
Exemple #16
0
int $UPROTO$_server_proc(void *param) {
    int ret;
    unsigned int len;
    
    int port;
    char *first, *second, *third;
    char cnt_str[30];

    pj_sockaddr_in caddr;
    char *caddr_str;
    pj_time_val timeout;

    pj_fd_set_t read_fds;

	char buffer[USERVER_BUFSIZE];
	$UPROTO$_request_t request;

    $UPROTO$_server_t *userver = ($UPROTO$_server_t *)param;
	ansi_copy_str(cnt_str, userver->connect_str);

    first = cnt_str;
    
    second = strchr(first, ':');
    EXIT_IF_TRUE(second == NULL, "Wrong connection string format\n");
    *second = '\0';
    second++;

    if(0 == strcmp(first, "udp")) {
        third = strchr(second, ':');
        EXIT_IF_TRUE(third == NULL, "Wrong connection string format\n");
        *third = '\0';
        third++;
        port = atoi(third);
        open_udp_socket(userver, second, port);
        if (userver->on_open_socket_f != NULL)
            userver->on_open_socket_f(userver);

        userver->recv_f = &udp_recvfrom;
        userver->send_f = &udp_sendto;
    }
    else if( 0 == strcmp(first, "tty") ) {
        open_tty(userver, second);
        userver->recv_f = &tty_recvfrom;
        userver->send_f = &tty_sendto;
    }
    else {
        EXIT_IF_TRUE(1, "Unsuported protocol\n");
    }

    // thread loop
    timeout.sec = 0;
    timeout.msec = 100;
    userver->is_end = 0;


    while( !userver->is_end ) {

        while (!userver->is_online) {
            SHOW_LOG(3, "Server is currently offline...\n");
            //usleep(8*1000*1000);
            pj_thread_sleep(1000);
        }

        PJ_FD_ZERO(&read_fds);
        PJ_FD_SET(userver->fd, &read_fds);

        pj_mutex_lock(userver->mutex);
        ret = pj_sock_select(userver->fd + 1, &read_fds, NULL, NULL, &timeout); 
        pj_mutex_unlock(userver->mutex);

        EXIT_IF_TRUE(ret < 0, "Error on server socket\n");

        if( PJ_FD_ISSET(userver->fd, &read_fds) ) {
            len = sizeof(caddr);
            pj_bzero(&caddr, len);

            pj_mutex_lock(userver->mutex);
            ret = userver->recv_f(userver->fd, buffer, USERVER_BUFSIZE, (void *)&caddr, &len);
            pj_mutex_unlock(userver->mutex);
            caddr_str = pj_inet_ntoa(caddr.sin_addr);

            if( ret > 0 ) {
                buffer[ret] = '\0';
                SHOW_LOG(5, "Received from client: %s\n", buffer);
                $UPROTO$_parse_request(buffer, ret, &request);
                userver->on_request_f(userver, &request, caddr_str);
            }
        }
        //usleep(100*1000);
        pj_thread_sleep(100);
        // if userver->fd is ready to write. When write finish, call userver->on_sent();
        // else --> time out
    }
	return 0;
}
Exemple #17
0
int $UPROTO$_secure_server_proc(void *param) {
    int ret;
    unsigned int len;
    
    int port;
    char *first, *second, *third;
    char cnt_str[30];

    pj_sockaddr_in caddr;
    char *caddr_str;
    pj_time_val timeout;

    pj_fd_set_t read_fds;

	char buffer[USERVER_BUFSIZE];

	$UPROTO$_request_t request;

    // For lvc parsing
    lvc_t lvc;
    int len1;
    char *val;
    uint32_t *ts;
    char sts[32];
    char plain[USERVER_BUFSIZE];
    char *pph;
    char otp[32];
    pj_str_t pjstr;
    // End for lvc parsing

    $UPROTO$_server_t *userver = ($UPROTO$_server_t *)param;
	ansi_copy_str(cnt_str, userver->connect_str);

    first = cnt_str;
    
    second = strchr(first, ':');
    EXIT_IF_TRUE(second == NULL, "Wrong connection string format\n");
    *second = '\0';
    second++;

    if(0 == strcmp(first, "udp")) {
        third = strchr(second, ':');
        EXIT_IF_TRUE(third == NULL, "Wrong connection string format\n");
        *third = '\0';
        third++;
        port = atoi(third);
        open_udp_socket(userver, second, port);
        if (userver->on_open_socket_f != NULL)
            userver->on_open_socket_f(userver);

        userver->recv_f = &udp_recvfrom;
        userver->send_f = &udp_sendto;
    }
    else if( 0 == strcmp(first, "tty") ) {
        open_tty(userver, second);
        userver->recv_f = &tty_recvfrom;
        userver->send_f = &tty_sendto;
    }
    else {
        EXIT_IF_TRUE(1, "Unsuported protocol\n");
    }

    // thread loop
    timeout.sec = 0;
    timeout.msec = 100;
    userver->is_end = 0;


    while( !userver->is_end ) {

        while (!userver->is_online) {
            SHOW_LOG(3, "Server is currently offline...\n");
            pj_thread_sleep(1000);
        }

        PJ_FD_ZERO(&read_fds);
        PJ_FD_SET(userver->fd, &read_fds);

        pj_mutex_lock(userver->mutex);
        ret = pj_sock_select(userver->fd + 1, &read_fds, NULL, NULL, &timeout); 
        pj_mutex_unlock(userver->mutex);

        EXIT_IF_TRUE(ret < 0, "Error on server socket\n");

        if( PJ_FD_ISSET(userver->fd, &read_fds) ) {
            len = sizeof(caddr);
            pj_bzero(&caddr, len);

            pj_mutex_lock(userver->mutex);
            ret = userver->recv_f(userver->fd, buffer, USERVER_BUFSIZE, (void *)&caddr, &len);
            pj_mutex_unlock(userver->mutex);
            caddr_str = pj_inet_ntoa(caddr.sin_addr);

            if( ret > 0 ) {
                buffer[ret] = '\0';

                lvc_init(&lvc, buffer, ret);

                lvc_unpack(&lvc, &len, &val);
                pj_strset(&pjstr, val, len);
                pph = userver->get_pph_f(&pjstr);
                if( pph != NULL ) {

                    lvc_unpack(&lvc, &len, &val);
                    ts = (uint32_t *)val;
                    ts2str(*ts, sts);

                    lvc_unpack(&lvc, &len, &val);
                    
                    generate_otp(otp, pph, sts);
                    do_decrypt(val, len, plain, &len1, otp);
                    if( pj_ansi_strncmp(sts, plain, len1) == 0 ) {
                        lvc_unpack(&lvc, &len, &val);
                        do_decrypt(val, len, plain, &len1, otp);
                        plain[len1] = '\0';

                        $UPROTO$_parse_request(plain, len1, &request);
                        userver->on_request_f(userver, &request, caddr_str);
                    }
                }
                //else {
                //}
            }
        }
        pj_thread_sleep(100);
    }
	return 0;
}
pj_status_t pj_open_tcp_serverport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	int enabled = 1;
	status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &enabled, sizeof(enabled));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	pj_sockaddr_in addr;
	status = pj_sockaddr_in_init(&addr, ip, port);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	status = pj_sock_bind(sock, &addr, pj_sockaddr_get_len(&addr));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	status = pj_sock_listen(sock, 5);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	return status;
}

pj_status_t pj_open_tcp_clientport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	pj_sockaddr_in addr;
	status = pj_sockaddr_in_init(&addr, ip, port);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	status = pj_sock_connect(sock, &addr, sizeof(addr));

	pj_time_val timeout = {2, 0}; // connect³¬Ê±Ê±¼ä1Ãë
	pj_fd_set_t rset, wset;
	PJ_FD_ZERO(&rset);
	PJ_FD_ZERO(&wset);
	PJ_FD_SET(sock, &rset);
	PJ_FD_SET(sock, &wset);

	int selret = pj_sock_select(sock + 1, &rset, &wset, nullptr, &timeout);
	switch(selret)
	{
		case -1:
			return PJ_EINVAL;
		case 0:
			return PJ_ETIMEDOUT;
		default:
		{
			if(PJ_FD_ISSET(sock, &rset) || PJ_FD_ISSET(sock, &wset))
			{
				return PJ_SUCCESS;
			}
			else
			{
				return PJ_EINVAL;
			}
		}
	}

	return PJ_EINVAL;
}

pj_status_t pj_open_udp_transport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	int enabled = 1;
	status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &enabled, sizeof(enabled));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	if ( ip != nullptr && port > 0 )
	{
		pj_sockaddr_in addr;
		status = pj_sockaddr_in_init(&addr, ip, port);
		RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

		status = pj_sock_bind(sock, &addr, pj_sockaddr_get_len(&addr));
		RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );
	}

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	return status;
}

pj_uint64_t pj_ntohll(pj_uint64_t netlonglong)
{
	return ntohll(netlonglong);
}

pj_uint64_t pj_htonll(pj_uint64_t hostlonglong)
{
	return htonll(hostlonglong);
}

static pj_oshandle_t g_log_handle;
pj_status_t log_open(pj_pool_t *pool, const pj_str_t &file_name)
{
	pj_log_set_log_func(log_writer);

	return pj_file_open(pool, file_name.ptr, PJ_O_WRONLY | PJ_O_APPEND, &g_log_handle);
}
PJ_DEF(int) pj_sock_select( int n, 
			    pj_fd_set_t *readfds, 
			    pj_fd_set_t *writefds,
			    pj_fd_set_t *exceptfds, 
			    const pj_time_val *timeout)
{
    CPjTimeoutTimer *pjTimer;
    unsigned i;

    PJ_UNUSED_ARG(n);
    PJ_UNUSED_ARG(writefds);
    PJ_UNUSED_ARG(exceptfds);

    if (timeout) {
	pjTimer = PjSymbianOS::Instance()->SelectTimeoutTimer();
	pjTimer->StartTimer(timeout->sec*1000 + timeout->msec);

    } else {
	pjTimer = NULL;
    }

    /* Scan for readable sockets */

    if (readfds) {
	symbian_fd_set *fds = (symbian_fd_set *)readfds;

	do {
	    /* Scan sockets for readily available data */
	    for (i=0; i<fds->count; ++i) {
		CPjSocket *pjsock = fds->sock[i];

		if (pjsock->Reader()) {
		    if (pjsock->Reader()->HasData() && !pjsock->Reader()->IsActive()) {

			/* Found socket with data ready */
			PJ_FD_ZERO(readfds);
			PJ_FD_SET((pj_sock_t)pjsock, readfds);

			/* Cancel timer, if any */
			if (pjTimer) {
			    pjTimer->Cancel();
			}

			/* Clear writable and exception fd_set */
			if (writefds)
			    PJ_FD_ZERO(writefds);
			if (exceptfds)
			    PJ_FD_ZERO(exceptfds);

			return 1;

		    } else if (!pjsock->Reader()->IsActive())
			pjsock->Reader()->StartRecvFrom();

		} else {
		    pjsock->CreateReader();
		    pjsock->Reader()->StartRecvFrom();
		}
	    }

	    PjSymbianOS::Instance()->WaitForActiveObjects();

	} while (pjTimer==NULL || !pjTimer->HasTimedOut());
    }


    /* Timeout */

    if (readfds)
	PJ_FD_ZERO(readfds);
    if (writefds)
	PJ_FD_ZERO(writefds);
    if (exceptfds)
	PJ_FD_ZERO(exceptfds);

    return 0;
}