Open hauleth opened 1 year ago
This is not high prio for us but would be reasonable easy to implement.
Do git grep TCP_PB_4
and add corresponding code for TCP_PB_LITTLE_4
and maybe also TCP_PB_LITTLE_2
for completeness.
Do not forget the https://www.erlang.org/eeps/eep-0034 while you are at it :-)
I was considering creating a PR for this, but EEP-34 mentions that the author implemented it. Is there an existing PR for this feature?
I like the use of negative numbers for the PacketType
described in EEP-34 because we can keep the same type. If we use an atom, something like '4_little'
would require quotes, since it starts with a digit, and little_4
breaks symmetry (subjective).
For gen_tcp:connect
options, something like {packet, 4, little}
or {packet, {4, little}}
also introduces some asymmetry, since packet type is also used in erlang:decode_packet
. It would create a tuple parameter, when all others are atoms or integers, depending on how we pass on the arguments.
I would go with {4, little}
as it would allow us to extend it in future, as I see one more improvement possible there. Because in general we have 2 configuration options:
So in total there are 4 combinations for each of possible sizes. We could leave negative numbers for inclusive/exclusive sizes and have textual flag for endianness. That allows us to cover all possible combinations:
{N, big}
(the same as current N
) - big-endian, size exclusive{-N, big}
- big-endian, size inclusive{N, little}
- little-endian, size exclusive{-N, little}
- little-endian, size inclusiveI do not see how that would be a problem for erlang:decode_packet/3
as it could be implemented there as well in exactly the same format as described there.
I think this proposal or EEP-34 is a very welcome change.
For anyone interested, here's a proof-of-concept for 3 byte little-endian packet headers using the {packet, -N}
notation per https://www.erlang.org/eeps/eep-0034#new-packet-types. An example use case is parsing MySQL packets 1, here focused on the handshake 2.
MySQL packets are <<Len:24/little, Seq:8, Payload:Len/binary>>
. The handshake is (essentially) <<10, ServerVsn/binary, 0, ...>>
.
$ docker run --rm -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
$ cat mysql.escript
#!/usr/bin/env escript
main(_) ->
connect1(),
connect2(),
ok.
connect1() ->
{ok, S} = gen_tcp:connect("localhost", 3306, [binary, {active, false}]),
{ok, Data} = gen_tcp:recv(S, 0),
<<Len:24/little, _Seq:8, Rest0:Len/binary>> = Data,
<<10, Rest1/binary>> = Rest0,
[ServerVsn, _Rest] = binary:split(Rest1, <<0>>),
io:format("server version: ~s~n", [ServerVsn]).
connect2() ->
{ok, S} = gen_tcp:connect("localhost", 3306, [binary, {active, false}, {packet, -3}]),
{ok, Data} = gen_tcp:recv(S, 0),
<<_Seq:8, 10, Rest/binary>> = Data,
[ServerVsn, _Rest] = binary:split(Rest, <<0>>),
io:format("server version: ~s~n", [ServerVsn]).
$ ./mysql.escript
server version: 8.2.0
server version: 8.2.0
Below is a diff, also available at https://github.com/wojtekmach/otp/commits/wm-little/.
I prefer {4, little}
. I do not like negative values meaning little endian.
Is anyone working on a PR for this one?
I'm not! It's on my long term TODO list but if anyone would like to pick it up, by all means. I hope my proof of concept helps.
Is your feature request related to a problem? Please describe.
I want to implement protocol that uses
gen_tcp
and uses little endian for packet length definitions.Describe the solution you'd like
Something like:
Or:
Would make it quite handy.
Describe alternatives you've considered
It is still possible to do it manually right now via
{active, false}
or similar to capture the length and doing everything manually, it is just a little bit more convenient to have it as a part ofpacket
option.