forked from sanmiguel/websocket_client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathws_client.erl
120 lines (97 loc) · 3.02 KB
/
ws_client.erl
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
-module(ws_client).
-behaviour(websocket_client).
-export([
start_link/0,
start_link/1,
start_link/2,
socket/1,
socket/2,
send_text/2,
send_binary/2,
send_ping/2,
sync_send_text/2,
sync_send_binary/2,
sync_send_ping/2,
recv/2,
recv/1,
stop/1
]).
-export([
init/1,
onconnect/2,
ondisconnect/2,
websocket_handle/3,
websocket_info/3,
websocket_terminate/3
]).
-record(state, {
buffer = [] :: list(),
waiting = undefined :: undefined | pid()
}).
start_link() ->
{ok, _} = start_link("ws://localhost:8080").
start_link(Url) ->
{ok, _} = websocket_client:start_link(Url, ?MODULE, [self()]).
start_link(Url, KeepAlive) ->
{ok, _} = websocket_client:start_link(Url, ?MODULE, [self()], [{keepalive, KeepAlive}]).
stop(Pid) ->
Pid ! stop.
socket(Pid) ->
socket(Pid, 5000).
socket(Pid, Timeout) ->
Pid ! {gimme_socket, self()},
receive
{hav_socket, Pid, Sock} -> {ok, Sock}
after Timeout ->
{error, timeout}
end.
send_text(Pid, Msg) ->
websocket_client:cast(Pid, {text, Msg}).
send_binary(Pid, Msg) ->
websocket_client:cast(Pid, {binary, Msg}).
send_ping(Pid, Msg) ->
websocket_client:cast(Pid, {ping, Msg}).
sync_send_text(Pid, Msg) ->
websocket_client:send(Pid, {text, Msg}).
sync_send_binary(Pid, Msg) ->
websocket_client:send(Pid, {binary, Msg}).
sync_send_ping(Pid, Msg) ->
websocket_client:send(Pid, {ping, Msg}).
recv(Pid) ->
recv(Pid, 5000).
recv(Pid, Timeout) ->
Pid ! {recv, self()},
receive
M -> M
after
Timeout -> error
end.
init([Waiting]) ->
{reconnect, #state{waiting=Waiting}}.
onconnect(_WSReq, State) ->
State#state.waiting ! {ok, self()},
{ok, State}.
ondisconnect(Reason, State) ->
{close, Reason, State}.
websocket_handle({Type, Payload}=Frame, _, State = #state{waiting = undefined, buffer = Buffer}) ->
ct:pal("Client added ~p to buffer of size ~p~n", [Type, byte_size(Payload)]),
{ok, State#state{buffer = Buffer++[Frame]}};
websocket_handle({Type,Payload}=Frame, _, State = #state{waiting = From}) ->
ct:pal("Client forwarded ~p of size ~p to ~p ~n", [Type, byte_size(Payload), From]),
From ! Frame,
{ok, State#state{waiting = undefined}}.
websocket_info({recv, From}, _, State = #state{buffer = []}) ->
{ok, State#state{waiting = From}};
websocket_info({recv, From}, _, State = #state{buffer = [Top|Rest]}) ->
ct:pal("Sending buffer hd to: ~p {Buffer: ~p}~n", [From, [Top|Rest]]),
From ! Top,
{ok, State#state{buffer = Rest}};
websocket_info({gimme_socket, Whom}, WSReq, State) ->
Sock = websocket_req:socket(WSReq),
Whom ! {hav_socket, self(), Sock},
{ok, State};
websocket_info(stop, _, State) ->
{close, <<>>, State}.
websocket_terminate(Close, _, State) ->
ct:pal("Websocket closed with frame ~p and state ~p", [Close, State]),
ok.