funbox/smppex

Receiving multipart SMS

dowusu opened this issue · 2 comments

This is not an issue, more of a feature request. I've been received multipart sms from the SMSC, currently I store the various parts in a ets table using using a combination of source_addr, destination_addr and part of the multipart as a key with the actual message and sequence stored in a MapSet, I was wondering if there's an existing feature for handling/assembling incoming multipart message. Below is my current implementation for handling multipart using ets.

def handle_cast(
        {:pdu, %{mandatory: %{destination_addr: short_code, source_addr: msisdn, esm_class: 64}} = pdu, pid},
        state
      ) do
    {:ok, {ref, count, seq}, msg} = SMPPEX.Pdu.Multipart.extract_from_pdu(pdu)
    key = "#{msisdn}_#{short_code}_#{ref}_#{count}" # Can use erlang:phash2 for a short key

    case lookup(key) do
      {:error, :not_found} ->
        :ets.insert(__MODULE__, {key, MapSet.new([{seq, msg}])})

      {:ok, [{_, result}]} ->
        process_message(result, key, count, seq, msg)
      
       
        end
    end

    {:noreply, state}
  end

defp process_message(result, key, count, seq, msg) do
    unless MapSet.member?(result, {seq, msg}) do
      result = MapSet.put(result, {seq, msg})

      if Enum.count(result) == count do
        merge_message(result)
      else
        update_element(key, {2, result})
      end
    else
      :ignore
    end
  end

  defp merge_message(result) do
    msg =
      result
      |> Enum.sort()
      |> Enum.map(fn {_, ms} -> ms end)
      |> Enum.join()

    {:sms, msg}
  end

 defp update_element(key, value) do
    :ets.update_element(__MODULE__, key, value)
  end

defp lookup(key) do
    case :ets.lookup(@table_name, key) do
      [_ | _] = result -> {:ok, result}
      _ -> {:error, :not_found}
    end
  end

Hello!

Thank you for the proposal. In the projects I worked on we used hashes in Redis to keep message parts, and quite similar key structure.

I will consider adding some aggregation functionality since it appears to be a common need.

Thanks 👍.