コード例 #1
0
ファイル: tsx_uas_test.c プロジェクト: CryptoCall/pjsip
/* Save transaction key to global variables. */
static void save_key(pjsip_transaction *tsx)
{
    pj_str_t key;

    pj_strdup(tsx->pool, &key, &tsx->transaction_key);
    pj_strcpy(&tsx_key, &key);
}
コード例 #2
0
ファイル: xpidf.c プロジェクト: 0x0B501E7E/pjproject
PJ_DEF(pjxpidf_pres*) pjxpidf_create(pj_pool_t *pool, const pj_str_t *uri_cstr)
{
    pjxpidf_pres *pres;
    pj_xml_node *presentity;
    pj_xml_node *atom;
    pj_xml_node *addr;
    pj_xml_node *status;
    pj_xml_attr *attr;
    pj_str_t uri;
    pj_str_t tmp;

    /* <presence> */
    pres = xml_create_node(pool, &STR_PRESENCE, NULL);

    /* <presentity> */
    presentity = xml_create_node(pool, &STR_PRESENTITY, NULL);
    pj_xml_add_node(pres, presentity);

    /* uri attribute */
    uri.ptr = (char*) pj_pool_alloc(pool, uri_cstr->slen + 
    					   STR_SUBSCRIBE_PARAM.slen);
    pj_strcpy( &uri, uri_cstr);
    pj_strcat( &uri, &STR_SUBSCRIBE_PARAM);
    attr = xml_create_attr(pool, &STR_URI, &uri);
    pj_xml_add_attr(presentity, attr);

    /* <atom> */
    atom = xml_create_node(pool, &STR_ATOM, NULL);
    pj_xml_add_node(pres, atom);

    /* atom id */
    pj_create_unique_string(pool, &tmp);
    attr = xml_create_attr(pool, &STR_ATOMID, &tmp);
    pj_xml_add_attr(atom, attr);

    /* address */
    addr = xml_create_node(pool, &STR_ADDRESS, NULL);
    pj_xml_add_node(atom, addr);

    /* address'es uri */
    attr = xml_create_attr(pool, &STR_URI, uri_cstr);
    pj_xml_add_attr(addr, attr);

    /* status */
    status = xml_create_node(pool, &STR_STATUS, NULL);
    pj_xml_add_node(addr, status);

    /* status attr */
    attr = xml_create_attr(pool, &STR_STATUS, &STR_OPEN);
    pj_xml_add_attr(status, attr);

    return pres;
}   
コード例 #3
0
ファイル: transport_test.c プロジェクト: Jopie64/pjsip
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;
}
コード例 #4
0
/*
 * The public API to invoke DNS SRV resolution.
 */
PJ_DEF(pj_status_t) pj_dns_srv_resolve( const pj_str_t *domain_name,
				        const pj_str_t *res_name,
					unsigned def_port,
					pj_pool_t *pool,
					pj_dns_resolver *resolver,
					unsigned option,
					void *token,
					pj_dns_srv_resolver_cb *cb,
					pj_dns_srv_async_query **p_query)
{
    pj_size_t len;
    pj_str_t target_name;
    pj_dns_srv_async_query *query_job;
    pj_status_t status;

    PJ_ASSERT_RETURN(domain_name && domain_name->slen &&
		     res_name && res_name->slen &&
		     pool && resolver && cb, PJ_EINVAL);

    /* Build full name */
    len = domain_name->slen + res_name->slen + 2;
    target_name.ptr = (char*) pj_pool_alloc(pool, len);
    pj_strcpy(&target_name, res_name);
    if (res_name->ptr[res_name->slen-1] != '.')
	pj_strcat2(&target_name, ".");
    len = target_name.slen;
    pj_strcat(&target_name, domain_name);
    target_name.ptr[target_name.slen] = '\0';


    /* Build the query_job state */
    query_job = PJ_POOL_ZALLOC_T(pool, pj_dns_srv_async_query);
    query_job->common.type = PJ_DNS_TYPE_SRV;
    query_job->objname = target_name.ptr;
    query_job->resolver = resolver;
    query_job->token = token;
    query_job->cb = cb;
    query_job->option = option;
    query_job->full_name = target_name;
    query_job->domain_part.ptr = target_name.ptr + len;
    query_job->domain_part.slen = target_name.slen - len;
    query_job->def_port = (pj_uint16_t)def_port;

    /* Start the asynchronous query_job */

    query_job->dns_state = PJ_DNS_TYPE_SRV;

    PJ_LOG(5, (query_job->objname, 
	       "Starting async DNS %s query_job: target=%.*s:%d",
	       pj_dns_get_type_name(query_job->dns_state),
	       (int)target_name.slen, target_name.ptr,
	       def_port));

    status = pj_dns_resolver_start_query(resolver, &target_name, 
				         query_job->dns_state, 0, 
					 &dns_callback,
    					 query_job, &query_job->q_srv);
    if (status==PJ_SUCCESS && p_query)
	*p_query = query_job;

    return status;
}
コード例 #5
0
void SIPCall::setContactHeader(pj_str_t *contact)
{
    pj_strcpy(&contactHeader_, contact);
}
コード例 #6
0
ファイル: string.hpp プロジェクト: 0x0B501E7E/pjproject
    //
    // Copy the contents of other string.
    //
    void strcpy(const Pj_String &rhs)
    {
	pj_strcpy(this, &rhs);
    }
