WIP: efl.net: Introduce Efl.Net.Dialer.Http

This class implements the Efl.Net.Dialer interface using libcurl to
perform HTTP requests. That means it's an Efl.Net.Dialer,
Efl.Net.Socket, Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus
being usable with Efl.Io.Copier as demonstrated in the
efl_io_copier_example.c
This commit is contained in:
Gustavo Sverzut Barbieri 2016-08-20 00:55:26 -03:00
parent e7df1a7483
commit b791c79ca0
11 changed files with 3224 additions and 11 deletions

View File

@ -11,6 +11,7 @@ ecore_con_eolian_files = \
lib/ecore_con/efl_net_socket_tcp.eo \
lib/ecore_con/efl_net_dialer.eo \
lib/ecore_con/efl_net_dialer_tcp.eo \
lib/ecore_con/efl_net_dialer_http.eo \
lib/ecore_con/efl_net_server.eo \
lib/ecore_con/efl_net_server_fd.eo \
lib/ecore_con/efl_net_server_tcp.eo \
@ -19,8 +20,13 @@ ecore_con_eolian_files = \
lib/ecore_con/ecore_con_eet_client_obj.eo \
lib/ecore_con/efl_network_url.eo
ecore_con_eolian_type_files = \
lib/ecore_con/efl_net_http_types.eot
ecore_con_eolian_c = $(ecore_con_eolian_files:%.eo=%.eo.c)
ecore_con_eolian_h = $(ecore_con_eolian_files:%.eo=%.eo.h) \
$(ecore_con_eolian_type_files:%.eot=%.eot.h) \
$(ecore_con_eolian_files:%.eo=%.eo.legacy.h)
BUILT_SOURCES += \
@ -29,11 +35,13 @@ BUILT_SOURCES += \
ecoreconeolianfilesdir = $(datadir)/eolian/include/ecore-@VMAJ@
ecoreconeolianfiles_DATA = \
$(ecore_con_eolian_files)
$(ecore_con_eolian_files) \
$(ecore_con_eolian_type_files)
EXTRA_DIST2 += \
${ecoreconeolianfiles_DATA}
lib_LTLIBRARIES += lib/ecore_con/libecore_con.la
installed_ecoreconmainheadersdir = $(includedir)/ecore-con-@VMAJ@
@ -66,6 +74,7 @@ lib/ecore_con/efl_net_socket_fd.c \
lib/ecore_con/efl_net_socket_tcp.c \
lib/ecore_con/efl_net_dialer.c \
lib/ecore_con/efl_net_dialer_tcp.c \
lib/ecore_con/efl_net_dialer_http.c \
lib/ecore_con/efl_net_server.c \
lib/ecore_con/efl_net_server_fd.c \
lib/ecore_con/efl_net_server_tcp.c

View File

@ -48,3 +48,4 @@
/ecore_buffer_provider_example
/efl_io_copier_example
/efl_net_server_example
/efl_net_dialer_http_example

View File

@ -78,7 +78,8 @@ ecore_getopt_example \
ecore_con_eet_client_example \
ecore_con_eet_server_example \
efl_io_copier_example \
efl_net_server_example
efl_net_server_example \
efl_net_dialer_http_example
ECORE_COMMON_LDADD = \
$(top_builddir)/src/lib/ecore/libecore.la \
@ -285,6 +286,9 @@ efl_io_copier_example_LDADD = $(ECORE_CON_COMMON_LDADD)
efl_net_server_example_SOURCES = efl_net_server_example.c
efl_net_server_example_LDADD = $(ECORE_CON_COMMON_LDADD)
efl_net_dialer_http_example_SOURCES = efl_net_dialer_http_example.c
efl_net_dialer_http_example_LDADD = $(ECORE_CON_COMMON_LDADD)
SRCS = \
ecore_animator_example.c \
ecore_buffer_example.c \
@ -331,7 +335,9 @@ ecore_getopt_example.c \
ecore_con_eet_client_example.c \
ecore_con_eet_server_example.c \
ecore_con_eet_descriptor_example.c \
efl_io_copier_example.c
efl_io_copier_example.c \
efl_net_server_example.c \
efl_net_dialer_http_example.c
DATA_FILES = red.png Makefile.examples

View File

