From: Enlightenment S. <no-...@en...> - 2010-12-04 10:16:08
|
Log: add full doxy for all azy_server* namespaces, add some new functions for servers, fix up some small bugs, use new addr server member, doxy for Azy.h, split azy_server_module functions to new file Author: discomfitor Date: 2010-12-04 02:16:01 -0800 (Sat, 04 Dec 2010) New Revision: 55256 Trac: http://trac.enlightenment.org/e/changeset/55256 Added: trunk/PROTO/azy/src/lib/azy_server_module.c Modified: trunk/PROTO/azy/src/include/Azy.h trunk/PROTO/azy/src/lib/Makefile.am trunk/PROTO/azy/src/lib/azy_server.c Modified: trunk/PROTO/azy/src/include/Azy.h =================================================================== --- trunk/PROTO/azy/src/include/Azy.h 2010-12-04 10:14:33 UTC (rev 55255) +++ trunk/PROTO/azy/src/include/Azy.h 2010-12-04 10:16:01 UTC (rev 55256) @@ -50,15 +50,21 @@ # endif #endif /* ! _WIN32 */ +/** + * Convenience define for Azy_Client_Return_Cb functions. + */ #define AZY_ERROR_NONE 0 extern int azy_log_dom; -extern int AZY_CLIENT_DISCONNECTED; -extern int AZY_CLIENT_CONNECTED; -extern int AZY_CLIENT_RESULT; -extern int AZY_CLIENT_RETURN; -extern int AZY_CLIENT_ERROR; +extern int AZY_CLIENT_DISCONNECTED; /**< Event emitted upon client disconnecting */ +extern int AZY_CLIENT_CONNECTED; /**< Event emitted upon client connecting */ +extern int AZY_CLIENT_RESULT; /**< Event emitted upon client method returning if + no callback was set */ +extern int AZY_CLIENT_RETURN; /**< Event emitted upon client method returning if + a callback for the method has been set */ +extern int AZY_CLIENT_ERROR; /**< Event emitted upon client method encountering + an error */ /** * @defgroup Azy_Typedefs Azy types @@ -67,29 +73,76 @@ */ /** - * @typedef _Azy_Server Azy_Server - * @brief An object representing the local server - * This type is for hosting a server, and is used by the - * azy_server namespace. + * @typedef Azy_Server + * A server object for hosting a server, and is used by the + * azy_server namespace */ typedef struct Azy_Server Azy_Server; +/** + * @typedef Azy_Server_Module + * A module object which contains all of the connection info + * for the associated client + */ typedef struct Azy_Server_Module Azy_Server_Module; +/** + * @typedef Azy_Server_Module_Method + * A method object containing the name and callback + */ typedef struct Azy_Server_Module_Method Azy_Server_Module_Method; +/** + * @typedef Azy_Server_Module_Def + * A module definition object. This type is the means by which + * #Azy_Server_Module objects are created and manipulated by users + * of the api; contains all methods present in the module + */ +typedef struct Azy_Server_Module_Def Azy_Server_Module_Def; +/** + * @typedef Azy_Client + * A client object for connecting to a server, used by the + * azy_client namespace + */ typedef struct Azy_Client Azy_Client; +/** + * @typedef Azy_Net + * A network object containing all connection and http + * information + */ typedef struct Azy_Net Azy_Net; -typedef struct Azy_Server_Module_Def Azy_Server_Module_Def; +/** + * @typedef Azy_Value + * A general struct which can hold any type of value + */ typedef struct Azy_Value Azy_Value; +/** + * @typedef Azy_Content + * A struct which holds the content being sent/received in an rpc method call + * in a list of #Azy_Value objects + */ typedef struct Azy_Content Azy_Content; - +/** + * @typedef Azy_Client_Call_Id + * A unique identifier for every azy_client_call and azy_client_send + * which can be used to set callbacks for the transmission + */ typedef unsigned int Azy_Client_Call_Id; +/** + * @typedef Azy_Server_Type + * A simple enum for easily specifying the type of server to run + */ typedef enum { - AZY_SERVER_LOCAL = 1, - AZY_SERVER_BROADCAST = 2, - AZY_SERVER_TLS = (1 << 4) + AZY_SERVER_NONE = 0, /**< Server listen address must be set using azy_server_addr_set */ + AZY_SERVER_LOCAL = 1, /**< Server listen address is 127.0.0.1 */ + AZY_SERVER_BROADCAST = 2, /**< Server listen address is 0.0.0.0 */ + AZY_SERVER_TLS = (1 << 4) /**< If bitwise ORed into the type, server will use TLS */ } Azy_Server_Type; +/** + * @typedef Azy_Client_Error + * Enum for client errors + */ +/* FIXME: THIS NEEDS TO GO AWAY OR SOMETHING!!!! */ typedef enum { AZY_CLIENT_ERROR_MARSHALIZER, @@ -99,18 +152,26 @@ AZY_CLIENT_ERROR_FAILED } Azy_Client_Error; +/** + * @typedef Azy_Value_Type + * Represents the type of value stored in the #Azy_Value object + */ typedef enum { - AZY_VALUE_ARRAY, - AZY_VALUE_STRUCT, - AZY_VALUE_MEMBER, - AZY_VALUE_INT, - AZY_VALUE_STRING, - AZY_VALUE_BOOL, - AZY_VALUE_DOUBLE, - AZY_VALUE_TIME, - AZY_VALUE_BASE64 + AZY_VALUE_ARRAY, /**< Array object */ + AZY_VALUE_STRUCT, /** Struct object */ + AZY_VALUE_MEMBER, /** Struct member object */ + AZY_VALUE_INT, /** Int object */ + AZY_VALUE_STRING, /** String (stringshared) object */ + AZY_VALUE_BOOL, /** Boolean object */ + AZY_VALUE_DOUBLE, /** Double object */ + AZY_VALUE_TIME, /** Time (stringshared) object */ + AZY_VALUE_BASE64 /** Base64 encoded string (stringshared) object */ } Azy_Value_Type; +/** + * @typedef Azy_Net_Type + * Represents the type of http method in the header + */ typedef enum { AZY_NET_TYPE_NONE, @@ -121,6 +182,10 @@ AZY_NET_TYPE_RESPONSE_ERROR } Azy_Net_Type; +/** + * @typedef Azy_Net_Transport + * Represents the content-type in the http headers + */ typedef enum { AZY_NET_TRANSPORT_XML, @@ -135,6 +200,11 @@ typedef void (*Azy_Server_Module_Shutdown_Cb)(Azy_Server_Module *); typedef Eina_Bool (*Azy_Server_Module_Content_Cb)(Azy_Server_Module *, Azy_Content *); typedef void *(*Azy_Content_Cb)(Azy_Value *, void **); +/** + * @typedef Azy_Client_Return_Cb + * Function must return AZY_ERROR_NONE (0) on success, else + * an error number. + */ typedef Eina_Error (*Azy_Client_Return_Cb)(Azy_Client *, Azy_Content *); #ifdef __cplusplus @@ -184,6 +254,8 @@ Azy_Server_Module_Content_Cb fallback); void azy_server_module_def_method_add(Azy_Server_Module_Def *def, Azy_Server_Module_Method *method); + Eina_Bool azy_server_module_def_method_del(Azy_Server_Module_Def *def, + Azy_Server_Module_Method *method); int azy_server_module_def_size_get(Azy_Server_Module_Def *def); Eina_Bool azy_server_module_size_set(Azy_Server_Module_Def *def, int size); @@ -200,6 +272,9 @@ int type, const char *cert, Azy_Server_Module_Def **modules); + Eina_Bool azy_server_addr_set(Azy_Server *server, + const char *addr); + const char *azy_server_addr_get(Azy_Server *server); /* net */ Azy_Net *azy_net_new(void *conn); Modified: trunk/PROTO/azy/src/lib/Makefile.am =================================================================== --- trunk/PROTO/azy/src/lib/Makefile.am 2010-12-04 10:14:33 UTC (rev 55255) +++ trunk/PROTO/azy/src/lib/Makefile.am 2010-12-04 10:16:01 UTC (rev 55256) @@ -30,6 +30,7 @@ azy_content_json.c \ azy_content_xml.c \ azy_server.c \ + azy_server_module.c \ azy_net.c \ azy_utils.c Modified: trunk/PROTO/azy/src/lib/azy_server.c =================================================================== --- trunk/PROTO/azy/src/lib/azy_server.c 2010-12-04 10:14:33 UTC (rev 55255) +++ trunk/PROTO/azy/src/lib/azy_server.c 2010-12-04 10:16:01 UTC (rev 55256) @@ -9,6 +9,12 @@ #include "Azy.h" #include "azy_private.h" +/** + * @brief Stop a running server + * This function stops running the specified server and stops the + * main loop. + * @param server The server object (NOT NULL) + */ void azy_server_stop(Azy_Server *server) { @@ -23,257 +29,24 @@ ecore_main_loop_quit(); } -void * -azy_server_module_data_get(Azy_Server_Module *module) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(module, NULL); - - return module->data; -} - -Azy_Net * -azy_server_module_net_get(Azy_Server_Module *module) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(module, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(module->client, NULL); - - return module->client->net; -} - -Azy_Server_Module_Def * -azy_server_module_def_find(Azy_Server *server, - const char *name) -{ - Azy_Server_Module_Def *def; - Eina_List *l; - - if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) - { - AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); - return NULL; - } - EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); - if (!server->module_defs) - return NULL; - - EINA_LIST_FOREACH(server->module_defs, l, def) - if (!strcmp(def->name, name)) - { - INFO("Found module with name: '%s'", name); - return def; - } - - INFO("Could not find module with name: '%s'", name); - return NULL; -} - -Eina_Bool -azy_server_module_add(Azy_Server *server, - Azy_Server_Module_Def *module) -{ - if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) - { - AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); - return EINA_FALSE; - } - if (!module) - return EINA_FALSE; - - if (azy_server_module_def_find(server, module->name)) - /* avoid adding same module twice */ - return EINA_TRUE; - - INFO("Adding new module: '%s'", module->name); - server->module_defs = eina_list_append(server->module_defs, module); - return EINA_TRUE; -} - -Eina_Bool -azy_server_module_del(Azy_Server *server, - Azy_Server_Module_Def *module) -{ - DBG("server=%p, module=%p", server, module); - if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) - { - AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); - return EINA_FALSE; - } - EINA_SAFETY_ON_NULL_RETURN_VAL(module, EINA_FALSE); - - if (!azy_server_module_def_find(server, module->name)) - return EINA_TRUE; - - server->module_defs = eina_list_remove(server->module_defs, module); - return EINA_TRUE; -} - -Azy_Server_Module_Def * -azy_server_module_def_new(const char *name) -{ - Azy_Server_Module_Def *def; - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); - - def = calloc(1, sizeof(Azy_Server_Module_Def)); - EINA_SAFETY_ON_NULL_RETURN_VAL(def, NULL); - - def->name = eina_stringshare_add(name); - AZY_MAGIC_SET(def, AZY_MAGIC_SERVER_MODULE_DEF); - return def; -} - -void -azy_server_module_def_free(Azy_Server_Module_Def *def) -{ - Azy_Server_Module_Method *method; - - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - - eina_stringshare_del(def->name); - EINA_LIST_FREE(def->methods, method) - azy_server_module_method_free(method); - - AZY_MAGIC_SET(def, AZY_MAGIC_NONE); - free(def); -} - -void -azy_server_module_def_init_shutdown_set(Azy_Server_Module_Def *def, Azy_Server_Module_Cb init, Azy_Server_Module_Shutdown_Cb shutdown) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - def->init = init; - def->shutdown = shutdown; -} - -void -azy_server_module_def_pre_post_set(Azy_Server_Module_Def *def, Azy_Server_Module_Content_Cb pre, Azy_Server_Module_Content_Cb post) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - def->pre = pre; - def->post = post; -} - -void -azy_server_module_def_download_upload_set(Azy_Server_Module_Def *def, Azy_Server_Module_Cb download, Azy_Server_Module_Cb upload) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - def->download = download; - def->upload = upload; -} - -void -azy_server_module_def_fallback_set(Azy_Server_Module_Def *def, Azy_Server_Module_Content_Cb fallback) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - def->fallback = fallback; -} - -void -azy_server_module_def_method_add(Azy_Server_Module_Def *def, Azy_Server_Module_Method *method) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return; - } - - if (!AZY_MAGIC_CHECK(method, AZY_MAGIC_SERVER_MODULE_METHOD)) - { - AZY_MAGIC_FAIL(method, AZY_MAGIC_SERVER_MODULE_METHOD); - return; - } - def->methods = eina_list_append(def->methods, method); -} - -Azy_Server_Module_Method * -azy_server_module_method_new(const char *name, Azy_Server_Module_Content_Cb cb) -{ - Azy_Server_Module_Method *method; - - if ((!name) || (!cb)) - return NULL; - - method = calloc(1, sizeof(Azy_Server_Module_Method)); - EINA_SAFETY_ON_NULL_RETURN_VAL(method, NULL); - - method->name = eina_stringshare_add(name); - method->method = cb; - - AZY_MAGIC_SET(method, AZY_MAGIC_SERVER_MODULE_METHOD); - return method; -} - -void -azy_server_module_method_free(Azy_Server_Module_Method *method) -{ - if (!AZY_MAGIC_CHECK(method, AZY_MAGIC_SERVER_MODULE_METHOD)) - { - AZY_MAGIC_FAIL(method, AZY_MAGIC_SERVER_MODULE_METHOD); - return; - } - - AZY_MAGIC_SET(method, AZY_MAGIC_NONE); - eina_stringshare_del(method->name); - free(method); -} - -int -azy_server_module_def_size_get(Azy_Server_Module_Def *def) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return -1; - } - - return def->data_size; -} - -Eina_Bool -azy_server_module_size_set(Azy_Server_Module_Def *def, int size) -{ - if (!AZY_MAGIC_CHECK(def, AZY_MAGIC_SERVER_MODULE_DEF)) - { - AZY_MAGIC_FAIL(def, AZY_MAGIC_SERVER_MODULE_DEF); - return EINA_FALSE; - } - - def->data_size = size; - return EINA_TRUE; -} - +/** + * @brief Create a new server object + * Create a new server object. If @p secure is specified, the server will require + * ssl/tls for connections. + * @param secure If true, server will use ssl for connections + * @return The new #Azy_Server object, or #NULL on failure + */ Azy_Server * azy_server_new(Eina_Bool secure) { Azy_Server *server; - azy_init(); if (!(server = calloc(1, sizeof(Azy_Server)))) return NULL; if (!(server->add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)azy_server_client_handler_add, server))) goto err; - server->security.secure = secure; + server->security.secure = !!secure; AZY_MAGIC_SET(server, AZY_MAGIC_SERVER); return server; @@ -283,6 +56,13 @@ return NULL; } +/** + * @brief Free the given server + * This function frees @p server. + * Note that the #Azy_Server_Module_Def objects are not freed + * with this function. + * @param server The server object to free (NOT NULL) + */ void azy_server_free(Azy_Server *server) { @@ -297,6 +77,14 @@ free(server); } +/** + * @brief Retrieve the list of #Azy_Server_Module_Def objects from a server + * This function will return an #Eina_List of #Azy_Server_Module_Def objects + * present in @p server. This list and the objects all belong to the server. + * They must NOT be freed. + * @param server The server object (NOT NULL) + * @return The list of #Azy_Server_Module_Def objects + */ Eina_List * azy_server_module_defs_get(Azy_Server *server) { @@ -309,6 +97,15 @@ return server->module_defs; } +/** + * @brief Send data to a client + * This function is used to queue arbitrary data to send to a client. It will automatically + * generate all http header strings from @p net including the content-length. + * @param net The client's #Azy_Net object (NOT NULL) + * @param data The data to send (NOT NULL) + * @param length The length of the data (NOT < 1) + * @return EINA_TRUE on success, else EINA_FALSE + */ Eina_Bool azy_server_client_send(Azy_Net *net, unsigned char *data, @@ -325,6 +122,7 @@ EINA_SAFETY_ON_TRUE_RETURN_VAL(length < 1, 0); EINA_SAFETY_ON_TRUE_RETURN_VAL(!ecore_con_server_connected_get(net->conn), 0); + azy_net_message_length_set(net, length); EINA_SAFETY_ON_TRUE_RETURN_VAL(!(header = azy_net_header_create(net)), 0); if (!ecore_con_client_send(net->conn, eina_strbuf_string_get(header), eina_strbuf_length_get(header))) @@ -340,12 +138,66 @@ return EINA_TRUE; } +/** + * @brief Set the address for a server to listen on + * This function sets the listen address for @p server to @p addr. + * Examples: 127.0.0.1, 0.0.0.0, localhost, etc + * @param server The server object (NOT NULL) + * @param addr The listen address (NOT NULL) + * @return EINA_TRUE on success, else EINA_FALSE + */ Eina_Bool +azy_server_addr_set(Azy_Server *server, + const char *addr) +{ + if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) + { + AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); + return EINA_FALSE; + } + EINA_SAFETY_ON_NULL_RETURN_VAL(addr, EINA_FALSE); + + server->addr = eina_stringshare_add(addr); + return EINA_TRUE; +} + +/** + * @brief Get the address for a server to listen on + * This function gets the listen address for @p server. + * Examples: 127.0.0.1, 0.0.0.0, localhost, etc + * @param server The server object (NOT NULL) + * @return The listen address + */ +const char * +azy_server_addr_get(Azy_Server *server) +{ + if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) + { + AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); + return NULL; + } + + return server->addr; +} + + +/** + * @brief Run the specified server + * This function starts the specified server, calling ecore_main_loop_begin. + * If the server's listen address has been previously specified, @p type should be + * #AZY_SERVER_NONE, otherwise it will be detected based on @p type. + * @param server The server object (NOT NULL) + * @param type The #Azy_Server_Type of the server; #AZY_SERVER_LOCAL for localhost, + * #AZY_SERVER_BROADCAST for 0.0.0.0, else #AZY_SERVER_NONE and call azy_server_addr_set + * @param port The port to listen on (0 < port < 65537) + * @return EINA_TRUE on success (after main loop exits), else the function will return + * immediately with EINA_FALSE + */ +Eina_Bool azy_server_run(Azy_Server *server, - int type, - int port) + int type, + int port) { - const char *name; int az, ecore = ECORE_CON_REMOTE_NODELAY; if (!AZY_MAGIC_CHECK(server, AZY_MAGIC_SERVER)) @@ -353,16 +205,24 @@ AZY_MAGIC_FAIL(server, AZY_MAGIC_SERVER); return EINA_FALSE; } - if (port < 1) - return EINA_FALSE; + EINA_SAFETY_ON_TRUE_RETURN_VAL(port < 1, EINA_FALSE); az = type & AZY_SERVER_TYPE; - if (az == AZY_SERVER_LOCAL) - name = "127.0.0.1"; - else - name = "0.0.0.0"; + switch (az) + { + case AZY_SERVER_NONE: + break; + case AZY_SERVER_BROADCAST: + eina_stringshare_replace(&server->addr, "0.0.0.0"); + break; + default: + eina_stringshare_replace(&server->addr, "127.0.0.1"); + break; + } + EINA_SAFETY_ON_NULL_RETURN_VAL(server->addr, EINA_FALSE); + if (az != type) { server->security.secure = EINA_TRUE; @@ -372,7 +232,7 @@ if (server->security.cert) ecore |= ECORE_CON_LOAD_CERT; - server->server = ecore_con_server_add(ecore, name, port, server); + server->server = ecore_con_server_add(ecore, server->addr, port, server); if (!server->server) return EINA_FALSE; @@ -383,16 +243,31 @@ return EINA_TRUE; } +/** + * @brief Run a server in a single call with no prior setup + * This function will create a server and run it all in one call, but + * provides less functionality and flexibility. + * It will call ecore_main_loop_begin, set up server modules, and + * free all allocated data upon return. + * @param port The port to listen on (0 < port < 65537) + * @param type The #Azy_Server_Type of the server; #AZY_SERVER_LOCAL for localhost, + * or #AZY_SERVER_BROADCAST for 0.0.0.0. To listen on another address you will need + * to manually set up your server object and use azy_server_run + * @param cert The ssl certificate file to use; #AZY_SERVER_TLS must + * be specified with @p type (NOT NULL) + * @param modules An array of module definitions (NOT NULL) + * @return EINA_TRUE on success (after main loop exits), else the function will return + * immediately with EINA_FALSE + */ Eina_Bool azy_server_basic_run(int port, - int type, - const char *cert, - Azy_Server_Module_Def **modules) + int type, + const char *cert, + Azy_Server_Module_Def **modules) { Azy_Server *server; Azy_Server_Module_Def **mods; Eina_Bool secure = EINA_FALSE; - const char *name; int az, ecore = ECORE_CON_REMOTE_NODELAY; if ((port < 1) || (port > 65535) || (!modules) || !(*modules)) @@ -400,11 +275,6 @@ az = type & AZY_SERVER_TYPE; - if (az == AZY_SERVER_LOCAL) - name = "127.0.0.1"; - else - name = "0.0.0.0"; - if (az != type) { secure = EINA_TRUE; @@ -413,16 +283,20 @@ if (!(server = azy_server_new(secure))) return EINA_FALSE; + if (az == AZY_SERVER_LOCAL) + server->addr = eina_stringshare_add("127.0.0.1"); + else + server->addr = eina_stringshare_add("0.0.0.0"); + for (mods = modules; mods && *mods; mods++) { if (!azy_server_module_add(server, *mods)) goto error; } - if (cert) - ecore |= ECORE_CON_LOAD_CERT; + if (cert) ecore |= ECORE_CON_LOAD_CERT; - if (!(server->server = ecore_con_server_add(ecore, name, port, server))) + if (!(server->server = ecore_con_server_add(ecore, server->addr, port, server))) goto error; ecore_con_server_data_set(server->server, server); |