Index: pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c	(revision 601)
+++ pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c	(revision 602)
@@ -986,5 +986,6 @@
 	"\n"
 	"Client options:\n"
-	"   --method=METHOD, -m     Set the test method [default: OPTIONS]\n"
+	"   --method=METHOD, -m     Set test method (set to INVITE for call benchmark)\n"
+        "                           [default: OPTIONS]\n"
 	"   --count=N, -n           Set total number of requests to initiate\n"
 	"                           [default=%d]\n"
@@ -1000,10 +1001,12 @@
 	"Client and Server options:\n"
 	"   --local-port=PORT, -p   Set local port [default: 5060]\n"
-	"   --use-tcp, -T           Use TCP instead of UDP [default: no]\n"
+	"   --use-tcp, -T           Use TCP instead of UDP. Note that when started as\n"
+	"                           client, you must add ;transport=tcp parameter to URL\n"
+	"                           [default: no]\n"
 	"   --thread-count=N        Set number of worker threads [default=1]\n"
 	"\n"
 	"Misc options:\n"
 	"   --help, -h              Display this screen\n"
-	"   --verbose, -v           Display verbose logging (can be put more than once)\n"
+	"   --verbose, -v           Verbose logging (put more than once for even more)\n"
 	"\n"
 	"When started as server, pjsip-perf can be contacted on the following URIs:\n"
