Skip to content

Commit

Permalink
client: make connect nonblock
Browse files Browse the repository at this point in the history
  • Loading branch information
liudongmiao committed Jun 12, 2024
1 parent 46b82e8 commit dd58b82
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ void safe_bufferevent_free(struct bufferevent *bev);

#ifndef _WIN32
#define EVUTIL_ERR_RW_RETRIABLE(e) ((e) == EINTR || (e) == EAGAIN || (e) == EWOULDBLOCK)
#define EVUTIL_ERR_CONNECT_RETRIABLE(e) ((e) == EINTR || (e) == EINPROGRESS)
#else
#define EVUTIL_ERR_RW_RETRIABLE(e) ((e) == WSAEINTR || (e) == WSAEWOULDBLOCK)
#define EVUTIL_ERR_CONNECT_RETRIABLE(e) ((e) == WSAEINTR || (e) == WSAEINPROGRESS || (e) == WSAEWOULDBLOCK)
#endif

uint16_t get_peer_port(struct bufferevent *bev);
Expand Down
78 changes: 69 additions & 9 deletions wss-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,9 @@ static void http2_readcb(evutil_socket_t sock, short event, void *context) {
lh_bufferevent_http_stream_doall(http_streams, evict_http2_stream);
lh_bufferevent_http_stream_set_down_load(http_streams, hash_factor);
}
do_http2_write(wss_context, wss_context->output);
if (wss_context->ssl_connected) {
do_http2_write(wss_context, wss_context->output);
}
}

static ssize_t do_http2_write(struct wss_context *wss_context, struct evbuffer *output) {
Expand Down Expand Up @@ -1204,6 +1206,52 @@ static void bufferevent_readcb(evutil_socket_t fd, short event, void *arg) {
return;
}

enum status {
error,
eagain,
connected,
};

static enum status is_ssl_connected(struct bev_context_ssl *bev_context_ssl, evutil_socket_t fd) {
int err;
ev_socklen_t len;

if (bev_context_ssl) {
if (bev_context_ssl->http == http1 && bev_context_ssl->connected) {
return connected;
}
if (bev_context_ssl->http == http2 && bev_context_ssl->wss_context->ssl_connected) {
return connected;
}
if (bev_context_ssl->http == http3) {
return connected;
}
}
len = sizeof(err);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) < 0) {
err = evutil_socket_geterror(sock);
LOGW("cannot getsockopt: %s", evutil_socket_error_to_string(err));
return error;
}
if (err) {
if (EVUTIL_ERR_CONNECT_RETRIABLE(err)) {
return eagain;
} else {
LOGW("socket error: %s", evutil_socket_error_to_string(err));
return error;
}
}
if (bev_context_ssl) {
if (bev_context_ssl->http == http1) {
bev_context_ssl->connected = 1;
}
if (bev_context_ssl->http == http2) {
bev_context_ssl->wss_context->ssl_connected = 1;
}
}
return connected;
}

static void bufferevent_writecb(evutil_socket_t fd, short event, void *arg) {
ssize_t res, size;
uint8_t buffer[WSS_PAYLOAD_SIZE];
Expand All @@ -1217,6 +1265,15 @@ static void bufferevent_writecb(evutil_socket_t fd, short event, void *arg) {
}

bev_context_ssl = bufferevent_get_context(bev);
switch (is_ssl_connected(bev_context_ssl, fd)) {
case error:
goto error;
case eagain:
goto done;
case connected:
default:
break;
}
if (bev_context_ssl && bev_context_ssl->http == http2) {
res = do_http2_write(bev_context_ssl->wss_context, bev_context_ssl->wss_context->output);
if (res < 0) {
Expand Down Expand Up @@ -1276,7 +1333,7 @@ static void bufferevent_writecb(evutil_socket_t fd, short event, void *arg) {
}

static int init_ssl_sock(struct wss_context *wss_context, struct event_base *base, SSL **ssl1) {
int sock;
int sock = -1, socket_error;
SSL *ssl, *stream = NULL;
socklen_t socklen;
struct sockaddr_storage sockaddr;
Expand All @@ -1301,17 +1358,20 @@ static int init_ssl_sock(struct wss_context *wss_context, struct event_base *bas
return -1;
}

if (update_socket_flag(sock)) {
goto error;
}

if (wss_context->server.http2 || wss_context->server.http3) {
LOGI("new sock");
}

if (!wss_context->server.http3 && connect(sock, (struct sockaddr *) &sockaddr, socklen) < 0) {
LOGW("cannot connect: %s", strerror(errno));
goto error;
}

if (update_socket_flag(sock)) {
goto error;
socket_error = evutil_socket_geterror(sock);
if (!EVUTIL_ERR_CONNECT_RETRIABLE(socket_error)) {
LOGW("cannot connect: %s", evutil_socket_error_to_string(socket_error));
goto error;
}
}

if (!wss_context->server.tls) {
Expand Down Expand Up @@ -1501,7 +1561,7 @@ void bufferevent_timeout(struct bev_context_ssl *bev_context_ssl) {
return;
}
wss_context = bev_context_ssl->wss_context;
if (!wss_context) {
if (!wss_context || !wss_context->http_streams) {
return;
}
key.stream_id = bev_context_ssl->stream_id;
Expand Down
2 changes: 2 additions & 0 deletions wss-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct wss_context {
struct timeval timeout;
uint8_t settings_sent: 1;
uint8_t ssl_error: 1;
uint8_t ssl_connected: 1;
uint8_t http2_evicted: 1;
uint32_t next_stream_id: 23;
uint32_t initial_window_size;
Expand All @@ -61,6 +62,7 @@ struct bev_context_ssl {
struct wss_context *wss_context;
enum http http: 2;
uint8_t upgrade: 1;
uint8_t connected: 1;
struct evbuffer *frame;
uint32_t stream_id;
uint32_t initial_window_size;
Expand Down

0 comments on commit dd58b82

Please sign in to comment.