/**
 * @brief Send arbitrary data to a connected server
 *
 * This function is used to send arbitrary data to a connected server using @p client through HTTP PUT.
 * It relies on the user to set required headers by operating on the client's #Azy_Net object.
 * @param client The client (NOT NULL)
 * @param send_data The data+length to send (NOT NULL)
 * @param data Optional data to pass to associated callbacks
 * @return The #Azy_Client_Call_Id of the transmission, to be used with azy_client_callback_set,
 * or 0 on failure
 * @see azy_net_header_set
 */
Azy_Client_Call_Id
azy_client_put(Azy_Client         *client,
               const Azy_Net_Data *send_data,
               void               *data)
{
   Eina_Strbuf *msg;
   Azy_Client_Handler_Data *hd;

   if (!AZY_MAGIC_CHECK(client, AZY_MAGIC_CLIENT))
     {
        AZY_MAGIC_FAIL(client, AZY_MAGIC_CLIENT);
        return 0;
     }
   EINA_SAFETY_ON_NULL_RETURN_VAL(send_data, 0);
   EINA_SAFETY_ON_NULL_RETURN_VAL(send_data->data, 0);

   azy_net_message_length_set(client->net, send_data->size);
   azy_net_type_set(client->net, AZY_NET_TYPE_PUT);
   msg = azy_net_header_create(client->net);
   EINA_SAFETY_ON_NULL_GOTO(msg, error);
#ifdef ISCOMFITOR
   DBG("\nSENDING >>>>>>>>>>>>>>>>>>>>>>>>\n%.*s%.*s\n>>>>>>>>>>>>>>>>>>>>>>>>",
       eina_strbuf_length_get(msg), eina_strbuf_string_get(msg), (int)send_data->size, send_data->data);
#endif
   EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, eina_strbuf_string_get(msg), eina_strbuf_length_get(msg)), error);
   INFO("Send [1/2] complete! %zi bytes queued for sending.", eina_strbuf_length_get(msg));
   eina_strbuf_free(msg);
   msg = NULL;

   EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, send_data->data, send_data->size), error);
   INFO("Send [2/2] complete! %" PRIi64 " bytes queued for sending.", send_data->size);
   ecore_con_server_flush(client->net->conn);

   EINA_SAFETY_ON_TRUE_RETURN_VAL(!(hd = calloc(1, sizeof(Azy_Client_Handler_Data))), 0);

   if (!client->conns)
     {
        client->recv = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
                                               (Ecore_Event_Handler_Cb)_azy_client_handler_data, hd);
        ecore_con_server_data_set(client->net->conn, client);
     }

   hd->client = client;
   hd->content_data = data;
   hd->type = AZY_NET_TYPE_PUT;
   AZY_MAGIC_SET(hd, AZY_MAGIC_CLIENT_DATA_HANDLER);

   while (++azy_client_send_id__ < 1) ;

   hd->id = azy_client_send_id__;
   client->conns = eina_list_append(client->conns, hd);

   return azy_client_send_id__;

error:
   if (msg)
     eina_strbuf_free(msg);
   return 0;
}
Exemple #2
0
Eldbus_Message *
_eldbus_connection_send_and_block(Eldbus_Connection *conn, Eldbus_Message *msg, double timeout)
{
   Eldbus_Message *reply = NULL;
   DBusError err;
   DBusMessage *dbus_msg;

   if (ecore_main_loop_nested_get())
     WRN("Calling this function may result in dropped frames because the main loop is running");

   dbus_error_init(&err);
   dbus_msg = 
     dbus_connection_send_with_reply_and_block(conn->dbus_conn,
                                               msg->dbus_msg, timeout, &err);
   EINA_SAFETY_ON_TRUE_GOTO(dbus_error_is_set(&err), dbus_error_set);
   dbus_error_free(&err);

   reply = eldbus_message_new(EINA_FALSE);
   EINA_SAFETY_ON_NULL_GOTO(reply, fail);

   reply->dbus_msg = dbus_msg;
   dbus_message_iter_init(reply->dbus_msg, &reply->iterator->dbus_iterator);
   eldbus_message_unref(msg);
   return reply;

dbus_error_set:
    reply = eldbus_message_error_new(msg, err.name, err.message);
    dbus_error_free(&err);
fail:
    eldbus_message_unref(msg);
    return reply;
}
/**
 * @brief Load a library and run a function from it which returns an #Azy_Server_Module_Def
 * This function loads @p file as an Eina_Module. If @p modname is specified, it attempts to call
 * modname() from the loaded module to create an #Azy_Server_Module_Def. If @p is NULL, the following
 * shell script formula will be used to generate a function name:
 * shell$ echo "$(basename $file | cut -d'.' -f1)_module_def"
 * @param file The file to load as a module (NOT NULL)
 * @param modname The name of the function to call of type #Azy_Server_Module_Def_Cb
 * @return On success, the loaded #Azy_Server_Module_Def, else NULL.
 */