@@ -1256,7 +1259,6 @@
 {
     unsigned last_timeout_check = 0;
-    pj_time_val end_time, now;
-
-    PJ_UNUSED_ARG(arg);
+    pj_time_val end_time, last_report, now;
+    unsigned thread_index = (unsigned)arg;
 
     pj_thread_sleep(100);
@@ -1265,4 +1267,6 @@
     end_time.sec += app.client.timeout;
 
+    pj_gettimeofday(&last_report);
+
     if (app.client.first_request.sec == 0) {
 	pj_gettimeofday(&app.client.first_request);
@@ -1270,5 +1274,5 @@
 
     /* Submit all jobs */
-    while (app.client.job_submitted < app.client.job_count && !app.thread_quit) {
+    while (app.client.job_submitted < app.client.job_count && !app.thread_quit){
 	pj_time_val timeout = { 0, 1 };
 	unsigned i;
@@ -1306,10 +1310,19 @@
 	pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL);
 
-	/* Check for time out */
-	if (app.client.job_submitted - last_timeout_check >= 2000) {
+	/* Check for time out, also print report */
+	if (app.client.job_submitted - last_timeout_check >= 500) {
 	    pj_gettimeofday(&now);
-	    if (PJ_TIME_VAL_GTE(now, end_time))
+	    if (PJ_TIME_VAL_GTE(now, end_time)) {
 		break;
+	    }
 	    last_timeout_check = app.client.job_submitted;
+
+	    
+	    if (thread_index == 0 && now.sec-last_report.sec >= 2) {
+		printf("\r%d jobs started, %d completed...   ",
+		       app.client.job_submitted, app.client.job_finished);
+		fflush(stdout);
+		last_report = now;
+	    }
 	}
     }
@@ -1320,7 +1333,15 @@
 
 
+    if (thread_index == 0) {
+	printf("\r%d jobs started, %d completed%s\n",
+	       app.client.job_submitted, app.client.job_finished,
+	       (app.client.job_submitted!=app.client.job_finished ? 
+		", waiting..." : ".") );
+	fflush(stdout);
+    }
+
     /* Wait until all jobs completes, or timed out */
     pj_gettimeofday(&now);
-    while (now.sec < end_time.sec && 
+    while (PJ_TIME_VAL_LT(now, end_time) && 
 	   app.client.job_finished < app.client.job_count && 
 	   !app.thread_quit) 
@@ -1330,5 +1351,30 @@
 
 	for (i=0; i<1000; ++i) {
-	    pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL);
+	    unsigned count;
+	    count = 0;
+	    pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count);
+	    if (count == 0)
+		break;
+	}
+
+	pj_gettimeofday(&now);
+    }
+
+    /* Wait couple of seconds if there are still unfinished jobs */
+    pj_gettimeofday(&now);
+    end_time = now;
+    end_time.sec += 2;
+    while (PJ_TIME_VAL_LT(now, end_time) && 
+	   app.client.job_finished < app.client.job_submitted) 
+    {
+	pj_time_val timeout = { 0, 1 };
+	unsigned i;
+
+	for (i=0; i<1000; ++i) {
+	    unsigned count;
+	    count = 0;
+	    pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count);
+	    if (count == 0)
+		break;
 	}
 
@@ -1432,4 +1478,7 @@
 {
     static char report[1024];
+
+    puts("PJSIP Performance Measurement Tool\n"
+        "(c)2006 pjsip.org\n");
 
     if (create_app() != 0)
@@ -1487,11 +1536,11 @@
 	
 
-	PJ_LOG(3,(THIS_FILE, "Sending %d %s to '%.*s' with %d maximum outstanding jobs, please wait..", 
+	printf("Sending %d %s to '%.*s' with %d maximum outstanding jobs, please wait..\n", 
 		  app.client.job_count, test_type,
 		  (int)app.client.dst_uri.slen, app.client.dst_uri.ptr,
-		  app.client.job_window));
+		  app.client.job_window);
 
 	for (i=0; i<app.thread_count; ++i) {
-	    status = pj_thread_create(app.pool, NULL, &client_thread, NULL,
+	    status = pj_thread_create(app.pool, NULL, &client_thread, (void*)i,
 				      0, 0, &app.thread[i]);
 	    if (status != PJ_SUCCESS) {
@@ -1528,8 +1577,12 @@
 	if (msec_req == 0) msec_req = 1;
 
+	if (app.client.job_submitted < app.client.job_count)
+	    puts("\ntimed-out!\n");
+	else
+	    puts("\ndone.\n");
 
 	pj_ansi_snprintf(
 	    report, sizeof(report),
-	    "Total %d %s sent in %d ms at rate %d/sec\n"
+	    "Total %d %s sent in %d ms at rate of %d/sec\n"
 	    "Total %d responses receieved in %d ms:\n"
 	    " - 2xx responses:  %7d (rate=%d/sec)\n"
Index: pjproject/trunk/pjsip/include/pjsip/sip_config.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 601)
+++ pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 602)
@@ -147,4 +147,55 @@
 #endif
 
+
+/**
+ * This macro controls maximum numbers of ioqueue events to be processed
+ * in a single pjsip_endpt_handle_events() poll. When PJSIP detects that
+ * there are probably more events available from the network and total
+ * events so far is less than this value, PJSIP will call pj_ioqueue_poll()
+ * again to get more events.
+ *
+ * Value 1 works best for ioqueue with select() back-end, while for IOCP it is
+ * probably best to set this value equal to PJSIP_MAX_TIMED_OUT_ENTRIES
+ * since IOCP only processes one event at a time.
+ *
+ * Default: 1
+ */
+#ifndef PJSIP_MAX_NET_EVENTS
+#   define PJSIP_MAX_NET_EVENTS		1
+#endif
+
+
+/**
+ * Max entries to process in timer heap per poll. 
+ * 
+ * Default: 10
+ */
+#ifndef PJSIP_MAX_TIMED_OUT_ENTRIES
+#   define PJSIP_MAX_TIMED_OUT_ENTRIES	10
+#endif
+
+
+/**
+ * Idle timeout interval to be applied to transports with no usage
+ * before the transport is destroyed. Value is in seconds.
+ *
+ * Default: 60
+ */
+#ifndef PJSIP_TRANSPORT_IDLE_TIME
+#   define PJSIP_TRANSPORT_IDLE_TIME	60
+#endif
+
+
+/**
+ * Maximum number of usages for a transport before a new transport is
+ * created. This only applies for ephemeral transports such as TCP.
+ *
+ * Currently this is not used.
+ * 
+ * Default: -1
+ */
+#ifndef PJSIP_MAX_TRANSPORT_USAGE
+#   define PJSIP_MAX_TRANSPORT_USAGE	((unsigned)-1)
+#endif
 
 
@@ -164,6 +215,4 @@
 #define PJSIP_POOL_LEN_UA		4000
 #define PJSIP_POOL_INC_UA		4000
-#define PJSIP_TRANSPORT_CLOSE_TIMEOUT	30
-#define PJSIP_MAX_TRANSPORT_USAGE	16
 
 #define PJSIP_MAX_FORWARDS_VALUE	70
@@ -193,10 +242,4 @@
 #define PJSIP_POOL_INC_DIALOG		512
 
-/* Transport idle timeout before it's destroyed. */
-#define PJSIP_TRANSPORT_IDLE_TIME	30
-
-/* Max entries to process in timer heap per poll. */
-#define PJSIP_MAX_TIMED_OUT_ENTRIES	10
-
 /* Maximum header types. */
 #define PJSIP_MAX_HEADER_TYPES		64
Index: pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 601)
+++ pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 602)
@@ -657,5 +657,5 @@
 	    timeout.sec = timeout.msec = 0;
 	}
-    } while (c > 0 && net_event_count < PJSIP_MAX_TIMED_OUT_ENTRIES*2);
+    } while (c > 0 && net_event_count < PJSIP_MAX_NET_EVENTS);
 
     count += net_event_count;
