Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / integration / TLSAsyncDispatcherMixIn.py
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)