Package tlslite :: Package integration :: Module tlsasyncdispatchermixin
[hide private]
[frames] | no frames]

Source Code for Module tlslite.integration.tlsasyncdispatchermixin

  1  # Author: Trevor Perrin 
  2  # See the LICENSE file for legal information regarding use of this file. 
  3   
  4  """TLS Lite + asyncore.""" 
  5   
  6   
  7  import asyncore 
  8  from tlslite.tlsconnection import TLSConnection 
  9  from asyncstatemachine import AsyncStateMachine 
 10   
 11   
12 -class TLSAsyncDispatcherMixIn(AsyncStateMachine):
13 """This class can be "mixed in" with an 14 L{asyncore.dispatcher} to add TLS support. 15 16 This class essentially sits between the dispatcher and the select 17 loop, intercepting events and only calling the dispatcher when 18 applicable. 19 20 In the case of handle_read(), a read operation will be activated, 21 and when it completes, the bytes will be placed in a buffer where 22 the dispatcher can retrieve them by calling recv(), and the 23 dispatcher's handle_read() will be called. 24 25 In the case of handle_write(), the dispatcher's handle_write() will 26 be called, and when it calls send(), a write operation will be 27 activated. 28 29 To use this class, you must combine it with an asyncore.dispatcher, 30 and pass in a handshake operation with setServerHandshakeOp(). 31 32 Below is an example of using this class with medusa. This class is 33 mixed in with http_channel to create http_tls_channel. Note: 34 1. the mix-in is listed first in the inheritance list 35 36 2. the input buffer size must be at least 16K, otherwise the 37 dispatcher might not read all the bytes from the TLS layer, 38 leaving some bytes in limbo. 39 40 3. IE seems to have a problem receiving a whole HTTP response in a 41 single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't 42 be displayed on IE. 43 44 Add the following text into 'start_medusa.py', in the 'HTTP Server' 45 section:: 46 47 from tlslite import * 48 s = open("./serverX509Cert.pem").read() 49 x509 = X509() 50 x509.parse(s) 51 certChain = X509CertChain([x509]) 52 53 s = open("./serverX509Key.pem").read() 54 privateKey = parsePEMKey(s, private=True) 55 56 class http_tls_channel(TLSAsyncDispatcherMixIn, 57 http_server.http_channel): 58 ac_in_buffer_size = 16384 59 60 def __init__ (self, server, conn, addr): 61 http_server.http_channel.__init__(self, server, conn, addr) 62 TLSAsyncDispatcherMixIn.__init__(self, conn) 63 self.tlsConnection.ignoreAbruptClose = True 64 self.setServerHandshakeOp(certChain=certChain, 65 privateKey=privateKey) 66 67 hs.channel_class = http_tls_channel 68 69 If the TLS layer raises an exception, the exception will be caught 70 in asyncore.dispatcher, which will call close() on this class. The 71 TLS layer always closes the TLS connection before raising an 72 exception, so the close operation will complete right away, causing 73 asyncore.dispatcher.close() to be called, which closes the socket 74 and removes this instance from the asyncore loop. 75 76 """ 77 78
79 - def __init__(self, sock=None):
80 AsyncStateMachine.__init__(self) 81 82 if sock: 83 self.tlsConnection = TLSConnection(sock) 84 85 #Calculate the sibling I'm being mixed in with. 86 #This is necessary since we override functions 87 #like readable(), handle_read(), etc., but we 88 #also want to call the sibling's versions. 89 for cl in self.__class__.__bases__: 90 if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine: 91 self.siblingClass = cl 92 break 93 else: 94 raise AssertionError()
95
96 - def readable(self):
97 result = self.wantsReadEvent() 98 if result != None: 99 return result 100 return self.siblingClass.readable(self)
101
102 - def writable(self):
103 result = self.wantsWriteEvent() 104 if result != None: 105 return result 106 return self.siblingClass.writable(self)
107
108 - def handle_read(self):
109 self.inReadEvent()
110
111 - def handle_write(self):
112 self.inWriteEvent()
113
114 - def outConnectEvent(self):
115 self.siblingClass.handle_connect(self)
116
117 - def outCloseEvent(self):
118 asyncore.dispatcher.close(self)
119
120 - def outReadEvent(self, readBuffer):
121 self.readBuffer = readBuffer 122 self.siblingClass.handle_read(self)
123
124 - def outWriteEvent(self):
125 self.siblingClass.handle_write(self)
126
127 - def recv(self, bufferSize=16384):
128 if bufferSize < 16384 or self.readBuffer == None: 129 raise AssertionError() 130 returnValue = self.readBuffer 131 self.readBuffer = None 132 return returnValue
133
134 - def send(self, writeBuffer):
135 self.setWriteOp(writeBuffer) 136 return len(writeBuffer)
137
138 - def close(self):
139 if hasattr(self, "tlsConnection"): 140 self.setCloseOp() 141 else: 142 asyncore.dispatcher.close(self)
143