blob: 169b6dc28caaa53c58664c7b424764ea2c991afb [file] [log] [blame]
Benny Prijono4766ffe2005-11-01 17:56:59 +00001/* $Id$
Benny Prijonodd859a62005-11-01 16:42:51 +00002 */
3#include "test.h"
4#include <pjlib.h>
5
6#if INCLUDE_ECHO_CLIENT
7
8enum { BUF_SIZE = 512 };
9
10struct client
11{
12 int sock_type;
13 const char *server;
14 int port;
15};
16
Benny Prijono005e4562005-11-01 21:46:17 +000017static pj_atomic_t *totalBytes;
Benny Prijonodd859a62005-11-01 16:42:51 +000018
19#define MSEC_PRINT_DURATION 1000
20
21static int wait_socket(pj_sock_t sock, unsigned msec_timeout)
22{
23 pj_fd_set_t fdset;
24 pj_time_val timeout;
25
26 timeout.sec = 0;
27 timeout.msec = msec_timeout;
28 pj_time_val_normalize(&timeout);
29
30 PJ_FD_ZERO(&fdset);
31 PJ_FD_SET(sock, &fdset);
32
33 return pj_sock_select(FD_SETSIZE, &fdset, NULL, NULL, &timeout);
34}
35
36static int echo_client_thread(void *arg)
37{
38 pj_sock_t sock;
39 char send_buf[BUF_SIZE];
40 char recv_buf[BUF_SIZE];
41 pj_sockaddr_in addr;
42 pj_str_t s;
43 pj_status_t rc;
44 struct client *client = arg;
45 pj_status_t last_recv_err = PJ_SUCCESS, last_send_err = PJ_SUCCESS;
Benny Prijono005e4562005-11-01 21:46:17 +000046 unsigned counter = 0;
Benny Prijonodd859a62005-11-01 16:42:51 +000047
48 rc = app_socket(PJ_AF_INET, client->sock_type, 0, -1, &sock);
49 if (rc != PJ_SUCCESS) {
50 app_perror("...unable to create socket", rc);
51 return -10;
52 }
53
54 rc = pj_sockaddr_in_init( &addr, pj_cstr(&s, client->server),
55 (pj_uint16_t)client->port);
56 if (rc != PJ_SUCCESS) {
57 app_perror("...unable to resolve server", rc);
58 return -15;
59 }
60
61 rc = pj_sock_connect(sock, &addr, sizeof(addr));
62 if (rc != PJ_SUCCESS) {
63 app_perror("...connect() error", rc);
64 pj_sock_close(sock);
65 return -20;
66 }
67
68 PJ_LOG(3,("", "...socket connected to %s:%d",
69 pj_inet_ntoa(addr.sin_addr),
70 pj_ntohs(addr.sin_port)));
71
Benny Prijono005e4562005-11-01 21:46:17 +000072 pj_memset(send_buf, 'A', BUF_SIZE);
73 send_buf[BUF_SIZE-1]='\0';
Benny Prijonodd859a62005-11-01 16:42:51 +000074
75 /* Give other thread chance to initialize themselves! */
Benny Prijono005e4562005-11-01 21:46:17 +000076 pj_thread_sleep(200);
Benny Prijonodd859a62005-11-01 16:42:51 +000077
78 //PJ_LOG(3,("", "...thread %p running", pj_thread_this()));
79
80 for (;;) {
81 int rc;
82 pj_ssize_t bytes;
Benny Prijono005e4562005-11-01 21:46:17 +000083
84 ++counter;
Benny Prijonodd859a62005-11-01 16:42:51 +000085
86 /* Send a packet. */
87 bytes = BUF_SIZE;
88 rc = pj_sock_send(sock, send_buf, &bytes, 0);
89 if (rc != PJ_SUCCESS || bytes != BUF_SIZE) {
90 if (rc != last_send_err) {
91 app_perror("...send() error", rc);
92 PJ_LOG(3,("", "...ignoring subsequent error.."));
93 last_send_err = rc;
94 pj_thread_sleep(100);
95 }
96 continue;
97 }
98
99 rc = wait_socket(sock, 500);
100 if (rc == 0) {
101 PJ_LOG(3,("", "...timeout"));
102 bytes = 0;
103 } else if (rc < 0) {
104 rc = pj_get_netos_error();
105 app_perror("...select() error", rc);
106 break;
107 } else {
108 /* Receive back the original packet. */
109 bytes = 0;
110 do {
111 pj_ssize_t received = BUF_SIZE - bytes;
112 rc = pj_sock_recv(sock, recv_buf+bytes, &received, 0);
113 if (rc != PJ_SUCCESS || received == 0) {
114 if (rc != last_recv_err) {
115 app_perror("...recv() error", rc);
116 PJ_LOG(3,("", "...ignoring subsequent error.."));
117 last_recv_err = rc;
118 pj_thread_sleep(100);
119 }
120 bytes = 0;
121 received = 0;
122 break;
123 }
124 bytes += received;
125 } while (bytes != BUF_SIZE && bytes != 0);
126 }
127
Benny Prijonodd859a62005-11-01 16:42:51 +0000128 if (bytes == 0)
129 continue;
130
131 if (pj_memcmp(send_buf, recv_buf, BUF_SIZE) != 0) {
Benny Prijono005e4562005-11-01 21:46:17 +0000132 recv_buf[BUF_SIZE-1] = '\0';
133 PJ_LOG(3,("", "...error: buffer %u has changed!\n"
134 "send_buf=%s\n"
135 "recv_buf=%s\n",
136 counter, send_buf, recv_buf));
137 //break;
Benny Prijonodd859a62005-11-01 16:42:51 +0000138 }
Benny Prijono005e4562005-11-01 21:46:17 +0000139
140 /* Accumulate total received. */
141 pj_atomic_add(totalBytes, bytes);
Benny Prijonodd859a62005-11-01 16:42:51 +0000142 }
143
144 pj_sock_close(sock);
145 return 0;
146}
147
148int echo_client(int sock_type, const char *server, int port)
149{
150 pj_pool_t *pool;
151 pj_thread_t *thread[ECHO_CLIENT_MAX_THREADS];
152 pj_status_t rc;
153 struct client client;
154 int i;
Benny Prijono005e4562005-11-01 21:46:17 +0000155 pj_atomic_value_t last_received;
156 pj_timestamp last_report;
Benny Prijonodd859a62005-11-01 16:42:51 +0000157
158 client.sock_type = sock_type;
159 client.server = server;
160 client.port = port;
161
162 pool = pj_pool_create( mem, NULL, 4000, 4000, NULL );
163
Benny Prijono005e4562005-11-01 21:46:17 +0000164 rc = pj_atomic_create(pool, 0, &totalBytes);
Benny Prijonodd859a62005-11-01 16:42:51 +0000165 if (rc != PJ_SUCCESS) {
166 PJ_LOG(3,("", "...error: unable to create atomic variable", rc));
167 return -30;
168 }
Benny Prijonodd859a62005-11-01 16:42:51 +0000169
170 PJ_LOG(3,("", "Echo client started"));
171 PJ_LOG(3,("", " Destination: %s:%d",
172 ECHO_SERVER_ADDRESS, ECHO_SERVER_START_PORT));
173 PJ_LOG(3,("", " Press Ctrl-C to exit"));
174
Benny Prijonodd859a62005-11-01 16:42:51 +0000175 for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
176 rc = pj_thread_create( pool, NULL, &echo_client_thread, &client,
177 PJ_THREAD_DEFAULT_STACK_SIZE, 0,
178 &thread[i]);
179 if (rc != PJ_SUCCESS) {
180 app_perror("...error: unable to create thread", rc);
181 return -10;
182 }
183 }
184
Benny Prijono005e4562005-11-01 21:46:17 +0000185 last_received = 0;
186 pj_get_timestamp(&last_report);
187
Benny Prijonodd859a62005-11-01 16:42:51 +0000188 for (;;) {
Benny Prijono005e4562005-11-01 21:46:17 +0000189 pj_timestamp now;
190 unsigned long received, cur_received;
191 unsigned msec;
192 pj_highprec_t bw;
193 pj_time_val elapsed;
194 unsigned bw32;
Benny Prijonodd859a62005-11-01 16:42:51 +0000195
Benny Prijono005e4562005-11-01 21:46:17 +0000196 pj_thread_sleep(1000);
Benny Prijonodd859a62005-11-01 16:42:51 +0000197
Benny Prijono005e4562005-11-01 21:46:17 +0000198 pj_get_timestamp(&now);
199 elapsed = pj_elapsed_time(&last_report, &now);
200 msec = PJ_TIME_VAL_MSEC(elapsed);
201
202 received = pj_atomic_get(totalBytes);
203 cur_received = received - last_received;
204
205 bw = cur_received;
206 pj_highprec_mul(bw, 1000);
207 pj_highprec_div(bw, msec);
208
209 bw32 = (unsigned)bw;
210
211 last_report = now;
212 last_received = received;
Benny Prijonodd859a62005-11-01 16:42:51 +0000213
214 PJ_LOG(3,("", "...%d threads, total bandwidth: %d KB/s",
Benny Prijono005e4562005-11-01 21:46:17 +0000215 ECHO_CLIENT_MAX_THREADS, bw32/1000));
Benny Prijonodd859a62005-11-01 16:42:51 +0000216 }
217
218 for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
219 pj_thread_join( thread[i] );
220 }
221
222 pj_pool_release(pool);
223 return 0;
224}
225
226
227#else
228int dummy_echo_client;
229#endif /* INCLUDE_ECHO_CLIENT */