Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c

Issue 242533005: [NaCl SDK] nacl_io: Add flow control the JavaScript pipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 */ 4 */
5 5
6 #include "nacl_io_demo.h" 6 #include "nacl_io_demo.h"
7 7
8 #include <assert.h> 8 #include <assert.h>
9 #include <errno.h>
10 #include <fcntl.h>
9 #include <stdio.h> 11 #include <stdio.h>
10 #include <stdlib.h> 12 #include <stdlib.h>
11 #include <string.h> 13 #include <string.h>
14 #include <sys/ioctl.h>
12 #include <sys/mount.h> 15 #include <sys/mount.h>
16 #include <sys/param.h>
17 #include <sys/select.h>
18 #include <sys/stat.h>
13 #include <pthread.h> 19 #include <pthread.h>
20 #include <unistd.h>
14 21
15 #include "ppapi/c/pp_errors.h" 22 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/pp_module.h" 23 #include "ppapi/c/pp_module.h"
17 #include "ppapi/c/ppb.h" 24 #include "ppapi/c/ppb.h"
18 #include "ppapi/c/ppb_instance.h" 25 #include "ppapi/c/ppb_instance.h"
19 #include "ppapi/c/ppb_messaging.h" 26 #include "ppapi/c/ppb_messaging.h"
20 #include "ppapi/c/ppb_var.h" 27 #include "ppapi/c/ppb_var.h"
21 #include "ppapi/c/ppb_var_array.h" 28 #include "ppapi/c/ppb_var_array.h"
22 #include "ppapi/c/ppb_var_dictionary.h" 29 #include "ppapi/c/ppb_var_dictionary.h"
23 #include "ppapi/c/ppp.h" 30 #include "ppapi/c/ppp.h"
24 #include "ppapi/c/ppp_instance.h" 31 #include "ppapi/c/ppp_instance.h"
25 #include "ppapi/c/ppp_messaging.h" 32 #include "ppapi/c/ppp_messaging.h"
33 #include "nacl_io/ioctl.h"
26 #include "nacl_io/nacl_io.h" 34 #include "nacl_io/nacl_io.h"
27 35
28 #include "handlers.h" 36 #include "handlers.h"
29 #include "queue.h" 37 #include "queue.h"
30 38
31 #if defined(WIN32) 39 #if defined(WIN32)
32 #define va_copy(d, s) ((d) = (s)) 40 #define va_copy(d, s) ((d) = (s))
33 #endif 41 #endif
34 42
35 typedef struct { 43 typedef struct {
36 const char* name; 44 const char* name;
37 HandleFunc function; 45 HandleFunc function;
38 } FuncNameMapping; 46 } FuncNameMapping;
39 47
40 PP_Instance g_instance = 0; 48 static PP_Instance g_instance = 0;
41 PPB_GetInterface g_get_browser_interface = NULL; 49 static PPB_GetInterface g_get_browser_interface = NULL;
42 PPB_Messaging* g_ppb_messaging = NULL; 50 static PPB_Messaging* g_ppb_messaging = NULL;
43 PPB_Var* g_ppb_var = NULL; 51 PPB_Var* g_ppb_var = NULL;
44 PPB_VarArray* g_ppb_var_array = NULL; 52 PPB_VarArray* g_ppb_var_array = NULL;
45 PPB_VarDictionary* g_ppb_var_dictionary = NULL; 53 PPB_VarDictionary* g_ppb_var_dictionary = NULL;
46 54
47 static FuncNameMapping g_function_map[] = { 55 static FuncNameMapping g_function_map[] = {
48 {"fopen", HandleFopen}, 56 {"fopen", HandleFopen},
49 {"fwrite", HandleFwrite}, 57 {"fwrite", HandleFwrite},
50 {"fread", HandleFread}, 58 {"fread", HandleFread},
51 {"fseek", HandleFseek}, 59 {"fseek", HandleFseek},
52 {"fclose", HandleFclose}, 60 {"fclose", HandleFclose},
(...skipping 10 matching lines...) Expand all
63 {"gethostbyname", HandleGethostbyname}, 71 {"gethostbyname", HandleGethostbyname},
64 {"connect", HandleConnect}, 72 {"connect", HandleConnect},
65 {"send", HandleSend}, 73 {"send", HandleSend},
66 {"recv", HandleRecv}, 74 {"recv", HandleRecv},
67 {"close", HandleClose}, 75 {"close", HandleClose},
68 {NULL, NULL}, 76 {NULL, NULL},
69 }; 77 };
70 78
71 /** A handle to the thread the handles messages. */ 79 /** A handle to the thread the handles messages. */
72 static pthread_t g_handle_message_thread; 80 static pthread_t g_handle_message_thread;
81 static pthread_t g_echo_thread;
73 82
74 /** 83 /**
75 * Create a new PP_Var from a C string. 84 * Create a new PP_Var from a C string.
76 * @param[in] str The string to convert. 85 * @param[in] str The string to convert.
77 * @return A new PP_Var with the contents of |str|. 86 * @return A new PP_Var with the contents of |str|.
78 */ 87 */
79 struct PP_Var CStrToVar(const char* str) { 88 struct PP_Var CStrToVar(const char* str) {
80 return g_ppb_var->VarFromUtf8(str, strlen(str)); 89 return g_ppb_var->VarFromUtf8(str, strlen(str));
81 } 90 }
82 91
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 string = VprintfToNewString(format, args); 141 string = VprintfToNewString(format, args);
133 va_end(args); 142 va_end(args);
134 143
135 var = g_ppb_var->VarFromUtf8(string, strlen(string)); 144 var = g_ppb_var->VarFromUtf8(string, strlen(string));
136 free(string); 145 free(string);
137 146
138 return var; 147 return var;
139 } 148 }
140 149
141 /** 150 /**
142 * Convert a PP_Var to a C string, given a buffer. 151 * Convert a PP_Var to a C string.
143 * @param[in] var The PP_Var to convert. 152 * @param[in] var The PP_Var to convert.
144 * @param[out] buffer The buffer to write to. 153 * @return A newly allocated, NULL-terminated string.
145 * @param[in] length The length of |buffer|.
146 * @return The number of characters written.
147 */ 154 */
148 const char* VarToCStr(struct PP_Var var) { 155 static const char* VarToCStr(struct PP_Var var) {
149 uint32_t length; 156 uint32_t length;
150 const char* str = g_ppb_var->VarToUtf8(var, &length); 157 const char* str = g_ppb_var->VarToUtf8(var, &length);
151 if (str == NULL) { 158 if (str == NULL) {
152 return NULL; 159 return NULL;
153 } 160 }
154 161
155 /* str is NOT NULL-terminated. Copy using memcpy. */ 162 /* str is NOT NULL-terminated. Copy using memcpy. */
156 char* new_str = (char*)malloc(length + 1); 163 char* new_str = (char*)malloc(length + 1);
157 memcpy(new_str, str, length); 164 memcpy(new_str, str, length);
158 new_str[length] = 0; 165 new_str[length] = 0;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 /* Post the error to JavaScript, so the user can see it. */ 279 /* Post the error to JavaScript, so the user can see it. */
273 PostMessageVar(var); 280 PostMessageVar(var);
274 return; 281 return;
275 } 282 }
276 283
277 /* Function returned an output dictionary. Send it to JavaScript. */ 284 /* Function returned an output dictionary. Send it to JavaScript. */
278 PostMessageVar(result_var); 285 PostMessageVar(result_var);
279 g_ppb_var->Release(result_var); 286 g_ppb_var->Release(result_var);
280 } 287 }
281 288
289
290 /**
291 * Helper function used by EchoThread which reads from a file descriptor
292 * and writes all the data that it reads back to the same descriptor.
293 */
294 static void EchoInput(int fd) {
295 char buffer[512];
296 while (1) {
297 int rtn = read(fd, buffer, 512);
298 if (rtn > 0) {
299 int wrote = write(fd, buffer, rtn);
300 if (wrote < rtn)
301 fprintf(stderr, "only wrote %d/%d bytes\n", wrote, rtn);
binji 2014/05/01 20:22:31 might be nice to send these errors to JavaScript,
Sam Clegg 2014/05/01 22:16:55 Done.
302 } else {
303 if (rtn < 0 && errno != EAGAIN)
304 fprintf(stderr, "read failed: %d (%s)\n", errno, strerror(errno));
305 break;
306 }
307 }
308 }
309
310 /**
311 * Worker thread that listens for input on JS pipe nodes and echos all input
312 * back to the same pipe.
313 */
314 static void* EchoThread(void* user_data) {
315 int fd1 = open("/dev/jspipe1", O_RDWR | O_NONBLOCK);
316 int fd2 = open("/dev/jspipe2", O_RDWR | O_NONBLOCK);
317 int fd3 = open("/dev/jspipe3", O_RDWR | O_NONBLOCK);
318 int nfds = MAX(fd1, fd2);
319 nfds = MAX(nfds, fd3);
320 while (1) {
321 fd_set readfds;
322 FD_ZERO(&readfds);
323 FD_SET(fd1, &readfds);
324 FD_SET(fd2, &readfds);
325 FD_SET(fd3, &readfds);
326 int rtn = select(nfds + 1, &readfds, NULL, NULL, NULL);
327 if (rtn < 0 && errno != EAGAIN) {
328 fprintf(stderr, "select failed: %s\n", strerror(errno));
329 break;
330 }
331 if (rtn > 0) {
332 if (FD_ISSET(fd1, &readfds))
333 EchoInput(fd1);
334 if (FD_ISSET(fd2, &readfds))
335 EchoInput(fd2);
336 if (FD_ISSET(fd3, &readfds))
337 EchoInput(fd3);
338 }
339
340 }
341 close(fd1);
342 close(fd2);
343 close(fd3);
344 return 0;
345 }
346
282 /** 347 /**
283 * A worker thread that handles messages from JavaScript. 348 * A worker thread that handles messages from JavaScript.
284 * @param[in] user_data Unused. 349 * @param[in] user_data Unused.
285 * @return unused. 350 * @return unused.
286 */ 351 */
287 void* HandleMessageThread(void* user_data) { 352 void* HandleMessageThread(void* user_data) {
288 while (1) { 353 while (1) {
289 struct PP_Var message = DequeueMessage(); 354 struct PP_Var message = DequeueMessage();
290 HandleMessage(message); 355 HandleMessage(message);
291 g_ppb_var->Release(message); 356 g_ppb_var->Release(message);
(...skipping 19 matching lines...) Expand all
311 0, /* mountflags */ 376 0, /* mountflags */
312 "type=PERSISTENT,expected_size=1048576"); /* data */ 377 "type=PERSISTENT,expected_size=1048576"); /* data */
313 378
314 mount("", /* source. Use relative URL */ 379 mount("", /* source. Use relative URL */
315 "/http", /* target */ 380 "/http", /* target */
316 "httpfs", /* filesystemtype */ 381 "httpfs", /* filesystemtype */
317 0, /* mountflags */ 382 0, /* mountflags */
318 ""); /* data */ 383 ""); /* data */
319 384
320 pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL); 385 pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
386 pthread_create(&g_echo_thread, NULL, &EchoThread, NULL);
321 InitializeMessageQueue(); 387 InitializeMessageQueue();
322 388
323 return PP_TRUE; 389 return PP_TRUE;
324 } 390 }
325 391
326 static void Instance_DidDestroy(PP_Instance instance) { 392 static void Instance_DidDestroy(PP_Instance instance) {
327 } 393 }
328 394
329 static void Instance_DidChangeView(PP_Instance instance, 395 static void Instance_DidChangeView(PP_Instance instance,
330 PP_Resource view_resource) { 396 PP_Resource view_resource) {
331 } 397 }
332 398
333 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { 399 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
334 } 400 }
335 401
336 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, 402 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
337 PP_Resource url_loader) { 403 PP_Resource url_loader) {
338 /* NaCl modules do not need to handle the document load function. */ 404 /* NaCl modules do not need to handle the document load function. */
339 return PP_FALSE; 405 return PP_FALSE;
340 } 406 }
341 407
342 static void Messaging_HandleMessage(PP_Instance instance, 408 static void Messaging_HandleMessage(PP_Instance instance,
343 struct PP_Var message) { 409 struct PP_Var message) {
410 /* Special case for jspipe input handling */
411 if (message.type == PP_VARTYPE_DICTIONARY) {
binji 2014/05/01 20:22:31 this won't work anymore because all messages are d
Sam Clegg 2014/05/01 22:16:55 Done.
412 struct PP_Var keys = g_ppb_var_dictionary->GetKeys(message);
413 struct PP_Var key = g_ppb_var_array->Get(keys, 0);
414 const char* key_string = VarToCStr(key);
415 char pipe_name[64];
416
417 sprintf(pipe_name, "/dev/%s", key_string);
binji 2014/05/01 20:22:31 snprintf
418 int fd = open(pipe_name, O_RDONLY);
419 if (fd < 0) {
420 struct PP_Var var = PrintfToVar("Warning: opening %s failed.",
421 pipe_name);
422 g_ppb_messaging->PostMessage(g_instance, var);
binji 2014/05/01 20:22:31 Use PostMessageVar to cleanup the newly created st
Sam Clegg 2014/05/01 22:16:55 Done.
423 return;
binji 2014/05/01 20:22:31 release PP_Vars on failure
Sam Clegg 2014/05/01 22:16:55 Done.
424 }
425 struct PP_Var payload = g_ppb_var_dictionary->Get(message, key);
426 if (ioctl(fd, NACL_IOC_HANDLEMESSAGE, (char*)&payload) != 0) {
427 struct PP_Var var = PrintfToVar("Error: ioctl on %s failed: %s",
428 pipe_name, strerror(errno));
429 g_ppb_messaging->PostMessage(g_instance, var);
430 }
431 g_ppb_var->Release(keys);
432 g_ppb_var->Release(key);
433 g_ppb_var->Release(payload);
434 close(fd);
435 return;
436 }
437
344 g_ppb_var->AddRef(message); 438 g_ppb_var->AddRef(message);
345 if (!EnqueueMessage(message)) { 439 if (!EnqueueMessage(message)) {
346 g_ppb_var->Release(message); 440 g_ppb_var->Release(message);
347 PostMessageVar( 441 PostMessageVar(
348 PrintfToVar("Warning: dropped message because the queue was full.")); 442 PrintfToVar("Warning: dropped message because the queue was full."));
349 } 443 }
350 } 444 }
351 445
352 #define GET_INTERFACE(var, type, name) \ 446 #define GET_INTERFACE(var, type, name) \
353 var = (type*)(get_browser(name)); \ 447 var = (type*)(get_browser(name)); \
(...skipping 27 matching lines...) Expand all
381 static PPP_Messaging messaging_interface = { 475 static PPP_Messaging messaging_interface = {
382 &Messaging_HandleMessage, 476 &Messaging_HandleMessage,
383 }; 477 };
384 return &messaging_interface; 478 return &messaging_interface;
385 } 479 }
386 return NULL; 480 return NULL;
387 } 481 }
388 482
389 PP_EXPORT void PPP_ShutdownModule() { 483 PP_EXPORT void PPP_ShutdownModule() {
390 } 484 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698