Exemplo n.º 1
0
/* Apply QoS */
PJ_DEF(pj_status_t) pj_sock_apply_qos( pj_sock_t sock,
				       pj_qos_type qos_type,
				       pj_qos_params *qos_params,
				       unsigned log_level,
				       const char *log_sender,
				       const char *sock_name)
{
    pj_status_t qos_type_rc = PJ_SUCCESS,
		qos_params_rc = PJ_SUCCESS;

    if (!log_sender)
	log_sender = THIS_FILE;
    if (!sock_name)
	sock_name = "socket";

    if (qos_type != PJ_QOS_TYPE_BEST_EFFORT) {
	qos_type_rc = pj_sock_set_qos_type(sock, qos_type);

	if (qos_type_rc != PJ_SUCCESS) {
	    pj_perror(log_level, log_sender,  qos_type_rc, 
		      "Error setting QoS type %d to %s", 
		      qos_type, sock_name);
	}
    }

    if (qos_params && qos_params->flags) {
	qos_params_rc = pj_sock_set_qos_params(sock, qos_params);
	if (qos_params_rc != PJ_SUCCESS) {
	    pj_perror(log_level, log_sender,  qos_params_rc, 
		      "Error setting QoS params (flags=%d) to %s", 
		      qos_params->flags, sock_name);
	    if (qos_type_rc != PJ_SUCCESS)
		return qos_params_rc;
	}
    } else if (qos_type_rc != PJ_SUCCESS)
	return qos_type_rc;

    return PJ_SUCCESS;
}
Exemplo n.º 2
0
static pj_status_t codec_get_frame(pjmedia_port *port,
                                   pjmedia_frame *frame)
{
    codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
    pjmedia_vid_codec *codec = port_data->codec;
    pjmedia_frame enc_frame;
    pj_status_t status;

    enc_frame.buf = port_data->enc_buf;
    enc_frame.size = port_data->enc_buf_size;

    if (port_data->conv) {
        pj_size_t frame_size = frame->size;

        status = pjmedia_port_get_frame(port_data->src_port, frame);
        if (status != PJ_SUCCESS) goto on_error;

        status = pjmedia_vid_codec_decode(codec, 1, frame,
                                          frame->size, &enc_frame);
        if (status != PJ_SUCCESS) goto on_error;

        frame->size = frame_size;
        status = pjmedia_converter_convert(port_data->conv, &enc_frame, frame);
        if (status != PJ_SUCCESS) goto on_error;

        return PJ_SUCCESS;
    }

    status = pjmedia_port_get_frame(port_data->src_port, &enc_frame);
    if (status != PJ_SUCCESS) goto on_error;

    status = pjmedia_vid_codec_decode(codec, 1, &enc_frame,
                                      frame->size, frame);
    if (status != PJ_SUCCESS) goto on_error;

    return PJ_SUCCESS;

on_error:
    pj_perror(3, THIS_FILE, status, "codec_get_frame() error");
    return status;
}
Exemplo n.º 3
0
int errno_test(void)
{
    enum { CUT = 6 };
    pj_status_t rc = 0;
    char errbuf[256];

    PJ_LOG(3,(THIS_FILE, "...errno test: check the msg carefully"));

    PJ_UNUSED_ARG(rc);
    
    /* 
     * Windows platform error. 
     */
#   ifdef ERROR_INVALID_DATA
    rc = PJ_STATUS_FROM_OS(ERROR_INVALID_DATA);
    pj_set_os_error(rc);

    /* Whole */
    pj_strerror(rc, errbuf, sizeof(errbuf));
    trim_newlines(errbuf);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA: '%s'", errbuf));
    if (my_stristr(errbuf, "invalid") == NULL) {
        PJ_LOG(3, (THIS_FILE, 
                   "...error: expecting \"invalid\" string in the msg"));
#ifndef PJ_WIN32_WINCE
        return -20;
#endif
    }

    /* Cut version. */
    pj_strerror(rc, errbuf, CUT);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=ERROR_INVALID_DATA (cut): '%s'", errbuf));
#   endif

    /*
     * Unix errors
     */
#   if defined(EINVAL) && !defined(PJ_SYMBIAN)
    rc = PJ_STATUS_FROM_OS(EINVAL);
    pj_set_os_error(rc);

    /* Whole */
    pj_strerror(rc, errbuf, sizeof(errbuf));
    trim_newlines(errbuf);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL: '%s'", errbuf));
    if (my_stristr(errbuf, "invalid") == NULL) {
        PJ_LOG(3, (THIS_FILE, 
                   "...error: expecting \"invalid\" string in the msg"));
        return -30;
    }

    /* Cut */
    pj_strerror(rc, errbuf, CUT);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=EINVAL (cut): '%s'", errbuf));
#   endif

    /* 
     * Windows WSA errors
     */
#   ifdef WSAEINVAL
    rc = PJ_STATUS_FROM_OS(WSAEINVAL);
    pj_set_os_error(rc);

    /* Whole */
    pj_strerror(rc, errbuf, sizeof(errbuf));
    trim_newlines(errbuf);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL: '%s'", errbuf));
    if (my_stristr(errbuf, "invalid") == NULL) {
        PJ_LOG(3, (THIS_FILE, 
                   "...error: expecting \"invalid\" string in the msg"));
        return -40;
    }

    /* Cut */
    pj_strerror(rc, errbuf, CUT);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=WSAEINVAL (cut): '%s'", errbuf));
#   endif

    pj_strerror(PJ_EBUG, errbuf, sizeof(errbuf));
    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG: '%s'", errbuf));
    if (my_stristr(errbuf, "BUG") == NULL) {
        PJ_LOG(3, (THIS_FILE, 
                   "...error: expecting \"BUG\" string in the msg"));
        return -20;
    }

    pj_strerror(PJ_EBUG, errbuf, CUT);
    PJ_LOG(3,(THIS_FILE, "...msg for rc=PJ_EBUG, cut at %d chars: '%s'", 
              CUT, errbuf));

    /* Perror */
    pj_perror(3, THIS_FILE, PJ_SUCCESS, "...testing %s", "pj_perror");
    PJ_PERROR(3,(THIS_FILE, PJ_SUCCESS, "...testing %s", "PJ_PERROR"));

    return 0;
}
Exemplo n.º 4
0
/*
 * Callback from TURN session when state has changed
 */