@ -89,6 +89,63 @@ EFL_CALLBACKS_ARRAY_DEFINE(dialer_cbs,
{ EFL_NET_DIALER_EVENT_ERROR, _dialer_error },
{ EFL_NET_DIALER_EVENT_CONNECTED, _dialer_connected });
static void
_http_headers_done(void *data EINA_UNUSED, const Eo_Event *event)
{
Eina_Iterator *itr;
Efl_Net_Http_Header *h;
Efl_Net_Http_Version ver = efl_net_dialer_http_version_get(event->object);
const char *response_content_type;
int64_t response_content_length;
fprintf(stderr, "INFO: HTTP/%d.%d connected to '%s', code=%d, headers:\n",
ver / 100, ver % 100,
efl_net_dialer_address_dial_get(event->object),
efl_net_dialer_http_response_status_get(event->object));
/* this is only for the last request, if allow_redirects and you want
* all of the headers, use efl_net_dialer_http_response_headers_all_get()
*/
itr = efl_net_dialer_http_response_headers_get(event->object);
EINA_ITERATOR_FOREACH(itr, h)
fprintf(stderr, "INFO: Header '%s: %s'\n", h->key, h->value);
eina_iterator_free(itr);
/* be nice to memory, we do not need these anymore */
efl_net_dialer_http_response_headers_clear(event->object);
response_content_length = efl_net_dialer_http_response_content_length_get(event->object);
response_content_type = efl_net_dialer_http_response_content_type_get(event->object);
fprintf(stderr, "INFO: Download %" PRId64 " bytes of type %s\n",
response_content_length, response_content_type);
if (efl_net_dialer_http_primary_mode_get(event->object) == EFL_NET_DIALER_HTTP_PRIMARY_MODE_UPLOAD)
{
int64_t request_content_type = efl_net_dialer_http_request_content_length_get(event->object);
fprintf(stderr, "INFO: Upload %" PRId64 " bytes\n",
request_content_type);
}
}
static void
_http_closed(void *data EINA_UNUSED, const Eo_Event *event)
{
uint64_t dn, dt, un, ut;
efl_net_dialer_http_progress_download_get(event->object, &dn, &dt);
efl_net_dialer_http_progress_upload_get(event->object, &un, &ut);
fprintf(stderr, "INFO: http transfer info: "
"download=%" PRIu64 "/%" PRIu64 " "
"upload=%" PRIu64 "/%" PRIu64 "\n",
dn, dt, un, ut);
}
EFL_CALLBACKS_ARRAY_DEFINE(http_cbs,
{ EFL_NET_DIALER_HTTP_EVENT_HEADERS_DONE, _http_headers_done },
{ EFL_IO_CLOSER_EVENT_CLOSED, _http_closed });
/* copier events are of interest, you should hook to at least "done"
* and "error"
*/
@ -274,6 +331,7 @@ static const Ecore_Getopt options = {
"The input file name or:\n"
":stdin: to read from stdin.\n"
"tcp://IP:PORT to connect using TCP and an IPv4 (A.B.C.D:PORT) or IPv6 ([A:B:C:D::E]:PORT).\n"
"http://address to do a GET request\n"
"",
"input-file"),
ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
@ -283,6 +341,7 @@ static const Ecore_Getopt options = {
":memory: to write to a memory buffer.\n"
":none: to not use a destination object.\n"
"tcp://IP:PORT to connect using TCP and an IPv4 (A.B.C.D:PORT) or IPv6 ([A:B:C:D::E]:PORT).\n"
"http://address to do a PUT request\n"
"",
"output-file"),
ECORE_GETOPT_SENTINEL
@ -321,6 +380,7 @@ main(int argc, char **argv)
ecore_init();
ecore_con_init();
ecore_con_url_init();
args = ecore_getopt_parse(&options, values, argc, argv);
if (args < 0)
@ -386,6 +446,32 @@ main(int argc, char **argv)
goto end_input;
}
}
else if (strncmp(input_fname, "http://", strlen("http://")) == 0 ||
strncmp(input_fname, "https://", strlen("https://")) == 0)
{
Eina_Error err;
input = efl_add(EFL_NET_DIALER_HTTP_CLASS, ecore_main_loop_get(),
efl_net_dialer_http_method_set(efl_self, "GET"),
efl_event_callback_array_add(efl_self, input_cbs(), NULL), /* optional */
efl_event_callback_array_add(efl_self, dialer_cbs(), NULL), /* optional */
efl_event_callback_array_add(efl_self, http_cbs(), NULL) /* optional */
);
if (!input)
{
fprintf(stderr, "ERROR: could not create HTTP Dialer.\n");
retval = EXIT_FAILURE;
goto end;
}
err = efl_net_dialer_dial(input, input_fname);
if (err)
{
fprintf(stderr, "ERROR: could not HTTP dial %s: %s\n",
input_fname, eina_error_msg_get(err));
goto end_input;
}
}
else
{
/* regular file, open with flags: read-only and close-on-exec */
@ -493,6 +579,32 @@ main(int argc, char **argv)
goto end_output;
}
}
else if (strncmp(output_fname, "http://", strlen("http://")) == 0 ||
strncmp(output_fname, "https://", strlen("https://")) == 0)
{
Eina_Error err;
output = efl_add(EFL_NET_DIALER_HTTP_CLASS, ecore_main_loop_get(),
efl_net_dialer_http_method_set(efl_self, "PUT"),
efl_event_callback_array_add(efl_self, output_cbs(), NULL), /* optional */
efl_event_callback_array_add(efl_self, dialer_cbs(), NULL), /* optional */
efl_event_callback_array_add(efl_self, http_cbs(), NULL) /* optional */
);
if (!output)
{
fprintf(stderr, "ERROR: could not create HTTP Dialer.\n");
retval = EXIT_FAILURE;
goto end_input;
}
err = efl_net_dialer_dial(output, output_fname);
if (err)
{
fprintf(stderr, "ERROR: could not HTTP dial %s: %s\n",
output_fname, eina_error_msg_get(err));
goto end_output;
}
}
else
{
/* regular file, open with flags: write-only, close-on-exec,
@ -560,6 +672,7 @@ main(int argc, char **argv)
input = NULL;
end:
ecore_con_url_shutdown();
ecore_con_shutdown();
ecore_shutdown();

View File

@ -0,0 +1,414 @@
#define EFL_BETA_API_SUPPORT 1
#define EFL_EO_API_SUPPORT 1
#include <Ecore.h>
#include <Ecore_Con.h>
#include <Ecore_Getopt.h>
#include <fcntl.h>
#include <ctype.h>
static int retval = EXIT_SUCCESS;
static int waiting;
static void
_closed(void *data EINA_UNUSED, const Eo_Event *event)
{
fprintf(stderr, "INFO: closed %s\n",
efl_name_get(event->object));
}
static void
_eos(void *data EINA_UNUSED, const Eo_Event *event)
{
fprintf(stderr, "INFO: eos %s\n",
efl_name_get(event->object));
}
static void
_connected(void *data EINA_UNUSED, const Eo_Event *event)
{
fprintf(stderr, "INFO: connected %s\n",
efl_net_dialer_address_dial_get(event->object));
}
static void
_resolved(void *data EINA_UNUSED, const Eo_Event *event)
{
fprintf(stderr, "INFO: resolved %s => %s\n",
efl_net_dialer_address_dial_get(event->object),
efl_net_socket_address_remote_get(event->object));
}
static void
_error(void *data EINA_UNUSED, const Eo_Event *event)
{
const Eina_Error *perr = event->info;
fprintf(stderr, "INFO: error: %d '%s'\n", *perr, eina_error_msg_get(*perr));
retval = EXIT_FAILURE;
}
static void
_http_headers_done(void *data EINA_UNUSED, const Eo_Event *event)
{
Eo *o = event->object;
Efl_Net_Http_Version ver = efl_net_dialer_http_version_get(o);
Eina_Iterator *itr;
const Efl_Net_Http_Header *h;
fprintf(stderr, "INFO: HTTP/%d.%d status=%d url=%s\n",
ver / 100, ver % 100,
efl_net_dialer_http_response_status_get(o),
efl_net_socket_address_remote_get(o));
itr = efl_net_dialer_http_response_headers_get(o);
EINA_ITERATOR_FOREACH(itr, h)
fprintf(stderr, "INFO: %s: %s\n", h->key, h->value);
eina_iterator_free(itr);
fprintf(stderr, "INFO: content-type: %s, content-length: %" PRId64 "\n",
efl_net_dialer_http_response_content_type_get(o),
efl_net_dialer_http_response_content_length_get(o));
fprintf(stderr, "INFO: to upload %zd bytes\n", efl_net_dialer_http_request_content_length_get(o));
}
EFL_CALLBACKS_ARRAY_DEFINE(dialer_cbs,
{ EFL_NET_DIALER_HTTP_EVENT_HEADERS_DONE, _http_headers_done },
{ EFL_NET_DIALER_EVENT_CONNECTED, _connected },
{ EFL_NET_DIALER_EVENT_RESOLVED, _resolved },
{ EFL_NET_DIALER_EVENT_ERROR, _error },
{ EFL_IO_CLOSER_EVENT_CLOSED, _closed },
{ EFL_IO_READER_EVENT_EOS, _eos });
static void
_done(void *data EINA_UNUSED, const Eo_Event *event)
{
waiting--;
fprintf(stderr, "INFO: done %s, waiting=%d\n",
efl_name_get(event->object), waiting);
if (waiting == 0)
ecore_main_loop_quit();
}
EFL_CALLBACKS_ARRAY_DEFINE(copier_cbs,
{ EFL_IO_COPIER_EVENT_DONE, _done },
{ EFL_IO_CLOSER_EVENT_CLOSED, _closed });
static const char *primary_mode_choices[] = {
"auto",
"download",
"upload",
NULL
};
static Efl_Net_Dialer_Http_Primary_Mode
_parse_primary_mode(const char *str)
{
if (strcmp(str, "upload") == 0)
return EFL_NET_DIALER_HTTP_PRIMARY_MODE_UPLOAD;
if (strcmp(str, "download") == 0)
return EFL_NET_DIALER_HTTP_PRIMARY_MODE_DOWNLOAD;
return EFL_NET_DIALER_HTTP_PRIMARY_MODE_AUTO;
}
static const char *http_version_choices[] = {
"1.0",
"1.1",
"2.0",
NULL
};
static Efl_Net_Http_Version
_parse_http_version(const char *str)
{
if (strcmp(str, "1.1") == 0)
return EFL_NET_HTTP_VERSION_V1_1;
if (strcmp(str, "2.0") == 0)
return EFL_NET_HTTP_VERSION_V2_0;
return EFL_NET_HTTP_VERSION_V1_0;
}
static const char *authentication_method_choices[] = {
"none",
"basic",
"digest",
"negotiate",
"ntlm",
"ntlm_winbind",
"any_safe",
"any",
NULL,
};
static Efl_Net_Http_Authentication_Method
_parse_authentication_method(const char *str)
{
if (strcmp(str, "basic") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_BASIC;
if (strcmp(str, "digest") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_DIGEST;
if (strcmp(str, "negotiate") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_NEGOTIATE;
if (strcmp(str, "ntlm") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_NTLM;
if (strcmp(str, "ntlm_winbind") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_NTLM_WINBIND;
if (strcmp(str, "any_safe") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_ANY_SAFE;
if (strcmp(str, "any") == 0)
return EFL_NET_HTTP_AUTHENTICATION_METHOD_ANY;
return EFL_NET_HTTP_AUTHENTICATION_METHOD_NONE;
}
static const Ecore_Getopt options = {
"efl_net_dialer_http_example", /* program name */
NULL, /* usage line */
"1", /* version */
"(C) 2016 Enlightenment Project", /* copyright */
"BSD 2-Clause", /* license */
/* long description, may be multiline and contain \n */
"Example of Efl_Net_Dialer_Http usage.\n",
EINA_FALSE,
{
ECORE_GETOPT_STORE_STR('m', "method", "HTTP method such as GET, POST, PUT..."),
ECORE_GETOPT_CHOICE('M', "primary-mode", "Define primary operation mode.", primary_mode_choices),
ECORE_GETOPT_CHOICE('v', "http-version", "HTTP protocol version to use", http_version_choices),
ECORE_GETOPT_STORE_STR('U', "username", "Authentication username"),
ECORE_GETOPT_STORE_STR('P', "password", "Authentication password"),
ECORE_GETOPT_CHOICE('A', "authentication-method", "Authentication method", authentication_method_choices),
ECORE_GETOPT_STORE_BOOL('R', "authentication-restricted", "Authentication method must be restricted"),
ECORE_GETOPT_STORE_BOOL('r', "allow-redirects", "allow redirections by following 'Location:' headers"),
ECORE_GETOPT_STORE_DOUBLE('t', "connect-timeout", "timeout in seconds for the connection phase"),
ECORE_GETOPT_APPEND('H', "header", "Add custom headers. Format must be 'Key: Value'", ECORE_GETOPT_TYPE_STR),
ECORE_GETOPT_APPEND('F', "form", "Add form field. Format must be 'key=value'", ECORE_GETOPT_TYPE_STR),
ECORE_GETOPT_STORE_STR('i', "input-file", "Input file to use when uploading"),
ECORE_GETOPT_VERSION('V', "version"),
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
"The address (URL) to dial", "address"),
ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
"The output file name or :stdout:",
"output-file"),
ECORE_GETOPT_SENTINEL
}
};
int
main(int argc, char **argv)
{
char *method = "GET";
char *primary_mode_str = "auto";
char *http_version_str = "1.1";
char *username = NULL;
char *password = NULL;
char *authentication_method_str = "basic";
char *address = NULL;
char *output_fname = NULL;
char *input_fname = NULL;
Eina_Bool quit_option = EINA_FALSE;
Eina_Bool authentication_restricted = EINA_FALSE;
Eina_Bool allow_redirects = EINA_TRUE;
double timeout_dial = 30.0;
Eina_List *headers = NULL;
Eina_List *form_fields = NULL;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(method),
ECORE_GETOPT_VALUE_STR(primary_mode_str),
ECORE_GETOPT_VALUE_STR(http_version_str),
ECORE_GETOPT_VALUE_STR(username),
ECORE_GETOPT_VALUE_STR(password),
ECORE_GETOPT_VALUE_STR(authentication_method_str),
ECORE_GETOPT_VALUE_BOOL(authentication_restricted),
ECORE_GETOPT_VALUE_BOOL(allow_redirects),
ECORE_GETOPT_VALUE_DOUBLE(timeout_dial),
ECORE_GETOPT_VALUE_LIST(headers),
ECORE_GETOPT_VALUE_LIST(form_fields),
ECORE_GETOPT_VALUE_STR(input_fname),
/* standard block to provide version, copyright, license and help */
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -C/--copyright quits */
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */
/* positional argument */
ECORE_GETOPT_VALUE_STR(address),
ECORE_GETOPT_VALUE_STR(output_fname),
ECORE_GETOPT_VALUE_NONE /* sentinel */
};
int args;
Eo *input, *dialer, *output, *sender, *receiver, *loop;
Efl_Net_Dialer_Http_Primary_Mode primary_mode;
Efl_Net_Http_Version http_version;
Efl_Net_Http_Authentication_Method authentication_method;
Efl_Net_Http_Header *header;
Eina_Iterator *itr;
Eina_Error err;
char *str;
ecore_init();
ecore_con_init();
ecore_con_url_init();
args = ecore_getopt_parse(&options, values, argc, argv);
if (args < 0)
{
fputs("ERROR: Could not parse command line options.\n", stderr);
retval = EXIT_FAILURE;
goto end;
}
if (quit_option) goto end;
loop = ecore_main_loop_get();
args = ecore_getopt_parse_positional(&options, values, argc, argv, args);
if (args < 0)
{
fputs("ERROR: Could not parse positional arguments.\n", stderr);
retval = EXIT_FAILURE;
goto end;
}
if ((!input_fname) || (strcmp(input_fname, ":stdin:") == 0))
{
input = efl_add(EFL_IO_STDIN_CLASS, loop,
efl_name_set(efl_self, "stdin"),
efl_event_callback_add(efl_self, EFL_IO_READER_EVENT_EOS, _eos, NULL));
}
else
{
input = efl_add(EFL_IO_FILE_CLASS, loop,
efl_name_set(efl_self, "input"),
efl_file_set(efl_self, input_fname, NULL),
efl_io_file_flags_set(efl_self, O_RDONLY | O_CLOEXEC),
efl_event_callback_add(efl_self, EFL_IO_READER_EVENT_EOS, _eos, NULL));
}
if ((!output_fname) || (strcmp(output_fname, ":stdout:") == 0))
{
output = efl_add(EFL_IO_STDOUT_CLASS, loop,
efl_name_set(efl_self, "stdout"));
}
else
{
output = efl_add(EFL_IO_FILE_CLASS, loop,
efl_name_set(efl_self, "output"),
efl_file_set(efl_self, output_fname, NULL),
efl_io_file_mode_set(efl_self, 0644),
efl_io_file_flags_set(efl_self, O_WRONLY | O_CLOEXEC | O_TRUNC | O_CREAT));
}
primary_mode = _parse_primary_mode(primary_mode_str);
http_version = _parse_http_version(http_version_str);
authentication_method = _parse_authentication_method(authentication_method_str);
dialer = efl_add(EFL_NET_DIALER_HTTP_CLASS, loop,
efl_name_set(efl_self, "dialer"),
efl_net_dialer_http_method_set(efl_self, method),
efl_net_dialer_http_primary_mode_set(efl_self, primary_mode),
efl_net_dialer_http_version_set(efl_self, http_version),
efl_net_dialer_http_authentication_set(efl_self, username, password, authentication_method, authentication_restricted),
efl_net_dialer_http_allow_redirects_set(efl_self, allow_redirects),
efl_net_dialer_timeout_dial_set(efl_self, timeout_dial),
efl_event_callback_array_add(efl_self, dialer_cbs(), NULL));
EINA_LIST_FREE(headers, str)
{
char *p = strchr(str, ':');
if (p)
{
p[0] = '\0';
p++;
while ((p[0] != '\0') && isspace(p[0]))
p++;
}
efl_net_dialer_http_request_header_add(dialer, str, p);
free(str);
}
EINA_LIST_FREE(form_fields, str)
{
fprintf(stderr, "TODO: form_field %s", str);
free(str);
}
waiting = 1;
if (efl_net_dialer_http_primary_mode_get(dialer) == EFL_NET_DIALER_HTTP_PRIMARY_MODE_UPLOAD)
waiting++;
sender = efl_add(EFL_IO_COPIER_CLASS, loop,
efl_name_set(efl_self, "sender"),
efl_io_copier_source_set(efl_self, input),
efl_io_copier_destination_set(efl_self, dialer),
efl_event_callback_array_add(efl_self, copier_cbs(), NULL));
fprintf(stderr, "INFO: sending %s->%s\n",
efl_name_get(input),
efl_name_get(dialer));
receiver = efl_add(EFL_IO_COPIER_CLASS, loop,
efl_name_set(efl_self, "receiver"),
efl_io_copier_source_set(efl_self, dialer),
efl_io_copier_destination_set(efl_self, output),
efl_event_callback_array_add(efl_self, copier_cbs(), NULL));
fprintf(stderr, "INFO: receiving %s->%s\n",
efl_name_get(dialer),
efl_name_get(output));
err = efl_net_dialer_dial(dialer, address);
if (err != 0)
{
fprintf(stderr, "ERROR: could not dial '%s': %s",
address, eina_error_msg_get(err));
goto no_mainloop;
}
fprintf(stderr,
"INFO: dialed %s\n"
"INFO: - method=%s\n"
"INFO: - primary_mode=%d\n"
"INFO: - version=%d\n"
"INFO: - allow_redirects=%d\n"
"INFO: - timeout_dial=%fs\n"
"INFO: - request headers:\n",
efl_net_dialer_address_dial_get(dialer),
efl_net_dialer_http_method_get(dialer),
efl_net_dialer_http_primary_mode_get(dialer),
efl_net_dialer_http_version_get(dialer),
efl_net_dialer_http_allow_redirects_get(dialer),
efl_net_dialer_timeout_dial_get(dialer));
itr = efl_net_dialer_http_request_headers_get(dialer);
EINA_ITERATOR_FOREACH(itr, header)
fprintf(stderr, "INFO: %s: %s\n", header->key, header->value);
eina_iterator_free(itr);
ecore_main_loop_begin();
fprintf(stderr, "INFO: main loop finished.\n");
no_mainloop:
efl_io_closer_close(sender);
efl_del(sender);
efl_io_closer_close(receiver);
efl_del(receiver);
efl_del(dialer);
efl_del(output);
efl_del(input);
end:
ecore_con_url_shutdown();
ecore_con_shutdown();
ecore_shutdown();
return retval;
}

