static void SetSocketVTable(SocketCore * core) { core->write=[](SocketCore * thisCore, const char * data, int len, bool instant) { SocketCore * core=(SocketCore*)thisCore; if (core->fd==-1) return; if (instant) SetSocketBuffering(core->fd, false); while (len) { int thislen=send(core->fd, data, len, 0); if (thislen<=0) { if (isagain(thislen)) { usleep(100000); continue; } core->close(core); return; } data+=thislen; len-=thislen; } if (instant) SetSocketBuffering(core->fd, true); }; core->read=[](SocketCore * thisCore, char * data, int len)->int { SocketCore * core=(SocketCore*)thisCore; if (core->fd==-1) return -1; int bytes=recv(core->fd, data, len, 0); if (bytes==0) { core->close(core); return -1; } if (isagain(bytes)) return 0; return bytes; }; core->isActive=[](SocketCore * thisCore, bool selected)->bool { SocketCore * core=(SocketCore*)thisCore; if (core->fd==-1) return true; return selected; }; core->close=[](SocketCore * thisCore) { SocketCore * core=(SocketCore*)thisCore; if (core->fd==-1) return; close(core->fd); core->fd=-1; }; }
ssize_t socket_send_all_nonblocking(int fd, const void *data_, size_t size, bool no_signal) { const uint8_t *data = (const uint8_t*)data_; ssize_t sent = 0; while (size) { ssize_t ret = send(fd, (const char*)data, size, no_signal ? MSG_NOSIGNAL : 0); if (ret < 0) { if (isagain((int)ret)) break; return -1; } else if (ret == 0) break; data += ret; size -= ret; sent += ret; } return sent; }
ssize_t ssl_socket_receive_all_nonblocking(void *state_data, bool *error, void *data_, size_t size) { struct ssl_state *state = (struct ssl_state*)state_data; const uint8_t *data = (const uint8_t*)data_; /* mbedtls_ssl_read wants non-const data but it only reads it, so this cast is safe */ ssize_t ret; mbedtls_net_set_nonblock(&state->net_ctx); ret = mbedtls_ssl_read(&state->ctx, (unsigned char*)data, size); if (ret > 0) return ret; if (ret == 0) { /* Socket closed */ *error = true; return -1; } if (isagain((int)ret)) return 0; *error = true; return -1; }
ssize_t socket_receive_all_nonblocking(int fd, bool *error, void *data_, size_t size) { const uint8_t *data = (const uint8_t*)data_; ssize_t ret = recv(fd, (char*)data, size, 0); if (ret > 0) return ret; if (ret == 0) return -1; if (isagain(ret)) return 0; *error = true; return -1; }
static ssize_t net_http_recv(int fd, bool *error, uint8_t *data, size_t maxlen) { ssize_t bytes; if (*error) return -1; bytes = recv(fd, (char*)data, maxlen, 0); if (bytes > 0) return bytes; else if (bytes == 0) return -1; else if (isagain(bytes)) return 0; *error=true; return -1; }
int socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_signal) { const uint8_t *data = (const uint8_t*)data_; while (size) { ssize_t ret = send(fd, (const char*)data, size, no_signal ? MSG_NOSIGNAL : 0); if (ret <= 0) { if (isagain((int)ret)) continue; return false; } data += ret; size -= ret; } return true; }
static void net_http_send(int fd, bool * error, const char * data, size_t len) { if (*error) return; while (len) { ssize_t thislen = send(fd, data, len, MSG_NOSIGNAL); if (thislen <= 0) { if (!isagain(thislen)) continue; *error=true; return; } data += thislen; len -= thislen; } }