@@ -53,13 +53,32 @@ proc pp_handshake*(fd: SocketHandle, sa: ptr SockAddr, sl: ptr Socklen): int =
53
53
hdr: Header
54
54
src: Sockaddr_in
55
55
src6: Sockaddr_in6
56
+ tv: Timeval
57
+ tv_size = sizeof (tv).SockLen
58
+ reset_tv = false
59
+ flags = fcntl (fd, F_GETFL , 0 )
60
+
61
+ # make sure fd is blocking
62
+ if (flags and O_NONBLOCK ) == 0 :
63
+ # get recv timeout, and set it if not set
64
+ if getsockopt (fd, SOL_SOCKET , SO_RCVTIMEO , addr tv, addr tv_size) >= 0 and tv.tv_sec.int == 0 and tv.tv_usec == 0 :
65
+ reset_tv = true
66
+ tv.tv_usec = 500
67
+ discard setsockopt (fd, SOL_SOCKET , SO_RCVTIMEO , addr tv, tv_size)
56
68
57
69
while true :
58
- result = recv (fd, addr hdr, sizeof (hdr), 0 )
70
+ result = recv (fd, addr hdr, sizeof (hdr), MSG_PEEK )
59
71
if not (result == - 1 and errno == EINTR ):
60
72
break
73
+
61
74
if result == - 1 :
62
- return if (errno == EAGAIN ): 0 else : - 1
75
+ return if (errno == EAGAIN or errno == EWOULDBLOCK ): 0 else : - 1
76
+
77
+ # reset recv timeout
78
+ if reset_tv:
79
+ tv.tv_sec = 0 .Time
80
+ tv.tv_usec = 0
81
+ discard setsockopt (fd, SOL_SOCKET , SO_RCVTIMEO , addr tv, tv_size)
63
82
64
83
if result >= 16 and hdr.v2.sig == v2sig and (hdr.v2.ver_cmd and 0x F0 ) == 0x 20 and result >= 16 + ntohs (hdr.v2.length).int :
65
84
case hdr.v2.ver_cmd and 0x F
@@ -145,22 +164,28 @@ proc pp_handshake*(fd: SocketHandle, sa: ptr SockAddr, sl: ptr Socklen): int =
145
164
else : # Wrong protocol
146
165
return - 1
147
166
167
+ while true :
168
+ result = recv (fd, addr hdr, result , 0 )
169
+ if not (result == - 1 and errno == EINTR ):
170
+ break
171
+
148
172
when isMainModule :
149
- type AcceptProc = proc (a1: SocketHandle , a2: ptr SockAddr , a3: ptr Socklen ): SocketHandle {.cdecl .}
150
173
var
151
174
RTLD_NEXT {.importc : " RTLD_NEXT" , header : " <dlfcn.h>" .}: LibHandle
152
- real_accept: AcceptProc
175
+ sys_accept: proc (a1: SocketHandle , a2: ptr SockAddr , a3: ptr Socklen ): SocketHandle {. cdecl .}
153
176
154
177
proc pp_accept * (a1: SocketHandle , a2: ptr SockAddr , a3: ptr Socklen ): SocketHandle {.exportc :" accept" ,cdecl .} =
155
- result = real_accept (a1, a2, a3)
178
+ result = sys_accept (a1, a2, a3)
156
179
if result .int != - 1 :
157
180
if pp_handshake (result , a2, a3) <= 0 :
158
181
echo " [PROXY] connection 0x" , $ result .int , " invalid proxy-protocol header"
182
+ discard close (result )
183
+ errno = ECONNABORTED
159
184
result = SocketHandle (- 1 )
160
185
161
186
let accept_ptr = symAddr (RTLD_NEXT , " accept" )
162
187
if accept_ptr == nil :
163
188
quit " [PROXY] cannot find accept proc"
164
189
165
- real_accept = cast [AcceptProc ](accept_ptr)
190
+ sys_accept = cast [sys_accept. type ](accept_ptr)
166
191
echo " [PROXY] hook accept OK"
0 commit comments