ref: rc/2.0.0 utos/utos/src/utos_net_websocket_handler_frame.erl -rw-r--r-- 2.0 KiB View raw
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
-module(utos_net_websocket_handler_frame).

-export([
	 pack/1,
	 unpack/1
	]).


mask_decode(K, P) when is_integer(K), is_binary(P) ->
    mask_decode(K, P, <<>>).

mask_decode(K, <<Data:32, Rest/bits>>, A) ->
    X = Data bxor K,
    mask_decode(K, Rest, <<A/binary, X:32>>);
mask_decode(K, <<Data:24>>, A) ->
    <<Part:24, _:8>> = <<K:32>>,
    X = Data bxor Part,
    <<A/binary, X:24>>;
mask_decode(K, <<Data:16>>, A) ->
    <<Part:16, _:16 >> = <<K:32>>,
    X = Data bxor Part,
    <<A/binary, X:16>>;
mask_decode(K, <<Data:8>>, A) ->
    <<Part:8, _:24>> = <<K:32>>,
    X = Data bxor Part,
    <<A/binary, X:8>>;
mask_decode(_, <<>>, A) ->
    A.

pack({Bin, Len}) when Len < 126 ->
    {ok, <<1:1, 0:3, 2:4, 0:1, Len:7, Bin/bits>>};
pack({Bin, Len}) when Len < 65536 ->
    {ok, <<1:1, 0:3, 2:4, 0:1, 126:7, Len:16, Bin/bits>>};
pack({Bin, Len}) ->
    {ok, <<1:1, 0:3, 2:4, 0:1, 127:7, Len:64, Bin/bits>>};
pack(Bin) when is_binary(Bin) ->
    Len = erlang:byte_size(Bin),
    pack({Bin, Len});
pack(_) ->
    {error, request}.

unmask(Len, Mask, Data) when byte_size(Data) < Len ->
    {ok, {incomplete, Data}};
unmask(Len, Mask, Data) when byte_size(Data) == Len ->
    {ok, {mask_decode(Mask, Data), <<>>}};
unmask(Len, Mask, Data) when byte_size(Data) > Len ->
    <<Msg:Len/binary, Rest/bits>> = Data,
    {ok, {mask_decode(Mask, Msg), Rest}}.

unpack(<<F:1, _:3, 8:4, _/bits>>) ->
    {ok, closed};
unpack(<<F:1, _:3, 9:4, 0:1, L:7, Mask:32, Data/bits>>) ->
    <<Decode:L/binary, Rest/bits>> = Data,
    {ok, {F, ping, L, Decode, Rest}};
unpack(<<F:1, _:3, Op:4, 1:1, 126:7, L:16, Mask:32, Data/bits>>) ->
    {ok, {Decode, Rest}} = unmask(L, Mask, Data),
    {ok, {F, Op, L, Decode, Rest}};
unpack(<<F:1, _:3, Op:4, 1:1, 127:7, L:64, Mask:32, Data/bits>>) ->
    {ok, {Decode, Rest}} = unmask(L, Mask, Data),
    {ok, {F, Op, L, Decode, Rest}};
unpack(<<F:1, _:3, Op:4, 1:1, L:7, Mask:32, Data/bits>>) ->
    {ok, {Decode, Rest}} = unmask(L, Mask, Data),
    {ok, {F, Op, L, Decode, Rest}};
unpack(_) ->
    {ok, incomplete}.