blob: 897e94d614fd53a70b4fa633e4c8a373be614404 [file] [log] [blame]
Benny Prijono4766ffe2005-11-01 17:56:59 +00001/* $Id$
2 *
3 */
Benny Prijonodd859a62005-11-01 16:42:51 +00004/*
5 * $Log: /pjproject-0.3/pjlib/src/pjlib-test/echo_clt.c $
6 *
7 * 3 10/29/05 10:25p Bennylp
8 * Tested.
9 *
10 * 2 10/29/05 11:51a Bennylp
11 * Version 0.3-pre2.
12 *
13 * 1 10/24/05 11:28a Bennylp
14 * Created.
15 *
16 */
17#include "test.h"
18#include <pjlib.h>
19
20#if INCLUDE_ECHO_CLIENT
21
22enum { BUF_SIZE = 512 };
23
24struct client
25{
26 int sock_type;
27 const char *server;
28 int port;
29};
30
Benny Prijono005e4562005-11-01 21:46:17 +000031static pj_atomic_t *totalBytes;
Benny Prijonodd859a62005-11-01 16:42:51 +000032
33#define MSEC_PRINT_DURATION 1000
34
35static int wait_socket(pj_sock_t sock, unsigned msec_timeout)
36{
37 pj_fd_set_t fdset;
38 pj_time_val timeout;
39
40 timeout.sec = 0;
41 timeout.msec = msec_timeout;
42 pj_time_val_normalize(&timeout);
43
44 PJ_FD_ZERO(&fdset);
45 PJ_FD_SET(sock, &fdset);
46
47 return pj_sock_select(FD_SETSIZE, &fdset, NULL, NULL, &timeout);
48}
49
50static int echo_client_thread(void *arg)
51{
52 pj_sock_t sock;
53 char send_buf[BUF_SIZE];
54 char recv_buf[BUF_SIZE];
55 pj_sockaddr_in addr;
56 pj_str_t s;
57 pj_status_t rc;
58 struct client *client = arg;
59 pj_status_t last_recv_err = PJ_SUCCESS, last_send_err = PJ_SUCCESS;
Benny Prijono005e4562005-11-01 21:46:17 +000060 unsigned counter = 0;
Benny Prijonodd859a62005-11-01 16:42:51 +000061
62 rc = app_socket(PJ_AF_INET, client->sock_type, 0, -1, &sock);
63 if (rc != PJ_SUCCESS) {
64 app_perror("...unable to create socket", rc);
65 return -10;
66 }
67
68 rc = pj_sockaddr_in_init( &addr, pj_cstr(&s, client->server),
69 (pj_uint16_t)client->port);
70 if (rc != PJ_SUCCESS) {
71 app_perror("...unable to resolve server", rc);
72 return -15;
73 }
74
75 rc = pj_sock_connect(sock, &addr, sizeof(addr));
76 if (rc != PJ_SUCCESS) {
77 app_perror("...connect() error", rc);
78 pj_sock_close(sock);
79 return -20;
80 }
81
82 PJ_LOG(3,("", "...socket connected to %s:%d",
83 pj_inet_ntoa(addr.sin_addr),
84 pj_ntohs(addr.sin_port)));
85
Benny Prijono005e4562005-11-01 21:46:17 +000086 pj_memset(send_buf, 'A', BUF_SIZE);
87 send_buf[BUF_SIZE-1]='\0';
Benny Prijonodd859a62005-11-01 16:42:51 +000088
89 /* Give other thread chance to initialize themselves! */
Benny Prijono005e4562005-11-01 21:46:17 +000090 pj_thread_sleep(200);
Benny Prijonodd859a62005-11-01 16:42:51 +000091
92 //PJ_LOG(3,("", "...thread %p running", pj_thread_this()));
93
94 for (;;) {
95 int rc;
96 pj_ssize_t bytes;
Benny Prijono005e4562005-11-01 21:46:17 +000097
98 ++counter;
Benny Prijonodd859a62005-11-01 16:42:51 +000099
100 /* Send a packet. */
101 bytes = BUF_SIZE;
102 rc = pj_sock_send(sock, send_buf, &bytes, 0);
103 if (rc != PJ_SUCCESS || bytes != BUF_SIZE) {
104 if (rc != last_send_err) {
105 app_perror("...send() error", rc);
106 PJ_LOG(3,("", "...ignoring subsequent error.."));
107 last_send_err = rc;
108 pj_thread_sleep(100);
109 }
110 continue;
111 }
112
113 rc = wait_socket(sock, 500);
114 if (rc == 0) {
115 PJ_LOG(3,("", "...timeout"));
116 bytes = 0;
117 } else if (rc < 0) {
118 rc = pj_get_netos_error();
119 app_perror("...select() error", rc);
120 break;
121 } else {
122 /* Receive back the original packet. */
123 bytes = 0;
124 do {
125 pj_ssize_t received = BUF_SIZE - bytes;
126 rc = pj_sock_recv(sock, recv_buf+bytes, &received, 0);
127 if (rc != PJ_SUCCESS || received == 0) {
128 if (rc != last_recv_err) {
129 app_perror("...recv() error", rc);
130 PJ_LOG(3,("", "...ignoring subsequent error.."));
131 last_recv_err = rc;
132 pj_thread_sleep(100);
133 }
134 bytes = 0;
135 received = 0;
136 break;
137 }
138 bytes += received;
139 } while (bytes != BUF_SIZE && bytes != 0);
140 }
141
Benny Prijonodd859a62005-11-01 16:42:51 +0000142 if (bytes == 0)
143 continue;
144
145 if (pj_memcmp(send_buf, recv_buf, BUF_SIZE) != 0) {
Benny Prijono005e4562005-11-01 21:46:17 +0000146 recv_buf[BUF_SIZE-1] = '\0';
147 PJ_LOG(3,("", "...error: buffer %u has changed!\n"
148 "send_buf=%s\n"
149 "recv_buf=%s\n",
150 counter, send_buf, recv_buf));
151 //break;
Benny Prijonodd859a62005-11-01 16:42:51 +0000152 }
Benny Prijono005e4562005-11-01 21:46:17 +0000153
154 /* Accumulate total received. */
155 pj_atomic_add(totalBytes, bytes);
Benny Prijonodd859a62005-11-01 16:42:51 +0000156 }
157
158 pj_sock_close(sock);
159 return 0;
160}
161
162int echo_client(int sock_type, const char *server, int port)
163{
164 pj_pool_t *pool;
165 pj_thread_t *thread[ECHO_CLIENT_MAX_THREADS];
166 pj_status_t rc;
167 struct client client;
168 int i;
Benny Prijono005e4562005-11-01 21:46:17 +0000169 pj_atomic_value_t last_received;
170 pj_timestamp last_report;
Benny Prijonodd859a62005-11-01 16:42:51 +0000171
172 client.sock_type = sock_type;
173 client.server = server;
174 client.port = port;
175
176 pool = pj_pool_create( mem, NULL, 4000, 4000, NULL );
177
Benny Prijono005e4562005-11-01 21:46:17 +0000178 rc = pj_atomic_create(pool, 0, &totalBytes);
Benny Prijonodd859a62005-11-01 16:42:51 +0000179 if (rc != PJ_SUCCESS) {
180 PJ_LOG(3,("", "...error: unable to create atomic variable", rc));
181 return -30;
182 }
Benny Prijonodd859a62005-11-01 16:42:51 +0000183
184 PJ_LOG(3,("", "Echo client started"));
185 PJ_LOG(3,("", " Destination: %s:%d",
186 ECHO_SERVER_ADDRESS, ECHO_SERVER_START_PORT));
187 PJ_LOG(3,("", " Press Ctrl-C to exit"));
188
Benny Prijonodd859a62005-11-01 16:42:51 +0000189 for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
190 rc = pj_thread_create( pool, NULL, &echo_client_thread, &client,
191 PJ_THREAD_DEFAULT_STACK_SIZE, 0,
192 &thread[i]);
193 if (rc != PJ_SUCCESS) {
194 app_perror("...error: unable to create thread", rc);
195 return -10;
196 }
197 }
198
Benny Prijono005e4562005-11-01 21:46:17 +0000199 last_received = 0;
200 pj_get_timestamp(&last_report);
201
Benny Prijonodd859a62005-11-01 16:42:51 +0000202 for (;;) {
Benny Prijono005e4562005-11-01 21:46:17 +0000203 pj_timestamp now;
204 unsigned long received, cur_received;
205 unsigned msec;
206 pj_highprec_t bw;
207 pj_time_val elapsed;
208 unsigned bw32;
Benny Prijonodd859a62005-11-01 16:42:51 +0000209
Benny Prijono005e4562005-11-01 21:46:17 +0000210 pj_thread_sleep(1000);
Benny Prijonodd859a62005-11-01 16:42:51 +0000211
Benny Prijono005e4562005-11-01 21:46:17 +0000212 pj_get_timestamp(&now);
213 elapsed = pj_elapsed_time(&last_report, &now);
214 msec = PJ_TIME_VAL_MSEC(elapsed);
215
216 received = pj_atomic_get(totalBytes);
217 cur_received = received - last_received;
218
219 bw = cur_received;
220 pj_highprec_mul(bw, 1000);
221 pj_highprec_div(bw, msec);
222
223 bw32 = (unsigned)bw;
224
225 last_report = now;
226 last_received = received;
Benny Prijonodd859a62005-11-01 16:42:51 +0000227
228 PJ_LOG(3,("", "...%d threads, total bandwidth: %d KB/s",
Benny Prijono005e4562005-11-01 21:46:17 +0000229 ECHO_CLIENT_MAX_THREADS, bw32/1000));
Benny Prijonodd859a62005-11-01 16:42:51 +0000230 }
231
232 for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
233 pj_thread_join( thread[i] );
234 }
235
236 pj_pool_release(pool);
237 return 0;
238}
239
240
241#else
242int dummy_echo_client;
243#endif /* INCLUDE_ECHO_CLIENT */