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