Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

108 rader
4.2 KiB

3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
3 år sedan
  1. %% Copyright (c) 2011-2017, 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(cowboy_loop).
  15. -behaviour(cowboy_sub_protocol).
  16. -export([upgrade/4]).
  17. -export([upgrade/5]).
  18. -export([loop/4]).
  19. -export([system_continue/3]).
  20. -export([system_terminate/4]).
  21. -export([system_code_change/4]).
  22. -callback init(Req, any())
  23. -> {ok | module(), Req, any()}
  24. | {module(), Req, any(), any()}
  25. when Req :: cowboy_req:req().
  26. -callback info(any(), Req, State)
  27. -> {ok, Req, State}
  28. | {ok, Req, State, hibernate}
  29. | {stop, Req, State}
  30. when Req :: cowboy_req:req(), State :: any().
  31. -callback terminate(any(), cowboy_req:req(), any()) -> ok.
  32. -optional_callbacks([terminate/3]).
  33. -spec upgrade(Req, Env, module(), any())
  34. -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
  35. when Req :: cowboy_req:req(), Env :: cowboy_middleware:env().
  36. upgrade(Req, Env, Handler, HandlerState) ->
  37. loop(Req, Env, Handler, HandlerState).
  38. -spec upgrade(Req, Env, module(), any(), hibernate)
  39. -> {suspend, ?MODULE, loop, [any()]}
  40. when Req :: cowboy_req:req(), Env :: cowboy_middleware:env().
  41. upgrade(Req, Env, Handler, HandlerState, hibernate) ->
  42. suspend(Req, Env, Handler, HandlerState).
  43. -spec loop(Req, Env, module(), any())
  44. -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
  45. when Req :: cowboy_req:req(), Env :: cowboy_middleware:env().
  46. %% @todo Handle system messages.
  47. loop(Req = #{pid := Parent}, Env, Handler, HandlerState) ->
  48. receive
  49. %% System messages.
  50. {'EXIT', Parent, Reason} ->
  51. terminate(Req, Env, Handler, HandlerState, Reason);
  52. {system, From, Request} ->
  53. sys:handle_system_msg(Request, From, Parent, ?MODULE, [],
  54. {Req, Env, Handler, HandlerState});
  55. %% Calls from supervisor module.
  56. {'$gen_call', From, Call} ->
  57. cowboy_children:handle_supervisor_call(Call, From, [], ?MODULE),
  58. loop(Req, Env, Handler, HandlerState);
  59. Message ->
  60. call(Req, Env, Handler, HandlerState, Message)
  61. end.
  62. call(Req0, Env, Handler, HandlerState0, Message) ->
  63. try Handler:info(Message, Req0, HandlerState0) of
  64. {ok, Req, HandlerState} ->
  65. loop(Req, Env, Handler, HandlerState);
  66. {ok, Req, HandlerState, hibernate} ->
  67. suspend(Req, Env, Handler, HandlerState);
  68. {stop, Req, HandlerState} ->
  69. terminate(Req, Env, Handler, HandlerState, stop)
  70. catch Class:Reason:Stacktrace ->
  71. cowboy_handler:terminate({crash, Class, Reason}, Req0, HandlerState0, Handler),
  72. erlang:raise(Class, Reason, Stacktrace)
  73. end.
  74. suspend(Req, Env, Handler, HandlerState) ->
  75. {suspend, ?MODULE, loop, [Req, Env, Handler, HandlerState]}.
  76. terminate(Req, Env, Handler, HandlerState, Reason) ->
  77. Result = cowboy_handler:terminate(Reason, Req, HandlerState, Handler),
  78. {ok, Req, Env#{result => Result}}.
  79. %% System callbacks.
  80. -spec system_continue(_, _, {Req, Env, module(), any()})
  81. -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
  82. when Req :: cowboy_req:req(), Env :: cowboy_middleware:env().
  83. system_continue(_, _, {Req, Env, Handler, HandlerState}) ->
  84. loop(Req, Env, Handler, HandlerState).
  85. -spec system_terminate(any(), _, _, {Req, Env, module(), any()})
  86. -> {ok, Req, Env} when Req :: cowboy_req:req(), Env :: cowboy_middleware:env().
  87. system_terminate(Reason, _, _, {Req, Env, Handler, HandlerState}) ->
  88. terminate(Req, Env, Handler, HandlerState, Reason).
  89. -spec system_code_change(Misc, _, _, _) -> {ok, Misc}
  90. when Misc :: {cowboy_req:req(), cowboy_middleware:env(), module(), any()}.
  91. system_code_change(Misc, _, _, _) ->
  92. {ok, Misc}.