void h2o_websocket_proceed(h2o_websocket_conn_t *conn) { int handled; /* run the loop until getting to a point where no more progress can be achieved */ do { handled = 0; if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) { if (wslay_event_send(conn->ws_ctx) != 0) { goto Close; } handled = 1; } if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) { if (wslay_event_recv(conn->ws_ctx) != 0) { goto Close; } handled = 1; } } while (handled); if (wslay_event_want_read(conn->ws_ctx)) { h2o_socket_read_start(conn->sock, on_recv); } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) { h2o_socket_read_stop(conn->sock); } else { /* nothing is going on... close the socket */ goto Close; } return; Close: on_close(conn); }
void h2o_websocket_proceed(h2o_websocket_conn_t *conn) { int handled; /* run the loop until getting to a point where no more progress can be achieved */ do { handled = 0; if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) { if (wslay_event_send(conn->ws_ctx) != 0) { goto Close; } /* avoid infinite loop when user want send more bufers count than ours in on_msg_callback() */ if (conn->_write_buf.cnt < sizeof(conn->_write_buf.bufs) / sizeof(conn->_write_buf.bufs[0])) { handled = 1; } } if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) { if (wslay_event_recv(conn->ws_ctx) != 0) { goto Close; } handled = 1; } } while (handled); if (!h2o_socket_is_writing(conn->sock) && conn->_write_buf.cnt > 0) { /* write */ h2o_socket_write(conn->sock, conn->_write_buf.bufs, conn->_write_buf.cnt, on_write_complete); } if (wslay_event_want_read(conn->ws_ctx)) { h2o_socket_read_start(conn->sock, on_recv); } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) { h2o_socket_read_stop(conn->sock); } else { /* nothing is going on... close the socket */ goto Close; } return; Close: on_close(conn); }
int h2o_socket_export(h2o_socket_t *sock, h2o_socket_export_t *info) { static h2o_buffer_prototype_t nonpooling_prototype = {}; assert(!h2o_socket_is_writing(sock)); if (do_export(sock, info) == -1) return -1; if ((info->ssl = sock->ssl) != NULL) { sock->ssl = NULL; h2o_buffer_set_prototype(&info->ssl->input.encrypted, &nonpooling_prototype); } info->input = sock->input; h2o_buffer_set_prototype(&info->input, &nonpooling_prototype); h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype); h2o_socket_close(sock); return 0; }
static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *_conn) { h2o_websocket_conn_t *conn = _conn; h2o_iovec_t *buf; /* return WOULDBLOCK if pending or no buffer available */ if (h2o_socket_is_writing(conn->sock) || conn->_write_buf.cnt == sizeof(conn->_write_buf.bufs) / sizeof(conn->_write_buf.bufs[0])) { wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK); return -1; } buf = &conn->_write_buf.bufs[conn->_write_buf.cnt]; /* copy data */ buf->base = h2o_mem_alloc(len); buf->len = len; memcpy(buf->base, data, len); ++conn->_write_buf.cnt; return len; }
static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *_conn) { h2o_websocket_conn_t *conn = _conn; h2o_iovec_t buf; /* return WOULDBLOCK if pending (TODO: queue fixed number of chunks, instead of only one) */ if (h2o_socket_is_writing(conn->sock)) { wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK); return -1; } /* copy data */ conn->_write_buf = h2o_mem_realloc(conn->_write_buf, len); memcpy(conn->_write_buf, data, len); /* write */ buf.base = conn->_write_buf; buf.len = len; h2o_socket_write(conn->sock, &buf, 1, on_write_complete); return len; }