Add basic forwarding/multiplexing functionality

This commit is contained in:
bluepython508
2024-09-15 14:00:32 +01:00
parent cb207114a7
commit 5229bd8d1c
7 changed files with 412 additions and 1 deletions

155
lib/proto/proto.ex Normal file
View File

@@ -0,0 +1,155 @@
defmodule Frajtano.Proto do
@agentc_request_identities 11
@agentc_sign_request 13
@agentc_remove_all_identities 19
@agentc_extension 27
@agent_failure 5
@agent_success 6
@agent_identities_answer 12
@agent_sign_response 14
@agent_extension_failure 28
@agent_extension_response 29
def encode({:agentc_request_identities, nil}),
do: encode_packet(@agentc_request_identities, <<>>)
def encode({:agentc_sign_request, {key, data, flags}}),
do:
encode_packet(
@agentc_sign_request,
<<byte_size(key)::big-integer-32, key::bytes, byte_size(data)::big-integer-32,
data::bytes, flags::big-integer-32>>
)
def encode({:agentc_remove_all_identities, nil}),
do: encode_packet(@agentc_remove_all_identities, <<>>)
def encode({:agentc_extension, {type, data}}),
do:
encode_packet(
@agentc_extension,
<<byte_size(type)::big-integer-32, type::bytes, data::bytes>>
)
def encode({:agent_failure, nil}), do: encode_packet(@agent_failure, <<>>)
def encode({:agent_success, nil}), do: encode_packet(@agent_success, <<>>)
def encode({:agent_identities_answer, keys}),
do:
encode_packet(
@agent_identities_answer,
<<length(keys)::big-integer-32,
keys
|> Enum.map_join(fn {key, comment} ->
<<
byte_size(key)::big-integer-32,
key::bytes,
byte_size(comment)::big-integer-32,
comment::bytes
>>
end)::bytes>>
)
def encode({:agent_sign_response, signature}),
do:
encode_packet(
@agent_sign_response,
<<byte_size(signature)::big-integer-32, signature::bytes>>
)
def encode({:agent_extension_failure, nil}),
do: encode_packet(@agent_extension_failure, <<>>)
def encode({:agent_extension_response, {type, data}}),
do:
encode_packet(
@agent_extension_response,
<<byte_size(type)::big-integer-32, type::bytes, data::bytes>>
)
defp encode_packet(type, contents),
do: <<byte_size(contents) + 1::big-integer-32, type::integer-8, contents::bytes>>
def decode(packet) do
case decode_packet(packet) do
{{@agentc_request_identities, contents}, rest} ->
{{:agentc_request_identities, decode_agentc_request_identities(contents)}, rest}
{{@agentc_sign_request, contents}, rest} ->
{{:agentc_sign_request, decode_agentc_sign_request(contents)}, rest}
{{@agentc_remove_all_identities, contents}, rest} ->
{{:agentc_remove_all_identities, decode_agentc_remove_all_identities(contents)}, rest}
{{@agentc_extension, contents}, rest} ->
{{:agentc_extension, decode_agentc_extension(contents)}, rest}
{{@agent_failure, contents}, rest} ->
{{:agent_failure, decode_agent_failure(contents)}, rest}
{{@agent_success, contents}, rest} ->
{{:agent_success, decode_agent_success(contents)}, rest}
{{@agent_identities_answer, contents}, rest} ->
{{:agent_identities_answer, decode_agent_identities_answer(contents)}, rest}
{{@agent_sign_response, contents}, rest} ->
{{:agent_sign_response, decode_agent_sign_response(contents)}, rest}
{{@agent_extension_failure, contents}, rest} ->
{{:agent_extension_failure, decode_agent_extension_failure(contents)}, rest}
{{@agent_extension_response, contents}, rest} ->
{{:agent_extension_response, decode_agent_extension_response(contents)}, rest}
{nil, rest} ->
{nil, rest}
end
end
defp decode_packet(
<<length::big-integer-32, type::integer-8, contents::bytes-size(length - 1),
rest::bytes>>
),
do: {{type, contents}, rest}
defp decode_packet(rest), do: {nil, rest}
defp decode_agentc_request_identities(<<>>), do: nil
defp decode_agentc_sign_request(
<<keylen::big-integer-32, key::bytes-size(keylen), datalen::big-integer-32,
data::bytes-size(datalen), flags::big-integer-32>>
),
do: {key, data, flags}
defp decode_agentc_remove_all_identities(<<>>), do: nil
defp decode_agentc_extension(
<<tylen::big-integer-32, type::bytes-size(tylen), contents::bytes>>
),
do: {type, contents}
defp decode_agent_failure(<<>>), do: nil
defp decode_agent_success(<<>>), do: nil
defp decode_agent_identities_answer(<<nkeys::big-integer-32, keys::bytes>>) do
lst =
for <<keylen::big-integer-32, key::bytes-size(keylen), commentlen::big-integer-32,
comment::bytes-size(commentlen) <- keys>>,
do: {key, comment}
^nkeys = length(lst)
lst
end
defp decode_agent_sign_response(<<len::big-integer-32, sig::bytes-size(len)>>), do: sig
defp decode_agent_extension_failure(<<>>), do: nil
defp decode_agent_extension_response(
<<tylen::big-integer-32, type::bytes-size(tylen), contents::bytes>>
),
do: {type, contents}
end