forked from enlightenment/efl
efl_net_socket_fd: make it more win32 friendly.
it seems that on windows read() and write() won't work with sockets, so use recv() and send(). Note that this code is still untested on windows, at least the errors must be fetched using WSAGetLastError() instead of errno directly, but I don't have a Windows machine I can test.
This commit is contained in:
parent
088c9675ef
commit
4814f937e2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue