Пример #1
0
static pj_status_t init_stack()
{
    pj_sockaddr addr;
    pjsip_inv_callback inv_cb;
    pj_status_t status;

    pj_log_set_level(5);

    status = pj_init();
    CHECK_STATUS();

    pj_log_set_level(3);

    status = pjlib_util_init();
    CHECK_STATUS();

    pj_caching_pool_init(&app.cp, NULL, 0);
    app.pool = pj_pool_create( &app.cp.factory, "sipecho", 512, 512, 0);

    status = pjsip_endpt_create(&app.cp.factory, NULL, &app.sip_endpt);
    CHECK_STATUS();

    pj_log_set_level(4);
    pj_sockaddr_init(AF, &addr, NULL, (pj_uint16_t)SIP_PORT);
    if (AF == pj_AF_INET()) {
	status = pjsip_udp_transport_start( app.sip_endpt, &addr.ipv4, NULL,
					    1, NULL);
    } else if (AF == pj_AF_INET6()) {
	status = pjsip_udp_transport_start6(app.sip_endpt, &addr.ipv6, NULL,
					    1, NULL);
    } else {
	status = PJ_EAFNOTSUP;
    }

    pj_log_set_level(3);
    CHECK_STATUS();

    status = pjsip_tsx_layer_init_module(app.sip_endpt) ||
	     pjsip_ua_init_module( app.sip_endpt, NULL );
    CHECK_STATUS();

    pj_bzero(&inv_cb, sizeof(inv_cb));
    inv_cb.on_state_changed = &call_on_state_changed;
    inv_cb.on_new_session = &call_on_forked;
    inv_cb.on_media_update = &call_on_media_update;
    inv_cb.on_rx_offer = &call_on_rx_offer;

    status = pjsip_inv_usage_init(app.sip_endpt, &inv_cb) ||
	     pjsip_100rel_init_module(app.sip_endpt) ||
	     pjsip_endpt_register_module( app.sip_endpt, &mod_sipecho) ||
	     pjsip_endpt_register_module( app.sip_endpt, &msg_logger) ||
	     //pjmedia_endpt_create(&app.cp.factory,
		//		  pjsip_endpt_get_ioqueue(app.sip_endpt),
		//		  0, &app.med_endpt) ||
             pj_thread_create(app.pool, "sipecho", &worker_proc, NULL, 0, 0,
                              &app.worker_thread);
    CHECK_STATUS();

    return PJ_SUCCESS;
}
Пример #2
0
static pj_status_t job_queue_create(pj_pool_t *pool, job_queue **pjq)
{
    unsigned i;
    pj_status_t status;
    
    job_queue *jq = PJ_POOL_ZALLOC_T(pool, job_queue);
    jq->size = MAX_JOBS;
    status = pj_sem_create(pool, "thread_sem", 0, jq->size + 1, &jq->sem);
    if (status != PJ_SUCCESS)
        goto on_error;

    for (i = 0; i < jq->size; i++) {
        status = pj_sem_create(pool, "job_sem", 0, 1, &jq->job_sem[i]);
        if (status != PJ_SUCCESS)
            goto on_error;
    }
    
    status = pj_mutex_create_recursive(pool, "job_mutex", &jq->mutex);
    if (status != PJ_SUCCESS)
        goto on_error;
    
    status = pj_thread_create(pool, "job_th", job_thread, jq, 0, 0,
                              &jq->thread);
    if (status != PJ_SUCCESS)
        goto on_error;
    
    *pjq = jq;
    return PJ_SUCCESS;
    
on_error:
    job_queue_destroy(jq);
    return status;
}
Пример #3
0
pjs_frame_processor::pjs_frame_processor(pjs_global& global,
		unsigned capacity, unsigned samples_per_frame) :
		m_global(global), m_samples_per_frame(samples_per_frame)
{
	m_started = false;
	m_thread = NULL;
	m_ready = false;
	m_exit = false;
	m_pool = pj_pool_create(m_global.get_pool_factory(), "pjs_frame_processor",
			128, 128, NULL);
	m_lock = new PPJ_SemaphoreLock(m_pool, NULL, 1, 1);
	pj_status_t status = pjmedia_circ_buf_create(m_pool, capacity, &m_buffer);
	if (status == PJ_SUCCESS)
	{
		status = pj_thread_create(m_pool, "frame processor thread",
				(pj_thread_proc*) &s_thread_proc, this, PJ_THREAD_DEFAULT_STACK_SIZE, PJ_THREAD_SUSPENDED,
				&m_thread);

		if (status != PJ_SUCCESS)
			m_thread = NULL;
		else
			m_ready = true;
	}
	else
		m_buffer = NULL;
}
Пример #4
0
/*
 * Start the clock. 
 */
PJ_DEF(pj_status_t) pjmedia_clock_start(pjmedia_clock *clock)
{
    pj_timestamp now;
    pj_status_t status;

    PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL);

    if (clock->running)
	return PJ_SUCCESS;

    status = pj_get_timestamp(&now);
    if (status != PJ_SUCCESS)
	return status;

    clock->next_tick.u64 = now.u64 + clock->interval.u64;
    clock->running = PJ_TRUE;
    clock->quitting = PJ_FALSE;

    if ((clock->options & PJMEDIA_CLOCK_NO_ASYNC) == 0 && !clock->thread) {
	status = pj_thread_create(clock->pool, "clock", &clock_thread, clock,
				  0, 0, &clock->thread);
	if (status != PJ_SUCCESS) {
	    pj_lock_destroy(clock->lock);
	    return status;
	}
    }

    return PJ_SUCCESS;
}
Пример #5
0
int udp_echo_srv_ioqueue(void)
{
    pj_pool_t *pool;
    pj_sock_t sock;
    pj_ioqueue_t *ioqueue;
    pj_ioqueue_callback callback;
    int i;
    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];
    pj_status_t rc;

    pj_bzero(&callback, sizeof(callback));
    callback.on_read_complete = &on_read_complete;
    callback.on_write_complete = &on_write_complete;

    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
    if (!pool)
        return -10;

    rc = pj_ioqueue_create(pool, 2, &ioqueue);
    if (rc != PJ_SUCCESS) {
        app_perror("...pj_ioqueue_create error", rc);
        return -20;
    }

    rc = app_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, 
                    ECHO_SERVER_START_PORT, &sock);
    if (rc != PJ_SUCCESS) {
        app_perror("...app_socket error", rc);
        return -30;
    }

    rc = pj_ioqueue_register_sock(pool, ioqueue, sock, NULL,
                                  &callback, &key);
    if (rc != PJ_SUCCESS) {
        app_perror("...error registering socket", rc);
        return -40;
    }

    rc = pj_atomic_create(pool, 0, &total_bytes);
    if (rc != PJ_SUCCESS) {
        app_perror("...error creating atomic variable", rc);
        return -45;
    }

    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {
        rc = pj_thread_create(pool, NULL, &worker_thread, ioqueue,
                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,
                              &thread[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...create thread error", rc);
            return -50;
        }
    }

    echo_srv_common_loop(total_bytes);

    return 0;
}
Пример #6
0
 //
 // Create a thread.
 //
 static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
                            pj_thread_proc *proc, void *arg,
                            unsigned flags = 0,
                            const char *name = NULL,
                            pj_size_t stack_size = 0 )
 {
     return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
                             flags, thread);
 }
Пример #7
0
/* API: start stream. */
static pj_status_t strm_start(pjmedia_aud_stream *s)
{
	struct android_aud_stream *stream = (struct android_aud_stream*)s;


	PJ_LOG(4,(THIS_FILE, "Starting %s stream..", stream->name.ptr));
	stream->quit_flag = 0;

	JNIEnv *jni_env = 0;
	ATTACH_JVM(jni_env);

	pj_status_t status;

	//Start threads
	if(stream->record){

		status = pj_thread_create(stream->pool, "android_recorder", &AndroidRecorderCallback, stream, 0, 0,  &stream->rec_thread);
		if (status != PJ_SUCCESS) {
			goto on_error;
		}
//		pj_sem_wait(stream->audio_launch_sem);
	}

	if(stream->track){
		status = pj_thread_create(stream->pool, "android_track", &AndroidTrackCallback, stream, 0, 0,  &stream->play_thread);
		if (status != PJ_SUCCESS) {
			goto on_error;
		}
//		pj_sem_wait(stream->audio_launch_sem);
	}

	PJ_LOG(4,(THIS_FILE, "Starting done"));

	status = PJ_SUCCESS;

on_error:
	DETACH_JVM(jni_env);
	if(status != PJ_SUCCESS){
		strm_destroy(&stream->base);
	}
	return status;
}
Пример #8
0
/*
 * Create media clock.
 */
PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
					  unsigned clock_rate,
					  unsigned channel_count,
					  unsigned samples_per_frame,
					  unsigned options,
					  pjmedia_clock_callback *cb,
					  void *user_data,
					  pjmedia_clock **p_clock)
{
    pjmedia_clock *clock;
    pj_status_t status;

    PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_clock,
		     PJ_EINVAL);

    clock = PJ_POOL_ALLOC_T(pool, pjmedia_clock);

    
    status = pj_get_timestamp_freq(&clock->freq);
    if (status != PJ_SUCCESS)
	return status;

    clock->interval.u64 = samples_per_frame * clock->freq.u64 / 
			  channel_count / clock_rate;
    clock->next_tick.u64 = 0;
    clock->timestamp.u64 = 0;
    clock->max_jump = MAX_JUMP_MSEC * clock->freq.u64 / 1000;
    clock->timestamp_inc = samples_per_frame / channel_count;
    clock->options = options;
    clock->cb = cb;
    clock->user_data = user_data;
    clock->thread = NULL;
    clock->running = PJ_FALSE;
    clock->quitting = PJ_FALSE;
    
    /* I don't think we need a mutex, so we'll use null. */
    status = pj_lock_create_null_mutex(pool, "clock", &clock->lock);
    if (status != PJ_SUCCESS)
	return status;

    if ((clock->options & PJMEDIA_CLOCK_NO_ASYNC) == 0) {
	status = pj_thread_create(pool, "clock", &clock_thread, clock,
				  0, 0, &clock->thread);
	if (status != PJ_SUCCESS) {
	    pj_lock_destroy(clock->lock);
	    return status;
	}
    }


    *p_clock = clock;

    return PJ_SUCCESS;
}
Пример #9
0
pj_status_t start_stack()
{
  pj_status_t status = PJ_SUCCESS;

  quit_flag = PJ_FALSE;

  // Create worker threads first as they take work from the PJSIP threads so
  // need to be ready.
  for (size_t ii = 0; ii < worker_threads.size(); ++ii)
  {
    pj_thread_t* thread;
    status = pj_thread_create(stack_data.pool, "worker", &worker_thread,
                              NULL, 0, 0, &thread);
    if (status != PJ_SUCCESS)
    {
      LOG_ERROR("Error creating worker thread, %s",
                PJUtils::pj_status_to_string(status).c_str());
      return 1;
    }
    worker_threads[ii] = thread;
  }

  // Now create the PJSIP threads.
  for (size_t ii = 0; ii < pjsip_threads.size(); ++ii)
  {
    pj_thread_t* thread;
    status = pj_thread_create(stack_data.pool, "pjsip", &pjsip_thread,
                              NULL, 0, 0, &thread);
    if (status != PJ_SUCCESS)
    {
      LOG_ERROR("Error creating PJSIP thread, %s",
                PJUtils::pj_status_to_string(status).c_str());
      return 1;
    }
    pjsip_threads[ii] = thread;
  }

  return status;
}
Пример #10
0
/*
 * Create media clock.
 */
PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
					  unsigned clock_rate,
					  unsigned samples_per_frame,
					  unsigned options,
					  pjmedia_clock_callback *cb,
					  void *user_data,
					  pjmedia_clock **p_clock)
{
    pjmedia_clock *clock;
    pj_status_t status;

    PJ_ASSERT_RETURN(pool && clock_rate && samples_per_frame && p_clock,
		     PJ_EINVAL);

    clock = pj_pool_alloc(pool, sizeof(pjmedia_clock));

    
    status = pj_get_timestamp_freq(&clock->freq);
    if (status != PJ_SUCCESS)
	return status;

    clock->interval.u64 = samples_per_frame * clock->freq.u64 / clock_rate;
    clock->next_tick.u64 = 0;
    clock->timestamp.u64 = 0;
    clock->samples_per_frame = samples_per_frame;
    clock->options = options;
    clock->cb = cb;
    clock->user_data = user_data;
    clock->thread = NULL;
    clock->running = PJ_FALSE;
    clock->quitting = PJ_FALSE;
    
    /* I don't think we need a mutex, so we'll use null. */
    status = pj_lock_create_null_mutex(pool, "clock", &clock->lock);
    if (status != PJ_SUCCESS)
	return status;

    status = pj_thread_create(pool, "clock", &clock_thread, clock,
			      0, 0, &clock->thread);
    if (status != PJ_SUCCESS) {
	pj_lock_destroy(clock->lock);
	return status;
    }


    *p_clock = clock;

    return PJ_SUCCESS;
}
Пример #11
0
/* API: start stream */
static pj_status_t alsa_stream_start (pjmedia_aud_stream *s)
{
    struct alsa_stream *stream = (struct alsa_stream*)s;
    pj_status_t status = PJ_SUCCESS;

    stream->quit = 0;
    if (stream->param.dir & PJMEDIA_DIR_PLAYBACK) {
	status = pj_thread_create (stream->pool,
				   "alsasound_playback",
				   pb_thread_func,
				   stream,
				   0, //ZERO,
				   0,
				   &stream->pb_thread);
	if (status != PJ_SUCCESS)
	    return status;
    }

    if (stream->param.dir & PJMEDIA_DIR_CAPTURE) {
	status = pj_thread_create (stream->pool,
				   "alsasound_playback",
				   ca_thread_func,
				   stream,
				   0, //ZERO,
				   0,
				   &stream->ca_thread);
	if (status != PJ_SUCCESS) {
	    stream->quit = PJ_TRUE;
	    pj_thread_join(stream->pb_thread);
	    pj_thread_destroy(stream->pb_thread);
	    stream->pb_thread = NULL;
	}
    }

    return status;
}
Пример #12
0
PJStunTurn::PJStunTurn() {
  if (PJ_SUCCESS != pjnath_init()) {
    g_warning("cannot init pjnath");
    return;
  }
  pj_ice_strans_cfg_default(&ice_cfg_);
  pj_timer_heap_create(PJSIP::this_->pool_, 100, &ice_cfg_.stun_cfg.timer_heap);
  pj_ioqueue_create(PJSIP::this_->pool_, 512, &ice_cfg_.stun_cfg.ioqueue);
  ice_cfg_.stun_cfg.pf = PJSIP::this_->pool_->factory;
  if (PJ_SUCCESS !=
      pj_thread_create(PJSIP::this_->pool_, "switcherSIP", &worker_thread, this, 0, 0, &thread_)) {
    g_warning("STUN TURN thread creating failed");
    return;
  }
  ice_cfg_.af = pj_AF_INET();
  ice_cfg_.stun.cfg.max_pkt_size = 8192;
  ice_cfg_.turn.cfg.max_pkt_size = 8192;
  ice_cfg_.opt.aggressive = PJ_FALSE;
  ice_cfg_.stun_cfg.rto_msec = 500;

  // set stun/turn config
  SIPPlugin::this_->install_method(
      "Set STUN/TURN parameters",                          // long name
      "set_stun_turn",                                     // name
      "Set STUN/TURN configuration",                       // description
      "the server(s) are reachable",                       // return description
      Method::make_arg_description("STUN server address",  // long name
                                   "stun",                 // name
                                   "string",               // description
                                   "TURN server address",
                                   "turn",
                                   "string",
                                   "TURN user name",
                                   "turn_user",
                                   "string",
                                   "TURN user password",
                                   "turn_pass",
                                   "string",
                                   nullptr),
      (Method::method_ptr)&set_stun_turn,
      G_TYPE_BOOLEAN,
      Method::make_arg_type_description(
          G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, nullptr),
      this);
}
Пример #13
0
int echo_srv_sync(void)
{
    pj_pool_t *pool;
    pj_sock_t sock;
    pj_thread_t *thread[ECHO_SERVER_MAX_THREADS];
    pj_status_t rc;
    int i;

    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
    if (!pool)
        return -5;

    rc = pj_atomic_create(pool, 0, &total_bytes);
    if (rc != PJ_SUCCESS) {
        app_perror("...unable to create atomic_var", rc);
        return -6;
    }

    rc = app_socket(pj_AF_INET(), pj_SOCK_DGRAM(),0, ECHO_SERVER_START_PORT, &sock);
    if (rc != PJ_SUCCESS) {
        app_perror("...socket error", rc);
        return -10;
    }

    for (i=0; i<ECHO_SERVER_MAX_THREADS; ++i) {
        rc = pj_thread_create(pool, NULL, &worker_thread, (void*)sock,
                              PJ_THREAD_DEFAULT_STACK_SIZE, 0,
                              &thread[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...unable to create thread", rc);
            return -20;
        }
    }

    PJ_LOG(3,("", "...UDP echo server running with %d threads at port %d",
                  ECHO_SERVER_MAX_THREADS, ECHO_SERVER_START_PORT));
    PJ_LOG(3,("", "...Press Ctrl-C to abort"));

    echo_srv_common_loop(total_bytes);
    return 0;
}
Пример #14
0
PJ_DEF(pj_status_t) pjmedia_event_mgr_create(pj_pool_t *pool,
                                             unsigned options,
				             pjmedia_event_mgr **p_mgr)
{
    pjmedia_event_mgr *mgr;
    pj_status_t status;

    mgr = PJ_POOL_ZALLOC_T(pool, pjmedia_event_mgr);
    mgr->pool = pj_pool_create(pool->factory, "evt mgr", 500, 500, NULL);
    pj_list_init(&mgr->esub_list);
    pj_list_init(&mgr->free_esub_list);

    if (!(options & PJMEDIA_EVENT_MGR_NO_THREAD)) {
        status = pj_sem_create(mgr->pool, "ev_sem", 0, MAX_EVENTS + 1,
                               &mgr->sem);
        if (status != PJ_SUCCESS)
            return status;

        status = pj_thread_create(mgr->pool, "ev_thread",
                                  &event_worker_thread,
                                  mgr, 0, 0, &mgr->thread);
        if (status != PJ_SUCCESS) {
            pjmedia_event_mgr_destroy(mgr);
            return status;
        }
    }

    status = pj_mutex_create_recursive(mgr->pool, "ev_mutex", &mgr->mutex);
    if (status != PJ_SUCCESS) {
        pjmedia_event_mgr_destroy(mgr);
        return status;
    }

    if (!event_manager_instance)
	event_manager_instance = mgr;

    if (p_mgr)
	*p_mgr = mgr;

    return PJ_SUCCESS;
}
Пример #15
0
pj_status_t start_pjsip_threads()
{
  pj_status_t status = PJ_SUCCESS;

  for (size_t ii = 0; ii < pjsip_threads.size(); ++ii)
  {
    pj_thread_t* thread;

    status = pj_thread_create(stack_data.pool, "pjsip", &pjsip_thread_func,
                              NULL, 0, 0, &thread);
    if (status != PJ_SUCCESS)
    {
        LOG_ERROR("Error creating PJSIP thread, %s",
                  PJUtils::pj_status_to_string(status).c_str());
        return 1;
    }
    pjsip_threads[ii] = thread;
  }
  
  return PJ_SUCCESS;
}
Пример #16
0
void ConnectionPool::init()
{
  // Create an initial set of connections.
  for (int ii = 0; ii < _num_connections; ++ii)
  {
    create_connection(ii);
  }

  if (_recycle_period != 0)
  {
    // Spawn a thread to recycle connections
    pj_status_t status = pj_thread_create(_pool, "recycler",
                                          &recycle_thread,
                                          (void*)this, 0, 0, &_recycler);
    if (status != PJ_SUCCESS)
    {
      TRC_ERROR("Error creating recycler thread, %s",
                PJUtils::pj_status_to_string(status).c_str());
    }
  }

  TRC_DEBUG("Started %d connections to %.*s:%d", _num_connections, _target.host.slen, _target.host.ptr, _target.port);
}
Пример #17
0
int main() {
    pj_caching_pool cp;
    pj_pool_t *pool;
    int i;
    pj_thread_t *thread1;
    
    pj_log_set_level(3);
    CHECK(__FILE__, pj_init());
    pj_srand(123765);
    pj_caching_pool_init(&cp, NULL, 1024);

    pool = pj_pool_create(&cp.factory, "objpool", 128, 128, NULL);

    pj_thread_create(pool, "thread1", &do_test, pool, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &thread1);
    pj_thread_sleep(500);
    do_test(pool);

    pj_thread_join(thread1);

    pj_pool_release(pool);
    pj_caching_pool_destroy(&cp);
    pj_shutdown();
    return 0;
}
Пример #18
0
/* Instantiate standard server */
static int create_std_server(pj_stun_auth_type auth_type,
			     pj_bool_t responding)
{
    pj_pool_t *pool;
    pj_stun_session_cb sess_cb;
    pj_stun_auth_cred cred;
    pj_status_t status;
    
    /* Create server */
    pool = pj_pool_create(mem, "server", 1000, 1000, NULL);
    server = PJ_POOL_ZALLOC_T(pool, struct server);
    server->pool = pool;
    server->auth_type = auth_type;
    server->responding = responding;

    /* Create STUN session */
    pj_bzero(&sess_cb, sizeof(sess_cb));
    sess_cb.on_rx_request = &server_on_rx_request;
    sess_cb.on_send_msg = &server_send_msg;
    status = pj_stun_session_create(&stun_cfg, "server", &sess_cb, PJ_FALSE, NULL, &server->sess);
    if (status != PJ_SUCCESS) {
	destroy_server();
	return -10;
    }

    /* Configure credential */
    pj_bzero(&cred, sizeof(cred));
    cred.type = PJ_STUN_AUTH_CRED_DYNAMIC;
    cred.data.dyn_cred.get_auth = &server_get_auth;
    cred.data.dyn_cred.get_password = &server_get_password;
    cred.data.dyn_cred.verify_nonce = &server_verify_nonce;
    status = pj_stun_session_set_credential(server->sess, auth_type, &cred);
    if (status != PJ_SUCCESS) {
	destroy_server();
	return -20;
    }

    /* Create socket */
    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &server->sock);
    if (status != PJ_SUCCESS) {
	destroy_server();
	return -30;
    }

    /* Bind */
    pj_sockaddr_in_init(&server->addr.ipv4, NULL, 0);
    status = pj_sock_bind(server->sock, &server->addr, pj_sockaddr_get_len(&server->addr));
    if (status != PJ_SUCCESS) {
	destroy_server();
	return -40;
    } else {
	/* Get the bound IP address */
	int namelen = sizeof(server->addr);
	pj_sockaddr addr;

	status = pj_sock_getsockname(server->sock, &server->addr, &namelen);
	if (status != PJ_SUCCESS) {
	    destroy_server();
	    return -43;
	}

	status = pj_gethostip(pj_AF_INET(), &addr);
	if (status != PJ_SUCCESS) {
	    destroy_server();
	    return -45;
	}

	pj_sockaddr_copy_addr(&server->addr, &addr);
    }


    /* Create worker thread */
    status = pj_thread_create(pool, "server", &server_thread, 0, 0, 0, &server->thread);
    if (status != PJ_SUCCESS) {
	destroy_server();
	return -30;
    }

    return 0;
}
Пример #19
0
/*
 * timeslice_test()
 */
