This test suite uses LXC containers to simulate various nodes connected
to each other in different network topologies, and allows for realistic
testing of the MeshLink library.
Guus Sliepen [Thu, 30 Aug 2018 17:45:13 +0000 (19:45 +0200)]
Always add both CanonicalAddress and any local address to the invitation URL.
We don't know in advance if the invitee will be on the LAN or outside
the LAN, and because hairpin routing is not working on many home
routers, it is safer to add all possible addresses.
Also, add the port number to each individual address in the URL, instead
of allowing only one port number.
Guus Sliepen [Sun, 12 Aug 2018 15:09:20 +0000 (17:09 +0200)]
Add duplicate node detection callback.
MeshLink can detect if two nodes are online simultaneously using the same
Name. Normally, one or both of the duplicate nodes will terminate its
connection. Now there is a duplicate node callback that will be called when
the local node detects a duplicate node. One use for this is to blacklist
the duplicate node and/or notify the user of the problem.
Add COPYING.README, detailing license obligations for users of MeshLink.
MeshLink itself depends on other libraries, and this document mainly
summarizes what obligations users of the MeshLink library have when they
distribute their software in binary form.
Guus Sliepen [Tue, 26 Jun 2018 14:42:57 +0000 (16:42 +0200)]
Add meshlink_set_invitation_timeout().
This sets a global timeout for invitation files. If a node tries to join
with an invitation whose file is older than the timeout, the invitation is
rejected.
Guus Sliepen [Tue, 26 Jun 2018 14:12:28 +0000 (16:12 +0200)]
Add meshlink_set_canonical_address().
This introduces the concept of a canonical address for a node, which is
its "official" address/port. It is only set manually, and never updated
or removed when other addresses have been discovered for this node.
Also, this changed meshlink_add_address(mesh, address) to be equivalent to
meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), address, NULL).
While not strictly equivalent to the old behaviour, it matches the
documented intent of this function.
Guus Sliepen [Mon, 21 May 2018 20:03:47 +0000 (22:03 +0200)]
Use getsockname() to get a listening sockets actual address in meshlink_stop().
This should be better than sending a packet to the listening address,
which might be a link-local address for which a valid scope-id is
necessary, and which might not be in listen_socket.sa.
Guus Sliepen [Tue, 8 May 2018 15:05:00 +0000 (17:05 +0200)]
Ensure -export-symbols-regex is not lost.
An earlier commit accidentily caused libmeshlink_la_LDFLAGS to be
overwritten later in src/Makefile.am, and this caused
-export-symbols-regex to be dropped, thereby exposing internal symbols
of the library.
Guus Sliepen [Sun, 6 May 2018 20:46:36 +0000 (22:46 +0200)]
Try to be smarter generating invitation URLs.
If we have a symbol hostname associated with us, use that. Otherwise, try
to find out which external addresses we have for both IPv4 and IPv6. If we
cannot connect to www.meshlink.io, then use the local address used for
outgoing connections as a fallback. Also, don't forget to add a port number
in all cases.
The generated invitation URL can now contain two addresses in the hostname
part, separated by a comma.
Guus Sliepen [Thu, 3 May 2018 20:33:58 +0000 (22:33 +0200)]
Allow multiple addresses in an invitation URL.
This allows the address field in an invitation URL to be a
comma-separated list. The goal is to allow both IPv4 and IPv6 addresses
to be encoded in a single URL.
This commit also ensures that if a hostname is given, that all address
records associated with that hostname are tried.
Guus Sliepen [Tue, 1 May 2018 12:10:45 +0000 (14:10 +0200)]
Check the return value of check_port().
When initializing a new MeshLink instance, fail if there is no port
available for listening. When starting an already configured instance,
if no Port statement is found in the local node's host config file,
select and add a new one.
Guus Sliepen [Sat, 16 Dec 2017 21:38:48 +0000 (22:38 +0100)]
Don't use SOL_IP and SOL_IPV6.
These macros do not exist on all platforms, instead one should use
IPPROTO_IP and IPPROTO_IPV6. This fixes a bug on macOS where the
IPV6_V6ONLY flag would not be applied and could result in IPv4 sockets
not working.
Guus Sliepen [Mon, 14 Aug 2017 19:19:41 +0000 (21:19 +0200)]
Add a test for a constellation of three nodes.
In particular, test whether two nodes that have been introduced to each
other via a third node can still continue to communicate with each other
when the third node goes offline.
Guus Sliepen [Sun, 13 Aug 2017 21:08:56 +0000 (23:08 +0200)]
Test cornercases of MeshLink channels.
- Ensure we can open a channel before starting MeshLink.
- Check that opening channels to a peer that has unregistered its accept
callback will not result in the poll callback to be called with a non-
zero length.
Guus Sliepen [Sun, 13 Aug 2017 21:07:25 +0000 (23:07 +0200)]
Add utility functions to create paired MeshLink instances.
This also adds a start_meshlink_pair() function which starts the two instances
and waits for them to establish a connection with each other. A condition
variable is used to avoid having to poll.
Guus Sliepen [Sun, 13 Aug 2017 15:51:28 +0000 (17:51 +0200)]
Reset UTCP timers after a succesful key exchange.
The problem is that MeshLink does key exchange with peers on-demand. One
has to start a channel for key exchange to be initiated, but it also tries
to send the first SYN packet immediately. This will not work, and then it
has to wait for the retransmit timer to expire before it will try to send
the SYN again. Since the retransmit timer is increased exponentially, this
can potentially take a long time. So when key exchange is finished, we now
force a reset of the timers of all UTCP connections with the peer.
Guus Sliepen [Sun, 13 Aug 2017 13:06:51 +0000 (15:06 +0200)]
Convert sizeof foo to sizeof(foo).
While technically sizeof is an operator and doesn't need the parentheses
around expressions it operates on, except if they are type names, code
formatters don't seem to handle this very well.
Guus Sliepen [Sun, 13 Aug 2017 12:57:29 +0000 (14:57 +0200)]
Remove hack to wait for a valid key.
This was obviously only necessary because the missing retransmits of SYN
packets. Now, if a channel is opened before we have finished the key
exchange with the peer, UTCP will retry after a second.
Don't start with underscores, as those are reserved for system
libraries. Make sure all start with MESHLINK_, and that they appear at
the top of the file.
Guus Sliepen [Sun, 25 Jun 2017 14:32:15 +0000 (16:32 +0200)]
Fix processing of mixed ID and SPTPS data.
When making a connection with another peer, the ID message and the first
SPTPS data is sent using separate send() calls, but they can be merged
along the way to the other side. When receiving the ID message, we
accidentily discarded the rest of the received packet. Handle this
properly.
The problem was found to trigger much more often on Linux kernel 4.4 in
KVM.
Guus Sliepen [Fri, 11 Mar 2016 11:08:48 +0000 (12:08 +0100)]
Add meshlink_get_external_address() and meshlink_add_external_address().
These functions try to discover the local node's external address by
contacting the meshlink.io server. The get function just returns the
discovered address as a string, the add function adds it as an Address,
so it will end up in the list of addresses when calling
meshlink_export().
Guus Sliepen [Thu, 17 Dec 2015 17:44:21 +0000 (18:44 +0100)]
Use free_known_addresses() to free memory allocated by get_known_addresses().
We know what struct addrinfo looks like, but the standard says nothing about
how it is allocated. So we cannot trust freeaddrinfo() to work correctly on
the struct addrinfo list we allocated ourselves in get_known_addresses().
To make a distinction by allocations from the latter and from str2addrinfo(),
we keep two pointers (*ai and *aip) in struct outgoing, and use the freeing
function that is appropriate for each.
Guus Sliepen [Fri, 13 Nov 2015 08:50:45 +0000 (08:50 +0000)]
Fix race condition when calling meshlink_stop() immediately after meshlink_start().
The event loop didn't react to event_loop_stop() if it wasn't started yet
(because that is done in mesh->thread). The solution is to add a
event_loop_start() function that is to be called by meshlink_start().