static void turn_on_state(pj_turn_session *sess, 
			  pj_turn_state_t old_state,
			  pj_turn_state_t new_state)
{
    pj_turn_sock *turn_sock = (pj_turn_sock*) 
			   pj_turn_session_get_user_data(sess);
    pj_status_t status;

    if (turn_sock == NULL) {
	/* We've been destroyed */
	return;
    }

    /* Notify app first */
    if (turn_sock->cb.on_state) {
	(*turn_sock->cb.on_state)(turn_sock, old_state, new_state);
    }

    /* Make sure user hasn't destroyed us in the callback */
    if (turn_sock->sess && new_state == PJ_TURN_STATE_RESOLVED) {
	pj_turn_session_info info;
	pj_turn_session_get_info(turn_sock->sess, &info);
	new_state = info.state;
    }

    if (turn_sock->sess && new_state == PJ_TURN_STATE_RESOLVED) {
	/*
	 * Once server has been resolved, initiate outgoing TCP
	 * connection to the server.
	 */
	pj_turn_session_info info;
	char addrtxt[PJ_INET6_ADDRSTRLEN+8];
	int sock_type;
	pj_sock_t sock;
	pj_activesock_cfg asock_cfg;
	pj_activesock_cb asock_cb;
	pj_sockaddr bound_addr, *cfg_bind_addr;
	pj_uint16_t max_bind_retry;

	/* Close existing connection, if any. This happens when
	 * we're switching to alternate TURN server when either TCP
	 * connection or ALLOCATE request failed.
	 */
	if (turn_sock->active_sock) {
	    pj_activesock_close(turn_sock->active_sock);
	    turn_sock->active_sock = NULL;
	}

	/* Get server address from session info */
	pj_turn_session_get_info(sess, &info);

	if (turn_sock->conn_type == PJ_TURN_TP_UDP)
	    sock_type = pj_SOCK_DGRAM();
	else
	    sock_type = pj_SOCK_STREAM();

	/* Init socket */
	status = pj_sock_socket(turn_sock->af, sock_type, 0, &sock);
	if (status != PJ_SUCCESS) {
	    pj_turn_sock_destroy(turn_sock);
	    return;
	}

	/* Bind socket */
	cfg_bind_addr = &turn_sock->setting.bound_addr;
	max_bind_retry = MAX_BIND_RETRY;
	if (turn_sock->setting.port_range &&
	    turn_sock->setting.port_range < max_bind_retry)
	{
	    max_bind_retry = turn_sock->setting.port_range;
	}
	pj_sockaddr_init(turn_sock->af, &bound_addr, NULL, 0);
	if (cfg_bind_addr->addr.sa_family == pj_AF_INET() || 
	    cfg_bind_addr->addr.sa_family == pj_AF_INET6())
	{
	    pj_sockaddr_cp(&bound_addr, cfg_bind_addr);
	}
	status = pj_sock_bind_random(sock, &bound_addr,
				     turn_sock->setting.port_range,
				     max_bind_retry);
	if (status != PJ_SUCCESS) {
	    pj_turn_sock_destroy(turn_sock);
	    return;
	}

	/* Apply QoS, if specified */
	status = pj_sock_apply_qos2(sock, turn_sock->setting.qos_type,
				    &turn_sock->setting.qos_params, 
				    (turn_sock->setting.qos_ignore_error?2:1),
				    turn_sock->pool->obj_name, NULL);
	if (status != PJ_SUCCESS && !turn_sock->setting.qos_ignore_error) {
	    pj_turn_sock_destroy(turn_sock);
	    return;
	}

	/* Apply socket buffer size */
	if (turn_sock->setting.so_rcvbuf_size > 0) {
	    unsigned sobuf_size = turn_sock->setting.so_rcvbuf_size;
	    status = pj_sock_setsockopt_sobuf(sock, pj_SO_RCVBUF(),
					      PJ_TRUE, &sobuf_size);
	    if (status != PJ_SUCCESS) {
		pj_perror(3, turn_sock->obj_name, status,
			  "Failed setting SO_RCVBUF");
	    } else {
		if (sobuf_size < turn_sock->setting.so_rcvbuf_size) {
		    PJ_LOG(4, (turn_sock->obj_name, 
			       "Warning! Cannot set SO_RCVBUF as configured,"
			       " now=%d, configured=%d", sobuf_size,
			       turn_sock->setting.so_rcvbuf_size));
		} else {
		    PJ_LOG(5, (turn_sock->obj_name, "SO_RCVBUF set to %d",
			       sobuf_size));
		}
	    }
	}
	if (turn_sock->setting.so_sndbuf_size > 0) {
	    unsigned sobuf_size = turn_sock->setting.so_sndbuf_size;
	    status = pj_sock_setsockopt_sobuf(sock, pj_SO_SNDBUF(),
					      PJ_TRUE, &sobuf_size);
	    if (status != PJ_SUCCESS) {
		pj_perror(3, turn_sock->obj_name, status,
			  "Failed setting SO_SNDBUF");
	    } else {
		if (sobuf_size < turn_sock->setting.so_sndbuf_size) {
		    PJ_LOG(4, (turn_sock->obj_name, 
			       "Warning! Cannot set SO_SNDBUF as configured,"
			       " now=%d, configured=%d", sobuf_size,
			       turn_sock->setting.so_sndbuf_size));
		} else {
		    PJ_LOG(5, (turn_sock->obj_name, "SO_SNDBUF set to %d",
			       sobuf_size));
		}
	    }
	}

	/* Create active socket */
	pj_activesock_cfg_default(&asock_cfg);
	asock_cfg.grp_lock = turn_sock->grp_lock;

	pj_bzero(&asock_cb, sizeof(asock_cb));
	asock_cb.on_data_read = &on_data_read;
	asock_cb.on_connect_complete = &on_connect_complete;
	status = pj_activesock_create(turn_sock->pool, sock,
				      sock_type, &asock_cfg,
				      turn_sock->cfg.ioqueue, &asock_cb, 
				      turn_sock,
				      &turn_sock->active_sock);
	if (status != PJ_SUCCESS) {
	    pj_turn_sock_destroy(turn_sock);
	    return;
	}

	PJ_LOG(5,(turn_sock->pool->obj_name,
		  "Connecting to %s", 
		  pj_sockaddr_print(&info.server, addrtxt, 
				    sizeof(addrtxt), 3)));

	/* Initiate non-blocking connect */
#if PJ_HAS_TCP
	status=pj_activesock_start_connect(turn_sock->active_sock, 
					   turn_sock->pool,
					   &info.server, 
					   pj_sockaddr_get_len(&info.server));
	if (status == PJ_SUCCESS) {
	    on_connect_complete(turn_sock->active_sock, PJ_SUCCESS);
	} else if (status != PJ_EPENDING) {
	    pj_turn_sock_destroy(turn_sock);
	    return;
	}
#else
	on_connect_complete(turn_sock->active_sock, PJ_SUCCESS);
#endif

	/* Done for now. Subsequent work will be done in 
	 * on_connect_complete() callback.
	 */
    }

    if (new_state >= PJ_TURN_STATE_DESTROYING && turn_sock->sess) {
	pj_time_val delay = {0, 0};

	turn_sock->sess = NULL;
	pj_turn_session_set_user_data(sess, NULL);

	pj_timer_heap_cancel_if_active(turn_sock->cfg.timer_heap,
	                               &turn_sock->timer, 0);
	pj_timer_heap_schedule_w_grp_lock(turn_sock->cfg.timer_heap,
	                                  &turn_sock->timer,
	                                  &delay, TIMER_DESTROY,
	                                  turn_sock->grp_lock);
    }
}
Exemplo n.º 5
0
static pj_status_t codec_put_frame(pjmedia_port *port,
                                   pjmedia_frame *frame)
{
    enum { MAX_PACKETS = 50 };
    codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
    pj_status_t status;
    pjmedia_vid_codec *codec = port_data->codec;
    unsigned enc_cnt = 0;
    pj_uint8_t *enc_buf;
    unsigned enc_size_left;
    pjmedia_frame enc_frames[MAX_PACKETS];
    pj_bool_t has_more = PJ_FALSE;

    enc_buf = port_data->enc_buf;
    enc_size_left = port_data->enc_buf_size;

    /*
     * Encode
     */
    enc_frames[enc_cnt].buf = enc_buf;
    enc_frames[enc_cnt].size = enc_size_left;

    status = pjmedia_vid_codec_encode_begin(codec, NULL, frame, enc_size_left,
                                            &enc_frames[enc_cnt], &has_more);
    if (status != PJ_SUCCESS) goto on_error;

    enc_buf += enc_frames[enc_cnt].size;
    enc_size_left -= enc_frames[enc_cnt].size;

    ++enc_cnt;
    while (has_more) {
        enc_frames[enc_cnt].buf = enc_buf;
        enc_frames[enc_cnt].size = enc_size_left;

        status = pjmedia_vid_codec_encode_more(codec, enc_size_left,
                                               &enc_frames[enc_cnt],
                                               &has_more);
        if (status != PJ_SUCCESS)
            break;

        enc_buf += enc_frames[enc_cnt].size;
        enc_size_left -= enc_frames[enc_cnt].size;

        ++enc_cnt;

        if (enc_cnt >= MAX_PACKETS) {
            assert(!"Too many packets!");
            break;
        }
    }

    /*
     * Decode
     */
    status = pjmedia_vid_codec_decode(codec, enc_cnt, enc_frames,
                                      frame->size, frame);
    if (status != PJ_SUCCESS) goto on_error;

    /* Display */
    status = pjmedia_port_put_frame(
                 pjmedia_vid_port_get_passive_port(port_data->rdr_port),
                 frame);
    if (status != PJ_SUCCESS) goto on_error;

    return PJ_SUCCESS;

on_error:
    pj_perror(3, THIS_FILE, status, "codec_put_frame() error");
    return status;
}
Exemplo n.º 6
0
/* Called by application to initialize the transport */
static pj_status_t transport_attach(   pjmedia_transport *tp,
				       void *user_data,
				       const pj_sockaddr_t *rem_addr,
				       const pj_sockaddr_t *rem_rtcp,
				       unsigned addr_len,
				       void (*rtp_cb)(void*,
						      void*,
						      pj_ssize_t),
				       void (*rtcp_cb)(void*,
						       void*,
						       pj_ssize_t))
{
    struct transport_udp *udp = (struct transport_udp*) tp;
    const pj_sockaddr *rtcp_addr;

    /* Validate arguments */
    PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL);

    /* Must not be "attached" to existing application */
    PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);

    /* Lock the ioqueue keys to make sure that callbacks are
     * not executed. See ticket #844 for details.
     */
    pj_ioqueue_lock_key(udp->rtp_key);
    pj_ioqueue_lock_key(udp->rtcp_key);

    /* "Attach" the application: */

    /* Copy remote RTP address */
    pj_memcpy(&udp->rem_rtp_addr, rem_addr, addr_len);

    /* Copy remote RTP address, if one is specified. */
    rtcp_addr = (const pj_sockaddr*) rem_rtcp;
    if (rtcp_addr && pj_sockaddr_has_addr(rtcp_addr)) {
	pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, addr_len);

    } else {
	unsigned rtcp_port;

	/* Otherwise guess the RTCP address from the RTP address */
	pj_memcpy(&udp->rem_rtcp_addr, rem_addr, addr_len);
	rtcp_port = pj_sockaddr_get_port(&udp->rem_rtp_addr) + 1;
	pj_sockaddr_set_port(&udp->rem_rtcp_addr, (pj_uint16_t)rtcp_port);
    }

    /* Save the callbacks */
    udp->rtp_cb = rtp_cb;
    udp->rtcp_cb = rtcp_cb;
    udp->user_data = user_data;

    /* Save address length */
    udp->addr_len = addr_len;

    /* Last, mark transport as attached */
    udp->attached = PJ_TRUE;

    /* Reset source RTP & RTCP addresses and counter */
    pj_bzero(&udp->rtp_src_addr, sizeof(udp->rtp_src_addr));
    pj_bzero(&udp->rtcp_src_addr, sizeof(udp->rtcp_src_addr));
    udp->rtp_src_cnt = 0;
    udp->rtcp_src_cnt = 0;

    /* Set buffer size for RTP socket */