View File

@ -14,3 +14,62 @@
#include "efl_net_socket_tcp.eo.h"
#include "efl_net_dialer_tcp.eo.h"
#include "efl_net_server_tcp.eo.h"
#include "efl_net_http_types.eot.h"
/* TODO: should be generated from 'var Efl.Net.Http.Error.*' */
extern Eina_Error EFL_NET_HTTP_ERROR_BAD_CONTENT_ENCODING;
extern Eina_Error EFL_NET_HTTP_ERROR_BAD_DOWNLOAD_RESUME;
extern Eina_Error EFL_NET_HTTP_ERROR_BAD_FUNCTION_ARGUMENT;
extern Eina_Error EFL_NET_HTTP_ERROR_CHUNK_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_CONV_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_CONV_REQD;
extern Eina_Error EFL_NET_HTTP_ERROR_COULDNT_CONNECT;
extern Eina_Error EFL_NET_HTTP_ERROR_COULDNT_RESOLVE_HOST;
extern Eina_Error EFL_NET_HTTP_ERROR_COULDNT_RESOLVE_PROXY;
extern Eina_Error EFL_NET_HTTP_ERROR_FAILED_INIT;
extern Eina_Error EFL_NET_HTTP_ERROR_FILE_COULDNT_READ_FILE;
extern Eina_Error EFL_NET_HTTP_ERROR_FILESIZE_EXCEEDED;
extern Eina_Error EFL_NET_HTTP_ERROR_FUNCTION_NOT_FOUND;
extern Eina_Error EFL_NET_HTTP_ERROR_GOT_NOTHING;
extern Eina_Error EFL_NET_HTTP_ERROR_HTTP2;
extern Eina_Error EFL_NET_HTTP_ERROR_HTTP2_STREAM;
extern Eina_Error EFL_NET_HTTP_ERROR_HTTP_POST_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_HTTP_RETURNED_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_INTERFACE_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_LOGIN_DENIED;
extern Eina_Error EFL_NET_HTTP_ERROR_NO_CONNECTION_AVAILABLE;
extern Eina_Error EFL_NET_HTTP_ERROR_NOT_BUILT_IN;
extern Eina_Error EFL_NET_HTTP_ERROR_OPERATION_TIMEDOUT;
extern Eina_Error EFL_NET_HTTP_ERROR_PARTIAL_FILE;
extern Eina_Error EFL_NET_HTTP_ERROR_PEER_FAILED_VERIFICATION;
extern Eina_Error EFL_NET_HTTP_ERROR_RANGE_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_READ_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_RECV_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_REMOTE_ACCESS_DENIED;
extern Eina_Error EFL_NET_HTTP_ERROR_REMOTE_DISK_FULL;
extern Eina_Error EFL_NET_HTTP_ERROR_REMOTE_FILE_EXISTS;
extern Eina_Error EFL_NET_HTTP_ERROR_REMOTE_FILE_NOT_FOUND;
extern Eina_Error EFL_NET_HTTP_ERROR_SEND_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_SEND_FAIL_REWIND;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CACERT;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CACERT_BADFILE;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CERTPROBLEM;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CIPHER;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CONNECT_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_CRL_BADFILE;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_INITFAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_NOTFOUND;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_SETFAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_INVALIDCERTSTATUS;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_ISSUER_ERROR;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_PINNEDPUBKEYNOTMATCH;
extern Eina_Error EFL_NET_HTTP_ERROR_SSL_SHUTDOWN_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_TOO_MANY_REDIRECTS;
extern Eina_Error EFL_NET_HTTP_ERROR_UNKNOWN_OPTION;
extern Eina_Error EFL_NET_HTTP_ERROR_UNSUPPORTED_PROTOCOL;
extern Eina_Error EFL_NET_HTTP_ERROR_UPLOAD_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_URL_MALFORMAT;
extern Eina_Error EFL_NET_HTTP_ERROR_USE_SSL_FAILED;
extern Eina_Error EFL_NET_HTTP_ERROR_WRITE_ERROR;
#include "efl_net_dialer_http.eo.h"