static int timeslice_test(void)
{
    enum { NUM_THREADS = 4 };
    pj_pool_t *pool;
    pj_uint32_t counter[NUM_THREADS], lowest, highest, diff;
    pj_thread_t *thread[NUM_THREADS];
    unsigned i;
    pj_status_t rc;

    quit_flag = 0;

    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
    if (!pool)
        return -10;

    PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS));

    /* Create all threads in suspended mode. */
    for (i=0; i<NUM_THREADS; ++i) {
        counter[i] = i;
        rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
			      &counter[i],
                              PJ_THREAD_DEFAULT_STACK_SIZE,
                              PJ_THREAD_SUSPENDED,
                              &thread[i]);
        if (rc!=PJ_SUCCESS) {
            app_perror("...ERROR in pj_thread_create()", rc);
            return -20;
        }
    }

    /* Sleep for 1 second.
     * The purpose of this is to test whether all threads are suspended.
     */
    TRACE__((THIS_FILE, "    Main thread waiting.."));
    pj_thread_sleep(1000);
    TRACE__((THIS_FILE, "    Main thread resuming.."));

    /* Check that all counters are still zero. */
    for (i=0; i<NUM_THREADS; ++i) {
        if (counter[i] > i) {
            PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!",
		      i));
            return -30;
        }
    }

    /* Now resume all threads. */
    for (i=0; i<NUM_THREADS; ++i) {
	TRACE__((THIS_FILE, "    Resuming thread %d [%p]..", i, thread[i]));
        rc = pj_thread_resume(thread[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...ERROR in pj_thread_resume()", rc);
            return -40;
        }
    }

    /* Main thread sleeps for some time to allow threads to run.
     * The longer we sleep, the more accurate the calculation will be,
     * but it'll make user waits for longer for the test to finish.
     */
    TRACE__((THIS_FILE, "    Main thread waiting (5s).."));
    pj_thread_sleep(5000);
    TRACE__((THIS_FILE, "    Main thread resuming.."));

    /* Signal all threads to quit. */
    quit_flag = 1;

    /* Wait until all threads quit, then destroy. */
    for (i=0; i<NUM_THREADS; ++i) {
	TRACE__((THIS_FILE, "    Main thread joining thread %d [%p]..",
			    i, thread[i]));
        rc = pj_thread_join(thread[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...ERROR in pj_thread_join()", rc);
            return -50;
        }
	TRACE__((THIS_FILE, "    Destroying thread %d [%p]..", i, thread[i]));
        rc = pj_thread_destroy(thread[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...ERROR in pj_thread_destroy()", rc);
            return -60;
        }
    }

    TRACE__((THIS_FILE, "    Main thread calculating time slices.."));

    /* Now examine the value of the counters.
     * Check that all threads had equal proportion of processing.
     */
    lowest = 0xFFFFFFFF;
    highest = 0;
    for (i=0; i<NUM_THREADS; ++i) {
        if (counter[i] < lowest)
            lowest = counter[i];
        if (counter[i] > highest)
            highest = counter[i];
    }

    /* Check that all threads are running. */
    if (lowest < 2) {
        PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!"));
        return -70;
    }

    /* The difference between lowest and higest should be lower than 50%.
     */
    diff = (highest-lowest)*100 / ((highest+lowest)/2);
    if ( diff >= 50) {
        PJ_LOG(3,(THIS_FILE,
		  "...ERROR: thread didn't have equal timeslice!"));
        PJ_LOG(3,(THIS_FILE,
		  ".....lowest counter=%u, highest counter=%u, diff=%u%%",
                  lowest, highest, diff));
        return -80;
    } else {
        PJ_LOG(3,(THIS_FILE,
                  "...info: timeslice diff between lowest & highest=%u%%",
                  diff));
    }

    pj_pool_release(pool);
    return 0;
}
Пример #20
0
/*
 * simple_thread()
 */
static int simple_thread(const char *title, unsigned flags)
{
    pj_pool_t *pool;
    pj_thread_t *thread;
    pj_status_t rc;
    pj_uint32_t counter = 0;

    PJ_LOG(3,(THIS_FILE, "..%s", title));

    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
    if (!pool)
	return -1000;

    quit_flag = 0;

    TRACE__((THIS_FILE, "    Creating thread 0.."));
    rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc,
			  &counter,
			  PJ_THREAD_DEFAULT_STACK_SIZE,
			  flags,
			  &thread);

    if (rc != PJ_SUCCESS) {
	app_perror("...error: unable to create thread", rc);
	return -1010;
    }

    TRACE__((THIS_FILE, "    Main thread waiting.."));
    pj_thread_sleep(1500);
    TRACE__((THIS_FILE, "    Main thread resuming.."));

    if (flags & PJ_THREAD_SUSPENDED) {

	/* Check that counter is still zero */
	if (counter != 0) {
	    PJ_LOG(3,(THIS_FILE, "...error: thread is not suspended"));
	    return -1015;
	}

	rc = pj_thread_resume(thread);
	if (rc != PJ_SUCCESS) {
	    app_perror("...error: resume thread error", rc);
	    return -1020;
	}
    }

    PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit.."));

    pj_thread_sleep(1500);

    quit_flag = 1;
    pj_thread_join(thread);

    pj_pool_release(pool);

    if (counter == 0) {
	PJ_LOG(3,(THIS_FILE, "...error: thread is not running"));
	return -1025;
    }

    PJ_LOG(3,(THIS_FILE, "...%s success", title));
    return PJ_SUCCESS;
}
Пример #21
0
/* Calculate the bandwidth for the specific test configuration.
 * The test is simple:
 *  - create sockpair_cnt number of producer-consumer socket pair.
 *  - create thread_cnt number of worker threads.
 *  - each producer will send buffer_size bytes data as fast and
 *    as soon as it can.
 *  - each consumer will read buffer_size bytes of data as fast 
 *    as it could.
 *  - measure the total bytes received by all consumers during a
 *    period of time.
 */
static int perform_test(pj_bool_t allow_concur,
			int sock_type, const char *type_name,
                        unsigned thread_cnt, unsigned sockpair_cnt,
                        pj_size_t buffer_size, 
                        pj_size_t *p_bandwidth)
{
    enum { MSEC_DURATION = 5000 };
    pj_pool_t *pool;
    test_item *items;
    pj_thread_t **thread;
    pj_ioqueue_t *ioqueue;
    pj_status_t rc;
    pj_ioqueue_callback ioqueue_callback;
    pj_uint32_t total_elapsed_usec, total_received;
    pj_highprec_t bandwidth;
    pj_timestamp start, stop;
    unsigned i;

    TRACE_((THIS_FILE, "    starting test.."));

    ioqueue_callback.on_read_complete = &on_read_complete;
    ioqueue_callback.on_write_complete = &on_write_complete;

    thread_quit_flag = 0;

    pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);
    if (!pool)
        return -10;

    items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));
    thread = (pj_thread_t**)
    	     pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));

    TRACE_((THIS_FILE, "     creating ioqueue.."));
    rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);
    if (rc != PJ_SUCCESS) {
        app_perror("...error: unable to create ioqueue", rc);
        return -15;
    }

    rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur);
    if (rc != PJ_SUCCESS) {
	app_perror("...error: pj_ioqueue_set_default_concurrency()", rc);
        return -16;
    }

    /* Initialize each producer-consumer pair. */
    for (i=0; i<sockpair_cnt; ++i) {
        pj_ssize_t bytes;

        items[i].ioqueue = ioqueue;
        items[i].buffer_size = buffer_size;
        items[i].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size);
        items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size);
        items[i].bytes_recv = items[i].bytes_sent = 0;

        /* randomize outgoing buffer. */
        pj_create_random_string(items[i].outgoing_buffer, buffer_size);

        /* Create socket pair. */
	TRACE_((THIS_FILE, "      calling socketpair.."));
        rc = app_socketpair(pj_AF_INET(), sock_type, 0, 
                            &items[i].server_fd, &items[i].client_fd);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: unable to create socket pair", rc);
            return -20;
        }

        /* Register server socket to ioqueue. */
	TRACE_((THIS_FILE, "      register(1).."));
        rc = pj_ioqueue_register_sock(pool, ioqueue, 
                                      items[i].server_fd,
                                      &items[i], &ioqueue_callback,
                                      &items[i].server_key);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: registering server socket to ioqueue", rc);
            return -60;
        }

        /* Register client socket to ioqueue. */
	TRACE_((THIS_FILE, "      register(2).."));
        rc = pj_ioqueue_register_sock(pool, ioqueue, 
                                      items[i].client_fd,
                                      &items[i],  &ioqueue_callback,
                                      &items[i].client_key);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: registering server socket to ioqueue", rc);
            return -70;
        }

        /* Start reading. */
	TRACE_((THIS_FILE, "      pj_ioqueue_recv.."));
        bytes = items[i].buffer_size;
        rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op,
                             items[i].incoming_buffer, &bytes,
			     0);
        if (rc != PJ_EPENDING) {
            app_perror("...error: pj_ioqueue_recv", rc);
            return -73;
        }

        /* Start writing. */
	TRACE_((THIS_FILE, "      pj_ioqueue_write.."));
        bytes = items[i].buffer_size;
        rc = pj_ioqueue_send(items[i].client_key, &items[i].send_op,
                             items[i].outgoing_buffer, &bytes, 0);
        if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
            app_perror("...error: pj_ioqueue_write", rc);
            return -76;
        }

        items[i].has_pending_send = (rc==PJ_EPENDING);
    }

    /* Create the threads. */
    for (i=0; i<thread_cnt; ++i) {
	struct thread_arg *arg;

	arg = (struct thread_arg*) pj_pool_zalloc(pool, sizeof(*arg));
	arg->id = i;
	arg->ioqueue = ioqueue;
	arg->counter = 0;

        rc = pj_thread_create( pool, NULL, 
                               &worker_thread, 
                               arg, 
                               PJ_THREAD_DEFAULT_STACK_SIZE, 
                               PJ_THREAD_SUSPENDED, &thread[i] );
        if (rc != PJ_SUCCESS) {
            app_perror("...error: unable to create thread", rc);
            return -80;
        }
    }

    /* Mark start time. */
    rc = pj_get_timestamp(&start);
    if (rc != PJ_SUCCESS)
        return -90;

    /* Start the thread. */
    TRACE_((THIS_FILE, "     resuming all threads.."));
    for (i=0; i<thread_cnt; ++i) {
        rc = pj_thread_resume(thread[i]);
        if (rc != 0)
            return -100;
    }

    /* Wait for MSEC_DURATION seconds. 
     * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually,
     * but unfortunately it doesn't work when system doesn't employ
     * timeslicing for threads.
     */
    TRACE_((THIS_FILE, "     wait for few seconds.."));
    do {
	pj_thread_sleep(1);

	/* Mark end time. */
	rc = pj_get_timestamp(&stop);

	if (thread_quit_flag) {
	    TRACE_((THIS_FILE, "      transfer limit reached.."));
	    break;
	}

	if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) {
	    TRACE_((THIS_FILE, "      time limit reached.."));
	    break;
	}

    } while (1);

    /* Terminate all threads. */
    TRACE_((THIS_FILE, "     terminating all threads.."));
    thread_quit_flag = 1;

    for (i=0; i<thread_cnt; ++i) {
	TRACE_((THIS_FILE, "      join thread %d..", i));
        pj_thread_join(thread[i]);
    }

    /* Close all sockets. */
    TRACE_((THIS_FILE, "     closing all sockets.."));
    for (i=0; i<sockpair_cnt; ++i) {
        pj_ioqueue_unregister(items[i].server_key);
        pj_ioqueue_unregister(items[i].client_key);
    }

    /* Destroy threads */
    for (i=0; i<thread_cnt; ++i) {
        pj_thread_destroy(thread[i]);
    }

    /* Destroy ioqueue. */
    TRACE_((THIS_FILE, "     destroying ioqueue.."));
    pj_ioqueue_destroy(ioqueue);

    /* Calculate actual time in usec. */
    total_elapsed_usec = pj_elapsed_usec(&start, &stop);

    /* Calculate total bytes received. */
    total_received = 0;
    for (i=0; i<sockpair_cnt; ++i) {
        total_received = (pj_uint32_t)items[i].bytes_recv;
    }

    /* bandwidth = total_received*1000/total_elapsed_usec */
    bandwidth = total_received;
    pj_highprec_mul(bandwidth, 1000);
    pj_highprec_div(bandwidth, total_elapsed_usec);
    
    *p_bandwidth = (pj_uint32_t)bandwidth;

    PJ_LOG(3,(THIS_FILE, "   %.4s    %2d        %2d       %8d KB/s",
              type_name, thread_cnt, sockpair_cnt,
              *p_bandwidth));

    /* Done. */
    pj_pool_release(pool);

    TRACE_((THIS_FILE, "    done.."));
    return 0;
}
Пример #22
0
/**
 * Initialize and get the instance of media endpoint.
 */
PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
					 pj_ioqueue_t *ioqueue,
					 unsigned worker_cnt,
					 pjmedia_endpt **p_endpt)
{
    pj_pool_t *pool;
    pjmedia_endpt *endpt;
    unsigned i;
    pj_status_t status;

    if (!error_subsys_registered) {
	pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, 
			     &pjmedia_strerror);
	error_subsys_registered = 1;
    }

    PJ_ASSERT_RETURN(pf && p_endpt, PJ_EINVAL);
    PJ_ASSERT_RETURN(worker_cnt <= MAX_THREADS, PJ_EINVAL);

    pool = pj_pool_create(pf, "med-ept", 512, 512, NULL);
    if (!pool)
	return PJ_ENOMEM;

    endpt = PJ_POOL_ZALLOC_T(pool, struct pjmedia_endpt);
    endpt->pool = pool;
    endpt->pf = pf;
    endpt->ioqueue = ioqueue;
    endpt->thread_cnt = worker_cnt;

    /* Sound */
    status = pjmedia_aud_subsys_init(pf);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Init codec manager. */
    status = pjmedia_codec_mgr_init(&endpt->codec_mgr);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Create ioqueue if none is specified. */
    if (endpt->ioqueue == NULL) {
	
	endpt->own_ioqueue = PJ_TRUE;

	status = pj_ioqueue_create( endpt->pool, PJ_IOQUEUE_MAX_HANDLES,
				    &endpt->ioqueue);
	if (status != PJ_SUCCESS)
	    goto on_error;

	if (worker_cnt == 0) {
	    PJ_LOG(4,(THIS_FILE, "Warning: no worker thread is created in"  
				 "media endpoint for internal ioqueue"));
	}
    }

    /* Create worker threads if asked. */
    for (i=0; i<worker_cnt; ++i) {
	status = pj_thread_create( endpt->pool, "media", &worker_proc,
				   endpt, 0, 0, &endpt->thread[i]);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }


    *p_endpt = endpt;
    return PJ_SUCCESS;