#if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE
    {
	unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE;
	pj_status_t status;
	status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, tp->name, status, "Failed setting SO_RCVBUF");
	} else {
	    if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) {
		PJ_LOG(4, (tp->name, 
			   "Warning! Cannot set SO_RCVBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE));
	    } else {
		PJ_LOG(5, (tp->name, "SO_RCVBUF set to %d", sobuf_size));
	    }
	}
    }
#endif
#if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE
    {
	unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE;
	pj_status_t status;
	status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, tp->name, status, "Failed setting SO_SNDBUF");
	} else {
	    if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) {
		PJ_LOG(4, (tp->name, 
			   "Warning! Cannot set SO_SNDBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE));
	    } else {
		PJ_LOG(5, (tp->name, "SO_SNDBUF set to %d", sobuf_size));
	    }
	}
    }
#endif

    /* Unlock keys */
    pj_ioqueue_unlock_key(udp->rtcp_key);
    pj_ioqueue_unlock_key(udp->rtp_key);

    return PJ_SUCCESS;
}
Exemplo n.º 7
0
/* Called when CLI (re)started */
void on_app_started(pj_status_t status, const char *msg)
{
    pj_perror(3, THIS_FILE, status, (msg)?msg:"");
}
Exemplo n.º 8
0
/*
 * Create the STUN transport using the specified configuration.
 */
PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg,
					 const char *name,
					 int af,
					 const pj_stun_sock_cb *cb,
					 const pj_stun_sock_cfg *cfg,
					 void *user_data,
					 pj_stun_sock **p_stun_sock)
{
    pj_pool_t *pool;
    pj_stun_sock *stun_sock;
    pj_stun_sock_cfg default_cfg;
    pj_sockaddr bound_addr;
    unsigned i;
    pj_uint16_t max_bind_retry;
    pj_status_t status;

    PJ_ASSERT_RETURN(stun_cfg && cb && p_stun_sock, PJ_EINVAL);
    PJ_ASSERT_RETURN(af==pj_AF_INET()||af==pj_AF_INET6(), PJ_EAFNOTSUP);
    PJ_ASSERT_RETURN(!cfg || pj_stun_sock_cfg_is_valid(cfg), PJ_EINVAL);
    PJ_ASSERT_RETURN(cb->on_status, PJ_EINVAL);

    status = pj_stun_config_check_valid(stun_cfg);
    if (status != PJ_SUCCESS)
	return status;

    if (name == NULL)
	name = "stuntp%p";

    if (cfg == NULL) {
	pj_stun_sock_cfg_default(&default_cfg);
	cfg = &default_cfg;
    }


    /* Create structure */
    pool = pj_pool_create(stun_cfg->pf, name, 256, 512, NULL);
    stun_sock = PJ_POOL_ZALLOC_T(pool, pj_stun_sock);
    stun_sock->pool = pool;
    stun_sock->obj_name = pool->obj_name;
    stun_sock->user_data = user_data;
    stun_sock->af = af;
    stun_sock->sock_fd = PJ_INVALID_SOCKET;
    pj_memcpy(&stun_sock->stun_cfg, stun_cfg, sizeof(*stun_cfg));
    pj_memcpy(&stun_sock->cb, cb, sizeof(*cb));

    stun_sock->ka_interval = cfg->ka_interval;
    		stun_sock->timerstat = cfg->timerstat;
    if (stun_sock->ka_interval == 0)
	stun_sock->ka_interval = PJ_STUN_KEEP_ALIVE_SEC;
    printf(": cfg->stunProtocol=%d\n", cfg->stunProtocol);
    printf("%s", cfg->timerstat ? "SBR keepalive enabled\n": "SBR keepalive disabled\n");

    if (cfg->grp_lock) {
	stun_sock->grp_lock = cfg->grp_lock;
    } else {
	status = pj_grp_lock_create(pool, NULL, &stun_sock->grp_lock);
	if (status != PJ_SUCCESS) {
	    pj_pool_release(pool);
	    return status;
	}
    }

    pj_grp_lock_add_ref(stun_sock->grp_lock);
    pj_grp_lock_add_handler(stun_sock->grp_lock, pool, stun_sock,
			    &stun_sock_destructor);

    /* Create socket and bind socket */
//    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd);
    if(cfg->stunProtocol == 1)
    status = pj_sock_socket(af, PJ_SOCK_STREAM, 0, &stun_sock->sock_fd);
    else
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &stun_sock->sock_fd);
    if (status != PJ_SUCCESS)
	goto on_error;
	
    /* Apply QoS, if specified */
    status = pj_sock_apply_qos2(stun_sock->sock_fd, cfg->qos_type,
				&cfg->qos_params, 2, stun_sock->obj_name,
				NULL);
    if (status != PJ_SUCCESS && !cfg->qos_ignore_error)
	goto on_error;

    /* Apply socket buffer size */
    if (cfg->so_rcvbuf_size > 0) {
	unsigned sobuf_size = cfg->so_rcvbuf_size;
	status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_RCVBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, stun_sock->obj_name, status,
		      "Failed setting SO_RCVBUF");
	} else {
	    if (sobuf_size < cfg->so_rcvbuf_size) {
		PJ_LOG(4, (stun_sock->obj_name, 
			   "Warning! Cannot set SO_RCVBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, cfg->so_rcvbuf_size));
	    } else {
		PJ_LOG(5, (stun_sock->obj_name, "SO_RCVBUF set to %d",
			   sobuf_size));
	    }
	}
    }
    if (cfg->so_sndbuf_size > 0) {
	unsigned sobuf_size = cfg->so_sndbuf_size;
	status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_SNDBUF(),
					  PJ_TRUE, &sobuf_size);
	if (status != PJ_SUCCESS) {
	    pj_perror(3, stun_sock->obj_name, status,
		      "Failed setting SO_SNDBUF");
	} else {
	    if (sobuf_size < cfg->so_sndbuf_size) {
		PJ_LOG(4, (stun_sock->obj_name, 
			   "Warning! Cannot set SO_SNDBUF as configured, "
			   "now=%d, configured=%d",
			   sobuf_size, cfg->so_sndbuf_size));
	    } else {
		PJ_LOG(5, (stun_sock->obj_name, "SO_SNDBUF set to %d",
			   sobuf_size));
	    }
	}
    }

