cow_ws.erl 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. %% Copyright (c) 2015, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. -module(cow_ws).
  15. -export([key/0]).
  16. -export([encode_key/1]).
  17. -export([negotiate_permessage_deflate/3]).
  18. -export([negotiate_x_webkit_deflate_frame/3]).
  19. -export([validate_permessage_deflate/3]).
  20. -export([parse_header/3]).
  21. -export([parse_payload/9]).
  22. -export([make_frame/4]).
  23. -export([frame/2]).
  24. -export([masked_frame/2]).
  25. -type close_code() :: 1000..1003 | 1006..1011 | 3000..4999.
  26. -export_type([close_code/0]).
  27. -type extensions() :: map().
  28. -export_type([extensions/0]).
  29. -type frag_state() :: undefined | {fin | nofin, text | binary, rsv()}.
  30. -export_type([frag_state/0]).
  31. -type frame() :: close | ping | pong
  32. | {text | binary | close | ping | pong, iodata()}
  33. | {close, close_code(), iodata()}
  34. | {fragment, fin | nofin, text | binary | continuation, iodata()}.
  35. -export_type([frame/0]).
  36. -type frame_type() :: fragment | text | binary | close | ping | pong.
  37. -export_type([frame_type/0]).
  38. -type mask_key() :: undefined | 0..16#ffffffff.
  39. -export_type([mask_key/0]).
  40. -type rsv() :: <<_:3>>.
  41. -export_type([rsv/0]).
  42. -type utf8_state() :: 0..8.
  43. -export_type([utf8_state/0]).
  44. %% @doc Generate a key for the Websocket handshake request.
  45. -spec key() -> binary().
  46. key() ->
  47. base64:encode(crypto:strong_rand_bytes(16)).
  48. %% @doc Encode the key into the accept value for the Websocket handshake response.
  49. -spec encode_key(binary()) -> binary().
  50. encode_key(Key) ->
  51. base64:encode(crypto:hash(sha, [Key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"])).
  52. %% @doc Negotiate the permessage-deflate extension.
  53. %% Ignore if deflate already negotiated.
  54. negotiate_permessage_deflate(_, #{deflate := _}, _) ->
  55. ignore;
  56. negotiate_permessage_deflate(Params, Extensions, Opts) ->
  57. case lists:usort(Params) of
  58. %% Ignore if multiple parameters with the same name.
  59. Params2 when length(Params) =/= length(Params2) ->
  60. ignore;
  61. Params2 ->
  62. %% @todo Might want to make these configurable defaults.
  63. case parse_request_permessage_deflate_params(Params2, 15, takeover, 15, takeover, []) of
  64. ignore ->
  65. ignore;
  66. {ClientWindowBits, ClientTakeOver, ServerWindowBits, ServerTakeOver, RespParams} ->
  67. {Inflate, Deflate} = init_permessage_deflate(ClientWindowBits, ServerWindowBits, Opts),
  68. {ok, [<<"permessage-deflate">>, RespParams],
  69. Extensions#{
  70. deflate => Deflate,
  71. deflate_takeover => ServerTakeOver,
  72. inflate => Inflate,
  73. inflate_takeover => ClientTakeOver}}
  74. end
  75. end.
  76. parse_request_permessage_deflate_params([], CB, CTO, SB, STO, RespParams) ->
  77. {CB, CTO, SB, STO, RespParams};
  78. parse_request_permessage_deflate_params([<<"client_max_window_bits">>|Tail], CB, CTO, SB, STO, RespParams) ->
  79. parse_request_permessage_deflate_params(Tail, CB, CTO, SB, STO,
  80. [<<"; ">>, <<"client_max_window_bits=">>, integer_to_binary(CB)|RespParams]);
  81. parse_request_permessage_deflate_params([{<<"client_max_window_bits">>, Max}|Tail], _, CTO, SB, STO, RespParams) ->
  82. case parse_max_window_bits(Max) of
  83. error ->
  84. ignore;
  85. CB ->
  86. parse_request_permessage_deflate_params(Tail, CB, CTO, SB, STO,
  87. [<<"; ">>, <<"client_max_window_bits=">>, Max|RespParams])
  88. end;
  89. parse_request_permessage_deflate_params([<<"client_no_context_takeover">>|Tail], CB, _, SB, STO, RespParams) ->
  90. parse_request_permessage_deflate_params(Tail, CB, no_takeover, SB, STO, [<<"; ">>, <<"client_no_context_takeover">>|RespParams]);
  91. parse_request_permessage_deflate_params([{<<"server_max_window_bits">>, Max}|Tail], CB, CTO, _, STO, RespParams) ->
  92. case parse_max_window_bits(Max) of
  93. error ->
  94. ignore;
  95. SB ->
  96. parse_request_permessage_deflate_params(Tail, CB, CTO, SB, STO,
  97. [<<"; ">>, <<"server_max_window_bits=">>, Max|RespParams])
  98. end;
  99. parse_request_permessage_deflate_params([<<"server_no_context_takeover">>|Tail], CB, CTO, SB, _, RespParams) ->
  100. parse_request_permessage_deflate_params(Tail, CB, CTO, SB, no_takeover, [<<"; ">>, <<"server_no_context_takeover">>|RespParams]);
  101. %% Ignore if unknown parameter; ignore if parameter with invalid or missing value.
  102. parse_request_permessage_deflate_params(_, _, _, _, _, _) ->
  103. ignore.
  104. parse_max_window_bits(<<"8">>) -> 8;
  105. parse_max_window_bits(<<"9">>) -> 9;
  106. parse_max_window_bits(<<"10">>) -> 10;
  107. parse_max_window_bits(<<"11">>) -> 11;
  108. parse_max_window_bits(<<"12">>) -> 12;
  109. parse_max_window_bits(<<"13">>) -> 13;
  110. parse_max_window_bits(<<"14">>) -> 14;
  111. parse_max_window_bits(<<"15">>) -> 15;
  112. parse_max_window_bits(_) -> error.
  113. % A negative WindowBits value indicates that zlib headers are not used.
  114. init_permessage_deflate(InflateWindowBits, DeflateWindowBits, Opts) ->
  115. Inflate = zlib:open(),
  116. ok = zlib:inflateInit(Inflate, -InflateWindowBits),
  117. Deflate = zlib:open(),
  118. %% @todo Remove this case .. of for OTP 18+ if PR https://github.com/erlang/otp/pull/633 gets merged.
  119. DeflateWindowBits2 = case DeflateWindowBits of
  120. 8 -> 9;
  121. _ -> DeflateWindowBits
  122. end,
  123. ok = zlib:deflateInit(Deflate,
  124. maps:get(level, Opts, best_compression),
  125. deflated,
  126. -DeflateWindowBits2,
  127. maps:get(mem_level, Opts, 8),
  128. maps:get(strategy, Opts, default)),
  129. %% Set the owner pid of the zlib contexts if requested.
  130. _ = case Opts of
  131. #{owner := Pid} ->
  132. true = erlang:port_connect(Inflate, Pid),
  133. true = unlink(Inflate),
  134. true = erlang:port_connect(Deflate, Pid),
  135. unlink(Deflate);
  136. _ ->
  137. true
  138. end,
  139. {Inflate, Deflate}.
  140. %% @doc Negotiate the x-webkit-deflate-frame extension.
  141. %%
  142. %% The implementation is very basic and none of the parameters
  143. %% are currently supported.
  144. negotiate_x_webkit_deflate_frame(_, #{deflate := _}, _) ->
  145. ignore;
  146. negotiate_x_webkit_deflate_frame(_Params, Extensions, Opts) ->
  147. % Since we are negotiating an unconstrained deflate-frame
  148. % then we must be willing to accept frames using the
  149. % maximum window size which is 2^15.
  150. {Inflate, Deflate} = init_permessage_deflate(15, 15, Opts),
  151. {ok, <<"x-webkit-deflate-frame">>,
  152. Extensions#{
  153. deflate => Deflate,
  154. deflate_takeover => takeover,
  155. inflate => Inflate,
  156. inflate_takeover => takeover}}.
  157. %% @doc Validate the negotiated permessage-deflate extension.
  158. %% Error when more than one deflate extension was negotiated.
  159. validate_permessage_deflate(_, #{deflate := _}, _) ->
  160. error;
  161. validate_permessage_deflate(Params, Extensions, Opts) ->
  162. case lists:usort(Params) of
  163. %% Error if multiple parameters with the same name.
  164. Params2 when length(Params) =/= length(Params2) ->
  165. error;
  166. Params2 ->
  167. %% @todo Might want to make some of these configurable defaults if at all possible.
  168. case parse_response_permessage_deflate_params(Params2, 15, takeover, 15, takeover) of
  169. error ->
  170. error;
  171. {ClientWindowBits, ClientTakeOver, ServerWindowBits, ServerTakeOver} ->
  172. {Inflate, Deflate} = init_permessage_deflate(ServerWindowBits, ClientWindowBits, Opts),
  173. {ok, Extensions#{
  174. deflate => Deflate,
  175. deflate_takeover => ClientTakeOver,
  176. inflate => Inflate,
  177. inflate_takeover => ServerTakeOver}}
  178. end
  179. end.
  180. parse_response_permessage_deflate_params([], CB, CTO, SB, STO) ->
  181. {CB, CTO, SB, STO};
  182. parse_response_permessage_deflate_params([{<<"client_max_window_bits">>, Max}|Tail], _, CTO, SB, STO) ->
  183. case parse_max_window_bits(Max) of
  184. error -> error;
  185. CB -> parse_response_permessage_deflate_params(Tail, CB, CTO, SB, STO)
  186. end;
  187. parse_response_permessage_deflate_params([<<"client_no_context_takeover">>|Tail], CB, _, SB, STO) ->
  188. parse_response_permessage_deflate_params(Tail, CB, no_takeover, SB, STO);
  189. parse_response_permessage_deflate_params([{<<"server_max_window_bits">>, Max}|Tail], CB, CTO, _, STO) ->
  190. case parse_max_window_bits(Max) of
  191. error -> error;
  192. SB -> parse_response_permessage_deflate_params(Tail, CB, CTO, SB, STO)
  193. end;
  194. parse_response_permessage_deflate_params([<<"server_no_context_takeover">>|Tail], CB, CTO, SB, _) ->
  195. parse_response_permessage_deflate_params(Tail, CB, CTO, SB, no_takeover);
  196. %% Error if unknown parameter; error if parameter with invalid or missing value.
  197. parse_response_permessage_deflate_params(_, _, _, _, _) ->
  198. error.
  199. %% @doc Parse and validate the Websocket frame header.
  200. %%
  201. %% This function also updates the fragmentation state according to
  202. %% information found in the frame's header.
  203. -spec parse_header(binary(), extensions(), frag_state())
  204. -> error | more | {frame_type(), frag_state(), rsv(), non_neg_integer(), mask_key(), binary()}.
  205. %% RSV bits MUST be 0 unless an extension is negotiated
  206. %% that defines meanings for non-zero values.
  207. parse_header(<< _:1, Rsv:3, _/bits >>, Extensions, _) when Extensions =:= #{}, Rsv =/= 0 -> error;
  208. %% Last 2 RSV bits MUST be 0 if deflate-frame extension is used.
  209. parse_header(<< _:2, 1:1, _/bits >>, #{deflate := _}, _) -> error;
  210. parse_header(<< _:3, 1:1, _/bits >>, #{deflate := _}, _) -> error;
  211. %% Invalid opcode. Note that these opcodes may be used by extensions.
  212. parse_header(<< _:4, 3:4, _/bits >>, _, _) -> error;
  213. parse_header(<< _:4, 4:4, _/bits >>, _, _) -> error;
  214. parse_header(<< _:4, 5:4, _/bits >>, _, _) -> error;
  215. parse_header(<< _:4, 6:4, _/bits >>, _, _) -> error;
  216. parse_header(<< _:4, 7:4, _/bits >>, _, _) -> error;
  217. parse_header(<< _:4, 11:4, _/bits >>, _, _) -> error;
  218. parse_header(<< _:4, 12:4, _/bits >>, _, _) -> error;
  219. parse_header(<< _:4, 13:4, _/bits >>, _, _) -> error;
  220. parse_header(<< _:4, 14:4, _/bits >>, _, _) -> error;
  221. parse_header(<< _:4, 15:4, _/bits >>, _, _) -> error;
  222. %% Control frames MUST NOT be fragmented.
  223. parse_header(<< 0:1, _:3, Opcode:4, _/bits >>, _, _) when Opcode >= 8 -> error;
  224. %% A frame MUST NOT use the zero opcode unless fragmentation was initiated.
  225. parse_header(<< _:4, 0:4, _/bits >>, _, undefined) -> error;
  226. %% Non-control opcode when expecting control message or next fragment.
  227. parse_header(<< _:4, 1:4, _/bits >>, _, {_, _, _}) -> error;
  228. parse_header(<< _:4, 2:4, _/bits >>, _, {_, _, _}) -> error;
  229. parse_header(<< _:4, 3:4, _/bits >>, _, {_, _, _}) -> error;
  230. parse_header(<< _:4, 4:4, _/bits >>, _, {_, _, _}) -> error;
  231. parse_header(<< _:4, 5:4, _/bits >>, _, {_, _, _}) -> error;
  232. parse_header(<< _:4, 6:4, _/bits >>, _, {_, _, _}) -> error;
  233. parse_header(<< _:4, 7:4, _/bits >>, _, {_, _, _}) -> error;
  234. %% Close control frame length MUST be 0 or >= 2.
  235. parse_header(<< _:4, 8:4, _:1, 1:7, _/bits >>, _, _) -> error;
  236. %% Close control frame with incomplete close code. Need more data.
  237. parse_header(Data = << _:4, 8:4, 0:1, Len:7, _/bits >>, _, _) when Len > 1, byte_size(Data) < 4 -> more;
  238. parse_header(Data = << _:4, 8:4, 1:1, Len:7, _/bits >>, _, _) when Len > 1, byte_size(Data) < 8 -> more;
  239. %% 7 bits payload length.
  240. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 0:1, Len:7, Rest/bits >>, _, FragState) when Len < 126 ->
  241. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  242. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 1:1, Len:7, MaskKey:32, Rest/bits >>, _, FragState) when Len < 126 ->
  243. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  244. %% 16 bits payload length.
  245. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 0:1, 126:7, Len:16, Rest/bits >>, _, FragState) when Len > 125, Opcode < 8 ->
  246. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  247. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 1:1, 126:7, Len:16, MaskKey:32, Rest/bits >>, _, FragState) when Len > 125, Opcode < 8 ->
  248. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  249. %% 63 bits payload length.
  250. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 0:1, 127:7, 0:1, Len:63, Rest/bits >>, _, FragState) when Len > 16#ffff, Opcode < 8 ->
  251. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  252. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 1:1, 127:7, 0:1, Len:63, MaskKey:32, Rest/bits >>, _, FragState) when Len > 16#ffff, Opcode < 8 ->
  253. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  254. %% When payload length is over 63 bits, the most significant bit MUST be 0.
  255. parse_header(<< _:9, 127:7, 1:1, _/bits >>, _, _) -> error;
  256. %% For the next two clauses, it can be one of the following:
  257. %%
  258. %% * The minimal number of bytes MUST be used to encode the length
  259. %% * All control frames MUST have a payload length of 125 bytes or less
  260. parse_header(<< _:8, 0:1, 126:7, _:16, _/bits >>, _, _) -> error;
  261. parse_header(<< _:8, 1:1, 126:7, _:48, _/bits >>, _, _) -> error;
  262. parse_header(<< _:8, 0:1, 127:7, _:64, _/bits >>, _, _) -> error;
  263. parse_header(<< _:8, 1:1, 127:7, _:96, _/bits >>, _, _) -> error;
  264. %% Need more data.
  265. parse_header(_, _, _) -> more.
  266. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest) ->
  267. Type = opcode_to_frame_type(Opcode),
  268. Type2 = case Fin of
  269. 0 -> fragment;
  270. 1 -> Type
  271. end,
  272. {Type2, frag_state(Type, Fin, Rsv, FragState), Rsv, Len, MaskKey, Rest}.
  273. opcode_to_frame_type(0) -> fragment;
  274. opcode_to_frame_type(1) -> text;
  275. opcode_to_frame_type(2) -> binary;
  276. opcode_to_frame_type(8) -> close;
  277. opcode_to_frame_type(9) -> ping;
  278. opcode_to_frame_type(10) -> pong.
  279. frag_state(Type, 0, Rsv, undefined) -> {nofin, Type, Rsv};
  280. frag_state(fragment, 0, _, FragState = {nofin, _, _}) -> FragState;
  281. frag_state(fragment, 1, _, {nofin, Type, Rsv}) -> {fin, Type, Rsv};
  282. frag_state(_, 1, _, FragState) -> FragState.
  283. %% @doc Parse and validate the frame's payload.
  284. %%
  285. %% Validation is only required for text and close frames which feature
  286. %% a UTF-8 payload.
  287. -spec parse_payload(binary(), mask_key(), utf8_state(), non_neg_integer(),
  288. frame_type(), non_neg_integer(), frag_state(), extensions(), rsv())
  289. -> {ok, binary(), utf8_state(), binary()} | {more, binary(), utf8_state()} | error.
  290. %% Empty last frame of compressed message.
  291. parse_payload(Data, _, Utf8State, _, _, 0, {fin, _, << 1:1, 0:2 >>},
  292. #{inflate := Inflate, inflate_takeover := TakeOver}, _) ->
  293. _ = zlib:inflate(Inflate, << 0, 0, 255, 255 >>),
  294. case TakeOver of
  295. no_takeover -> zlib:inflateReset(Inflate);
  296. takeover -> ok
  297. end,
  298. {ok, <<>>, Utf8State, Data};
  299. %% Compressed fragmented frame.
  300. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState = {_, _, << 1:1, 0:2 >>},
  301. #{inflate := Inflate, inflate_takeover := TakeOver}, _) ->
  302. {Data2, Rest, Eof} = split_payload(Data, Len),
  303. Payload = inflate_frame(unmask(Data2, MaskKey, ParsedLen), Inflate, TakeOver, FragState, Eof),
  304. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof);
  305. %% Compressed frame.
  306. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState,
  307. #{inflate := Inflate, inflate_takeover := TakeOver}, << 1:1, 0:2 >>) when Type =:= text; Type =:= binary ->
  308. {Data2, Rest, Eof} = split_payload(Data, Len),
  309. Payload = inflate_frame(unmask(Data2, MaskKey, ParsedLen), Inflate, TakeOver, FragState, Eof),
  310. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof);
  311. %% Empty frame.
  312. parse_payload(Data, _, Utf8State = 0, 0, _, 0, _, _, _) ->
  313. {ok, <<>>, Utf8State, Data};
  314. %% Start of close frame.
  315. parse_payload(Data, MaskKey, Utf8State, 0, Type = close, Len, FragState, _, << 0:3 >>) ->
  316. {<< MaskedCode:2/binary, Data2/bits >>, Rest, Eof} = split_payload(Data, Len),
  317. << CloseCode:16 >> = unmask(MaskedCode, MaskKey, 0),
  318. case validate_close_code(CloseCode) of
  319. ok ->
  320. Payload = unmask(Data2, MaskKey, 2),
  321. case validate_payload(Payload, Rest, Utf8State, 2, Type, FragState, Eof) of
  322. {ok, _, Utf8State2, _} -> {ok, CloseCode, Payload, Utf8State2, Rest};
  323. {more, _, Utf8State2} -> {more, CloseCode, Payload, Utf8State2};
  324. Error -> Error
  325. end;
  326. error ->
  327. {error, badframe}
  328. end;
  329. %% Normal frame.
  330. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState, _, << 0:3 >>) ->
  331. {Data2, Rest, Eof} = split_payload(Data, Len),
  332. Payload = unmask(Data2, MaskKey, ParsedLen),
  333. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof).
  334. split_payload(Data, Len) ->
  335. case byte_size(Data) of
  336. Len ->
  337. {Data, <<>>, true};
  338. DataLen when DataLen < Len ->
  339. {Data, <<>>, false};
  340. _ ->
  341. << Data2:Len/binary, Rest/bits >> = Data,
  342. {Data2, Rest, true}
  343. end.
  344. validate_close_code(Code) ->
  345. if
  346. Code < 1000 -> error;
  347. Code =:= 1004 -> error;
  348. Code =:= 1005 -> error;
  349. Code =:= 1006 -> error;
  350. Code > 1011, Code < 3000 -> error;
  351. Code > 4999 -> error;
  352. true -> ok
  353. end.
  354. unmask(Data, undefined, _) ->
  355. Data;
  356. unmask(Data, MaskKey, 0) ->
  357. mask(Data, MaskKey, <<>>);
  358. %% We unmask on the fly so we need to continue from the right mask byte.
  359. unmask(Data, MaskKey, UnmaskedLen) ->
  360. Left = UnmaskedLen rem 4,
  361. Right = 4 - Left,
  362. MaskKey2 = (MaskKey bsl (Left * 8)) + (MaskKey bsr (Right * 8)),
  363. mask(Data, MaskKey2, <<>>).
  364. mask(<<>>, _, Unmasked) ->
  365. Unmasked;
  366. mask(<< O:32, Rest/bits >>, MaskKey, Acc) ->
  367. T = O bxor MaskKey,
  368. mask(Rest, MaskKey, << Acc/binary, T:32 >>);
  369. mask(<< O:24 >>, MaskKey, Acc) ->
  370. << MaskKey2:24, _:8 >> = << MaskKey:32 >>,
  371. T = O bxor MaskKey2,
  372. << Acc/binary, T:24 >>;
  373. mask(<< O:16 >>, MaskKey, Acc) ->
  374. << MaskKey2:16, _:16 >> = << MaskKey:32 >>,
  375. T = O bxor MaskKey2,
  376. << Acc/binary, T:16 >>;
  377. mask(<< O:8 >>, MaskKey, Acc) ->
  378. << MaskKey2:8, _:24 >> = << MaskKey:32 >>,
  379. T = O bxor MaskKey2,
  380. << Acc/binary, T:8 >>.
  381. inflate_frame(Data, Inflate, TakeOver, FragState, true)
  382. when FragState =:= undefined; element(1, FragState) =:= fin ->
  383. Data2 = zlib:inflate(Inflate, << Data/binary, 0, 0, 255, 255 >>),
  384. case TakeOver of
  385. no_takeover -> zlib:inflateReset(Inflate);
  386. takeover -> ok
  387. end,
  388. iolist_to_binary(Data2);
  389. inflate_frame(Data, Inflate, _T, _F, _E) ->
  390. iolist_to_binary(zlib:inflate(Inflate, Data)).
  391. %% Text frames and close control frames MUST have a payload that is valid UTF-8.
  392. validate_payload(Payload, Rest, Utf8State, _, Type, _, Eof) when Type =:= text; Type =:= close ->
  393. case validate_utf8(Payload, Utf8State) of
  394. 1 -> {error, badencoding};
  395. Utf8State2 when not Eof -> {more, Payload, Utf8State2};
  396. 0 when Eof -> {ok, Payload, 0, Rest};
  397. _ -> {error, badencoding}
  398. end;
  399. validate_payload(Payload, Rest, Utf8State, _, fragment, {Fin, text, _}, Eof) ->
  400. case validate_utf8(Payload, Utf8State) of
  401. 1 -> {error, badencoding};
  402. 0 when Eof -> {ok, Payload, 0, Rest};
  403. Utf8State2 when Eof, Fin =:= nofin -> {ok, Payload, Utf8State2, Rest};
  404. Utf8State2 when not Eof -> {more, Payload, Utf8State2};
  405. _ -> {error, badencoding}
  406. end;
  407. validate_payload(Payload, _, Utf8State, _, _, _, false) ->
  408. {more, Payload, Utf8State};
  409. validate_payload(Payload, Rest, Utf8State, _, _, _, true) ->
  410. {ok, Payload, Utf8State, Rest}.
  411. %% Based on the Flexible and Economical UTF-8 Decoder algorithm by
  412. %% Bjoern Hoehrmann <bjoern@hoehrmann.de> (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/).
  413. %%
  414. %% The original algorithm has been unrolled into all combinations of values for C and State
  415. %% each with a clause. The common clauses were then grouped together.
  416. %%
  417. %% This function returns 0 on success, 1 on error, and 2..8 on incomplete data.
  418. validate_utf8(<<>>, State) -> State;
  419. validate_utf8(<< C, Rest/bits >>, 0) when C < 128 -> validate_utf8(Rest, 0);
  420. validate_utf8(<< C, Rest/bits >>, 2) when C >= 128, C < 144 -> validate_utf8(Rest, 0);
  421. validate_utf8(<< C, Rest/bits >>, 3) when C >= 128, C < 144 -> validate_utf8(Rest, 2);
  422. validate_utf8(<< C, Rest/bits >>, 5) when C >= 128, C < 144 -> validate_utf8(Rest, 2);
  423. validate_utf8(<< C, Rest/bits >>, 7) when C >= 128, C < 144 -> validate_utf8(Rest, 3);
  424. validate_utf8(<< C, Rest/bits >>, 8) when C >= 128, C < 144 -> validate_utf8(Rest, 3);
  425. validate_utf8(<< C, Rest/bits >>, 2) when C >= 144, C < 160 -> validate_utf8(Rest, 0);
  426. validate_utf8(<< C, Rest/bits >>, 3) when C >= 144, C < 160 -> validate_utf8(Rest, 2);
  427. validate_utf8(<< C, Rest/bits >>, 5) when C >= 144, C < 160 -> validate_utf8(Rest, 2);
  428. validate_utf8(<< C, Rest/bits >>, 6) when C >= 144, C < 160 -> validate_utf8(Rest, 3);
  429. validate_utf8(<< C, Rest/bits >>, 7) when C >= 144, C < 160 -> validate_utf8(Rest, 3);
  430. validate_utf8(<< C, Rest/bits >>, 2) when C >= 160, C < 192 -> validate_utf8(Rest, 0);
  431. validate_utf8(<< C, Rest/bits >>, 3) when C >= 160, C < 192 -> validate_utf8(Rest, 2);
  432. validate_utf8(<< C, Rest/bits >>, 4) when C >= 160, C < 192 -> validate_utf8(Rest, 2);
  433. validate_utf8(<< C, Rest/bits >>, 6) when C >= 160, C < 192 -> validate_utf8(Rest, 3);
  434. validate_utf8(<< C, Rest/bits >>, 7) when C >= 160, C < 192 -> validate_utf8(Rest, 3);
  435. validate_utf8(<< C, Rest/bits >>, 0) when C >= 194, C < 224 -> validate_utf8(Rest, 2);
  436. validate_utf8(<< 224, Rest/bits >>, 0) -> validate_utf8(Rest, 4);
  437. validate_utf8(<< C, Rest/bits >>, 0) when C >= 225, C < 237 -> validate_utf8(Rest, 3);
  438. validate_utf8(<< 237, Rest/bits >>, 0) -> validate_utf8(Rest, 5);
  439. validate_utf8(<< C, Rest/bits >>, 0) when C =:= 238; C =:= 239 -> validate_utf8(Rest, 3);
  440. validate_utf8(<< 240, Rest/bits >>, 0) -> validate_utf8(Rest, 6);
  441. validate_utf8(<< C, Rest/bits >>, 0) when C =:= 241; C =:= 242; C =:= 243 -> validate_utf8(Rest, 7);
  442. validate_utf8(<< 244, Rest/bits >>, 0) -> validate_utf8(Rest, 8);
  443. validate_utf8(_, _) -> 1.
  444. %% @doc Return a frame tuple from parsed state and data.
  445. -spec make_frame(frame_type(), binary(), close_code(), frag_state()) -> frame().
  446. %% Fragmented frame.
  447. make_frame(fragment, Payload, _, {Fin, Type, _}) -> {fragment, Fin, Type, Payload};
  448. make_frame(text, Payload, _, _) -> {text, Payload};
  449. make_frame(binary, Payload, _, _) -> {binary, Payload};
  450. make_frame(close, <<>>, undefined, _) -> close;
  451. make_frame(close, Payload, CloseCode, _) -> {close, CloseCode, Payload};
  452. make_frame(ping, <<>>, _, _) -> ping;
  453. make_frame(ping, Payload, _, _) -> {ping, Payload};
  454. make_frame(pong, <<>>, _, _) -> pong;
  455. make_frame(pong, Payload, _, _) -> {pong, Payload}.
  456. %% @doc Construct an unmasked Websocket frame.
  457. -spec frame(frame(), extensions()) -> iodata().
  458. %% Control frames. Control packets must not be > 125 in length.
  459. frame(close, _) ->
  460. << 1:1, 0:3, 8:4, 0:8 >>;
  461. frame(ping, _) ->
  462. << 1:1, 0:3, 9:4, 0:8 >>;
  463. frame(pong, _) ->
  464. << 1:1, 0:3, 10:4, 0:8 >>;
  465. frame({close, Payload}, Extensions) ->
  466. frame({close, 1000, Payload}, Extensions);
  467. frame({close, StatusCode, Payload}, _) ->
  468. Len = 2 + iolist_size(Payload),
  469. true = Len =< 125,
  470. [<< 1:1, 0:3, 8:4, 0:1, Len:7, StatusCode:16 >>, Payload];
  471. frame({ping, Payload}, _) ->
  472. Len = iolist_size(Payload),
  473. true = Len =< 125,
  474. [<< 1:1, 0:3, 9:4, 0:1, Len:7 >>, Payload];
  475. frame({pong, Payload}, _) ->
  476. Len = iolist_size(Payload),
  477. true = Len =< 125,
  478. [<< 1:1, 0:3, 10:4, 0:1, Len:7 >>, Payload];
  479. %% Data frames, deflate-frame extension.
  480. frame({text, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver}) ->
  481. Payload2 = deflate_frame(Payload, Deflate, TakeOver),
  482. Len = payload_length(Payload2),
  483. [<< 1:1, 1:1, 0:2, 1:4, 0:1, Len/bits >>, Payload2];
  484. frame({binary, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver}) ->
  485. Payload2 = deflate_frame(Payload, Deflate, TakeOver),
  486. Len = payload_length(Payload2),
  487. [<< 1:1, 1:1, 0:2, 2:4, 0:1, Len/bits >>, Payload2];
  488. %% Data frames.
  489. frame({text, Payload}, _) ->
  490. Len = payload_length(Payload),
  491. [<< 1:1, 0:3, 1:4, 0:1, Len/bits >>, Payload];
  492. frame({binary, Payload}, _) ->
  493. Len = payload_length(Payload),
  494. [<< 1:1, 0:3, 2:4, 0:1, Len/bits >>, Payload].
  495. %% @doc Construct a masked Websocket frame.
  496. %%
  497. %% We use a mask key of 0 if there is no payload for close, ping and pong frames.
  498. -spec masked_frame(frame(), extensions()) -> iodata().
  499. %% Control frames. Control packets must not be > 125 in length.
  500. masked_frame(close, _) ->
  501. << 1:1, 0:3, 8:4, 1:1, 0:39 >>;
  502. masked_frame(ping, _) ->
  503. << 1:1, 0:3, 9:4, 1:1, 0:39 >>;
  504. masked_frame(pong, _) ->
  505. << 1:1, 0:3, 10:4, 1:1, 0:39 >>;
  506. masked_frame({close, Payload}, Extensions) ->
  507. frame({close, 1000, Payload}, Extensions);
  508. masked_frame({close, StatusCode, Payload}, _) ->
  509. Len = 2 + iolist_size(Payload),
  510. true = Len =< 125,
  511. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  512. [<< 1:1, 0:3, 8:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary([<< StatusCode:16 >>, Payload]), MaskKey, <<>>)];
  513. masked_frame({ping, Payload}, _) ->
  514. Len = iolist_size(Payload),
  515. true = Len =< 125,
  516. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  517. [<< 1:1, 0:3, 9:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  518. masked_frame({pong, Payload}, _) ->
  519. Len = iolist_size(Payload),
  520. true = Len =< 125,
  521. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  522. [<< 1:1, 0:3, 10:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  523. %% Data frames, deflate-frame extension.
  524. masked_frame({text, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver}) ->
  525. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  526. Payload2 = mask(deflate_frame(Payload, Deflate, TakeOver), MaskKey, <<>>),
  527. Len = payload_length(Payload2),
  528. [<< 1:1, 1:1, 0:2, 1:4, 1:1, Len/bits >>, MaskKeyBin, Payload2];
  529. masked_frame({binary, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver}) ->
  530. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  531. Payload2 = mask(deflate_frame(Payload, Deflate, TakeOver), MaskKey, <<>>),
  532. Len = payload_length(Payload2),
  533. [<< 1:1, 1:1, 0:2, 2:4, 1:1, Len/bits >>, MaskKeyBin, Payload2];
  534. %% Data frames.
  535. masked_frame({text, Payload}, _) ->
  536. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  537. Len = payload_length(Payload),
  538. [<< 1:1, 0:3, 1:4, 1:1, Len/bits >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  539. masked_frame({binary, Payload}, _) ->
  540. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  541. Len = payload_length(Payload),
  542. [<< 1:1, 0:3, 2:4, 1:1, Len/bits >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)].
  543. payload_length(Payload) ->
  544. case iolist_size(Payload) of
  545. N when N =< 125 -> << N:7 >>;
  546. N when N =< 16#ffff -> << 126:7, N:16 >>;
  547. N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >>
  548. end.
  549. deflate_frame(Payload, Deflate, TakeOver) ->
  550. Deflated = iolist_to_binary(zlib:deflate(Deflate, Payload, sync)),
  551. case TakeOver of
  552. no_takeover -> zlib:deflateReset(Deflate);
  553. takeover -> ok
  554. end,
  555. Len = byte_size(Deflated) - 4,
  556. case Deflated of
  557. << Body:Len/binary, 0:8, 0:8, 255:8, 255:8 >> -> Body;
  558. _ -> Deflated
  559. end.