on_error:

    /* Destroy threads */
    for (i=0; i<endpt->thread_cnt; ++i) {
	if (endpt->thread[i]) {
	    pj_thread_destroy(endpt->thread[i]);
	}
    }

    /* Destroy internal ioqueue */
    if (endpt->ioqueue && endpt->own_ioqueue)
	pj_ioqueue_destroy(endpt->ioqueue);

    pjmedia_aud_subsys_shutdown();
    pj_pool_release(pool);
    return status;
}
Пример #23
0
static int stun_destroy_test(void)
{
    enum { LOOP = 500 };
    struct stun_test_session test_sess;
    pj_sockaddr bind_addr;
    int addr_len;
    pj_caching_pool cp;
    pj_pool_t *pool;
    unsigned i;
    pj_status_t status;
    int rc = 0;

    PJ_LOG(3,(THIS_FILE, "  STUN destroy concurrency test"));

    pj_bzero(&test_sess, sizeof(test_sess));

    pj_caching_pool_init(&cp, NULL, 0);
    pool = pj_pool_create(&cp.factory, "testsess", 512, 512, NULL);

    pj_stun_config_init(&test_sess.stun_cfg, &cp.factory, 0, NULL, NULL);

    status = pj_timer_heap_create(pool, 1023, &test_sess.stun_cfg.timer_heap);
    pj_assert(status == PJ_SUCCESS);

    status = pj_lock_create_recursive_mutex(pool, NULL, &test_sess.lock);
    pj_assert(status == PJ_SUCCESS);

    pj_timer_heap_set_lock(test_sess.stun_cfg.timer_heap, test_sess.lock, PJ_TRUE);
    pj_assert(status == PJ_SUCCESS);

    status = pj_ioqueue_create(pool, 512, &test_sess.stun_cfg.ioqueue);
    pj_assert(status == PJ_SUCCESS);

    pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &test_sess.server_sock);
    pj_sockaddr_init(pj_AF_INET(), &bind_addr, NULL, 0);
    status = pj_sock_bind(test_sess.server_sock, &bind_addr, pj_sockaddr_get_len(&bind_addr));
    pj_assert(status == PJ_SUCCESS);

    addr_len = sizeof(bind_addr);
    status = pj_sock_getsockname(test_sess.server_sock, &bind_addr, &addr_len);
    pj_assert(status == PJ_SUCCESS);

    test_sess.server_port = pj_sockaddr_get_port(&bind_addr);

    status = pj_event_create(pool, NULL, PJ_TRUE, PJ_FALSE, &test_sess.server_event);
    pj_assert(status == PJ_SUCCESS);

    for (i=0; i<SERVER_THREAD_CNT; ++i) {
	status = pj_thread_create(pool, NULL,
	                          &server_thread_proc, &test_sess,
	                          0, 0, &test_sess.server_threads[i]);
	pj_assert(status == PJ_SUCCESS);
    }

    for (i=0; i<WORKER_THREAD_CNT; ++i) {
	status = pj_thread_create(pool, NULL,
	                          &worker_thread_proc, &test_sess,
	                          0, 0, &test_sess.worker_threads[i]);
	pj_assert(status == PJ_SUCCESS);
    }

    /* Test 1: Main thread calls destroy while callback is processing response */
    PJ_LOG(3,(THIS_FILE, "    Destroy in main thread while callback is running"));
    for (i=0; i<LOOP; ++i) {
	int sleep = pj_rand() % 5;

	PJ_LOG(3,(THIS_FILE, "      Try %-3d of %d", i+1, LOOP));

	/* Test 1: destroy at the same time when receiving response */
	pj_bzero(&test_sess.param, sizeof(test_sess.param));
	test_sess.param.client_sleep_after_start = 20;
	test_sess.param.client_sleep_before_destroy = sleep;
	test_sess.param.server_wait_for_event = PJ_TRUE;
	stun_destroy_test_session(&test_sess);
	PJ_LOG(3,(THIS_FILE,
		  "        stun test a: sleep delay:%d: clients with response: %d",
		  sleep, test_sess.param.client_got_response));

	/* Test 2: destroy at the same time with STUN retransmit timer */
	test_sess.param.server_drop_request = PJ_TRUE;
	test_sess.param.client_sleep_after_start = 0;
	test_sess.param.client_sleep_before_destroy = PJ_STUN_RTO_VALUE;
	test_sess.param.server_wait_for_event = PJ_FALSE;
	stun_destroy_test_session(&test_sess);
	PJ_LOG(3,(THIS_FILE, "        stun test b: retransmit concurrency"));

	/* Test 3: destroy at the same time with receiving response
	 * AND STUN retransmit timer */
	test_sess.param.client_got_response = 0;
	test_sess.param.server_drop_request = PJ_FALSE;
	test_sess.param.client_sleep_after_start = PJ_STUN_RTO_VALUE;
	test_sess.param.client_sleep_before_destroy = 0;
	test_sess.param.server_wait_for_event = PJ_TRUE;
	stun_destroy_test_session(&test_sess);
	PJ_LOG(3,(THIS_FILE,
		  "        stun test c: clients with response: %d",
		  test_sess.param.client_got_response));

	pj_thread_sleep(10);

	ice_one_conc_test(&test_sess.stun_cfg, PJ_FALSE);

	pj_thread_sleep(10);
    }

    /* Avoid compiler warning */
    goto on_return;


on_return:
    test_sess.thread_quit_flag = PJ_TRUE;

    for (i=0; i<SERVER_THREAD_CNT; ++i) {
	pj_thread_join(test_sess.server_threads[i]);
    }

    for (i=0; i<WORKER_THREAD_CNT; ++i) {
	pj_thread_join(test_sess.worker_threads[i]);
    }

    pj_event_destroy(test_sess.server_event);
    pj_sock_close(test_sess.server_sock);
    pj_ioqueue_destroy(test_sess.stun_cfg.ioqueue);
    pj_timer_heap_destroy(test_sess.stun_cfg.timer_heap);

    pj_pool_release(pool);
    pj_caching_pool_destroy(&cp);

    PJ_LOG(3,(THIS_FILE, "    Done. rc=%d", rc));
    return rc;
}
Пример #24
0
void serial_start(serial_t *serial) {
    pj_thread_create(serial->pool, NULL, do_thing, serial, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &serial->master_thread);
}
Пример #25
0
int http_client_test_delete()
{
    pj_str_t url;
    pj_http_req_callback hcb;
    pj_http_req_param param;
    char urlbuf[80];

    pj_bzero(&hcb, sizeof(hcb));
    hcb.on_complete = &on_complete;
    hcb.on_response = &on_response;

    /* Create pool, timer, and ioqueue */
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
    if (pj_timer_heap_create(pool, 16, &timer_heap))
        return -61;
    if (pj_ioqueue_create(pool, 16, &ioqueue))
        return -62;

#ifdef USE_LOCAL_SERVER
    thread_quit = PJ_FALSE;
    g_server.action = ACTION_REPLY;
    g_server.send_content_length = PJ_TRUE;
    g_server.data_size = 0;
    g_server.buf_size = 1024;

    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
                             &g_server.sock);
    if (sstatus != PJ_SUCCESS)
        return -41;

    pj_sockaddr_in_init(&addr, NULL, 0);

    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
    if (sstatus != PJ_SUCCESS)
        return -43;

    {
	pj_sockaddr_in addr;
	int addr_len = sizeof(addr);
	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
	if (sstatus != PJ_SUCCESS)
	    return -44;
	g_server.port = pj_sockaddr_in_get_port(&addr);
	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
			 "http://127.0.0.1:%d/test/test2.txt",
			 g_server.port);
	url = pj_str(urlbuf);
    }

    sstatus = pj_sock_listen(g_server.sock, 8);
    if (sstatus != PJ_SUCCESS)
        return -45;

    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
                               0, 0, &g_server.thread);
    if (sstatus != PJ_SUCCESS)
        return -47;

#else
    pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt");
#endif

    pj_http_req_param_default(&param);
    pj_strset2(&param.method, (char*)"DELETE");
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
                           &param, &hcb, &http_req))
        return -63;

    if (pj_http_req_start(http_req))
        return -65;

    while (pj_http_req_is_running(http_req)) {
        pj_time_val delay = {0, 50};
	pj_ioqueue_poll(ioqueue, &delay);
	pj_timer_heap_poll(timer_heap, NULL);
    }

#ifdef USE_LOCAL_SERVER
    thread_quit = PJ_TRUE;
    pj_thread_join(g_server.thread);
    pj_sock_close(g_server.sock);
#endif

    pj_http_req_destroy(http_req);
    pj_ioqueue_destroy(ioqueue);
    pj_timer_heap_destroy(timer_heap);
    pj_pool_release(pool);

    return PJ_SUCCESS;
}
Пример #26
0
/* 
 * GET request scenario 2: using on_complete() to get the 
 * complete data. Server does not reply with content-length.
 * Request timed out, application sets a longer timeout, then
 * then restart the request.
 */
