1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/peek.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,360 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * A test case for the PR_MSG_PEEK flag of PR_Recv(). 1.11 + * 1.12 + * Test both blocking and non-blocking sockets. 1.13 + */ 1.14 + 1.15 +#include "nspr.h" 1.16 + 1.17 +#include <stdio.h> 1.18 +#include <stdlib.h> 1.19 +#include <string.h> 1.20 + 1.21 +#define BUFFER_SIZE 1024 1.22 + 1.23 +static int iterations = 10; 1.24 + 1.25 +/* 1.26 + * In iteration i, recv_amount[i] is the number of bytes we 1.27 + * wish to receive, and send_amount[i] is the number of bytes 1.28 + * we actually send. Therefore, the number of elements in the 1.29 + * recv_amount or send_amount array should equal to 'iterations'. 1.30 + * For this test to pass we need to ensure that 1.31 + * recv_amount[i] <= BUFFER_SIZE, 1.32 + * send_amount[i] <= BUFFER_SIZE, 1.33 + * send_amount[i] <= recv_amount[i]. 1.34 + */ 1.35 +static PRInt32 recv_amount[10] = { 1.36 + 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32}; 1.37 +static PRInt32 send_amount[10] = { 1.38 + 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32}; 1.39 + 1.40 +/* Blocking I/O */ 1.41 +static void ServerB(void *arg) 1.42 +{ 1.43 + PRFileDesc *listenSock = (PRFileDesc *) arg; 1.44 + PRFileDesc *sock; 1.45 + char buf[BUFFER_SIZE]; 1.46 + PRInt32 nbytes; 1.47 + int i; 1.48 + int j; 1.49 + 1.50 + sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); 1.51 + if (NULL == sock) { 1.52 + fprintf(stderr, "PR_Accept failed\n"); 1.53 + exit(1); 1.54 + } 1.55 + 1.56 + for (i = 0; i < iterations; i++) { 1.57 + memset(buf, 0, sizeof(buf)); 1.58 + nbytes = PR_Recv(sock, buf, recv_amount[i], 1.59 + PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 1.60 + if (-1 == nbytes) { 1.61 + fprintf(stderr, "PR_Recv failed\n"); 1.62 + exit(1); 1.63 + } 1.64 + if (send_amount[i] != nbytes) { 1.65 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.66 + exit(1); 1.67 + } 1.68 + for (j = 0; j < nbytes; j++) { 1.69 + if (buf[j] != 2*i) { 1.70 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.71 + j, 2*i, buf[j]); 1.72 + exit(1); 1.73 + } 1.74 + } 1.75 + fprintf(stderr, "server: peeked expected data\n"); 1.76 + 1.77 + memset(buf, 0, sizeof(buf)); 1.78 + nbytes = PR_Recv(sock, buf, recv_amount[i], 1.79 + PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 1.80 + if (-1 == nbytes) { 1.81 + fprintf(stderr, "PR_Recv failed\n"); 1.82 + exit(1); 1.83 + } 1.84 + if (send_amount[i] != nbytes) { 1.85 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.86 + exit(1); 1.87 + } 1.88 + for (j = 0; j < nbytes; j++) { 1.89 + if (buf[j] != 2*i) { 1.90 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.91 + j, 2*i, buf[j]); 1.92 + exit(1); 1.93 + } 1.94 + } 1.95 + fprintf(stderr, "server: peeked expected data\n"); 1.96 + 1.97 + memset(buf, 0, sizeof(buf)); 1.98 + nbytes = PR_Recv(sock, buf, recv_amount[i], 1.99 + 0, PR_INTERVAL_NO_TIMEOUT); 1.100 + if (-1 == nbytes) { 1.101 + fprintf(stderr, "PR_Recv failed\n"); 1.102 + exit(1); 1.103 + } 1.104 + if (send_amount[i] != nbytes) { 1.105 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.106 + exit(1); 1.107 + } 1.108 + for (j = 0; j < nbytes; j++) { 1.109 + if (buf[j] != 2*i) { 1.110 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.111 + j, 2*i, buf[j]); 1.112 + exit(1); 1.113 + } 1.114 + } 1.115 + fprintf(stderr, "server: received expected data\n"); 1.116 + 1.117 + PR_Sleep(PR_SecondsToInterval(1)); 1.118 + memset(buf, 2*i+1, send_amount[i]); 1.119 + nbytes = PR_Send(sock, buf, send_amount[i], 1.120 + 0, PR_INTERVAL_NO_TIMEOUT); 1.121 + if (-1 == nbytes) { 1.122 + fprintf(stderr, "PR_Send failed\n"); 1.123 + exit(1); 1.124 + } 1.125 + if (send_amount[i] != nbytes) { 1.126 + fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); 1.127 + exit(1); 1.128 + } 1.129 + } 1.130 + if (PR_Close(sock) == PR_FAILURE) { 1.131 + fprintf(stderr, "PR_Close failed\n"); 1.132 + exit(1); 1.133 + } 1.134 +} 1.135 + 1.136 +/* Non-blocking I/O */ 1.137 +static void ClientNB(void *arg) 1.138 +{ 1.139 + PRFileDesc *sock; 1.140 + PRSocketOptionData opt; 1.141 + PRUint16 port = (PRUint16) arg; 1.142 + PRNetAddr addr; 1.143 + char buf[BUFFER_SIZE]; 1.144 + PRPollDesc pd; 1.145 + PRInt32 npds; 1.146 + PRInt32 nbytes; 1.147 + int i; 1.148 + int j; 1.149 + 1.150 + sock = PR_OpenTCPSocket(PR_AF_INET6); 1.151 + if (NULL == sock) { 1.152 + fprintf(stderr, "PR_OpenTCPSocket failed\n"); 1.153 + exit(1); 1.154 + } 1.155 + opt.option = PR_SockOpt_Nonblocking; 1.156 + opt.value.non_blocking = PR_TRUE; 1.157 + if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) { 1.158 + fprintf(stderr, "PR_SetSocketOption failed\n"); 1.159 + exit(1); 1.160 + } 1.161 + memset(&addr, 0, sizeof(addr)); 1.162 + if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr) 1.163 + == PR_FAILURE) { 1.164 + fprintf(stderr, "PR_SetNetAddr failed\n"); 1.165 + exit(1); 1.166 + } 1.167 + if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { 1.168 + if (PR_GetError() != PR_IN_PROGRESS_ERROR) { 1.169 + fprintf(stderr, "PR_Connect failed\n"); 1.170 + exit(1); 1.171 + } 1.172 + pd.fd = sock; 1.173 + pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; 1.174 + npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 1.175 + if (-1 == npds) { 1.176 + fprintf(stderr, "PR_Poll failed\n"); 1.177 + exit(1); 1.178 + } 1.179 + if (1 != npds) { 1.180 + fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 1.181 + exit(1); 1.182 + } 1.183 + if (PR_GetConnectStatus(&pd) == PR_FAILURE) { 1.184 + fprintf(stderr, "PR_GetConnectStatus failed\n"); 1.185 + exit(1); 1.186 + } 1.187 + } 1.188 + 1.189 + for (i = 0; i < iterations; i++) { 1.190 + PR_Sleep(PR_SecondsToInterval(1)); 1.191 + memset(buf, 2*i, send_amount[i]); 1.192 + while ((nbytes = PR_Send(sock, buf, send_amount[i], 1.193 + 0, PR_INTERVAL_NO_TIMEOUT)) == -1) { 1.194 + if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { 1.195 + fprintf(stderr, "PR_Send failed\n"); 1.196 + exit(1); 1.197 + } 1.198 + pd.fd = sock; 1.199 + pd.in_flags = PR_POLL_WRITE; 1.200 + npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 1.201 + if (-1 == npds) { 1.202 + fprintf(stderr, "PR_Poll failed\n"); 1.203 + exit(1); 1.204 + } 1.205 + if (1 != npds) { 1.206 + fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 1.207 + exit(1); 1.208 + } 1.209 + } 1.210 + if (send_amount[i] != nbytes) { 1.211 + fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); 1.212 + exit(1); 1.213 + } 1.214 + 1.215 + memset(buf, 0, sizeof(buf)); 1.216 + while ((nbytes = PR_Recv(sock, buf, recv_amount[i], 1.217 + PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) { 1.218 + if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { 1.219 + fprintf(stderr, "PR_Recv failed\n"); 1.220 + exit(1); 1.221 + } 1.222 + pd.fd = sock; 1.223 + pd.in_flags = PR_POLL_READ; 1.224 + npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 1.225 + if (-1 == npds) { 1.226 + fprintf(stderr, "PR_Poll failed\n"); 1.227 + exit(1); 1.228 + } 1.229 + if (1 != npds) { 1.230 + fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 1.231 + exit(1); 1.232 + } 1.233 + } 1.234 + if (send_amount[i] != nbytes) { 1.235 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.236 + exit(1); 1.237 + } 1.238 + for (j = 0; j < nbytes; j++) { 1.239 + if (buf[j] != 2*i+1) { 1.240 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.241 + j, 2*i+1, buf[j]); 1.242 + exit(1); 1.243 + } 1.244 + } 1.245 + fprintf(stderr, "client: peeked expected data\n"); 1.246 + 1.247 + memset(buf, 0, sizeof(buf)); 1.248 + nbytes = PR_Recv(sock, buf, recv_amount[i], 1.249 + PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 1.250 + if (-1 == nbytes) { 1.251 + fprintf(stderr, "PR_Recv failed\n"); 1.252 + exit(1); 1.253 + } 1.254 + if (send_amount[i] != nbytes) { 1.255 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.256 + exit(1); 1.257 + } 1.258 + for (j = 0; j < nbytes; j++) { 1.259 + if (buf[j] != 2*i+1) { 1.260 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.261 + j, 2*i+1, buf[j]); 1.262 + exit(1); 1.263 + } 1.264 + } 1.265 + fprintf(stderr, "client: peeked expected data\n"); 1.266 + 1.267 + memset(buf, 0, sizeof(buf)); 1.268 + nbytes = PR_Recv(sock, buf, recv_amount[i], 1.269 + 0, PR_INTERVAL_NO_TIMEOUT); 1.270 + if (-1 == nbytes) { 1.271 + fprintf(stderr, "PR_Recv failed\n"); 1.272 + exit(1); 1.273 + } 1.274 + if (send_amount[i] != nbytes) { 1.275 + fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 1.276 + exit(1); 1.277 + } 1.278 + for (j = 0; j < nbytes; j++) { 1.279 + if (buf[j] != 2*i+1) { 1.280 + fprintf(stderr, "byte %d should be %d but is %d\n", 1.281 + j, 2*i+1, buf[j]); 1.282 + exit(1); 1.283 + } 1.284 + } 1.285 + fprintf(stderr, "client: received expected data\n"); 1.286 + } 1.287 + if (PR_Close(sock) == PR_FAILURE) { 1.288 + fprintf(stderr, "PR_Close failed\n"); 1.289 + exit(1); 1.290 + } 1.291 +} 1.292 + 1.293 +static void 1.294 +RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port) 1.295 +{ 1.296 + PRThread *server, *client; 1.297 + 1.298 + server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock, 1.299 + PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); 1.300 + if (NULL == server) { 1.301 + fprintf(stderr, "PR_CreateThread failed\n"); 1.302 + exit(1); 1.303 + } 1.304 + client = PR_CreateThread( 1.305 + PR_USER_THREAD, ClientNB, (void *) port, 1.306 + PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); 1.307 + if (NULL == client) { 1.308 + fprintf(stderr, "PR_CreateThread failed\n"); 1.309 + exit(1); 1.310 + } 1.311 + 1.312 + if (PR_JoinThread(server) == PR_FAILURE) { 1.313 + fprintf(stderr, "PR_JoinThread failed\n"); 1.314 + exit(1); 1.315 + } 1.316 + if (PR_JoinThread(client) == PR_FAILURE) { 1.317 + fprintf(stderr, "PR_JoinThread failed\n"); 1.318 + exit(1); 1.319 + } 1.320 +} 1.321 + 1.322 +int main(int argc, char **argv) 1.323 +{ 1.324 + PRFileDesc *listenSock; 1.325 + PRNetAddr addr; 1.326 + PRUint16 port; 1.327 + 1.328 + listenSock = PR_OpenTCPSocket(PR_AF_INET6); 1.329 + if (NULL == listenSock) { 1.330 + fprintf(stderr, "PR_OpenTCPSocket failed\n"); 1.331 + exit(1); 1.332 + } 1.333 + memset(&addr, 0, sizeof(addr)); 1.334 + if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { 1.335 + fprintf(stderr, "PR_SetNetAddr failed\n"); 1.336 + exit(1); 1.337 + } 1.338 + if (PR_Bind(listenSock, &addr) == PR_FAILURE) { 1.339 + fprintf(stderr, "PR_Bind failed\n"); 1.340 + exit(1); 1.341 + } 1.342 + if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { 1.343 + fprintf(stderr, "PR_GetSockName failed\n"); 1.344 + exit(1); 1.345 + } 1.346 + port = PR_ntohs(addr.ipv6.port); 1.347 + if (PR_Listen(listenSock, 5) == PR_FAILURE) { 1.348 + fprintf(stderr, "PR_Listen failed\n"); 1.349 + exit(1); 1.350 + } 1.351 + 1.352 + fprintf(stderr, "Running the test with local threads\n"); 1.353 + RunTest(PR_LOCAL_THREAD, listenSock, port); 1.354 + fprintf(stderr, "Running the test with global threads\n"); 1.355 + RunTest(PR_GLOBAL_THREAD, listenSock, port); 1.356 + 1.357 + if (PR_Close(listenSock) == PR_FAILURE) { 1.358 + fprintf(stderr, "PR_Close failed\n"); 1.359 + exit(1); 1.360 + } 1.361 + printf("PASS\n"); 1.362 + return 0; 1.363 +}