summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-08-29 23:35:31 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-08-30 00:36:00 -0300
commitb004b8a4f986f49e23c3314e7f59d4fb8f4fd524 (patch)
tree84db1cff0c4d60f16a3759f2dedb31bb9b0d45ff
parentf1c691d0f54c13ad76163ce419cbc54f2b3b2afc (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.h20
-rw-r--r--src/lib/ecore_con/efl_net_dialer_http.c46
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
43typedef 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
49struct 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
932static 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
949static 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
931EOLIAN static Efl_Object * 963EOLIAN 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 }