AmendHub

Download:

cyberslak

/

lightsout

/

amendments

/

5

net: make most functions return an error code, add connection timeouts


cyberslak made amendment 5 25 days ago
--- net.c Mon Mar 3 04:28:16 2025 +++ net.c Sat Mar 8 23:42:12 2025 @@ -4,26 +4,34 @@ #include "net.h" #include "util.h" #include "dbuf.h" -#include "cJSON.h" #define OT_CHECK(x) \ { \ OTResult _m_res = (x); \ if (_m_res < 0) \ - die("OT Error at %s:%d: %d", \ + die("OT Error at %s:%d: %ld", \ __FILE__, __LINE__, _m_res); \ } \ +#define kConnectionTimeoutSecs 2 + static bool gOTInited = false; static InetSvcRef inet_svcs; +static OTResult SetFourByteOption(EndpointRef ep, + OTXTILevel level, OTXTIName name, UInt32 value); + /* Look up the IPv4 address of a given host using DNS. */ -static InetHost net_dns_lookup(const char* hostname) +short net_dns_lookup(const char* hostname, InetHost *host) { InetHostInfo hi; + memset(&hi, 0, sizeof(InetHostInfo)); - OT_CHECK(OTInetStringToAddress(inet_svcs, (char*)hostname, &hi)); - return hi.addrs[0]; + if (OTInetStringToAddress(inet_svcs, (char*)hostname, &hi) < 0) + return -1; + + *host = hi.addrs[0]; + return 0; } void net_init() @@ -56,6 +64,13 @@ EndpointRef net_create_endpoint() OT_CHECK(OTBind(ep, nil, nil)); OT_CHECK(OTSetNonBlocking(ep)); + /* Set reasonable connection timeout (2s) */ + + OT_CHECK(SetFourByteOption(ep, INET_TCP, TCP_CONN_ABORT_THRESHOLD, + kConnectionTimeoutSecs * 1000)); + OT_CHECK(SetFourByteOption(ep, INET_TCP, TCP_CONN_NOTIFY_THRESHOLD, + (kConnectionTimeoutSecs * 1000 / 2))); + return ep; } @@ -94,8 +109,11 @@ EndpointRef net_connect(const char* hostname, short po EndpointRef ep = net_create_endpoint(); TCall connectCall; InetAddress addr; - InetHost host = net_dns_lookup(hostname); + InetHost host; + if (net_dns_lookup(hostname, &host) < 0) + goto fail; + OTInitInetAddress(&addr, port, host); OTMemzero(&connectCall, sizeof(TCall)); @@ -103,9 +121,14 @@ EndpointRef net_connect(const char* hostname, short po connectCall.addr.buf = (unsigned char*)&addr; connectCall.addr.len = sizeof(InetAddress); - OT_CHECK(OTConnect(ep, &connectCall, nil)); + if (OTConnect(ep, &connectCall, nil) < 0) + goto fail; return ep; + +fail: + OTCloseProvider(ep); + return NULL; } EndpointRef @@ -123,6 +146,8 @@ net_socks_connect( OTFlags flags; ep = net_connect(proxy_host, proxy_port); + if (!ep) + return NULL; if (host_len > 253) die("invalid host %s; too long!", host); @@ -178,9 +203,14 @@ static void net_recv_response(EndpointRef ep, struct d else if (readable == 0) { res = OTRcv(ep, tmpBuf, sizeof(tmpBuf), &flags); + if (res < 0) + die("readable socket returned error on read? %ld", res); db_extend(db, (u8*)tmpBuf, res); } } + + // null-terminate response + db_extend(db, (u8*)"\0", 1); } struct dbuf net_post(EndpointRef ep, const char* path, const char* token, const char* content) @@ -231,20 +261,81 @@ char* net_http_response_content(const char* response) { char* s = strstr(response, "\r\n\r\n"); if (!s) - die("malformed http response?"); + return NULL; return s + 4; } -void net_test_socks() +short net_test_socks() { EndpointRef ep = net_socks_connect("192.168.1.187", 1080, "httpbin.org", 443); struct dbuf respBuf; + if (!ep) + return -1; + respBuf = net_get(ep, "/uuid", ""); info("%s", respBuf.buf); db_destroy(&respBuf); OTCloseProvider(ep); +} + +/* Taken from the OT sample code here: + * https://lists.apple.com/archives/macnetworkprog/2004/Jan/msg00145.html + */ +static OTResult SetFourByteOption(EndpointRef ep, + OTXTILevel level, OTXTIName name, UInt32 value) +// level and name must denote a four byte option that is +// appropriate for the endpoint ep. This routine sets the +// option to value. ep is assumed to be in synchronous +// mode. +// +// If all goes well, the result is noErr. If an error +// occurs, the result is negative. If the option could not +// be negotiated, a positive result being one of (T_FAILURE, +// T_PARTSUCCESS, T_READONLY, T_NOTSUPPORT) is returned +{ + OTResult err; + TOption option; + TOptMgmt request; + TOptMgmt result; + // Set up the option buffer to reflect the specific option + // and value we want to set. We use a TOption structure + // to represent the option buffer. TOption is specifically + // defined to allow easy construction of 4 byte options. + // If you want to negotiate different size options, or + // multiple options in a single call, then constructing + // the option buffer is a little trickier + option.len = kOTFourByteOptionSize; + option.level = level; + option.name = name; + option.status = 0; + option.value[0] = value; + + // Set up the request for OTOptionManagement to point + // to the option buffer we just filled out, and tell + // it that we want to negotiate (ie set) the option. + request.opt.buf = (UInt8 *) &option; + request.opt.len = sizeof(option); + request.flags = T_NEGOTIATE; + + // Set up the reply for OTOptionManagement. This is where + // OTOptionManagement puts the result of the negotiation. + result.opt.buf = (UInt8 *) &option; + result.opt.maxlen = sizeof(option); + + // Call OTOptionManagement and then check that the value + // was negotiated successfully. Any value other than + // T_SUCCESS is reported via the error result. + err = OTOptionManagement(ep, &request, &result); + + if (err == noErr) { + if (option.status != T_SUCCESS) { + err = option.status; + } + } + + return (err); } void net_fini() --- net.h Mon Mar 3 04:13:49 2025 +++ net.h Sat Mar 8 20:54:32 2025 @@ -9,17 +9,27 @@ void net_fini(); // DNS -/* Resolve a hostname via DNS. */ -InetHost net_dns_lookup(const char* hostname); +/** Resolve a hostname via DNS. + * + * If resolution fails, returns -1, otherwise 0. + */ +short net_dns_lookup(const char* hostname, InetHost* host); // CONNECTION -/* Create a new synchronous, non-blocking - * client endpoint using TCP/IP. */ +/** Create a new synchronous, non-blocking + * client endpoint using TCP/IP. + * + * Failure is fatal - presumably, if we cannot create an endpoint, + * there is no TCP network connectivity at all. + */ EndpointRef net_create_endpoint(); -/* Connect an endpoint to a host-port combination. */ +/* Connect an endpoint to a host-port combination. + * + * On failure, returns NULL. + */ EndpointRef net_connect(const char* host, short port); /* Connect an endpoint to a host, proxying @@ -36,8 +46,9 @@ EndpointRef net_socks_connect( * returns 0. If the endpoint is closed, returns -1. */ short net_wait_readable(EndpointRef ep); + /* Send an HTTP POST request to the given path with the - * given content. Returns the reply as a malloc'ed struct dbuf. + * given content. Returns the reply as a struct dbuf. * The caller is responsible for freeing the result. */ struct dbuf net_post( EndpointRef ep, const char* path, @@ -45,13 +56,17 @@ struct dbuf net_post( /* Send an HTTP GET request to the given path. - * Returns the reply as a malloc'ed struct dbuf. + * Returns the reply as a struct dbuf. * The caller is responsible for freeing the result. */ struct dbuf net_get( EndpointRef ep, const char* path, const char* token); -/* Get a pointer to the content in an HTTP response. */ +/* Get a pointer to the content in an HTTP response. + * Assumes a properly formatted HTTP response (i.e. + * CRLF line endings, ...). If the response does not + * contain CRLFCRLF, returns NULL. + */ char* net_http_response_content(const char* response); -void net_test_socks(); +short net_test_socks();