OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2015 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. |
| 5 */ |
| 6 |
| 7 #include "native_client/src/shared/platform/nacl_log.h" |
| 8 #include "native_client/src/shared/srpc/nacl_srpc.h" |
| 9 #include "native_client/src/untrusted/irt/irt_dev.h" |
| 10 #include "native_client/src/untrusted/irt/irt_interfaces.h" |
| 11 |
| 12 #include <argz.h> |
| 13 #include <string.h> |
| 14 |
| 15 static const int kMaxObjectFiles = 16; |
| 16 |
| 17 static const struct nacl_irt_pnacl_compile_funcs *g_funcs; |
| 18 |
| 19 static void stream_init_with_split( |
| 20 NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
| 21 NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
| 22 int num_threads = in_args[0]->u.ival; |
| 23 if (num_threads < 0 || num_threads > kMaxObjectFiles) { |
| 24 NaClLog(LOG_FATAL, "Invalid # of threads (%d)\n", num_threads); |
| 25 } |
| 26 int fd_start = 1; |
| 27 int i = fd_start; |
| 28 int num_valid_fds = 0; |
| 29 int obj_fds[kMaxObjectFiles]; |
| 30 while (num_valid_fds < kMaxObjectFiles && in_args[i]->u.hval >= 0) { |
| 31 obj_fds[num_valid_fds] = in_args[i]->u.hval; |
| 32 ++i; |
| 33 ++num_valid_fds; |
| 34 } |
| 35 /* |
| 36 * Convert the null-delimited strings into an array of |
| 37 * null-terminated strings. |
| 38 */ |
| 39 char *cmd_argz = in_args[kMaxObjectFiles + fd_start]->arrays.carr; |
| 40 size_t cmd_argz_len = in_args[kMaxObjectFiles + fd_start]->u.count; |
| 41 size_t argc = argz_count(cmd_argz, cmd_argz_len); |
| 42 char **argv = (char **)malloc((argc + 1) * sizeof(char *)); |
| 43 argz_extract(cmd_argz, cmd_argz_len, argv); |
| 44 char *result = g_funcs->init_callback(num_threads, obj_fds, num_valid_fds, |
| 45 argv, argc); |
| 46 free(argv); |
| 47 if (result != NULL) { |
| 48 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 49 /* |
| 50 * SRPC wants to free() the string, so just strdup here so that the |
| 51 * init_callback implementation doesn't have to know if the string |
| 52 * comes from malloc or new. On error, we don't care so much |
| 53 * about leaking this bit of memory. |
| 54 */ |
| 55 out_args[0]->arrays.str = strdup(result); |
| 56 } else { |
| 57 rpc->result = NACL_SRPC_RESULT_OK; |
| 58 out_args[0]->arrays.str = strdup(""); |
| 59 } |
| 60 done->Run(done); |
| 61 } |
| 62 |
| 63 static void stream_chunk(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
| 64 NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
| 65 int result = g_funcs->data_callback( |
| 66 in_args[0]->arrays.carr, |
| 67 in_args[0]->u.count); |
| 68 rpc->result = result == 0 ? NACL_SRPC_RESULT_OK : NACL_SRPC_RESULT_APP_ERROR; |
| 69 done->Run(done); |
| 70 } |
| 71 |
| 72 static void stream_end(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
| 73 NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
| 74 char *result = g_funcs->end_callback(); |
| 75 /* Fill in the deprecated return values with dummy values. */ |
| 76 out_args[0]->u.ival = 0; |
| 77 out_args[1]->arrays.str = strdup(""); |
| 78 out_args[2]->arrays.str = strdup(""); |
| 79 if (result != NULL) { |
| 80 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 81 /* SRPC wants to free(), so strdup() and leak to hide this detail. */ |
| 82 out_args[3]->arrays.str = strdup(result); |
| 83 } else { |
| 84 rpc->result = NACL_SRPC_RESULT_OK; |
| 85 out_args[3]->arrays.str = strdup(""); |
| 86 } |
| 87 done->Run(done); |
| 88 } |
| 89 |
| 90 static const struct NaClSrpcHandlerDesc srpc_methods[] = { |
| 91 /* |
| 92 * Protocol for streaming: |
| 93 * StreamInitWithSplit(num_threads, obj_fd x 16, cmdline_flags) -> error_str |
| 94 * StreamChunk(data) + |
| 95 * TODO(jvoung): remove these is_shared_lib, etc. |
| 96 * StreamEnd() -> (is_shared_lib, soname, dependencies, error_str) |
| 97 */ |
| 98 { "StreamInitWithSplit:ihhhhhhhhhhhhhhhhC:s", stream_init_with_split }, |
| 99 { "StreamChunk:C:", stream_chunk }, |
| 100 { "StreamEnd::isss", stream_end }, |
| 101 { NULL, NULL }, |
| 102 }; |
| 103 |
| 104 static void serve_translate_request( |
| 105 const struct nacl_irt_pnacl_compile_funcs *funcs) { |
| 106 g_funcs = funcs; |
| 107 if (!NaClSrpcModuleInit()) { |
| 108 NaClLog(LOG_FATAL, "NaClSrpcModuleInit() failed\n"); |
| 109 } |
| 110 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
| 111 NaClLog(LOG_FATAL, "NaClSrpcAcceptClientConnection() failed\n"); |
| 112 } |
| 113 } |
| 114 |
| 115 const struct nacl_irt_private_pnacl_translator_compile |
| 116 nacl_irt_private_pnacl_translator_compile = { |
| 117 serve_translate_request |
| 118 }; |
OLD | NEW |