コード例 #7
0
ファイル: string.hpp プロジェクト: 0x0B501E7E/pjproject
    //
    // Copy the contents of other string.
    //
    void strcpy(const pj_str_t *s)
    {
	pj_strcpy(this, s);
    }
コード例 #8
0
ファイル: tsx_uac_test.c プロジェクト: tibastral/symphonie
/*
 * This is the handler to receive message for this test. It is used to
 * control and verify the behavior of the message transmitted by the
 * transaction.
 */
static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata)
{
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST1_BRANCH_ID) == 0) {
	/*
	 * The TEST1_BRANCH_ID test performs the verifications for transaction
	 * retransmission mechanism. It will not answer the incoming request
	 * with any response.
	 */
	pjsip_msg *msg = rdata->msg_info.msg;

	PJ_LOG(4,(THIS_FILE, "    received request"));

	/* Only wants to take INVITE or OPTIONS method. */
	if (msg->line.req.method.id != PJSIP_INVITE_METHOD &&
	    msg->line.req.method.id != PJSIP_OPTIONS_METHOD)
	{
	    PJ_LOG(3,(THIS_FILE, "    error: received unexpected method %.*s",
			  msg->line.req.method.name.slen,
			  msg->line.req.method.name.ptr));
	    test_complete = -600;
	    return PJ_TRUE;
	}

	if (recv_count == 0) {
	    recv_count++;
	    //pj_gettimeofday(&recv_last);
	    recv_last = rdata->pkt_info.timestamp;
	} else {
	    pj_time_val now;
	    unsigned msec_expected, msec_elapsed;
	    int max_received;

	    //pj_gettimeofday(&now);
	    now = rdata->pkt_info.timestamp;
	    PJ_TIME_VAL_SUB(now, recv_last);
	    msec_elapsed = now.sec*1000 + now.msec;

	    ++recv_count;
    	    msec_expected = (1<<(recv_count-2))*PJSIP_T1_TIMEOUT;

	    if (msg->line.req.method.id != PJSIP_INVITE_METHOD) {
		if (msec_expected > PJSIP_T2_TIMEOUT)
		    msec_expected = PJSIP_T2_TIMEOUT;
		max_received = 11;
	    } else {
		max_received = 7;
	    }

	    if (DIFF(msec_expected, msec_elapsed) > TEST1_ALLOWED_DIFF) {
		PJ_LOG(3,(THIS_FILE,
			  "    error: expecting retransmission no. %d in %d "
			  "ms, received in %d ms",
			  recv_count-1, msec_expected, msec_elapsed));
		test_complete = -610;
	    }

	    
	    if (recv_count > max_received) {
		PJ_LOG(3,(THIS_FILE, 
			  "    error: too many messages (%d) received",
			  recv_count));
		test_complete = -620;
	    }

	    //pj_gettimeofday(&recv_last);
	    recv_last = rdata->pkt_info.timestamp;
	}
	return PJ_TRUE;

    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST4_BRANCH_ID) == 0) {
	/*
	 * The TEST4_BRANCH_ID test simulates transport failure after several
	 * retransmissions.
	 */
	recv_count++;

	if (recv_count == TEST4_RETRANSMIT_CNT) {
	    /* Simulate transport failure. */
	    pjsip_loop_set_failure(loop, 2, NULL);

	} else if (recv_count > TEST4_RETRANSMIT_CNT) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -631;
	}

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST5_BRANCH_ID) == 0) {
	/*
	 * The TEST5_BRANCH_ID test simulates user terminating the transaction
	 * after several retransmissions.
	 */
	recv_count++;

	if (recv_count == TEST5_RETRANSMIT_CNT+1) {
	    pj_str_t key;
	    pjsip_transaction *tsx;

	    pjsip_tsx_create_key( rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,
				  &rdata->msg_info.msg->line.req.method, rdata);
	    tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE);
	    if (tsx) {
		pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED);
		pj_mutex_unlock(tsx->mutex);
	    } else {
		PJ_LOG(3,(THIS_FILE, "    error: uac transaction not found!"));
		test_complete = -633;
	    }

	} else if (recv_count > TEST5_RETRANSMIT_CNT+1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -634;
	}

	return PJ_TRUE;

    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) {
	/*
	 * The TEST6_BRANCH_ID test successfull non-INVITE transaction.
	 */
	pj_status_t status;

	recv_count++;

	if (recv_count > 1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -635;
	}

	status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL,
					       NULL, NULL);
	if (status != PJ_SUCCESS) {
	    app_perror("    error: unable to send response", status);
	    test_complete = -636;
	}

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) {
	/*
	 * The TEST7_BRANCH_ID test successfull non-INVITE transaction
	 * with provisional response.
	 */
	pj_status_t status;
	pjsip_response_addr res_addr;
	struct response *r;
	pjsip_tx_data *tdata;
	pj_time_val delay = { 2, 0 };

	recv_count++;

	if (recv_count > 1) {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
		      recv_count));
	    test_complete = -640;
	    return PJ_TRUE;
	}

	/* Respond with provisional response */
	status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
	pj_assert(status == PJ_SUCCESS);

	status = pjsip_endpt_send_response(endpt, &res_addr, tdata, 
					   NULL, NULL);
	pj_assert(status == PJ_SUCCESS);

	/* Create the final response. */
	status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata);
	pj_assert(status == PJ_SUCCESS);

	/* Schedule sending final response in couple of of secs. */
	r = pj_pool_alloc(tdata->pool, sizeof(*r));
	r->res_addr = res_addr;
	r->tdata = tdata;
	if (r->res_addr.transport)
	    pjsip_transport_add_ref(r->res_addr.transport);

	timer.entry.cb = &send_response_callback;
	timer.entry.user_data = r;
	pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);

	return PJ_TRUE;


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) {
	/*
	 * The TEST8_BRANCH_ID test failed INVITE transaction.
	 */
	pjsip_method *method;
	pj_status_t status;

	method = &rdata->msg_info.msg->line.req.method;

	recv_count++;

	if (method->id == PJSIP_INVITE_METHOD) {

	    if (recv_count > 1) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -635;
	    }

	    status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL,
						   NULL, NULL);
	    if (status != PJ_SUCCESS) {
		app_perror("    error: unable to send response", status);
		test_complete = -636;
	    }

	} else if (method->id == PJSIP_ACK_METHOD) {

	    if (recv_count == 2) {
		pj_str_t key;
		pj_time_val delay = { 5, 0 };
		
		/* Schedule timer to destroy transaction after 5 seconds.
		 * This is to make sure that transaction does not 
		 * retransmit ACK.
		 */
		pjsip_tsx_create_key(rdata->tp_info.pool, &key,
				     PJSIP_ROLE_UAC, &pjsip_invite_method,
				     rdata);

		pj_strcpy(&timer.tsx_key, &key);
		timer.entry.id = 301;
		timer.entry.cb = &terminate_tsx_callback;

		pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
	    }

	    if (recv_count > 2) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -638;
	    }


	} else {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %s",
		      pjsip_rx_data_get_info(rdata)));
	    test_complete = -639;

	}


    } else
    if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) {
	/*
	 * The TEST9_BRANCH_ID test failed INVITE transaction with
	 * provisional response.
	 */
	pjsip_method *method;
	pj_status_t status;

	method = &rdata->msg_info.msg->line.req.method;

	recv_count++;

	if (method->id == PJSIP_INVITE_METHOD) {

	    pjsip_response_addr res_addr;
	    struct response *r;
	    pjsip_tx_data *tdata;
	    pj_time_val delay = { 2, 0 };

	    if (recv_count > 1) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -650;
		return PJ_TRUE;
	    }

	    /* Respond with provisional response */
	    status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, 
						 &tdata);
	    pj_assert(status == PJ_SUCCESS);

	    status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
	    pj_assert(status == PJ_SUCCESS);

	    status = pjsip_endpt_send_response(endpt, &res_addr, tdata, 
					       NULL, NULL);
	    pj_assert(status == PJ_SUCCESS);

	    /* Create the final response. */
	    status = pjsip_endpt_create_response(endpt, rdata, 302, NULL, 
						 &tdata);
	    pj_assert(status == PJ_SUCCESS);

	    /* Schedule sending final response in couple of of secs. */
	    r = pj_pool_alloc(tdata->pool, sizeof(*r));
	    r->res_addr = res_addr;
	    r->tdata = tdata;
	    if (r->res_addr.transport)
		pjsip_transport_add_ref(r->res_addr.transport);

	    timer.entry.cb = &send_response_callback;
	    timer.entry.user_data = r;
	    pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);

	} else if (method->id == PJSIP_ACK_METHOD) {

	    if (recv_count == 2) {
		pj_str_t key;
		pj_time_val delay = { 5, 0 };
		
		/* Schedule timer to destroy transaction after 5 seconds.
		 * This is to make sure that transaction does not 
		 * retransmit ACK.
		 */
		pjsip_tsx_create_key(rdata->tp_info.pool, &key,
				     PJSIP_ROLE_UAC, &pjsip_invite_method,
				     rdata);

		pj_strcpy(&timer.tsx_key, &key);
		timer.entry.id = 302;
		timer.entry.cb = &terminate_tsx_callback;

		pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay);
	    }

	    if (recv_count > 2) {
		PJ_LOG(3,(THIS_FILE,"   error: not expecting %d-th packet!",
			  recv_count));
		test_complete = -638;
	    }


	} else {
	    PJ_LOG(3,(THIS_FILE,"   error: not expecting %s",
		      pjsip_rx_data_get_info(rdata)));
	    test_complete = -639;

	}

	return PJ_TRUE;

    }

    return PJ_FALSE;
}
コード例 #9
0
ファイル: string.c プロジェクト: Jopie64/pjsip
int string_test(void)
{
    const pj_str_t hello_world = { HELLO_WORLD, HELLO_WORLD_LEN };
    const pj_str_t just_hello = { JUST_HELLO, JUST_HELLO_LEN };
    pj_str_t s1, s2, s3, s4, s5;
    enum { RCOUNT = 10, RLEN = 16 };
    pj_str_t random[RCOUNT];
    pj_pool_t *pool;
    int i;

    pool = pj_pool_create(mem, SNULL, 4096, 0, SNULL);
    if (!pool) return -5;
    
    /* 
     * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(), 
     * pj_strncmp(), pj_strchr() 
     */
    s1 = pj_str(HELLO_WORLD);
    if (pj_strcmp(&s1, &hello_world) != 0)
	return -10;
    if (pj_stricmp(&s1, &hello_world) != 0)
	return -20;
    if (pj_strcmp(&s1, &just_hello) <= 0)
	return -30;
    if (pj_stricmp(&s1, &just_hello) <= 0)
	return -40;
    if (pj_strlen(&s1) != strlen(HELLO_WORLD))
	return -50;
    if (pj_strncmp(&s1, &hello_world, 5) != 0)
	return -60;
    if (pj_strnicmp(&s1, &hello_world, 5) != 0)
	return -70;
    if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
	return -80;

    /* 
     * pj_strdup() 
     */
    if (!pj_strdup(pool, &s2, &s1))
	return -100;
    if (pj_strcmp(&s1, &s2) != 0)
	return -110;
    
    /* 
     * pj_strcpy(), pj_strcat() 
     */
    s3.ptr = (char*) pj_pool_alloc(pool, 256);
    if (!s3.ptr) 
	return -200;
    pj_strcpy(&s3, &s2);
    pj_strcat(&s3, &just_hello);

    if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
	return -210;

    /* 
     * pj_strdup2(), pj_strtrim(). 
     */
    pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
    pj_strtrim(&s4);
    if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
	return -250;

    /* 
     * pj_utoa() 
     */
    s5.ptr = (char*) pj_pool_alloc(pool, 16);
    if (!s5.ptr)
	return -270;
    s5.slen = pj_utoa(UL_VALUE, s5.ptr);

    /* 
     * pj_strtoul() 
     */
    if (pj_strtoul(&s5) != UL_VALUE)
	return -280;

    /*
     * pj_strtoul2()
     */
    s5 = pj_str("123456");

    pj_strtoul2(&s5, SNULL, 10);	/* Crash test */

    if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
	return -290;
    if (s4.slen != 0)
	return -291;
    if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
	return -292;

    s5 = pj_str("0123ABCD");
    if (pj_strtoul2(&s5, &s4, 10) != 123)
	return -293;
    if (s4.slen != 4)
	return -294;
    if (s4.ptr == SNULL || *s4.ptr != 'A')
	return -295;
    if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
	return -296;
    if (s4.slen != 0)
	return -297;

    /* 
     * pj_create_random_string() 
     * Check that no duplicate strings are returned.
     */
    for (i=0; i<RCOUNT; ++i) {
	int j;
	
	random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
	if (!random[i].ptr)
	    return -320;

        random[i].slen = RLEN;
	pj_create_random_string(random[i].ptr, RLEN);

	for (j=0; j<i; ++j) {
	    if (pj_strcmp(&random[i], &random[j])==0)
		return -330;
	}
    }

    /* Done. */
    pj_pool_release(pool);

    /* Case sensitive comparison test. */
    i = strcmp_test();
    if (i != 0)
	return i;

    /* Caseless comparison test. */
    i = stricmp_test();
    if (i != 0)
	return i;

    return 0;
}