1 : /*
2 : * Copyright (c) 2013 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 : #include <stdio.h>
8 : #include <string.h>
9 :
10 : #include "native_client/src/include/nacl_macros.h"
11 : #include "native_client/src/include/portability.h"
12 : #include "native_client/src/shared/platform/nacl_log.h"
13 : #include "native_client/src/shared/platform/nacl_threads.h"
14 : #include "native_client/src/shared/platform/platform_init.h"
15 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
16 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
17 : #include "native_client/src/trusted/desc/nrd_xfer.h"
18 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
19 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
20 :
21 : #define MAX_TEST_DESCS 8
22 :
23 : char *exe_path = NULL;
24 :
25 : struct TestParam {
26 : uint32_t flags;
27 : int32_t metadata_type;
28 : char const *metadata_string;
29 : };
30 :
31 : struct TestCase {
32 : nacl_abi_size_t num_desc;
33 : struct TestParam descs[MAX_TEST_DESCS];
34 : };
35 :
36 : struct TestCase test_case[] = {
37 : { 1, {
38 : { 0x1, 1, "" } } },
39 : { 1, {
40 : { 0x2, 2,
41 : "Goofe' Dean. Well, let's see, we have on the bags,"
42 : " Who's on first, What's on second, I Don't Know is on third..."},
43 : } },
44 : { 2, {
45 : { 0x4, 3,
46 : "That's what I want to find out."},
47 : { 0x8, 4,
48 : "I say Who's on first, What's on second, I Don't Know's on third."},
49 : } },
50 : { 3, {
51 : { 0x10, 5,
52 : "Are you the manager?"},
53 : { 0x20, 6,
54 : "Yes."},
55 : { 0x40, 7,
56 : "You gonna be the coach too?"} } },
57 : { 4, {
58 : { 0x80, 8,
59 : "Yes."},
60 : { 0x100, 9,
61 : "And you don't know the fellows' names?"},
62 : { 0x200, 10,
63 : "Well I should."},
64 : { 0x400, 11, "Well then who's on first?"},
65 : } },
66 : { 8, {
67 : { 0x800, 12, "Yes." },
68 : { 0x1000, 13, "I mean the fellow's name." },
69 : { 0x2000, 14, "Who." },
70 : { 0x4000, 15, "The guy on first." },
71 :
72 : { 0x8000, 16, "Who." },
73 : { 0xffff, 17, "The first baseman." },
74 : { 0xf0f0, 18, "Who." },
75 : { 0x0f0f, 19, "The guy playing..." },
76 : } },
77 : { 7, {
78 : { 0x5555, 20, "Who is on first!" },
79 : { 0xaaaa, 21, "I'm asking YOU who's on first!" },
80 : { 0x8888, 22, "That's the man's name." },
81 : { 0x4444, 23, "That's who's name?" },
82 :
83 : { 0x2222, 24, "Yes." },
84 : { 0x1111, 25, "Well go ahead and tell me." },
85 : { 0x8181, 26, "That's it." },
86 : } },
87 : };
88 :
89 : struct NaClDesc* bound_and_conn_cap[2];
90 :
91 : struct desc_list {
92 : struct desc_list *next;
93 : struct NaClDesc *desc;
94 : };
95 :
96 : struct desc_list *sender_discards = NULL;
97 : struct desc_list *receiver_discards = NULL;
98 :
99 1 : void desc_list_discard(struct desc_list *p) {
100 1 : while (NULL != p) {
101 : struct desc_list *q;
102 1 : NaClDescUnref(p->desc);
103 1 : q = p->next;
104 1 : free(p);
105 1 : p = q;
106 1 : }
107 1 : }
108 1 : void desc_list_add(struct desc_list **dl, struct NaClDesc *d) {
109 1 : struct desc_list *entry = malloc(sizeof *entry);
110 1 : if (NULL == entry) {
111 0 : fprintf(stderr, "desc_list_add: NO MEMORY\n");
112 0 : exit(1);
113 : }
114 1 : entry->next = *dl;
115 1 : entry->desc = d;
116 1 : *dl = entry;
117 1 : }
118 :
119 1 : void sender_thread(void) {
120 : int err;
121 : struct NaClDesc *conn;
122 : size_t ix;
123 : struct NaClImcTypedMsgHdr header;
124 : struct NaClDesc *desc_buf[MAX_TEST_DESCS];
125 : size_t dix;
126 : ssize_t bytes_sent;
127 :
128 1 : printf("[ sender_thread ]\n");
129 : if (0 != (err = (*NACL_VTBL(NaClDesc, bound_and_conn_cap[1])->ConnectAddr)(
130 1 : bound_and_conn_cap[1], &conn))) {
131 0 : fprintf(stderr, "Cound not connect: NaCl errno %d\n", -err);
132 0 : exit(1);
133 : }
134 1 : for (ix = 0; ix < NACL_ARRAY_SIZE(test_case); ++ix) {
135 1 : printf("[ sender: Test %"NACL_PRIdS" ]\n", ix);
136 1 : header.iov = NULL;
137 1 : header.iov_length = 0;
138 1 : header.ndescv = desc_buf;
139 1 : header.ndesc_length = test_case[ix].num_desc;
140 1 : for (dix = 0; dix < header.ndesc_length; ++dix) {
141 : desc_buf[dix] = (struct NaClDesc *)
142 1 : NaClDescIoDescOpen(exe_path, NACL_ABI_O_RDONLY, 0);
143 : err = ((*NACL_VTBL(NaClDesc, desc_buf[dix])->SetMetadata)
144 : (desc_buf[dix], test_case[ix].descs[dix].metadata_type,
145 : (uint32_t) strlen(test_case[ix].descs[dix].metadata_string),
146 1 : (uint8_t const *) test_case[ix].descs[dix].metadata_string));
147 1 : if (0 != err) {
148 : fprintf(stderr,
149 : "ix %"NACL_PRIdS" dix %"NACL_PRIdS
150 : " SetMetadata failed NaCl errno %d\n",
151 0 : ix, dix, -err);
152 0 : exit(1);
153 : }
154 1 : }
155 : bytes_sent = ((*NACL_VTBL(NaClDesc, conn)->SendMsg)
156 1 : (conn, &header, 0));
157 1 : if (0 != bytes_sent) {
158 : fprintf(stderr,
159 : "ix %"NACL_PRIdS" SendMsg failed NaCl errno %"NACL_PRIdS"\n",
160 0 : ix, -bytes_sent);
161 0 : exit(1);
162 : }
163 1 : for (dix = 0; dix < header.ndesc_length; ++dix) {
164 1 : desc_list_add(&sender_discards, desc_buf[dix]);
165 1 : }
166 1 : }
167 : return;
168 1 : }
169 :
170 1 : void receiver_thread(void) {
171 : int err;
172 : struct NaClDesc *conn;
173 : size_t ix;
174 : struct NaClImcTypedMsgHdr header;
175 : struct NaClDesc *desc_buf[MAX_TEST_DESCS];
176 : size_t dix;
177 : ssize_t bytes_received;
178 : int32_t metadata_type;
179 : uint8_t metadata_buffer[1024];
180 : uint32_t metadata_buffer_num_bytes;
181 :
182 1 : printf("[ receiver_thread ]\n");
183 : if (0 != (err = (*NACL_VTBL(NaClDesc, bound_and_conn_cap[0])->AcceptConn)(
184 1 : bound_and_conn_cap[0], &conn))) {
185 0 : fprintf(stderr, "Cound not accept connection: NaCl errno %d\n", -err);
186 0 : exit(1);
187 : }
188 1 : for (ix = 0; ix < NACL_ARRAY_SIZE(test_case); ++ix) {
189 1 : printf("[ receiver: Test %"NACL_PRIdS" ]\n", ix);
190 1 : header.iov = NULL;
191 1 : header.iov_length = 0;
192 1 : header.ndescv = desc_buf;
193 1 : header.ndesc_length = NACL_ARRAY_SIZE(desc_buf);
194 : bytes_received = ((*NACL_VTBL(NaClDesc, conn)->RecvMsg)
195 1 : (conn, &header, 0, NULL));
196 1 : if (0 != bytes_received) {
197 : fprintf(stderr,
198 : "ix %"NACL_PRIdS" RecvMsg failed NaCl errno %"NACL_PRIdS"\n",
199 0 : ix, -bytes_received);
200 0 : exit(1);
201 : }
202 1 : if (header.ndesc_length != test_case[ix].num_desc) {
203 : fprintf(stderr,
204 : "Test case %"NACL_PRIdS", expected %u descriptors, got %u\n",
205 0 : ix, test_case[ix].num_desc, header.ndesc_length);
206 0 : exit(1);
207 : }
208 1 : for (dix = 0; dix < header.ndesc_length; ++dix) {
209 1 : metadata_buffer_num_bytes = sizeof metadata_buffer;
210 : metadata_type = ((*NACL_VTBL(NaClDesc, desc_buf[dix])->GetMetadata)
211 : (desc_buf[dix],
212 1 : &metadata_buffer_num_bytes, metadata_buffer));
213 1 : if (test_case[ix].descs[dix].metadata_type != metadata_type) {
214 : fprintf(stderr,
215 : "ix %"NACL_PRIdS" dix %"NACL_PRIdS
216 : " GetMetadata failed expected metadata %d, got %d\n",
217 0 : ix, dix, test_case[ix].descs[dix].metadata_type, metadata_type);
218 0 : exit(1);
219 : }
220 : if (strlen(test_case[ix].descs[dix].metadata_string) !=
221 1 : metadata_buffer_num_bytes) {
222 : fprintf(stderr,
223 : "ix %"NACL_PRIdS" dix %"NACL_PRIdS
224 : " GetMetadata failed expected %"NACL_PRIdS" bytes, got %u\n",
225 : ix, dix,
226 : strlen(test_case[ix].descs[dix].metadata_string),
227 0 : metadata_buffer_num_bytes);
228 0 : exit(1);
229 : }
230 :
231 1 : metadata_buffer[metadata_buffer_num_bytes] = '\0';
232 : /* these are not ASCII NUL terminated strings */
233 :
234 : if (0 != strcmp(test_case[ix].descs[dix].metadata_string,
235 1 : (char *) metadata_buffer)) {
236 : fprintf(stderr,
237 : "ix %"NACL_PRIdS" dix %"NACL_PRIdS
238 : " GetMetadata failed expected string %s, got %s\n",
239 : ix, dix,
240 : test_case[ix].descs[dix].metadata_string,
241 0 : (char *) metadata_buffer);
242 0 : exit(1);
243 : }
244 1 : printf("%s\n", metadata_buffer);
245 1 : }
246 : /* could unref right away */
247 1 : for (dix = 0; dix < header.ndesc_length; ++dix) {
248 1 : desc_list_add(&receiver_discards, desc_buf[dix]);
249 1 : }
250 1 : }
251 : return;
252 1 : }
253 :
254 1 : void WINAPI child_thread_fn(void *child_thread_state) {
255 : /*
256 : * create and send a desc with flags, and then with metadata string,
257 : * and then with both.
258 : */
259 : UNREFERENCED_PARAMETER(child_thread_state);
260 1 : sender_thread();
261 : return;
262 1 : }
263 :
264 1 : int main(int ac, char **av) {
265 : int err;
266 : struct NaClThread child_thread;
267 :
268 1 : if (ac < 2) {
269 : fprintf(stderr,
270 0 : "metadata_test: the first argument should be path to a file\n");
271 0 : exit(2);
272 : }
273 1 : NaClPlatformInit();
274 1 : exe_path = av[1];
275 1 : if (0 != (err = NaClCommonDescMakeBoundSock(bound_and_conn_cap))) {
276 : fprintf(stderr,
277 0 : "NaClCommonDescMakeBoundSock failed: NaCl errno %d\n", -err);
278 0 : exit(3);
279 : }
280 : if (!NaClThreadCreateJoinable(&child_thread,
281 : child_thread_fn,
282 : (void *) NULL,
283 1 : 65536)) {
284 0 : fprintf(stderr, "could not create worker thread\n");
285 0 : exit(4);
286 : }
287 :
288 1 : receiver_thread();
289 :
290 1 : NaClThreadJoin(&child_thread);
291 :
292 1 : desc_list_discard(sender_discards);
293 1 : desc_list_discard(receiver_discards);
294 :
295 1 : NaClPlatformFini();
296 1 : printf("OK\n");
297 1 : return 0;
298 1 : }
|