VintageNet.Connectivity.Inspector (vintage_net v0.11.3) View Source

This module looks at the network activity of all TCP socket connections known to Erlang/OTP to deduce whether the internet is working.

To use it, call check_internet/2, save the returned cache, and then call it again a minute later (or so). If any socket has transferred data in both directions to an off-LAN host on the interface of interest, then it will return that the internet is available.

This has a couple advantages:

  1. No data is sent to perform the check which is good for metered connections
  2. Most long-lived TCP connections have a keepalive mechanism that generates traffic, so this piggy-backs off that existing connectivity check.
  3. Devices can be behind very restrictive firewalls and internet connectivity can still be verified without knowing which IP/port/protocol combinations are allowed.

It is not perfect:

  1. It only works on long-lived TCP connections.
  2. The TCP connection must be sending and receiving data. If the keapalive is longer than the check_internet/2
  3. It doesn't help if nobody is using the network interface.
  4. It may have scalability issues if there are a LOT of TCP sockets.

Link to this section Summary

Types

Cache for use between check_internet/2 calls. Initialize to an empty map.

The return tuple for check_internet/2

Functions

Check whether the internet is accessible on the specified interface

Return true if an IP address is on one of the subnets in a list

Return true if an IP address is in the subnet

Link to this section Types

Specs

cache() :: %{required(port()) => {non_neg_integer(), non_neg_integer()}}

Cache for use between check_internet/2 calls. Initialize to an empty map.

Specs

result() :: {:available | :unknown | :unavailable, cache()}

The return tuple for check_internet/2:

  • :available - at least one TCP connection sent and received data to a non-LAN IP address
  • :unknown - no conclusion could be made
  • :unavailable - the interface didn't have an IP address, so Internet is definitely not available

Save the cache away and pass it to the next call to check_internet/2.

Link to this section Functions

Link to this function

check_internet(ifname, cache)

View Source

Specs

check_internet(VintageNet.ifname(), cache()) :: result()

Check whether the internet is accessible on the specified interface

Pass an empty map for the cache parameter for the first call. Then pass it back the returned cache for each subsequent call. If any TCP socket that's connected to a computer on another subnet and that's using the passed in network interface has send AND received data since the previous call, then :available is returned. If not, then usually :unknown is returned to signify that internet may be available, but we just don't know. If the interface doesn't have an IP address, then :unavailable is returned, since that's a prerequisite to communicating with anyone on the internet.

Specs

on_interface?(:inet.ip_address(), [ip_address_and_mask()]) :: boolean()

Return true if an IP address is on one of the subnets in a list

Specs

on_subnet?(:inet.ip_address(), ip_address_and_mask()) :: boolean()

Return true if an IP address is in the subnet

Examples

iex> Inspector.on_subnet?({192,168,0,50}, {{192,168,0,1}, {255,255,255,0}})
true

iex> Inspector.on_subnet?({192,168,5,1}, {{192,168,0,1}, {255,255,255,0}})
false