Add debug code to trace socket state transitions and fix bug in response parser where a space was consumed twice

This commit is contained in:
2025-11-26 15:33:15 +01:00
parent aa158980f5
commit 749aef7c8d
6 changed files with 336 additions and 228 deletions
+93 -43
View File
@@ -1179,12 +1179,11 @@ static int parse_response(Scanner *s, HTTP_Response *res)
return -1;
}
if (s->len - s->cur < 5
|| s->src[s->cur+0] != ' '
if (s->len - s->cur < 4
|| !is_digit(s->src[s->cur+0])
|| !is_digit(s->src[s->cur+1])
|| !is_digit(s->src[s->cur+2])
|| !is_digit(s->src[s->cur+3])
|| s->src[s->cur+4] != ' ')
|| s->src[s->cur+3] != ' ')
return -1;
s->cur += 5;
@@ -1969,6 +1968,35 @@ int server_secure_context_add_certificate(ServerSecureContext *ctx,
// src/socket.c
////////////////////////////////////////////////////////////////////////////////////////
#define TRACE_STATE_CHANGES
#ifndef TRACE_STATE_CHANGES
#define UPDATE_STATE(a, b) a = b
#else
static char *state_to_str(SocketState state)
{
switch (state) {
case SOCKET_STATE_FREE : return "FREE";
case SOCKET_STATE_PENDING : return "PENDING";
case SOCKET_STATE_CONNECTING: return "CONNECTING";
case SOCKET_STATE_CONNECTED : return "CONNECTED";
case SOCKET_STATE_ACCEPTED : return "ACCEPTED";
case SOCKET_STATE_ESTABLISHED_WAIT : return "ESTABLISHED_WAIT";
case SOCKET_STATE_ESTABLISHED_READY: return "ESTABLISHED_READY";
case SOCKET_STATE_SHUTDOWN : return "SHUTDOWN";
case SOCKET_STATE_DIED : return "DIED";
}
return "???";
}
#define UPDATE_STATE(a, b) { \
printf("%s -> %s %s:%d\n", \
state_to_str(a), \
state_to_str(b), \
__FILE__, __LINE__); \
a = b; \
}
#endif
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
{
#ifdef _WIN32
@@ -2300,7 +2328,7 @@ static void socket_update(Socket *s)
s->next_addr++;
if (s->next_addr == s->num_addr) {
// All addresses have been tried and failed
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
@@ -2315,14 +2343,14 @@ static void socket_update(Socket *s)
int family = (addr.is_ipv4 ? AF_INET : AF_INET6);
NATIVE_SOCKET sock = socket(family, SOCK_STREAM, 0);
if (sock == NATIVE_SOCKET_INVALID) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
if (set_socket_blocking(sock, false) < 0) {
CLOSE_NATIVE_SOCKET(sock);
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
@@ -2345,25 +2373,25 @@ static void socket_update(Socket *s)
if (ret == 0) {
// Connect resolved immediately
s->sock = sock;
s->state = SOCKET_STATE_CONNECTED;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTED);
s->events = 0;
again = true;
} else if (connect_pending()) {
// Connect is pending, which is expected
s->sock = sock;
s->state = SOCKET_STATE_CONNECTING;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTING);
s->events = POLLOUT;
} else if (connect_failed_because_of_peer()) {
// Conenct failed due to the peer host
// We should try a different address.
s->sock = sock;
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
} else {
// An error occurred that we can't recover from
s->sock = sock;
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
again = true;
}
@@ -2379,23 +2407,23 @@ static void socket_update(Socket *s)
socklen_t len = sizeof(err);
if (getsockopt(s->sock, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0) {
// Failed to get socket error status
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
if (err == 0) {
// Connection succeded
s->state = SOCKET_STATE_CONNECTED;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTED);
s->events = 0;
again = true;
} else if (connect_failed_because_of_peer_2(err)) {
// Try the next address
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
} else {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
}
@@ -2412,19 +2440,19 @@ static void socket_update(Socket *s)
free(s->addrs);
s->events = 0;
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
} else {
#ifdef HTTPS_ENABLED
if (s->ssl == NULL) {
s->ssl = SSL_new(s->client_secure_context->p);
if (s->ssl == NULL) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
if (SSL_set_fd(s->ssl, s->sock) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -2439,7 +2467,7 @@ static void socket_update(Socket *s)
// Set expected hostname for verification
if (SSL_set1_host(s->ssl, addr.name->data) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -2468,7 +2496,7 @@ static void socket_update(Socket *s)
free(s->addrs);
}
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
}
@@ -2484,7 +2512,7 @@ static void socket_update(Socket *s)
break;
}
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
#endif
@@ -2495,7 +2523,7 @@ static void socket_update(Socket *s)
case SOCKET_STATE_ACCEPTED:
{
if (!is_secure(s)) {
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
} else {
#ifdef HTTPS_ENABLED
@@ -2504,13 +2532,13 @@ static void socket_update(Socket *s)
s->ssl = SSL_new(s->server_secure_context->p);
if (s->ssl == NULL) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
if (SSL_set_fd(s->ssl, s->sock) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -2519,7 +2547,7 @@ static void socket_update(Socket *s)
int ret = SSL_accept(s->ssl);
if (ret == 1) {
// Handshake done
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
}
@@ -2536,7 +2564,7 @@ static void socket_update(Socket *s)
}
// Server socket error - close the connection
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
#endif
}
@@ -2544,20 +2572,20 @@ static void socket_update(Socket *s)
break;
case SOCKET_STATE_ESTABLISHED_WAIT:
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
case SOCKET_STATE_SHUTDOWN:
{
if (!is_secure(s)) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
} else {
#ifdef HTTPS_ENABLED
int ret = SSL_shutdown(s->ssl);
if (ret == 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -2573,7 +2601,7 @@ static void socket_update(Socket *s)
break;
}
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
#endif
}
@@ -2758,7 +2786,7 @@ static int socket_manager_translate_events_nolock(
socket_update(s);
if (s->state == SOCKET_STATE_DIED) {
CLOSE_NATIVE_SOCKET(sock);
s->state = SOCKET_STATE_FREE;
UPDATE_STATE(s->state, SOCKET_STATE_FREE);
s->gen++;
if (s->gen == 0)
s->gen = 1;
@@ -2800,7 +2828,7 @@ static int socket_manager_translate_events_nolock(
};
// Free resources associated to socket
s->state = SOCKET_STATE_FREE;
UPDATE_STATE(s->state, SOCKET_STATE_FREE);
if (s->sock != NATIVE_SOCKET_INVALID)
CLOSE_NATIVE_SOCKET(s->sock);
if (s->sock == SOCKET_STATE_PENDING ||
@@ -2989,7 +3017,7 @@ int socket_connect(SocketManager *sm, int num_targets,
s->addrs[i] = resolved[i];
}
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->sock = NATIVE_SOCKET_INVALID;
s->user = user;
#ifdef HTTPS_ENABLED
@@ -3032,7 +3060,7 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
return 0;
if (s->state != SOCKET_STATE_ESTABLISHED_READY) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
return 0;
}
@@ -3040,14 +3068,14 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
if (!is_secure(s)) {
int ret = recv(s->sock, dst, max, 0);
if (ret == 0) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
} else if (ret < 0) {
if (would_block()) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLIN;
} else if (!interrupted()) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
ret = 0;
@@ -3062,7 +3090,7 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
s->events = POLLIN;
} else if (err == SSL_ERROR_WANT_WRITE) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLOUT;
} else {
s->state = SOCKET_STATE_DIED;
@@ -3096,7 +3124,7 @@ static int socket_send_nolock(SocketManager *sm, SocketHandle handle,
return 0;
if (s->state != SOCKET_STATE_ESTABLISHED_READY) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
return 0;
}
@@ -3105,10 +3133,10 @@ static int socket_send_nolock(SocketManager *sm, SocketHandle handle,
int ret = send(s->sock, src, len, 0);
if (ret < 0) {
if (would_block()) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLOUT;
} else if (!interrupted()) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
ret = 0;
@@ -3161,7 +3189,7 @@ int socket_close(SocketManager *sm, SocketHandle handle)
else {
// Only transition to SHUTDOWN if socket is not already DIED
if (s->state != SOCKET_STATE_DIED) {
s->state = SOCKET_STATE_SHUTDOWN;
UPDATE_STATE(s->state, SOCKET_STATE_SHUTDOWN);
s->events = 0;
socket_update(s);
}
@@ -3209,6 +3237,24 @@ int socket_set_user(SocketManager *sm, SocketHandle handle, void *user)
return ret;
}
bool socket_ready(SocketManager *sm, SocketHandle handle)
{
if (mutex_lock(&sm->mutex) < 0) {
assert(0); // TODO
}
bool ready = false;
Socket *s = handle_to_socket(sm, handle);
if (s && s->events == 0 && s->state != SOCKET_STATE_DIED) {
ready = true;
}
if (mutex_unlock(&sm->mutex) < 0) {
assert(0); // TODO
}
return ready;
}
////////////////////////////////////////////////////////////////////////////////////////
// src/byte_queue.c
////////////////////////////////////////////////////////////////////////////////////////
@@ -4196,6 +4242,8 @@ int http_client_process_events(HTTP_Client *client,
if (conn->handle == SOCKET_HANDLE_INVALID)
conn->handle = events[i].handle;
while (socket_ready(&client->sockets, conn->handle)) {
if (conn->state == HTTP_CLIENT_CONN_FLUSHING) {
ByteView src = byte_queue_read_buf(&conn->output);
@@ -4263,7 +4311,7 @@ int http_client_process_events(HTTP_Client *client,
}
// Ready
assert(ret == 1);
assert(ret > 0);
conn->state = HTTP_CLIENT_CONN_COMPLETE;
conn->result = 0;
@@ -4278,6 +4326,8 @@ int http_client_process_events(HTTP_Client *client,
conn->url.path);
// TODO: Handle redirects here
break;
}
}
}
+4
View File
@@ -649,6 +649,10 @@ int socket_is_secure(SocketManager *sm, SocketHandle handle);
// Set the user pointer of a socket
int socket_set_user(SocketManager *sm, SocketHandle handle, void *user);
// Returns true iff the socket is ready for reading or
// writing.
bool socket_ready(SocketManager *sm, SocketHandle handle);
////////////////////////////////////////////////////////////////////////////////////////
// src/byte_queue.h
////////////////////////////////////////////////////////////////////////////////////////
+5 -1
View File
@@ -523,6 +523,8 @@ int http_client_process_events(HTTP_Client *client,
if (conn->handle == SOCKET_HANDLE_INVALID)
conn->handle = events[i].handle;
while (socket_ready(&client->sockets, conn->handle)) {
if (conn->state == HTTP_CLIENT_CONN_FLUSHING) {
ByteView src = byte_queue_read_buf(&conn->output);
@@ -590,7 +592,7 @@ int http_client_process_events(HTTP_Client *client,
}
// Ready
assert(ret == 1);
assert(ret > 0);
conn->state = HTTP_CLIENT_CONN_COMPLETE;
conn->result = 0;
@@ -605,6 +607,8 @@ int http_client_process_events(HTTP_Client *client,
conn->url.path);
// TODO: Handle redirects here
break;
}
}
}
+3 -4
View File
@@ -1067,12 +1067,11 @@ static int parse_response(Scanner *s, HTTP_Response *res)
return -1;
}
if (s->len - s->cur < 5
|| s->src[s->cur+0] != ' '
if (s->len - s->cur < 4
|| !is_digit(s->src[s->cur+0])
|| !is_digit(s->src[s->cur+1])
|| !is_digit(s->src[s->cur+2])
|| !is_digit(s->src[s->cur+3])
|| s->src[s->cur+4] != ' ')
|| s->src[s->cur+3] != ' ')
return -1;
s->cur += 5;
+85 -38
View File
@@ -1,4 +1,33 @@
//#define TRACE_STATE_CHANGES
#ifndef TRACE_STATE_CHANGES
#define UPDATE_STATE(a, b) a = b
#else
static char *state_to_str(SocketState state)
{
switch (state) {
case SOCKET_STATE_FREE : return "FREE";
case SOCKET_STATE_PENDING : return "PENDING";
case SOCKET_STATE_CONNECTING: return "CONNECTING";
case SOCKET_STATE_CONNECTED : return "CONNECTED";
case SOCKET_STATE_ACCEPTED : return "ACCEPTED";
case SOCKET_STATE_ESTABLISHED_WAIT : return "ESTABLISHED_WAIT";
case SOCKET_STATE_ESTABLISHED_READY: return "ESTABLISHED_READY";
case SOCKET_STATE_SHUTDOWN : return "SHUTDOWN";
case SOCKET_STATE_DIED : return "DIED";
}
return "???";
}
#define UPDATE_STATE(a, b) { \
printf("%s -> %s %s:%d\n", \
state_to_str(a), \
state_to_str(b), \
__FILE__, __LINE__); \
a = b; \
}
#endif
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
{
#ifdef _WIN32
@@ -330,7 +359,7 @@ static void socket_update(Socket *s)
s->next_addr++;
if (s->next_addr == s->num_addr) {
// All addresses have been tried and failed
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
@@ -345,14 +374,14 @@ static void socket_update(Socket *s)
int family = (addr.is_ipv4 ? AF_INET : AF_INET6);
NATIVE_SOCKET sock = socket(family, SOCK_STREAM, 0);
if (sock == NATIVE_SOCKET_INVALID) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
if (set_socket_blocking(sock, false) < 0) {
CLOSE_NATIVE_SOCKET(sock);
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
@@ -375,25 +404,25 @@ static void socket_update(Socket *s)
if (ret == 0) {
// Connect resolved immediately
s->sock = sock;
s->state = SOCKET_STATE_CONNECTED;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTED);
s->events = 0;
again = true;
} else if (connect_pending()) {
// Connect is pending, which is expected
s->sock = sock;
s->state = SOCKET_STATE_CONNECTING;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTING);
s->events = POLLOUT;
} else if (connect_failed_because_of_peer()) {
// Conenct failed due to the peer host
// We should try a different address.
s->sock = sock;
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
} else {
// An error occurred that we can't recover from
s->sock = sock;
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
again = true;
}
@@ -409,23 +438,23 @@ static void socket_update(Socket *s)
socklen_t len = sizeof(err);
if (getsockopt(s->sock, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0) {
// Failed to get socket error status
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
continue;
}
if (err == 0) {
// Connection succeded
s->state = SOCKET_STATE_CONNECTED;
UPDATE_STATE(s->state, SOCKET_STATE_CONNECTED);
s->events = 0;
again = true;
} else if (connect_failed_because_of_peer_2(err)) {
// Try the next address
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
} else {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
}
@@ -442,19 +471,19 @@ static void socket_update(Socket *s)
free(s->addrs);
s->events = 0;
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
} else {
#ifdef HTTPS_ENABLED
if (s->ssl == NULL) {
s->ssl = SSL_new(s->client_secure_context->p);
if (s->ssl == NULL) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
if (SSL_set_fd(s->ssl, s->sock) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -469,7 +498,7 @@ static void socket_update(Socket *s)
// Set expected hostname for verification
if (SSL_set1_host(s->ssl, addr.name->data) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -498,7 +527,7 @@ static void socket_update(Socket *s)
free(s->addrs);
}
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
}
@@ -514,7 +543,7 @@ static void socket_update(Socket *s)
break;
}
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->events = 0;
again = true;
#endif
@@ -525,7 +554,7 @@ static void socket_update(Socket *s)
case SOCKET_STATE_ACCEPTED:
{
if (!is_secure(s)) {
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
} else {
#ifdef HTTPS_ENABLED
@@ -534,13 +563,13 @@ static void socket_update(Socket *s)
s->ssl = SSL_new(s->server_secure_context->p);
if (s->ssl == NULL) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
if (SSL_set_fd(s->ssl, s->sock) != 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -549,7 +578,7 @@ static void socket_update(Socket *s)
int ret = SSL_accept(s->ssl);
if (ret == 1) {
// Handshake done
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
}
@@ -566,7 +595,7 @@ static void socket_update(Socket *s)
}
// Server socket error - close the connection
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
#endif
}
@@ -574,20 +603,20 @@ static void socket_update(Socket *s)
break;
case SOCKET_STATE_ESTABLISHED_WAIT:
s->state = SOCKET_STATE_ESTABLISHED_READY;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_READY);
s->events = 0;
break;
case SOCKET_STATE_SHUTDOWN:
{
if (!is_secure(s)) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
} else {
#ifdef HTTPS_ENABLED
int ret = SSL_shutdown(s->ssl);
if (ret == 1) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
break;
}
@@ -603,7 +632,7 @@ static void socket_update(Socket *s)
break;
}
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
#endif
}
@@ -788,7 +817,7 @@ static int socket_manager_translate_events_nolock(
socket_update(s);
if (s->state == SOCKET_STATE_DIED) {
CLOSE_NATIVE_SOCKET(sock);
s->state = SOCKET_STATE_FREE;
UPDATE_STATE(s->state, SOCKET_STATE_FREE);
s->gen++;
if (s->gen == 0)
s->gen = 1;
@@ -830,7 +859,7 @@ static int socket_manager_translate_events_nolock(
};
// Free resources associated to socket
s->state = SOCKET_STATE_FREE;
UPDATE_STATE(s->state, SOCKET_STATE_FREE);
if (s->sock != NATIVE_SOCKET_INVALID)
CLOSE_NATIVE_SOCKET(s->sock);
if (s->sock == SOCKET_STATE_PENDING ||
@@ -1019,7 +1048,7 @@ int socket_connect(SocketManager *sm, int num_targets,
s->addrs[i] = resolved[i];
}
s->state = SOCKET_STATE_PENDING;
UPDATE_STATE(s->state, SOCKET_STATE_PENDING);
s->sock = NATIVE_SOCKET_INVALID;
s->user = user;
#ifdef HTTPS_ENABLED
@@ -1062,7 +1091,7 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
return 0;
if (s->state != SOCKET_STATE_ESTABLISHED_READY) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
return 0;
}
@@ -1070,14 +1099,14 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
if (!is_secure(s)) {
int ret = recv(s->sock, dst, max, 0);
if (ret == 0) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
} else if (ret < 0) {
if (would_block()) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLIN;
} else if (!interrupted()) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
ret = 0;
@@ -1092,7 +1121,7 @@ static int socket_recv_nolock(SocketManager *sm, SocketHandle handle,
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
s->events = POLLIN;
} else if (err == SSL_ERROR_WANT_WRITE) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLOUT;
} else {
s->state = SOCKET_STATE_DIED;
@@ -1126,7 +1155,7 @@ static int socket_send_nolock(SocketManager *sm, SocketHandle handle,
return 0;
if (s->state != SOCKET_STATE_ESTABLISHED_READY) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
return 0;
}
@@ -1135,10 +1164,10 @@ static int socket_send_nolock(SocketManager *sm, SocketHandle handle,
int ret = send(s->sock, src, len, 0);
if (ret < 0) {
if (would_block()) {
s->state = SOCKET_STATE_ESTABLISHED_WAIT;
UPDATE_STATE(s->state, SOCKET_STATE_ESTABLISHED_WAIT);
s->events = POLLOUT;
} else if (!interrupted()) {
s->state = SOCKET_STATE_DIED;
UPDATE_STATE(s->state, SOCKET_STATE_DIED);
s->events = 0;
}
ret = 0;
@@ -1191,7 +1220,7 @@ int socket_close(SocketManager *sm, SocketHandle handle)
else {
// Only transition to SHUTDOWN if socket is not already DIED
if (s->state != SOCKET_STATE_DIED) {
s->state = SOCKET_STATE_SHUTDOWN;
UPDATE_STATE(s->state, SOCKET_STATE_SHUTDOWN);
s->events = 0;
socket_update(s);
}
@@ -1238,3 +1267,21 @@ int socket_set_user(SocketManager *sm, SocketHandle handle, void *user)
return -1;
return ret;
}
bool socket_ready(SocketManager *sm, SocketHandle handle)
{
if (mutex_lock(&sm->mutex) < 0) {
assert(0); // TODO
}
bool ready = false;
Socket *s = handle_to_socket(sm, handle);
if (s && s->events == 0 && s->state != SOCKET_STATE_DIED) {
ready = true;
}
if (mutex_unlock(&sm->mutex) < 0) {
assert(0); // TODO
}
return ready;
}
+4
View File
@@ -331,3 +331,7 @@ int socket_is_secure(SocketManager *sm, SocketHandle handle);
// Set the user pointer of a socket
int socket_set_user(SocketManager *sm, SocketHandle handle, void *user);
// Returns true iff the socket is ready for reading or
// writing.
bool socket_ready(SocketManager *sm, SocketHandle handle);