struct lws_vhost *vh;
bool is_server;
bool close_requested;
+ bool destroy_requested;
int curr_conn;
int max_conn;
WEBSOCKET_OP_CONNECT,
WEBSOCKET_OP_WRITE,
WEBSOCKET_OP_TERMINATE,
+ WEBSOCKET_OP_DESTROY,
} websocket_op_code_e;
typedef struct {
websocket_op_code_e code;
websocket_s *ws;
+ struct lws_vhost *vh;
int addr_family;
char *ip; // connect only
int port; // open, connect only
}
static int _add_websocket_op_request(websocket_op_code_e code,
- websocket_s *ws, int addr_family,
+ websocket_s *ws, struct lws_vhost *vh, int addr_family,
const char *ip, int port, const char *iface_name,
- int max_conn,
- vine_dp_ssl *ssl)
+ int max_conn, vine_dp_ssl *ssl)
{
websocket_op_s *op = (websocket_op_s *)calloc(1, sizeof(websocket_op_s));
if (!op)
op->code = code;
op->ws = ws;
+ op->vh = vh;
op->addr_family = addr_family;
op->ip = STRDUP(ip);
op->port = port;
free(op);
}
-static void _process_pending_destroy(void)
+static void _process_pending_destroy(struct lws_vhost *vh)
{
VINE_LOGD("Process pending destroy");
+ if (!vh)
+ return;
+
+ const struct lws_protocols *protocol = lws_vhost_name_to_protocol(vh,
+ VINE_PROTOCOL_NAME);
+ if (!protocol)
+ return;
+
+ lws_callback_all_protocol_vhost_args(vh, protocol, LWS_CALLBACK_USER, NULL, 0);
+ listen_vh_list.erase(vh);
+ lws_vhost_destroy(vh);
+ VINE_LOGI("vh[%p] is destroyed", vh);
+
while (!lws_service_adjust_timeout(g_context, 1, 0))
lws_service_tsi(g_context, -1, 0);
}
+
+static void _destroy_websocket(websocket_s *ws)
+{
+ if (!ws)
+ return;
+
+ VINE_LOGD("ws[%s] is destroyed.", ws);
+
+ ws->wsi = NULL;
+ ws->vh = NULL;
+ ws->user = NULL;
+
+ free(ws->host_name);
+ ws->host_name = NULL;
+ free(ws->token);
+ ws->token = NULL;
+ ws->token_len = 0;
+
+ delete ws->recv_buffer;
+ delete ws->write_buffer;
+
+ ws->recv_buffer = NULL;
+ ws->write_buffer = NULL;
+
+ free(ws);
+}
+
static void _process_websocket_op_request(void)
{
RET_IF(op_queue.empty(), "operation queue is NULL");
_request_write(op->ws);
break;
case WEBSOCKET_OP_TERMINATE:
- _process_pending_destroy();
+ _process_pending_destroy(op->vh);
+ break;
+ case WEBSOCKET_OP_DESTROY:
+ _destroy_websocket(op->ws);
break;
default:
break;
/* --- client callbacks --- */
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
VINE_LOGI("Failed connection request to server.");
- if (ws && g_callbacks.connected_cb)
+ if (ws && !ws->destroy_requested && g_callbacks.connected_cb)
_invoke_connected_cb(wsi, false, ws->user);
break;
case LWS_CALLBACK_CLIENT_ESTABLISHED:
VINE_LOGI("Connected with server.");
- if (ws && g_callbacks.connected_cb)
+ if (ws && !ws->destroy_requested && g_callbacks.connected_cb)
_invoke_connected_cb(wsi, true, ws->user);
break;
size_t total_len = _save_data(ws, in, len,
lws_is_first_fragment(wsi),
lws_is_final_fragment(wsi));
- if (lws_is_final_fragment(wsi) && g_callbacks.received_cb)
+ if (lws_is_final_fragment(wsi)
+ && !ws->destroy_requested && g_callbacks.received_cb)
g_callbacks.received_cb(total_len, ws->user);
break;
}
return -1;
}
+ if (ws->destroy_requested) {
+ VINE_LOGI("ws[%p] will be destroyed.", ws);
+ return -1;
+ }
+
VINE_LOGI("Writeable to server.");
n = _write_data(ws);
if (g_callbacks.written_cb)
case LWS_CALLBACK_CLIENT_CLOSED:
VINE_LOGI("Connected server is closed.");
// call terminated_cb() when close isn't requested only.
- if (ws && !ws->close_requested && g_callbacks.terminated_cb)
+ if (ws && !ws->close_requested
+ && !ws->destroy_requested && g_callbacks.terminated_cb)
g_callbacks.terminated_cb(ws->user);
break;
return;
}
- //listen_vh_list.insert((void *)ws->vh);
listen_vh_list.insert(ws->vh);
void *user_data = lws_protocol_vh_priv_zalloc(ws->vh, protocols, sizeof(websocket_s));
ws->is_server = true;
VINE_LOGD("ws[%p]", ws);
if (_add_websocket_op_request(WEBSOCKET_OP_OPEN,
- (websocket_s *)handle, addr_family, NULL, port, iface_name, max_conn, &ssl) < 0)
+ (websocket_s *)handle, NULL,
+ addr_family, NULL, port, iface_name, max_conn, &ssl) < 0)
return VINE_DATA_PATH_ERROR_OPERATION_FAILED;
_notify_websocket_op_request();
RET_VAL_IF(!g_context, VINE_DATA_PATH_ERROR_INVALID_OPERATION, "g_context is NULL");
if (_add_websocket_op_request(WEBSOCKET_OP_CONNECT,
- (websocket_s *)handle, addr_family, ip, port, iface_name, 0, &ssl) < 0)
+ (websocket_s *)handle, NULL,
+ addr_family, ip, port, iface_name, 0, &ssl) < 0)
return VINE_DATA_PATH_ERROR_OPERATION_FAILED;
_notify_websocket_op_request();
ws->write_buffer->push(wd);
VINE_LOGD("websocket_data[%p] is pushed to write_buffer. len[%d]", wd, len);
- if (_add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, 0, NULL, -1, NULL, 0, NULL) < 0)
+ if (_add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, NULL,
+ 0, NULL, -1, NULL, 0, NULL) < 0)
return VINE_DATA_PATH_ERROR_OPERATION_FAILED;
_notify_websocket_op_request();
RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "plugin handle is NULL");
websocket_s *ws = (websocket_s *)handle;
+ if (ws->close_requested) {
+ VINE_LOGI("Already requested.");
+ return VINE_DATA_PATH_ERROR_NONE;
+ }
+
+ VINE_LOGD("ws[%p] will be closed.", ws);
ws->close_requested = true;
if (ws->is_server) {
- const struct lws_protocols *protocol = lws_vhost_name_to_protocol(ws->vh,
- VINE_PROTOCOL_NAME);
- if (!protocol)
- return VINE_DATA_PATH_ERROR_OPERATION_FAILED;
-
- lws_callback_all_protocol_vhost_args(ws->vh, protocol, LWS_CALLBACK_USER, NULL, 0);
- listen_vh_list.erase(ws->vh);
- lws_vhost_destroy(ws->vh);
- ws->vh = NULL;
-
_add_websocket_op_request(WEBSOCKET_OP_TERMINATE,
- ws, 0, NULL, 0, NULL, 0, NULL);
+ ws, ws->vh, 0, NULL, 0, NULL, 0, NULL);
_notify_websocket_op_request();
-
return VINE_DATA_PATH_ERROR_NONE;
}
(websocket_s *)plugin_data : (websocket_s *)calloc(1, sizeof(websocket_s));
RET_VAL_IF(ws == NULL, VINE_DATA_PATH_ERROR_OUT_OF_MEMORY, "Out of memory");
- VINE_LOGD("ws[%p], user[%p]", ws, user);
-
ws->close_requested = false;
ws->curr_conn = 0;
ws->max_conn = 0;
{
RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL");
- VINE_LOGE("ws[%p] is destroyed", handle);
- websocket_s *ws = (websocket_s *)handle;
-
- ws->wsi = NULL;
- ws->vh = NULL;
- ws->user = NULL;
- free(ws->host_name);
- ws->host_name = NULL;
- free(ws->token);
- ws->token = NULL;
- ws->token_len = 0;
-
- delete ws->recv_buffer;
- delete ws->write_buffer;
-
- ws->recv_buffer = NULL;
- ws->write_buffer = NULL;
-
- free(ws);
+ websocket_s *ws = (websocket_s *)handle;
+ if (ws->destroy_requested) {
+ VINE_LOGD("Already requested.");
+ return VINE_DATA_PATH_ERROR_NONE;
+ }
+ ws->destroy_requested = true;
+ _add_websocket_op_request(WEBSOCKET_OP_DESTROY, ws, NULL, 0, NULL, 0, NULL, 0, NULL);
+ _notify_websocket_op_request();
return VINE_DATA_PATH_ERROR_NONE;
}