Index: tests/nameservice/srpc_nameservice_test.c |
=================================================================== |
--- tests/nameservice/srpc_nameservice_test.c (revision 0) |
+++ tests/nameservice/srpc_nameservice_test.c (revision 0) |
@@ -0,0 +1,292 @@ |
+/* |
+ * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+/* |
+ * Test for simple rpc based access to name services. |
+ */ |
+ |
+#include <assert.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <inttypes.h> |
+#include <sys/fcntl.h> |
+#include <string.h> |
+#include <unistd.h> |
+#include <sys/nacl_syscalls.h> |
+#include <nacl/nacl_srpc.h> |
+#if 0 /* swap after SDK update */ |
+#include <sys/nacl_name_service.h> |
+#else |
+#include "native_client/src/trusted/service_runtime/include/sys/nacl_name_service.h" |
+#endif |
+#include <nacl/nacl_srpc.h> |
+ |
+#define RNG_OUTPUT_BYTES 1024 |
+ |
+#define BYTES_PER_LINE 32 |
+#define BYTE_SPACING 4 |
+ |
+struct StringBuffer { |
+ size_t nbytes; |
+ size_t insert; |
+ char *buffer; |
+}; |
+ |
+NaClSrpcChannel ns_channel; |
+ |
+void StringBufferCtor(struct StringBuffer *sb) { |
+ sb->nbytes = 1024; |
+ sb->insert = 0; |
+ sb->buffer = malloc(sb->nbytes); |
+ if (NULL == sb->buffer) { |
+ perror("StringBufferInit::malloc"); |
+ abort(); |
+ } |
+ sb->buffer[0] = '\0'; |
+} |
+ |
+void StringBufferDiscardOutput(struct StringBuffer *sb) { |
+ sb->insert = 0; |
+} |
+ |
+void StringBufferDtor(struct StringBuffer *sb) { |
+ sb->nbytes = 0; |
+ sb->insert = 0; |
+ free(sb->buffer); |
+ sb->buffer = NULL; |
+} |
+ |
+void StringBufferPrintf(struct StringBuffer *sb, |
+ char const *fmt, ...) |
+ __attribute__((format(printf, 2, 3))); |
+ |
+void StringBufferPrintf(struct StringBuffer *sb, |
+ char const *fmt, ...) { |
+ size_t space; |
+ char *insert_pt; |
+ va_list ap; |
+ int written = 0; |
+ char *new_buffer; |
+ |
+ va_start(ap, fmt); |
+ vfprintf(stderr, fmt, ap); |
+ va_end(ap); |
+ |
+ for (;;) { |
+ space = sb->nbytes - sb->insert; |
+ insert_pt = sb->buffer + sb->insert; |
+ va_start(ap, fmt); |
+ written = vsnprintf(insert_pt, space, fmt, ap); |
+ va_end(ap); |
+ if (written < space) { |
+ sb->insert += written; |
+ break; |
+ } |
+ /* insufficient space -- grow the buffer */ |
+ new_buffer = realloc(sb->buffer, 2 * sb->nbytes); |
+ if (NULL == new_buffer) { |
+ /* give up */ |
+ fprintf(stderr, "StringBufferPrintf: no memory\n"); |
+ break; |
+ } |
+ sb->nbytes *= 2; |
+ sb->buffer = new_buffer; |
+ } |
+} |
+ |
+void dump_output(struct StringBuffer *sb, int d, size_t nbytes) { |
+ uint8_t *bytes; |
+ int got; |
+ int copied; |
+ int ix; |
+ |
+ bytes = malloc(nbytes); |
+ if (!bytes) { |
+ perror("dump_output"); |
+ fprintf(stderr, "No memory\n"); |
+ return; |
+ } |
+ /* read output */ |
+ for (got = 0; got < nbytes; got += copied) { |
+ copied = read(d, bytes + got, nbytes - got); |
+ if (-1 == copied) { |
+ perror("dump_output:read"); |
+ fprintf(stderr, "read failure\n"); |
+ break; |
+ } |
+ printf("read(%d, ..., %zd) -> %d\n", d, nbytes - got, copied); |
+ } |
+ /* hex dump it */ |
+ for (ix = 0; ix < got; ++ix) { |
+ if (0 == (ix & (BYTES_PER_LINE-1))) { |
+ StringBufferPrintf(sb, "\n%04x:", ix); |
+ } else if (0 == (ix & (BYTE_SPACING-1))) { |
+ StringBufferPrintf(sb, " "); |
+ } |
+ StringBufferPrintf(sb, "%02x", bytes[ix]); |
+ } |
+ StringBufferPrintf(sb, "\n"); |
+ |
+ free(bytes); |
+} |
+ |
+int EnumerateNames(struct StringBuffer *sb, NaClSrpcChannel *nschan) { |
+ char buffer[1024]; |
+ uint32_t nbytes = sizeof buffer; |
+ char *p; |
+ size_t name_len; |
+ |
+ if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan, |
+ NACL_NAME_SERVICE_LIST, |
+ &nbytes, buffer)) { |
+ return 0; |
+ } |
+ StringBufferPrintf(sb, "nbytes = %zu\n", (size_t) nbytes); |
+ if (nbytes == sizeof buffer) { |
+ fprintf(stderr, "Insufficent space for namespace enumeration\n"); |
+ return 0; |
+ } |
+ for (p = buffer; p - buffer < nbytes; p += name_len) { |
+ name_len = strlen(p) + 1; |
+ StringBufferPrintf(sb, "%s\n", p); |
+ } |
+ return 1; |
+} |
+ |
+/* |
+ * Return name service output |
+ */ |
+void NameServiceDump(NaClSrpcRpc *rpc, |
+ NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, |
+ NaClSrpcClosure *done) { |
+ struct StringBuffer sb; |
+ StringBufferCtor(&sb); |
+ |
+ if (EnumerateNames(&sb, &ns_channel)) { |
+ out_args[0]->arrays.str = strdup(sb.buffer); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ } else { |
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
+ } |
+ done->Run(done); |
+ StringBufferDtor(&sb); |
+} |
+ |
+/* |
+ * Dump RNG output into a string. |
+ */ |
+void RngDump(NaClSrpcRpc *rpc, |
+ NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, |
+ NaClSrpcClosure *done) { |
+ struct StringBuffer sb; |
+ NaClSrpcError rpc_result; |
+ int status; |
+ int rng; |
+ |
+ StringBufferCtor(&sb); |
+ rpc_result = NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, |
+ "SecureRandom", O_RDONLY, |
+ &status, &rng); |
+ assert(NACL_SRPC_RESULT_OK == rpc_result); |
+ printf("rpc status %d\n", status); |
+ assert(NACL_NAME_SERVICE_SUCCESS == status); |
+ printf("rng descriptor %d\n", rng); |
+ |
+ dump_output(&sb, rng, RNG_OUTPUT_BYTES); |
+ out_args[0]->arrays.str = strdup(sb.buffer); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ done->Run(done); |
+ close(rng); |
+ StringBufferDtor(&sb); |
+} |
+ |
+void ManifestTest(NaClSrpcRpc *rpc, |
+ NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, |
+ NaClSrpcClosure *done) { |
+ struct StringBuffer sb; |
+ int status; |
+ int manifest; |
+ char buffer[1024]; |
+ uint32_t nbytes = sizeof buffer; |
+ |
+ /* just get the descriptor for now */ |
+ StringBufferCtor(&sb); |
+ if (NACL_SRPC_RESULT_OK != |
+ NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, |
+ "manifest_proxy", O_RDWR, &status, &manifest)) { |
+ fprintf(stderr, "nameservice lookup failed, status %d\n", status); |
+ } |
+ StringBufferPrintf(&sb, "Got manifest descriptor %d\n", manifest); |
+ if (-1 != manifest) { |
+ /* connect to manifest name server */ |
+ int manifest_conn; |
+ struct NaClSrpcChannel manifest_channel; |
+ |
+ manifest_conn = imc_connect(manifest); |
+ StringBufferPrintf(&sb, "got manifest connection %d\n", manifest_conn); |
+ if (-1 == manifest_conn) { |
+ StringBufferPrintf(&sb, "could not connect\n"); |
+ goto done; |
+ } |
+ close(manifest); |
+ if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) { |
+ StringBufferPrintf(&sb, "could not build srpc client\n"); |
+ goto done; |
+ } |
+ if (NACL_SRPC_RESULT_OK != |
+ NaClSrpcInvokeBySignature(&manifest_channel, NACL_NAME_SERVICE_LIST, |
+ &nbytes, buffer)) { |
+ StringBufferPrintf(&sb, "manifest list failed\n"); |
+ goto done; |
+ } |
+ StringBufferDiscardOutput(&sb); |
+ StringBufferPrintf(&sb, "ManifestList: %.*s\n", (int) nbytes, buffer); |
+ } |
+ done: |
+ out_args[0]->arrays.str = strdup(sb.buffer); |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ done->Run(done); |
+ StringBufferDtor(&sb); |
+} |
+ |
+const struct NaClSrpcHandlerDesc srpc_methods[] = { |
+ /* Export the methods as taking no arguments and returning a string. */ |
+ { "namedump::s", NameServiceDump }, |
+ { "rngdump::s", RngDump }, |
+ { "manifest_test::s", ManifestTest }, |
+ { NULL, NULL }, |
+}; |
+ |
+int main() { |
+ int ns; |
+ int connected_socket; |
+ |
+ if (!NaClSrpcModuleInit()) { |
+ return 1; |
+ } |
+ ns = -1; |
+ nacl_nameservice(&ns); |
+ printf("ns = %d\n", ns); |
+ assert(-1 != ns); |
+ |
+ connected_socket = imc_connect(ns); |
+ assert(-1 != connected_socket); |
+ if (!NaClSrpcClientCtor(&ns_channel, connected_socket)) { |
+ fprintf(stderr, "Srpc client channel ctor failed\n"); |
+ return 1; |
+ } |
+ printf("NaClSrpcClientCtor succeeded\n"); |
+ close(ns); |
+ |
+ if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
+ return 1; |
+ } |
+ NaClSrpcModuleFini(); |
+ return 0; |
+} |
Property changes on: tests/nameservice/srpc_nameservice_test.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |