Skip to content

Commit

Permalink
Shutdown on unexpected packet
Browse files Browse the repository at this point in the history
  • Loading branch information
bokner committed Jul 17, 2023
1 parent 0f3ba0a commit 9c6cbf1
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
34 changes: 24 additions & 10 deletions lib/mllp/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ defmodule MLLP.Client do
"Data received after trailer"
end

def format_error(:unexpected_packet_received) do
"Unexpected packet received"
end

def format_error(posix) when is_atom(posix) do
case :inet.format_error(posix) do
'unknown POSIX error' ->
Expand Down Expand Up @@ -576,8 +580,9 @@ defmodule MLLP.Client do
## Handle the (fragmented) responses to `send` request from a caller

defp handle_received(_reply, %{caller: nil} = data) do
## No caller, ignore
data
## No caller, we must have received the full MLLP already,
## or it could be a request from external process other than the receiver
maybe_close(:unexpected_packet_received, data)
end

defp handle_received(<<@header, _rest::binary>> = reply, data) do
Expand Down Expand Up @@ -691,15 +696,24 @@ defmodule MLLP.Client do

defp maybe_close(_reason, data), do: data

defp stop_connection(%State{} = data, error, context) do
if data.socket != nil do
telemetry(
:status,
%{status: :disconnected, error: format_error(error), context: context},
data
)
defp stop_connection(%State{socket: nil} = data, _error, _context) do
data
end

defp stop_connection(%State{socket: socket, tcp: tcp} = data, error, context) do
telemetry(
:status,
%{status: :disconnected, error: format_error(error), context: context},
data
)

Logger.debug("Stopping connection: #{format_error(error)}}")

data.tcp.close(data.socket)
if error == :unexpected_packet_received do
:ok = :inet.setopts(socket, linger: {true, 0})
tcp.shutdown(socket, :read_write)
else
tcp.close(socket)
end

data
Expand Down
1 change: 1 addition & 0 deletions lib/mllp/tcp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ defmodule MLLP.TCP do
defdelegate recv(socket, length, timeout), to: :gen_tcp
defdelegate connect(address, port, options, timeout), to: :gen_tcp
defdelegate close(socket), to: :gen_tcp
defdelegate shutdown(socket, opts), to: :gen_tcp
end
1 change: 1 addition & 0 deletions lib/mllp/tls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ defmodule MLLP.TLS do
defdelegate recv(socket, length, timeout), to: :ssl
defdelegate connect(address, port, options, timeout), to: :ssl
defdelegate close(socket), to: :ssl
defdelegate shutdown(socket, opts), to: :ssl
end
25 changes: 22 additions & 3 deletions test/client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,35 @@ defmodule ClientTest do
end
end

describe "handle_info/2" do
test "handles unexpected info messages" do
assert {:ok, pid} = MLLP.Client.start_link({127, 0, 0, 1}, 9998, use_backoff: true)
describe "unexpected messages" do
setup do
Logger.configure(level: :debug)
setup_client_receiver()
end

test "handles unexpected info messages", %{client: pid} = _ctx do
assert capture_log(fn ->
Kernel.send(pid, :eh?)
Process.sleep(100)
assert Process.alive?(pid)
end) =~ "Unknown message received => :eh?"
end

test "handles unexpected incoming packet", %{client: pid} = _ctx do
{_fsm_state, state} = :sys.get_state(pid)
socket = state.socket

log =
capture_log([level: :debug], fn ->
Kernel.send(pid, {:tcp, socket, "what's up?"})
Process.sleep(100)
end)

assert String.contains?(log, Client.format_error(:unexpected_packet_received))
assert String.contains?(log, "Connection closed")

refute Client.is_connected?(pid)
end
end

describe "send/2" do
Expand Down

0 comments on commit 9c6cbf1

Please sign in to comment.