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(&server_address
);
75 if (g_front
== nacl::kInvalidHandle
) {
76 PrintError("BoundSocket");
81 // Test name collision.
82 nacl::Handle front2
= nacl::BoundSocket(&server_address
);
83 assert(front2
== nacl::kInvalidHandle
);
84 if (front2
== nacl::kInvalidHandle
) {
85 PrintError("BoundSocket");
88 nacl::Handle handles
[8];
89 nacl::MessageHeader header
;
93 // Receive a handle connected to the client.
94 nacl::Handle client_handle
= nacl::kInvalidHandle
;
96 vec
[0].length
= sizeof buffer
;
98 header
.iov_length
= 1;
99 header
.handles
= handles
;
100 header
.handle_count
= sizeof handles
/ sizeof handles
[0];
101 result
= nacl::ReceiveDatagram(g_front
, &header
, 0);
102 if (0 < result
&& header
.handle_count
== 1) {
103 client_handle
= handles
[0];
104 printf("%.*s: %d\n", result
, buffer
, client_handle
);
106 PrintError("ReceiveDatagram");
110 // Test kDontWait for a socket created by socketpair().
111 vec
[0].base
= buffer
;
112 vec
[0].length
= sizeof buffer
;
114 header
.iov_length
= 1;
115 header
.handles
= NULL
;
116 header
.handle_count
= 0;
117 result
= nacl::ReceiveDatagram(client_handle
, &header
, nacl::kDontWait
);
118 assert(result
== -1);
119 PrintError("ReceiveDatagram");
120 assert(nacl::WouldBlock());
122 // Test an empty message.
123 vec
[0].base
= buffer
;
126 header
.iov_length
= 1;
127 header
.handles
= NULL
;
128 header
.handle_count
= 0;
129 result
= nacl::SendDatagram(client_handle
, &header
, 0);
132 // Test scatter/gather.
133 for (unsigned int i
= 0; i
< sizeof vec
/ sizeof vec
[0]; ++i
) {
134 buffer
[i
] = "ABC"[i
];
135 vec
[i
].base
= buffer
+ i
;
139 header
.iov_length
= sizeof vec
/ sizeof vec
[0];
140 header
.handles
= &client_handle
;
141 header
.handle_count
= 1;
142 result
= nacl::SendDatagram(client_handle
, &header
, 0);
143 assert(result
== sizeof vec
/ sizeof vec
[0]);
146 result
= nacl::Receive(client_handle
, buffer
, sizeof buffer
, 0);
148 PrintError("ReceiveDatagram");
152 printf("%.*s\n", result
, buffer
);
155 // Test shared memory.
156 nacl::Handle shared_memory
= nacl::CreateMemoryObject(1024 * 1024);
157 if (shared_memory
!= nacl::kInvalidHandle
) {
158 void* shared_region
= nacl::Map(0, 1024 * 1024,
159 nacl::kProtRead
| nacl::kProtWrite
,
163 memset(shared_region
, 0, 1024 * 1024);
166 header
.iov_length
= 2;
167 header
.handles
= &shared_memory
;
168 header
.handle_count
= 1;
169 nacl::SendDatagram(client_handle
, &header
, 0);
171 memset(shared_region
, 0xff, 1024 * 1024);
172 while (*static_cast<volatile unsigned int*>(shared_region
) ==
175 printf("server: shm ok.\n");
178 nacl::Unmap(shared_region
, 1024 * 1024);
179 nacl::Close(shared_memory
);
182 // Test kDontWait for a large message.
183 vec
[0].base
= buffer
;
184 vec
[0].length
= sizeof buffer
;
186 header
.iov_length
= 1;
187 header
.handles
= NULL
;
188 header
.handle_count
= 0;
189 result
= nacl::ReceiveDatagram(client_handle
, &header
, nacl::kDontWait
);
190 assert(result
== sizeof buffer
);
192 // Test close detection.
193 vec
[0].base
= buffer
;
194 vec
[0].length
= sizeof buffer
;
196 header
.iov_length
= 1;
197 header
.handles
= NULL
;
198 header
.handle_count
= 0;
199 result
= nacl::ReceiveDatagram(client_handle
, &header
, 0);
202 nacl::Close(client_handle
);