*
******************************************************************/
+#include <cstring>
+#include <mutex>
+#include <vector>
+
+#include <boost/asio.hpp>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
+
+#include "dcm_support.pb.h"
#include "device_certificate_manager_ext.h"
#include "log.h"
+#include "protobuf_asio.h"
#ifndef API_DEVICE_CERTIFICATE_MANAGER_EXT_EXPORT
#define API_DEVICE_CERTIFICATE_MANAGER_EXT_EXPORT __attribute__((visibility("default")))
#endif
+static std::mutex g_mutex;
+
API_DEVICE_CERTIFICATE_MANAGER_EXT_EXPORT
int dcm_ext_call_api(const char* method_name, const char* input_data, size_t input_len,
- char** output_data, size_t* output_len)
+ char** output_data, size_t* output_len)
{
- (void) method_name;
- (void) input_data;
- (void) input_len;
- (void) output_data;
- (void) output_len;
- LOGE("No implementation yet - TODO");
- return DCM_EXT_ERROR_UNKNOWN;
+ if(!method_name) {
+ LOGE("Invalid input parameters");
+ return DCM_EXT_ERROR_INVALID_PARAMETER;
+ }
+
+ std::lock_guard<std::mutex> locker(g_mutex);
+ std::unique_ptr<boost::asio::local::stream_protocol::socket> socket;
+ boost::asio::io_service ioService;
+
+ try {
+ socket.reset(new boost::asio::local::stream_protocol::socket(ioService));
+ boost::asio::local::stream_protocol::endpoint endpoint(DCM_UNIX_SOCKET_PATH);
+ socket->connect(endpoint);
+ } catch(std::exception& ex) {
+ LOGE("Caught exception \"%s\" when connecting from client-ext library to DCM daemon", ex.what());
+ return DCM_EXT_ERROR_SOCKET;
+ } catch(...) {
+ LOGE("Caught unknown exception when connecting from client-ext library to DCM daemon");
+ return DCM_EXT_ERROR_SOCKET;
+ }
+
+ try {
+ RequestMessage request;
+ ResponseMessage response;
+
+ auto* req = request.mutable_ext_call();
+ req->set_method_name(std::string(method_name));
+
+ if(input_data)
+ req->set_input_data(input_data, input_len);
+
+ protobuf_sync_message_serialization(*socket).encodeMessage(request);
+ protobuf_sync_message_deserialization(*socket).decodeMessage(response);
+
+ if(!response.has_ext_call()) {
+ LOGE("Response for ext-api malformed, exiting");
+ return DCM_EXT_ERROR_UNKNOWN;
+ }
+
+ auto& ext_resp(response.ext_call());
+
+ if(ext_resp.result() != DCM_EXT_ERROR_NONE) {
+ switch(ext_resp.result()) {
+ case DCM_EXT_ERROR_INVALID_PARAMETER:
+ case DCM_EXT_ERROR_OUT_OF_MEMORY:
+ case DCM_EXT_ERROR_PERMISSION_DENIED:
+ case DCM_EXT_ERROR_NOT_SUPPORTED:
+ case DCM_EXT_ERROR_UNKNOWN:
+ case DCM_EXT_ERROR_SOCKET:
+ LOGE("Ext API call received error %d", ext_resp.result());
+ return ext_resp.result();
+ default:
+ LOGE("Ext API call received non-standard error %d", ext_resp.result());
+ return DCM_EXT_ERROR_UNKNOWN;
+ }
+ }
+
+ const auto& out = ext_resp.output_data();
+
+ if(!out.empty()) {
+ if(!output_data || !output_len) {
+ LOGE("Daemon returned response but ext_call API didn't get buffer pointers to return it");
+ socket.reset();
+ return DCM_EXT_ERROR_INVALID_PARAMETER;
+ }
+
+ *output_data = (char*) malloc(sizeof(char) * out.size());
+
+ if(*output_data == NULL) {
+ LOGE("Can't allocate enough memory for response from ext API call - required buffer in bytes: %d", out.size());
+ socket.reset();
+ return DCM_EXT_ERROR_OUT_OF_MEMORY;
+ }
+
+ memcpy(*output_data, out.c_str(), out.size());
+ *output_len = out.size();
+ }
+ } catch(std::exception& ex) {
+ LOGE("Caught exception \"%s\" when connecting from client-ext library to DCM daemon", ex.what());
+ socket.reset();
+ return DCM_EXT_ERROR_SOCKET;
+ } catch(...) {
+ LOGE("Caught unknown exception when connecting from client-ext library to DCM daemon");
+ socket.reset();
+ return DCM_EXT_ERROR_SOCKET;
+ }
+
+ return DCM_EXT_ERROR_NONE;
}