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

Unified 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: 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 side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
diff --git a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
index 6a08cd22d8e7af3fd6c015d2c823e69214b7a335..226d50f662ea4546ea45f62b2342dca5fb4840fc 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
@@ -6,11 +6,19 @@
#include "nacl_io_demo.h"
#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/stat.h>
#include <pthread.h>
+#include <unistd.h>
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_module.h"
@@ -23,6 +31,7 @@
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppp_messaging.h"
+#include "nacl_io/ioctl.h"
#include "nacl_io/nacl_io.h"
#include "handlers.h"
@@ -37,9 +46,9 @@ typedef struct {
HandleFunc function;
} FuncNameMapping;
-PP_Instance g_instance = 0;
-PPB_GetInterface g_get_browser_interface = NULL;
-PPB_Messaging* g_ppb_messaging = NULL;
+static PP_Instance g_instance = 0;
+static PPB_GetInterface g_get_browser_interface = NULL;
+static PPB_Messaging* g_ppb_messaging = NULL;
PPB_Var* g_ppb_var = NULL;
PPB_VarArray* g_ppb_var_array = NULL;
PPB_VarDictionary* g_ppb_var_dictionary = NULL;
@@ -70,6 +79,7 @@ static FuncNameMapping g_function_map[] = {
/** A handle to the thread the handles messages. */
static pthread_t g_handle_message_thread;
+static pthread_t g_echo_thread;
/**
* Create a new PP_Var from a C string.
@@ -118,34 +128,25 @@ char* PrintfToNewString(const char* format, ...) {
}
/**
- * Printf to a new PP_Var.
+ * Vprintf to a new PP_Var.
* @param[in] format A print format string.
- * @param[in] ... The printf arguments.
+ * @param[in] va_list The printf arguments.
* @return A new PP_Var.
*/
-struct PP_Var PrintfToVar(const char* format, ...) {
- char* string;
- va_list args;
+static struct PP_Var VprintfToVar(const char* format, va_list args) {
struct PP_Var var;
-
- va_start(args, format);
- string = VprintfToNewString(format, args);
- va_end(args);
-
+ char* string = VprintfToNewString(format, args);
var = g_ppb_var->VarFromUtf8(string, strlen(string));
free(string);
-
return var;
}
/**
- * Convert a PP_Var to a C string, given a buffer.
+ * Convert a PP_Var to a C string.
* @param[in] var The PP_Var to convert.
- * @param[out] buffer The buffer to write to.
- * @param[in] length The length of |buffer|.
- * @return The number of characters written.
+ * @return A newly allocated, NULL-terminated string.
*/
-const char* VarToCStr(struct PP_Var var) {
+static const char* VarToCStr(struct PP_Var var) {
uint32_t length;
const char* str = g_ppb_var->VarToUtf8(var, &length);
if (str == NULL) {
@@ -174,10 +175,18 @@ struct PP_Var GetDictVar(struct PP_Var dict, const char* key) {
}
/**
- * Send a newly-created PP_Var to JavaScript, then release it.
- * @param[in] var The PP_Var to send.
+ * Post a message to JavaScript.
+ * @param[in] format A printf format string.
+ * @param[in] ... The printf arguments.
*/
-static void PostMessageVar(struct PP_Var var) {
+static void PostMessage(const char* format, ...) {
+ struct PP_Var var;
+ va_list args;
+
+ va_start(args, format);
+ var = VprintfToVar(format, args);
+ va_end(args);
+
g_ppb_messaging->PostMessage(g_instance, var);
g_ppb_var->Release(var);
}
@@ -243,15 +252,14 @@ static void HandleMessage(struct PP_Var message) {
const char* function_name;
struct PP_Var params;
if (ParseMessage(message, &function_name, &params)) {
- PostMessageVar(CStrToVar("Error: Unable to parse message"));
+ PostMessage("Error: Unable to parse message");
return;
}
HandleFunc function = GetFunctionByName(function_name);
if (!function) {
/* Function name wasn't found. Error. */
- PostMessageVar(
- PrintfToVar("Error: Unknown function \"%s\"", function_name));
+ PostMessage("Error: Unknown function \"%s\"", function_name);
return;
}
@@ -261,24 +269,78 @@ static void HandleMessage(struct PP_Var message) {
int result = (*function)(params, &result_var, &error);
if (result != 0) {
/* Error. */
- struct PP_Var var;
if (error != NULL) {
- var = PrintfToVar("Error: \"%s\" failed: %s.", function_name, error);
+ PostMessage("Error: \"%s\" failed: %s.", function_name, error);
free((void*)error);
} else {
- var = PrintfToVar("Error: \"%s\" failed.", function_name);
+ PostMessage("Error: \"%s\" failed.", function_name);
}
-
- /* Post the error to JavaScript, so the user can see it. */
- PostMessageVar(var);
return;
}
/* Function returned an output dictionary. Send it to JavaScript. */
- PostMessageVar(result_var);
+ g_ppb_messaging->PostMessage(g_instance, result_var);
g_ppb_var->Release(result_var);
}
+
+/**
+ * Helper function used by EchoThread which reads from a file descriptor
+ * and writes all the data that it reads back to the same descriptor.
+ */
+static void EchoInput(int fd) {
+ char buffer[512];
+ while (1) {
+ int rtn = read(fd, buffer, 512);
+ if (rtn > 0) {
+ int wrote = write(fd, buffer, rtn);
+ if (wrote < rtn)
+ PostMessage("only wrote %d/%d bytes\n", wrote, rtn);
+ } else {
+ if (rtn < 0 && errno != EAGAIN)
+ PostMessage("read failed: %d (%s)\n", errno, strerror(errno));
+ break;
+ }
+ }
+}
+
+/**
+ * Worker thread that listens for input on JS pipe nodes and echos all input
+ * back to the same pipe.
+ */
+static void* EchoThread(void* user_data) {
+ int fd1 = open("/dev/jspipe1", O_RDWR | O_NONBLOCK);
+ int fd2 = open("/dev/jspipe2", O_RDWR | O_NONBLOCK);
+ int fd3 = open("/dev/jspipe3", O_RDWR | O_NONBLOCK);
+ int nfds = MAX(fd1, fd2);
+ nfds = MAX(nfds, fd3);
+ while (1) {
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(fd1, &readfds);
+ FD_SET(fd2, &readfds);
+ FD_SET(fd3, &readfds);
+ int rtn = select(nfds + 1, &readfds, NULL, NULL, NULL);
+ if (rtn < 0 && errno != EAGAIN) {
+ PostMessage("select failed: %s\n", strerror(errno));
+ break;
+ }
+ if (rtn > 0) {
+ if (FD_ISSET(fd1, &readfds))
+ EchoInput(fd1);
+ if (FD_ISSET(fd2, &readfds))
+ EchoInput(fd2);
+ if (FD_ISSET(fd3, &readfds))
+ EchoInput(fd3);
+ }
+
+ }
+ close(fd1);
+ close(fd2);
+ close(fd3);
+ return 0;
+}
+
/**
* A worker thread that handles messages from JavaScript.
* @param[in] user_data Unused.
@@ -318,6 +380,7 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
""); /* data */
pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
+ pthread_create(&g_echo_thread, NULL, &EchoThread, NULL);
InitializeMessageQueue();
return PP_TRUE;
@@ -341,12 +404,41 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
static void Messaging_HandleMessage(PP_Instance instance,
struct PP_Var message) {
+ /* Special case for jspipe input handling */
+ if (message.type != PP_VARTYPE_DICTIONARY) {
+ PostMessage("Got unexpected message type: %d\n", message.type);
+ return;
+ }
+
+ struct PP_Var pipe_var = CStrToVar("pipe");
+ struct PP_Var pipe_name = g_ppb_var_dictionary->Get(message, pipe_var);
+ g_ppb_var->Release(pipe_var);
+
+ /* Special case for jspipe input handling */
+ if (pipe_name.type == PP_VARTYPE_STRING) {
+ char file_name[PATH_MAX];
+ snprintf(file_name, PATH_MAX, "/dev/%s", VarToCStr(pipe_name));
+ int fd = open(file_name, O_RDONLY);
+ g_ppb_var->Release(pipe_name);
+ if (fd < 0) {
+ PostMessage("Warning: opening %s failed.", file_name);
+ goto done;
+ }
+ if (ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message) != 0) {
+ PostMessage("Error: ioctl on %s failed: %s", file_name, strerror(errno));
+ }
+ close(fd);
+ goto done;
+ }
+
g_ppb_var->AddRef(message);
if (!EnqueueMessage(message)) {
g_ppb_var->Release(message);
- PostMessageVar(
- PrintfToVar("Warning: dropped message because the queue was full."));
+ PostMessage("Warning: dropped message because the queue was full.");
}
+
+done:
+ g_ppb_var->Release(pipe_name);
}
#define GET_INTERFACE(var, type, name) \
« no previous file with comments | « native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h ('k') | native_client_sdk/src/libraries/nacl_io/devfs/dev_fs.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698