int http_client_test2()
{
    pj_str_t url;
    pj_http_req_callback hcb;
    pj_http_req_param param;
    pj_time_val timeout;
    char urlbuf[80];

    pj_bzero(&hcb, sizeof(hcb));
    hcb.on_complete = &on_complete;
    hcb.on_response = &on_response;
    pj_http_req_param_default(&param);

    /* Create pool, timer, and ioqueue */
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
    if (pj_timer_heap_create(pool, 16, &timer_heap))
        return -41;
    if (pj_ioqueue_create(pool, 16, &ioqueue))
        return -42;

#ifdef USE_LOCAL_SERVER

    pj_cstr(&url, "http://127.0.0.1:380");
    param.timeout.sec = 0;
    param.timeout.msec = 2000;

    thread_quit = PJ_FALSE;
    g_server.action = ACTION_IGNORE;
    g_server.send_content_length = PJ_FALSE;
    g_server.data_size = 4173;
    g_server.buf_size = 1024;

    sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, 
                             &g_server.sock);
    if (sstatus != PJ_SUCCESS)
        return -41;

    pj_sockaddr_in_init(&addr, NULL, 0);

    sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr));
    if (sstatus != PJ_SUCCESS)
        return -43;

    {
	pj_sockaddr_in addr;
	int addr_len = sizeof(addr);
	sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len);
	if (sstatus != PJ_SUCCESS)
	    return -44;
	g_server.port = pj_sockaddr_in_get_port(&addr);
	pj_ansi_snprintf(urlbuf, sizeof(urlbuf),
			 "http://127.0.0.1:%d",
			 g_server.port);
	url = pj_str(urlbuf);
    }

    sstatus = pj_sock_listen(g_server.sock, 8);
    if (sstatus != PJ_SUCCESS)
        return -45;

    sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server,
                               0, 0, &g_server.thread);
    if (sstatus != PJ_SUCCESS)
        return -47;

#else
    pj_cstr(&url, "http://www.google.com.sg");
    param.timeout.sec = 0;
    param.timeout.msec = 50;
#endif

    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept",
			     (char*)"image/gif, image/x-xbitmap, image/jpeg, "
				    "image/pjpeg, application/x-ms-application,"
				    " application/vnd.ms-xpsdocument, "
			            "application/xaml+xml, "
			            "application/x-ms-xbap, "
			            "application/x-shockwave-flash, "
			            "application/vnd.ms-excel, "
			            "application/vnd.ms-powerpoint, "
			            "application/msword, */*");
    pj_http_headers_add_elmt2(&param.headers, (char*)"Accept-Language",
	                      (char*)"en-sg");
    pj_http_headers_add_elmt2(&param.headers, (char*)"User-Agent",
                              (char*)"Mozilla/4.0 (compatible; MSIE 7.0; "
                                     "Windows NT 6.0; SLCC1; "
                                     ".NET CLR 2.0.50727; "
                                     ".NET CLR 3.0.04506)");
    if (pj_http_req_create(pool, &url, timer_heap, ioqueue, 
                           &param, &hcb, &http_req))
        return -43;

    if (pj_http_req_start(http_req))
        return -45;

    while (pj_http_req_is_running(http_req)) {
        pj_time_val delay = {0, 50};
	pj_ioqueue_poll(ioqueue, &delay);
	pj_timer_heap_poll(timer_heap, NULL);
    }

#ifdef USE_LOCAL_SERVER
    g_server.action = ACTION_REPLY;
#endif

    timeout.sec = 0; timeout.msec = 10000;
    pj_http_req_set_timeout(http_req, &timeout);
    if (pj_http_req_start(http_req))
        return -47;

    while (pj_http_req_is_running(http_req)) {
        pj_time_val delay = {0, 50};
	pj_ioqueue_poll(ioqueue, &delay);
	pj_timer_heap_poll(timer_heap, NULL);
    }

#ifdef USE_LOCAL_SERVER
    thread_quit = PJ_TRUE;
    pj_thread_join(g_server.thread);
    pj_sock_close(g_server.sock);
#endif

    pj_http_req_destroy(http_req);
    pj_ioqueue_destroy(ioqueue);
    pj_timer_heap_destroy(timer_heap);
    pj_pool_release(pool);

    return PJ_SUCCESS;
}
static int init()
{
    int i;
    pj_status_t status;

    CHECK( pj_init() );
    CHECK( pjlib_util_init() );
    CHECK( pjnath_init() );

    /* Check that server is specified */
    if (!o.srv_addr) {
	printf("Error: server must be specified\n");
	return PJ_EINVAL;
    }

    pj_caching_pool_init(&g.cp, &pj_pool_factory_default_policy, 0);

    g.pool = pj_pool_create(&g.cp.factory, "main", 1000, 1000, NULL);

    /* Init global STUN config */
    pj_stun_config_init(&g.stun_config, &g.cp.factory, 0, NULL, NULL);

    /* Create global timer heap */
    CHECK( pj_timer_heap_create(g.pool, 1000, &g.stun_config.timer_heap) );

    /* Create global ioqueue */
    CHECK( pj_ioqueue_create(g.pool, 16, &g.stun_config.ioqueue) );

    /* 
     * Create peers
     */
    for (i=0; i<(int)PJ_ARRAY_SIZE(g.peer); ++i) {
	pj_stun_sock_cb stun_sock_cb;
	char name[] = "peer0";
	pj_uint16_t port;
	pj_stun_sock_cfg ss_cfg;
	pj_str_t server;

	pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
	stun_sock_cb.on_rx_data = &stun_sock_on_rx_data;
	stun_sock_cb.on_status = &stun_sock_on_status;

	g.peer[i].mapped_addr.addr.sa_family = pj_AF_INET();

	pj_stun_sock_cfg_default(&ss_cfg);
#if 1
	/* make reading the log easier */
	ss_cfg.ka_interval = 300;
#endif

	name[strlen(name)-1] = '0'+i;
	status = pj_stun_sock_create(&g.stun_config, name, pj_AF_INET(), 
				     &stun_sock_cb, &ss_cfg,
				     &g.peer[i], &g.peer[i].stun_sock);
	if (status != PJ_SUCCESS) {
	    my_perror("pj_stun_sock_create()", status);
	    return status;
	}

	if (o.stun_server) {
	    server = pj_str(o.stun_server);
	    port = PJ_STUN_PORT;
	} else {
	    server = pj_str(o.srv_addr);
	    port = (pj_uint16_t)(o.srv_port?atoi(o.srv_port):PJ_STUN_PORT);
	}
	status = pj_stun_sock_start(g.peer[i].stun_sock, &server, 
				    port,  NULL);
	if (status != PJ_SUCCESS) {
	    my_perror("pj_stun_sock_start()", status);
	    return status;
	}
    }

    /* Start the worker thread */
    CHECK( pj_thread_create(g.pool, "stun", &worker_thread, NULL, 0, 0, &g.thread) );


    return PJ_SUCCESS;
}
Пример #28
0
static int run_client_test(const char *title,

			   pj_bool_t server_responding,
			   pj_stun_auth_type server_auth_type,

			   pj_stun_auth_type client_auth_type,
			   const char *realm,
			   const char *username,
			   const char *nonce,
			   const char *password,
			   pj_bool_t dummy_mi,

			   pj_bool_t expected_error,
			   pj_status_t expected_code,
			   const char *expected_realm,
			   const char *expected_nonce,
			   
			   int (*more_check)(void))
{
    pj_pool_t *pool;
    pj_stun_session_cb sess_cb;
    pj_stun_auth_cred cred;
    pj_stun_tx_data *tdata;
    pj_status_t status;
    int rc = 0;
    
    PJ_LOG(3,(THIS_FILE, "   %s test", title));

    /* Create client */
    pool = pj_pool_create(mem, "client", 1000, 1000, NULL);
    client = PJ_POOL_ZALLOC_T(pool, struct client);
    client->pool = pool;
    client->responding = PJ_TRUE;

    /* Create STUN session */
    pj_bzero(&sess_cb, sizeof(sess_cb));
    sess_cb.on_request_complete = &client_on_request_complete;
    sess_cb.on_send_msg = &client_send_msg;
    status = pj_stun_session_create(&stun_cfg, "client", &sess_cb, PJ_FALSE, NULL, &client->sess);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -200;
    }

    /* Create semaphore */
    status = pj_sem_create(pool, "client", 0, 1, &client->test_complete);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -205;
    }

    /* Create client socket */
    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &client->sock);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -210;
    }

    /* Bind client socket */
    status = pj_sock_bind_in(client->sock, 0, 0);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -220;
    }

    /* Create client thread */
    status = pj_thread_create(pool, "client", &client_thread, NULL, 0, 0, &client->thread);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -230;
    }

    /* Initialize credential */
    pj_bzero(&cred, sizeof(cred));
    cred.type = PJ_STUN_AUTH_CRED_STATIC;
    if (realm) cred.data.static_cred.realm = pj_str((char*)realm);
    if (username) cred.data.static_cred.username = pj_str((char*)username);
    if (nonce) cred.data.static_cred.nonce = pj_str((char*)nonce);
    if (password) cred.data.static_cred.data = pj_str((char*)password);
    cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
    status = pj_stun_session_set_credential(client->sess, client_auth_type, &cred);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -240;
    }

    /* Create the server */
    status = create_std_server(server_auth_type, server_responding);
    if (status != 0) {
	destroy_client_server();
	return status;
    }

    /* Create request */
    status = pj_stun_session_create_req(client->sess, PJ_STUN_BINDING_REQUEST, 
					PJ_STUN_MAGIC, NULL, &tdata);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -250;
    }

    /* Add our own attributes if client authentication is set to none */
    if (client_auth_type == PJ_STUN_AUTH_NONE) {
	pj_str_t tmp;
	if (realm)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_REALM, pj_cstr(&tmp, realm));
	if (username)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_USERNAME, pj_cstr(&tmp, username));
	if (nonce)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, nonce));
	if (password) {
	    // ignored
	}
	if (dummy_mi) {
	    pj_stun_msgint_attr *mi;

	    pj_stun_msgint_attr_create(tdata->pool, &mi);
	    pj_stun_msg_add_attr(tdata->msg, &mi->hdr);
	}
	   
    }

    /* Send the request */
    status = pj_stun_session_send_msg(client->sess, NULL, PJ_FALSE, PJ_TRUE, &server->addr,
				      pj_sockaddr_get_len(&server->addr), tdata);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -270;
    }

    /* Wait until test complete */
    pj_sem_wait(client->test_complete);


    /* Verify response */
    if (expected_error) {
	if (expected_code != client->response_status) {
	    char e1[PJ_ERR_MSG_SIZE], e2[PJ_ERR_MSG_SIZE];

	    pj_strerror(expected_code, e1, sizeof(e1));
	    pj_strerror(client->response_status, e2, sizeof(e2));

	    PJ_LOG(3,(THIS_FILE, "    err: expecting %d (%s) but got %d (%s) response",
		      expected_code, e1, client->response_status, e2));
	    rc = -500;
	} 

    } else {
	int res_code = 0;
	pj_stun_realm_attr *arealm;
	pj_stun_nonce_attr *anonce;

	if (client->response_status != 0) {
	    PJ_LOG(3,(THIS_FILE, "    err: expecting successful operation but got error %d", 
		      client->response_status));
	    rc = -600;
	    goto done;
	} 

	if (PJ_STUN_IS_ERROR_RESPONSE(client->response->hdr.type)) {
	    pj_stun_errcode_attr *aerr = NULL;

	    aerr = (pj_stun_errcode_attr*)
		   pj_stun_msg_find_attr(client->response, 
					 PJ_STUN_ATTR_ERROR_CODE, 0);
	    if (aerr == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: received error response without ERROR-CODE"));
		rc = -610;
		goto done;
	    }

	    res_code = aerr->err_code;
	} else {
	    res_code = 0;
	}

	/* Check that code matches */
	if (expected_code != res_code) {
	    PJ_LOG(3,(THIS_FILE, "    err: expecting response code %d but got %d",
		      expected_code, res_code));
	    rc = -620;
	    goto done;
	}

	/* Find REALM and NONCE attributes */
	arealm = (pj_stun_realm_attr*)
	         pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_REALM, 0);
	anonce = (pj_stun_nonce_attr*)
	         pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_NONCE, 0);

	if (expected_realm) {
	    if (arealm == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: expecting REALM in esponse"));
		rc = -630;
		goto done;
	    }
	    if (pj_strcmp2(&arealm->value, expected_realm)!=0) {
		PJ_LOG(3,(THIS_FILE, "    err: REALM mismatch in response"));
		rc = -640;
		goto done;
	    }
	} else {
	    if (arealm != NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: non expecting REALM in response"));
		rc = -650;
		goto done;
	    }
	}

	if (expected_nonce) {
	    if (anonce == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: expecting NONCE in esponse"));
		rc = -660;
		goto done;
	    }
	    if (pj_strcmp2(&anonce->value, expected_nonce)!=0) {
		PJ_LOG(3,(THIS_FILE, "    err: NONCE mismatch in response"));
		rc = -670;
		goto done;
	    }
	} else {
	    if (anonce != NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: non expecting NONCE in response"));
		rc = -680;
		goto done;
	    }
	}
    }

    /* Our tests are okay so far. Let caller do some more tests if
     * it wants to.
     */
    if (rc==0 && more_check) {
	rc = (*more_check)();
    }


