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
| | # -*- encoding: binary -*-
# :enddoc:
#
# Revactor Sockets do not implement readpartial, so we emulate just
# enough to avoid mucking with TeeInput internals. Fortunately
# this code is not heavily used so we can usually avoid the overhead
# of adding a userspace buffer.
class Rainbows::Revactor::Client::TeeSocket
def initialize(socket)
# IO::Buffer is used internally by Rev which Revactor is based on
# so we'll always have it available
@socket, @rbuf = socket, IO::Buffer.new
end
def leftover
@rbuf.read
end
# Revactor socket reads always return an unspecified amount,
# sometimes too much
def kgio_read(length, dst = "")
return dst.replace("") if length == 0
# always check and return from the userspace buffer first
@rbuf.size > 0 and return dst.replace(@rbuf.read(length))
# read off the socket since there was nothing in rbuf
tmp = @socket.read
# we didn't read too much, good, just return it straight back
# to avoid needlessly wasting memory bandwidth
tmp.size <= length and return dst.replace(tmp)
# ugh, read returned too much
@rbuf << tmp[length, tmp.size]
dst.replace(tmp[0, length])
rescue EOFError
end
# just proxy any remaining methods TeeInput may use
def close
@socket.close
end
end
|