These are objects to allow control of networking devices
(efl_net_control) as well as an application to request for
connectivity (efl_net_session).
They are loosely based on ConnMan.org, which we already use in
Enlightenment Window Manager via DBus access with Eldbus. However they
do not map 1:1 as the goal was to expose a viable subset of controls
but in a simple and general way, thus nome strings were converted to
enums, some arrays of strings were converted to bitwise flags, some
names were made more general, such as "service" was turned into
"access point" so it doesn't generate confusion with other "network
services" (ie: http server), or "favorite" that was renamed to
"remembered". Some behavior are slightly different (yet able to be
implemented on top), such as "Service.MoveBefore" and "MoveAfter" were
converted to a numeric "priority", calculated from service's list
index, changing the priority will reoder the list and thus generate
the MoveBefore and MoveAfter DBus commands.
ConnMan was chosen not only because we already use it, but because its
DBus API is sane and simple, with the server doing almost all that we
need. This is visible in the efl_net_session, which is completely done
in the server and do not require any extra work on our side -- aside
from talking DBus and converting to Eo, which is a major work :-D
NOTE: ConnMan doesn't use FreeDesktop.Org DBus interfaces such as
Properties and ObjectManager, thus we cannot use
eldbus_model_object.
There are two examples added:
- efl_net_session_example: monitors the connection available for an
application and try to connect. You need a connman compiled with
session_policy_local and a configuration file explained in
https://github.com/aldebaran/connman/blob/master/doc/session-policy-format.txt
to get a connection if nothing is connected. Otherwise it will just
monitor the connectivity state.
- efl_net_control_example: monitors, plays the agent and configure
the network details. It can enable/disable technologies, connect to
access points (services) and configure them. It's quite extensive
as allows testing all of ConnMan's DBus API except P2P (Peers).
not the ideal solution, but we need a decision if we're going to copy
the long code from OpenSSL into our library just to support legacy
users, given that Efl.Net targeted at the future.
in the previous commit we're manually upgrading an existing TCP socket
to SSL. It is desired since some protocols need to negotiate, like
STARTTLS and the likes
Now we offer 2 classes that does autostart SSL once the socket is
ready.
Clang raised a massive amount of warnings due to the struct sockaddr_un
not being declared before using it. So, include the header that declares
this structure first.
for short downloads the CURL handle will be done before the client had
time to read it, like done by efl_io_copier's job. We need to wait it
drain before we emit eos/closed.
This introduces AF_UNIX server and dialer, these are not available on
Windows as in that platform we'll create a custom class for native
'local' communication.
In the future we can add a wrapper class Efl.Net.Local that will use
the class for each platform, but won't expose its details.
For instance, if we ever expose 'credentials' (which I didn't because
they are not portable), then it doesn't make sense to try to match
that on Windows. The 'Efl.Net.Local' would just stick to the basics:
Reader, Writer and Closer APIs.
This was a huge work, but now UDP is usable as seen in the examples.
Instead of relying on 'connect()', just do 'sendto()' and 'recvfrom()'
as they are universal. Multicast address can only be connected in
IPv4, IPv6 wasn't working and I'm not sure the IPv4 is portable to
other platforms.
Dialer will auto-join multicast groups is the dialed address is
one. Multicast properties such as time to live (hops) and loopback can
be configured. When joining multicast groups, the local
address/interface can be configured by 'IP@IFACE' format, with
'@IFACE' being optional.
Dialers will now auto-bind, so it can receive data as dialers are
expected to be bi-directional. One can manually specify the binding
address if there is such need.
Since datagrams must be read in their full size, otherwise the
remaining bits are dropped, expose next_datagram_size_query() in both
Efl.Net.Socket.Udp and Efl.Net.Server.Udp.Client.
To finalize UDP for real we need to introduce an 'Efl_Net_Ip_Address'
structure to serve as both IPv4 and IPv6 and expose 'sendto()' and
'recvfrom()'. These will come later as this commit is already too big.
Thanks to vtorri for poiting out about close() is not the correct
socket function, we should use closesocket() instead.
Also defined SOCKET to int on Linux so we can use the same 'type' and
avoid lots of ifdef in our code. On Windows it's unsigned, thus would
cause some warnings about incorrect signed comparison.
Defined INVALID_SOCKET=-1 and SOCKET_ERROR=-1 on non-Windows platforms
so we can keep the same construct 'function() == error' and it should
work on POSIX and windows.
I cannot test these on Windows, but the situation should be improved
with this commit.
if no hints were specified, getaddrinfo() will assume ai_flags as
AI_ADDRCONFIG | AI_V4MAPPED, which only reports useful results based
on what system supports. For instance AI_ADDRCONFIG will only return
IPv4 if IPv4 address exists, likewise IPv6 will only be returned if
IPv6 address is configured, avoiding these to be tried and error for
most local networks where such address could not be used. AI_V4MAPPED
will map IPv4 address over IPv6 if no IPv4 was found.
This is the initial UDP server that works similarly to the TCP one,
however under the hood it's widely different since the socket is
reused for all "clients", thus needs a new Efl.Net.Server.Udp.Client
(Efl.Net.Socket) as Efl.Net.Socket.Udp exposes the fd and options such
as 'cork', which would interfere in other clients.
The main socket will read the packets and find an existing client to
feed it. If no client exists, then it will create one if not overr
limit. Since there is no kernel-queuing as done by listen()/accept(),
the 'no reject' case will just accept the client anyway.
Next commits will improve UDP server handling with some advanced
features:
- join multicast groups
- bind to a specific interface (SO_BINDTODEVICE)
- block packets going out of local network (SO_DONTROUTE)
- specify priorities (SO_PRIORITY)
this allows nicer usage such as 'localhost:http' as the address, which
will resolve to [::1]:80 (if IPv6 is enabled) or 127.0.0.1:80 if only
IPv4 exists.
Sometimes we want to handle both IPv4 and IPv6 in the same socket,
instead of spawning 2 servers, one for each protocol. That is achieved
by means of disabling IPV6_V6ONLY socket option, present in most
recent platforms.
Like other toolkits, let's enable this automatically for users before
connecting to 255.255.255.255 IPv4 (IPADDR_BROADCAST), otherwise most
systems will just fail to connect and send packets.
Like existing ecore_con code, this does not use SOCKSv5 UDP
proxy. It's kinda cumbersome to add since requires a keep alive TCP
connection to the server, a second UDP channel and framing around the
original UDP frame.
Added UDP_CORK (if present) to match TCP_UDP present in TCP sockets,
this allows one to execute multiple write() calls that will result in
a single datagram, generated when CORK becomes FALSE again.
The efl_io_copier_example.c now accepts this as output. There is no
input UDP as there is no way to notify the server of a connection
(since such thing doesn't exit), usually servers react after a
datagram is received, replying to the source.
by default we'll start with cork=0 and on adoption of a FD we'll apply
cached values, thus we'd try to apply cork=0 (default) and it would
error, which is annoying on platforms without such feature.
since users interested in TCP_CORK will enable it first, they will get
the error at that point.
Thanks to Victor Pereira from the SUSE Security team for auditing
this and recommending better options.
This has been discussed several times but knowone ever got to
commiting it.