h2o_websocket_conn_t *h2o_upgrade_to_websocket(h2o_req_t *req, const char *client_key, void *data, h2o_websocket_msg_callback cb) { h2o_websocket_conn_t *conn = h2o_mem_alloc(sizeof(*conn)); char accept_key[29]; /* only for http1 connection */ assert(req->version < 0x200); /* setup the context */ memset(conn, 0, sizeof(*conn)); // conn->sock = sock; set by on_complete conn->ws_callbacks.recv_callback = recv_callback; conn->ws_callbacks.send_callback = send_callback; conn->ws_callbacks.on_msg_recv_callback = on_msg_callback; conn->data = data; conn->cb = cb; wslay_event_context_server_init(&conn->ws_ctx, &conn->ws_callbacks, conn); /* build response */ create_accept_key(accept_key, client_key); req->res.status = 101; req->res.reason = "Switching Protocols"; h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket")); h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("sec-websocket-accept"), 0, NULL, accept_key, strlen(accept_key)); /* send */ h2o_http1_upgrade(req, NULL, 0, on_complete, conn); return conn; }
static inline void on_websocket_upgrade(struct rp_generator_t *self, h2o_timeout_t *timeout) { h2o_req_t *req = self->src_req; h2o_socket_t *sock = h2o_http1client_steal_socket(self->client); struct rp_ws_upgrade_info_t *info = h2o_mem_alloc(sizeof(*info)); info->upstream_sock = sock; info->timeout = timeout; info->ctx = req->conn->ctx; h2o_http1_upgrade(req, NULL, 0, on_websocket_upgrade_complete, info); }
static inline void on_websocket_upgrade(struct rp_generator_t *self, h2o_timeout_t *timeout, int rlen) { h2o_req_t *req = self->src_req; h2o_socket_t *sock = h2o_http1client_steal_socket(self->client); h2o_buffer_consume(&sock->input, rlen);//trash data after stealing sock. struct rp_ws_upgrade_info_t *info = h2o_mem_alloc(sizeof(*info)); info->upstream_sock = sock; info->timeout = timeout; info->ctx = req->conn->ctx; h2o_http1_upgrade(req, NULL, 0, on_websocket_upgrade_complete, info); }