1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /* This test uses asserts, which are disabled whenever NDEBUG is defined. */
8 : #if defined(NDEBUG)
9 : #undef NDEBUG
10 : #endif
11 :
12 : #include <assert.h>
13 : #include <errno.h>
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 : #if defined(__native_client__)
18 : #include <pthread.h>
19 : #include <stdint.h>
20 : #include "native_client/src/public/imc_syscalls.h"
21 : #include "native_client/src/shared/srpc/nacl_srpc.h"
22 : #else
23 : #include "native_client/src/include/portability.h"
24 : #include "native_client/src/shared/platform/nacl_threads.h"
25 : #include "native_client/src/shared/platform/platform_init.h"
26 : #include "native_client/src/shared/srpc/nacl_srpc.h"
27 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
28 : #include "native_client/src/trusted/desc/nrd_all_modules.h"
29 : #include "native_client/src/trusted/desc/nrd_xfer.h"
30 : #endif
31 : #include "native_client/src/shared/srpc/nacl_srpc_message.h"
32 :
33 : /*
34 : * Tests the NaClSrpcMessageChannel component. This component is a layer
35 : * over IMC that provides the ability to send and receive messages that are
36 : * larger than the size limits imposed by IMC. In particular, IMC imposes
37 : * two limits:
38 : * IMC_USER_BYTES_MAX is the maximum number of bytes that imc_sendmsg
39 : * can possibly send. The actual value may be lower.
40 : * IMC_USER_DESC_MAX is the maximum number of descriptors that imc_sedmsg
41 : * can possibly send.
42 : * There remain, furthermore, limitations on the number of IOV entries that
43 : * a header can have.
44 : *
45 : * main sends and receives various combinations of bytes and descriptors and
46 : * checks the return values.
47 : */
48 :
49 : #if defined(__native_client__)
50 : #define NaClImcMsgIoVec NaClAbiNaClImcMsgIoVec
51 : #endif
52 :
53 : /* TODO(sehr): test larger than IMC_IOVEC_MAX / 2 iov entries. */
54 : #define kIovEntryCount (NACL_ABI_IMC_IOVEC_MAX / 2)
55 : #define kDescCount (4 * NACL_ABI_IMC_USER_DESC_MAX)
56 :
57 : #define ARRAY_SIZE(a) (sizeof a / sizeof a[0])
58 :
59 : #define MAX(a, b) (((a) > (b)) ? (a) : (b))
60 : #define MIN(a, b) (((a) < (b)) ? (a) : (b))
61 :
62 : /* The largest message to be tested. */
63 : size_t g_max_message_size;
64 : /* The size of a fragment. */
65 : size_t g_fragment_bytes;
66 : /* The size of the neighborhood around k * g_fragment_bytes to consider. */
67 : size_t g_message_delta;
68 :
69 : /* An array filled with 0, 1, 2, ... for sending and comparison. */
70 : int32_t* gTestArray;
71 :
72 : /* An array used for recieving messages smaller than a fragment. */
73 : int32_t* gShortBuf;
74 : /* The length of the messages smaller than a fragment. */
75 : size_t g_short_message_length;
76 :
77 : /* An array used for recieving messages larger than a fragment. */
78 : int32_t* gLongBuf;
79 : /* The length of the messages larger than a fragment. */
80 : size_t g_long_message_length;
81 :
82 : /*
83 : * The size of an IOV chunk for a long message. Long messages will be
84 : * uniformly chunked.
85 : */
86 : size_t g_long_message_iov_chunk_size;
87 :
88 : /* An invalid descriptor to be transferred back and forth. */
89 : NaClSrpcMessageDesc g_bogus_desc;
90 :
91 1 : void SendShortMessage(struct NaClSrpcMessageChannel* channel) {
92 : NaClSrpcMessageHeader header;
93 : struct NaClImcMsgIoVec iovec[1];
94 : NaClSrpcMessageDesc descs[1];
95 :
96 : /* One iov entry, short enough to pass in one fragment. */
97 1 : header.iov_length = ARRAY_SIZE(iovec);
98 1 : header.iov = iovec;
99 1 : iovec[0].base = (void*) gTestArray;
100 1 : iovec[0].length = g_short_message_length;
101 : /* One descriptor. */
102 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
103 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
104 1 : descs[0] = g_bogus_desc;
105 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH != 0);
106 : /* Check that the entire message was sent. */
107 : assert(NaClSrpcMessageChannelSend(channel, &header) ==
108 1 : (ssize_t) g_short_message_length);
109 1 : }
110 :
111 1 : void ReceiveShortMessage(struct NaClSrpcMessageChannel* channel) {
112 : NaClSrpcMessageHeader header;
113 : struct NaClImcMsgIoVec iovec[1];
114 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
115 :
116 : /*
117 : * One iov entry pointing to a buffer large enough to read the expected
118 : * result.
119 : */
120 1 : header.iov_length = ARRAY_SIZE(iovec);
121 1 : header.iov = iovec;
122 1 : iovec[0].base = (void*) gShortBuf;
123 1 : iovec[0].length = g_short_message_length;
124 : /* Accept some descriptors. */
125 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
126 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
127 : /* Clear the receive buffer. */
128 1 : memset(gShortBuf, 0, g_short_message_length);
129 : /* Check that all of it was received. */
130 : assert(NaClSrpcMessageChannelReceive(channel, &header) ==
131 1 : (ssize_t) g_short_message_length);
132 : /* Check that the data bytes are as expected. */
133 1 : assert(memcmp(header.iov[0].base, gTestArray, header.iov[0].length) == 0);
134 : /* Check that one descriptor was received. */
135 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
136 1 : assert(header.flags == 0);
137 1 : }
138 :
139 : void PeekShortMessage(struct NaClSrpcMessageChannel* channel,
140 1 : int expected_flags) {
141 : NaClSrpcMessageHeader header;
142 : struct NaClImcMsgIoVec iovec[1];
143 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
144 : size_t i;
145 :
146 : /*
147 : * One iov entry pointing to a buffer large enough to read the expected
148 : * result.
149 : */
150 1 : header.iov_length = ARRAY_SIZE(iovec);
151 1 : header.iov = iovec;
152 1 : iovec[0].base = (void*) gShortBuf;
153 1 : iovec[0].length = g_short_message_length;
154 : /* Accept some descriptors. */
155 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
156 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
157 : /* Clear the receive buffer. */
158 1 : memset(gShortBuf, 0, g_short_message_length);
159 : /* Check that all of it was received. */
160 : assert(NaClSrpcMessageChannelPeek(channel, &header) ==
161 1 : (ssize_t) g_short_message_length);
162 : /* Check that the data bytes are as expected. */
163 1 : for (i = 0; i < header.iov[0].length / sizeof(int32_t); ++i) {
164 1 : assert(gShortBuf[i] == (int32_t) i);
165 1 : }
166 : /* Check that one descriptor was received. */
167 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
168 1 : assert(header.flags == expected_flags);
169 1 : }
170 :
171 1 : void SendLongMessage(struct NaClSrpcMessageChannel* channel) {
172 : NaClSrpcMessageHeader header;
173 : struct NaClImcMsgIoVec iovec[1];
174 : NaClSrpcMessageDesc descs[1];
175 :
176 : /* One iov entry, with enough bytes to require fragmentation. */
177 1 : header.iov_length = ARRAY_SIZE(iovec);
178 1 : header.iov = iovec;
179 1 : iovec[0].base = (void*) gTestArray;
180 1 : iovec[0].length = g_long_message_length;
181 : /* One descriptor. */
182 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
183 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
184 1 : descs[0] = g_bogus_desc;
185 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH != 0);
186 : assert(NaClSrpcMessageChannelSend(channel, &header) ==
187 1 : (ssize_t) g_long_message_length);
188 1 : }
189 :
190 1 : void ReceiveLongMessage(struct NaClSrpcMessageChannel* channel) {
191 : NaClSrpcMessageHeader header;
192 : struct NaClImcMsgIoVec iovec[1];
193 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
194 :
195 : /*
196 : * One iov entry pointing to a buffer large enough to read the expected
197 : * result.
198 : */
199 1 : header.iov_length = ARRAY_SIZE(iovec);
200 1 : header.iov = iovec;
201 1 : iovec[0].base = gLongBuf;
202 1 : iovec[0].length = g_long_message_length;
203 : /* Accept some descriptors. */
204 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
205 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
206 : /* Clear the receive buffer. */
207 1 : memset(gLongBuf, 0, g_long_message_length);
208 : /* Check that all of it was received. */
209 : assert(NaClSrpcMessageChannelReceive(channel, &header) ==
210 1 : (ssize_t) g_long_message_length);
211 : /* Check that the data bytes are as expected. */
212 1 : assert(memcmp(header.iov[0].base, gTestArray, header.iov[0].length) == 0);
213 : /* Check that one descriptor was received. */
214 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
215 1 : assert(header.flags == 0);
216 1 : }
217 :
218 : void SendMessageOfLength(struct NaClSrpcMessageChannel* channel,
219 1 : size_t message_bytes) {
220 : NaClSrpcMessageHeader header;
221 : struct NaClImcMsgIoVec iovec[1];
222 : NaClSrpcMessageDesc descs[1];
223 :
224 : /* One iov entry, with the given number of bytes. */
225 1 : header.iov_length = ARRAY_SIZE(iovec);
226 1 : header.iov = iovec;
227 1 : assert(message_bytes < g_max_message_size);
228 1 : iovec[0].base = (void*) gTestArray;
229 1 : iovec[0].length = message_bytes;
230 : /* One descriptor. */
231 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
232 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
233 1 : descs[0] = g_bogus_desc;
234 : assert(NaClSrpcMessageChannelSend(channel, &header) ==
235 1 : (ssize_t) message_bytes);
236 1 : }
237 :
238 : void ReceiveMessageOfLength(struct NaClSrpcMessageChannel* channel,
239 1 : size_t message_bytes) {
240 : NaClSrpcMessageHeader header;
241 : struct NaClImcMsgIoVec iovec[1];
242 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
243 :
244 : /*
245 : * One iov entry pointing to a buffer large enough to read the expected
246 : * result.
247 : */
248 1 : header.iov_length = ARRAY_SIZE(iovec);
249 1 : header.iov = iovec;
250 1 : iovec[0].base = gLongBuf;
251 1 : iovec[0].length = message_bytes;
252 1 : assert(message_bytes < g_max_message_size);
253 : /* Accept some descriptors. */
254 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
255 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
256 : /* Clear the receive buffer. */
257 1 : memset(gLongBuf, 0, g_long_message_length);
258 : /* Check that all of it was received. */
259 : assert(NaClSrpcMessageChannelReceive(channel, &header) ==
260 1 : (ssize_t) message_bytes);
261 : /* Check that the data bytes are as expected. */
262 1 : assert(memcmp(header.iov[0].base, gTestArray, header.iov[0].length) == 0);
263 : /* Check that one descriptor was received. */
264 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
265 1 : assert(header.flags == 0);
266 1 : }
267 :
268 1 : void ReceiveShorterMessage(struct NaClSrpcMessageChannel* channel) {
269 : NaClSrpcMessageHeader header;
270 : struct NaClImcMsgIoVec iovec[1];
271 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
272 :
273 : /*
274 : * One iov entry pointing to a buffer large enough to read the expected
275 : * result.
276 : */
277 1 : header.iov_length = ARRAY_SIZE(iovec);
278 1 : header.iov = iovec;
279 1 : iovec[0].base = gLongBuf;
280 1 : iovec[0].length = g_long_message_length / 2;
281 : /* Accept some descriptors. */
282 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
283 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
284 : /* Clear the receive buffer. */
285 1 : memset(gLongBuf, 0, g_long_message_length);
286 : /* Check that all of it was received. */
287 : assert(NaClSrpcMessageChannelReceive(channel, &header) ==
288 1 : (ssize_t) g_long_message_length / 2);
289 : /* Check that the data bytes are as expected. */
290 1 : assert(memcmp(header.iov[0].base, gTestArray, header.iov[0].length) == 0);
291 : /* Check that one descriptor was received. */
292 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
293 1 : assert(header.flags == NACL_ABI_RECVMSG_DATA_TRUNCATED);
294 1 : }
295 :
296 1 : void SendLotsOfIovs(struct NaClSrpcMessageChannel* channel) {
297 : NaClSrpcMessageHeader header;
298 : struct NaClImcMsgIoVec iovec[kIovEntryCount];
299 : NaClSrpcMessageDesc descs[1];
300 : size_t i;
301 :
302 : /*
303 : * kIovEntryCount iov entries, each of g_long_message_iov_chunk_size.
304 : * The total data payload fills gTestArray.
305 : */
306 1 : header.iov_length = ARRAY_SIZE(iovec);
307 1 : header.iov = iovec;
308 1 : for(i = 0; i < kIovEntryCount; ++i) {
309 : iovec[i].base =
310 1 : (void*) ((char*) gTestArray + i * g_long_message_iov_chunk_size);
311 1 : iovec[i].length = g_long_message_iov_chunk_size;
312 1 : }
313 : /* And one descriptor. */
314 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
315 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
316 1 : descs[0] = g_bogus_desc;
317 : /* Make sure that the entire message was sent. */
318 : assert(NaClSrpcMessageChannelSend(channel, &header) ==
319 1 : (ssize_t) g_long_message_length);
320 1 : }
321 :
322 1 : void ReceiveLotsOfIovs(struct NaClSrpcMessageChannel* channel) {
323 : NaClSrpcMessageHeader header;
324 : struct NaClImcMsgIoVec iovec[kIovEntryCount];
325 : NaClSrpcMessageDesc descs[NACL_ABI_IMC_USER_DESC_MAX];
326 : char* buf_chunk;
327 : char* test_chunk;
328 : size_t i;
329 :
330 : /*
331 : * kIovEntryCount iov entries, each of g_long_message_iov_chunk_size.
332 : * The total data payload fills gLongBuf.
333 : */
334 1 : header.iov_length = ARRAY_SIZE(iovec);
335 1 : header.iov = iovec;
336 1 : buf_chunk = (char*) gLongBuf;
337 1 : for(i = 0; i < kIovEntryCount; ++i) {
338 1 : iovec[i].base = buf_chunk;
339 1 : iovec[i].length = g_long_message_iov_chunk_size;
340 1 : buf_chunk += iovec[i].length;
341 1 : }
342 : /* Accept some descriptors. */
343 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
344 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
345 : /* Clear the receive buffer. */
346 1 : memset(gLongBuf, 0, g_long_message_length);
347 : /* Check that all of it was received. */
348 : assert(NaClSrpcMessageChannelReceive(channel, &header) ==
349 1 : (ssize_t) g_long_message_length);
350 : /* Check that the data bytes are as expected. */
351 1 : test_chunk = (char*) gTestArray;
352 1 : for(i = 0; i < kIovEntryCount; ++i) {
353 1 : assert(memcmp(header.iov[i].base, test_chunk, header.iov[i].length) == 0);
354 1 : test_chunk += header.iov[i].length;
355 1 : }
356 : /* Check that one descriptor was received. */
357 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == 1);
358 1 : assert(header.flags == 0);
359 1 : }
360 :
361 1 : void SendLotsOfDescs(struct NaClSrpcMessageChannel* channel) {
362 : NaClSrpcMessageHeader header;
363 : NaClSrpcMessageDesc descs[kDescCount];
364 : size_t i;
365 :
366 : /* No iov entries. */
367 1 : header.iov_length = 0;
368 1 : header.iov = 0;
369 : /* kDescCount descriptors. */
370 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = kDescCount;
371 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
372 1 : for (i = 0; i < kDescCount; ++i) {
373 1 : descs[i] = g_bogus_desc;
374 1 : }
375 : /* Check that no error was returned. */
376 1 : assert(NaClSrpcMessageChannelSend(channel, &header) == 0);
377 1 : }
378 :
379 1 : void ReceiveLotsOfDescs(struct NaClSrpcMessageChannel* channel) {
380 : NaClSrpcMessageHeader header;
381 : NaClSrpcMessageDesc descs[4 * kDescCount];
382 : size_t i;
383 :
384 : /* No iov entries. */
385 1 : header.iov_length = 0;
386 1 : header.iov = 0;
387 : /* Accept descriptors than we expect to get. */
388 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
389 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
390 : /* Clear the receive descriptor array. */
391 1 : memset(descs, 0, sizeof descs);
392 : /* Make sure there were no errors. */
393 1 : assert(NaClSrpcMessageChannelReceive(channel, &header) == 0);
394 : /*
395 : * Check that the right number of descriptors was passed and that they have
396 : * the correct value.
397 : */
398 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == kDescCount);
399 1 : for (i = 0; i < kDescCount; ++i) {
400 1 : assert(descs[i] == g_bogus_desc);
401 1 : }
402 1 : assert(header.flags == 0);
403 1 : }
404 :
405 1 : void ReceiveFewerDescs(struct NaClSrpcMessageChannel* channel) {
406 : NaClSrpcMessageHeader header;
407 : NaClSrpcMessageDesc descs[kDescCount / 2];
408 : size_t i;
409 :
410 : /* No iov entries. */
411 1 : header.iov_length = 0;
412 1 : header.iov = 0;
413 : /* Accept descriptors than we expect to get. */
414 1 : header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH = ARRAY_SIZE(descs);
415 1 : header.NACL_SRPC_MESSAGE_HEADER_DESCV = descs;
416 : /* Clear the receive descriptor array. */
417 1 : memset(descs, 0, sizeof descs);
418 : /* Make sure there were no errors. */
419 1 : assert(NaClSrpcMessageChannelReceive(channel, &header) == 0);
420 : /*
421 : * Check that the right number of descriptors was passed and that they have
422 : * the correct value.
423 : */
424 1 : assert(header.NACL_SRPC_MESSAGE_HEADER_DESC_LENGTH == ARRAY_SIZE(descs));
425 1 : for (i = 0; i < ARRAY_SIZE(descs); ++i) {
426 1 : assert(descs[i] == g_bogus_desc);
427 1 : }
428 1 : assert(header.flags == NACL_ABI_RECVMSG_DESC_TRUNCATED);
429 1 : }
430 :
431 1 : void InitArrays(size_t large_array_size) {
432 : /* Round up to a multiple of sizeof(int32_t). */
433 : size_t long_size =
434 1 : (large_array_size + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
435 : size_t short_size =
436 1 : ((large_array_size / 2) + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
437 : size_t i;
438 : /*
439 : * An array filled with monotonically increasing values. Used to check
440 : * payload sanity.
441 : */
442 1 : gTestArray = (int32_t*) malloc(long_size);
443 1 : assert(gTestArray != NULL);
444 1 : for (i = 0; i < long_size / sizeof(int32_t); ++i) {
445 1 : gTestArray[i] = (int32_t) i;
446 1 : }
447 : /* Large buffer used for receiving messages. */
448 1 : gLongBuf = (int32_t*) malloc(long_size);
449 1 : assert(gLongBuf != NULL);
450 : /* Small buffer used for receiving messages. */
451 1 : gShortBuf = (int32_t*) malloc(short_size);
452 1 : assert(gShortBuf != NULL);
453 1 : }
454 :
455 : NaClSrpcMessageDesc g_bound_sock_pair[2];
456 : /* Forward declarations. */
457 : static NaClSrpcMessageDesc Connect(void);
458 : static NaClSrpcMessageDesc Accept(void);
459 :
460 1 : static void Sender(void) {
461 : size_t msg_len;
462 : size_t fragments;
463 : size_t max_fragment_count;
464 : struct NaClSrpcMessageChannel* send_channel =
465 1 : NaClSrpcMessageChannelNew(Connect());
466 1 : assert(send_channel != NULL);
467 : /*
468 : * Test values within g_message_delta of n * g_max_fragment_count on
469 : * either side. Tests for header sizes and boundary cases.
470 : * If g_max_message_size == g_message_delta / 2, this will cover all
471 : * values from 0 to g_max_message_size.
472 : */
473 1 : max_fragment_count = g_max_message_size / g_fragment_bytes;
474 1 : for (fragments = 0; fragments <= max_fragment_count; ++fragments) {
475 : size_t lower =
476 1 : MAX((fragments * g_fragment_bytes) - g_message_delta, 0);
477 : size_t upper =
478 : MIN((fragments * g_fragment_bytes) + g_message_delta,
479 1 : g_max_message_size);
480 1 : for (msg_len = lower; msg_len < upper; ++msg_len) {
481 1 : SendMessageOfLength(send_channel, msg_len);
482 1 : }
483 1 : }
484 : /* Test send/receive of message that fits in one message. */
485 1 : SendShortMessage(send_channel);
486 : /* Test send/receive of message that requires multiple messages. */
487 1 : SendLongMessage(send_channel);
488 : /* Test that fragmentation sets data truncated flag. */
489 1 : SendLongMessage(send_channel);
490 : /* Test send with lots of iov entries that equals one long send. */
491 1 : SendLotsOfIovs(send_channel);
492 : /* Test receive with lots of iov entries that equals one long receive. */
493 1 : SendLongMessage(send_channel);
494 : /* Test fragmentation of large numbers of descriptors. */
495 1 : SendLotsOfDescs(send_channel);
496 : /* Test that fragmentation sets descriptor truncated flag. */
497 1 : SendLotsOfDescs(send_channel);
498 : /* Clean up the channel. */
499 1 : NaClSrpcMessageChannelDelete(send_channel);
500 1 : }
501 :
502 1 : static void Receiver(void* arg) {
503 : size_t msg_len;
504 : size_t fragments;
505 : size_t max_fragment_count;
506 : struct NaClSrpcMessageChannel* recv_channel =
507 1 : NaClSrpcMessageChannelNew(Accept());
508 1 : assert(recv_channel != NULL);
509 :
510 : #if !defined(__native_client__)
511 : UNREFERENCED_PARAMETER(arg);
512 : #endif
513 : /*
514 : * Test values within g_message_delta of n * g_max_fragment_count on
515 : * either side. Tests for header sizes and boundary cases.
516 : * If g_max_message_size == g_message_delta / 2, this will cover all
517 : * values from 0 to g_max_message_size.
518 : */
519 1 : max_fragment_count = g_max_message_size / g_fragment_bytes;
520 1 : for (fragments = 0; fragments <= max_fragment_count; ++fragments) {
521 : size_t lower =
522 1 : MAX((fragments * g_fragment_bytes) - g_message_delta, 0);
523 : size_t upper =
524 : MIN((fragments * g_fragment_bytes) + g_message_delta,
525 1 : g_max_message_size);
526 1 : for (msg_len = lower; msg_len < upper; ++msg_len) {
527 1 : ReceiveMessageOfLength(recv_channel, msg_len);
528 1 : }
529 1 : }
530 : /* Test send/receive of message that fits in one message. */
531 1 : PeekShortMessage(recv_channel, 0);
532 1 : ReceiveShortMessage(recv_channel);
533 : /* Test send/receive of message that requires multiple messages. */
534 1 : PeekShortMessage(recv_channel, NACL_ABI_RECVMSG_DATA_TRUNCATED);
535 1 : ReceiveLongMessage(recv_channel);
536 : /* Test that fragmentation sets data truncated flag. */
537 1 : ReceiveShorterMessage(recv_channel);
538 : /* Test send with lots of iov entries that equals one long send. */
539 1 : ReceiveLongMessage(recv_channel);
540 : /* Test receive with lots of iov entries that equals one long receive. */
541 1 : ReceiveLotsOfIovs(recv_channel);
542 : /* Test fragmentation of large numbers of descriptors. */
543 1 : ReceiveLotsOfDescs(recv_channel);
544 : /* Test that fragmentation sets descriptor truncated flag. */
545 1 : ReceiveFewerDescs(recv_channel);
546 : /* Clean up the channel. */
547 1 : NaClSrpcMessageChannelDelete(recv_channel);
548 1 : }
549 :
550 : #if defined(__native_client__)
551 : static int InitBoundSock(void) {
552 : return (imc_makeboundsock(g_bound_sock_pair) == 0);
553 : }
554 :
555 : static int RunTests(void) {
556 : pthread_t recv_thread;
557 : void* result;
558 : void* (*fp)(void* arg) = (void *(*)(void*)) Receiver;
559 : if (pthread_create(&recv_thread, NULL, fp, NULL) != 0) {
560 : return 0;
561 : }
562 : /* Send a bunch of messages. */
563 : Sender();
564 : /* Close down the receive thread. */
565 : pthread_join(recv_thread, &result);
566 : return 1;
567 : }
568 :
569 : static NaClSrpcMessageDesc Connect(void) {
570 : NaClSrpcMessageDesc desc = imc_connect(g_bound_sock_pair[1]);
571 : assert(desc != -1);
572 : return desc;
573 : }
574 :
575 : static NaClSrpcMessageDesc Accept(void) {
576 : NaClSrpcMessageDesc desc = imc_accept(g_bound_sock_pair[0]);
577 : assert(desc != -1);
578 : return desc;
579 : }
580 :
581 : #else
582 :
583 1 : static int InitBoundSock(void) {
584 1 : return (NaClCommonDescMakeBoundSock(g_bound_sock_pair) == 0);
585 1 : }
586 :
587 1 : static int RunTests(void) {
588 : struct NaClThread recv_thread;
589 1 : void (WINAPI *fp)(void* arg) = (void (WINAPI *)(void*)) Receiver;
590 1 : if (NaClThreadCreateJoinable(&recv_thread, fp, NULL, 1024 * 1024) == 0) {
591 0 : return 0;
592 : }
593 : /* Send a bunch of messages. */
594 1 : Sender();
595 : /* Close down the receive thread. */
596 1 : NaClThreadJoin(&recv_thread);
597 1 : return 1;
598 1 : }
599 :
600 1 : static NaClSrpcMessageDesc Connect(void) {
601 : NaClSrpcMessageDesc desc;
602 : int result =
603 : (*NACL_VTBL(NaClDesc, g_bound_sock_pair[1])->ConnectAddr)(
604 1 : g_bound_sock_pair[1], &desc);
605 1 : assert(result == 0);
606 1 : return desc;
607 1 : }
608 :
609 1 : static NaClSrpcMessageDesc Accept(void) {
610 : NaClSrpcMessageDesc desc;
611 : int result =
612 : (*NACL_VTBL(NaClDesc, g_bound_sock_pair[0])->AcceptConn)(
613 1 : g_bound_sock_pair[0], &desc);
614 1 : assert(result == 0);
615 1 : return desc;
616 1 : }
617 : #endif
618 :
619 1 : int main(int argc, char* argv[]) {
620 1 : if (argc < 4) {
621 0 : fprintf(stderr, "usage: srpc_message max_msg_sz frag_sz delta\n");
622 0 : return 1;
623 : }
624 1 : g_max_message_size = atoi(argv[1]);
625 1 : g_fragment_bytes = atoi(argv[2]);
626 1 : g_message_delta = atoi(argv[3]);
627 :
628 1 : g_short_message_length = g_fragment_bytes / 2;
629 1 : g_long_message_length = 4 * g_fragment_bytes;
630 1 : g_long_message_iov_chunk_size = g_long_message_length / kIovEntryCount;
631 :
632 : #if defined(__native_client__)
633 : assert(NaClSrpcModuleInit());
634 : g_bogus_desc = (NaClSrpcMessageDesc) -1;
635 : #else
636 1 : NaClPlatformInit();
637 1 : NaClNrdAllModulesInit();
638 1 : NaClSrpcModuleInit();
639 1 : g_bogus_desc = (NaClSrpcMessageDesc) NaClDescInvalidMake();
640 : #endif
641 : /* Create the bound socket / socket address pair used to connect. */
642 1 : assert(InitBoundSock());
643 : /* Set up arrays for sending/receiving messages. */
644 1 : InitArrays(g_max_message_size + g_message_delta + sizeof(int32_t));
645 1 : assert(RunTests());
646 1 : NaClSrpcModuleFini();
647 1 : return 0;
648 1 : }
|