diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-05-04 10:42:22 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2017-05-04 10:42:22 -0700 |
commit | 54c47a1e03b5a7446315fc2cff64fb93fd85c5b7 (patch) | |
tree | 9298a528541fe19c7de8ac086da0b6b39b319757 /attic/historic/anode/libanode/anode.h | |
parent | 6bb855873d98309cf7ae9ed117615638366e5d8b (diff) | |
download | infinitytier-54c47a1e03b5a7446315fc2cff64fb93fd85c5b7.tar.gz infinitytier-54c47a1e03b5a7446315fc2cff64fb93fd85c5b7.zip |
Add some historic code just for the heck of it.
Diffstat (limited to 'attic/historic/anode/libanode/anode.h')
-rw-r--r-- | attic/historic/anode/libanode/anode.h | 795 |
1 files changed, 795 insertions, 0 deletions
diff --git a/attic/historic/anode/libanode/anode.h b/attic/historic/anode/libanode/anode.h new file mode 100644 index 00000000..e0c51e2e --- /dev/null +++ b/attic/historic/anode/libanode/anode.h @@ -0,0 +1,795 @@ +/* libanode: the Anode C reference implementation + * Copyright (C) 2009-2010 Adam Ierymenko <adam.ierymenko@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _ANODE_ANODE_H +#define _ANODE_ANODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define ANODE_ADDRESS_LENGTH_ANODE_256_40 40 +#define ANODE_ADDRESS_MAX_LENGTH 40 +#define ANODE_ADDRESS_SECRET_LENGTH_ANODE_256_40 32 +#define ANODE_ADDRESS_MAX_SECRET_LENGTH 32 + +#define ANODE_ADDRESS_ID_LENGTH 8 +#define ANODE_ZONE_LENGTH 4 + +#define ANODE_ERR_NONE 0 +#define ANODE_ERR_INVALID_ARGUMENT (-10000) +#define ANODE_ERR_OUT_OF_MEMORY (-10001) +#define ANODE_ERR_INVALID_URI (-10002) +#define ANODE_ERR_BUFFER_TOO_SMALL (-10003) +#define ANODE_ERR_ADDRESS_INVALID (-10010) +#define ANODE_ERR_ADDRESS_TYPE_NOT_SUPPORTED (-10011) +#define ANODE_ERR_CONNECTION_CLOSED (-10012) +#define ANODE_ERR_CONNECTION_CLOSED_BY_REMOTE (-10013) +#define ANODE_ERR_CONNECT_FAILED (-10014) +#define ANODE_ERR_UNABLE_TO_BIND (-10015) +#define ANODE_ERR_TOO_MANY_OPEN_SOCKETS (-10016) +#define ANODE_ERR_DNS_NAME_NOT_FOUND_OR_TIMED_OUT (-10017) + +/** + * Get a human-readable error description for an error code + * + * The value of 'err' can be either negative or positive. + * + * @param err Error code + * @return Human-readable description + */ +extern const char *Anode_strerror(int err); + +/* ----------------------------------------------------------------------- */ +/* Secure random source */ +/* ----------------------------------------------------------------------- */ + +/** + * Opaque secure random instance + */ +typedef void AnodeSecureRandom; + +/** + * Initialize a secure random source + * + * No cleanup/destructor is necessary. + * + * @param srng Random structure to initialize + */ +extern AnodeSecureRandom *AnodeSecureRandom_new(); + +/** + * Generate random bytes + * + * @param srng Secure random source + * @param buf Buffer to fill + * @param count Number of bytes to generate + */ +extern void AnodeSecureRandom_gen_bytes(AnodeSecureRandom *srng,void *buf,long count); + +/** + * Destroy and free a secure random instance + * + * @param srng Secure random source + */ +extern void AnodeSecureRandom_delete(AnodeSecureRandom *srng); + +/* ----------------------------------------------------------------------- */ +/* AES-256 derived Davis-Meyer hash function */ +/* ----------------------------------------------------------------------- */ + +/** + * Digest a message using AES-DIGEST to yield a 16-byte hash code + * + * @param message Message to digest + * @param message_len Length of message in bytes + * @param hash Buffer to store 16 byte hash code + */ +extern void Anode_aes_digest( + const void *const message, + unsigned long message_len, + void *const hash); + +/* ----------------------------------------------------------------------- */ +/* Address Types and Components */ +/* ----------------------------------------------------------------------- */ + +/** + * Anode address + * + * The first byte always identifies the address type, which right now can + * only be type 1 (ANODE-256-40). + */ +typedef struct +{ + char bits[ANODE_ADDRESS_MAX_LENGTH]; +} AnodeAddress; + +/** + * 8-byte short Anode address ID + */ +typedef struct +{ + char bits[ANODE_ADDRESS_ID_LENGTH]; +} AnodeAddressId; + +/** + * 4-byte Anode zone ID + */ +typedef struct +{ + char bits[ANODE_ZONE_LENGTH]; +} AnodeZone; + +/** + * Anode address types + */ +enum AnodeAddressType +{ + ANODE_ADDRESS_ANODE_256_40 = 1 +}; + +/** + * Get the type of an Anode address + * + * This is a shortcut macro for just looking at the first byte and casting + * it to the AnodeAddressType enum. + * + * @param a Pointer to address + * @return Type as enum AnodeAddressType + */ +#define AnodeAddress_get_type(a) ((enum AnodeAddressType)((a)->bits[0])) + +/** + * Calculate the short 8 byte address ID from an address + * + * @param address Binary address + * @param short_address_id Buffer to store 8-byte short address ID + * @return 0 on success or error code on failure + */ +extern int AnodeAddress_calc_short_id( + const AnodeAddress *address, + AnodeAddressId *short_address_id); + +/** + * Extract the zone from an anode address + * + * @param address Binary address + * @param zone Zone value-result parameter to fill on success + * @return 0 on success or error code on failure + */ +extern int AnodeAddress_get_zone(const AnodeAddress *address,AnodeZone *zone); + +/** + * Convert an address to an ASCII string + * + * Anode addresses are 64 characters in ASCII form, so the buffer should + * have 65 bytes of space. + * + * @param address Address to convert + * @param buf Buffer to receive address in string form (should have 65 bytes of space) + * @param len Length of buffer + * @return Length of resulting string or a negative error code on error + */ +extern int AnodeAddress_to_string(const AnodeAddress *address,char *buf,int len); + +/** + * Convert a string into an address + * + * @param str Address in string form + * @param address Address buffer to receive result + * @return Zero on sucess or error code on error + */ +extern int AnodeAddress_from_string(const char *str,AnodeAddress *address); + +/** + * Supported network address types + */ +enum AnodeNetworkAddressType +{ + ANODE_NETWORK_ADDRESS_IPV4 = 0, + ANODE_NETWORK_ADDRESS_IPV6 = 1, + ANODE_NETWORK_ADDRESS_ETHERNET = 2, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_USB = 3, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_BLUETOOTH = 4, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_IPC = 5, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_80211S = 6, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_SERIAL = 7, /* reserved but unused */ + ANODE_NETWORK_ADDRESS_ANODE_256_40 = 8 +}; + +/** + * Anode network address + * + * This can contain an address of any type: IPv4, IPv6, or Anode, and is used + * with the common transport API. + * + * The length of the address stored in bits[] is determined by the type. + */ +typedef struct +{ + enum AnodeNetworkAddressType type; + char bits[ANODE_ADDRESS_MAX_LENGTH]; +} AnodeNetworkAddress; + +/** + * An endpoint with an address and a port + */ +typedef struct +{ + AnodeNetworkAddress address; + int port; +} AnodeNetworkEndpoint; + +/* Constants for binding to any address (v4 or v6) */ +extern const AnodeNetworkAddress AnodeNetworkAddress_IP_ANY_V4; +extern const AnodeNetworkAddress AnodeNetworkAddress_IP_ANY_V6; + +/* Local host address in v4 and v6 */ +extern const AnodeNetworkAddress AnodeNetworkAddress_IP_LOCAL_V4; +extern const AnodeNetworkAddress AnodeNetworkAddress_IP_LOCAL_V6; + +/** + * Convert a network address to an ASCII string + * + * The buffer must have room for a 15 character string for IPv4, a 40 byte + * string for IPv6, and a 64 byte string for Anode addresses. This does not + * include the trailing null. + * + * @param address Address to convert + * @param buf Buffer to receive address in string form + * @param len Length of buffer + * @return Length of resulting string or a negative error code on error + */ +extern int AnodeNetworkAddress_to_string(const AnodeNetworkAddress *address,char *buf,int len); + +/** + * Convert a string into a network address of the correct type + * + * @param str Address in string form + * @param address Address buffer to receive result + * @return Zero on sucess or error code on error + */ +extern int AnodeNetworkAddress_from_string(const char *str,AnodeNetworkAddress *address); + +/** + * Fill a network endpoint from a C-API sockaddr structure + * + * The argument must be struct sockaddr_in for IPv4 or sockaddr_in6 for IPv6. + * The common sin_family field will be used to differentiate. + * + * @param sockaddr Pointer to proper sockaddr structure + * @param endpoint Endpoint structure to fill + * @return Zero on success or error on failure + */ +extern int AnodeNetworkEndpoint_from_sockaddr(const void *sockaddr,AnodeNetworkEndpoint *endpoint); + +/** + * Fill a sockaddr from a network endpoint + * + * To support either IPv4 or IPv6 addresses, there is a sockaddr_storage + * structure in most C APIs. If you supply anything other than an IP address + * such as an Anode address, this will return an error. + * + * @param endpoint Endpoint structure to convert + * @param sockaddr Sockaddr structure storage + * @param sockaddr_len Length of sockaddr structure storage in bytes + * @return Zero on success or error on failure + */ +extern int AnodeNetworkEndpoint_to_sockaddr(const AnodeNetworkEndpoint *endpoint,void *sockaddr,int sockaddr_len); + +/* ----------------------------------------------------------------------- */ +/* Identity Generation and Management */ +/* ----------------------------------------------------------------------- */ + +/** + * Anode identity structure containing address and secret key + * + * This structure is memcpy-safe, and its members are accessible. + */ +typedef struct +{ + /* The public Anode address */ + AnodeAddress address; + + /* Short address ID */ + AnodeAddressId address_id; + + /* The secret key corresponding with the public address */ + /* Secret length is determined by address type */ + char secret[ANODE_ADDRESS_MAX_SECRET_LENGTH]; +} AnodeIdentity; + +/** + * Generate a new identity + * + * This generates a public/private key pair and from that generates an + * identity containing an address and a secret key. + * + * @param identity Destination structure to store new identity + * @param zone Zone ID + * @param type Type of identity to generate + * @return Zero on success, error on failure + */ +extern int AnodeIdentity_generate( + AnodeIdentity *identity, + const AnodeZone *zone, + enum AnodeAddressType type); + +/** + * Convert an Anode identity to a string representation + * + * @param identity Identity to convert + * @param dest String buffer + * @param dest_len Length of string buffer + * @return Length of string created or negative error code on failure + */ +extern int AnodeIdentity_to_string( + const AnodeIdentity *identity, + char *dest, + int dest_len); + +/** + * Convert a string representation to an Anode identity structure + * + * @param identity Destination structure to fill + * @param str C-string containing string representation + * @return Zero on success or negative error code on failure + */ +extern int AnodeIdentity_from_string( + AnodeIdentity *identity, + const char *str); + +/* ----------------------------------------------------------------------- */ +/* Transport API */ +/* ----------------------------------------------------------------------- */ + +struct _AnodeTransport; +typedef struct _AnodeTransport AnodeTransport; +struct _AnodeEvent; +typedef struct _AnodeEvent AnodeEvent; + +/** + * Anode socket + */ +typedef struct +{ + /* Type of socket (read-only) */ + enum { + ANODE_SOCKET_DATAGRAM = 1, + ANODE_SOCKET_STREAM_LISTEN = 2, + ANODE_SOCKET_STREAM_CONNECTION = 3 + } type; + + /* Socket state */ + enum { + ANODE_SOCKET_CLOSED = 0, + ANODE_SOCKET_OPEN = 1, + ANODE_SOCKET_CONNECTING = 2, + } state; + + /* Local address or remote address for stream connections (read-only) */ + AnodeNetworkEndpoint endpoint; + + /* Name of owning class (read-only) */ + const char *class_name; + + /* Pointers for end user use (writable) */ + void *user_ptr[2]; + + /* Special handler to receive events or null for default (writable) */ + void (*event_handler)(const AnodeEvent *event); +} AnodeSocket; + +/** + * Anode transport I/O event + */ +struct _AnodeEvent +{ + enum { + ANODE_TRANSPORT_EVENT_DATAGRAM_RECEIVED = 1, + ANODE_TRANSPORT_EVENT_STREAM_INCOMING_CONNECT = 2, + ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_ESTABLISHED = 3, + ANODE_TRANSPORT_EVENT_STREAM_OUTGOING_CONNECT_FAILED = 4, + ANODE_TRANSPORT_EVENT_STREAM_CLOSED = 5, + ANODE_TRANSPORT_EVENT_STREAM_DATA_RECEIVED = 6, + ANODE_TRANSPORT_EVENT_STREAM_AVAILABLE_FOR_WRITE = 7, + ANODE_TRANSPORT_EVENT_DNS_RESULT = 8 + } type; + + AnodeTransport *transport; + + /* Anode socket corresponding to this event */ + AnodeSocket *sock; + + /* Originating endpoint for incoming datagrams */ + AnodeNetworkEndpoint *datagram_from; + + /* DNS lookup results */ + const char *dns_name; + AnodeNetworkAddress *dns_addresses; + int dns_address_count; + + /* Error code or 0 for none */ + int error_code; + + /* Data for incoming datagrams and stream received events */ + int data_length; + char *data; +}; + +/** + * Enum used for dns_resolve method in transport to specify query rules + * + * This can be specified for ipv4, ipv6, and Anode address types to tell the + * DNS resolver when to bother querying for addresses of the given type. + * NEVER means to never query for this type, and ALWAYS means to always + * query. IF_NO_PREVIOUS means to query for this type if no addresses were + * found in previous queries. Addresses are queried in the order of ipv4, + * ipv6, then Anode, so if you specify IF_NO_PREVIOUS for all three you will + * get addresses in that order of priority. + */ +enum AnodeTransportDnsIncludeMode +{ + ANODE_TRANSPORT_DNS_QUERY_NEVER = 0, + ANODE_TRANSPORT_DNS_QUERY_ALWAYS = 1, + ANODE_TRANSPORT_DNS_QUERY_IF_NO_PREVIOUS = 2 +}; + +struct _AnodeTransport +{ + /** + * Set the default event handler + * + * @param transport Transport engine + * @param event_handler Default event handler + */ + void (*set_default_event_handler)(AnodeTransport *transport, + void (*event_handler)(const AnodeEvent *event)); + + /** + * Enqueue a function to be executed during a subsequent call to poll() + * + * This can be called from other threads, so it can be used to pass a + * message to the I/O thread in multithreaded applications. + * + * If it is called from the same thread, the function is still queued to be + * run later rather than being run instantly. + * + * The order in which invoked functions are called is undefined. + * + * @param transport Transport engine + * @param ptr Arbitrary pointer to pass to function to be called + * @param func Function to be called + */ + void (*invoke)(AnodeTransport *transport, + void *ptr, + void (*func)(void *)); + + /** + * Initiate a forward DNS query + * + * @param transport Transport instance + * @param name DNS name to query + * @param event_handler Event handler or null for default event path + * @param ipv4_include_mode Inclusion mode for IPv4 addresses + * @param ipv6_include_mode Inclusion mode for IPv6 addresses + * @param anode_include_mode Inclusion mode for Anode addresses + */ + void (*dns_resolve)(AnodeTransport *transport, + const char *name, + void (*event_handler)(const AnodeEvent *), + enum AnodeTransportDnsIncludeMode ipv4_include_mode, + enum AnodeTransportDnsIncludeMode ipv6_include_mode, + enum AnodeTransportDnsIncludeMode anode_include_mode); + + /** + * Open a datagram socket + * + * @param transport Transport instance + * @param local_address Local address to bind + * @param local_port Local port to bind + * @param error_code Value-result parameter to receive error code on error + * @return Listen socket or null if error (check error_code in error case) + */ + AnodeSocket *(*datagram_listen)(AnodeTransport *transport, + const AnodeNetworkAddress *local_address, + int local_port, + int *error_code); + + /** + * Open a socket to listen for incoming stream connections + * + * @param transport Transport instance + * @param local_address Local address to bind + * @param local_port Local port to bind + * @param error_code Value-result parameter to receive error code on error + * @return Listen socket or null if error (check error_code in error case) + */ + AnodeSocket *(*stream_listen)(AnodeTransport *transport, + const AnodeNetworkAddress *local_address, + int local_port, + int *error_code); + + /** + * Send a datagram to a network endpoint + * + * @param transport Transport instance + * @param socket Originating datagram socket + * @param data Data to send + * @param data_len Length of data to send + * @param to_endpoint Destination endpoint + * @return Zero on success or error code on error + */ + int (*datagram_send)(AnodeTransport *transport, + AnodeSocket *sock, + const void *data, + int data_len, + const AnodeNetworkEndpoint *to_endpoint); + + /** + * Initiate an outgoing stream connection attempt + * + * For IPv4 and IPv6 addresses, this will initiate a TCP connection. For + * Anode addresses, Anode's internal streaming protocol will be used. + * + * @param transport Transport instance + * @param to_endpoint Destination endpoint + * @param error_code Error code value-result parameter, filled on error + * @return Stream socket object or null on error (check error_code) + */ + AnodeSocket *(*stream_connect)(AnodeTransport *transport, + const AnodeNetworkEndpoint *to_endpoint, + int *error_code); + + /** + * Indicate that you are interested in writing to a stream + * + * This does nothing if the socket is not a stream connection or is not + * connected. + * + * @param transport Transport instance + * @param sock Stream connection + */ + void (*stream_start_writing)(AnodeTransport *transport, + AnodeSocket *sock); + + /** + * Indicate that you are no longer interested in writing to a stream + * + * This does nothing if the socket is not a stream connection or is not + * connected. + * + * @param transport Transport instance + * @param sock Stream connection + */ + void (*stream_stop_writing)(AnodeTransport *transport, + AnodeSocket *sock); + + /** + * Send data to a stream connection + * + * This must be called after a stream is indicated to be ready for writing. + * It returns the number of bytes actually written, or a negative error + * code on failure. + * + * A return value of zero can occur here, and simply indicates that nothing + * was sent. This may occur with certain network stacks on certain + * platforms. + * + * @param transport Transport engine + * @param sock Stream socket + * @param data Data to send + * @param data_len Maximum data to send in bytes + * @return Actual data sent or negative error code on error + */ + int (*stream_send)(AnodeTransport *transport, + AnodeSocket *sock, + const void *data, + int data_len); + + /** + * Close a socket + * + * If the socket is a stream connection in the connected state, this + * will generate a stream closed event with a zero error_code to indicate + * a normal close. + * + * @param transport Transport engine + * @param sock Socket object + */ + void (*close)(AnodeTransport *transport, + AnodeSocket *sock); + + /** + * Run main polling loop + * + * This should be called repeatedly from the I/O thread of your main + * process. It blocks until one or more events occur, and then returns + * the number of events. Error returns here are fatal and indicate + * serious problems such as build or platform issues or a lack of any + * network interface. + * + * Functions queued with invoke() are also called inside here. + * + * @param transport Transport engine + * @return Number of events handled or negative on (fatal) error + */ + int (*poll)(AnodeTransport *transport); + + /** + * Check whether transport supports an address type + * + * Inheriting classes should call their base if they do not natively + * speak the specified type. + * + * @param transport Transport engine + * @param at Address type + * @return Nonzero if true + */ + int (*supports_address_type)(const AnodeTransport *transport, + enum AnodeNetworkAddressType at); + + /** + * Get the instance of AnodeTransport under this one (if any) + * + * @param transport Transport engine + * @return Base instance or null if none + */ + AnodeTransport *(*base_instance)(const AnodeTransport *transport); + + /** + * @param transport Transport engine + * @return Class name of this instance + */ + const char *(*class_name)(AnodeTransport *transport); + + /** + * Delete this transport and its base transports + * + * The 'transport' pointer and any streams or sockets it owns are no longer + * valid after this call. + * + * @param transport Transport engine + */ + void (*delete)(AnodeTransport *transport); +}; + +/** + * Construct a new system transport + * + * This is the default base for AnodeTransport, and it is constructed + * automatically if 'base' is null in AnodeTransport_new(). However, it also + * exposed to the user so that specialized transports (such as those that use + * proxy servers) can be developed on top of it. These in turn can be supplied + * as 'base' to AnodeTransport_new() to talk Anode over these transports. + * + * The system transport supports IP protocols and possibly others. + * + * @param base Base class or null for none (usually null) + * @return Base transport engine instance + */ +extern AnodeTransport *AnodeSystemTransport_new(AnodeTransport *base); + +/** + * Construct a new Anode core transport + * + * This is the transport that talks Anode using the specified base transport. + * Requests for other address types are passed through to the base. If the + * base is null, an instance of AnodeSystemTransport is used. + * + * Since transport engines inherit their functionality, this transport + * will also do standard IP and everything else that the system transport + * supports. Most users will just want to construct this with a null base. + * + * @param base Base transport to use, or null to use SystemTransport + * @return Anode transport engine or null on error + */ +extern AnodeTransport *AnodeCoreTransport_new(AnodeTransport *base); + +/* ----------------------------------------------------------------------- */ +/* URI Parser */ +/* ----------------------------------------------------------------------- */ + +/** + * URI broken down by component + */ +typedef struct +{ + char scheme[8]; + char username[64]; + char password[64]; + char host[128]; + char path[256]; + char query[256]; + char fragment[64]; + int port; +} AnodeURI; + +/** + * URI parser + * + * A buffer too small error will occur if any field is too large for the + * AnodeURI structure. + * + * @param parsed_uri Structure to fill with parsed URI data + * @param uri_string URI in string format + * @return Zero on success or error on failure + */ +extern int AnodeURI_parse(AnodeURI *parsed_uri,const char *uri_string); + +/** + * Output a URI in string format + * + * @param uri URI to output as string + * @param buf Buffer to store URI string + * @param len Length of buffer + * @return Buffer or null on error + */ +extern char *AnodeURI_to_string(const AnodeURI *uri,char *buf,int len); + +/* ----------------------------------------------------------------------- */ +/* Zone File Lookup and Dictionary */ +/* ----------------------------------------------------------------------- */ + +/** + * Zone file dictionary + */ +typedef void AnodeZoneFile; + +/** + * Start asynchronous zone fetch + * + * When the zone is retrieved, the lookup handler is called. If zone lookup + * failed, the zone file argument to the handler will be null. + * + * @param transport Transport engine + * @param zone Zone ID + * @param user_ptr User pointer + * @param zone_lookup_handler Handler for Anode zone lookup + */ +extern void AnodeZoneFile_lookup( + AnodeTransport *transport, + const AnodeZone *zone, + void *ptr, + void (*zone_lookup_handler)(const AnodeZone *,AnodeZoneFile *,void *)); + +/** + * Look up a key in a zone file + * + * @param zone Zone file object + * @param key Key to get in zone file + */ +extern const char *AnodeZoneFile_get(const AnodeZoneFile *zone,const char *key); + +/** + * Free a zone file + * + * @param zone Zone to free + */ +extern void AnodeZoneFile_free(AnodeZoneFile *zone); + +/* ----------------------------------------------------------------------- */ + +#ifdef __cplusplus +} +#endif + +#endif |