efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
#define EFL_NET_SERVER_TCP_PROTECTED 1
|
|
|
|
#define EFL_NET_SERVER_FD_PROTECTED 1
|
|
|
|
#define EFL_NET_SERVER_PROTECTED 1
|
|
|
|
#define EFL_LOOP_FD_PROTECTED 1
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Ecore.h"
|
|
|
|
#include "Ecore_Con.h"
|
|
|
|
#include "ecore_con_private.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
# include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_TCP_H
|
|
|
|
# include <netinet/tcp.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MY_CLASS EFL_NET_SERVER_TCP_CLASS
|
|
|
|
|
2016-10-18 16:24:16 -07:00
|
|
|
typedef struct _Efl_Net_Server_Tcp_Data
|
|
|
|
{
|
2016-10-20 19:15:09 -07:00
|
|
|
Ecore_Thread *resolver;
|
2016-10-18 16:24:16 -07:00
|
|
|
Eina_Bool ipv6_only;
|
|
|
|
} Efl_Net_Server_Tcp_Data;
|
|
|
|
|
2016-10-20 15:43:02 -07:00
|
|
|
EOLIAN Efl_Object *
|
|
|
|
_efl_net_server_tcp_efl_object_constructor(Eo *o, Efl_Net_Server_Tcp_Data *pd)
|
|
|
|
{
|
|
|
|
pd->ipv6_only = 0xff;
|
|
|
|
return efl_constructor(efl_super(o, MY_CLASS));
|
|
|
|
}
|
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
EOLIAN void
|
|
|
|
_efl_net_server_tcp_efl_object_destructor(Eo *o, Efl_Net_Server_Tcp_Data *pd)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
2016-10-20 19:15:09 -07:00
|
|
|
if (pd->resolver)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
2016-10-20 19:15:09 -07:00
|
|
|
ecore_thread_cancel(pd->resolver);
|
|
|
|
pd->resolver = NULL;
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
}
|
2016-10-20 19:15:09 -07:00
|
|
|
efl_destructor(efl_super(o, MY_CLASS));
|
|
|
|
}
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
static Eina_Error
|
|
|
|
_efl_net_server_tcp_resolved_bind(Eo *o, Efl_Net_Server_Tcp_Data *pd, const struct addrinfo *addr)
|
|
|
|
{
|
|
|
|
Eina_Error err = 0;
|
|
|
|
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")];
|
|
|
|
socklen_t addrlen = addr->ai_addrlen;
|
2016-10-22 16:49:01 -07:00
|
|
|
SOCKET fd;
|
|
|
|
int r;
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
efl_net_server_fd_family_set(o, addr->ai_family);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
fd = efl_net_socket4(addr->ai_family, addr->ai_socktype, addr->ai_protocol,
|
2016-08-24 08:34:59 -07:00
|
|
|
efl_net_server_fd_close_on_exec_get(o));
|
2016-10-22 08:15:16 -07:00
|
|
|
if (fd == INVALID_SOCKET)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
2016-10-22 08:15:16 -07:00
|
|
|
err = efl_net_socket_error_get();
|
2016-10-20 19:15:09 -07:00
|
|
|
ERR("socket(%d, %d, %d): %s",
|
|
|
|
addr->ai_family, addr->ai_socktype, addr->ai_protocol,
|
2016-10-22 08:15:16 -07:00
|
|
|
eina_error_msg_get(err));
|
|
|
|
return err;
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
efl_loop_fd_set(o, fd);
|
|
|
|
|
2016-10-18 16:24:16 -07:00
|
|
|
/* apply pending value BEFORE bind() */
|
2016-10-20 19:15:09 -07:00
|
|
|
if (addr->ai_family == AF_INET6)
|
2016-10-20 15:43:02 -07:00
|
|
|
{
|
|
|
|
if (pd->ipv6_only == 0xff)
|
|
|
|
efl_net_server_tcp_ipv6_only_get(o); /* fetch & sync */
|
|
|
|
else
|
|
|
|
efl_net_server_tcp_ipv6_only_set(o, pd->ipv6_only);
|
|
|
|
}
|
2016-10-18 16:24:16 -07:00
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
r = bind(fd, addr->ai_addr, addrlen);
|
2016-10-22 08:15:16 -07:00
|
|
|
if (r != 0)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
2016-10-22 08:15:16 -07:00
|
|
|
err = efl_net_socket_error_get();
|
2016-10-20 19:15:09 -07:00
|
|
|
efl_net_ip_port_fmt(buf, sizeof(buf), addr->ai_addr);
|
2016-11-18 06:17:08 -08:00
|
|
|
DBG("bind(" SOCKET_FMT ", %s): %s", fd, buf, eina_error_msg_get(err));
|
2016-10-20 19:15:09 -07:00
|
|
|
goto error;
|
2016-10-18 16:24:16 -07:00
|
|
|
}
|
|
|
|
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
r = listen(fd, 0);
|
2016-10-22 08:15:16 -07:00
|
|
|
if (r != 0)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
2016-10-22 08:15:16 -07:00
|
|
|
err = efl_net_socket_error_get();
|
2016-11-18 06:17:08 -08:00
|
|
|
DBG("listen(" SOCKET_FMT "): %s", fd, eina_error_msg_get(err));
|
2016-10-20 19:15:09 -07:00
|
|
|
goto error;
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
}
|
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
if (getsockname(fd, addr->ai_addr, &addrlen) != 0)
|
|
|
|
{
|
2016-10-22 08:15:16 -07:00
|
|
|
err = efl_net_socket_error_get();
|
2016-11-18 06:17:08 -08:00
|
|
|
ERR("getsockname(" SOCKET_FMT "): %s", fd, eina_error_msg_get(err));
|
2016-10-20 19:15:09 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
else if (efl_net_ip_port_fmt(buf, sizeof(buf), addr->ai_addr))
|
|
|
|
efl_net_server_address_set(o, buf);
|
|
|
|
|
2016-11-18 06:17:08 -08:00
|
|
|
DBG("fd=" SOCKET_FMT " serving at %s", fd, buf);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
efl_net_server_serving_set(o, EINA_TRUE);
|
|
|
|
return 0;
|
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
error:
|
|
|
|
efl_net_server_fd_family_set(o, AF_UNSPEC);
|
2016-11-18 06:17:08 -08:00
|
|
|
efl_loop_fd_set(o, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
|
2016-10-22 16:49:01 -07:00
|
|
|
closesocket(fd);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
static void
|
|
|
|
_efl_net_server_tcp_resolved(void *data, const char *host EINA_UNUSED, const char *port EINA_UNUSED, const struct addrinfo *hints EINA_UNUSED, struct addrinfo *result, int gai_error)
|
|
|
|
{
|
|
|
|
Eo *o = data;
|
|
|
|
Efl_Net_Server_Tcp_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
|
|
const struct addrinfo *addr;
|
|
|
|
Eina_Error err;
|
|
|
|
|
|
|
|
pd->resolver = NULL;
|
|
|
|
|
|
|
|
efl_ref(o); /* we're emitting callbacks then continuing the workflow */
|
|
|
|
|
|
|
|
if (gai_error)
|
|
|
|
{
|
2016-12-11 16:17:15 -08:00
|
|
|
err = EFL_NET_ERROR_COULDNT_RESOLVE_HOST;
|
2016-10-20 19:15:09 -07:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (addr = result; addr != NULL; addr = addr->ai_next)
|
|
|
|
{
|
|
|
|
err = _efl_net_server_tcp_resolved_bind(o, pd, addr);
|
|
|
|
if (err == 0) break;
|
|
|
|
}
|
|
|
|
freeaddrinfo(result);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (err) efl_event_callback_call(o, EFL_NET_SERVER_EVENT_ERROR, &err);
|
|
|
|
|
|
|
|
efl_unref(o);
|
|
|
|
}
|
|
|
|
|
2016-11-01 11:01:57 -07:00
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_net_server_tcp_efl_net_server_fd_socket_activate(Eo *o, Efl_Net_Server_Tcp_Data *pd EINA_UNUSED, const char *address)
|
|
|
|
{
|
2016-11-18 06:17:08 -08:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL((SOCKET)efl_loop_fd_get(o) != INVALID_SOCKET, EALREADY);
|
2016-11-01 11:01:57 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
|
|
|
|
|
|
|
|
#ifndef HAVE_SYSTEMD
|
|
|
|
return efl_net_server_fd_socket_activate(efl_super(o, MY_CLASS), address);
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")];
|
|
|
|
Eina_Bool listening;
|
|
|
|
Eina_Error err;
|
|
|
|
struct sockaddr_storage *addr;
|
|
|
|
socklen_t addrlen;
|
2016-11-18 06:17:08 -08:00
|
|
|
SOCKET fd;
|
2016-11-01 11:01:57 -07:00
|
|
|
|
|
|
|
err = efl_net_ip_socket_activate_check(address, AF_UNSPEC, SOCK_STREAM, &listening);
|
|
|
|
if (err) return err;
|
|
|
|
|
|
|
|
err = efl_net_server_fd_socket_activate(efl_super(o, MY_CLASS), address);
|
|
|
|
if (err) return err;
|
|
|
|
|
|
|
|
fd = efl_loop_fd_get(o);
|
|
|
|
|
|
|
|
if (!listening)
|
|
|
|
{
|
|
|
|
if (listen(fd, 0) != 0)
|
|
|
|
{
|
|
|
|
err = efl_net_socket_error_get();
|
2016-11-18 06:17:08 -08:00
|
|
|
DBG("listen(" SOCKET_FMT "): %s", fd, eina_error_msg_get(err));
|
2016-11-01 11:01:57 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addrlen = sizeof(addr);
|
|
|
|
if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) != 0)
|
|
|
|
{
|
|
|
|
err = efl_net_socket_error_get();
|
2016-11-18 06:17:08 -08:00
|
|
|
ERR("getsockname(" SOCKET_FMT "): %s", fd, eina_error_msg_get(err));
|
2016-11-01 11:01:57 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
else if (efl_net_ip_port_fmt(buf, sizeof(buf), (struct sockaddr *)&addr))
|
|
|
|
efl_net_server_address_set(o, buf);
|
|
|
|
|
2016-11-18 06:17:08 -08:00
|
|
|
DBG("fd=" SOCKET_FMT " serving at %s", fd, address);
|
2016-11-01 11:01:57 -07:00
|
|
|
efl_net_server_serving_set(o, EINA_TRUE);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
efl_net_server_fd_family_set(o, AF_UNSPEC);
|
2016-11-18 06:17:08 -08:00
|
|
|
efl_loop_fd_set(o, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
|
2016-11-01 11:01:57 -07:00
|
|
|
closesocket(fd);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-10-20 19:15:09 -07:00
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_net_server_tcp_efl_net_server_serve(Eo *o, Efl_Net_Server_Tcp_Data *pd, const char *address)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
const char *host, *port;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = SOCK_STREAM,
|
|
|
|
.ai_protocol = IPPROTO_TCP,
|
|
|
|
.ai_family = AF_UNSPEC,
|
2016-10-22 04:41:26 -07:00
|
|
|
.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED,
|
2016-10-20 19:15:09 -07:00
|
|
|
};
|
2016-12-09 05:42:17 -08:00
|
|
|
struct sockaddr_storage ss;
|
|
|
|
Eina_Error err;
|
2016-10-20 19:15:09 -07:00
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
|
|
|
|
|
|
|
|
str = strdup(address);
|
|
|
|
if (!efl_net_ip_port_split(str, &host, &port))
|
|
|
|
{
|
|
|
|
free(str);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
if (!port) port = "0";
|
|
|
|
|
2016-12-09 05:42:17 -08:00
|
|
|
if (efl_net_ip_port_parse_split(host, port, &ss))
|
|
|
|
{
|
|
|
|
struct addrinfo ai = hints;
|
|
|
|
|
|
|
|
ai.ai_family = ss.ss_family;
|
|
|
|
ai.ai_addr = (struct sockaddr *)&ss;
|
|
|
|
ai.ai_addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
|
|
|
|
|
|
|
|
err = _efl_net_server_tcp_resolved_bind(o, pd, &ai);
|
|
|
|
free(str);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pd->resolver = efl_net_ip_resolve_async_new(host, port, &hints,
|
|
|
|
_efl_net_server_tcp_resolved, o);
|
|
|
|
free(str);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->resolver, EINVAL);
|
|
|
|
err = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
2016-10-20 19:15:09 -07:00
|
|
|
}
|
|
|
|
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
static void
|
2016-10-18 16:24:16 -07:00
|
|
|
_efl_net_server_tcp_efl_net_server_fd_client_add(Eo *o, Efl_Net_Server_Tcp_Data *pd EINA_UNUSED, int client_fd)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
|
|
|
Eo *client = efl_add(EFL_NET_SOCKET_TCP_CLASS, o,
|
2016-09-12 08:23:29 -07:00
|
|
|
efl_io_closer_close_on_exec_set(efl_added, efl_net_server_fd_close_on_exec_get(o)),
|
|
|
|
efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE),
|
2016-09-05 08:57:35 -07:00
|
|
|
efl_loop_fd_set(efl_added, client_fd));
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
if (!client)
|
|
|
|
{
|
2016-11-18 06:17:08 -08:00
|
|
|
ERR("could not create client object fd=" SOCKET_FMT, (SOCKET)client_fd);
|
2016-10-22 16:49:01 -07:00
|
|
|
closesocket(client_fd);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
efl_net_server: add 'client_announce', share logic and fix a bug.
I just realized that if a client is not referenced it would leak in
the 'ssl' server as we must del it.
However, if we del the SSL socket, we're going to close the underlying
TCP. But we're from the TCP "client,add" callback and this causes
issues since "closed" will be emitted, our close callback will
unparent the client, which lead to it being deleted.
The proper solution is to only monitor "closed" if the client is
accepted. Otherwise we just check if it was closed, if we're the
parent, etc...
Fixing this in all servers were painful, we could share since most
inherit from Efl.Net.Server.Fd. Then add the "client_announce"
protected method to do it, and document how it should work.
2016-11-24 23:32:16 -08:00
|
|
|
efl_net_server_client_announce(o, client);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-10-18 16:24:16 -07:00
|
|
|
_efl_net_server_tcp_efl_net_server_fd_client_reject(Eo *o, Efl_Net_Server_Tcp_Data *pd EINA_UNUSED, int client_fd)
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
{
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
socklen_t addrlen;
|
|
|
|
char str[INET6_ADDRSTRLEN + sizeof("[]:65536")] = "";
|
|
|
|
|
|
|
|
addrlen = sizeof(addr);
|
2016-10-22 08:15:16 -07:00
|
|
|
if (getpeername(client_fd, (struct sockaddr *)&addr, &addrlen) != 0)
|
2016-11-18 06:17:08 -08:00
|
|
|
ERR("getpeername(" SOCKET_FMT "): %s", (SOCKET)client_fd, eina_error_msg_get(efl_net_socket_error_get()));
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
else
|
|
|
|
efl_net_ip_port_fmt(str, sizeof(str), (struct sockaddr *)&addr);
|
|
|
|
|
2016-10-22 16:49:01 -07:00
|
|
|
closesocket(client_fd);
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(o, EFL_NET_SERVER_EVENT_CLIENT_REJECTED, str);
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
}
|
|
|
|
|
2016-10-18 16:24:16 -07:00
|
|
|
EOLIAN void
|
|
|
|
_efl_net_server_tcp_ipv6_only_set(Eo *o, Efl_Net_Server_Tcp_Data *pd, Eina_Bool ipv6_only)
|
|
|
|
{
|
2016-10-22 08:15:16 -07:00
|
|
|
#ifdef IPV6_V6ONLY
|
2016-10-18 16:24:16 -07:00
|
|
|
Eina_Bool old = pd->ipv6_only;
|
2016-10-22 16:49:01 -07:00
|
|
|
SOCKET fd = efl_loop_fd_get(o);
|
2016-10-22 08:15:16 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
DWORD value = ipv6_only;
|
|
|
|
#else
|
2016-10-18 16:24:16 -07:00
|
|
|
int value = ipv6_only;
|
2016-10-22 08:15:16 -07:00
|
|
|
#endif
|
|
|
|
#endif
|
2016-10-18 16:24:16 -07:00
|
|
|
|
|
|
|
pd->ipv6_only = ipv6_only;
|
|
|
|
|
2016-10-22 08:15:16 -07:00
|
|
|
#ifdef IPV6_V6ONLY
|
|
|
|
if (fd == INVALID_SOCKET) return;
|
2016-10-18 16:24:16 -07:00
|
|
|
if (efl_net_server_fd_family_get(o) != AF_INET6) return;
|
|
|
|
|
2016-11-18 06:52:08 -08:00
|
|
|
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value)) != 0)
|
2016-10-18 16:24:16 -07:00
|
|
|
{
|
2016-12-09 13:33:40 -08:00
|
|
|
ERR("could not set socket=" SOCKET_FMT " IPV6_V6ONLY=%d: %s", fd, (int)value, eina_error_msg_get(efl_net_socket_error_get()));
|
2016-10-18 16:24:16 -07:00
|
|
|
pd->ipv6_only = old;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN Eina_Bool
|
|
|
|
_efl_net_server_tcp_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Tcp_Data *pd)
|
|
|
|
{
|
|
|
|
#ifdef IPV6_V6ONLY
|
2016-10-22 16:49:01 -07:00
|
|
|
SOCKET fd = efl_loop_fd_get(o);
|
2016-10-22 08:15:16 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
DWORD value = 0;
|
|
|
|
int valuelen;
|
|
|
|
#else
|
2016-10-18 16:24:16 -07:00
|
|
|
int value = 0;
|
2016-10-22 08:15:16 -07:00
|
|
|
socklen_t valuelen;
|
|
|
|
#endif
|
2016-10-18 16:24:16 -07:00
|
|
|
|
2016-10-22 08:15:16 -07:00
|
|
|
if (fd == INVALID_SOCKET) goto end;
|
2016-10-18 16:24:16 -07:00
|
|
|
if (efl_net_server_fd_family_get(o) != AF_INET6) goto end;
|
|
|
|
|
2016-10-22 08:15:16 -07:00
|
|
|
valuelen = sizeof(value);
|
2016-11-18 06:52:08 -08:00
|
|
|
if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, &valuelen) != 0)
|
2016-10-18 16:24:16 -07:00
|
|
|
{
|
2016-11-18 06:17:08 -08:00
|
|
|
WRN("getsockopt(" SOCKET_FMT ", IPPROTO_IPV6, IPV6_V6ONLY): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
|
2016-10-18 16:24:16 -07:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
pd->ipv6_only = !!value;
|
|
|
|
|
|
|
|
end:
|
|
|
|
#endif
|
|
|
|
return pd->ipv6_only;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
#include "efl_net_server_tcp.eo.c"
|