Revision d7fa9982 lib/http/__init__.py
b/lib/http/__init__.py | ||
---|---|---|
67 | 67 |
# Socket operations |
68 | 68 |
(SOCKOP_SEND, |
69 | 69 |
SOCKOP_RECV, |
70 |
SOCKOP_SHUTDOWN) = range(3) |
|
70 |
SOCKOP_SHUTDOWN, |
|
71 |
SOCKOP_HANDSHAKE) = range(4) |
|
71 | 72 |
|
72 | 73 |
# send/receive quantum |
73 | 74 |
SOCK_BUF_SIZE = 32768 |
... | ... | |
90 | 91 |
""" |
91 | 92 |
|
92 | 93 |
|
94 |
class HttpSessionHandshakeUnexpectedEOF(HttpError): |
|
95 |
"""Internal exception for errors during SSL handshake. |
|
96 |
|
|
97 |
This should only be used for internal error reporting. |
|
98 |
|
|
99 |
""" |
|
100 |
|
|
101 |
|
|
93 | 102 |
class HttpSocketTimeout(Exception): |
94 | 103 |
"""Internal exception for socket timeouts. |
95 | 104 |
|
... | ... | |
213 | 222 |
|
214 | 223 |
""" |
215 | 224 |
# TODO: event_poll/event_check/override |
216 |
if op == SOCKOP_SEND:
|
|
225 |
if op in (SOCKOP_SEND, SOCKOP_HANDSHAKE):
|
|
217 | 226 |
event_poll = select.POLLOUT |
218 | 227 |
event_check = select.POLLOUT |
219 | 228 |
|
... | ... | |
232 | 241 |
else: |
233 | 242 |
raise AssertionError("Invalid socket operation") |
234 | 243 |
|
244 |
# Handshake is only supported by SSL sockets |
|
245 |
if (op == SOCKOP_HANDSHAKE and |
|
246 |
not isinstance(sock, OpenSSL.SSL.ConnectionType)): |
|
247 |
return |
|
248 |
|
|
235 | 249 |
# No override by default |
236 | 250 |
event_override = 0 |
237 | 251 |
|
238 | 252 |
while True: |
239 | 253 |
# Poll only for certain operations and when asked for by an override |
240 |
if event_override or op in (SOCKOP_SEND, SOCKOP_RECV): |
|
254 |
if event_override or op in (SOCKOP_SEND, SOCKOP_RECV, SOCKOP_HANDSHAKE):
|
|
241 | 255 |
if event_override: |
242 | 256 |
wait_for_event = event_override |
243 | 257 |
else: |
... | ... | |
272 | 286 |
else: |
273 | 287 |
return sock.shutdown(arg1) |
274 | 288 |
|
289 |
elif op == SOCKOP_HANDSHAKE: |
|
290 |
return sock.do_handshake() |
|
291 |
|
|
275 | 292 |
except OpenSSL.SSL.WantWriteError: |
276 | 293 |
# OpenSSL wants to write, poll for POLLOUT |
277 | 294 |
event_override = select.POLLOUT |
... | ... | |
308 | 325 |
# and can be ignored |
309 | 326 |
return 0 |
310 | 327 |
|
311 |
elif op == SOCKOP_RECV:
|
|
312 |
if err.args == (-1, _SSL_UNEXPECTED_EOF):
|
|
328 |
if err.args == (-1, _SSL_UNEXPECTED_EOF):
|
|
329 |
if op == SOCKOP_RECV:
|
|
313 | 330 |
return "" |
331 |
elif op == SOCKOP_HANDSHAKE: |
|
332 |
# Can happen if peer disconnects directly after the connection is |
|
333 |
# opened. |
|
334 |
raise HttpSessionHandshakeUnexpectedEOF(err.args) |
|
314 | 335 |
|
315 | 336 |
raise socket.error(err.args) |
316 | 337 |
|
... | ... | |
369 | 390 |
raise HttpError("Error while shutting down connection: %s" % err) |
370 | 391 |
|
371 | 392 |
|
393 |
def Handshake(poller, sock, write_timeout): |
|
394 |
"""Shakes peer's hands. |
|
395 |
|
|
396 |
@type poller: select.Poller |
|
397 |
@param poller: Poller object as created by select.poll() |
|
398 |
@type sock: socket |
|
399 |
@param sock: Socket to be shut down |
|
400 |
@type write_timeout: float |
|
401 |
@param write_timeout: Write timeout for handshake |
|
402 |
|
|
403 |
""" |
|
404 |
try: |
|
405 |
return SocketOperation(poller, sock, SOCKOP_HANDSHAKE, None, write_timeout) |
|
406 |
except HttpSocketTimeout: |
|
407 |
raise HttpError("Timeout during SSL handshake") |
|
408 |
except socket.error, err: |
|
409 |
raise HttpError("Error in SSL handshake: %s" % err) |
|
410 |
|
|
411 |
|
|
372 | 412 |
class HttpSslParams(object): |
373 | 413 |
"""Data class for SSL key and certificate. |
374 | 414 |
|
Also available in: Unified diff