Packages

Network interface monitor, sending events when the any of the network interfaces go up or go down.

Current section

7 Versions

Jump to

Compare versions

3 files changed
+45 additions
-19 deletions
  @@ -11,4 +11,4 @@
11 11 [{<<"github">>,<<"https://github.com/diodechain/network_monitor">>}]}.
12 12 {<<"name">>,<<"network_monitor">>}.
13 13 {<<"requirements">>,[]}.
14 - {<<"version">>,<<"1.1.1">>}.
14 + {<<"version">>,<<"1.1.2">>}.
  @@ -16,18 +16,20 @@ defmodule NetworkMonitor do
16 16
17 17 @app :network_monitor
18 18 @enforce_keys [:intervall, :timer, :interfaces, :subscribers, :on_down]
19 - defstruct [:intervall, :timer, :interfaces, :subscribers, :on_down]
19 + defstruct [:intervall, :timer, :interfaces, :known_interfaces, :subscribers, :on_down]
20 20
21 21 @impl true
22 22 def start(:normal, _opts) do
23 23 intervall = Application.get_env(@app, :intervall, 5_000)
24 + interfaces = interfaces()
24 25
25 26 GenServer.start_link(
26 27 __MODULE__,
27 28 %NetworkMonitor{
28 29 timer: nil,
29 30 intervall: intervall,
30 - interfaces: interfaces(),
31 + interfaces: interfaces,
32 + known_interfaces: interfaces,
31 33 subscribers: MapSet.new(),
32 34 on_down: %{}
33 35 },
  @@ -86,9 +88,18 @@ defmodule NetworkMonitor do
86 88 def handle_call(
87 89 {:on_down_apply, addr, mfa},
88 90 _from,
89 - state = %NetworkMonitor{on_down: on_down, interfaces: interfaces}
91 + state = %NetworkMonitor{
92 + on_down: on_down,
93 + interfaces: interfaces,
94 + known_interfaces: known_interfaces
95 + }
90 96 ) do
91 - if MapSet.member?(interfaces, addr) do
97 + # The logic here is that we will consider
98 + # 1) interfaces we have seen as "up"
99 + # 2) and interfaces we have never seen
100 + # This fixes platform (android/ios atm) where :net.getifaddrs() returns {:error, :enotsup}
101 +
102 + if MapSet.member?(interfaces, addr) or not MapSet.member?(known_interfaces, addr) do
92 103 on_down =
93 104 Map.update(on_down, addr, MapSet.new([mfa]), fn on_downs ->
94 105 MapSet.put(on_downs, mfa)
  @@ -111,23 +122,38 @@ defmodule NetworkMonitor do
111 122 {:noreply, %NetworkMonitor{state | subscribers: subscribers}}
112 123 end
113 124
114 - def handle_info(:check, state = %NetworkMonitor{interfaces: old_interfaces, on_down: on_downs}) do
125 + def handle_info(
126 + :check,
127 + state = %NetworkMonitor{
128 + interfaces: old_interfaces,
129 + known_interfaces: known_interfaces,
130 + on_down: on_downs
131 + }
132 + ) do
115 133 new_interfaces = interfaces()
116 134
117 - MapSet.difference(old_interfaces, new_interfaces)
118 - |> MapSet.to_list()
119 - |> handle_lost_interfaces(state)
120 - |> Enum.each(fn addr ->
121 - for mfa <- Map.get(on_downs, addr, []) do
122 - exec_mfa(addr, mfa)
135 + known_interfaces =
136 + if MapSet.equal?(new_interfaces, old_interfaces) do
137 + known_interfaces
138 + else
139 + MapSet.difference(old_interfaces, new_interfaces)
140 + |> MapSet.to_list()
141 + |> handle_lost_interfaces(state)
142 + |> Enum.each(fn addr ->
143 + for mfa <- Map.get(on_downs, addr, []) do
144 + exec_mfa(addr, mfa)
145 + end
146 + end)
147 +
148 + MapSet.difference(new_interfaces, old_interfaces)
149 + |> MapSet.to_list()
150 + |> handle_new_interfaces(state)
151 +
152 + MapSet.union(known_interfaces, new_interfaces)
123 153 end
124 - end)
125 154
126 - MapSet.difference(new_interfaces, old_interfaces)
127 - |> MapSet.to_list()
128 - |> handle_new_interfaces(state)
129 -
130 - {:noreply, %NetworkMonitor{state | interfaces: new_interfaces}}
155 + {:noreply,
156 + %NetworkMonitor{state | interfaces: new_interfaces, known_interfaces: known_interfaces}}
131 157 end
132 158
133 159 @impl true
  @@ -1,7 +1,7 @@
1 1 defmodule NetworkMonitor.MixProject do
2 2 use Mix.Project
3 3
4 - @version "1.1.1"
4 + @version "1.1.2"
5 5 @name "NetworkMonitor"
6 6 @url "https://github.com/diodechain/network_monitor"
7 7 @maintainers ["Dominic Letz"]