diff options
author | Gustavo Sverzut Barbieri <barbieri@profusion.mobi> | 2016-08-29 23:35:31 -0300 |
---|---|---|
committer | Gustavo Sverzut Barbieri <barbieri@profusion.mobi> | 2016-08-30 00:36:00 -0300 |
commit | b004b8a4f986f49e23c3314e7f59d4fb8f4fd524 (patch) | |
tree | 84db1cff0c4d60f16a3759f2dedb31bb9b0d45ff | |
parent | f1c691d0f54c13ad76163ce419cbc54f2b3b2afc (diff) |
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.
-rw-r--r-- | src/lib/ecore_con/ecore_con_url_curl.h | 20 | ||||
-rw-r--r-- | src/lib/ecore_con/efl_net_dialer_http.c | 46 |
2 files changed, 62 insertions, 4 deletions
diff --git a/src/lib/ecore_con/ecore_con_url_curl.h b/src/lib/ecore_con/ecore_con_url_curl.h index ff9ad170a3..98d4a1ee8d 100644 --- a/src/lib/ecore_con/ecore_con_url_curl.h +++ b/src/lib/ecore_con/ecore_con_url_curl.h | |||
@@ -40,6 +40,22 @@ typedef int curl_socket_t; | |||
40 | #define curl_socket_typedef | 40 | #define curl_socket_typedef |
41 | #endif /* curl_socket_typedef */ | 41 | #endif /* curl_socket_typedef */ |
42 | 42 | ||
43 | typedef enum { | ||
44 | CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ | ||
45 | CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ | ||
46 | CURLSOCKTYPE_LAST /* never use */ | ||
47 | } curlsocktype; | ||
48 | |||
49 | struct curl_sockaddr { | ||
50 | int family; | ||
51 | int socktype; | ||
52 | int protocol; | ||
53 | unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it | ||
54 | turned really ugly and painful on the systems that | ||
55 | lack this type */ | ||
56 | struct sockaddr addr; | ||
57 | }; | ||
58 | |||
43 | #define CURL_POLL_NONE 0 | 59 | #define CURL_POLL_NONE 0 |
44 | #define CURL_POLL_IN 1 | 60 | #define CURL_POLL_IN 1 |
45 | #define CURL_POLL_OUT 2 | 61 | #define CURL_POLL_OUT 2 |
@@ -243,8 +259,12 @@ typedef enum | |||
243 | CINIT(INFILESIZE_LARGE, OFF_T, 115), | 259 | CINIT(INFILESIZE_LARGE, OFF_T, 115), |
244 | CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), | 260 | CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), |
245 | CINIT(COOKIELIST, OBJECTPOINT, 135), | 261 | CINIT(COOKIELIST, OBJECTPOINT, 135), |
262 | CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), | ||
263 | CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), | ||
246 | CINIT(USERNAME, OBJECTPOINT, 173), | 264 | CINIT(USERNAME, OBJECTPOINT, 173), |
247 | CINIT(PASSWORD, OBJECTPOINT, 174), | 265 | CINIT(PASSWORD, OBJECTPOINT, 174), |
266 | CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), | ||
267 | CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), | ||
248 | CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), | 268 | CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), |
249 | #define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA | 269 | #define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA |
250 | } CURLoption; | 270 | } CURLoption; |
diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index 68477ac6c3..06c5743d3c 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c | |||
@@ -200,6 +200,7 @@ typedef struct | |||
200 | Efl_Net_Http_Authentication_Method method; | 200 | Efl_Net_Http_Authentication_Method method; |
201 | Eina_Bool restricted; | 201 | Eina_Bool restricted; |
202 | } authentication; | 202 | } authentication; |
203 | int fd; | ||
203 | Eina_Error error; | 204 | Eina_Error error; |
204 | Efl_Net_Http_Version version; | 205 | Efl_Net_Http_Version version; |
205 | Efl_Net_Dialer_Http_Primary_Mode primary_mode; | 206 | 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 | |||
928 | return len; | 929 | return len; |
929 | } | 930 | } |
930 | 931 | ||
932 | static curl_socket_t | ||
933 | _efl_net_dialer_http_socket_open(void *data, curlsocktype purpose EINA_UNUSED, struct curl_sockaddr *addr) | ||
934 | { | ||
935 | Eo *o = data; | ||
936 | Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS); | ||
937 | |||
938 | pd->fd = socket(addr->family, addr->socktype, addr->protocol); | ||
939 | if (pd->fd < 0) | ||
940 | ERR("could not create curl socket family=%d, type=%d, protocol=%d", | ||
941 | addr->family, addr->socktype, addr->protocol); | ||
942 | else | ||
943 | DBG("socket(%d, %d, %d) = %d", | ||
944 | addr->family, addr->socktype, addr->protocol, pd->fd); | ||
945 | |||
946 | return pd->fd; | ||
947 | } | ||
948 | |||
949 | static void | ||
950 | _efl_net_dialer_http_socket_close(void *data, curl_socket_t fd) | ||
951 | { | ||
952 | Eo *o = data; | ||
953 | Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS); | ||
954 | |||
955 | EINA_SAFETY_ON_TRUE_RETURN(pd->fd != fd); | ||
956 | |||
957 | DBG("close(%d)", fd); | ||
958 | |||
959 | close(fd); | ||
960 | pd->fd = -1; | ||
961 | } | ||
962 | |||
931 | EOLIAN static Efl_Object * | 963 | EOLIAN static Efl_Object * |
932 | _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) | 964 | _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) |
933 | { | 965 | { |
@@ -961,6 +993,12 @@ _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) | |||
961 | curl_easy_setopt(pd->easy, CURLOPT_READFUNCTION, _efl_net_dialer_http_send_data); | 993 | curl_easy_setopt(pd->easy, CURLOPT_READFUNCTION, _efl_net_dialer_http_send_data); |
962 | curl_easy_setopt(pd->easy, CURLOPT_READDATA, o); | 994 | curl_easy_setopt(pd->easy, CURLOPT_READDATA, o); |
963 | 995 | ||
996 | curl_easy_setopt(pd->easy, CURLOPT_OPENSOCKETFUNCTION, _efl_net_dialer_http_socket_open); | ||
997 | curl_easy_setopt(pd->easy, CURLOPT_OPENSOCKETDATA, o); | ||
998 | |||
999 | curl_easy_setopt(pd->easy, CURLOPT_CLOSESOCKETFUNCTION, _efl_net_dialer_http_socket_close); | ||
1000 | curl_easy_setopt(pd->easy, CURLOPT_CLOSESOCKETDATA, o); | ||
1001 | |||
964 | curl_easy_setopt(pd->easy, CURLOPT_NOPROGRESS, 0L); | 1002 | curl_easy_setopt(pd->easy, CURLOPT_NOPROGRESS, 0L); |
965 | 1003 | ||
966 | curl_easy_setopt(pd->easy, CURLOPT_VERBOSE, (long)(eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))); | 1004 | 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 | |||
1256 | 1294 | ||
1257 | pd->error = 0; | 1295 | pd->error = 0; |
1258 | rm = curl_multi_socket_action(pd->cm->multi, | 1296 | rm = curl_multi_socket_action(pd->cm->multi, |
1259 | ecore_main_fd_handler_fd_get(pd->fdhandler), | 1297 | pd->fd, |
1260 | CURL_CSELECT_OUT, &pd->cm->running); | 1298 | CURL_CSELECT_OUT, &pd->cm->running); |
1261 | if (rm != CURLM_OK) | 1299 | if (rm != CURLM_OK) |
1262 | { | 1300 | { |
1263 | err = _curlcode_to_eina_error(rm); | 1301 | err = _curlcode_to_eina_error(rm); |
1264 | ERR("dialer=%p could not trigger socket=%d action: %s", | 1302 | ERR("dialer=%p could not trigger socket=%d (fdhandler=%p) action: %s", |
1265 | o, ecore_main_fd_handler_fd_get(pd->fdhandler), | 1303 | o, pd->fd, pd->fdhandler, eina_error_msg_get(err)); |
1266 | eina_error_msg_get(err)); | ||
1267 | goto error; | 1304 | goto error; |
1268 | } | 1305 | } |
1269 | _efl_net_dialer_http_curlm_check(pd->cm); | 1306 | _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) | |||
1315 | 1352 | ||
1316 | if (pd->cm) | 1353 | if (pd->cm) |
1317 | { | 1354 | { |
1355 | DBG("close dialer=%p, cm=%p, easy=%p", o, pd->cm, pd->easy); | ||
1318 | _efl_net_dialer_http_curlm_remove(pd->cm, o, pd->easy); | 1356 | _efl_net_dialer_http_curlm_remove(pd->cm, o, pd->easy); |
1319 | pd->cm = NULL; | 1357 | pd->cm = NULL; |
1320 | } | 1358 | } |