2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // NaCl inter-module communication primitives.
35 // TODO: Make this program a unit test.
41 #include <sys/types.h>
42 #include "native_client/intermodule_comm/nacl_imc.h"
44 nacl::SocketAddress server_address
= {
48 nacl::SocketAddress client_address
= {
60 // Writes the last error message to the standard error.
61 void PrintError(const char* message
) {
64 if (nacl::GetLastErrorString(buffer
, sizeof buffer
) == 0) {
65 fprintf(stderr
, "%s: %s\n", message
, buffer
);
74 g_front
= nacl::BoundSocket(&client_address
);
75 if (g_front
== nacl::kInvalidHandle
) {
76 PrintError("BoundSocket");
82 if (nacl::SocketPair(pair
) != 0) {
83 PrintError("SocketPair");
87 // Test more than one SocketPair() creation
88 nacl::Handle pair2
[2];
89 result
= nacl::SocketPair(pair2
);
92 PrintError("SocketPair");
95 nacl::Close(pair2
[0]);
96 nacl::Close(pair2
[1]);
98 nacl::MessageHeader header
;
102 // Test kDontWait for a bound socket
103 vec
[0].base
= buffer
;
104 vec
[0].length
= sizeof buffer
;
106 header
.iov_length
= 1;
107 header
.handles
= NULL
;
108 header
.handle_count
= 0;
109 result
= nacl::ReceiveDatagram(g_front
, &header
, nacl::kDontWait
);
110 assert(result
== -1);
111 PrintError("ReceiveDatagram");
112 assert(nacl::WouldBlock());
115 strncpy_s(buffer
, sizeof buffer
, "Hello!", sizeof buffer
);
117 strncpy(buffer
, "Hello!", sizeof buffer
);
118 #endif // NACL_WINDOWS
119 vec
[0].base
= buffer
;
120 vec
[0].length
= strlen(buffer
);
122 // Test kCancel ControlHeader::command
123 nacl::Handle broken
[2] = {
125 nacl::Handle(&pair
[1]) // &pair[1] cannot be a valid handle
128 header
.iov_length
= 1;
129 header
.handles
= broken
;
130 header
.handle_count
= sizeof broken
/ sizeof broken
[0];
131 result
= nacl::SendDatagramTo(g_front
, &header
, 0, &server_address
);
132 assert(result
== -1);
134 // Send pair[1] to the server.
136 header
.iov_length
= 1;
137 header
.handles
= &pair
[1];
138 header
.handle_count
= 1;
139 result
= nacl::SendDatagramTo(g_front
, &header
, 0, &server_address
);
140 if (static_cast<size_t>(result
) != vec
[0].length
) {
141 PrintError("SendDatagram");
144 result
= nacl::Close(pair
[1]);
150 nacl::Handle server_handle
= pair
[0];
151 nacl::Handle shared_memory
;
153 // Test an empty message
154 memset(buffer
, 0, sizeof buffer
);
155 vec
[0].base
= buffer
;
156 vec
[0].length
= sizeof buffer
;
158 header
.iov_length
= 1;
159 header
.handles
= NULL
;
160 header
.handle_count
= 0;
161 result
= nacl::ReceiveDatagram(server_handle
, &header
, 0);
164 // Test scatter/gather
165 memset(buffer
, 0, sizeof buffer
);
167 header
.iov_length
= sizeof vec
/ sizeof vec
[0];
168 header
.handles
= NULL
;
169 header
.handle_count
= 0;
170 for (size_t i
= 0; i
< sizeof vec
/ sizeof vec
[0]; ++i
) {
171 vec
[i
].base
= buffer
+ i
;
174 result
= nacl::ReceiveDatagram(server_handle
, &header
, 0);
175 assert(result
== sizeof vec
/ sizeof vec
[0]);
176 assert(header
.flags
& nacl::kMessageTruncated
);
177 assert(header
.flags
& nacl::kHandlesTruncated
);
178 printf("%s\n", buffer
);
181 result
= nacl::Send(server_handle
, buffer
, sizeof vec
/ sizeof vec
[0], 0);
182 assert(result
== sizeof vec
/ sizeof vec
[0]);
184 // Test shared memory
186 header
.iov_length
= sizeof vec
/ sizeof vec
[0];
187 header
.handles
= &shared_memory
;
188 header
.handle_count
= 1;
189 if (0 <= nacl::ReceiveDatagram(server_handle
, &header
, 0) &&
190 header
.handle_count
== 1) {
191 void* shared_region
= nacl::Map(0, 1024 * 1024,
192 nacl::kProtRead
| nacl::kProtWrite
,
196 while (*static_cast<volatile int*>(shared_region
) == 0x00) {
198 printf("client: shm ok.\n");
199 result
= nacl::Send(server_handle
, buffer
, sizeof buffer
, 0);
200 assert(result
== sizeof buffer
);
201 memset(shared_region
, 0x00, 1024 * 1024);
202 nacl::Unmap(shared_region
, 1024 * 1024);
204 nacl::Close(shared_memory
);
206 PrintError("ReceiveDatagram");
209 // Test close detection.
210 nacl::Close(server_handle
);