Revision d7fa9982

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