/
socket.rb
124 lines (102 loc) · 2.76 KB
/
socket.rb
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
121
122
123
124
# backtick_javascript: true
module Browser
# A {Socket} allows the browser and a server to have a bidirectional data
# connection.
#
# @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
class Socket < IO
def self.supported?
Browser.supports? :WebSocket
end
include Native::Wrapper
include IO::Writable if defined? IO::Writable
include Event::Target
target {|value|
Socket.new(value) if Native.is_a?(value, `window.WebSocket`)
}
# Create a connection to the given URL, optionally using the given protocol.
#
# @param url [String] the URL to connect to
# @param protocol [String] the protocol to use
#
# @yield if the block has no parameters it's `instance_exec`d, otherwise it's
# called with `self`
def initialize(url, protocol = nil, &block)
if native?(url)
super(url)
elsif protocol
super(`new window.WebSocket(#{url.to_s}, #{protocol.to_n})`)
else
super(`new window.WebSocket(#{url.to_s})`)
end
if block.arity == 0
instance_exec(&block)
else
block.call(self)
end if block
end
# @!attribute [r] protocol
# @return [String] the protocol of the socket
alias_native :protocol
# @!attribute [r] url
# @return [String] the URL the socket is connected to
alias_native :url
# @!attribute [r] buffered
# @return [Integer] the amount of buffered data.
alias_native :buffered, :bufferedAmount
# @!attribute [r] type
# @return [:blob, :buffer, :string] the type of the socket
def type
%x{
switch (#@native.binaryType) {
case "blob":
return "blob";
case "arraybuffer":
return "buffer";
default:
return "string";
}
}
end
# @!attribute [r] state
# @return [:connecting, :open, :closing, :closed] the state of the socket
def state
%x{
switch (#@native.readyState) {
case window.WebSocket.CONNECTING:
return "connecting";
case window.WebSocket.OPEN:
return "open";
case window.WebSocket.CLOSING:
return "closing";
case window.WebSocket.CLOSED:
return "closed";
}
}
end
# @!attribute [r] extensions
# @return [Array<String>] the extensions used by the socket
def extensions
`#@native.extensions`.split(/\s*,\s*/)
end
# Check if the socket is alive.
def alive?
state == :open
end
# Send data to the socket.
#
# @param data [#to_n] the data to send
def write(data)
`#@native.send(#{data.to_n})`
end
alias << write
alias send write
# Close the socket.
#
# @param code [Integer, nil] the error code
# @param reason [String, nil] the reason for closing
def close(code = nil, reason = nil)
`#@native.close(#{code.to_n}, #{reason.to_n})`
end
end
end