diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h index e2fab7a506..69102d7563 100644 --- a/src/lib/ecore_con/ecore_con_private.h +++ b/src/lib/ecore_con/ecore_con_private.h @@ -377,4 +377,78 @@ Eina_Bool efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr int efl_net_socket4(int domain, int type, int protocol, Eina_Bool close_on_exec); +static inline Eina_Error +efl_net_socket_error_get(void) +{ +#ifndef _WIN32 + return errno; +#else + Eina_Error err = WSAGetLastError(); + + if (0) { } + + /* used by send() */ +#if defined(WSAEACCES) && (WSAEACCES != EACCES) + else if (err == WSAEACCES) err = EACCES; +#endif +#if defined(WSAEWOULDBLOCK) && (WSAEWOULDBLOCK != EAGAIN) + else if (err == WSAEWOULDBLOCK) err = EAGAIN; +#endif +#if defined(WSAEBADF) && (WSAEBADF != EBADF) + else if (err == WSAEBADF) err = EBADF; +#endif +#if defined(WSAECONNRESET) && (WSAECONNRESET != ECONNRESET) + else if (err == WSAECONNRESET) err = ECONNRESET; +#endif +#if defined(WSAEDESTADDRREQ) && (WSAEDESTADDRREQ != EDESTADDRREQ) + else if (err == WSAEDESTADDRREQ) err = EDESTADDRREQ; +#endif +#if defined(WSAEFAULT) && (WSAEFAULT != EFAULT) + else if (err == WSAEFAULT) err = EFAULT; +#endif +#if defined(WSAEINTR) && (WSAEINTR != EINTR) + else if (err == WSAEINTR) err = EINTR; +#endif +#if defined(WSAEINVAL) && (WSAEINVAL != EINVAL) + else if (err == WSAEINVAL) err = EINVAL; +#endif +#if defined(WSAEISCONN) && (WSAEISCONN != EISCONN) + else if (err == WSAEISCONN) err = EISCONN; +#endif +#if defined(WSAEMSGSIZE) && (WSAEMSGSIZE != EMSGSIZE) + else if (err == WSAEMSGSIZE) err = EMSGSIZE; +#endif +#if defined(WSAENOBUFS) && (WSAENOBUFS != ENOBUFS) + else if (err == WSAENOBUFS) err = ENOBUFS; +#endif +#if defined(WSA_NOT_ENOUGH_MEMORY) && (WSA_NOT_ENOUGH_MEMORY != ENOMEM) + else if (err == WSA_NOT_ENOUGH_MEMORY) err = ENOMEM; +#endif +#if defined(WSAENOTCONN) && (WSAENOTCONN != ENOTCONN) + else if (err == WSAENOTCONN) err = ENOTCONN; +#endif +#if defined(WSAENOTSOCK) && (WSAENOTSOCK != ENOTSOCK) + else if (err == WSAENOTSOCK) err = ENOTSOCK; +#endif +#if defined(WSAEOPNOTSUPP) && (WSAEOPNOTSUPP != EOPNOTSUPP) + else if (err == WSAEOPNOTSUPP) err = EOPNOTSUPP; +#endif +#if defined(WSAESHUTDOWN) && (WSAESHUTDOWN != EPIPE) + else if (err == WSAESHUTDOWN) err = EPIPE; +#endif + + /* extras used by recv() */ +#if defined(WSAECONNREFUSED) && (WSAECONNREFUSED != ECONNREFUSED) + else if (err == WSAECONNREFUSED) err = ECONNREFUSED; +#endif + + /* extras used by getsockopt() */ +#if defined(WSAENOPROTOOPT) && (WSAENOPROTOOPT != ENOPROTOOPT) + else if (err == WSAENOPROTOOPT) err = ENOPROTOOPT; +#endif + + return err; +#endif +} + #endif diff --git a/src/lib/ecore_con/efl_net_socket_fd.c b/src/lib/ecore_con/efl_net_socket_fd.c index 0cc9152918..339e7efdfb 100644 --- a/src/lib/ecore_con/efl_net_socket_fd.c +++ b/src/lib/ecore_con/efl_net_socket_fd.c @@ -120,7 +120,7 @@ _efl_net_socket_fd_efl_loop_fd_fd_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, int fd) struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) < 0) - ERR("getsockname(%d): %s", fd, strerror(errno)); + ERR("getsockname(%d): %s", fd, eina_error_msg_get(efl_net_socket_error_get())); else efl_net_socket_fd_family_set(o, addr.ss_family); } @@ -157,25 +157,84 @@ _efl_net_socket_fd_efl_io_closer_close(Eo *o, Efl_Net_Socket_Fd_Data *pd EINA_UN EOLIAN static Eina_Error _efl_net_socket_fd_efl_io_reader_read(Eo *o, Efl_Net_Socket_Fd_Data *pd EINA_UNUSED, Eina_Rw_Slice *rw_slice) { - Eina_Error ret; + int fd = efl_io_reader_fd_reader_fd_get(o); + ssize_t r; - ret = efl_io_reader_read(efl_super(o, MY_CLASS), rw_slice); - if (rw_slice && rw_slice->len > 0) - efl_io_reader_can_read_set(o, EINA_FALSE); /* wait Efl.Loop.Fd "read" */ + EINA_SAFETY_ON_NULL_RETURN_VAL(rw_slice, EINVAL); + if (fd < 0) goto error; + do + { + r = recv(fd, rw_slice->mem, rw_slice->len, 0); + if (r < 0) + { + Eina_Error err = efl_net_socket_error_get(); - return ret; + if (err == EINTR) continue; + + rw_slice->len = 0; + rw_slice->mem = NULL; + + if (err == EAGAIN) efl_io_reader_can_read_set(o, EINA_FALSE); + return err; + } + } + while (r < 0); + + rw_slice->len = r; + efl_io_reader_can_read_set(o, EINA_FALSE); /* wait Efl.Loop.Fd "read" */ + if (r == 0) + efl_io_reader_eos_set(o, EINA_TRUE); + + return 0; + + error: + rw_slice->len = 0; + rw_slice->mem = NULL; + return EINVAL; } EOLIAN static Eina_Error _efl_net_socket_fd_efl_io_writer_write(Eo *o, Efl_Net_Socket_Fd_Data *pd EINA_UNUSED, Eina_Slice *ro_slice, Eina_Slice *remaining) { - Eina_Error ret; + int fd = efl_io_writer_fd_writer_fd_get(o); + ssize_t r; - ret = efl_io_writer_write(efl_super(o, MY_CLASS), ro_slice, remaining); - if (ro_slice && ro_slice->len > 0) - efl_io_writer_can_write_set(o, EINA_FALSE); /* wait Efl.Loop.Fd "write" */ + EINA_SAFETY_ON_NULL_RETURN_VAL(ro_slice, EINVAL); + if (fd < 0) goto error; - return ret; + do + { + r = send(fd, ro_slice->mem, ro_slice->len, 0); + if (r < 0) + { + Eina_Error err = efl_net_socket_error_get(); + + if (err == EINTR) continue; + + if (remaining) *remaining = *ro_slice; + ro_slice->len = 0; + ro_slice->mem = NULL; + if (err == EAGAIN) efl_io_writer_can_write_set(o, EINA_FALSE); + return err; + } + } + while (r < 0); + + if (remaining) + { + remaining->len = ro_slice->len - r; + remaining->bytes = ro_slice->bytes + r; + } + ro_slice->len = r; + efl_io_writer_can_write_set(o, EINA_FALSE); /* wait Efl.Loop.Fd "write" */ + + return 0; + + error: + if (remaining) *remaining = *ro_slice; + ro_slice->len = 0; + ro_slice->mem = NULL; + return EINVAL; } EOLIAN static void @@ -205,6 +264,11 @@ _efl_net_socket_fd_efl_net_socket_address_remote_get(Eo *o EINA_UNUSED, Efl_Net_ EOLIAN static Eina_Bool _efl_net_socket_fd_close_on_exec_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, Eina_Bool close_on_exec) { +#ifdef _WIN32 + DBG("close on exec is not supported on windows"); + pd->close_on_exec = close_on_exec; + return EINA_FALSE; +#else int flags, fd; pd->close_on_exec = close_on_exec; @@ -229,11 +293,16 @@ _efl_net_socket_fd_close_on_exec_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, Eina_Boo } return EINA_TRUE; +#endif } EOLIAN static Eina_Bool _efl_net_socket_fd_close_on_exec_get(Eo *o, Efl_Net_Socket_Fd_Data *pd) { +#ifdef _WIN32 + DBG("close on exec is not supported on windows"); + return pd->close_on_exec; +#else int flags, fd; fd = efl_loop_fd_get(o); @@ -251,6 +320,7 @@ _efl_net_socket_fd_close_on_exec_get(Eo *o, Efl_Net_Socket_Fd_Data *pd) pd->close_on_exec = !!(flags & FD_CLOEXEC); /* sync */ return pd->close_on_exec; +#endif } EOLIAN static void