View File

@ -26,6 +26,204 @@ Ecore_Con_Curl *_c = NULL;
Eina_Bool _c_fail = EINA_FALSE;
double _c_timeout = 0.0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_BAD_CONTENT_ENCODING = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_BAD_DOWNLOAD_RESUME = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_BAD_FUNCTION_ARGUMENT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_CHUNK_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_CONV_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_CONV_REQD = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_COULDNT_CONNECT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_COULDNT_RESOLVE_HOST = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_COULDNT_RESOLVE_PROXY = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_FAILED_INIT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_FILE_COULDNT_READ_FILE = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_FILESIZE_EXCEEDED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_FUNCTION_NOT_FOUND = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_GOT_NOTHING = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_HTTP2 = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_HTTP2_STREAM = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_HTTP_POST_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_HTTP_RETURNED_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_INTERFACE_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_LOGIN_DENIED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_NO_CONNECTION_AVAILABLE = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_NOT_BUILT_IN = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_OPERATION_TIMEDOUT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_PARTIAL_FILE = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_PEER_FAILED_VERIFICATION = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_RANGE_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_READ_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_RECV_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_REMOTE_ACCESS_DENIED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_REMOTE_DISK_FULL = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_REMOTE_FILE_EXISTS = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_REMOTE_FILE_NOT_FOUND = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SEND_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SEND_FAIL_REWIND = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CACERT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CACERT_BADFILE = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CERTPROBLEM = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CIPHER = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CONNECT_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_CRL_BADFILE = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_INITFAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_NOTFOUND = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_ENGINE_SETFAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_INVALIDCERTSTATUS = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_ISSUER_ERROR = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_PINNEDPUBKEYNOTMATCH = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_SSL_SHUTDOWN_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_TOO_MANY_REDIRECTS = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_UNKNOWN_OPTION = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_UNSUPPORTED_PROTOCOL = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_UPLOAD_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_URL_MALFORMAT = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_USE_SSL_FAILED = 0;
EAPI Eina_Error EFL_NET_HTTP_ERROR_WRITE_ERROR = 0;
Eina_Error
_curlcode_to_eina_error(const CURLcode code)
{
switch (code) {
case CURLE_OK: return 0;
case CURLE_ABORTED_BY_CALLBACK: return ECONNABORTED;
case CURLE_AGAIN: return EAGAIN;
case CURLE_OUT_OF_MEMORY: return ENOMEM;
#define _MAP(n) case CURLE_ ## n: return EFL_NET_HTTP_ERROR_ ## n
_MAP(BAD_CONTENT_ENCODING);
_MAP(BAD_DOWNLOAD_RESUME);
_MAP(BAD_FUNCTION_ARGUMENT);
_MAP(CHUNK_FAILED);
_MAP(CONV_FAILED);
_MAP(CONV_REQD);
_MAP(COULDNT_CONNECT);
_MAP(COULDNT_RESOLVE_HOST);
_MAP(COULDNT_RESOLVE_PROXY);
_MAP(FAILED_INIT);
_MAP(FILE_COULDNT_READ_FILE);
_MAP(FILESIZE_EXCEEDED);
_MAP(FUNCTION_NOT_FOUND);
_MAP(GOT_NOTHING);
_MAP(HTTP2);
_MAP(HTTP2_STREAM);
_MAP(HTTP_POST_ERROR);
_MAP(HTTP_RETURNED_ERROR);
_MAP(INTERFACE_FAILED);
_MAP(LOGIN_DENIED);
_MAP(NO_CONNECTION_AVAILABLE);
_MAP(NOT_BUILT_IN);
_MAP(OPERATION_TIMEDOUT);
_MAP(PARTIAL_FILE);
_MAP(PEER_FAILED_VERIFICATION);
_MAP(RANGE_ERROR);
_MAP(READ_ERROR);
_MAP(RECV_ERROR);
_MAP(REMOTE_ACCESS_DENIED);
_MAP(REMOTE_DISK_FULL);
_MAP(REMOTE_FILE_EXISTS);
_MAP(REMOTE_FILE_NOT_FOUND);
_MAP(SEND_ERROR);
_MAP(SEND_FAIL_REWIND);
_MAP(SSL_CACERT);
_MAP(SSL_CACERT_BADFILE);
_MAP(SSL_CERTPROBLEM);
_MAP(SSL_CIPHER);
_MAP(SSL_CONNECT_ERROR);
_MAP(SSL_CRL_BADFILE);
_MAP(SSL_ENGINE_INITFAILED);
_MAP(SSL_ENGINE_NOTFOUND);
_MAP(SSL_ENGINE_SETFAILED);
_MAP(SSL_INVALIDCERTSTATUS);
_MAP(SSL_ISSUER_ERROR);
_MAP(SSL_PINNEDPUBKEYNOTMATCH);
_MAP(SSL_SHUTDOWN_FAILED);
_MAP(TOO_MANY_REDIRECTS);
_MAP(UNKNOWN_OPTION);
_MAP(UNSUPPORTED_PROTOCOL);
_MAP(UPLOAD_FAILED);
_MAP(URL_MALFORMAT);
_MAP(USE_SSL_FAILED);
_MAP(WRITE_ERROR);
#undef _MAP
default:
ERR("unexpected error CURcode=%d '%s', not mapped",
code, _c->curl_easy_strerror(code));
return EINVAL;
}
}
static void
_c_init_errors(void)
{
/* use from system: */
// CURLE_ABORTED_BY_CALLBACK = ECONNABORTED
// CURLE_AGAIN = EAGAIN
// CURLE_OUT_OF_MEMORY = ENOMEM
if (EFL_NET_HTTP_ERROR_BAD_CONTENT_ENCODING) return; /* only once in the whole runtime */
#define _MAP(n) EFL_NET_HTTP_ERROR_ ## n = eina_error_msg_static_register(_c->curl_easy_strerror(CURLE_ ## n))
_MAP(BAD_CONTENT_ENCODING);
_MAP(BAD_DOWNLOAD_RESUME);
_MAP(BAD_FUNCTION_ARGUMENT);
_MAP(CHUNK_FAILED);
_MAP(CONV_FAILED);
_MAP(CONV_REQD);
_MAP(COULDNT_CONNECT);
_MAP(COULDNT_RESOLVE_HOST);
_MAP(COULDNT_RESOLVE_PROXY);
_MAP(FAILED_INIT);
_MAP(FILE_COULDNT_READ_FILE);
_MAP(FILESIZE_EXCEEDED);
_MAP(FUNCTION_NOT_FOUND);
_MAP(GOT_NOTHING);
_MAP(HTTP2);
_MAP(HTTP2_STREAM);
_MAP(HTTP_POST_ERROR);
_MAP(HTTP_RETURNED_ERROR);
_MAP(INTERFACE_FAILED);
_MAP(LOGIN_DENIED);
_MAP(NO_CONNECTION_AVAILABLE);
_MAP(NOT_BUILT_IN);
_MAP(OPERATION_TIMEDOUT);
_MAP(PARTIAL_FILE);
_MAP(PEER_FAILED_VERIFICATION);
_MAP(RANGE_ERROR);
_MAP(READ_ERROR);
_MAP(RECV_ERROR);
_MAP(REMOTE_ACCESS_DENIED);
_MAP(REMOTE_DISK_FULL);
_MAP(REMOTE_FILE_EXISTS);
_MAP(REMOTE_FILE_NOT_FOUND);
_MAP(SEND_ERROR);
_MAP(SEND_FAIL_REWIND);
_MAP(SSL_CACERT);
_MAP(SSL_CACERT_BADFILE);
_MAP(SSL_CERTPROBLEM);
_MAP(SSL_CIPHER);
_MAP(SSL_CONNECT_ERROR);
_MAP(SSL_CRL_BADFILE);
_MAP(SSL_ENGINE_INITFAILED);
_MAP(SSL_ENGINE_NOTFOUND);
_MAP(SSL_ENGINE_SETFAILED);
_MAP(SSL_INVALIDCERTSTATUS);
_MAP(SSL_ISSUER_ERROR);
_MAP(SSL_PINNEDPUBKEYNOTMATCH);
_MAP(SSL_SHUTDOWN_FAILED);
_MAP(TOO_MANY_REDIRECTS);
_MAP(UNKNOWN_OPTION);
_MAP(UNSUPPORTED_PROTOCOL);
_MAP(UPLOAD_FAILED);
_MAP(URL_MALFORMAT);
_MAP(USE_SSL_FAILED);
_MAP(WRITE_ERROR);
#undef _MAP
}
Eina_Bool
_c_init(void)
{
@ -88,15 +286,20 @@ _c_init(void)
SYM(curl_multi_perform);
SYM(curl_multi_add_handle);
SYM(curl_multi_setopt);
SYM(curl_multi_socket_action);
SYM(curl_multi_assign);
SYM(curl_easy_init);
SYM(curl_easy_setopt);
SYM(curl_easy_strerror);
SYM(curl_easy_cleanup);
SYM(curl_easy_getinfo);
SYM(curl_easy_pause);
SYM(curl_slist_free_all);
SYM(curl_slist_append);
SYM(curl_version_info);
_c_init_errors();
// curl_global_init() is not thread safe!
if (_c->curl_global_init(CURL_GLOBAL_ALL)) goto error;
_c->_curlm = _c->curl_multi_init();

View File

@ -1,6 +1,14 @@
#ifndef ECORE_CON_URL_CURL_H
#define ECORE_CON_URL_CURL_H 1
#ifdef USE_CURL_H
/* During development you can set USE_CURL_H to use the system's
* curl.h instead of the local replicated values, it will provide all
* constants and type-checking.
*/
#include <curl/curl.h>
#else
// all the types, defines, enums etc. from curl that we actually USE.
// we have to add to this if we use more things from curl not already
// defined here. see curl headers to get them from
@ -9,13 +17,173 @@ typedef enum
CURLM_CALL_MULTI_PERFORM = -1,
CURLM_OK = 0
} CURLMcode;
typedef enum
{
CURLE_OK = 0,
CURLE_OPERATION_TIMEDOUT = 28
#ifndef curl_socket_typedef
/* socket typedef */
#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
typedef int curl_socket_t;
#define CURL_SOCKET_BAD -1
#endif
#define curl_socket_typedef
#endif /* curl_socket_typedef */
#define CURL_POLL_NONE 0
#define CURL_POLL_IN 1
#define CURL_POLL_OUT 2
#define CURL_POLL_INOUT 3
#define CURL_POLL_REMOVE 4
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
#define CURL_CSELECT_IN 0x01
#define CURL_CSELECT_OUT 0x02
#define CURL_CSELECT_ERR 0x04
typedef enum {
CURLINFO_TEXT = 0,
CURLINFO_HEADER_IN, /* 1 */
CURLINFO_HEADER_OUT, /* 2 */
CURLINFO_DATA_IN, /* 3 */
CURLINFO_DATA_OUT, /* 4 */
CURLINFO_SSL_DATA_IN, /* 5 */
CURLINFO_SSL_DATA_OUT, /* 6 */
CURLINFO_END
} curl_infotype;
typedef enum {
CURLE_OK = 0,
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
CURLE_FAILED_INIT, /* 2 */
CURLE_URL_MALFORMAT, /* 3 */
CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
7.17.0, reused in April 2011 for 7.21.5] */
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
CURLE_COULDNT_CONNECT, /* 7 */
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
due to lack of access - when login fails
this is not returned. */
CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
7.15.4, reused in Dec 2011 for 7.24.0]*/
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
[was obsoleted in August 2007 for 7.17.0,
reused in Dec 2011 for 7.24.0]*/
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
CURLE_FTP_CANT_GET_HOST, /* 15 */
CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
[was obsoleted in August 2007 for 7.17.0,
reused in July 2014 for 7.38.0] */
CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
CURLE_PARTIAL_FILE, /* 18 */
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
CURLE_OBSOLETE20, /* 20 - NOT USED */
CURLE_QUOTE_ERROR, /* 21 - quote command failure */
CURLE_HTTP_RETURNED_ERROR, /* 22 */
CURLE_WRITE_ERROR, /* 23 */
CURLE_OBSOLETE24, /* 24 - NOT USED */
CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
CURLE_OUT_OF_MEMORY, /* 27 */
/* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
instead of a memory allocation error if CURL_DOES_CONVERSIONS
is defined
*/
CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
CURLE_OBSOLETE29, /* 29 - NOT USED */
CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
CURLE_OBSOLETE32, /* 32 - NOT USED */
CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
CURLE_HTTP_POST_ERROR, /* 34 */
CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
CURLE_FILE_COULDNT_READ_FILE, /* 37 */
CURLE_LDAP_CANNOT_BIND, /* 38 */
CURLE_LDAP_SEARCH_FAILED, /* 39 */
CURLE_OBSOLETE40, /* 40 - NOT USED */
CURLE_FUNCTION_NOT_FOUND, /* 41 */
CURLE_ABORTED_BY_CALLBACK, /* 42 */
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
CURLE_OBSOLETE44, /* 44 - NOT USED */
CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
CURLE_OBSOLETE46, /* 46 - NOT USED */
CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */
CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
CURLE_OBSOLETE50, /* 50 - NOT USED */
CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
wasn't verified fine */
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
default */
CURLE_SEND_ERROR, /* 55 - failed sending network data */
CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
CURLE_OBSOLETE57, /* 57 - NOT IN USE */
CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
that failed */
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
accepted and we failed to login */
CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
CURLE_TFTP_PERM, /* 69 - permission problem on server */
CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
CURLE_CONV_FAILED, /* 75 - conversion failed */
CURLE_CONV_REQD, /* 76 - caller must register conversion
callbacks using curl_easy_setopt options
CURLOPT_CONV_FROM_NETWORK_FUNCTION,
CURLOPT_CONV_TO_NETWORK_FUNCTION, and
CURLOPT_CONV_FROM_UTF8_FUNCTION */
CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
or wrong format */
CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
CURLE_SSH, /* 79 - error from the SSH layer, somewhat
generic so the error message will be of
interest when this has happened */
CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
connection */
CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
wait till it's ready and try again (Added
in 7.18.2) */
CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
wrong format (Added in 7.19.0) */
CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
7.19.0) */
CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
session will be queued */
CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
match */
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
*/
CURL_LAST /* never use! */
} CURLcode;
#define CURLOPTTYPE_LONG 0
#define CURLOPTTYPE_OBJECTPOINT 10000
#define CURLOPTTYPE_STRINGPOINT 10000
#define CURLOPTTYPE_FUNCTIONPOINT 20000
#define CURLOPTTYPE_OFF_T 30000
#define CINIT(na, t, nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
@ -29,6 +197,7 @@ typedef enum
CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
CINIT(READFUNCTION, FUNCTIONPOINT, 12),
CINIT(POSTFIELDS, OBJECTPOINT, 15),
CINIT(USERAGENT, STRINGPOINT, 18),
CINIT(HTTPHEADER, OBJECTPOINT, 23),
CINIT(WRITEHEADER, OBJECTPOINT, 29),
CINIT(COOKIEFILE, OBJECTPOINT, 31),
@ -40,6 +209,7 @@ typedef enum
CINIT(NOBODY, LONG, 44),
CINIT(UPLOAD, LONG, 46),
CINIT(POST, LONG, 47),
CINIT(PUT, LONG, 54),
CINIT(FOLLOWLOCATION, LONG, 52),
CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
CINIT(PROGRESSDATA, OBJECTPOINT, 57),
@ -47,18 +217,26 @@ typedef enum
CINIT(SSL_VERIFYPEER, LONG, 64),
CINIT(CAINFO, OBJECTPOINT, 65),
CINIT(CONNECTTIMEOUT, LONG, 78),
CINIT(CONNECTTIMEOUT_MS, LONG, 156),
CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
CINIT(HTTPGET, LONG, 80),
CINIT(COOKIEJAR, OBJECTPOINT, 82),
CINIT(HTTP_VERSION, LONG, 84),
CINIT(FTP_USE_EPSV, LONG, 85),
CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
CINIT(DEBUGDATA, OBJECTPOINT, 95),
CINIT(COOKIESESSION, LONG, 96),
CINIT(PROXYTYPE, LONG, 101),
CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
CINIT(PRIVATE, OBJECTPOINT, 103),
CINIT(HTTPAUTH, LONG, 107),
CINIT(INFILESIZE_LARGE, OFF_T, 115),
CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
CINIT(COOKIELIST, OBJECTPOINT, 135),
CINIT(USERNAME, OBJECTPOINT, 173),
CINIT(PASSWORD, OBJECTPOINT, 174)
CINIT(PASSWORD, OBJECTPOINT, 174),
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
} CURLoption;
#define CURLINFO_STRING 0x100000
#define CURLINFO_LONG 0x200000
@ -68,7 +246,15 @@ typedef enum
#define CURLINFO_TYPEMASK 0xf00000
typedef enum
{
CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
CURLINFO_PRIVATE = CURLINFO_STRING + 21,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
} CURLINFO;
typedef enum
{
@ -82,7 +268,11 @@ typedef enum
#define CINIT(name, type, num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
typedef enum
{
CINIT(PIPELINING, LONG, 3)
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
CINIT(SOCKETDATA, OBJECTPOINT, 2),
CINIT(PIPELINING, LONG, 3),
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
CINIT(TIMERDATA, OBJECTPOINT, 5)
} CURLMoption;
typedef enum
{
@ -92,8 +282,10 @@ typedef enum
} curl_TimeCond;
enum
{
CURL_HTTP_VERSION_NONE = 0,
CURL_HTTP_VERSION_1_0 = 1,
CURL_HTTP_VERSION_1_1 = 2,
CURL_HTTP_VERSION_2_0 = 3
};
typedef enum
{
@ -112,11 +304,26 @@ typedef enum
#define CURLOPT_READDATA CURLOPT_INFILE
#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
#define CURLVERSION_NOW CURLVERSION_FOURTH
#define CURLAUTH_NONE ((unsigned long)0)
#define CURLAUTH_BASIC (((unsigned long)1) << 0)
#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
#define CURLAUTH_DIGEST_IE (((unsigned long)1) << 4)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC | CURLAUTH_DIGEST_IE))
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
#define CURL_READFUNC_ABORT 0x10000000
#define CURL_READFUNC_PAUSE 0x10000001
#define CURL_WRITEFUNC_PAUSE 0x10000001
#define CURLPAUSE_RECV (1<<0)
#define CURLPAUSE_RECV_CONT (0)
#define CURLPAUSE_SEND (1<<2)
#define CURLPAUSE_SEND_CONT (0)
typedef void CURLM;
typedef void CURL;
@ -153,6 +360,9 @@ typedef struct
} data;
} CURLMsg;
#endif /* USE_CURL_H */
typedef struct _Ecore_Con_Curl Ecore_Con_Curl;
struct _Ecore_Con_Curl
@ -183,11 +393,19 @@ struct _Ecore_Con_Curl
CURL *curl_handle);
CURLMcode (*curl_multi_setopt)(CURLM *multi_handle,
CURLMoption option, ...);
CURLMcode (*curl_multi_socket_action)(CURLM *multi_handle,
curl_socket_t fd,
int ev_bitmask,
int *running_handles);
CURLMcode (*curl_multi_assign)(CURLM *multi_handle,
curl_socket_t sockfd,
void *sockp);
CURL *(*curl_easy_init)(void);
CURLcode (*curl_easy_setopt)(CURL *curl, CURLoption option, ...);
const char *(*curl_easy_strerror)(CURLcode);
void (*curl_easy_cleanup)(CURL *curl);
CURLcode (*curl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
CURLcode (*curl_easy_pause)(CURL *curl, int bitmask);
void (*curl_slist_free_all)(struct curl_slist *);
struct curl_slist *(*curl_slist_append)(struct curl_slist *list,
const char *string);
@ -202,5 +420,6 @@ extern double _c_timeout;
Eina_Bool _c_init(void);
void _c_shutdown(void);
Eina_Error _curlcode_to_eina_error(const CURLcode code);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
import efl_net_http_types;
enum Efl.Net.Dialer.Http.Primary_Mode {
auto,
download,
upload,
}
class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Sizer) { /* TODO: reader/writer should be from dialer->socket, but are being missed somehow... */
[[HTTP Dialer (Client).
The effective URL in use, if @.allow_redirects is $true will be
available as @Efl.Net.Socket.address_remote. The
@Efl.Net.Socket.address_local is an IP:PORT pair.
The dialer can do bi-directional information exchange. It can
also do a PUT and upload a file, or GET and download one. Anoter
case is to do a POST with some form values, including a file,
and retrieve its headers and response body. To make usage more
streamlined, choose your primary interest with @.primary_mode
then get some properties such as @Efl.Io.Sizer.size to report or
use what matters to your use case.
If @.allow_redirects is $true, multiple "connected" and
"resolved" signals will be dispatched, one for each
connection. Then @.response_status and @.response_headers_get
will keep changing. Using @.response_headers_all_get one can see
the whole history of headers and connections.
To enable debugging use EINA_LOG_LEVELS=ecore_con:4 environment
variable.
@since 1.19
]]
methods {
@property method {
[[The HTTP method to use.
A string representing the HTTP method to use, such as
GET, POST, HEAD, PUT, DELETE...
This should be set before dialing.
]]
get { }
set { }
values {
method: string;
}
}
@property primary_mode {
[[Is this request primarily a download or upload?
This property will change the behavior of @Efl.Io.Sizer:
- if @Efl.Net.Dialer.Http.Primary_Mode.auto, then
@Efl.Net.Dialer.Http.Primary_Mode.download or
@Efl.Net.Dialer.Http.Primary_Mode.upload will be
choosen based on the @.method: if "PUT", then it's
upload, otherwise it's download.
- if @Efl.Net.Dialer.Http.Primary_Mode.upload, applying
a new size with @Efl.Io.Sizer.resize or
@Efl.Io.Sizer.size.set will specify the
"Content-Length" to upload. If no size is previously
set, then the upload will happen in
"Transfer-encoding: chunked".
- if @Efl.Net.Dialer.Http.Primary_Mode.download, then
@Efl.Io.Sizer.size.get will report the
"Content-Length" provided by the server, if any.
If is worth to mention that one can provide and
retrieve these values using @.request_headers_get (to
send) and @.response_headers_get (what was received),
as well as using the specific properties
@.request_content_length (upload) and
@.response_content_length (download).
]]
get {
[[The effective primary mode.
This will return one of
@Efl.Net.Dialer.Http.Primary_Mode.download or
@Efl.Net.Dialer.Http.Primary_Mode.upload. If "auto"
was set (the default), then it will pick the best
based on the @.method in use.
]]
}
set { }
values {
primary_mode: Efl.Net.Dialer.Http.Primary_Mode;
}
}
@property user_agent {
[[The User-Agent to specify.
This should be set before dialing.
]]
get { }
set { }
values {
user_agent: string;
}
}
@property http_version {
[[The HTTP version to use.
This should be set before dialing.
Once connected, it will change to the actual connection
HTTP version, so check after "connected" event.
]]
get { }
set { }
values {
http_version: Efl.Net.Http.Version;
}
}
@property authentication {
[[HTTP authentication to use.
This should be set before dialing.
]]
get { }
set { }
values {
username: string;
password: string;
method: Efl.Net.Http.Authentication_Method @optional; [[authentication method to use, defaults to @Efl.Net.Http.Authentication_Method.basic]]
restricted: bool @optional; [[restrict method]]
}
}
@property allow_redirects {
[[Allow HTTP redirects to be followed.
This should be set before dialing.
]]
get { }
set { }
values {
allow_redirects: bool;
}
}
request_header_add {
[[Add a request header 'key: value'.
See @.request_headers_clear
This should be called before dialing.
]]
params {
@in key: string;
@in value: string;
}
}
request_headers_clear {
[[Clear all request headers.
See @.request_header_add
This should be called before dialing.
]]
}
request_headers_get {
[[Return an iterator to the key-value pairs for request headers]]
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
}
@property request_content_length {
[["Content-Length:" Header used for uploading/sending.
To unset use -1
]]
get { }
set { }
values {
length: int64;
}
}
@property response_content_length {
[["Content-Length:" Header used for downloading/receiving.
If unset is -1.
]]
get { }
set @protected { }
values {
length: int64;
}
}
@property response_content_type {
[["Content-Type:" Header used for downloading/receiving]]
get { }
set @protected { }
values {
content_type: string;
}
}
@property response_status {
[[The HTTP response status of this request.
It will be 0 if not connected, otherwise will be what is
returned by the server, such as.
See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
This will be usable after "connected" event is dispatched.
]]
get { }
values {
status_code: Efl.Net.Http.Status;
}
}
response_headers_get {
[[Return an iterator to the key-value pairs for the last response headers.
Since multiple requests can happen if @.allow_redirects
is true, then all headers will be accumulated. This
method returns only the headers for the last request.
To know all the headers, check @.response_headers_all_get.
This will be usable after "headers,done" event is dispatched.
]]
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
}
response_headers_all_get {
[[Return an iterator to the key-value pairs for all response headers.
Since multiple requests can happen if @.allow_redirects
is true, then all headers will be accumulated. To know
when new request is started, check for headers with keys
being NULL, the value will be the "HTTP/VERSION RESPONSE"
string received from the host, such as:
- key=NULL, value="HTTP/1.1 302 Found"
- key="Location", value="http://someredirect.com"
- key=NULL, value="HTTP/1.1 200 Ok"
- key="Content-Type", value="text/html"
Which mean the original request had a redirect to
http://someredirect.com.
To receive an iterator to just the last request, use
@.response_headers_get
This will be usable after "headers,done" event is dispatched.
]]
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
}
response_headers_clear {
[[Save some memory by disposing the received headers]]
}
@property progress_download {
[[How many bytes were downloaded and how much was expected.]]
get { }
values {
downloaded: uint64 @optional;
total: uint64 @optional; [[0 if unknown]]
}
}
@property progress_upload {
[[How many bytes were uploaded and how much was expected.]]
get { }
values {
uploaded: uint64 @optional;
total: uint64 @optional; [[0 if unknown]]
}
}
}
events {
headers,done; [[Notifies all headers were parsed and are available.]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Net.Dialer.dial;
Efl.Net.Dialer.address_dial;
Efl.Net.Dialer.connected;
Efl.Net.Dialer.timeout_dial;
Efl.Net.Socket.address_local;
Efl.Net.Socket.address_remote;
Efl.Io.Reader.read;
Efl.Io.Reader.can_read.get;
Efl.Io.Reader.can_read.set;
Efl.Io.Reader.eos.get;
Efl.Io.Reader.eos.set;
Efl.Io.Writer.write;
Efl.Io.Writer.can_write.get;
Efl.Io.Writer.can_write.set;
Efl.Io.Closer.close;
Efl.Io.Closer.closed.get;
Efl.Io.Sizer.resize;
Efl.Io.Sizer.size.get;
}
}

View File

@ -0,0 +1,176 @@
import eina_types;
enum Efl.Net.Http.Version {
v1_0 = 100, [[1.0]]
v1_1 = 101, [[1.1]]
v2_0 = 200, [[2.0]]
}
enum Efl.Net.Http.Authentication_Method {
none = 0,
basic = (1 << 0),
digest = (1 << 1),
negotiate = (1 << 2),
ntlm = (1 << 3),
ntlm_winbind = (1 << 4),
any_safe = Efl.Net.Http.Authentication_Method.digest | Efl.Net.Http.Authentication_Method.negotiate | Efl.Net.Http.Authentication_Method.ntlm | Efl.Net.Http.Authentication_Method.ntlm_winbind,
any = Efl.Net.Http.Authentication_Method.any_safe | Efl.Net.Http.Authentication_Method.basic,
}
enum Efl.Net.Http.Status {
[[Common HTTP status codes]]
unknown = 0, [[unknown status, likely not connected]]
/* Informational: 1xx */
continue = 100,
switching_protocols = 101,
checkpoint = 103, /* unofficial extension */
processing = 102,
/* success: 2xx */
ok = 200,
created = 201,
accepted = 202,
non_authoritative_information = 203,
no_content = 204,
reset_content = 205,
partial_content = 206,
multi_status = 207,
already_reported = 208,
im_used = 226,
/* redirection: 3xx */
multiple_choices = 300,
moved_permanently = 301,
found = 302,
see_other = 303,
not_modified = 304,
use_proxy = 305,
switch_proxy = 306,
temporary_redirect = 307,
permanent_redirect = 308,
/* client error: 4xx */
bad_request = 400,
unauthorized = 401,
payment_required = 402,
forbidden = 403,
not_found = 404,
method_not_allowed = 405,
not_acceptable = 406,
proxy_authentication_required = 407,
request_timeout = 408,
conflict = 409,
gone = 410,
length_required = 411,
precondition_failed = 412,
payload_too_large = 413,
uri_too_long = 414,
unsupported_media_type = 415,
range_not_satisfiable = 416,
expectation_failed = 417,
misdirected_request = 421,
unprocessable_entity = 422,
locked = 423,
failed_dependency = 424,
upgrade_required = 426,
precondition_required = 428,
too_many_requests = 429,
request_header_fields_too_large = 431,
login_timeout = 440, /* unofficial extension */
no_response = 444, /* unofficial extension */
retry_with = 449, /* unofficial extension */
blocked_by_windows_parental_controls = 450, /* unofficial extension */
unavailable_for_legal_reasons = 451,
ssl_certificate_error = 495, /* unofficial extension */
ssl_certificate_required = 496, /* unofficial extension */
http_request_sent_to_https_port = 497, /* unofficial extension */
request_has_been_forbidden_by_antivirus = 499,
/* server error: 5xx */
internal_server_error = 500,
not_implemented = 501,
bad_gateway = 502,
service_unavailable = 503,
gateway_timeout = 504,
http_version_not_supported = 505,
variant_also_negotiates = 506,
insufficient_storage = 507,
loop_detected = 508,
bandwidth_limit_exceeded = 509, /* unofficial extension */
not_extended = 510,
network_authentication_required = 511,
}
struct Efl.Net.Http.Header {
[[An HTTP Header.
Do not assume strings are Eina_Stringshare and they may be
NULL. The key and value should not include any trailing
whitespace.
There is a special case for response headers when
"allow_redirects" is enabled, in that case
efl_net_dialer_http_response_headers_all_get() will return some
items with key being NULL, that notifies of a new request as
described in the value "HTTP/1.1 200 Ok".
]]
key: string; [[for response headers this may be null to indicate a new request response, then the value will be a line such as 'HTTP/1.1 200 Ok']]
value: string;
}
var @extern Efl.Net.Http.Error.BAD_CONTENT_ENCODING: Eina.Error;
var @extern Efl.Net.Http.Error.BAD_DOWNLOAD_RESUME: Eina.Error;
var @extern Efl.Net.Http.Error.BAD_FUNCTION_ARGUMENT: Eina.Error;
var @extern Efl.Net.Http.Error.CHUNK_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.CONV_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.CONV_REQD: Eina.Error;
var @extern Efl.Net.Http.Error.COULDNT_CONNECT: Eina.Error;
var @extern Efl.Net.Http.Error.COULDNT_RESOLVE_HOST: Eina.Error;
var @extern Efl.Net.Http.Error.COULDNT_RESOLVE_PROXY: Eina.Error;
var @extern Efl.Net.Http.Error.FAILED_INIT: Eina.Error;
var @extern Efl.Net.Http.Error.FILE_COULDNT_READ_FILE: Eina.Error;
var @extern Efl.Net.Http.Error.FILESIZE_EXCEEDED: Eina.Error;
var @extern Efl.Net.Http.Error.FUNCTION_NOT_FOUND: Eina.Error;
var @extern Efl.Net.Http.Error.GOT_NOTHING: Eina.Error;
var @extern Efl.Net.Http.Error.HTTP2: Eina.Error;
var @extern Efl.Net.Http.Error.HTTP2_STREAM: Eina.Error;
var @extern Efl.Net.Http.Error.HTTP_POST_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.HTTP_RETURNED_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.INTERFACE_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.LOGIN_DENIED: Eina.Error;
var @extern Efl.Net.Http.Error.NO_CONNECTION_AVAILABLE: Eina.Error;
var @extern Efl.Net.Http.Error.NOT_BUILT_IN: Eina.Error;
var @extern Efl.Net.Http.Error.OPERATION_TIMEDOUT: Eina.Error;
var @extern Efl.Net.Http.Error.PARTIAL_FILE: Eina.Error;
var @extern Efl.Net.Http.Error.PEER_FAILED_VERIFICATION: Eina.Error;
var @extern Efl.Net.Http.Error.RANGE_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.READ_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.RECV_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.REMOTE_ACCESS_DENIED: Eina.Error;
var @extern Efl.Net.Http.Error.REMOTE_DISK_FULL: Eina.Error;
var @extern Efl.Net.Http.Error.REMOTE_FILE_EXISTS: Eina.Error;
var @extern Efl.Net.Http.Error.REMOTE_FILE_NOT_FOUND: Eina.Error;
var @extern Efl.Net.Http.Error.SEND_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.SEND_FAIL_REWIND: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CACERT: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CACERT_BADFILE: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CERTPROBLEM: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CIPHER: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CONNECT_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_CRL_BADFILE: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_ENGINE_INITFAILED: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_ENGINE_NOTFOUND: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_ENGINE_SETFAILED: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_INVALIDCERTSTATUS: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_ISSUER_ERROR: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_PINNEDPUBKEYNOTMATCH: Eina.Error;
var @extern Efl.Net.Http.Error.SSL_SHUTDOWN_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.TOO_MANY_REDIRECTS: Eina.Error;
var @extern Efl.Net.Http.Error.UNKNOWN_OPTION: Eina.Error;
var @extern Efl.Net.Http.Error.UNSUPPORTED_PROTOCOL: Eina.Error;
var @extern Efl.Net.Http.Error.UPLOAD_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.URL_MALFORMAT: Eina.Error;
var @extern Efl.Net.Http.Error.USE_SSL_FAILED: Eina.Error;
var @extern Efl.Net.Http.Error.WRITE_ERROR: Eina.Error;