done:
    destroy_client_server();
    return rc;
}
Пример #29
0
int transport_rt_test( pjsip_transport_type_e tp_type,
		       pjsip_transport *ref_tp,
		       char *target_url,
		       int *lost)
{
    enum { THREADS = 4, INTERVAL = 10 };
    int i;
    pj_status_t status;
    pj_pool_t *pool;
    pj_bool_t logger_enabled;

    pj_timestamp zero_time, total_time;
    unsigned usec_rt;
    unsigned total_sent;
    unsigned total_recv;

    PJ_UNUSED_ARG(tp_type);
    PJ_UNUSED_ARG(ref_tp);

    PJ_LOG(3,(THIS_FILE, "  multithreaded round-trip test (%d threads)...",
		  THREADS));
    PJ_LOG(3,(THIS_FILE, "    this will take approx %d seconds, please wait..",
		INTERVAL));

    /* Make sure msg logger is disabled. */
    logger_enabled = msg_logger_set_enabled(0);

    /* Register module (if not yet registered) */
    if (rt_module.id == -1) {
	status = pjsip_endpt_register_module( endpt, &rt_module );
	if (status != PJ_SUCCESS) {
	    app_perror("   error: unable to register module", status);
	    return -600;
	}
    }

    /* Create pool for this test. */
    pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000);
    if (!pool)
	return -610;

    /* Initialize static test data. */
    pj_ansi_strcpy(rt_target_uri, target_url);
    rt_call_id = pj_str("RT-Call-Id/");
    rt_stop = PJ_FALSE;

    /* Initialize thread data. */
    for (i=0; i<THREADS; ++i) {
	char buf[1];
	pj_str_t str_id;
	
	pj_strset(&str_id, buf, 1);
	pj_bzero(&rt_test_data[i], sizeof(rt_test_data[i]));

	/* Init timer entry */
	rt_test_data[i].tx_timer.id = i;
	rt_test_data[i].tx_timer.cb = &rt_tx_timer;
	rt_test_data[i].timeout_timer.id = i;
	rt_test_data[i].timeout_timer.cb = &rt_timeout_timer;

	/* Generate Call-ID for each thread. */
	rt_test_data[i].call_id.ptr = (char*) pj_pool_alloc(pool, rt_call_id.slen+1);
	pj_strcpy(&rt_test_data[i].call_id, &rt_call_id);
	buf[0] = '0' + (char)i;
	pj_strcat(&rt_test_data[i].call_id, &str_id);

	/* Init mutex. */
	status = pj_mutex_create_recursive(pool, "rt", &rt_test_data[i].mutex);
	if (status != PJ_SUCCESS) {
	    app_perror("   error: unable to create mutex", status);
	    return -615;
	}

	/* Create thread, suspended. */
	status = pj_thread_create(pool, "rttest%p", &rt_worker_thread, (void*)(long)i, 0,
				  PJ_THREAD_SUSPENDED, &rt_test_data[i].thread);
	if (status != PJ_SUCCESS) {
	    app_perror("   error: unable to create thread", status);
	    return -620;
	}
    }

    /* Start threads! */
    for (i=0; i<THREADS; ++i) {
	pj_time_val delay = {0,0};
	pj_thread_resume(rt_test_data[i].thread);

	/* Schedule first message transmissions. */
	rt_test_data[i].tx_timer.user_data = (void*)1;
	pjsip_endpt_schedule_timer(endpt, &rt_test_data[i].tx_timer, &delay);
    }

    /* Sleep for some time. */
    pj_thread_sleep(INTERVAL * 1000);

    /* Signal thread to stop. */
    rt_stop = PJ_TRUE;

    /* Wait threads to complete. */
    for (i=0; i<THREADS; ++i) {
	pj_thread_join(rt_test_data[i].thread);
	pj_thread_destroy(rt_test_data[i].thread);
    }

    /* Destroy rt_test_data */
    for (i=0; i<THREADS; ++i) {
	pj_mutex_destroy(rt_test_data[i].mutex);
	pjsip_endpt_cancel_timer(endpt, &rt_test_data[i].timeout_timer);
    }

    /* Gather statistics. */
    pj_bzero(&total_time, sizeof(total_time));
    pj_bzero(&zero_time, sizeof(zero_time));
    usec_rt = total_sent = total_recv = 0;
    for (i=0; i<THREADS; ++i) {
	total_sent += rt_test_data[i].sent_request_count;
	total_recv +=  rt_test_data[i].recv_response_count;
	pj_add_timestamp(&total_time, &rt_test_data[i].total_rt_time);
    }

    /* Display statistics. */
    if (total_recv)
	total_time.u64 = total_time.u64/total_recv;
    else
	total_time.u64 = 0;
    usec_rt = pj_elapsed_usec(&zero_time, &total_time);
    PJ_LOG(3,(THIS_FILE, "    done."));
    PJ_LOG(3,(THIS_FILE, "    total %d messages sent", total_sent));
    PJ_LOG(3,(THIS_FILE, "    average round-trip=%d usec", usec_rt));

    pjsip_endpt_release_pool(endpt, pool);

    *lost = total_sent-total_recv;

    /* Flush events. */
    flush_events(500);

    /* Restore msg logger. */
    msg_logger_set_enabled(logger_enabled);

    return 0;
}
Пример #30
0
/* API: create stream */
static pj_status_t android_create_stream(pjmedia_aud_dev_factory *f,
                                         const pjmedia_aud_param *param,
                                         pjmedia_aud_rec_cb rec_cb,
                                         pjmedia_aud_play_cb play_cb,
                                         void *user_data,
                                         pjmedia_aud_stream **p_aud_strm)
{
    struct android_aud_factory *pa = (struct android_aud_factory*)f;
    pj_pool_t *pool;
    struct android_aud_stream *stream;
    pj_status_t status = PJ_SUCCESS;
    int state = 0;
    int buffSize, inputBuffSizePlay, inputBuffSizeRec;
    int channelInCfg, channelOutCfg, sampleFormat;
    jmethodID constructor_method=0, bufsize_method = 0;
    jmethodID method_id = 0;
    jclass jcl;
    JNIEnv *jni_env = 0;
    pj_bool_t attached;
    
    PJ_ASSERT_RETURN(param->channel_count >= 1 && param->channel_count <= 2,
                     PJ_EINVAL);
    PJ_ASSERT_RETURN(param->bits_per_sample==8 || param->bits_per_sample==16,
                     PJ_EINVAL);
    PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);

    pool = pj_pool_create(pa->pf, "jnistrm", 1024, 1024, NULL);
    if (!pool)
        return PJ_ENOMEM;

    PJ_LOG(4, (THIS_FILE, "Creating Android JNI stream"));
    
    stream = PJ_POOL_ZALLOC_T(pool, struct android_aud_stream);
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, "JNI stream");
    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
    pj_memcpy(&stream->param, param, sizeof(*param));
    stream->user_data = user_data;
    stream->rec_cb = rec_cb;
    stream->play_cb = play_cb;
    buffSize = stream->param.samples_per_frame*stream->param.bits_per_sample/8;
    stream->rec_buf_size = stream->play_buf_size = buffSize;
    channelInCfg = (param->channel_count == 1)? 16 /*CHANNEL_IN_MONO*/:
                   12 /*CHANNEL_IN_STEREO*/;
    channelOutCfg = (param->channel_count == 1)? 4 /*CHANNEL_OUT_MONO*/:
                    12 /*CHANNEL_OUT_STEREO*/;
    sampleFormat = (param->bits_per_sample == 8)? 3 /*ENCODING_PCM_8BIT*/:
                   2 /*ENCODING_PCM_16BIT*/;

    attached = attach_jvm(&jni_env);

    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
        /* Find audio record class and create global ref */
        jcl = (*jni_env)->FindClass(jni_env, "android/media/AudioRecord");
        if (jcl == NULL) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record class"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        stream->record_class = (jclass)(*jni_env)->NewGlobalRef(jni_env, jcl);
        (*jni_env)->DeleteLocalRef(jni_env, jcl);
        if (stream->record_class == 0) {
            status = PJ_ENOMEM;
            goto on_error;
        }

        /* Get the min buffer size function */
        bufsize_method = (*jni_env)->GetStaticMethodID(jni_env,
                                                       stream->record_class,
                                                       "getMinBufferSize",
                                                       "(III)I");
        if (bufsize_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record "
                                  "getMinBufferSize() method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }

        inputBuffSizeRec = (*jni_env)->CallStaticIntMethod(jni_env,
                                                           stream->record_class,
                                                           bufsize_method,
                                                           param->clock_rate,
                                                           channelInCfg,
                                                           sampleFormat);
        if (inputBuffSizeRec <= 0) {
            PJ_LOG(3, (THIS_FILE, "Unsupported audio record params"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
    }
    
    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
        /* Find audio track class and create global ref */
        jcl = (*jni_env)->FindClass(jni_env, "android/media/AudioTrack");
        if (jcl == NULL) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track class"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        stream->track_class = (jclass)(*jni_env)->NewGlobalRef(jni_env, jcl);
        (*jni_env)->DeleteLocalRef(jni_env, jcl);
        if (stream->track_class == 0) {
            status = PJ_ENOMEM;
            goto on_error;
        }

        /* Get the min buffer size function */
        bufsize_method = (*jni_env)->GetStaticMethodID(jni_env,
                                                       stream->track_class,
                                                       "getMinBufferSize",
                                                       "(III)I");
        if (bufsize_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track "
                                  "getMinBufferSize() method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        inputBuffSizePlay = (*jni_env)->CallStaticIntMethod(jni_env,
                                                            stream->track_class,
                                                            bufsize_method,
                                                            param->clock_rate,
                                                            channelOutCfg,
                                                            sampleFormat);
        if (inputBuffSizePlay <= 0) {
            PJ_LOG(3, (THIS_FILE, "Unsupported audio track params"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
    }
    
    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
        jthrowable exc;
        int mic_source = 0; /* DEFAULT: default audio source */

        /* Get pointer to the constructor */
        constructor_method = (*jni_env)->GetMethodID(jni_env,
                                                     stream->record_class,
                                                     "<init>", "(IIIII)V");
        if (constructor_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record's constructor"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        if (mic_source == 0) {
            /* Android-L (android-21) removes __system_property_get
             * from the NDK.
	     */
	    /*           
	    char sdk_version[PROP_VALUE_MAX];
            pj_str_t pj_sdk_version;
            int sdk_v;

            __system_property_get("ro.build.version.sdk", sdk_version);
            pj_sdk_version = pj_str(sdk_version);
            sdk_v = pj_strtoul(&pj_sdk_version);
            if (sdk_v > 10)
            */
            mic_source = 7; /* VOICE_COMMUNICATION */
        }
        PJ_LOG(4, (THIS_FILE, "Using audio input source : %d", mic_source));
        
        do {
            stream->record =  (*jni_env)->NewObject(jni_env,
                                                    stream->record_class,
                                                    constructor_method,
                                                    mic_source, 
                                                    param->clock_rate,
                                                    channelInCfg,
                                                    sampleFormat,
                                                    inputBuffSizeRec);
            if (stream->record == 0) {
                PJ_LOG(3, (THIS_FILE, "Unable to create audio record object"));
                status = PJMEDIA_EAUD_INIT;
                goto on_error;
            }
        
            exc = (*jni_env)->ExceptionOccurred(jni_env);
            if (exc) {
                (*jni_env)->ExceptionDescribe(jni_env);
                (*jni_env)->ExceptionClear(jni_env);
                PJ_LOG(3, (THIS_FILE, "Failure in audio record's constructor"));
                if (mic_source == 0) {
                    status = PJMEDIA_EAUD_INIT;
                    goto on_error;
                }
                mic_source = 0;
                PJ_LOG(4, (THIS_FILE, "Trying the default audio source."));
                continue;
            }

            /* Check state */
            method_id = (*jni_env)->GetMethodID(jni_env, stream->record_class,
                                                "getState", "()I");
            if (method_id == 0) {
                PJ_LOG(3, (THIS_FILE, "Unable to find audio record getState() "
                                      "method"));
                status = PJMEDIA_EAUD_SYSERR;
                goto on_error;
            }
            state = (*jni_env)->CallIntMethod(jni_env, stream->record,
                                              method_id);
            if (state == 0) { /* STATE_UNINITIALIZED */
                PJ_LOG(3, (THIS_FILE, "Failure in initializing audio record."));
                if (mic_source == 0) {
                    status = PJMEDIA_EAUD_INIT;
                    goto on_error;
                }
                mic_source = 0;
                PJ_LOG(4, (THIS_FILE, "Trying the default audio source."));
            }
        } while (state == 0);
        
        stream->record = (*jni_env)->NewGlobalRef(jni_env, stream->record);
        if (stream->record == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio record global ref."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }

        status = pj_sem_create(stream->pool, NULL, 0, 1, &stream->rec_sem);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        status = pj_thread_create(stream->pool, "android_recorder",
                                  AndroidRecorderCallback, stream, 0, 0,
                                  &stream->rec_thread);
        if (status != PJ_SUCCESS)
            goto on_error;

        PJ_LOG(4, (THIS_FILE, "Audio record initialized successfully."));
    }
    
    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
        jthrowable exc;
        
        /* Get pointer to the constructor */
        constructor_method = (*jni_env)->GetMethodID(jni_env,
                                                     stream->track_class,
                                                     "<init>", "(IIIIII)V");
        if (constructor_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track's constructor."));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        stream->track = (*jni_env)->NewObject(jni_env,
                                              stream->track_class,
                                              constructor_method,
                                              0, /* STREAM_VOICE_CALL */
                                              param->clock_rate,
                                              channelOutCfg,
                                              sampleFormat,
                                              inputBuffSizePlay,
                                              1 /* MODE_STREAM */);
        if (stream->track == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio track object."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        exc = (*jni_env)->ExceptionOccurred(jni_env);
        if (exc) {
            (*jni_env)->ExceptionDescribe(jni_env);
            (*jni_env)->ExceptionClear(jni_env);
            PJ_LOG(3, (THIS_FILE, "Failure in audio track's constructor"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        stream->track = (*jni_env)->NewGlobalRef(jni_env, stream->track);
        if (stream->track == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio track's global ref"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        /* Check state */
        method_id = (*jni_env)->GetMethodID(jni_env, stream->track_class,
                                            "getState", "()I");
        if (method_id == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track getState() "
                                  "method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        state = (*jni_env)->CallIntMethod(jni_env, stream->track,
                                          method_id);
        if (state == 0) { /* STATE_UNINITIALIZED */
            PJ_LOG(3, (THIS_FILE, "Failure in initializing audio track."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }

        status = pj_sem_create(stream->pool, NULL, 0, 1, &stream->play_sem);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        status = pj_thread_create(stream->pool, "android_track",
                                  AndroidTrackCallback, stream, 0, 0,
                                  &stream->play_thread);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        PJ_LOG(4, (THIS_FILE, "Audio track initialized successfully."));
    }

    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
	strm_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
                     &param->output_vol);
    }
    
    /* Done */
    stream->base.op = &android_strm_op;
    *p_aud_strm = &stream->base;
    
    detach_jvm(attached);
    
    return PJ_SUCCESS;
    
on_error:
    detach_jvm(attached);
    strm_destroy(&stream->base);
    return status;
}