/* * Create a service descriptor from an array of methods. */ int NaClSrpcServiceHandlerCtor(NaClSrpcService* service, const NaClSrpcHandlerDesc* handler_desc) { char* service_str; nacl_abi_size_t str_length; NaClSrpcMethodDesc* methods = NULL; uint32_t method_count = 0; /* Initialize the struct, so that failures can be cleaned up properly. */ service->service_string = NULL; service->service_string_length = 0; service->rpc_descr = NULL; service->rpc_count = 0; /* Add the service_discovery method to the table. */ methods = BuildMethods(handler_desc, &method_count); if (NULL == methods) { goto cleanup; } service_str = BuildSDString(methods, method_count, &str_length); if (NULL == service_str) { goto cleanup; } service->service_string = service_str; service->service_string_length = str_length; service->rpc_descr = methods; service->rpc_count = method_count; return 1; cleanup: FreeMethods(methods, method_count); return 0; }
/* * Destroy a service descriptor. */ void NaClSrpcServiceDtor(NaClSrpcService* service) { if (NULL == service) { return; } /* Free the method descriptors. */ FreeMethods((NaClSrpcMethodDesc*) service->rpc_descr, service->rpc_count); /* Free the service discovery string. */ free((char*) service->service_string); }
/* * The method tables passed to construction do not contain "intrinsic" methods * such as service discovery and shutdown. Build a complete table including * those from a given input. */ static NaClSrpcMethodDesc* BuildMethods( const struct NaClSrpcHandlerDesc* methods, uint32_t* method_count) { static const char* kSDDescString = "service_discovery::C"; NaClSrpcMethodDesc* complete_methods = NULL; uint32_t i; const char* nul_loc; /* Compute the number of methods to export. */ *method_count = 0; while (NULL != methods[*method_count].entry_fmt) ++*method_count; /* Add one extra method for service discovery. */ ++*method_count; /* Allocate the method descriptors. One extra for NULL termination. */ complete_methods = (NaClSrpcMethodDesc*) calloc(*method_count + 1, sizeof(*complete_methods)); if (NULL == complete_methods) { return NULL; } /* Copy the methods passed in, adding service discovery as element zero. */ nul_loc = ParseOneEntry(kSDDescString, (char**) &complete_methods[0].name, (char**) &complete_methods[0].input_types, (char**) &complete_methods[0].output_types); if (nul_loc == NULL) { goto cleanup; } complete_methods[0].handler = ServiceDiscovery; for (i = 0; i < *method_count - 1; ++i) { nul_loc = ParseOneEntry(methods[i].entry_fmt, (char**) &complete_methods[i + 1].name, (char**) &complete_methods[i + 1].input_types, (char**) &complete_methods[i + 1].output_types); if (nul_loc == NULL) { goto cleanup; } complete_methods[i + 1].handler = methods[i].handler; } /* Add the NULL terminator */ complete_methods[*method_count].name = NULL; complete_methods[*method_count].input_types = NULL; complete_methods[*method_count].output_types = NULL; complete_methods[*method_count].handler = NULL; /* Return the array */ return complete_methods; cleanup: FreeMethods(complete_methods, *method_count); return NULL; }
int NaClSrpcServiceStringCtor(NaClSrpcService* service, const char* str) { NaClSrpcMethodDesc* methods = NULL; const char* p; uint32_t i; uint32_t rpc_count; size_t rpc_count_size_t; /* Count the number of rpc methods */ rpc_count = 0; for (p = str; *p != '\0'; ) { char* next_p = strchr(p, '\n'); if (NULL == next_p) { /* malformed input -- no remaining \n character was found */ goto cleanup; } p = next_p + 1; ++rpc_count; if (0 == rpc_count) { /* uint32_t overflow detected. */ goto cleanup; } } /* * The front end knows the next comparison is useless due to the range of * uint32_t. And furthermore at least one version of gcc knows that a * cast doesn't really change that fact. Hence, assign to a new variable * of size_t type. */ rpc_count_size_t = (size_t) rpc_count; /* Allocate and clear the descriptor array */ if (rpc_count_size_t >= SIZE_T_MAX / sizeof(*methods)) { goto cleanup; } methods = (NaClSrpcMethodDesc*) malloc(rpc_count_size_t * sizeof(*methods)); if (NULL == methods) { goto cleanup; } memset(methods, 0, rpc_count_size_t * sizeof(*methods)); /* Parse the list of method descriptions */ p = str; for (i = 0; i < rpc_count; ++i) { const char* newline_loc; newline_loc = ParseOneEntry(p, (char**) &methods[i].name, (char**) &methods[i].input_types, (char**) &methods[i].output_types); if (NULL == newline_loc || '\n' != *newline_loc) { goto cleanup; } p = newline_loc + 1; /* The handler is not set from service_discovery strings */ methods[i].handler = NULL; } service->service_string = strdup(str); service->service_string_length = nacl_abi_size_t_saturate(strlen(str)); service->rpc_descr = methods; service->rpc_count = rpc_count; return 1; cleanup: FreeMethods(methods, rpc_count); return 0; }