From 9f5d2e74e61cbc112d6e71176f4389f0be2c4f9f Mon Sep 17 00:00:00 2001 From: Test_User Date: Tue, 18 Jun 2024 14:25:16 -0400 Subject: Network relocations, and in-progress buffered networking code --- networks/gnutls.c | 436 ++++++++++++++++++++++++++++++++++++++++++ networks/gnutls.h | 45 +++++ networks/openssl.c | 411 +++++++++++++++++++++++++++++++++++++++ networks/openssl.h | 45 +++++ networks/plaintext.c | 173 +++++++++++++++++ networks/plaintext.h | 45 +++++ networks/plaintext_buffered.c | 288 ++++++++++++++++++++++++++++ networks/plaintext_buffered.h | 45 +++++ 8 files changed, 1488 insertions(+) create mode 100644 networks/gnutls.c create mode 100644 networks/gnutls.h create mode 100644 networks/openssl.c create mode 100644 networks/openssl.h create mode 100644 networks/plaintext.c create mode 100644 networks/plaintext.h create mode 100644 networks/plaintext_buffered.c create mode 100644 networks/plaintext_buffered.h (limited to 'networks') diff --git a/networks/gnutls.c b/networks/gnutls.c new file mode 100644 index 0000000..c5a4122 --- /dev/null +++ b/networks/gnutls.c @@ -0,0 +1,436 @@ +// One of the code files for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "../general_network.h" +#include "../main.h" +#include "../mutex.h" +#include "gnutls.h" + +struct gnutls_handle { + gnutls_session_t session; + MUTEX_TYPE mutex; + int fd; + char valid; +}; + +gnutls_certificate_credentials_t gnutls_cert_creds; + +int init_gnutls_network(void) { + if (gnutls_global_init() < 0) + return 1; + + if (gnutls_certificate_allocate_credentials(&gnutls_cert_creds) != GNUTLS_E_SUCCESS) + return 2; + + if (GNUTLS_USE_SYSTEM_TRUST && (gnutls_certificate_set_x509_system_trust(gnutls_cert_creds) < 0)) + return 3; + + if (GNUTLS_KEY_PATH && GNUTLS_CERT_PATH && gnutls_certificate_set_x509_key_file(gnutls_cert_creds, GNUTLS_CERT_PATH, GNUTLS_KEY_PATH, GNUTLS_X509_FMT_PEM) < 0) + return 4; + + return 0; +} + +int gnutls_send(void *handle, struct string msg) { + if (msg.len == 0) + return 0; + + struct gnutls_handle *gnutls_handle = handle; + + mutex_lock(&(gnutls_handle->mutex)); + + if (!gnutls_handle->valid) + goto gnutls_send_error_unlock; + + struct pollfd pollfd = { + .fd = gnutls_handle->fd, + }; + do { + ssize_t gnutls_res; + int poll_res; + gnutls_res = gnutls_record_send(gnutls_handle->session, msg.data, msg.len); + if (gnutls_res <= 0) { + if (gnutls_res == GNUTLS_E_INTERRUPTED) { + continue; + } else if (gnutls_res == GNUTLS_E_AGAIN) { + pollfd.events = POLLIN | POLLOUT; + do { + poll_res = poll(&pollfd, 1, 0); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_send_error_unlock; + + if ((pollfd.revents & (POLLIN | POLLOUT)) == (POLLIN | POLLOUT)) + continue; + else if (pollfd.revents & (~(POLLIN | POLLOUT))) + goto gnutls_send_error_unlock; + else + pollfd.events = (pollfd.revents & (POLLIN | POLLOUT)) ^ (POLLIN | POLLOUT); + } else { + goto gnutls_send_error_unlock; + } + } else { + break; + } + + do { + poll_res = poll(&pollfd, 1, PING_INTERVAL*1000); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_send_error_unlock; + if (poll_res == 0) // Timed out + goto gnutls_send_error_unlock; + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) + goto gnutls_send_error_unlock; + } while (1); + + mutex_unlock(&(gnutls_handle->mutex)); + return 0; + + gnutls_send_error_unlock: + if (gnutls_handle->valid) { + mutex_unlock(&(gnutls_handle->mutex)); + gnutls_shutdown(gnutls_handle); + } else { + mutex_unlock(&(gnutls_handle->mutex)); + } + return 1; +} + +size_t gnutls_recv(void *handle, char *data, size_t len, char *err) { + struct gnutls_handle *gnutls_handle = handle; + + struct pollfd pollfd = { + .fd = gnutls_handle->fd, + }; + ssize_t gnutls_res; + do { + int poll_res; + mutex_lock(&(gnutls_handle->mutex)); + if (!gnutls_handle->valid) { + mutex_unlock(&(gnutls_handle->mutex)); + *err = 3; + return 0; + } + do { + gnutls_res = gnutls_record_recv(gnutls_handle->session, data, len); + } while (gnutls_res == GNUTLS_E_INTERRUPTED); + mutex_unlock(&(gnutls_handle->mutex)); + if (gnutls_res < 0) { + if (gnutls_res == GNUTLS_E_AGAIN) { + pollfd.events = POLLIN | POLLOUT; + do { + poll_res = poll(&pollfd, 1, 0); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) { + *err = 3; + return 0; + } + + if ((pollfd.revents & (POLLIN | POLLOUT)) == (POLLIN | POLLOUT)) + continue; + else + pollfd.events = (pollfd.revents & (POLLIN | POLLOUT)) ^ (POLLIN | POLLOUT); + } else { + *err = 3; + return 0; + } + } else if (gnutls_res == 0) { + *err = 2; + return 0; + } else { + break; + } + + do { + poll_res = poll(&pollfd, 1, PING_INTERVAL*1000); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) { + *err = 3; + return 0; + } if (poll_res == 0) { // Timed out + *err = 1; + return 0; + } if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) { + *err = 3; + return 0; + } + } while (1); + + *err = 0; + + return (size_t)gnutls_res; +} + +int gnutls_connect(void **handle, struct string address, struct string port, struct string *addr_out) { + struct gnutls_handle *gnutls_handle; + gnutls_handle = malloc(sizeof(*gnutls_handle)); + if (!gnutls_handle) + return -1; + + *handle = gnutls_handle; + + int res = mutex_init(&(gnutls_handle->mutex)); + if (res != 0) + goto gnutls_connect_free_gnutls_handle; + + struct sockaddr sockaddr; + if (resolve(address, port, &sockaddr) != 0) + goto gnutls_connect_destroy_mutex; + + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + goto gnutls_connect_destroy_mutex; + + gnutls_handle->fd = fd; + gnutls_handle->valid = 1; + + do { + res = connect(fd, &sockaddr, sizeof(sockaddr)); + } while (res < 0 && errno == EINTR); + if (res < 0) + goto gnutls_connect_close; + + int flags = fcntl(fd, F_GETFL); + if (flags == -1) + goto gnutls_connect_close; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) + goto gnutls_connect_close; + + if (gnutls_init(&(gnutls_handle->session), GNUTLS_CLIENT | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS) + goto gnutls_connect_close; + + if (gnutls_server_name_set(gnutls_handle->session, GNUTLS_NAME_DNS, address.data, address.len) != GNUTLS_E_SUCCESS) + goto gnutls_connect_deinit_session; + + if (gnutls_credentials_set(gnutls_handle->session, GNUTLS_CRD_CERTIFICATE, gnutls_cert_creds) != GNUTLS_E_SUCCESS) + goto gnutls_connect_deinit_session; + + if (gnutls_set_default_priority(gnutls_handle->session) != GNUTLS_E_SUCCESS) + goto gnutls_connect_deinit_session; + + gnutls_transport_set_int(gnutls_handle->session, fd); + + struct pollfd pollfd = { + .fd = fd, + }; + ssize_t gnutls_res; + do { + int poll_res; + do { + gnutls_res = gnutls_handshake(gnutls_handle->session); + } while (res == GNUTLS_E_INTERRUPTED); + if (gnutls_res < 0) { + if (gnutls_res == GNUTLS_E_AGAIN) { + pollfd.events = POLLIN | POLLOUT; + do { + poll_res = poll(&pollfd, 1, 0); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_connect_deinit_session; + + if ((pollfd.revents & (POLLIN | POLLOUT)) == (POLLIN | POLLOUT)) + continue; + else if (pollfd.revents & (~(POLLIN | POLLOUT))) + goto gnutls_connect_deinit_session; + else + pollfd.events = pollfd.revents ^ (POLLIN | POLLOUT); + } + } else { + break; + } + + do { + poll_res = poll(&pollfd, 1, PING_INTERVAL*1000); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_connect_deinit_session; + if (poll_res == 0) // Timed out + goto gnutls_connect_deinit_session; + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) + goto gnutls_connect_deinit_session; + } while (1); + + addr_out->data = malloc(sizeof(sockaddr)); + if (!addr_out->data) + goto gnutls_connect_deinit_session; + + memcpy(addr_out->data, &sockaddr, sizeof(sockaddr)); + addr_out->len = sizeof(sockaddr); + + return fd; + + gnutls_connect_deinit_session: + gnutls_deinit(gnutls_handle->session); + gnutls_connect_close: + close(fd); + gnutls_connect_destroy_mutex: + mutex_destroy(&(gnutls_handle->mutex)); + gnutls_connect_free_gnutls_handle: + free(gnutls_handle); + + return -1; +} + +int gnutls_accept(int listen_fd, void **handle, struct string *addr) { + if (!GNUTLS_CERT_PATH || !GNUTLS_KEY_PATH) + return -1; + + struct sockaddr address; + socklen_t address_len = sizeof(address); + + int con_fd; + do { + con_fd = accept(listen_fd, &address, &address_len); + } while (con_fd == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)); + + if (con_fd == -1) + return -1; + + int flags = fcntl(con_fd, F_GETFL); + if (flags == -1) + goto gnutls_accept_close; + if (fcntl(con_fd, F_SETFL, flags | O_NONBLOCK) == -1) + goto gnutls_accept_close; + + struct gnutls_handle *gnutls_handle; + gnutls_handle = malloc(sizeof(*gnutls_handle)); + if (!gnutls_handle) + goto gnutls_accept_close; + + *handle = gnutls_handle; + gnutls_handle->valid = 1; + gnutls_handle->fd = con_fd; + + int res = mutex_init(&(gnutls_handle->mutex)); + if (res != 0) + goto gnutls_accept_free_gnutls_handle; + + addr->data = malloc(address_len); + if (addr->data == 0 && address_len != 0) + goto gnutls_accept_destroy_mutex; + + memcpy(addr->data, &address, address_len); + addr->len = address_len; + + if (gnutls_init(&(gnutls_handle->session), GNUTLS_SERVER | GNUTLS_NONBLOCK) != GNUTLS_E_SUCCESS) + goto gnutls_accept_free_addr_data; + + if (gnutls_credentials_set(gnutls_handle->session, GNUTLS_CRD_CERTIFICATE, gnutls_cert_creds) != GNUTLS_E_SUCCESS) + goto gnutls_accept_deinit_session; + + if (gnutls_set_default_priority(gnutls_handle->session) != GNUTLS_E_SUCCESS) + goto gnutls_accept_deinit_session; + + gnutls_transport_set_int(gnutls_handle->session, con_fd); + + gnutls_handshake_set_timeout(gnutls_handle->session, PING_INTERVAL * 1000); + gnutls_record_set_timeout(gnutls_handle->session, PING_INTERVAL * 1000); + + struct pollfd pollfd = { + .fd = con_fd, + }; + ssize_t gnutls_res; + do { + int poll_res; + do { + gnutls_res = gnutls_handshake(gnutls_handle->session); + } while (res == GNUTLS_E_INTERRUPTED); + if (gnutls_res < 0) { + if (gnutls_res == GNUTLS_E_AGAIN) { + pollfd.events = POLLIN | POLLOUT; + do { + poll_res = poll(&pollfd, 1, 0); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_accept_deinit_session; + + if ((pollfd.revents & (POLLIN | POLLOUT)) == (POLLIN | POLLOUT)) + continue; + else if (pollfd.revents & (~(POLLIN | POLLOUT))) + goto gnutls_accept_deinit_session; + else + pollfd.events = pollfd.revents ^ (POLLIN | POLLOUT); + } + } else { + break; + } + + do { + poll_res = poll(&pollfd, 1, PING_INTERVAL*1000); + } while (poll_res < 0 && errno == EINTR); + if (poll_res < 0) + goto gnutls_accept_deinit_session; + if (poll_res == 0) // Timed out + goto gnutls_accept_deinit_session; + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) + goto gnutls_accept_deinit_session; + } while (1); + + return con_fd; + + gnutls_accept_deinit_session: + gnutls_deinit(gnutls_handle->session); + gnutls_accept_free_addr_data: + free(addr->data); + gnutls_accept_destroy_mutex: + mutex_destroy(&(gnutls_handle->mutex)); + gnutls_accept_free_gnutls_handle: + free(gnutls_handle); + gnutls_accept_close: + close(con_fd); + return -1; +} + +void gnutls_shutdown(void *handle) { + struct gnutls_handle *gnutls_handle = handle; + mutex_lock(&(gnutls_handle->mutex)); + shutdown(gnutls_handle->fd, SHUT_RDWR); + gnutls_handle->valid = 0; + mutex_unlock(&(gnutls_handle->mutex)); +} + +void gnutls_close(int fd, void *handle) { + struct gnutls_handle *gnutls_handle = handle; + mutex_destroy(&(gnutls_handle->mutex)); + gnutls_deinit(gnutls_handle->session); + free(gnutls_handle); + close(fd); +} diff --git a/networks/gnutls.h b/networks/gnutls.h new file mode 100644 index 0000000..51c7362 --- /dev/null +++ b/networks/gnutls.h @@ -0,0 +1,45 @@ +// One of the headers for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include + +#include "../haxstring.h" +#include "../general_network.h" + +int init_gnutls_network(void); + +int gnutls_send(void *fd, struct string msg); +size_t gnutls_recv(void *fd, char *data, size_t len, char *err); + +int gnutls_connect(void **handle, struct string address, struct string port, struct string *addr_out); +int gnutls_accept(int listen_fd, void **handle, struct string *addr); + +void gnutls_shutdown(void *handle); +void gnutls_close(int fd, void *handle); diff --git a/networks/openssl.c b/networks/openssl.c new file mode 100644 index 0000000..fdfd602 --- /dev/null +++ b/networks/openssl.c @@ -0,0 +1,411 @@ +// One of the code files for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "../main.h" +#include "../mutex.h" +#include "openssl.h" + +struct openssl_handle { + SSL *ssl; + MUTEX_TYPE mutex; + int fd; + char valid; +}; + +SSL_CTX *openssl_ctx; + +int init_openssl_network(void) { + SSL_library_init(); + + openssl_ctx = SSL_CTX_new(TLS_method()); + if (OPENSSL_CERT_PATH && OPENSSL_KEY_PATH) { + if (SSL_CTX_use_certificate_file(openssl_ctx, OPENSSL_CERT_PATH, SSL_FILETYPE_PEM) != 1) + return 1; + if (SSL_CTX_use_PrivateKey_file(openssl_ctx, OPENSSL_KEY_PATH, SSL_FILETYPE_PEM) != 1) + return 1; + } + + if (OPENSSL_USE_SYSTEM_TRUST) { + if (SSL_CTX_set_default_verify_paths(openssl_ctx) != 1) { + return 1; + } + } + + return 0; +} + +int openssl_send(void *handle, struct string msg) { + if (msg.len == 0) + return 0; + + struct openssl_handle *openssl_handle = handle; + + mutex_lock(&(openssl_handle->mutex)); + + if (!openssl_handle->valid) + goto openssl_send_error_unlock; + + struct pollfd pollfd = { + .fd = openssl_handle->fd, + }; + int res; + do { + res = SSL_write(openssl_handle->ssl, msg.data, msg.len); + if (res <= 0) { + switch(SSL_get_error(openssl_handle->ssl, res)) { + case SSL_ERROR_WANT_READ: + pollfd.events = POLLIN; + break; + case SSL_ERROR_WANT_WRITE: + pollfd.events = POLLOUT; + break; + default: + goto openssl_send_error_unlock; + } + } else { + break; + } + + do { + res = poll(&pollfd, 1, PING_INTERVAL*1000); + } while (res < 0 && errno == EINTR); + if (res < 0) + goto openssl_send_error_unlock; + if (res == 0) // Timed out... maybe handle differently later + goto openssl_send_error_unlock; + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) // Only errors returned + goto openssl_send_error_unlock; + } while (1); + + mutex_unlock(&(openssl_handle->mutex)); + return 0; + + openssl_send_error_unlock: + if (openssl_handle->valid) { + mutex_unlock(&(openssl_handle->mutex)); + openssl_shutdown(handle); + } else { + mutex_unlock(&(openssl_handle->mutex)); + } + return 1; +} + +size_t openssl_recv(void *handle, char *data, size_t len, char *err) { + struct openssl_handle *openssl_handle = handle; + + struct pollfd pollfd = { + .fd = openssl_handle->fd, + }; + int res; + do { + mutex_lock(&(openssl_handle->mutex)); + if (!openssl_handle->valid) { + mutex_unlock(&(openssl_handle->mutex)); + *err = 3; + return 0; + } + res = SSL_read(openssl_handle->ssl, data, len); + mutex_unlock(&(openssl_handle->mutex)); + if (res <= 0) { + switch(SSL_get_error(openssl_handle->ssl, res)) { + case SSL_ERROR_WANT_READ: + pollfd.events = POLLIN; + break; + case SSL_ERROR_WANT_WRITE: + pollfd.events = POLLOUT; + break; + default: + *err = 3; + return 0; + } + } else { + break; + } + + res = poll(&pollfd, 1, PING_INTERVAL*1000); + if (res == 0) { // Timeout + *err = 1; + return 0; + } + if (res == -1) { + if (errno != EINTR) { + continue; + } else { + *err = 3; + return 0; + } + } + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) { // Only errors returned + if (pollfd.revents & POLLHUP) { + *err = 2; + } else { + *err = 3; + } + + return 0; + } + } while (1); + + *err = 0; + return (size_t)res; +} + +int openssl_connect(void **handle, struct string address, struct string port, struct string *addr_out) { + struct sockaddr sockaddr; + if (resolve(address, port, &sockaddr) != 0) + return -1; + + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + return -1; + + { + struct timeval timeout = { + .tv_sec = PING_INTERVAL, + .tv_usec = 0, + }; + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + } + + int res; + do { + res = connect(fd, &sockaddr, sizeof(sockaddr)); + } while (res < 0 && errno == EINTR); + if (res < 0) + goto openssl_connect_close; + + int flags = fcntl(fd, F_GETFL); + if (flags == -1) + goto openssl_connect_close; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) + goto openssl_connect_close; + + addr_out->data = malloc(sizeof(sockaddr)); + if (!addr_out->data) + goto openssl_connect_close; + memcpy(addr_out->data, &sockaddr, sizeof(sockaddr)); + addr_out->len = sizeof(sockaddr); + + struct openssl_handle *openssl_handle; + openssl_handle = malloc(sizeof(*openssl_handle)); + if (!openssl_handle) + goto openssl_connect_free_addr_data; + *handle = openssl_handle; + + openssl_handle->fd = fd; + + openssl_handle->ssl = SSL_new(openssl_ctx); + if (!openssl_handle->ssl) + goto openssl_connect_free_openssl_handle; + SSL_set_fd(openssl_handle->ssl, fd); + + res = mutex_init(&(openssl_handle->mutex)); + if (res != 0) + goto openssl_connect_free_ssl; + + struct pollfd pollfd = { + .fd = fd, + }; + do { + res = SSL_connect(openssl_handle->ssl); + if (res == 0) + goto openssl_connect_destroy_mutex; + if (res < 0) { + switch(SSL_get_error(openssl_handle->ssl, res)) { + case SSL_ERROR_WANT_READ: + pollfd.events = POLLIN; + break; + case SSL_ERROR_WANT_WRITE: + pollfd.events = POLLOUT; + break; + default: + goto openssl_connect_destroy_mutex; + } + } else { + break; + } + + res = poll(&pollfd, 1, PING_INTERVAL*1000); + if (res == 0) // Timeout + goto openssl_connect_destroy_mutex; + if (res == -1) { + if (errno != EINTR) { + continue; + } else { + goto openssl_connect_destroy_mutex; + } + } + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) // Only errors returned + goto openssl_connect_destroy_mutex; + } while (1); + + openssl_handle->valid = 1; + + return fd; + + openssl_connect_destroy_mutex: + mutex_destroy(&(openssl_handle->mutex)); + openssl_connect_free_ssl: + SSL_free(openssl_handle->ssl); + openssl_connect_free_openssl_handle: + free(openssl_handle); + openssl_connect_free_addr_data: + free(addr_out->data); + openssl_connect_close: + close(fd); + + return -1; +} + +int openssl_accept(int listen_fd, void **handle, struct string *addr) { + if (!OPENSSL_CERT_PATH || !OPENSSL_KEY_PATH) + return -1; + + struct sockaddr address; + socklen_t address_len = sizeof(address); + + int con_fd; + do { + con_fd = accept(listen_fd, &address, &address_len); + } while (con_fd == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)); + + if (con_fd == -1) + return -1; + + int flags = fcntl(con_fd, F_GETFL); + if (flags == -1) + goto openssl_accept_close; + if (fcntl(con_fd, F_SETFL, flags | O_NONBLOCK) == -1) + goto openssl_accept_close; + + addr->data = malloc(address_len); + if (addr->data == 0 && address_len != 0) + goto openssl_accept_close; + + memcpy(addr->data, &address, address_len); + addr->len = address_len; + + struct openssl_handle *openssl_handle; + openssl_handle = malloc(sizeof(*openssl_handle)); + if (!openssl_handle) + goto openssl_accept_free_addr_data; + + *handle = openssl_handle; + + openssl_handle->fd = con_fd; + + openssl_handle->ssl = SSL_new(openssl_ctx); + if (!openssl_handle->ssl) + goto openssl_accept_free_openssl_handle; + + SSL_set_fd(openssl_handle->ssl, con_fd); + + int res = mutex_init(&(openssl_handle->mutex)); + if (res != 0) + goto openssl_accept_free_ssl; + + struct pollfd pollfd = { + .fd = con_fd, + }; + do { + res = SSL_accept(openssl_handle->ssl); + if (res == 0) + goto openssl_accept_destroy_mutex; + if (res < 0) { + switch(SSL_get_error(openssl_handle->ssl, res)) { + case SSL_ERROR_WANT_READ: + pollfd.events = POLLIN; + break; + case SSL_ERROR_WANT_WRITE: + pollfd.events = POLLOUT; + break; + default: + goto openssl_accept_destroy_mutex; + } + } else { + break; + } + + res = poll(&pollfd, 1, PING_INTERVAL*1000); + if (res == 0) // Timeout + goto openssl_accept_destroy_mutex; + if (res == -1) { + if (errno != EINTR) { + continue; + } else { + goto openssl_accept_destroy_mutex; + } + } + if ((pollfd.revents & (POLLIN | POLLOUT)) == 0) // Only errors returned + goto openssl_accept_destroy_mutex; + } while (1); + + openssl_handle->valid = 1; + + return con_fd; + + openssl_accept_destroy_mutex: + mutex_destroy(&(openssl_handle->mutex)); + openssl_accept_free_ssl: + SSL_free(openssl_handle->ssl); + openssl_accept_free_openssl_handle: + free(openssl_handle); + openssl_accept_free_addr_data: + free(addr->data); + openssl_accept_close: + close(con_fd); + + return -1; +} + +void openssl_shutdown(void *handle) { + struct openssl_handle *openssl_handle = handle; + mutex_lock(&(openssl_handle->mutex)); + shutdown(openssl_handle->fd, SHUT_RDWR); + openssl_handle->valid = 0; + mutex_unlock(&(openssl_handle->mutex)); +} + +void openssl_close(int fd, void *handle) { + struct openssl_handle *openssl_handle = handle; + mutex_destroy(&(openssl_handle->mutex)); + SSL_free(openssl_handle->ssl); + free(openssl_handle); + close(fd); +} diff --git a/networks/openssl.h b/networks/openssl.h new file mode 100644 index 0000000..8c032f7 --- /dev/null +++ b/networks/openssl.h @@ -0,0 +1,45 @@ +// One of the headers for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include + +#include "../haxstring.h" +#include "../general_network.h" + +int init_openssl_network(void); + +int openssl_send(void *handle, struct string msg); +size_t openssl_recv(void *handle, char *data, size_t len, char *err); + +int openssl_connect(void **handle, struct string address, struct string port, struct string *addr_out); +int openssl_accept(int listen_fd, void **handle, struct string *addr); + +void openssl_shutdown(void *handle); +void openssl_close(int fd, void *handle); diff --git a/networks/plaintext.c b/networks/plaintext.c new file mode 100644 index 0000000..4279f8c --- /dev/null +++ b/networks/plaintext.c @@ -0,0 +1,173 @@ +// One of the code files for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "../general_network.h" +#include "../haxstring.h" +#include "plaintext.h" + +int init_plaintext_network(void) { + return 0; +} + +int plaintext_send(void *fd, struct string msg) { + while (msg.len > 0) { + ssize_t res; + do { + res = send(*((int*)fd), msg.data, msg.len, 0); + } while (res == -1 && (errno == EINTR)); + + if (res < 0 || (size_t)res > msg.len) { // res > len shouldn't be possible, but is still an error + plaintext_shutdown(fd); + return 1; + } else if (res > 0) { + msg.len -= (size_t)res; + msg.data += (size_t)res; + } + } + + return 0; +} + +size_t plaintext_recv(void *fd, char *data, size_t len, char *err) { + ssize_t res; + do { + res = recv(*((int*)fd), data, len, 0); + } while (res == -1 && (errno == EINTR)); + + if (res == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + *err = 1; + } else { + *err = 3; + } + return 0; + } else if (res == 0) { + *err = 2; + return 0; + } + *err = 0; + + return (size_t)res; +} + +int plaintext_connect(void **handle, struct string address, struct string port, struct string *addr_out) { + struct sockaddr sockaddr; + if (resolve(address, port, &sockaddr) != 0) + return -1; + + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + return -1; + + { + struct timeval timeout = { + .tv_sec = PING_INTERVAL, + .tv_usec = 0, + }; + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + } + + int res; + do { + res = connect(fd, &sockaddr, sizeof(sockaddr)); + } while (res < 0 && errno == EINTR); + if (res < 0) { + close(fd); + return -1; + } + + *handle = malloc(sizeof(fd)); + if (!handle) { + close(fd); + return -1; + } + *((int*)*handle) = fd; + + addr_out->data = malloc(sizeof(sockaddr)); + if (!addr_out->data) { + free(handle); + close(fd); + return -1; + } + memcpy(addr_out->data, &sockaddr, sizeof(sockaddr)); + addr_out->len = sizeof(sockaddr); + + return fd; +} + +int plaintext_accept(int listen_fd, void **handle, struct string *addr) { + struct sockaddr address; + socklen_t address_len = sizeof(address); + + int con_fd; + do { + con_fd = accept(listen_fd, &address, &address_len); + } while (con_fd == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)); + + if (con_fd == -1) + return -1; + + addr->data = malloc(address_len); + if (addr->data == 0 && address_len != 0) { + close(con_fd); + return -1; + } + + memcpy(addr->data, &address, address_len); + addr->len = address_len; + + *handle = malloc(sizeof(con_fd)); + if (!handle) { + free(addr->data); + close(con_fd); + return -1; + } + *((int*)*handle) = con_fd; + + return con_fd; +} + +void plaintext_shutdown(void *handle) { + shutdown(*((int*)handle), SHUT_RDWR); +} + +void plaintext_close(int fd, void *handle) { + free(handle); + close(fd); +} diff --git a/networks/plaintext.h b/networks/plaintext.h new file mode 100644 index 0000000..2cc390a --- /dev/null +++ b/networks/plaintext.h @@ -0,0 +1,45 @@ +// One of the headers for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include + +#include "../haxstring.h" +#include "../general_network.h" + +int init_plaintext_network(void); + +int plaintext_send(void *fd, struct string msg); +size_t plaintext_recv(void *fd, char *data, size_t len, char *err); + +int plaintext_connect(void **handle, struct string address, struct string port, struct string *addr_out); +int plaintext_accept(int listen_fd, void **handle, struct string *addr); + +void plaintext_shutdown(void *handle); +void plaintext_close(int fd, void *handle); diff --git a/networks/plaintext_buffered.c b/networks/plaintext_buffered.c new file mode 100644 index 0000000..97a6672 --- /dev/null +++ b/networks/plaintext_buffered.c @@ -0,0 +1,288 @@ +// One of the code files for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "../general_network.h" +#include "../haxstring.h" +#include "../main.h" +#include "../mutex.h" +#include "plaintext_buffered.h" + +struct plaintext_buffered_handle { + MUTEX_TYPE mutex; + int fd; + char valid; + char close; + char *buffer; + size_t write_buffer_index; + size_t buffer_len; +}; + +void * plaintext_buffered_send_thread(void *handle) { + struct plaintext_buffered_handle *info = handle; + + size_t read_buffer_index = 0; + mutex_lock(&(info->mutex)); + while (1) { + size_t len; + len = info->buffer_len; + mutex_unlock(&(info->mutex)); + if (read_buffer_index + len > PLAINTEXT_BUFFERED_LEN) + len = PLAINTEXT_BUFFERED_LEN - read_buffer_index; + + ssize_t res; + do { + res = send(info->fd, &(info->buffer[read_buffer_index]), len, 0); + } while (res == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == ETIMEDOUT)); + if (res < 0) + goto plaintext_buffered_send_thread_error; + + read_buffer_index += (size_t)res; + if (read_buffer_index >= PLAINTEXT_BUFFERED_LEN) + read_buffer_index = 0; + + mutex_lock(&(info->mutex)); + + info->buffer_len -= (size_t)res; + } + + plaintext_buffered_send_thread_error: + // TODO: Sane solution that works with ptread mutexes + while (1) { + mutex_lock(&(info->mutex)); + if (info->close) { + close(info->fd); + free(info->buffer); + mutex_unlock(&(info->mutex)); + mutex_destroy(&(info->mutex)); + free(info); + return 0; + } + mutex_unlock(&(info->mutex)); + } + + return 0; +} + +int init_plaintext_buffered_network(void) { + return 0; +} + +int plaintext_buffered_send(void *handle, struct string msg) { + struct plaintext_buffered_handle *plaintext_handle = handle; + while (msg.len > 0) { + size_t len = msg.len; + if (len > PLAINTEXT_BUFFERED_LEN - plaintext_handle->write_buffer_index) + len = PLAINTEXT_BUFFERED_LEN - plaintext_handle->write_buffer_index; + mutex_lock(&(plaintext_handle->mutex)); + if (!plaintext_handle->valid) + return 1; + if (len > PLAINTEXT_BUFFERED_LEN - plaintext_handle->buffer_len) + len = PLAINTEXT_BUFFERED_LEN - plaintext_handle->buffer_len; + memcpy(&(plaintext_handle->buffer[plaintext_handle->write_buffer_index]), msg.data, len); + plaintext_handle->write_buffer_index += len; + if (plaintext_handle->write_buffer_index >= PLAINTEXT_BUFFERED_LEN) + plaintext_handle->write_buffer_index = 0; + plaintext_handle->buffer_len += len; + mutex_unlock(&(plaintext_handle->mutex)); + msg.len -= len; + } + + return 0; +} + +size_t plaintext_buffered_recv(void *handle, char *data, size_t len, char *err) { + struct plaintext_buffered_handle *plaintext_handle = handle; + ssize_t res; + do { + res = recv(plaintext_handle->fd, data, len, 0); + } while (res == -1 && (errno == EINTR)); + + if (res == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + *err = 1; + } else { + *err = 3; + } + return 0; + } else if (res == 0) { + *err = 2; + return 0; + } + *err = 0; + + return (size_t)res; +} + +int plaintext_buffered_connect(void **handle, struct string address, struct string port, struct string *addr_out) { + struct sockaddr sockaddr; + if (resolve(address, port, &sockaddr) != 0) + return -1; + + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + return -1; + + { + struct timeval timeout = { + .tv_sec = PING_INTERVAL, + .tv_usec = 0, + }; + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + } + + int res; + do { + res = connect(fd, &sockaddr, sizeof(sockaddr)); + } while (res < 0 && errno == EINTR); + if (res < 0) + goto plaintext_buffered_connect_close; + + struct plaintext_buffered_handle *plaintext_handle; + plaintext_handle = malloc(sizeof(*plaintext_handle)); + if (!handle) + goto plaintext_buffered_connect_close; + *handle = plaintext_handle; + plaintext_handle->valid = 1; + plaintext_handle->fd = fd; + + addr_out->data = malloc(sizeof(sockaddr)); + if (!addr_out->data) + goto plaintext_buffered_connect_free_handle; + memcpy(addr_out->data, &sockaddr, sizeof(sockaddr)); + addr_out->len = sizeof(sockaddr); + + plaintext_handle->buffer = malloc(PLAINTEXT_BUFFERED_LEN); + if (!plaintext_handle->buffer) + goto plaintext_buffered_connect_free_addr; + plaintext_handle->write_buffer_index = 0; + plaintext_handle->buffer_len = 0; + + if (mutex_init(&(plaintext_handle->mutex)) != 0) + goto plaintext_buffered_connect_free_buffer; + + pthread_t trash; + if (pthread_create(&trash, &pthread_attr, plaintext_buffered_send_thread, plaintext_handle) != 0) + goto plaintext_buffered_connect_destroy_mutex; + + return fd; + + plaintext_buffered_connect_destroy_mutex: + mutex_destroy(&(plaintext_handle->mutex)); + plaintext_buffered_connect_free_buffer: + free(plaintext_handle->buffer); + plaintext_buffered_connect_free_addr: + free(addr_out->data); + plaintext_buffered_connect_free_handle: + free(plaintext_handle); + plaintext_buffered_connect_close: + close(fd); + + return -1; +} + +int plaintext_buffered_accept(int listen_fd, void **handle, struct string *addr) { + struct sockaddr address; + socklen_t address_len = sizeof(address); + + int con_fd; + do { + con_fd = accept(listen_fd, &address, &address_len); + } while (con_fd == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)); + + if (con_fd == -1) + return -1; + + struct plaintext_buffered_handle *plaintext_handle = malloc(sizeof(*plaintext_handle)); + if (!plaintext_handle) + goto plaintext_buffered_accept_close; + *handle = plaintext_handle; + plaintext_handle->valid = 1; + plaintext_handle->close = 1; + plaintext_handle->fd = con_fd; + + addr->data = malloc(address_len); + if (addr->data == 0 && address_len != 0) + goto plaintext_buffered_accept_free_handle; + memcpy(addr->data, &address, address_len); + addr->len = address_len; + + + plaintext_handle->buffer = malloc(PLAINTEXT_BUFFERED_LEN); + if (!plaintext_handle->buffer) + goto plaintext_buffered_accept_free_addr; + plaintext_handle->write_buffer_index = 0; + plaintext_handle->buffer_len = 0; + + if (mutex_init(&(plaintext_handle->mutex)) != 0) + goto plaintext_buffered_accept_free_buffer; + + pthread_t trash; + if (pthread_create(&trash, &pthread_attr, plaintext_buffered_send_thread, plaintext_handle) != 0) + goto plaintext_buffered_accept_destroy_mutex; + + return con_fd; + + plaintext_buffered_accept_destroy_mutex: + mutex_destroy(&(plaintext_handle->mutex)); + plaintext_buffered_accept_free_buffer: + free(plaintext_handle->buffer); + plaintext_buffered_accept_free_addr: + free(addr->data); + plaintext_buffered_accept_free_handle: + free(plaintext_handle); + plaintext_buffered_accept_close: + close(con_fd); + + return -1; +} + +void plaintext_buffered_shutdown(void *handle) { + struct plaintext_buffered_handle *plaintext_handle = handle; + mutex_lock(&(plaintext_handle->mutex)); + plaintext_handle->valid = 0; + mutex_unlock(&(plaintext_handle->mutex)); + shutdown(plaintext_handle->fd, SHUT_RDWR); +} + +void plaintext_buffered_close(int fd, void *handle) { + struct plaintext_buffered_handle *plaintext_handle = handle; + mutex_lock(&(plaintext_handle->mutex)); + plaintext_handle->close = 1; + mutex_unlock(&(plaintext_handle->mutex)); +} diff --git a/networks/plaintext_buffered.h b/networks/plaintext_buffered.h new file mode 100644 index 0000000..dbe591f --- /dev/null +++ b/networks/plaintext_buffered.h @@ -0,0 +1,45 @@ +// One of the headers for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include + +#include "../haxstring.h" +#include "../general_network.h" + +int init_plaintext_buffered_network(void); + +int plaintext_buffered_send(void *fd, struct string msg); +size_t plaintext_buffered_recv(void *fd, char *data, size_t len, char *err); + +int plaintext_buffered_connect(void **handle, struct string address, struct string port, struct string *addr_out); +int plaintext_buffered_accept(int listen_fd, void **handle, struct string *addr); + +void plaintext_buffered_shutdown(void *handle); +void plaintext_buffered_close(int fd, void *handle); -- cgit v1.2.3