forked from enlightenment/efl
efl_net_dialer_http: keep fd directly.
provide curl with CURLOPT_OPENSOCKETFUNCTION and keep the fd in our private data. This is required because on _efl_net_dialer_http_efl_io_writer_write() we may have no fdhandler. It happened to me while implementing the WebSocket that uses a bi-directional communication on top of HTTP and the server sent the whole message, CURL reads: recvfrom(7, "...", 16384, 0, NULL, NULL) = 86 recvfrom(7, "", 16384, 0, NULL, NULL) = 0 After the empty (second) recvfrom(), CURL will remove the fdhandler: DBG:ecore_con lib/ecore_con/efl_net_dialer_http.c:482 _efl_net_dialer_http_curlm_socket_manage() dialer=0x4000000040000005 fdhandler=(nil), fd=7, curl_easy=0x5561846ca8d0, flags=0x4 However I should be able to write to this socket, in my case I need to reply to a PING request with a PONG.
This commit is contained in:
parent
f1c691d0f5
commit
b004b8a4f9
|
@ -40,6 +40,22 @@ typedef int curl_socket_t;
|
|||
#define curl_socket_typedef
|
||||
#endif /* curl_socket_typedef */
|
||||
|
||||
typedef enum {
|
||||
CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
|
||||
CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
|
||||
CURLSOCKTYPE_LAST /* never use */
|
||||
} curlsocktype;
|
||||
|
||||
struct curl_sockaddr {
|
||||
int family;
|
||||
int socktype;
|
||||
int protocol;
|
||||
unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
|
||||
turned really ugly and painful on the systems that
|
||||
lack this type */
|
||||
struct sockaddr addr;
|
||||
};
|
||||
|
||||
#define CURL_POLL_NONE 0
|
||||
#define CURL_POLL_IN 1
|
||||
#define CURL_POLL_OUT 2
|
||||
|
@ -243,8 +259,12 @@ typedef enum
|
|||
CINIT(INFILESIZE_LARGE, OFF_T, 115),
|
||||
CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
|
||||
CINIT(COOKIELIST, OBJECTPOINT, 135),
|
||||
CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
|
||||
CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
|
||||
CINIT(USERNAME, OBJECTPOINT, 173),
|
||||
CINIT(PASSWORD, OBJECTPOINT, 174),
|
||||
CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
|
||||
CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
|
||||
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
|
||||
#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
|
||||
} CURLoption;
|
||||
|
|
|
@ -200,6 +200,7 @@ typedef struct
|
|||
Efl_Net_Http_Authentication_Method method;
|
||||
Eina_Bool restricted;
|
||||
} authentication;
|
||||
int fd;
|
||||
Eina_Error error;
|
||||
Efl_Net_Http_Version version;
|
||||
Efl_Net_Dialer_Http_Primary_Mode primary_mode;
|
||||
|
@ -928,6 +929,37 @@ _efl_net_dialer_http_receive_header(const char *buffer, size_t count, size_t nit
|
|||
return len;
|
||||
}
|
||||
|
||||
static curl_socket_t
|
||||
_efl_net_dialer_http_socket_open(void *data, curlsocktype purpose EINA_UNUSED, struct curl_sockaddr *addr)
|
||||
{
|
||||
Eo *o = data;
|
||||
Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
||||
|
||||
pd->fd = socket(addr->family, addr->socktype, addr->protocol);
|
||||
if (pd->fd < 0)
|
||||
ERR("could not create curl socket family=%d, type=%d, protocol=%d",
|
||||
addr->family, addr->socktype, addr->protocol);
|
||||
else
|
||||
DBG("socket(%d, %d, %d) = %d",
|
||||
addr->family, addr->socktype, addr->protocol, pd->fd);
|
||||
|
||||
return pd->fd;
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_net_dialer_http_socket_close(void *data, curl_socket_t fd)
|
||||
{
|
||||
Eo *o = data;
|
||||
Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
||||
|
||||
EINA_SAFETY_ON_TRUE_RETURN(pd->fd != fd);
|
||||
|
||||
DBG("close(%d)", fd);
|
||||
|
||||
close(fd);
|
||||
pd->fd = -1;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Object *
|
||||
_efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd)
|
||||
{
|
||||
|
@ -961,6 +993,12 @@ _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd)
|
|||
curl_easy_setopt(pd->easy, CURLOPT_READFUNCTION, _efl_net_dialer_http_send_data);
|
||||
curl_easy_setopt(pd->easy, CURLOPT_READDATA, o);
|
||||
|
||||
curl_easy_setopt(pd->easy, CURLOPT_OPENSOCKETFUNCTION, _efl_net_dialer_http_socket_open);
|
||||
curl_easy_setopt(pd->easy, CURLOPT_OPENSOCKETDATA, o);
|
||||
|
||||
curl_easy_setopt(pd->easy, CURLOPT_CLOSESOCKETFUNCTION, _efl_net_dialer_http_socket_close);
|
||||
curl_easy_setopt(pd->easy, CURLOPT_CLOSESOCKETDATA, o);
|
||||
|
||||
curl_easy_setopt(pd->easy, CURLOPT_NOPROGRESS, 0L);
|
||||
|
||||
curl_easy_setopt(pd->easy, CURLOPT_VERBOSE, (long)(eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)));
|
||||
|
@ -1256,14 +1294,13 @@ _efl_net_dialer_http_efl_io_writer_write(Eo *o, Efl_Net_Dialer_Http_Data *pd, Ei
|
|||
|
||||
pd->error = 0;
|
||||
rm = curl_multi_socket_action(pd->cm->multi,
|
||||
ecore_main_fd_handler_fd_get(pd->fdhandler),
|
||||
pd->fd,
|
||||
CURL_CSELECT_OUT, &pd->cm->running);
|
||||
if (rm != CURLM_OK)
|
||||
{
|
||||
err = _curlcode_to_eina_error(rm);
|
||||
ERR("dialer=%p could not trigger socket=%d action: %s",
|
||||
o, ecore_main_fd_handler_fd_get(pd->fdhandler),
|
||||
eina_error_msg_get(err));
|
||||
ERR("dialer=%p could not trigger socket=%d (fdhandler=%p) action: %s",
|
||||
o, pd->fd, pd->fdhandler, eina_error_msg_get(err));
|
||||
goto error;
|
||||
}
|
||||
_efl_net_dialer_http_curlm_check(pd->cm);
|
||||
|
@ -1315,6 +1352,7 @@ _efl_net_dialer_http_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Http_Data *pd)
|
|||
|
||||
if (pd->cm)
|
||||
{
|
||||
DBG("close dialer=%p, cm=%p, easy=%p", o, pd->cm, pd->easy);
|
||||
_efl_net_dialer_http_curlm_remove(pd->cm, o, pd->easy);
|
||||
pd->cm = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue