defmodule DaProductApp.TCP.Handler do @behaviour :ranch_protocol require Logger @timeout 30_000 @socket_opts [packet: 2, active: false] # ISO8583 typically uses length-prefixed messages # Ranch 2.1-compatible start_link def start_link(ref, transport, _opts) do Task.start_link(__MODULE__, :handle, [ref, transport]) end def handle(ref, transport) do # 1. Handshake and socket acquisition with error handling case :ranch.handshake(ref) do {:ok, socket} -> Logger.info("New TCP connection accepted") set_socket_opts(socket, transport) loop(socket, transport) {:error, reason} -> Logger.error("Handshake failed: #{inspect(reason)}") exit(:handshake_failed) end end defp set_socket_opts(socket, transport) do case transport.setopts(socket, @socket_opts) do :ok -> :ok {:error, reason} -> Logger.error("Socket options failed: #{inspect(reason)}") transport.close(socket) exit(:socket_options_failed) end end defp loop(socket, transport) do case transport.recv(socket, 0, @timeout) do {:ok, data} -> Logger.debug("Received data: #{inspect(data)}") process_data(socket, transport, data) loop(socket, transport) {:error, :timeout} -> Logger.info("Connection timeout") transport.close(socket) {:error, reason} -> Logger.warn("Connection error: #{inspect(reason)}") transport.close(socket) end end defp process_data(socket, transport, data) do Logger.debug("Received data process data: #{inspect(data)}") # Add your ISO8583 parsing and business logic here response = <<0, 4>> <> "ACK" # Sample ISO8583 response case transport.send(socket, response) do :ok -> Logger.debug("Response sent successfully") {:error, reason} -> Logger.error("Failed to send response: #{inspect(reason)}") end end end