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