Packages
smppex
3.0.4
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
retired
3.1.0
retired
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.4.0
2.3.3
2.3.2
2.3.1
2.3.0
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.0
2.0.1
2.0.0
1.0.1
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
SMPP 3.4 protocol and framework implemented in Elixir
Current section
Files
Jump to
Current section
Files
lib/smppex/protocol/optional_fields_builder.ex
defmodule SMPPEX.Protocol.OptionalFieldsBuilder do
@moduledoc false
alias SMPPEX.Protocol.Pack
alias SMPPEX.Protocol.TlvFormat
use Bitwise
@spec build(map) :: {:ok, iodata} | {:error, any}
def build(fields) when is_map(fields) do
fields |> Map.to_list() |> build([])
end
defp build([], built), do: {:ok, built}
defp build([{name, value} | rest], built) when is_atom(name) do
case TlvFormat.id_by_name(name) do
{:ok, id} -> build([{id, value} | rest], built)
:unknown -> {:error, "Can't find id for name #{inspect(name)}"}
end
end
defp build([{id, value} | rest], built) do
case build_tlv(id, value) do
{:ok, bin} -> build(rest, [bin | built])
{:error, error} -> {:error, {"Error building optional fields", error}}
end
end
defp build_tlv(id, value) do
case build_value(id, value) do
{:ok, bin} -> Pack.tlv(id, bin)
{:error, error} -> {:error, {"Invalid value for Tag #{inspect(id)}", error}}
end
end
defp build_value(id, value) do
format = TlvFormat.format_by_id(id)
case format do
{:ok, format} -> build_value_with_format(value, format)
:unknown -> build_value_without_format(value)
end
end
@invalid_octet_string "TLV Octet String: invalid value"
@invalid_unknown_tlv_value "TLV: value for unknown Tag is not binary"
defp build_value_with_format(value, {:integer, size}), do: Pack.integer(value, size)
defp build_value_with_format(value, {:c_octet_string, {:max, size}}),
do: Pack.c_octet_string(value, {:max, size})
defp build_value_with_format(value, {:octet_string, size}) when is_integer(size),
do: Pack.octet_string(value, size)
defp build_value_with_format(value, {:octet_string, {_from, _to}})
when not is_binary(value) do
{:error, @invalid_octet_string}
end
defp build_value_with_format(value, {:octet_string, {from, to}})
when byte_size(value) > to or byte_size(value) < from do
{:error, @invalid_octet_string}
end
defp build_value_with_format(value, {:octet_string, {_from, _to}}), do: {:ok, value}
defp build_value_without_format(value) when not is_binary(value),
do: {:error, @invalid_unknown_tlv_value}
defp build_value_without_format(value), do: {:ok, value}
end