/** * @file ggz.h * @author Brent M. Hendricks * @date Fri Nov 2 23:32:17 2001 * $Id: ggz.h 8945 2007-01-16 17:42:57Z josef $ * * Header file for ggz components lib * * Copyright (C) 2001 Brent Hendricks. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GGZ_H__ #define __GGZ_H__ #define LIBGGZ_VERSION_MAJOR 0 #define LIBGGZ_VERSION_MINOR 0 #define LIBGGZ_VERSION_MICRO 14 #define LIBGGZ_VERSION_IFACE "5:0:3" #include #ifdef __cplusplus extern "C" { #endif /** @brief Allow easy use of GCC's "attribute" macro for debugging. * * Under gcc, we use the __attribute__ macro to check variadic arguments, * for instance to printf-style functions. Other compilers may be able * to do something similar, but this is generally unnecessary since it's * only realy purpose is to give warning messages when the developer compiles * the code. */ #ifdef __GNUC__ # define ggz__attribute(att) __attribute__(att) #else # define ggz__attribute(att) #endif #if defined __GNUC__ && (__GNUC__ >= 3) # define _GGZFUNCTION_ "" #else # ifndef __cplusplus # define _GGZFUNCTION_ __FUNCTION__ # else # define _GGZFUNCTION_ "" # endif #endif /** * @defgroup memory Memory Handling * * These macros provide an alternative to the normal C library * functions for dynamically allocating memory. They keep track of * memory allocated by storing the name of the function and file in * which they were called. * * You can then call ggz_memory_check() to make sure all allocated * memory has been freed. Note that you will need to enable MEMORY * debugging to see this. * * @{ */ /** @brief Debugging type for memory debugging. * @see ggz_debug_enable */ #define GGZ_MEM_DEBUG "ggz_mem" /** * Macro for memory allocation * * @param size the size of memory to allocate, in bytes * * @return a pointer to the newly allocated and zeroed memory */ #define ggz_malloc(size) _ggz_malloc(size, _GGZFUNCTION_ " in " __FILE__, __LINE__) /** * Macro for resizing previously allocated memory * * @param mem pointer to memory to reallocate * @param size new size requested, in bytes * * @return pointer to allocated memory */ #define ggz_realloc(mem, size) _ggz_realloc(mem, size, _GGZFUNCTION_ " in " __FILE__, __LINE__) /** * Macro for freeing memory previously allocated * * @param mem pointer to allocated memory * * @return failure code */ #define ggz_free(mem) _ggz_free(mem, _GGZFUNCTION_ " in " __FILE__, __LINE__) /** * Macro for duplicating string * * @param string string to duplicate * * @return pointer to new string * * @note It is safe to pass a NULL string. */ #define ggz_strdup(string) _ggz_strdup(string, _GGZFUNCTION_ " in " __FILE__, __LINE__) /** * Function to actually perform memory allocation. Don't call this * directly. Instead, call ggz_malloc(). * * @param size size of memory to allocate, in bytes * @param tag string describing the calling function * @param line linenumber * * @return pointer to newly allocated, zeroed memory */ void * _ggz_malloc(const size_t size, const char * tag, int line); /** * Function to perform memory reallocation. Don't call this * directly. Instead, call ggz_realloc(). * * @param ptr pointer to memory to reallocate * @param size new size, in bytes * @param tag string describing the calling function * @param line linenumber * * @return pointer to allocated memory */ void * _ggz_realloc(const void * ptr, const size_t size, const char * tag, int line); /** * Function to free allocated memory. Don't call this * directly. Instead, call ggz_free(). * * @param ptr pointer to memory * @param tag string describing the calling function * @param line linenumber * * @return 0 on success, -1 on error */ int _ggz_free(const void * ptr, const char * tag, int line); /** * Function to copy a string. Don't call this * directly. Instead, call ggz_strdup(). * * @param ptr string to duplicate * @param tag string describing the calling function * @param line linenumber * * @return newly allocated string * * @note It is safe to pass a NULL string. */ char * _ggz_strdup(const char * ptr, const char * tag, int line); /** * Check memory allocated against memory freed and display any discrepancies. * * * @return 0 if no allocated memory remains, -1 otherwise */ int ggz_memory_check(void); /** @} */ /** * @defgroup conf Configuration file parsing * * Configuration file routines to store and retrieve values. * Configuration file parsing begins by calling ggz_conf_parse() to open * a config file. The file can be created automatically if GGZ_CONF_CREATE * is specified. The returned handle uniquely identifies the configuration * file, so multiple files can be open at one time. * * If the same configuration file is opened multiple times, the original * handle will be returned and only one copy will be retained within memory. * One use of this feature is that a file may be opened read only initially and * later have writing enabled by merely reparsing the file using the same * pathname. Note that this feature can be fooled if the same file is * opened using different pathnames. Chaos may or may not result in this * case, and it is considered a feature not a bug. * * Values are stored using a system of section and keys. A key must be * unique within a section (you cannot store both an integer and a string * under the same key. Section and key names may contain any characters * (including whitespace) other than an equals sign. Although keys may not * have leading or trailing whitespace, section names may. It is suggested * that any whitespace (other than possibly internal spaces) be avoided when * specifying section and key names. Alphabetic case is preserved, and must * be matched. * * An important caveat to remember when using the configuration functions * is that writing a value only caches the value in memory. In order to * write the values to the physical file, ggz_conf_commit() must be called * at some point. This makes writing multiple values in rapid succession * more efficient, as the entire file must be regenerated in order to be * written to the flat-file format of the configuration file. * * The string and list reading functions return dynamically allocated * memory to the caller. The user is responsible for calling ggz_free() on * this memory when they no longer need the returned values. * * All memory used internally by the configuration functions will be * released when ggz_conf_cleanup() is called. Note that this does NOT * commit any changes made to the configuration files. * The user is expected to call this at program termination, but it may * be called at any time earlier than termination and new files may * be subsequently opened. * * @bug The maximum length of a configuration file line is fixed at 1024 * characters. Exceeding this length will result in parsing errors when * the file is parsed. No internal problems should (hopefully) result, * but values will be lost. * @{ */ /** @brief Debugging type for config-file debugging. * @see ggz_debug_enable */ #define GGZ_CONF_DEBUG "ggz_conf" /** * Specifies the mode for opening a configuration file. * @see ggz_conf_parse() */ typedef enum { GGZ_CONF_RDONLY = ((unsigned char) 0x01), /**< Read only */ GGZ_CONF_RDWR = ((unsigned char) 0x02), /**< Read and write */ GGZ_CONF_CREATE = ((unsigned char) 0x04) /**< Create file */ } GGZConfType; /** * Closes all open configuration files. * @note This does not automatically commit changed values. Any non-committed * values written will be lost. */ void ggz_conf_cleanup (void); /** * Closes one configuration file. * @note The same warning as for ggz_conf_cleanup() applies here. */ void ggz_conf_close (int handle); /** * Opens a configuration file and parses the variables so they can * be retrieved with the access functions. * @param path A string specifying the filename to be parsed * @param options An or'ed set of GGZConfType option bits * @return An integer configuration file handle or -1 on error * @see GGZConfType */ int ggz_conf_parse (const char *path, const GGZConfType options); /** * Commits any changed variables to the configuration file. The configuration * file remains open and may continue to be written to. * @param handle A valid handle returned by ggz_conf_parse() * @return 0 if successful, -1 on failure */ int ggz_conf_commit (int handle); /** * Writes a string value to a section and key in an open configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to write to * @param key A string variable key name to write to * @param value The string value to write * @return 0 if successful, -1 on failure */ int ggz_conf_write_string (int handle, const char *section, const char *key, const char *value); /** * Writes an integer value to a section and key in an open configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to write to * @param key A string variable key name to write to * @param value The integer value to write * @return 0 if successful, -1 on failure */ int ggz_conf_write_int (int handle, const char *section, const char *key, int value); /** * Writes a list of string values to a section and key in an open * configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to write to * @param key A string variable key name to write to * @param argc The number of string array entries in argv * @param argv An array of strings to create a list from * @return 0 if successful, -1 on failure */ int ggz_conf_write_list (int handle, const char *section, const char *key, int argc, char **argv); /** * Reads a string value from an open configuration file. If the section/key * combination is not found, the default entry is returned. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to read from * @param key A string variable key name to read from * @param def A value to be returned if the entry does not exist (may be NULL) * @return A dynamically allocated copy of the stored (or default) value * or NULL * @note The copy is allocated via a standard ggz_malloc() call and the * caller is expected to be responsible for calling ggz_free() on the * returned value when they no longer need the value. No memory is allocated * if a default value of NULL is returned. */ char * ggz_conf_read_string (int handle, const char *section, const char *key, const char *def); /** * Reads an integer value from an open configuration file. If the section/key * combination is not found, the default entry is returned. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to read from * @param key A string variable key name to read from * @param def A value to be returned if the entry does not exist * @return The integer value stored in the configuration file, or the default */ int ggz_conf_read_int (int handle, const char *section, const char *key, int def); /** * Reads a list of string values from an open configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to read from * @param key A string variable key name to read from * @param argcp A pointer to an integer which will receive the number of * list entries read * @param argvp A pointer to a string array. This will receive a value * pointing to a dynamically allocated array of string values. The * list will be NULL-terminated. * @return 0 on success, -1 on failure * @note The array is allocated via standard ggz_malloc() calls and the * caller is expected to be responsible for calling ggz_free() on the string * values and the associated array structure when they no longer need the * list. If the section/key combination is not found -1 will be returned, * *argcp is set to a value of zero, no memory will be allocated, and * *argvp will be set to NULL. */ int ggz_conf_read_list(int handle, const char *section, const char *key, int *argcp, char ***argvp); /** * This will remove an entire section and all its associated keys from * a configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name to remove * @return 0 on success, -1 on failure */ int ggz_conf_remove_section (int handle, const char *section); /** * This will remove a single key from a configuration file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name the key is located in * @param key A string key name to remove * @return 0 on success, -1 on failure */ int ggz_conf_remove_key (int handle, const char *section, const char *key); /** * This function returns a list of all sections in a config file. * @param handle A valid handle returned by ggz_conf_parse() * @param argcp A pointer to an integer which will receive the number of * sections in the configuration file * @param argvp A pointer to a string array. This will receive a value * pointing to a dynamically allocated array of string values. This list * is NOT NULL terminated. * @return 0 on success, -1 on failure * @note The array is allocated via standard ggz_malloc() calls and the * caller is expected to be responsible for calling ggz_free() on the string * values and the associated array structure when they no longer need the * list. */ int ggz_conf_get_sections (int handle, int *argcp, char ***argvp); /** * This function returns a list of all keys within a section in a config file. * @param handle A valid handle returned by ggz_conf_parse() * @param section A string section name * @param argcp A pointer to an integer which will receive the number of * lists within section in the configuration file * @param argvp A pointer to a string array. This will receive a value * pointing to a dynamically allocated array of string values. This list * is NOT NULL terminated. * @return 0 on success, -1 on failure * @note The array is allocated via standard ggz_malloc() calls and the * caller is expected to be responsible for calling ggz_free() on the string * values and the associated array structure when they no longer need the * list. */ int ggz_conf_get_keys (int handle, const char *section, int *argcp, char ***argvp); /** @} */ /** * @defgroup list List functions * * Data Structures and functions for manipulating linked-lists. * @{ */ /** @brief A function type for doing data comparison on two items in a * ::GGZList. * * @param a An arbitrary element in the ::GGZList. * @param b An arbitrary element in the ::GGZList. * @return Negative if a < b; 0 if a == b; positive if a > b. */ typedef int (*ggzEntryCompare)(const void *a, const void *b); /** @brief A function type for creating a copy of a data item for * insertion into a ::GGZList. * * A function of this type may be called on an element when * it is first inserted into a ::GGZList. * @param data A pointer to the data given to the list for insertion * @return A new copy of the data, safe for list insertion */ typedef void * (*ggzEntryCreate) (void *data); /** @brief A function type to destroy an entry in a ::GGZList. * * A function of this type may be called on an element when * it is removed from a ::GGZList. * @param data The entry being removed */ typedef void (*ggzEntryDestroy) (void *data); /** @brief A single entry in a ::GGZList. * * Do not access these members directly, but use the * ggz_list_get_data(), ggz_list_next() and ggz_list_prev() * accessor functions instead. */ typedef struct _GGZListEntry { void *data; /**< Pointer to data for this node */ struct _GGZListEntry *next, /**< Pointer to next nodes in the list */ *prev; /**< Pointer to previous node in the list */ } GGZListEntry; /** @brief Simple doubly-linked list. * * Do not access these members directly. Instead use accessor functions. */ typedef struct _GGZList { GGZListEntry *head, /**< Pointer to the first node in the list */ *tail; /**< Pointer to the last node in the list */ ggzEntryCompare compare_func; /**< Function used to compare data entries */ ggzEntryCreate create_func; /**< Function used to copy data entries */ ggzEntryDestroy destroy_func; /**< Function used to destroy data entries */ int options; /**< List options */ int entries; /**< The current number of list entries (ie. list length) */ } GGZList; #define GGZ_LIST_REPLACE_DUPS 0x00 /**< Overwrite duplicate values on insert */ #define GGZ_LIST_ALLOW_DUPS 0x01 /**< Allow duplicate data entries to exist in the list */ /** @brief Create a new ::GGZList. * * When creating a a new list, you have some control over its * behavior. The first parameter, compare_func allows you to specify * a comparison for sorting the list elements. If you specify NULL * for compare_func, the list will be unordered. The second * parameter, create_func allows you to specify how new copies of data * will be created during insertion. ::GGZList objects stores * pointers to your data in ::GGZListEntry nodes. If you specify NULL * for create_func, the list will store the actual pointer to your * data when you call ggz_list_insert(). If you specify a * create_func, it will be called to create a new copy of the object * for storage in the list. You are then safely deallocate the * original copy of the data. The third parameter, destroy_func * allows you to specify a deallocation function for data entries when * they are removed from the list. * @note The functions ggz_list_compare_str(), ggz_list_create_str(), * ggz_list_destroy_str() are provided for use with character string * data. * * The last argument must be one of #GGZ_LIST_REPLACE_DUPS or * #GGZ_LIST_ALLOW_DUPS, to specify how the list will behave with * respect to duplicate data entries. If #GGZ_LIST_REPLACE_DUPS is * passed, duplicate entries (as determined by compare_func) will be * replaced upon ggz_list_insert(). If #GGZ_LIST_ALLOW_DUPS is * specified, duplicate data entries will be allowed to exist in the * list. * * @note If compare_func is NULL, #GGZ_LIST_REPLACE_DUPS has no meaning. * * @param compare_func Function to use for comparing data items * @param create_func Function to use for allocating and copying data items * @param destroy_func Function to use for dellocating data items * @param options One of #GGZ_LIST_REPLACE_DUPS or #GGZ_LIST_ALLOW_DUPS * specifying how the list should handle duplicate data entries * @return A pointer to a newly allocated ::GGZList */ GGZList *ggz_list_create (ggzEntryCompare compare_func, ggzEntryCreate create_func, ggzEntryDestroy destroy_func, int options); /** @brief Insert data into a list. * * @param list Pointer to a ::GGZList * @param data Pointer to data to be inserted * @return -1 on failure, 0 is the item was inserted, and 1 if the * item replaced an existing list item * @note Replacement of duplicate items only occurs if #GGZ_LIST_REPLACE_DUPS * was passed to ggz_list_create(). */ int ggz_list_insert (GGZList *list, void *data); /** @brief Get the first node of a list. * * @param list Pointer to a ::GGZList * @return The ::GGZListEntry that is first in the list */ GGZListEntry *ggz_list_head (GGZList *list); /** @brief Get the last node of a list. * * @param list Pointer to a ::GGZList * @return The ::GGZListEntry that is last in the list */ GGZListEntry *ggz_list_tail (GGZList *list); /** @brief Get the next node of a list. * * @param entry Pointer to a ::GGZListEntry in a ::GGZList * @return The next ::GGZListEntry in the list */ GGZListEntry *ggz_list_next (GGZListEntry *entry); /** @brief Get the previous node of a list. * * @param entry Pointer to a ::GGZListEntry in a ::GGZList * @return The previous ::GGZListEntry in the list */ GGZListEntry *ggz_list_prev (GGZListEntry *entry); /** @brief Retrieve the data stored in a list entry. * * @param entry Pointer to a ::GGZListEntry * @return Pointer to the data stored in the specifed node (::GGZListEntry) */ void *ggz_list_get_data (GGZListEntry *entry); /** @brief Search for a specified data item in the list. * * ggz_list_search() searches a list for a particular data item using * the ggzEntryCompare function provided as compare_func to * ggz_list_create(). If you wish to search using an alternative * comparison function, see ggz_list_search_alt(). * * @param list Pointer to a ::GGZList * @param data Pointer to data to search for * @return Pointer to the ::GGZListEntry containing the specifed node * (NULL if the data could not be found or if no compare_func was * specified at list-creation time) */ GGZListEntry *ggz_list_search (GGZList *list, void *data); /** @brief Search for a specified data item in the list using a provided comparison function. * * ggz_list_search_alt() searches a list for a particular data item * using the passed ggzEntryCompare function. * * @param list Pointer to a ::GGZList * @param data Pointer to data to search for * @param compare_func Comparison function * @return Pointer to the ::GGZListEntry containing the specified node * (NULL if the data could not be found or if no compare_func was * specified) */ GGZListEntry *ggz_list_search_alt(GGZList *list, void *data, ggzEntryCompare compare_func); /** @brief Removes an entry from a list, calling a destructor if registered. * * ggz_list_delete_entry() removes the specifed entry from the list. * If a ggzEntryDestroy function was passed as destroy_func to * ggz_list_create(), it will be called on the data item after it has * been removed. * * @param list Pointer to a ::GGZList * @param entry Pointer to the ::GGZListEntry to remove */ void ggz_list_delete_entry (GGZList *list, GGZListEntry *entry); /** @brief Free all resources associated with a list. * * ggz_list_free() will free all resources allocated by the list. If * a ggzEntryDestroy function was passed as destroy_func to * ggz_list_create(), it will be called on all data items in the list * as well. * * @param list Pointer to a ::GGZList */ void ggz_list_free (GGZList *list); /** @brief Get the length of the list. * * @param list Pointer to a ::GGZList * @return The number of entries in the list */ int ggz_list_count (GGZList *list); /* String list functions */ /** @brief Compare two character strings. * * This function is intended to be passed as the compare_func of * ggz_list_create() when creating a list that stores character * strings. * * @param a A string to compare * @param b A second string to compare * @return The result of strcmp() on a and b, or 1 if either is NULL * */ int ggz_list_compare_str (void *a, void *b); /** @brief Copy a character string. * * This function is intended to be passed as the create_func of * ggz_list_create() when creating a list that stores character * strings. * * @param data A string to copy * @return A newly allocated copy of the string */ void * ggz_list_create_str (void *data); /** @brief Free a character string. * * This function is intended to be passed as the destroy_func of * ggz_list_create() when creating a list that stores character * strings. * * @param data The string to deallocate */ void ggz_list_destroy_str (void *data); /** @} */ /** * @defgroup stack Stacks * * Data Structures and functions for manipulating stacks. * * @{ */ /** @brief Simple implementation of stacks using ::GGZList. */ typedef struct _GGZList GGZStack; /** @brief Create a new stack. * * @return Pointer to a newly allocated ::GGZStack object */ GGZStack* ggz_stack_new(void); /** @brief Push a data item onto the top of the stack. * * @param stack Pointer to a ::GGZStack * @param data Pointer to data to insert onto stack */ void ggz_stack_push(GGZStack *stack, void *data); /** @brief Pop the top item off of the stack. * * @param stack Pointer to a ::GGZStack * @return Pointer to the data item on the top of the stack */ void* ggz_stack_pop(GGZStack *stack); /** @brief Get the top item on the stack without popping it. * * @param stack Pointer to a ::GGZList * @return Pointer to the data item currently in to of the stack */ void* ggz_stack_top(GGZStack *stack); /** @brief Free the stack. * * @note This does not free the data stored in the stack. * * @param stack Pointer to a ::GGZStack */ void ggz_stack_free(GGZStack *stack); /** @} */ /** * @defgroup xml XML parsing * * Utility functions for doing simple XML parsing. These can be used * with streaming XML parsers, and don't have the overhead of a full * DOM tree. ::GGZXMLElement represents a single element, along with * its attributes and text data. * * @note This does not parse your XML. It is simply for use to store * the data as you are parsing. * * @{ */ /** @brief Object representing a single XML element. * * Except for "process", do not access these members directly. * Instead use the provided accessor functions. "process" is meant * to be invoked as a method on instances of GGZXMLElement. */ struct _GGZXMLElement { char *tag; /**< The name of the element */ char *text; /**< Text content of an element */ GGZList *attributes; /**< List of attributes on the element */ void *data; /**< Extra data associated with tag (usually gleaned from children) */ void (*free)(struct _GGZXMLElement*); /**< Function to free allocated memory */ void (*process)(void*, struct _GGZXMLElement*); /**< Function to "process" tag */ }; /** @brief Object representing a single XML element. */ typedef struct _GGZXMLElement GGZXMLElement; /** @brief Create a new ::GGZXMLElement element. * * @param tag The name of the XML element (tag) * @param attrs NULL terminated array of attributes/values. These must alternate: attribute1, value1, attribute2, value2, etc. * @param process User-defined function for processing XML elements * @param free User-defined function for deallocating ::GGZXMLElement * objects. If provided, this will be invoked by * ggz_xmlelement_free(), and in addition to any user-defined * processing should call ggz_free() the element itself. * @return Pointer to a newly allocated ::GGZXMLElement object */ GGZXMLElement* ggz_xmlelement_new(const char *tag, const char * const *attrs, void (*process)(void*, GGZXMLElement*), void (*free)(GGZXMLElement*)); /** @brief Initialize a ::GGZXMLElement. * * @param element Pointer to a ::GGZXMLElement to initialize * @param tag The name of the XML element (tag) * @param attrs NULL terminated array of attributes/values. These must alternate: attribute1, value1, attribute2, value2, etc. * @param process User-defined function for processing XML elements * @param free User-defined function for deallocating ::GGZXMLElement * objects. If provided, this will be invoked by * ggz_xmlelement_free(), and in addition to any user-defined * processing should call ggz_free() the element itself. * @return Pointer to a newly allocated ::GGZXMLElement object */ void ggz_xmlelement_init(GGZXMLElement *element, const char *tag, const char * const *attrs, void (*process)(void*, GGZXMLElement*), void (*free)(GGZXMLElement*)); /** @brief Set ancillary data on a ::GGZXMLElement object. * * Associate some extra data with an XML element. * * @param element Pointer to an XML element * @param data Pointer to user-supplied data * @return The element's name */ void ggz_xmlelement_set_data(GGZXMLElement *element, void *data); /** @brief Get an XML element's name. * * @param element Pointer to an XML element * @return The element's name */ const char *ggz_xmlelement_get_tag(GGZXMLElement *element); /** @brief Get the value of an attribute on XML element. * * @param element Pointer to an XML element * @param attr An attribute name * @return The value of the attribute, or NULL is there is no such * attribute present */ const char *ggz_xmlelement_get_attr(GGZXMLElement *element, const char *attr); /** @brief Get the user-supplied data associated with an XML element. * * @param element Pointer to an XML element * @return Pointer to the user-supplied data */ void* ggz_xmlelement_get_data(GGZXMLElement *element); /** @brief Get an XML element's content text. * * @param element Pointer to an XML element * @return The text content of the element */ char* ggz_xmlelement_get_text(GGZXMLElement *element); /** @brief Append a string to the element's content text. * * @param element Pointer to an XML element * @param text String to append * @param len The string's length, in bytes */ void ggz_xmlelement_add_text(GGZXMLElement *element, const char *text, int len); /** @brief Free the memory associated with an XML element. * * @param element Pointer to an XML element */ void ggz_xmlelement_free(GGZXMLElement *element); /** @} */ /** * @defgroup debug Debug/error logging * * Functions for debugging and error messages. * @{ */ /** @brief What memory checks should we do? * * @see ggz_debug_cleanup */ typedef enum { GGZ_CHECK_NONE = 0x00, /**< No checks. */ GGZ_CHECK_MEM = 0x01 /**< Memory (leak) checks. */ } GGZCheckType; /** @brief A callback function to handle debugging output. * * A function of this type can be registered as a callback handler to handle * debugging output, rather than having the output go to stderr or to a file. * If this is done, each line of output will be sent directly to this function * (no trailing newline will be appended). * * @see ggz_debug_set_func * @param priority The priority of the log, i.e. LOG_DEBUG; see syslog() * @param msg The debugging output message * @note If your program is threaded, this function must be threadsafe. */ typedef void (*GGZDebugHandlerFunc)(int priority, const char *msg); /** * @brief Initialize and configure debugging for the program. * * This should be called early in the program to set up the debugging routines. * @param types A null-terminated list of arbitrary string debugging "types" * @param file A file to write debugging output to, or NULL for none * @see ggz_debug */ void ggz_debug_init(const char **types, const char* file); /** @brief Set the debug handler function. * * Call this function to register a debug handler function. NULL can * be passed to disable the debug handler. If set, the debug handler * function will be called to handle debugging output, overriding any * file that had previously been specified. * * @param func The new debug handler function * @return The previous debug handler function * @note This function is not threadsafe (re-entrant). */ GGZDebugHandlerFunc ggz_debug_set_func(GGZDebugHandlerFunc func); /** * @brief Enable a specific type of debugging. * * Any ggz_debug() calls that use that type will then be logged. * @param type The "type" of debugging to enable * @see ggz_debug */ void ggz_debug_enable(const char *type); /** * @brief Disable a specific type of debugging. * * Any ggz_debug() calls that use the given type of debugging will then not be * logged. * @param type The "type" of debugging to disable * @see ggz_debug */ void ggz_debug_disable(const char *type); /** * @brief Log a debugging message. * * This function takes a debugging "type" as well as a printf-style list of * arguments. It assembles the debugging message (printf-style) and logs it * if the given type of debugging is enabled. * @param type The "type" of debugging (similar to a loglevel) * @param fmt A printf-style format string * @see ggz_debug_enable, ggz_debug_disable */ void ggz_debug(const char *type, const char *fmt, ...) ggz__attribute((format(printf, 2, 3))); /** @brief Log a notice message. * * This function is nearly identical to ggz_debug(), except that if the * debugging output ends up passed to the debug handler function, * the priority will be LOG_NOTICE instead of LOG_DEBUG. This is only * of interest to a few programs. * @param type The "type" of debugging (similar to a loglevel) * @param fmt A printf-style format string * @see ggz_debug, ggz_debug_set_func */ void ggz_log(const char *type, const char *fmt, ...) ggz__attribute((format(printf, 2, 3))); /** * @brief Log a syscall error. * * This logs an error message in a similar manner to ggz_debug()'s debug * logging. However, the logging is done regardless of whether * debugging is enabled or what debugging types are set. errno and * strerror are also used to create a more useful message. * @param fmt A printf-style format string * @see ggz_debug */ void ggz_error_sys(const char *fmt, ...) ggz__attribute((format(printf, 1, 2))); /** * @brief Log a fatal syscall error. * * This logs an error message just like ggz_error_sys(), and also * exits the program. * @param fmt A printf-style format string */ void ggz_error_sys_exit(const char *fmt, ...) ggz__attribute((format(printf, 1, 2))) ggz__attribute((noreturn)); /** * @brief Log an error message. * * This logs an error message in a similar manner to ggz_debug()'s debug * logging. However, the logging is done regardless of whether * debugging is enabled or what debugging types are set. * @param fmt A printf-style format string * @note This is equivalent to ggz_debug(NULL, ...) with debugging enabled. */ void ggz_error_msg(const char *fmt, ...) ggz__attribute((format(printf, 1, 2))); /** * @brief Log a fatal error message. * * This logs an error message just like ggz_error_msg(), and also * exits the program. * @param fmt A printf-style format string */ void ggz_error_msg_exit(const char *fmt, ...) ggz__attribute((format(printf, 1, 2))) ggz__attribute((noreturn)); /** * @brief Cleans up debugging state and prepares for exit. * * This function should be called right before the program exits. It cleans * up all of the debugging state data, including writing out the memory check * data (if enabled) and closing the debugging file (if enabled). * @param check A mask of things to check */ void ggz_debug_cleanup(GGZCheckType check); /** @} */ /** * @defgroup misc Miscellaneous convenience functions * * @{ */ /** * Escape XML characters in a text string. * @param str The string to encode * @return A pointer to a dynamically allocated string with XML characters * replaced with ampersand tags, or NULL on error * @note The dynamic memory is allocated using ggz_malloc() and the caller is * expected to later free this memory using ggz_free(). If the original string * did not contain any characters which required escaping a ggz_strdup() copy * is returned. */ char * ggz_xml_escape(const char *str); /** * Restore escaped XML characters into a text string. * @param str The string to decode * @return A pointer to a dynamically allocated string with XML ampersand tags * replaced with their normal ASCII characters, or NULL on error * @note The dyanmic memory is allocated using ggz_malloc() and the caller is * expected to later free this memory using ggz_free(). If the original string * did not contain any characters which required decoding, a ggz_strdup() copy * is returned. * @note When using expat, incoming text is automatically unescaped by the * expat library. It is therefore generally not necessary to use this function * with expat. */ char * ggz_xml_unescape(const char *str); /** @brief Structure used internally by ggz_read_line(). */ typedef struct _GGZFile GGZFile; /** * Setup a file structure to use with ggz_read_line(). * @param fdes A preopened integer file descriptor to read from * @return A pointer to a dynamically allocated ::GGZFile structure * @note The user MUST have opened the requested file for reading before * using this function. When finished using ggz_read_line(), the user should * cleanup this struct using ggz_free_file_struct(). */ GGZFile * ggz_get_file_struct(int fdes); /** * Create directories to fill out a path. New directories are created with * permissions 700 (S_IRWXU). * @param full The full path to be created. * @return 0 on success; -1 on failure */ int ggz_make_path(const char *full); /** * Read a line of arbitrary length from a file. * @param file A ::GGZFile structure allocated via ggz_get_file_struct() * @return A NULL terminated line from the file of arbitrary length or * NULL at end of file * @note The dynamic memory is allocated using ggz_malloc() and the caller is * expected to later free this memory using ggz_free(). */ char * ggz_read_line(GGZFile *file); /** * Deallocate a file structure allocated via ggz_get_file_struct(). * @param file A ::GGZFile structure allocated via ggz_get_file_struct() * @note The caller is expected to close the I/O file before or after * freeing the file structure. */ void ggz_free_file_struct(GGZFile *file); /** * String comparison function that is safe with NULLs. * @param s1 First string to compare * @param s2 Second string to compare * @return An integer less than, equal to, or greater than zero if s1 * is found, respectively, to be less than, to match, or be greater * than s2 * @note NULL in considered to be less than any non-NULL string and * equal to itself */ int ggz_strcmp(const char *s1, const char *s2); /** @brief Case-insensitive string comparison function that is safe with NULLs * The function returns an integer less than, equal to, or greater than * zero if s1 is found, respectively, to be less than, to match, or be greater * than s2. NULL in considered to be less than any non-NULL string * and equal to itself * @param s1 First string to compare * @param s2 Second string to compare * @return The comparison value. */ int ggz_strcasecmp(const char *s1, const char *s2); /** @} */ /** * @defgroup easysock Easysock IO * * Simple functions for reading/writing binary data across file descriptors. * * @{ */ /** @brief ggz_debug debugging type for Easysock debugging. * * To enable socket debugging, add this to the list of debugging types. * @see ggz_debug_enable */ #define GGZ_SOCKET_DEBUG "socket" /** @brief An error type for the GGZ socket functions. * * If there is a GGZ socket error, the registered error handler will be * called and will be given one of these error types. */ typedef enum { GGZ_IO_CREATE, /**< Error creating a socket. */ GGZ_IO_READ, /**< Error reading from a socket. */ GGZ_IO_WRITE, /**< Error writing to a socket. */ GGZ_IO_ALLOCATE /**< Error when the allocation limit is exceeded. */ } GGZIOType; /** @brief A data type for the GGZ socket function error handler. * * If there is a GGZ socket error, the registered error handler will be * called and will be given one of these error data types. */ typedef enum { GGZ_DATA_NONE, /**< No data is associated with the error. */ GGZ_DATA_CHAR, /**< The error occurred while dealing with a char. */ GGZ_DATA_INT, /**< The error occurred in dealing with an integer. */ GGZ_DATA_STRING, /**< The error occurred in dealing with a string. */ GGZ_DATA_FD /**< Error while dealing with a file descriptor. */ } GGZDataType; /** @brief An error function type. * * This function type will be called when there is an error in a GGZ * socket function. * * @param msg The strerror message associated with the error * @param type The type of error that occurred * @param fd The socket on which the error occurred, or -1 if not applicable * @param data Extra data associated with the error */ typedef void (*ggzIOError) (const char * msg, const GGZIOType type, const int fd, const GGZDataType data); /** @brief Set the ggz/easysock error handling function. * * Any time an error occurs in a GGZ socket function, the registered error * handling function will be called. Use this function to register a new * error function. Any previous error function will be discarded. * * @param func The new error-handling function * @return 0 * @todo Shouldn't this function return a void or ggzIOError? */ int ggz_set_io_error_func(ggzIOError func); /** @brief Remove the ggz/easysock error handling function. * * The default behavior when a socket failure occurs in one of the GGZ socket * functions is to do nothing (outside of the function's return value). This * may be overridden by registering an error handler with * ggz_set_io_error_func(), but the behavior may be returned by calling this * function to remove the error handler. * * @return The previous error-handling function, or NULL if none. */ ggzIOError ggz_remove_io_error_func(void); /** @brief An exit function type. * * This function type will be called to exit the program. * @param status The exit value */ typedef void (*ggzIOExit) (int status); /** @brief Set the ggz/easysock exit function. * * Any of the *_or_die() functions will call the set exit function if there * is an error. If there is no set function, exit() will be called. * @param func The newly set exit function * @return 0 * @todo Shouldn't this return a void? */ int ggz_set_io_exit_func(ggzIOExit func); /** @brief Remove the ggz/easysock exit function. * * This removes the existing exit function, if one is set. exit() will * then be called to exit the program. * @return The old exit function (or NULL if none) */ ggzIOExit ggz_remove_io_exit_func(void); /** @brief Get libggz's limit on memory allocation. * * @return The limit to allow on ggz_read_*_alloc() calls, in bytes * @see ggz_set_io_alloc_limit */ unsigned int ggz_get_io_alloc_limit(void); /** @brief Set libggz's limit on memory allocation. * * In functions of the form ggz_read_*_alloc(), libggz will itself * allocate memory for the * object that is being read in. This * presents an obvious security concern, so we limit the amount of * memory that can be allocated. The default value is 32,767 bytes, * but it can be changed by calling this function. * * @param limit The new limit to allow on alloc-style calls, in bytes * @return The previous limit * @see ggz_get_io_alloc_limit * @see ggz_read_string_alloc */ unsigned int ggz_set_io_alloc_limit(const unsigned int limit); /** @brief Initialize the network. * * This function will do anything necessary to initialize the network to * use sockets (this is needed on some platforms). It should be called at * least once before any sockets are put to use. Calling it more than once * is harmless. It will be called automatically at the start of all GGZ * socket creation functions. * * @return 0 on success, negative on failure */ int ggz_init_network(void); /** @brief A network resolver function type. * * This function type will be called whenever a hostname has been resolved * or a socket has been created asynchronously. * @param status The IP address of the host name * @param socket File descriptor or error code like in ggz_make_socket */ typedef void (*ggzNetworkNotify) (const char *address, int socket); /** @brief Set the ggz/easysock resolver notification function. * * This function will be called whenever a resolving task submitted * to ggz_resolvename() or ggz_make_socket() has finished. * @param func The newly set resolver notification function * @return 0 * @todo Shouldn't this return a void? (from ggz_set_io_exit_func) */ int ggz_set_network_notify_func(ggzNetworkNotify func); /** @brief Resolve a host name. * * In order to prevent blocking GUIs, this function can handle * resolving a hostname into a numerical address asynchronously. * The notification function will be called whenever it finishes. * It receives as its argument the address, which might still be the * same hostname in the case of errors. The result should be passed * to gethostbyname() to receive the network data structures. * If no notification function is set, this function returns the hostname * as it is, without any lookup. If no GAI support is available, but a * notification function is set, it is called with the unresolved hostname, * too. * @param name Hostname to resolve * @return The hostname in case no notification function is set, or NULL * @todo Should this resolve synchronously in the special cases above? */ const char *ggz_resolvename(const char *name); /** @brief Get the IP address or host name of a connected peer. * * This function tells about the IP address of the peer which is * connected to the specified socket. If resolving is enabled, then * the hostname is returned instead. In this case, resolving will * be a blocking operation. * @param fd Local end file descriptor of the connection * @param resolve Whether or not to resolve the host name * @return IP address or host name of peer, or NULL on error * @note The string must be ggz_free()d afterwards */ const char *ggz_getpeername(int fd, int resolve); /**************************************************************************** * Creating a socket. * * type : one of GGZ_SERVER or GGZ_CLIENT * port : tcp port number * server: hostname to connect to (only relevant for client) * * Returns socket fd or -1 on error ***************************************************************************/ /** @brief A socket type. * * These socket types are used by ggz_make_socket() and friends to decide * what actions are necessary in making a connection. */ typedef enum { GGZ_SOCK_SERVER, /**< Just listen on a particular port. */ GGZ_SOCK_CLIENT /**< Connect to a particular port of a server. */ } GGZSockType; /** @brief Make a socket connection. * * This function makes a TCP socket connection. * - For a server socket, we'll just listen on the given port and accept * the first connection that is made there. * - For a client socket, we'll connect to a server that is (hopefully) * listening at the given port and hostname. * * Note that when a ggzNetworkNotify callback has been set up, this function * returns immediately and creates the socket later on. * * @param type The type of socket (server or client) * @param port The port to listen/connect to * @param server The server hostname for clients, the interface address else * @return File descriptor on success, -1 on creation error, -2 on lookup * error, -3 when using asynchronous creation */ int ggz_make_socket(const GGZSockType type, const unsigned short port, const char *server); /** @brief Make a socket connection, exiting on error. * * Aside from the error condition, this is identical to ggz_make_socket(). */ int ggz_make_socket_or_die(const GGZSockType type, const unsigned short port, const char *server); /** @brief Connect to a unix domain socket. * * This function connects to a unix domain socket, a socket associated with * a file on the VFS. * - For a server socket, we unlink the socket file first and then * create it. * - For a client socket, we connect to a pre-existing socket file. * * @param type The type of socket (server or client) * @param name The name of the socket file * @return The socket FD on success, -1 on error * @note When possible, this should not be used. Use socketpair() instead. */ int ggz_make_unix_socket(const GGZSockType type, const char* name); /** @brief Connect to a unix domain socket, exiting on error. * * Aside from the error condition, this is identical to ggz_make_unix_socket(). */ int ggz_make_unix_socket_or_die(const GGZSockType type, const char* name); /** @brief Write a character value to the given socket. * * This function will write a single character to the socket. The * character will be readable at the other end with ggz_read_char. * * @param sock The socket file descriptor to write to * @param data A single character to write * @return 0 on success, -1 on error */ int ggz_write_char(const int sock, const char data); /** @brief Write a character value to the given socket, exiting on error. * * @param sock The socket file descriptor to write to * @param data A single character to write * @note Aside from error handling, this is identical to ggz_write_char(). */ void ggz_write_char_or_die(const int sock, const char data); /** @brief Read a character value from the given socket. * * This function will read a single character (as written by * ggz_write_char()) from a socket. It places the value into the * character pointed to. * * @param sock The socket file descriptor to read from * @param data A pointer to a single character * @return 0 on success, -1 on error */ int ggz_read_char(const int sock, char *data); /** @brief Read a character value from the given socket, exiting on error. * * @param sock The socket file descriptor to read from * @param data A pointer to a single character * @note Aside from error handling, this is identical to ggz_read_char(). */ void ggz_read_char_or_die(const int sock, char *data); /** @brief Write an integer to the socket in network byte order. * * ggz_write_int() and ggz_read_int() can be used to send an integer across a * socket. The integer will be sent in network byte order, so the * functions may safely be used across a network. Note, though, that it * is probably not safe to use this function to send structs or other * data that may use a different representation than a simple integer. * * @param sock The socket to write to * @param data The integer to write * @return 0 on success, -1 on error */ int ggz_write_int(const int sock, const int data); /** @brief Write an integer to the socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_write_int(). */ void ggz_write_int_or_die(const int sock, const int data); /** @brief Read an integer from the socket in network byte order. * * @see ggz_write_int * * @param sock The socket to read from * @param data A pointer to an integer in which to place the data * @return 0 on success, -1 on error */ int ggz_read_int(const int sock, int *data); /** @brief Read an integer from the socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_read_int. */ void ggz_read_int_or_die(const int sock, int *data); /** @brief Write a string to the given socket. * * This function will write a full string to the given socket. The string * may be read at the other end by ggz_read_string() and friends. * * @param sock The socket file descriptor to write to * @param data A pointer to the string to write * @return 0 on success, -1 on error */ int ggz_write_string(const int sock, const char *data); /** @brief Write a string to the given socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_write_string(). */ void ggz_write_string_or_die(const int sock, const char *data); /** @brief Write a printf-style formatted string to the given socket. * * This function allows a format string and a list of arguments * to be passed in. The function will assemble the string (printf-style) * and write it to the socket. * * @param sock The socket file descriptor to write to * @param fmt A printf-style formatting string * @param ... A printf-style list of arguments * @note This function will write identically to ggz_write_string(). */ int ggz_va_write_string(const int sock, const char *fmt, ...) ggz__attribute((format(printf, 2, 3))); /** @brief Write a formatted string to the socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_va_write_string. */ void ggz_va_write_string_or_die(const int sock, const char *fmt, ...) ggz__attribute((format(printf, 2, 3))); /** @brief Read a string from the given socket. * * This function will read a full string from the given socket. The string * may be written at the other end by ggz_write_string() and friends. The * length of the string is given as well to avoid buffer overruns; any * characters beyond this will be lost. * * @param sock The socket file descriptor to read from * @param data A pointer to the string to read; it will be changed * @param len The length of the string pointed to by data * @return 0 on success, -1 on error */ int ggz_read_string(const int sock, char *data, const unsigned int len); /** @brief Read a string from the given socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_read_string(). */ void ggz_read_string_or_die(const int sock, char *data, const unsigned int len); /** @brief Read and allocate a string from the given socket. * * This function reads a string from the socket, just like ggz_read_string(). * But instead of passing in a pre-allocated buffer to write in, here * we pass a pointer to a string pointer: * * @code * char* str; * if (ggz_read_string_alloc(fd, &str) >= 0) { * // ... handle the string ... * ggz_free(str); * } * @endcode * * @param sock The socket file descriptor to read from * @param data A pointer to an empty string pointer * @return 0 on success, -1 on error * @note The use of this function is a security risk. * @see ggz_set_io_alloc_limit */ int ggz_read_string_alloc(const int sock, char **data); /** @brief Read and allocate string from the given socket, exiting on error. * * Aside from the error condition, this function is identical to * ggz_read_string_alloc(). */ void ggz_read_string_alloc_or_die(const int sock, char **data); /* ggz_write_fd/ggz_read_fd are not supported on all systems. */ /** @brief Write a file descriptor to the given (local) socket. * * ggz_write_fd() and ggz_read_fd() handle the rather tricky task of sending * a file descriptor across a socket. The FD is written with ggz_write_fd() * and can be read at the other end by ggz_read_fd(). Note that this will * only work for local sockets (i.e. not over the network). Many thanks to * Richard Stevens and his wonderful books, from which these functions come. * * @param sock The socket to write to * @param sendfd The FD to send across the socket * @return 0 on success, -1 on error */ int ggz_write_fd(const int sock, int sendfd); /** @brief Read a file descriptor from the given (local) socket. * * @see ggz_write_fd * * @param sock The socket to read from * @param recvfd The FD that is read * @return 0 on success, -1 on error **/ int ggz_read_fd(const int sock, int *recvfd); /** @brief Write a sequence of bytes to the socket. * * ggz_writen() and ggz_readn() are used to send an arbitrary quantity of raw * data across the a socket. The data is written with ggz_writen() and can * be read at the other end with ggz_readn(). Many thanks to Richard Stevens * and his wonderful books, from which these functions come. * * @param sock The socket to write to * @param vdata A pointer to the data to write * @param n The number of bytes of data to write from vdata * @return 0 on success, -1 on error */ int ggz_writen(const int sock, const void *vdata, size_t n); /** @brief Read a sequence of bytes from the socket. * * @see ggz_writen * * @param sock The socket to read from * @param data A pointer a buffer of size >= n in which to place the data * @param n The number of bytes to read * @return 0 on success, -1 on error * @note You must know how much data you want BEFORE calling this function. */ int ggz_readn(const int sock, void *data, size_t n); /** @} */ /** * @defgroup security Security functions * * All functions related to encryption and encoding go here. * * Encryption functions use gcrypt, and will always fail if support for gcrypt * has not been compiled in. Encoding functions will always be available. * * @{ */ /** @brief Hash data structure. * * Contains a string and its length, so that NULL-safe * functions are possible. */ typedef struct { char *hash; /**< Hash value */ int hashlen; /**< Length of the hash value, in bytes */ } hash_t; /** @brief Create a hash over a text. * * A hash sum over a given text is created, using the given * algorithm. Space is allocated as needed. * * @param algo The algorithm, like md5 or sha1 * @param text Plain text used to calculate the hash sum * @return Hash value in a structure */ hash_t ggz_hash_create(const char *algo, const char *text); /** @brief Create a HMAC hash over a text. * * Creates a hash sum using a secret key. * Space is allocated as needed and must be freed afterwards. * * @param algo The algorithm to use, like md5 or sha1 * @param text Plain text used to calculate the hash sum * @param secret Secret key to be used for the HMAC creation * @return Hash value in a structure */ hash_t ggz_hmac_create(const char *algo, const char *text, const char *secret); /** @brief Encodes text to base16. * * Plain text with possibly unsafe characters is converted * to the base16 (hex) format through this function. * The returned string is allocated internally and must be freed. * * @param text Plain text to encode * @param length Length of the text (which may contain binary characters), in bytes * @return Base16 representation of the text */ char *ggz_base16_encode(const char *text, int length); /** @brief Encodes text to base64. * * Plain text with possibly unsafe characters is converted * to the base64 format through this function. * The returned string is allocated internally and must be freed. * * @param text Plain text to encode * @param length Length of the text (which may contain binary characters), in bytes * @return Base64 representation of the text */ char *ggz_base64_encode(const char *text, int length); /** @brief Decodes text from base64. * * This is the reverse function to ggz_base64_encode(). * It will also allocate space as needed. * * @param text Text in base64 format * @param length Length of the text, in bytes * @return Native representation, may contain binary characters */ char *ggz_base64_decode(const char *text, int length); /** @brief TLS operation mode. * * Hints whether the TLS handshake will happen in either * client or server mode. * * @see ggz_tls_enable_fd */ typedef enum { GGZ_TLS_CLIENT, /**< Operate as client */ GGZ_TLS_SERVER /**< Operate as server */ } GGZTLSType; /** @brief TLS verification type. * * The authentication (verification) model to be used * for the handshake. None means that no certificate * is validated. * * @see ggz_tls_enable_fd */ typedef enum { GGZ_TLS_VERIFY_NONE, /**< Don't perform verification */ GGZ_TLS_VERIFY_PEER /**< Perform validation of the server's cert */ } GGZTLSVerificationType; /** @brief Initialize TLS support on the server side. * * This function ought only be used on the server side. * It sets up the necessary initialization values. * * @param certfile File containing the certificate, or NULL * @param keyfile File containing the private key, or NULL * @param password Password to the private key, or NULL */ void ggz_tls_init(const char *certfile, const char *keyfile, const char *password); /** @brief Check TLS support. * * Checks if real TLS support is available or communication * will fall back to unencrypted connections. * Even in the case of support, individual connections might * still be unencrypted if the handshake fails. * * @return 1 if TLS is supported, 0 if no support is present * @see ggz_tls_enable_fd */ int ggz_tls_support_query(void); /** @brief Name of the TLS implementation. * * Returns the name of the TLS layer implementation used * to encrypt connections. * * @return TLS implementation name, or NULL if no TLS support is present * @see ggz_tls_support_query */ const char *ggz_tls_support_name(void); /** @brief Enable TLS for a file descriptor. * * A TLS handshake is performed for an existing connection on the given * file descriptor. On success, all consecutive data will be encrypted. * * @param fdes File descriptor in question * @param whoami Operation mode (client or server) * @param verify Verification mode * @return 1 on success, 0 on failure */ int ggz_tls_enable_fd(int fdes, GGZTLSType whoami, GGZTLSVerificationType verify); /** @brief Disable TLS for a file descriptor. * * An existing TLS connection is reset to a normal connection on which * all communication happens without encryption. * * @param fdes File descriptor in question * @return 1 on success, 0 on failure */ int ggz_tls_disable_fd(int fdes); /** @brief Write some bytes to a secured file descriptor. * * This function acts as a TLS-aware wrapper for write(2). * * @param fd File descriptor to use * @param ptr Pointer to the data to write * @param n Length of the data to write, in bytes * @return Actual number of bytes written */ size_t ggz_tls_write(int fd, void *ptr, size_t n); /** @brief Read from a secured file descriptor. * * This function acts as a TLS-aware wrapper for read(2). * * @param fd File descriptor to use * @param ptr Pointer to a buffer to store the data into * @param n Number of bytes to read, and minimum size of the buffer * @return Actually read number of bytes */ size_t ggz_tls_read(int fd, void *ptr, size_t n); /** @} */ #ifdef __cplusplus } #endif #endif /* __GGZ_H__ */