Azy_Server_Module_Def *
azy_server_module_def_load(const char *file,
                           const char *modname)
{
   Eina_Module *m;
   Azy_Server_Module_Def *ret;
   const char *name;
   char buf[4096];
   Azy_Server_Module_Def_Cb cb;

   EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);

   if (modname) name = modname;
   else /* attempt to autodetect module name */
     {
        const char *s, *d;

        s = strrchr(file, '/');
        EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);

        d = strchr(++s, '.');
        EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
        EINA_SAFETY_ON_TRUE_RETURN_VAL(d - s + sizeof("_module_def") > sizeof(buf), NULL);
        snprintf(buf, d - s + sizeof("_module_def"), "%s_module_def", s);
        name = buf;
     }

   m = eina_module_new(file);
   EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);

   EINA_SAFETY_ON_TRUE_GOTO(!eina_module_load(m), err);
   cb = (Azy_Server_Module_Def_Cb)eina_module_symbol_get(m, name);
   EINA_SAFETY_ON_TRUE_GOTO(!cb, err);
   ret = cb();
   EINA_SAFETY_ON_TRUE_GOTO(!ret, err);
   ret->module = m;
   return ret;

err:
   eina_module_free(m);
   return NULL;
}
/**
 * @brief Make an HTTP GET or POST request using a connected client with no HTTP BODY
 *
 * This function is used to make a GET or POST request using @p client to the uri of the client's
 * #Azy_Net object (azy_net_get(client)) using HTTP method @p type, content-type
 * defined by @p transport, and the optional deserialization function specified by @p cb.
 * @param client The client (NOT NULL)
 * @param type The HTTP method to use (NOT NULL)
 * @param netdata The HTTP BODY to send with a POST
 * @param cb The deserialization callback to use for the response
 * @param data The user data to be passed to resulting callbacks
 * @return The #Azy_Client_Call_Id of the transmission, to be used with azy_client_callback_set,
 * or 0 on failure
 */
Azy_Client_Call_Id
azy_client_blank(Azy_Client    *client,
                 Azy_Net_Type   type,
                 Azy_Net_Data  *netdata,
                 Azy_Content_Cb cb,
                 void          *data)
{
   Eina_Strbuf *msg;
   Azy_Client_Handler_Data *hd;

   DBG("(client=%p, net=%p)", client, client->net);

   if (!AZY_MAGIC_CHECK(client, AZY_MAGIC_CLIENT))
     {
        AZY_MAGIC_FAIL(client, AZY_MAGIC_CLIENT);
        return 0;
     }
   EINA_SAFETY_ON_NULL_RETURN_VAL(client->net, 0);
   EINA_SAFETY_ON_TRUE_RETURN_VAL((type != AZY_NET_TYPE_GET) && (type != AZY_NET_TYPE_POST), 0);

   while (++azy_client_send_id__ < 1) ;

   client->net->type = type;

   if (!client->net->http.req.http_path)
     {
        WARN("NULL URI passed, defaulting to \"/\"");
        azy_net_uri_set(client->net, "/");
     }
   if (netdata && netdata->size && (type == AZY_NET_TYPE_POST))
     azy_net_message_length_set(client->net, netdata->size);

   msg = azy_net_header_create(client->net);
   EINA_SAFETY_ON_NULL_GOTO(msg, error);

#ifdef ISCOMFITOR
   char buf[64];
   snprintf(buf, sizeof(buf), "\nSENDING >>>>>>>>>>>>>>>>>>>>>>>>\n%%.%zus\n>>>>>>>>>>>>>>>>>>>>>>>>",
            eina_strbuf_length_get(msg));
   DBG(buf, eina_strbuf_string_get(msg));
#endif

   EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, eina_strbuf_string_get(msg), eina_strbuf_length_get(msg)), error);
   if (netdata && netdata->size && (type == AZY_NET_TYPE_POST))
     {
        INFO("Send [1/2] complete! %zu bytes queued for sending.", eina_strbuf_length_get(msg));
        EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, netdata->data, netdata->size), error);
        INFO("Send [2/2] complete! %" PRIi64 " bytes queued for sending.", netdata->size);
     }
   else
     INFO("Send [1/1] complete! %zu bytes queued for sending.", eina_strbuf_length_get(msg));
   eina_strbuf_free(msg);
   msg = NULL;

   ecore_con_server_flush(client->net->conn);

   hd = calloc(1, sizeof(Azy_Client_Handler_Data));
   EINA_SAFETY_ON_NULL_RETURN_VAL(hd, 0);
   hd->client = client;
   hd->callback = cb;
   hd->type = type;
   hd->content_data = data;
   if (netdata && netdata->size && (type == AZY_NET_TYPE_POST))
     {
        hd->send = eina_strbuf_new();
        eina_strbuf_append_length(hd->send, (char *)netdata->data, netdata->size);
     }

   hd->id = azy_client_send_id__;
   AZY_MAGIC_SET(hd, AZY_MAGIC_CLIENT_DATA_HANDLER);
   if (!client->conns)
     {
        client->recv = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
                                               (Ecore_Event_Handler_Cb)_azy_client_handler_data, hd);
        ecore_con_server_data_set(client->net->conn, client);
     }

   client->conns = eina_list_append(client->conns, hd);

   DBG("(client=%p, net=%p, hd=%p)", client, client->net, hd);
   return azy_client_send_id__;
