Add set/get_token plugin API 02/257002/4
authorSeonah Moon <seonah1.moon@samsung.com>
Fri, 16 Apr 2021 08:08:43 +0000 (17:08 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Tue, 20 Apr 2021 04:13:07 +0000 (13:13 +0900)
Change-Id: Ic0ffb001c9d20be9dba35ea11cc0597782d3883c

plugins/libwebsockets/libwebsockets-plugin.cpp
src/include/vine-data-path-plugin.h
src/include/vine-data-path.h
src/vine-data-path.cpp

index 99cacd72730dddb83d560595efaa646d51bf06bf..1e6ad622261e934219dc62b63ebecb8bcb5c0135 100755 (executable)
@@ -27,6 +27,7 @@
 
 #include "vine-data-path-plugin.h"
 
+#include "vine-constants.h"
 #include "vine-log.h"
 #include "vine-utils.h"
 #include "vine-queue.h"
@@ -50,6 +51,10 @@ typedef struct {
        bool close_requested;
        int curr_conn;
        int max_conn;
+
+       unsigned char *token;
+       int token_len;
+
        VineQueue<websocket_data_s *> *recv_buffer;
        VineQueue<websocket_data_s *> *write_buffer;
        void *user; // vine_data_path_h
@@ -97,6 +102,9 @@ static struct lws_protocols protocols[] = {
        { NULL, NULL, 0, 0 } /* terminator */
 };
 
+#define VINE_SERVICE_NAME_HEADER "vine-service-name:"
+#define VINE_SERVICE_NAME_HEADER_LEN 18
+
 static void websocket_process_event(int fd, int events);
 static void _connect_server(websocket_s *ws,
                int addr_family, const char *ip, int port, const char *iface_name, vine_dp_ssl ssl);
@@ -353,18 +361,52 @@ static int _websocket_protocol_cb(struct lws *wsi,
                break;
 
        /* --- serving callbacks --- */
-       case LWS_CALLBACK_ESTABLISHED: {
-               VINE_LOGI("Websocket connection is established.");
-               // When client is connected, ws(wsi->user_space) is automatically allocated by lws.
+       case LWS_CALLBACK_HTTP_CONFIRM_UPGRADE: {
+               //In LWS_CALLBACK_ESTABLISHED, ws(wsi->user_space) is automatically allocated by lws.
                // So lws has the ownership of a user data.
-               // Reset a user data to own the memory.
+               // Set a user data before lws allocates the memory to own the memory.
+               // If user_space is already exist, lws doesn't assign it.
                websocket_s *client_ws = (websocket_s *)calloc(1, sizeof(websocket_s));
                if (!client_ws)
-                       return 0;
+                       return -1;
+
                client_ws->wsi = wsi;
                lws_set_wsi_user(wsi, client_ws);
-               vhd->curr_conn++;
 
+               client_ws->token_len = lws_hdr_custom_length(wsi, VINE_SERVICE_NAME_HEADER,
+                               strlen(VINE_SERVICE_NAME_HEADER));
+               if (client_ws->token_len < 0) {
+                       VINE_LOGI("Cannot find %s header.", VINE_SERVICE_NAME_HEADER);
+                       return 0;
+               }
+
+               char *service_name = (char *)calloc(client_ws->token_len + 1,
+                               sizeof(char));
+               if (!service_name) {
+                       lws_set_wsi_user(wsi, NULL);
+                       free(client_ws);
+                       return -1;
+               }
+
+               if (lws_hdr_custom_copy(wsi, service_name, sizeof(service_name),
+                               VINE_SERVICE_NAME_HEADER, strlen(VINE_SERVICE_NAME_HEADER)) < 0) {
+                       VINE_LOGE("Failed to get custom header.");
+                       free(service_name);
+                       lws_set_wsi_user(wsi, NULL);
+                       free(client_ws);
+                       return -1;
+               }
+
+               client_ws->token = (unsigned char *)service_name;
+               VINE_LOGE("Peer service name[%s]", client_ws->token);
+               break;
+       }
+
+       case LWS_CALLBACK_ESTABLISHED: {
+               VINE_LOGI("Websocket connection is established.");
+
+               websocket_s *client_ws = (websocket_s *)lws_wsi_user(wsi);
+               vhd->curr_conn++;
                if (g_callbacks.accepted_cb) {
                        char ip[INET6_ADDRSTRLEN];
                        int port;
@@ -421,6 +463,21 @@ static int _websocket_protocol_cb(struct lws *wsi,
                        g_callbacks.connected_cb(-1, ws->user);
                break;
 
+       case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: {
+               if (!ws || !ws->token)
+                       return 0;
+
+               VINE_LOGI("Add custom header.");
+               unsigned char **p = (unsigned char **) in, *end = (*p) + len;
+               unsigned char hdr[VINE_SERVICE_NAME_HEADER_LEN + 1] = {0, };
+               memcpy(hdr, VINE_SERVICE_NAME_HEADER, VINE_SERVICE_NAME_HEADER_LEN);
+               if (lws_add_http_header_by_name(wsi, hdr, ws->token, ws->token_len, p, end) < 0) {
+                       VINE_LOGE("Failed to add custom header.");
+                       return -1;
+               }
+               break;
+       }
+
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
                VINE_LOGI("Connected with server.");
                if (ws && g_callbacks.connected_cb)
@@ -822,6 +879,8 @@ static int websocket_create(vine_dp_plugin_h *handle, void *plugin_data, void *u
        ws->close_requested = false;
        ws->curr_conn = 0;
        ws->max_conn = 0;
+       ws->token = NULL;
+       ws->token_len = 0;
        ws->user = user;
        ws->recv_buffer = new VineQueue<websocket_data_s *>;
        ws->write_buffer = new VineQueue<websocket_data_s *>;
@@ -840,6 +899,10 @@ static int websocket_destroy(vine_dp_plugin_h handle)
        ws->vh = NULL;
        ws->user = NULL;
 
+       free(ws->token);
+       ws->token = NULL;
+       ws->token_len = 0;
+
        delete ws->recv_buffer;
        delete ws->write_buffer;
 
@@ -856,6 +919,36 @@ static void websocket_register_callbacks(vine_dp_plugin_callbacks callbacks)
        g_callbacks = callbacks;
 }
 
+static int websocket_set_token(vine_dp_plugin_h handle, const char *token)
+{
+       RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL");
+
+       websocket_s *ws = (websocket_s *)handle;
+       int len = strlen(token);
+       if (len < 0)
+               return -1;
+
+       ws->token_len = len;
+       ws->token = (unsigned char *)calloc(len, sizeof(unsigned char));
+       memcpy(ws->token, token, ws->token_len);
+       return VINE_DATA_PATH_ERROR_NONE;
+}
+
+static int websocket_get_token(vine_dp_plugin_h handle, char **token)
+{
+       RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL");
+
+       websocket_s *ws = (websocket_s *)handle;
+       if (!ws->token || ws->token_len <= 0) {
+               *token = NULL;
+               return VINE_DATA_PATH_ERROR_INVALID_OPERATION;
+       }
+
+       *token = (char *)calloc(ws->token_len, sizeof(char));
+       memcpy(*token, ws->token, ws->token_len);
+       return VINE_DATA_PATH_ERROR_NONE;
+}
+
 void vine_data_path_plugin_init(vine_dp_plugin_fn *fn)
 {
        fn->init = websocket_init;
@@ -870,4 +963,7 @@ void vine_data_path_plugin_init(vine_dp_plugin_fn *fn)
        fn->read = websocket_read;
        fn->write = websocket_write;
        fn->close = websocket_close;
+
+       fn->set_token = websocket_set_token;
+       fn->get_token = websocket_get_token;
 }
index dea2fb64a8ef62a2ef9b8a8a292f21ac3ff71902..87d7496405f129bcbf3655a73a73802786b45f39 100755 (executable)
@@ -100,6 +100,13 @@ typedef struct {
        int (*read)(vine_dp_plugin_h handle, unsigned char *buf, size_t len);
        int (*write)(vine_dp_plugin_h handle, unsigned char *buf, size_t len);
        int (*close)(vine_dp_plugin_h handle);
+
+       // The token means an additional information which is used during connection establishing.
+       // The way to send it can be different based on a plugin.
+       // In case of libwebsockets, send it through a HTTP custom header.
+       // DPPubSub uses it to inform own service name to a peer.
+       int (*set_token)(vine_dp_plugin_h handle, const char *token);
+       int (*get_token)(vine_dp_plugin_h handle, char **token);
 } vine_dp_plugin_fn;
 
 extern "C" void vine_data_path_plugin_init(vine_dp_plugin_fn *fn);
index b2b9f1cf6243a311d54b5146b00ffec17ff86ddb..e622aad68c3c8d1f034bf7c1e252059aa9763995 100755 (executable)
@@ -65,6 +65,7 @@ int vine_data_path_connect(vine_address_family_e addr_family,
                vine_event_queue_h event_fd);
 int vine_data_path_set_terminated_cb(vine_data_path_h datapath,
                vine_data_path_terminated_cb callback, void *user_data);
+int vine_data_path_get_token(vine_data_path_h datapath, char **token);
 
 vine_security_h _vine_dp_get_security(vine_data_path_h datapath);
 
index dff898aec388d7bde875beee5c3b40384555e05c..25a62ae93af14db95f9ccbf241a033f4161bf470 100755 (executable)
@@ -722,6 +722,16 @@ int vine_data_path_set_terminated_cb(vine_data_path_h datapath,
        return VINE_ERROR_NONE;
 }
 
+int vine_data_path_get_token(vine_data_path_h datapath, char **token)
+{
+       RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
+       RET_VAL_IF(token == NULL, VINE_ERROR_INVALID_PARAMETER, "token is NULL");
+
+       vine_data_path_s *dp = (vine_data_path_s *)datapath;
+       int ret = g_dp_plugin_fn.get_token(dp->plugin_handle, token);
+       return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
+}
+
 vine_security_h _vine_dp_get_security(vine_data_path_h datapath)
 {
        RET_VAL_IF(datapath == NULL, NULL, "datapath is NULL");