| 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
|
| deleted file mode 100644
|
| index 226d50f662ea4546ea45f62b2342dca5fb4840fc..0000000000000000000000000000000000000000
|
| --- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
|
| +++ /dev/null
|
| @@ -1,482 +0,0 @@
|
| -/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#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"
|
| -#include "ppapi/c/ppb.h"
|
| -#include "ppapi/c/ppb_instance.h"
|
| -#include "ppapi/c/ppb_messaging.h"
|
| -#include "ppapi/c/ppb_var.h"
|
| -#include "ppapi/c/ppb_var_array.h"
|
| -#include "ppapi/c/ppb_var_dictionary.h"
|
| -#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"
|
| -#include "queue.h"
|
| -
|
| -#if defined(WIN32)
|
| -#define va_copy(d, s) ((d) = (s))
|
| -#endif
|
| -
|
| -typedef struct {
|
| - const char* name;
|
| - HandleFunc function;
|
| -} FuncNameMapping;
|
| -
|
| -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;
|
| -
|
| -static FuncNameMapping g_function_map[] = {
|
| - {"fopen", HandleFopen},
|
| - {"fwrite", HandleFwrite},
|
| - {"fread", HandleFread},
|
| - {"fseek", HandleFseek},
|
| - {"fclose", HandleFclose},
|
| - {"fflush", HandleFflush},
|
| - {"stat", HandleStat},
|
| - {"opendir", HandleOpendir},
|
| - {"readdir", HandleReaddir},
|
| - {"closedir", HandleClosedir},
|
| - {"mkdir", HandleMkdir},
|
| - {"rmdir", HandleRmdir},
|
| - {"chdir", HandleChdir},
|
| - {"getcwd", HandleGetcwd},
|
| - {"getaddrinfo", HandleGetaddrinfo},
|
| - {"gethostbyname", HandleGethostbyname},
|
| - {"connect", HandleConnect},
|
| - {"send", HandleSend},
|
| - {"recv", HandleRecv},
|
| - {"close", HandleClose},
|
| - {NULL, NULL},
|
| -};
|
| -
|
| -/** 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.
|
| - * @param[in] str The string to convert.
|
| - * @return A new PP_Var with the contents of |str|.
|
| - */
|
| -struct PP_Var CStrToVar(const char* str) {
|
| - return g_ppb_var->VarFromUtf8(str, strlen(str));
|
| -}
|
| -
|
| -/**
|
| - * Printf to a newly allocated C string.
|
| - * @param[in] format A printf format string.
|
| - * @param[in] args The printf arguments.
|
| - * @return The newly constructed string. Caller takes ownership. */
|
| -char* VprintfToNewString(const char* format, va_list args) {
|
| - va_list args_copy;
|
| - int length;
|
| - char* buffer;
|
| - int result;
|
| -
|
| - va_copy(args_copy, args);
|
| - length = vsnprintf(NULL, 0, format, args);
|
| - buffer = (char*)malloc(length + 1); /* +1 for NULL-terminator. */
|
| - result = vsnprintf(&buffer[0], length + 1, format, args_copy);
|
| - if (result != length) {
|
| - assert(0);
|
| - return NULL;
|
| - }
|
| - return buffer;
|
| -}
|
| -
|
| -/**
|
| - * Printf to a newly allocated C string.
|
| - * @param[in] format A print format string.
|
| - * @param[in] ... The printf arguments.
|
| - * @return The newly constructed string. Caller takes ownership.
|
| - */
|
| -char* PrintfToNewString(const char* format, ...) {
|
| - va_list args;
|
| - char* result;
|
| - va_start(args, format);
|
| - result = VprintfToNewString(format, args);
|
| - va_end(args);
|
| - return result;
|
| -}
|
| -
|
| -/**
|
| - * Vprintf to a new PP_Var.
|
| - * @param[in] format A print format string.
|
| - * @param[in] va_list The printf arguments.
|
| - * @return A new PP_Var.
|
| - */
|
| -static struct PP_Var VprintfToVar(const char* format, va_list args) {
|
| - struct PP_Var var;
|
| - 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.
|
| - * @param[in] var The PP_Var to convert.
|
| - * @return A newly allocated, NULL-terminated string.
|
| - */
|
| -static const char* VarToCStr(struct PP_Var var) {
|
| - uint32_t length;
|
| - const char* str = g_ppb_var->VarToUtf8(var, &length);
|
| - if (str == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - /* str is NOT NULL-terminated. Copy using memcpy. */
|
| - char* new_str = (char*)malloc(length + 1);
|
| - memcpy(new_str, str, length);
|
| - new_str[length] = 0;
|
| - return new_str;
|
| -}
|
| -
|
| -/**
|
| - * Get a value from a Dictionary, given a string key.
|
| - * @param[in] dict The dictionary to look in.
|
| - * @param[in] key The key to look up.
|
| - * @return PP_Var The value at |key| in the |dict|. If the key doesn't exist,
|
| - * return a PP_Var with the undefined value.
|
| - */
|
| -struct PP_Var GetDictVar(struct PP_Var dict, const char* key) {
|
| - struct PP_Var key_var = CStrToVar(key);
|
| - struct PP_Var value = g_ppb_var_dictionary->Get(dict, key_var);
|
| - g_ppb_var->Release(key_var);
|
| - return value;
|
| -}
|
| -
|
| -/**
|
| - * Post a message to JavaScript.
|
| - * @param[in] format A printf format string.
|
| - * @param[in] ... The printf arguments.
|
| - */
|
| -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);
|
| -}
|
| -
|
| -/**
|
| - * Given a message from JavaScript, parse it for functions and parameters.
|
| - *
|
| - * The format of the message is:
|
| - * {
|
| - * "cmd": <function name>,
|
| - * "args": [<arg0>, <arg1>, ...]
|
| - * }
|
| - *
|
| - * @param[in] message The message to parse.
|
| - * @param[out] out_function The function name.
|
| - * @param[out] out_params A PP_Var array.
|
| - * @return 0 if successful, otherwise 1.
|
| - */
|
| -static int ParseMessage(struct PP_Var message,
|
| - const char** out_function,
|
| - struct PP_Var* out_params) {
|
| - if (message.type != PP_VARTYPE_DICTIONARY) {
|
| - return 1;
|
| - }
|
| -
|
| - struct PP_Var cmd_value = GetDictVar(message, "cmd");
|
| - *out_function = VarToCStr(cmd_value);
|
| - g_ppb_var->Release(cmd_value);
|
| - if (cmd_value.type != PP_VARTYPE_STRING) {
|
| - return 1;
|
| - }
|
| -
|
| - *out_params = GetDictVar(message, "args");
|
| - if (out_params->type != PP_VARTYPE_ARRAY) {
|
| - return 1;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -/**
|
| - * Given a function name, look up its handler function.
|
| - * @param[in] function_name The function name to look up.
|
| - * @return The handler function mapped to |function_name|.
|
| - */
|
| -static HandleFunc GetFunctionByName(const char* function_name) {
|
| - FuncNameMapping* map_iter = g_function_map;
|
| - for (; map_iter->name; ++map_iter) {
|
| - if (strcmp(map_iter->name, function_name) == 0) {
|
| - return map_iter->function;
|
| - }
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -/**
|
| - * Handle as message from JavaScript on the worker thread.
|
| - *
|
| - * @param[in] message The message to parse and handle.
|
| - */
|
| -static void HandleMessage(struct PP_Var message) {
|
| - const char* function_name;
|
| - struct PP_Var params;
|
| - if (ParseMessage(message, &function_name, ¶ms)) {
|
| - PostMessage("Error: Unable to parse message");
|
| - return;
|
| - }
|
| -
|
| - HandleFunc function = GetFunctionByName(function_name);
|
| - if (!function) {
|
| - /* Function name wasn't found. Error. */
|
| - PostMessage("Error: Unknown function \"%s\"", function_name);
|
| - return;
|
| - }
|
| -
|
| - /* Function name was found, call it. */
|
| - struct PP_Var result_var;
|
| - const char* error;
|
| - int result = (*function)(params, &result_var, &error);
|
| - if (result != 0) {
|
| - /* Error. */
|
| - if (error != NULL) {
|
| - PostMessage("Error: \"%s\" failed: %s.", function_name, error);
|
| - free((void*)error);
|
| - } else {
|
| - PostMessage("Error: \"%s\" failed.", function_name);
|
| - }
|
| - return;
|
| - }
|
| -
|
| - /* Function returned an output dictionary. Send it to JavaScript. */
|
| - 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.
|
| - * @return unused.
|
| - */
|
| -void* HandleMessageThread(void* user_data) {
|
| - while (1) {
|
| - struct PP_Var message = DequeueMessage();
|
| - HandleMessage(message);
|
| - g_ppb_var->Release(message);
|
| - }
|
| -}
|
| -
|
| -static PP_Bool Instance_DidCreate(PP_Instance instance,
|
| - uint32_t argc,
|
| - const char* argn[],
|
| - const char* argv[]) {
|
| - g_instance = instance;
|
| - nacl_io_init_ppapi(instance, g_get_browser_interface);
|
| -
|
| - // By default, nacl_io mounts / to pass through to the original NaCl
|
| - // filesystem (which doesn't do much). Let's remount it to a memfs
|
| - // filesystem.
|
| - umount("/");
|
| - mount("", "/", "memfs", 0, "");
|
| -
|
| - mount("", /* source */
|
| - "/persistent", /* target */
|
| - "html5fs", /* filesystemtype */
|
| - 0, /* mountflags */
|
| - "type=PERSISTENT,expected_size=1048576"); /* data */
|
| -
|
| - mount("", /* source. Use relative URL */
|
| - "/http", /* target */
|
| - "httpfs", /* filesystemtype */
|
| - 0, /* mountflags */
|
| - ""); /* data */
|
| -
|
| - pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
|
| - pthread_create(&g_echo_thread, NULL, &EchoThread, NULL);
|
| - InitializeMessageQueue();
|
| -
|
| - return PP_TRUE;
|
| -}
|
| -
|
| -static void Instance_DidDestroy(PP_Instance instance) {
|
| -}
|
| -
|
| -static void Instance_DidChangeView(PP_Instance instance,
|
| - PP_Resource view_resource) {
|
| -}
|
| -
|
| -static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
|
| -}
|
| -
|
| -static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
|
| - PP_Resource url_loader) {
|
| - /* NaCl modules do not need to handle the document load function. */
|
| - return PP_FALSE;
|
| -}
|
| -
|
| -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);
|
| - PostMessage("Warning: dropped message because the queue was full.");
|
| - }
|
| -
|
| -done:
|
| - g_ppb_var->Release(pipe_name);
|
| -}
|
| -
|
| -#define GET_INTERFACE(var, type, name) \
|
| - var = (type*)(get_browser(name)); \
|
| - if (!var) { \
|
| - printf("Unable to get interface " name "\n"); \
|
| - return PP_ERROR_FAILED; \
|
| - }
|
| -
|
| -PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
|
| - PPB_GetInterface get_browser) {
|
| - g_get_browser_interface = get_browser;
|
| - GET_INTERFACE(g_ppb_messaging, PPB_Messaging, PPB_MESSAGING_INTERFACE);
|
| - GET_INTERFACE(g_ppb_var, PPB_Var, PPB_VAR_INTERFACE);
|
| - GET_INTERFACE(g_ppb_var_array, PPB_VarArray, PPB_VAR_ARRAY_INTERFACE);
|
| - GET_INTERFACE(
|
| - g_ppb_var_dictionary, PPB_VarDictionary, PPB_VAR_DICTIONARY_INTERFACE);
|
| - return PP_OK;
|
| -}
|
| -
|
| -PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
|
| - if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
|
| - static PPP_Instance instance_interface = {
|
| - &Instance_DidCreate,
|
| - &Instance_DidDestroy,
|
| - &Instance_DidChangeView,
|
| - &Instance_DidChangeFocus,
|
| - &Instance_HandleDocumentLoad,
|
| - };
|
| - return &instance_interface;
|
| - } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
|
| - static PPP_Messaging messaging_interface = {
|
| - &Messaging_HandleMessage,
|
| - };
|
| - return &messaging_interface;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -PP_EXPORT void PPP_ShutdownModule() {
|
| -}
|
|
|