error:
   if (msg) eina_strbuf_free(msg);
   return 0;
}
/**
 * @brief Make a method call using a connected client
 *
 * This function is used to make a method call on @p client as defined in
 * @p content, using content-type defined by @p transport and the deserialization
 * function specified by @p cb.  This should generally not be used by users, as azy_parser
 * will automatically generate the correct calls from a .azy file.
 * @param client The client (NOT NULL)
 * @param content The content containing the method name and parameters (NOT NULL)
 * @param transport The content-type (xml/json/etc) to use
 * @param cb The deserialization callback to use for the response
 * @return The #Azy_Client_Call_Id of the transmission, to be used with azy_client_callback_set,
 * or 0 on failure
 */
Azy_Client_Call_Id
azy_client_call(Azy_Client       *client,
                Azy_Content      *content,
                Azy_Net_Transport transport,
                Azy_Content_Cb    cb)
{
   Eina_Strbuf *msg;
   Azy_Client_Handler_Data *hd;

   DBG("(client=%p, net=%p, content=%p)", client, client->net, content);

   if (!AZY_MAGIC_CHECK(client, AZY_MAGIC_CLIENT))
     {
        AZY_MAGIC_FAIL(client, AZY_MAGIC_CLIENT);
        return 0;
     }
   EINA_SAFETY_ON_NULL_RETURN_VAL(client->net, 0);
   EINA_SAFETY_ON_NULL_RETURN_VAL(content, 0);
   EINA_SAFETY_ON_NULL_RETURN_VAL(content->method, 0);

   INFO("New method call: '%s'", content->method);

   while (++azy_client_send_id__ < 1) ;

   content->id = azy_client_send_id__;

   azy_net_transport_set(client->net, transport);
   if (!azy_content_serialize_request(content, transport))
     return 0;
   azy_net_type_set(client->net, AZY_NET_TYPE_POST);
   if (!client->net->http.req.http_path)
     {
        WARN("URI currently set to NULL, defaulting to \"/\"");
        azy_net_uri_set(client->net, "/");
     }

   azy_net_message_length_set(client->net, content->length);
   msg = azy_net_header_create(client->net);
   EINA_SAFETY_ON_NULL_GOTO(msg, error);

   if (azy_rpc_log_dom >= 0)
     {
        char buf[64];
        snprintf(buf, sizeof(buf), "\nSENDING >>>>>>>>>>>>>>>>>>>>>>>>\n%%.%is%%.%llis\n>>>>>>>>>>>>>>>>>>>>>>>>",
            eina_strbuf_length_get(msg), content->length);
        RPC_DBG(buf, eina_strbuf_string_get(msg), content->buffer);
     }

   EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, eina_strbuf_string_get(msg), eina_strbuf_length_get(msg)), error);
   INFO("Send [1/2] complete! %zu bytes queued for sending.", eina_strbuf_length_get(msg));
   eina_strbuf_free(msg);
   msg = NULL;

   EINA_SAFETY_ON_TRUE_GOTO(!ecore_con_server_send(client->net->conn, content->buffer, content->length), error);
   INFO("Send [2/2] complete! %lli bytes queued for sending.", content->length);
   ecore_con_server_flush(client->net->conn);

   hd = calloc(1, sizeof(Azy_Client_Handler_Data));
   EINA_SAFETY_ON_NULL_RETURN_VAL(hd, 0);
   hd->client = client;
   hd->method = eina_stringshare_ref(content->method);
   hd->callback = cb;
   hd->type = AZY_NET_TYPE_POST;
   hd->content_data = content->data;
   hd->send = eina_strbuf_new();
   eina_strbuf_append_length(hd->send, (char *)content->buffer, content->length);

   hd->id = azy_client_send_id__;
   AZY_MAGIC_SET(hd, AZY_MAGIC_CLIENT_DATA_HANDLER);
   if (!client->conns)
     {
        client->recv = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
                                               (Ecore_Event_Handler_Cb)_azy_client_handler_data, hd);
        ecore_con_server_data_set(client->net->conn, client);
     }

   client->conns = eina_list_append(client->conns, hd);

   DBG("(client=%p, net=%p, content=%p, hd=%p)", client, client->net, content, hd);
   return azy_client_send_id__;
error:
   if (msg)
     eina_strbuf_free(msg);
   return 0;
}