#include "vine-data-path-plugin.h"
+#include "vine-constants.h"
#include "vine-log.h"
#include "vine-utils.h"
#include "vine-queue.h"
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
{ 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);
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;
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)
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 *>;
ws->vh = NULL;
ws->user = NULL;
+ free(ws->token);
+ ws->token = NULL;
+ ws->token_len = 0;
+
delete ws->recv_buffer;
delete ws->write_buffer;
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;
fn->read = websocket_read;
fn->write = websocket_write;
fn->close = websocket_close;
+
+ fn->set_token = websocket_set_token;
+ fn->get_token = websocket_get_token;
}