### Starting and Sending PDUs with Minimal ESME Source: https://hexdocs.pm/smppex Demonstrates how to start a minimal ESME client and send a bind_transmitter PDU. This example assumes a functional DummyESME module is defined. ```elixir {:ok, esme} = DummyESME.start_link(host, port) SMPPEX.Session.send_pdu(esme, SMPPEX.Pdu.Factory.bind_transmitter("system_id", "password")) ``` -------------------------------- ### SMPPEX ESME.Sync Example Source: https://hexdocs.pm/smppex Demonstrates how to use SMPPEX.ESME.Sync to connect to an SMSC, bind as a transmitter, send a message, and wait for delivery reports. Requires host and port for the SMSC. ```elixir {:ok, esme} = SMPPEX.ESME.Sync.start_link(host, port) bind = SMPPEX.Pdu.Factory.bind_transmitter("system_id", "password") {:ok, _bind_resp} = SMPPEX.ESME.Sync.request(esme, bind) # We are bound, let's send a message submit_sm = SMPPEX.Pdu.Factory.submit_sm({"from", 1, 1}, {"to", 1, 1}, "hello!") {:ok, submit_sm_resp} = SMPPEX.ESME.Sync.request(esme, submit_sm) # Message is sent, let's get the obtained id: message_id = SMPPEX.Pdu.field(submit_sm_resp, :message_id) # Now let's wait for a delivery report: delivery_report? = fn(pdu) -> SMPPEX.Pdu.command_name(pdu) == :deliver_sm and SMPPEX.Pdu.field(pdu, :receipted_message_id) == message_id end delivery_reports = case SMPPEX.ESME.Sync.wait_for_pdus(esme, 60000) do :stop -> Logger.info("Ooops, ESME stopped") [] :timeout -> Logger.info("No DLR in 60 seconds") [] received_items -> # Let's filter out DLRs for the previously submitted message for {:pdu, pdu} <- received_items, delivery_report?.(pdu), do: pdu end ``` -------------------------------- ### Simple SMPPEX.MC Implementation Source: https://hexdocs.pm/smppex This code defines a basic SMPPEX.MC module that listens for SMPP connections, responds to binds, and handles submit_sm PDUs with incremental message IDs. It requires the SMPPEX library and is designed to be started as a child of a supervisor. ```Elixir defmodule MC do use SMPPEX.Session alias SMPPEX.Pdu alias SMPPEX.Pdu.Factory, as: PduFactory def child_spec(port) do Supervisor.child_spec( { SMPPEX.MC, session: {__MODULE__, []}, transport_opts: [port: port] }, [] ) end def init(_socket, _transport, []) do {:ok, 0} end def handle_pdu(pdu, last_id) do case Pdu.command_name(pdu) do :submit_sm -> {:ok, [PduFactory.submit_sm_resp(0, to_string(last_id)) |> Pdu.as_reply_to(pdu)], last_id + 1} :bind_transmitter -> {:ok, [PduFactory.bind_transmitter_resp(0) |> Pdu.as_reply_to(pdu)], last_id} _ -> {:ok, last_id} end end end ``` -------------------------------- ### Minimal SMPPEX.ESME Implementation Source: https://hexdocs.pm/smppex A basic implementation of SMPPEX.ESME using default callbacks from SMPPEX.Session. This is useful for creating simple ESME clients with minimal boilerplate code. ```elixir defmodule DummyESME do use SMPPEX.Session def start_link(host, port) do SMPPEX.ESME.start_link(host, port, {__MODULE__, []}) end end ``` -------------------------------- ### Advanced SMPPEX.ESME for Benchmarking Source: https://hexdocs.pm/smppex An advanced ESME implementation designed for benchmarking, handling PDU sending, window size control, and process notification upon completion. It requires specific arguments for port, waiting PID, PDU count, and window size. ```elixir defmodule SMPPBenchmarks.ESME do use SMPPEX.Session require Logger @from {"from", 1, 1} @to {"to", 1, 1} @message "hello" @system_id "system_id" @password "password" def start_link(port, waiting_pid, count, window) do SMPPEX.ESME.start_link("127.0.0.1", port, {__MODULE__, [waiting_pid, count, window]}) end def init(_, _, [waiting_pid, count, window]) do Kernel.send(self(), :bind) {:ok, %{waiting_pid: waiting_pid, count_to_send: count, count_waiting_resp: 0, window: window}} end def handle_resp(pdu, _original_pdu, st) do case SMPPEX.Pdu.command_name(pdu) do :submit_sm_resp -> new_st = %{ st | count_waiting_resp: st.count_waiting_resp - 1 } send_pdus(new_st) :bind_transmitter_resp -> send_pdus(st) _ -> {:ok, st} end end def handle_resp_timeout(pdu, st) do Logger.error("PDU timeout: #{inspect pdu}, terminating") {:stop, :resp_timeout, st} end def terminate(reason, _, st) do Logger.info("ESME stopped with reason #{inspect reason}") Kernel.send(st.waiting_pid, {self(), :done}) :stop end def handle_info(:bind, st) do {:noreply, [SMPPEX.Pdu.Factory.bind_transmitter(@system_id, @password)], st} end defp send_pdus(st) do cond do st.count_to_send > 0 -> count_to_send = min(st.window - st.count_waiting_resp, st.count_to_send) new_st = %{ st | count_waiting_resp: st.window, count_to_send: st.count_to_send - count_to_send } {:ok, make_pdus(count_to_send), new_st} st.count_waiting_resp > 0 -> {:ok, st} true -> Logger.info("All PDUs sent, all resps received, terminating") {:stop, :normal, st} end end defp make_pdus(0), do: [] defp make_pdus(n) do for _ <- 1..n, do: SMPPEX.Pdu.Factory.submit_sm(@from, @to, @message) end end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.