#if 1
    /* Bind socket */
    max_bind_retry = MAX_BIND_RETRY;
    if (cfg->port_range && cfg->port_range < max_bind_retry)
	max_bind_retry = cfg->port_range;
    pj_sockaddr_init(af, &bound_addr, NULL, 0);
    if (cfg->bound_addr.addr.sa_family == pj_AF_INET() || 
	cfg->bound_addr.addr.sa_family == pj_AF_INET6())
    {
	pj_sockaddr_cp(&bound_addr, &cfg->bound_addr);
    }
    status = pj_sock_bind_random(stun_sock->sock_fd, &bound_addr,
				 cfg->port_range, max_bind_retry);
    if (status != PJ_SUCCESS)
	goto on_error;
#endif

    /* Create more useful information string about this transport */
#if 0
    {
	pj_sockaddr bound_addr;
	int addr_len = sizeof(bound_addr);

	status = pj_sock_getsockname(stun_sock->sock_fd, &bound_addr, 
				     &addr_len);
	if (status != PJ_SUCCESS)
	    goto on_error;

	stun_sock->info = pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+10);
	pj_sockaddr_print(&bound_addr, stun_sock->info, 
			  PJ_INET6_ADDRSTRLEN, 3);
    }
#endif

    /* Init active socket configuration */
    {
	pj_activesock_cfg activesock_cfg;
	pj_activesock_cb activesock_cb;

	pj_activesock_cfg_default(&activesock_cfg);
	activesock_cfg.grp_lock = stun_sock->grp_lock;
	activesock_cfg.async_cnt = cfg->async_cnt;
	activesock_cfg.concurrency = 0;

	/* Create the active socket */
	pj_bzero(&activesock_cb, sizeof(activesock_cb));
	activesock_cb.on_data_recvfrom = &on_data_recvfrom;
	activesock_cb.on_data_sent = &on_data_sent;
        if(cfg->stunProtocol == 1)
	{
	status = pj_activesock_create(pool, stun_sock->sock_fd, 
				      PJ_SOCK_STREAM, 
				      &activesock_cfg, stun_cfg->ioqueue,
				      &activesock_cb, stun_sock,
				      &stun_sock->active_sock);
	}
	else
	{
	    status = pj_activesock_create(pool, stun_sock->sock_fd, 
				      pj_SOCK_DGRAM(), 		//nish
				      &activesock_cfg, stun_cfg->ioqueue,
				      &activesock_cb, stun_sock,
				      &stun_sock->active_sock);
	}

	if (status != PJ_SUCCESS)
	    goto on_error;
        if(cfg->stunProtocol == 1)
	{
		stun_sock->srv_addr.addr.sa_family = AF_INET;
		stun_sock->srv_addr.ipv4.sin_port= pj_htons(cfg->sin_port);
		stun_sock->srv_addr.ipv4.sin_addr = (cfg->sin_addr);

		status=pj_activesock_start_connect(stun_sock->active_sock, 
				pool,
				&(stun_sock->srv_addr), 
				pj_sockaddr_get_len(&(stun_sock->srv_addr)));

		if (status == PJ_SUCCESS) {
			printf("actie sock connect succesful");
		}
	}

	
	/* Start asynchronous read operations */
	status = pj_activesock_start_recvfrom(stun_sock->active_sock, pool,
					      cfg->max_pkt_size, 0);
	if (status != PJ_SUCCESS)
	    goto on_error;

	/* Init send keys */
	pj_ioqueue_op_key_init(&stun_sock->send_key, 
			       sizeof(stun_sock->send_key));
	pj_ioqueue_op_key_init(&stun_sock->int_send_key,
			       sizeof(stun_sock->int_send_key));
    }

    /* Create STUN session */
    {
	pj_stun_session_cb sess_cb;

	pj_bzero(&sess_cb, sizeof(sess_cb));
	sess_cb.on_request_complete = &sess_on_request_complete;
	sess_cb.on_send_msg = &sess_on_send_msg;
//	stun_sock->stunProtocol = 1; //FIXME: cfg->stunProtocol;
//	stun_sock->stunProtocol = 0; //FIXME: cfg->stunProtocol;
	printf(" stun_sock->stunProtocol=%d\n", stun_sock->stunProtocol);
	status = pj_stun_session_create(&stun_sock->stun_cfg, 
					stun_sock->obj_name,
					&sess_cb, PJ_FALSE, 
					stun_sock->grp_lock,
					&stun_sock->stun_sess);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Associate us with the STUN session */
    pj_stun_session_set_user_data(stun_sock->stun_sess, stun_sock);

    /* Initialize random numbers to be used as STUN transaction ID for
     * outgoing Binding request. We use the 80bit number to distinguish
     * STUN messages we sent with STUN messages that the application sends.
     * The last 16bit value in the array is a counter.
     */
    for (i=0; i<PJ_ARRAY_SIZE(stun_sock->tsx_id); ++i) {
	stun_sock->tsx_id[i] = (pj_uint16_t) pj_rand();
    }
    stun_sock->tsx_id[5] = 0;


    /* Init timer entry */
    stun_sock->ka_timer.cb = &ka_timer_cb;
    stun_sock->ka_timer.user_data = stun_sock;

    /* Done */
    *p_stun_sock = stun_sock;
    return PJ_SUCCESS;

on_error:
    pj_stun_sock_destroy(stun_sock);
    return status;
}