cow_ws.erl 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. %% Copyright (c) 2015-2023, 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 deflate_opts() :: #{
  30. %% Compression parameters.
  31. level => zlib:zlevel(),
  32. mem_level => zlib:zmemlevel(),
  33. strategy => zlib:zstrategy(),
  34. %% Whether the compression context will carry over between frames.
  35. server_context_takeover => takeover | no_takeover,
  36. client_context_takeover => takeover | no_takeover,
  37. %% LZ77 sliding window size limits.
  38. server_max_window_bits => 8..15,
  39. client_max_window_bits => 8..15
  40. }.
  41. -export_type([deflate_opts/0]).
  42. -type frag_state() :: undefined | {fin | nofin, text | binary, rsv()}.
  43. -export_type([frag_state/0]).
  44. -type frame() :: close | ping | pong
  45. | {text | binary | close | ping | pong, iodata()}
  46. | {close, close_code(), iodata()}
  47. | {fragment, fin | nofin, text | binary | continuation, iodata()}.
  48. -export_type([frame/0]).
  49. -type frame_type() :: fragment | text | binary | close | ping | pong.
  50. -export_type([frame_type/0]).
  51. -type mask_key() :: undefined | 0..16#ffffffff.
  52. -export_type([mask_key/0]).
  53. -type rsv() :: <<_:3>>.
  54. -export_type([rsv/0]).
  55. -type utf8_state() :: 0..8 | undefined.
  56. -export_type([utf8_state/0]).
  57. %% @doc Generate a key for the Websocket handshake request.
  58. -spec key() -> binary().
  59. key() ->
  60. base64:encode(crypto:strong_rand_bytes(16)).
  61. %% @doc Encode the key into the accept value for the Websocket handshake response.
  62. -spec encode_key(binary()) -> binary().
  63. encode_key(Key) ->
  64. base64:encode(crypto:hash(sha, [Key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"])).
  65. %% @doc Negotiate the permessage-deflate extension.
  66. -spec negotiate_permessage_deflate(
  67. [binary() | {binary(), binary()}], Exts, deflate_opts())
  68. -> ignore | {ok, iolist(), Exts} when Exts::extensions().
  69. %% Ignore if deflate already negotiated.
  70. negotiate_permessage_deflate(_, #{deflate := _}, _) ->
  71. ignore;
  72. negotiate_permessage_deflate(Params, Extensions, Opts) ->
  73. case lists:usort(Params) of
  74. %% Ignore if multiple parameters with the same name.
  75. Params2 when length(Params) =/= length(Params2) ->
  76. ignore;
  77. Params2 ->
  78. negotiate_permessage_deflate1(Params2, Extensions, Opts)
  79. end.
  80. negotiate_permessage_deflate1(Params, Extensions, Opts) ->
  81. %% We are allowed to send back no_takeover even if the client
  82. %% accepts takeover. Therefore we use no_takeover if any of
  83. %% the inputs have it.
  84. ServerTakeover = maps:get(server_context_takeover, Opts, takeover),
  85. ClientTakeover = maps:get(client_context_takeover, Opts, takeover),
  86. %% We can send back window bits smaller than or equal to what
  87. %% the client sends us.
  88. ServerMaxWindowBits = maps:get(server_max_window_bits, Opts, 15),
  89. ClientMaxWindowBits = maps:get(client_max_window_bits, Opts, 15),
  90. %% We may need to send back no_context_takeover depending on configuration.
  91. RespParams0 = case ServerTakeover of
  92. takeover -> [];
  93. no_takeover -> [<<"; server_no_context_takeover">>]
  94. end,
  95. RespParams1 = case ClientTakeover of
  96. takeover -> RespParams0;
  97. no_takeover -> [<<"; client_no_context_takeover">>|RespParams0]
  98. end,
  99. Negotiated0 = #{
  100. server_context_takeover => ServerTakeover,
  101. client_context_takeover => ClientTakeover,
  102. server_max_window_bits => ServerMaxWindowBits,
  103. client_max_window_bits => ClientMaxWindowBits
  104. },
  105. case negotiate_params(Params, Negotiated0, RespParams1) of
  106. ignore ->
  107. ignore;
  108. {#{server_max_window_bits := SB}, _} when SB > ServerMaxWindowBits ->
  109. ignore;
  110. {#{client_max_window_bits := CB}, _} when CB > ClientMaxWindowBits ->
  111. ignore;
  112. {Negotiated, RespParams2} ->
  113. %% We add the configured max window bits if necessary.
  114. RespParams = case Negotiated of
  115. #{server_max_window_bits_set := true} -> RespParams2;
  116. _ when ServerMaxWindowBits =:= 15 -> RespParams2;
  117. _ -> [<<"; server_max_window_bits=">>,
  118. integer_to_binary(ServerMaxWindowBits)|RespParams2]
  119. end,
  120. {Inflate, Deflate} = init_permessage_deflate(
  121. maps:get(client_max_window_bits, Negotiated),
  122. maps:get(server_max_window_bits, Negotiated), Opts),
  123. {ok, [<<"permessage-deflate">>, RespParams], Extensions#{
  124. deflate => Deflate,
  125. deflate_takeover => maps:get(server_context_takeover, Negotiated),
  126. inflate => Inflate,
  127. inflate_takeover => maps:get(client_context_takeover, Negotiated)}}
  128. end.
  129. negotiate_params([], Negotiated, RespParams) ->
  130. {Negotiated, RespParams};
  131. %% We must only send the client_max_window_bits parameter if the
  132. %% request explicitly indicated the client supports it.
  133. negotiate_params([<<"client_max_window_bits">>|Tail], Negotiated, RespParams) ->
  134. CB = maps:get(client_max_window_bits, Negotiated),
  135. negotiate_params(Tail, Negotiated#{client_max_window_bits_set => true},
  136. [<<"; client_max_window_bits=">>, integer_to_binary(CB)|RespParams]);
  137. negotiate_params([{<<"client_max_window_bits">>, Max}|Tail], Negotiated, RespParams) ->
  138. CB0 = maps:get(client_max_window_bits, Negotiated, undefined),
  139. case parse_max_window_bits(Max) of
  140. error ->
  141. ignore;
  142. CB when CB =< CB0 ->
  143. negotiate_params(Tail, Negotiated#{client_max_window_bits => CB},
  144. [<<"; client_max_window_bits=">>, Max|RespParams]);
  145. %% When the client sends window bits larger than the server wants
  146. %% to use, we use what the server defined.
  147. _ ->
  148. negotiate_params(Tail, Negotiated,
  149. [<<"; client_max_window_bits=">>, integer_to_binary(CB0)|RespParams])
  150. end;
  151. negotiate_params([{<<"server_max_window_bits">>, Max}|Tail], Negotiated, RespParams) ->
  152. SB0 = maps:get(server_max_window_bits, Negotiated, undefined),
  153. case parse_max_window_bits(Max) of
  154. error ->
  155. ignore;
  156. SB when SB =< SB0 ->
  157. negotiate_params(Tail, Negotiated#{
  158. server_max_window_bits => SB,
  159. server_max_window_bits_set => true},
  160. [<<"; server_max_window_bits=">>, Max|RespParams]);
  161. %% When the client sends window bits larger than the server wants
  162. %% to use, we use what the server defined. The parameter will be
  163. %% set only when this function returns.
  164. _ ->
  165. negotiate_params(Tail, Negotiated, RespParams)
  166. end;
  167. %% We only need to send the no_context_takeover parameter back
  168. %% here if we didn't already define it via configuration.
  169. negotiate_params([<<"client_no_context_takeover">>|Tail], Negotiated, RespParams) ->
  170. case maps:get(client_context_takeover, Negotiated) of
  171. no_takeover ->
  172. negotiate_params(Tail, Negotiated, RespParams);
  173. takeover ->
  174. negotiate_params(Tail, Negotiated#{client_context_takeover => no_takeover},
  175. [<<"; client_no_context_takeover">>|RespParams])
  176. end;
  177. negotiate_params([<<"server_no_context_takeover">>|Tail], Negotiated, RespParams) ->
  178. case maps:get(server_context_takeover, Negotiated) of
  179. no_takeover ->
  180. negotiate_params(Tail, Negotiated, RespParams);
  181. takeover ->
  182. negotiate_params(Tail, Negotiated#{server_context_takeover => no_takeover},
  183. [<<"; server_no_context_takeover">>|RespParams])
  184. end;
  185. %% Ignore if unknown parameter; ignore if parameter with invalid or missing value.
  186. negotiate_params(_, _, _) ->
  187. ignore.
  188. parse_max_window_bits(<<"8">>) -> 8;
  189. parse_max_window_bits(<<"9">>) -> 9;
  190. parse_max_window_bits(<<"10">>) -> 10;
  191. parse_max_window_bits(<<"11">>) -> 11;
  192. parse_max_window_bits(<<"12">>) -> 12;
  193. parse_max_window_bits(<<"13">>) -> 13;
  194. parse_max_window_bits(<<"14">>) -> 14;
  195. parse_max_window_bits(<<"15">>) -> 15;
  196. parse_max_window_bits(_) -> error.
  197. %% A negative WindowBits value indicates that zlib headers are not used.
  198. init_permessage_deflate(InflateWindowBits, DeflateWindowBits, Opts) ->
  199. Inflate = zlib:open(),
  200. ok = zlib:inflateInit(Inflate, -InflateWindowBits),
  201. Deflate = zlib:open(),
  202. %% zlib 1.2.11+ now rejects -8. It used to transform it to -9.
  203. %% We need to use 9 when 8 is requested for interoperability.
  204. DeflateWindowBits2 = case DeflateWindowBits of
  205. 8 -> 9;
  206. _ -> DeflateWindowBits
  207. end,
  208. ok = zlib:deflateInit(Deflate,
  209. maps:get(level, Opts, best_compression),
  210. deflated,
  211. -DeflateWindowBits2,
  212. maps:get(mem_level, Opts, 8),
  213. maps:get(strategy, Opts, default)),
  214. %% Set the owner pid of the zlib contexts if requested.
  215. case Opts of
  216. #{owner := Pid} -> set_owner(Pid, Inflate, Deflate);
  217. _ -> ok
  218. end,
  219. {Inflate, Deflate}.
  220. -ifdef(OTP_RELEASE).
  221. %% Using is_port/1 on a zlib context results in a Dialyzer warning in OTP 21.
  222. %% This function helps silence that warning while staying compatible
  223. %% with all supported versions.
  224. set_owner(Pid, Inflate, Deflate) ->
  225. zlib:set_controlling_process(Inflate, Pid),
  226. zlib:set_controlling_process(Deflate, Pid).
  227. -else.
  228. %% The zlib port became a reference in OTP 20.1+. There
  229. %% was however no way to change the controlling process
  230. %% until the OTP 20.1.3 patch version. Since we can't
  231. %% enable compression for 20.1, 20.1.1 and 20.1.2 we
  232. %% explicitly crash. The caller should ignore this extension.
  233. set_owner(Pid, Inflate, Deflate) when is_port(Inflate) ->
  234. true = erlang:port_connect(Inflate, Pid),
  235. true = unlink(Inflate),
  236. true = erlang:port_connect(Deflate, Pid),
  237. true = unlink(Deflate),
  238. ok;
  239. set_owner(Pid, Inflate, Deflate) ->
  240. case erlang:function_exported(zlib, set_controlling_process, 2) of
  241. true ->
  242. zlib:set_controlling_process(Inflate, Pid),
  243. zlib:set_controlling_process(Deflate, Pid);
  244. false ->
  245. exit({error, incompatible_zlib_version,
  246. 'OTP 20.1, 20.1.1 and 20.1.2 are missing required functionality.'})
  247. end.
  248. -endif.
  249. %% @doc Negotiate the x-webkit-deflate-frame extension.
  250. %%
  251. %% The implementation is very basic and none of the parameters
  252. %% are currently supported.
  253. -spec negotiate_x_webkit_deflate_frame(
  254. [binary() | {binary(), binary()}], Exts, deflate_opts())
  255. -> ignore | {ok, binary(), Exts} when Exts::extensions().
  256. negotiate_x_webkit_deflate_frame(_, #{deflate := _}, _) ->
  257. ignore;
  258. negotiate_x_webkit_deflate_frame(_Params, Extensions, Opts) ->
  259. % Since we are negotiating an unconstrained deflate-frame
  260. % then we must be willing to accept frames using the
  261. % maximum window size which is 2^15.
  262. {Inflate, Deflate} = init_permessage_deflate(15, 15, Opts),
  263. {ok, <<"x-webkit-deflate-frame">>,
  264. Extensions#{
  265. deflate => Deflate,
  266. deflate_takeover => takeover,
  267. inflate => Inflate,
  268. inflate_takeover => takeover}}.
  269. %% @doc Validate the negotiated permessage-deflate extension.
  270. %% Error when more than one deflate extension was negotiated.
  271. validate_permessage_deflate(_, #{deflate := _}, _) ->
  272. error;
  273. validate_permessage_deflate(Params, Extensions, Opts) ->
  274. case lists:usort(Params) of
  275. %% Error if multiple parameters with the same name.
  276. Params2 when length(Params) =/= length(Params2) ->
  277. error;
  278. Params2 ->
  279. case parse_response_permessage_deflate_params(Params2, 15, takeover, 15, takeover) of
  280. error ->
  281. error;
  282. {ClientWindowBits, ClientTakeOver, ServerWindowBits, ServerTakeOver} ->
  283. {Inflate, Deflate} = init_permessage_deflate(ServerWindowBits, ClientWindowBits, Opts),
  284. {ok, Extensions#{
  285. deflate => Deflate,
  286. deflate_takeover => ClientTakeOver,
  287. inflate => Inflate,
  288. inflate_takeover => ServerTakeOver}}
  289. end
  290. end.
  291. parse_response_permessage_deflate_params([], CB, CTO, SB, STO) ->
  292. {CB, CTO, SB, STO};
  293. parse_response_permessage_deflate_params([{<<"client_max_window_bits">>, Max}|Tail], _, CTO, SB, STO) ->
  294. case parse_max_window_bits(Max) of
  295. error -> error;
  296. CB -> parse_response_permessage_deflate_params(Tail, CB, CTO, SB, STO)
  297. end;
  298. parse_response_permessage_deflate_params([<<"client_no_context_takeover">>|Tail], CB, _, SB, STO) ->
  299. parse_response_permessage_deflate_params(Tail, CB, no_takeover, SB, STO);
  300. parse_response_permessage_deflate_params([{<<"server_max_window_bits">>, Max}|Tail], CB, CTO, _, STO) ->
  301. case parse_max_window_bits(Max) of
  302. error -> error;
  303. SB -> parse_response_permessage_deflate_params(Tail, CB, CTO, SB, STO)
  304. end;
  305. parse_response_permessage_deflate_params([<<"server_no_context_takeover">>|Tail], CB, CTO, SB, _) ->
  306. parse_response_permessage_deflate_params(Tail, CB, CTO, SB, no_takeover);
  307. %% Error if unknown parameter; error if parameter with invalid or missing value.
  308. parse_response_permessage_deflate_params(_, _, _, _, _) ->
  309. error.
  310. %% @doc Parse and validate the Websocket frame header.
  311. %%
  312. %% This function also updates the fragmentation state according to
  313. %% information found in the frame's header.
  314. -spec parse_header(binary(), extensions(), frag_state())
  315. -> error | more | {frame_type(), frag_state(), rsv(), non_neg_integer(), mask_key(), binary()}.
  316. %% RSV bits MUST be 0 unless an extension is negotiated
  317. %% that defines meanings for non-zero values.
  318. parse_header(<< _:1, Rsv:3, _/bits >>, Extensions, _) when Extensions =:= #{}, Rsv =/= 0 -> error;
  319. %% Last 2 RSV bits MUST be 0 if deflate-frame extension is used.
  320. parse_header(<< _:2, 1:1, _/bits >>, #{deflate := _}, _) -> error;
  321. parse_header(<< _:3, 1:1, _/bits >>, #{deflate := _}, _) -> error;
  322. %% Invalid opcode. Note that these opcodes may be used by extensions.
  323. parse_header(<< _:4, 3:4, _/bits >>, _, _) -> error;
  324. parse_header(<< _:4, 4:4, _/bits >>, _, _) -> error;
  325. parse_header(<< _:4, 5:4, _/bits >>, _, _) -> error;
  326. parse_header(<< _:4, 6:4, _/bits >>, _, _) -> error;
  327. parse_header(<< _:4, 7:4, _/bits >>, _, _) -> error;
  328. parse_header(<< _:4, 11:4, _/bits >>, _, _) -> error;
  329. parse_header(<< _:4, 12:4, _/bits >>, _, _) -> error;
  330. parse_header(<< _:4, 13:4, _/bits >>, _, _) -> error;
  331. parse_header(<< _:4, 14:4, _/bits >>, _, _) -> error;
  332. parse_header(<< _:4, 15:4, _/bits >>, _, _) -> error;
  333. %% Control frames MUST NOT be fragmented.
  334. parse_header(<< 0:1, _:3, Opcode:4, _/bits >>, _, _) when Opcode >= 8 -> error;
  335. %% A frame MUST NOT use the zero opcode unless fragmentation was initiated.
  336. parse_header(<< _:4, 0:4, _/bits >>, _, undefined) -> error;
  337. %% Non-control opcode when expecting control message or next fragment.
  338. parse_header(<< _:4, 1:4, _/bits >>, _, {_, _, _}) -> error;
  339. parse_header(<< _:4, 2:4, _/bits >>, _, {_, _, _}) -> error;
  340. parse_header(<< _:4, 3:4, _/bits >>, _, {_, _, _}) -> error;
  341. parse_header(<< _:4, 4:4, _/bits >>, _, {_, _, _}) -> error;
  342. parse_header(<< _:4, 5:4, _/bits >>, _, {_, _, _}) -> error;
  343. parse_header(<< _:4, 6:4, _/bits >>, _, {_, _, _}) -> error;
  344. parse_header(<< _:4, 7:4, _/bits >>, _, {_, _, _}) -> error;
  345. %% Close control frame length MUST be 0 or >= 2.
  346. parse_header(<< _:4, 8:4, _:1, 1:7, _/bits >>, _, _) -> error;
  347. %% Close control frame with incomplete close code. Need more data.
  348. parse_header(Data = << _:4, 8:4, 0:1, Len:7, _/bits >>, _, _) when Len > 1, byte_size(Data) < 4 -> more;
  349. parse_header(Data = << _:4, 8:4, 1:1, Len:7, _/bits >>, _, _) when Len > 1, byte_size(Data) < 8 -> more;
  350. %% 7 bits payload length.
  351. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 0:1, Len:7, Rest/bits >>, _, FragState) when Len < 126 ->
  352. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  353. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 1:1, Len:7, MaskKey:32, Rest/bits >>, _, FragState) when Len < 126 ->
  354. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  355. %% 16 bits payload length.
  356. parse_header(<< Fin:1, Rsv:3/bits, Opcode:4, 0:1, 126:7, Len:16, Rest/bits >>, _, FragState) when Len > 125, Opcode < 8 ->
  357. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  358. 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 ->
  359. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  360. %% 63 bits payload length.
  361. 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 ->
  362. parse_header(Opcode, Fin, FragState, Rsv, Len, undefined, Rest);
  363. 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 ->
  364. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest);
  365. %% When payload length is over 63 bits, the most significant bit MUST be 0.
  366. parse_header(<< _:9, 127:7, 1:1, _/bits >>, _, _) -> error;
  367. %% For the next two clauses, it can be one of the following:
  368. %%
  369. %% * The minimal number of bytes MUST be used to encode the length
  370. %% * All control frames MUST have a payload length of 125 bytes or less
  371. parse_header(<< _:8, 0:1, 126:7, _:16, _/bits >>, _, _) -> error;
  372. parse_header(<< _:8, 1:1, 126:7, _:48, _/bits >>, _, _) -> error;
  373. parse_header(<< _:8, 0:1, 127:7, _:64, _/bits >>, _, _) -> error;
  374. parse_header(<< _:8, 1:1, 127:7, _:96, _/bits >>, _, _) -> error;
  375. %% Need more data.
  376. parse_header(_, _, _) -> more.
  377. parse_header(Opcode, Fin, FragState, Rsv, Len, MaskKey, Rest) ->
  378. Type = opcode_to_frame_type(Opcode),
  379. Type2 = case Fin of
  380. 0 -> fragment;
  381. 1 -> Type
  382. end,
  383. {Type2, frag_state(Type, Fin, Rsv, FragState), Rsv, Len, MaskKey, Rest}.
  384. opcode_to_frame_type(0) -> fragment;
  385. opcode_to_frame_type(1) -> text;
  386. opcode_to_frame_type(2) -> binary;
  387. opcode_to_frame_type(8) -> close;
  388. opcode_to_frame_type(9) -> ping;
  389. opcode_to_frame_type(10) -> pong.
  390. frag_state(Type, 0, Rsv, undefined) -> {nofin, Type, Rsv};
  391. frag_state(fragment, 0, _, FragState = {nofin, _, _}) -> FragState;
  392. frag_state(fragment, 1, _, {nofin, Type, Rsv}) -> {fin, Type, Rsv};
  393. frag_state(_, 1, _, FragState) -> FragState.
  394. %% @doc Parse and validate the frame's payload.
  395. %%
  396. %% Validation is only required for text and close frames which feature
  397. %% a UTF-8 payload.
  398. -spec parse_payload(binary(), mask_key(), utf8_state(), non_neg_integer(),
  399. frame_type(), non_neg_integer(), frag_state(), extensions(), rsv())
  400. -> {ok, binary(), utf8_state(), binary()}
  401. | {ok, close_code(), binary(), utf8_state(), binary()}
  402. | {more, binary(), utf8_state()}
  403. | {more, close_code(), binary(), utf8_state()}
  404. | {error, badframe | badencoding}.
  405. %% Empty last frame of compressed message.
  406. parse_payload(Data, _, Utf8State, _, _, 0, {fin, _, << 1:1, 0:2 >>},
  407. #{inflate := Inflate, inflate_takeover := TakeOver}, _) ->
  408. _ = zlib:inflate(Inflate, << 0, 0, 255, 255 >>),
  409. case TakeOver of
  410. no_takeover -> zlib:inflateReset(Inflate);
  411. takeover -> ok
  412. end,
  413. {ok, <<>>, Utf8State, Data};
  414. %% Compressed fragmented frame.
  415. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState = {_, _, << 1:1, 0:2 >>},
  416. #{inflate := Inflate, inflate_takeover := TakeOver}, _) ->
  417. {Data2, Rest, Eof} = split_payload(Data, Len),
  418. Payload = inflate_frame(unmask(Data2, MaskKey, ParsedLen), Inflate, TakeOver, FragState, Eof),
  419. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof);
  420. %% Compressed frame.
  421. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState,
  422. #{inflate := Inflate, inflate_takeover := TakeOver}, << 1:1, 0:2 >>) when Type =:= text; Type =:= binary ->
  423. {Data2, Rest, Eof} = split_payload(Data, Len),
  424. Payload = inflate_frame(unmask(Data2, MaskKey, ParsedLen), Inflate, TakeOver, FragState, Eof),
  425. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof);
  426. %% Empty frame.
  427. parse_payload(Data, _, Utf8State, 0, _, 0, _, _, _)
  428. when Utf8State =:= 0; Utf8State =:= undefined ->
  429. {ok, <<>>, Utf8State, Data};
  430. %% Start of close frame.
  431. parse_payload(Data, MaskKey, Utf8State, 0, Type = close, Len, FragState, _, << 0:3 >>) ->
  432. {<< MaskedCode:2/binary, Data2/bits >>, Rest, Eof} = split_payload(Data, Len),
  433. << CloseCode:16 >> = unmask(MaskedCode, MaskKey, 0),
  434. case validate_close_code(CloseCode) of
  435. ok ->
  436. Payload = unmask(Data2, MaskKey, 2),
  437. case validate_payload(Payload, Rest, Utf8State, 2, Type, FragState, Eof) of
  438. {ok, _, Utf8State2, _} -> {ok, CloseCode, Payload, Utf8State2, Rest};
  439. {more, _, Utf8State2} -> {more, CloseCode, Payload, Utf8State2};
  440. Error -> Error
  441. end;
  442. error ->
  443. {error, badframe}
  444. end;
  445. %% Normal frame.
  446. parse_payload(Data, MaskKey, Utf8State, ParsedLen, Type, Len, FragState, _, << 0:3 >>) ->
  447. {Data2, Rest, Eof} = split_payload(Data, Len),
  448. Payload = unmask(Data2, MaskKey, ParsedLen),
  449. validate_payload(Payload, Rest, Utf8State, ParsedLen, Type, FragState, Eof).
  450. split_payload(Data, Len) ->
  451. case byte_size(Data) of
  452. Len ->
  453. {Data, <<>>, true};
  454. DataLen when DataLen < Len ->
  455. {Data, <<>>, false};
  456. _ ->
  457. << Data2:Len/binary, Rest/bits >> = Data,
  458. {Data2, Rest, true}
  459. end.
  460. validate_close_code(Code) ->
  461. if
  462. Code < 1000 -> error;
  463. Code =:= 1004 -> error;
  464. Code =:= 1005 -> error;
  465. Code =:= 1006 -> error;
  466. Code > 1011, Code < 3000 -> error;
  467. Code > 4999 -> error;
  468. true -> ok
  469. end.
  470. unmask(Data, undefined, _) ->
  471. Data;
  472. unmask(Data, MaskKey, 0) ->
  473. mask(Data, MaskKey, <<>>);
  474. %% We unmask on the fly so we need to continue from the right mask byte.
  475. unmask(Data, MaskKey, UnmaskedLen) ->
  476. Left = UnmaskedLen rem 4,
  477. Right = 4 - Left,
  478. MaskKey2 = (MaskKey bsl (Left * 8)) + (MaskKey bsr (Right * 8)),
  479. mask(Data, MaskKey2, <<>>).
  480. mask(<<>>, _, Unmasked) ->
  481. Unmasked;
  482. mask(<< O:32, Rest/bits >>, MaskKey, Acc) ->
  483. T = O bxor MaskKey,
  484. mask(Rest, MaskKey, << Acc/binary, T:32 >>);
  485. mask(<< O:24 >>, MaskKey, Acc) ->
  486. << MaskKey2:24, _:8 >> = << MaskKey:32 >>,
  487. T = O bxor MaskKey2,
  488. << Acc/binary, T:24 >>;
  489. mask(<< O:16 >>, MaskKey, Acc) ->
  490. << MaskKey2:16, _:16 >> = << MaskKey:32 >>,
  491. T = O bxor MaskKey2,
  492. << Acc/binary, T:16 >>;
  493. mask(<< O:8 >>, MaskKey, Acc) ->
  494. << MaskKey2:8, _:24 >> = << MaskKey:32 >>,
  495. T = O bxor MaskKey2,
  496. << Acc/binary, T:8 >>.
  497. inflate_frame(Data, Inflate, TakeOver, FragState, true)
  498. when FragState =:= undefined; element(1, FragState) =:= fin ->
  499. Data2 = zlib:inflate(Inflate, << Data/binary, 0, 0, 255, 255 >>),
  500. case TakeOver of
  501. no_takeover -> zlib:inflateReset(Inflate);
  502. takeover -> ok
  503. end,
  504. iolist_to_binary(Data2);
  505. inflate_frame(Data, Inflate, _T, _F, _E) ->
  506. iolist_to_binary(zlib:inflate(Inflate, Data)).
  507. %% The Utf8State variable can be set to 'undefined' to disable the validation.
  508. validate_payload(Payload, _, undefined, _, _, _, false) ->
  509. {more, Payload, undefined};
  510. validate_payload(Payload, Rest, undefined, _, _, _, true) ->
  511. {ok, Payload, undefined, Rest};
  512. %% Text frames and close control frames MUST have a payload that is valid UTF-8.
  513. validate_payload(Payload, Rest, Utf8State, _, Type, _, Eof) when Type =:= text; Type =:= close ->
  514. case validate_utf8(Payload, Utf8State) of
  515. 1 -> {error, badencoding};
  516. Utf8State2 when not Eof -> {more, Payload, Utf8State2};
  517. 0 when Eof -> {ok, Payload, 0, Rest};
  518. _ -> {error, badencoding}
  519. end;
  520. validate_payload(Payload, Rest, Utf8State, _, fragment, {Fin, text, _}, Eof) ->
  521. case validate_utf8(Payload, Utf8State) of
  522. 1 -> {error, badencoding};
  523. 0 when Eof -> {ok, Payload, 0, Rest};
  524. Utf8State2 when Eof, Fin =:= nofin -> {ok, Payload, Utf8State2, Rest};
  525. Utf8State2 when not Eof -> {more, Payload, Utf8State2};
  526. _ -> {error, badencoding}
  527. end;
  528. validate_payload(Payload, _, Utf8State, _, _, _, false) ->
  529. {more, Payload, Utf8State};
  530. validate_payload(Payload, Rest, Utf8State, _, _, _, true) ->
  531. {ok, Payload, Utf8State, Rest}.
  532. %% Based on the Flexible and Economical UTF-8 Decoder algorithm by
  533. %% Bjoern Hoehrmann <bjoern@hoehrmann.de> (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/).
  534. %%
  535. %% The original algorithm has been unrolled into all combinations of values for C and State
  536. %% each with a clause. The common clauses were then grouped together.
  537. %%
  538. %% This function returns 0 on success, 1 on error, and 2..8 on incomplete data.
  539. validate_utf8(<<>>, State) -> State;
  540. validate_utf8(<< C, Rest/bits >>, 0) when C < 128 -> validate_utf8(Rest, 0);
  541. validate_utf8(<< C, Rest/bits >>, 2) when C >= 128, C < 144 -> validate_utf8(Rest, 0);
  542. validate_utf8(<< C, Rest/bits >>, 3) when C >= 128, C < 144 -> validate_utf8(Rest, 2);
  543. validate_utf8(<< C, Rest/bits >>, 5) when C >= 128, C < 144 -> validate_utf8(Rest, 2);
  544. validate_utf8(<< C, Rest/bits >>, 7) when C >= 128, C < 144 -> validate_utf8(Rest, 3);
  545. validate_utf8(<< C, Rest/bits >>, 8) when C >= 128, C < 144 -> validate_utf8(Rest, 3);
  546. validate_utf8(<< C, Rest/bits >>, 2) when C >= 144, C < 160 -> validate_utf8(Rest, 0);
  547. validate_utf8(<< C, Rest/bits >>, 3) when C >= 144, C < 160 -> validate_utf8(Rest, 2);
  548. validate_utf8(<< C, Rest/bits >>, 5) when C >= 144, C < 160 -> validate_utf8(Rest, 2);
  549. validate_utf8(<< C, Rest/bits >>, 6) when C >= 144, C < 160 -> validate_utf8(Rest, 3);
  550. validate_utf8(<< C, Rest/bits >>, 7) when C >= 144, C < 160 -> validate_utf8(Rest, 3);
  551. validate_utf8(<< C, Rest/bits >>, 2) when C >= 160, C < 192 -> validate_utf8(Rest, 0);
  552. validate_utf8(<< C, Rest/bits >>, 3) when C >= 160, C < 192 -> validate_utf8(Rest, 2);
  553. validate_utf8(<< C, Rest/bits >>, 4) when C >= 160, C < 192 -> validate_utf8(Rest, 2);
  554. validate_utf8(<< C, Rest/bits >>, 6) when C >= 160, C < 192 -> validate_utf8(Rest, 3);
  555. validate_utf8(<< C, Rest/bits >>, 7) when C >= 160, C < 192 -> validate_utf8(Rest, 3);
  556. validate_utf8(<< C, Rest/bits >>, 0) when C >= 194, C < 224 -> validate_utf8(Rest, 2);
  557. validate_utf8(<< 224, Rest/bits >>, 0) -> validate_utf8(Rest, 4);
  558. validate_utf8(<< C, Rest/bits >>, 0) when C >= 225, C < 237 -> validate_utf8(Rest, 3);
  559. validate_utf8(<< 237, Rest/bits >>, 0) -> validate_utf8(Rest, 5);
  560. validate_utf8(<< C, Rest/bits >>, 0) when C =:= 238; C =:= 239 -> validate_utf8(Rest, 3);
  561. validate_utf8(<< 240, Rest/bits >>, 0) -> validate_utf8(Rest, 6);
  562. validate_utf8(<< C, Rest/bits >>, 0) when C =:= 241; C =:= 242; C =:= 243 -> validate_utf8(Rest, 7);
  563. validate_utf8(<< 244, Rest/bits >>, 0) -> validate_utf8(Rest, 8);
  564. validate_utf8(_, _) -> 1.
  565. %% @doc Return a frame tuple from parsed state and data.
  566. -spec make_frame(frame_type(), binary(), close_code(), frag_state()) -> frame().
  567. %% Fragmented frame.
  568. make_frame(fragment, Payload, _, {Fin, Type, _}) -> {fragment, Fin, Type, Payload};
  569. make_frame(text, Payload, _, _) -> {text, Payload};
  570. make_frame(binary, Payload, _, _) -> {binary, Payload};
  571. make_frame(close, <<>>, undefined, _) -> close;
  572. make_frame(close, Payload, CloseCode, _) -> {close, CloseCode, Payload};
  573. make_frame(ping, <<>>, _, _) -> ping;
  574. make_frame(ping, Payload, _, _) -> {ping, Payload};
  575. make_frame(pong, <<>>, _, _) -> pong;
  576. make_frame(pong, Payload, _, _) -> {pong, Payload}.
  577. %% @doc Construct an unmasked Websocket frame.
  578. -spec frame(frame(), extensions()) -> iodata().
  579. %% Control frames. Control packets must not be > 125 in length.
  580. frame(close, _) ->
  581. << 1:1, 0:3, 8:4, 0:8 >>;
  582. frame(ping, _) ->
  583. << 1:1, 0:3, 9:4, 0:8 >>;
  584. frame(pong, _) ->
  585. << 1:1, 0:3, 10:4, 0:8 >>;
  586. frame({close, Payload}, Extensions) ->
  587. frame({close, 1000, Payload}, Extensions);
  588. frame({close, StatusCode, Payload}, _) ->
  589. Len = 2 + iolist_size(Payload),
  590. true = Len =< 125,
  591. [<< 1:1, 0:3, 8:4, 0:1, Len:7, StatusCode:16 >>, Payload];
  592. frame({ping, Payload}, _) ->
  593. Len = iolist_size(Payload),
  594. true = Len =< 125,
  595. [<< 1:1, 0:3, 9:4, 0:1, Len:7 >>, Payload];
  596. frame({pong, Payload}, _) ->
  597. Len = iolist_size(Payload),
  598. true = Len =< 125,
  599. [<< 1:1, 0:3, 10:4, 0:1, Len:7 >>, Payload];
  600. %% Data frames, deflate-frame extension.
  601. frame({text, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver})
  602. when Deflate =/= false ->
  603. Payload2 = deflate_frame(Payload, Deflate, TakeOver),
  604. Len = payload_length(Payload2),
  605. [<< 1:1, 1:1, 0:2, 1:4, 0:1, Len/bits >>, Payload2];
  606. frame({binary, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver})
  607. when Deflate =/= false ->
  608. Payload2 = deflate_frame(Payload, Deflate, TakeOver),
  609. Len = payload_length(Payload2),
  610. [<< 1:1, 1:1, 0:2, 2:4, 0:1, Len/bits >>, Payload2];
  611. %% Data frames.
  612. frame({text, Payload}, _) ->
  613. Len = payload_length(Payload),
  614. [<< 1:1, 0:3, 1:4, 0:1, Len/bits >>, Payload];
  615. frame({binary, Payload}, _) ->
  616. Len = payload_length(Payload),
  617. [<< 1:1, 0:3, 2:4, 0:1, Len/bits >>, Payload].
  618. %% @doc Construct a masked Websocket frame.
  619. %%
  620. %% We use a mask key of 0 if there is no payload for close, ping and pong frames.
  621. -spec masked_frame(frame(), extensions()) -> iodata().
  622. %% Control frames. Control packets must not be > 125 in length.
  623. masked_frame(close, _) ->
  624. << 1:1, 0:3, 8:4, 1:1, 0:39 >>;
  625. masked_frame(ping, _) ->
  626. << 1:1, 0:3, 9:4, 1:1, 0:39 >>;
  627. masked_frame(pong, _) ->
  628. << 1:1, 0:3, 10:4, 1:1, 0:39 >>;
  629. masked_frame({close, Payload}, Extensions) ->
  630. frame({close, 1000, Payload}, Extensions);
  631. masked_frame({close, StatusCode, Payload}, _) ->
  632. Len = 2 + iolist_size(Payload),
  633. true = Len =< 125,
  634. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  635. [<< 1:1, 0:3, 8:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary([<< StatusCode:16 >>, Payload]), MaskKey, <<>>)];
  636. masked_frame({ping, Payload}, _) ->
  637. Len = iolist_size(Payload),
  638. true = Len =< 125,
  639. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  640. [<< 1:1, 0:3, 9:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  641. masked_frame({pong, Payload}, _) ->
  642. Len = iolist_size(Payload),
  643. true = Len =< 125,
  644. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  645. [<< 1:1, 0:3, 10:4, 1:1, Len:7 >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  646. %% Data frames, deflate-frame extension.
  647. masked_frame({text, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver})
  648. when Deflate =/= false ->
  649. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  650. Payload2 = mask(deflate_frame(Payload, Deflate, TakeOver), MaskKey, <<>>),
  651. Len = payload_length(Payload2),
  652. [<< 1:1, 1:1, 0:2, 1:4, 1:1, Len/bits >>, MaskKeyBin, Payload2];
  653. masked_frame({binary, Payload}, #{deflate := Deflate, deflate_takeover := TakeOver})
  654. when Deflate =/= false ->
  655. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  656. Payload2 = mask(deflate_frame(Payload, Deflate, TakeOver), MaskKey, <<>>),
  657. Len = payload_length(Payload2),
  658. [<< 1:1, 1:1, 0:2, 2:4, 1:1, Len/bits >>, MaskKeyBin, Payload2];
  659. %% Data frames.
  660. masked_frame({text, Payload}, _) ->
  661. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  662. Len = payload_length(Payload),
  663. [<< 1:1, 0:3, 1:4, 1:1, Len/bits >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)];
  664. masked_frame({binary, Payload}, _) ->
  665. MaskKeyBin = << MaskKey:32 >> = crypto:strong_rand_bytes(4),
  666. Len = payload_length(Payload),
  667. [<< 1:1, 0:3, 2:4, 1:1, Len/bits >>, MaskKeyBin, mask(iolist_to_binary(Payload), MaskKey, <<>>)].
  668. payload_length(Payload) ->
  669. case iolist_size(Payload) of
  670. N when N =< 125 -> << N:7 >>;
  671. N when N =< 16#ffff -> << 126:7, N:16 >>;
  672. N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >>
  673. end.
  674. deflate_frame(Payload, Deflate, TakeOver) ->
  675. Deflated = iolist_to_binary(zlib:deflate(Deflate, Payload, sync)),
  676. case TakeOver of
  677. no_takeover -> zlib:deflateReset(Deflate);
  678. takeover -> ok
  679. end,
  680. Len = byte_size(Deflated) - 4,
  681. case Deflated of
  682. << Body:Len/binary, 0:8, 0:8, 255:8, 255:8 >> -> Body;
  683. _ -> Deflated
  684. end.