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