static int wslay_event_context_init (wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks, void *user_data) { int i, r; struct wslay_frame_callbacks frame_callbacks = { wslay_event_frame_send_callback, wslay_event_frame_recv_callback, wslay_event_frame_genmask_callback }; *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context)); if(!*ctx) { return WSLAY_ERR_NOMEM; } memset(*ctx, 0, sizeof(struct wslay_event_context)); wslay_event_config_set_callbacks(*ctx, callbacks); (*ctx)->user_data = user_data; (*ctx)->frame_user_data.ctx = *ctx; (*ctx)->frame_user_data.user_data = user_data; if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, &(*ctx)->frame_user_data)) != 0) { wslay_event_context_free(*ctx); return r; } (*ctx)->read_enabled = (*ctx)->write_enabled = 1; (*ctx)->send_queue = wslay_queue_new(); if(!(*ctx)->send_queue) { wslay_event_context_free(*ctx); return WSLAY_ERR_NOMEM; } (*ctx)->send_ctrl_queue = wslay_queue_new(); if(!(*ctx)->send_ctrl_queue) { wslay_event_context_free(*ctx); return WSLAY_ERR_NOMEM; } (*ctx)->queued_msg_count = 0; (*ctx)->queued_msg_length = 0; for(i = 0; i < 2; ++i) { wslay_event_imsg_reset(&(*ctx)->imsgs[i]); (*ctx)->imsgs[i].chunks = wslay_queue_new(); if(!(*ctx)->imsgs[i].chunks) { wslay_event_context_free(*ctx); return WSLAY_ERR_NOMEM; } } (*ctx)->imsg = &(*ctx)->imsgs[0]; (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf; (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE; (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE; (*ctx)->max_recv_msg_length = (1u << 31)-1; return 0; }
websocket_return_t websocket_queue_close(websocket_t *websocket, const char *close_message) { int r = WEBSOCKET_SUCCESS; if (websocket == NULL) { WEBSOCKET_DEBUG("NULL parameter\n"); return WEBSOCKET_ALLOCATION_ERROR; } if (close_message == NULL) { close_message = "\0"; } if (websocket->ctx != NULL && websocket->state != WEBSOCKET_STOP) { if (wslay_event_queue_close(websocket->ctx, 1000, (const uint8_t *)close_message, strlen(close_message)) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to queue close message\n"); r = WEBSOCKET_SEND_ERROR; goto EXIT_QUEUE_CLOSE; } websocket_wait_state(websocket, WEBSOCKET_STOP, 100000); WEBSOCKET_DEBUG("websocket handler successfully stopped, closing\n"); } EXIT_QUEUE_CLOSE: WEBSOCKET_CLOSE(websocket->fd); if (websocket->ctx) { wslay_event_context_free(websocket->ctx); websocket->ctx = NULL; } websocket_update_state(websocket, WEBSOCKET_STOP); return r; }
void dslink_handshake_handle_ws(DSLink *link) { struct wslay_event_callbacks callbacks = { want_read_cb, want_write_cb, gen_mask_cb, NULL, NULL, NULL, recv_frame_cb }; wslay_event_context_ptr ptr; if (wslay_event_context_client_init(&ptr, &callbacks, link) != 0) { return; } link->_ws = ptr; dslink_event_loop_init(&link->loop, io_handler, link); dslink_event_loop_sched(&link->loop, ping_handler, link); dslink_event_loop_process(&link->loop); dslink_event_loop_free(&link->loop); wslay_event_context_free(ptr); link->_ws = NULL; }
void h2o_websocket_close(h2o_websocket_conn_t *conn) { if (conn->sock != NULL) h2o_socket_close(conn->sock); free_write_buf(conn); wslay_event_context_free(conn->ws_ctx); free(conn); }
/* * if websocket server is initiated from http(s), you just can call this function. * see the comment of websocket_server_open to know what is different. */ websocket_return_t websocket_server_init(websocket_t *server) { int r = WEBSOCKET_SUCCESS; struct websocket_info_t *socket_data = NULL; if (server == NULL) { WEBSOCKET_DEBUG("NULL parameter\n"); return WEBSOCKET_ALLOCATION_ERROR; } socket_data = calloc(1, sizeof(struct websocket_info_t)); if (socket_data == NULL) { WEBSOCKET_DEBUG("fail to allocate memory\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_SERVER_INIT; } socket_data->data = server; if (wslay_event_context_server_init(&(server->ctx), server->cb, socket_data) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to initiate websocket server\n"); r = WEBSOCKET_INIT_ERROR; goto EXIT_SERVER_INIT; } if (websocket_config_socket(server->fd) != WEBSOCKET_SUCCESS) { r = WEBSOCKET_SOCKET_ERROR; goto EXIT_SERVER_INIT; } WEBSOCKET_DEBUG("start websocket server handling loop\n"); r = websocket_handler(server); EXIT_SERVER_INIT: WEBSOCKET_CLOSE(server->fd); if (server->ctx) { wslay_event_context_free(server->ctx); server->ctx = NULL; } if (server->tls_enabled) { mbedtls_net_free(&(server->tls_net)); mbedtls_ssl_free(server->tls_ssl); WEBSOCKET_FREE(server->tls_ssl); } websocket_update_state(server, WEBSOCKET_STOP); return r; }
HIDDEN void ws_end_channel(void *ws_ctx) { struct ws_context *ctx = (struct ws_context *) ws_ctx; if (!ctx) return; wslay_event_context_free(ctx->event); buf_free(&ctx->log); if (ctx->cb_rock) ctx->data_cb(NULL, NULL, NULL, &ctx->cb_rock); if (ctx->pmce.deflate.zstrm) { inflateEnd(ctx->pmce.deflate.zstrm); free(ctx->pmce.deflate.zstrm); } free(ctx); }
websocket_return_t websocket_client_open(websocket_t *client, char *host, char *port, char *path) { int fd = -1; int r = WEBSOCKET_SUCCESS; struct websocket_info_t *socket_data = NULL; struct sched_param ws_sparam; if (client == NULL || host == NULL || port == NULL || path == NULL) { WEBSOCKET_DEBUG("NULL parameter\n"); return WEBSOCKET_ALLOCATION_ERROR; } websocket_update_state(client, WEBSOCKET_RUN_CLIENT); //TODO : all TLS initializing code will be moved from example to here if (websocket_connect(client, host, port) != WEBSOCKET_SUCCESS) { r = WEBSOCKET_CONNECT_ERROR; goto EXIT_CLIENT_OPEN; } fd = client->fd; if (websocket_client_handshake(client, host, port, path) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to http handshake\n"); r = WEBSOCKET_HANDSHAKE_ERROR; goto EXIT_CLIENT_OPEN; } socket_data = malloc(sizeof(struct websocket_info_t)); if (socket_data == NULL) { WEBSOCKET_DEBUG("fail to allocate memory\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } memset(socket_data, 0, sizeof(struct websocket_info_t)); socket_data->data = client; if (wslay_event_context_client_init(&client->ctx, client->cb, socket_data) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to init websocket client context\n"); WEBSOCKET_FREE(socket_data); r = WEBSOCKET_INIT_ERROR; goto EXIT_CLIENT_OPEN; } WEBSOCKET_DEBUG("start websocket client handling thread\n"); if (pthread_attr_init(&client->thread_attr) != 0) { WEBSOCKET_DEBUG("fail to init pthread attribute\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } if (pthread_attr_setstacksize(&client->thread_attr, WEBSOCKET_STACKSIZE) != 0) { WEBSOCKET_DEBUG("fail to set stack size\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } ws_sparam.sched_priority = WEBSOCKET_PRI; if (pthread_attr_setschedparam(&client->thread_attr, &ws_sparam) != 0) { WEBSOCKET_DEBUG("fail to set priority\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } if (pthread_attr_setschedpolicy(&client->thread_attr, WEBSOCKET_SCHED_POLICY) != 0) { WEBSOCKET_DEBUG("fail to set scheduler policy\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } if (pthread_create(&client->thread_id, &client->thread_attr, (pthread_startroutine_t) websocket_handler, (pthread_addr_t) client) != 0) { WEBSOCKET_DEBUG("fail to create websocket client thread\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } if (pthread_setname_np(client->thread_id, "websocket client handler") != 0) { WEBSOCKET_DEBUG("fail to set thread name\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } if (pthread_detach(client->thread_id) != 0) { WEBSOCKET_DEBUG("fail to detach websocket handler thread\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_CLIENT_OPEN; } return r; EXIT_CLIENT_OPEN: WEBSOCKET_CLOSE(fd); if (client->ctx) { wslay_event_context_free(client->ctx); client->ctx = NULL; } websocket_update_state(client, WEBSOCKET_STOP); return r; }
~WebSocketClient() { wslay_event_context_free(ctx_); shutdown(fd_, SHUT_WR); close(fd_); }