1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 from spoon import SpoonStream
25 from threading import Semaphore, Thread
26 from transporthub import TransportException, TransportHub, LMTYPE_NETWORK, LMTYPE_NETWORK_PROTO, LinkMessage
27 import StringIO
28
30 """
31 The spoon transport base class. This will probably mostly be responsible for handling locking on
32 the transport. It also takes care of removing itself from the transport hub if it is made inactive.
33
34 Any reads or writes on the socket should be performed with the SpoonTransport, or otherwise synchronized
35 once this is created.
36 @ivar sock: The raw socket or file object that the transport is bound to
37 @ivar spoon: The SpoonStream wrapper around the socket.
38 @ivar active: Indicates if the transport is currently active.
39
40 """
42 """
43 Creates a spoon transport link out of an existing socket and joins it to a network. This network
44 is either a mesh network or a point to point network (just a direct connection.)
45 @param t: Some sort of a socket or file like object.
46 @param network: An instance of a mesh network or a point to point network that the transport will be joined to.
47 """
48 self.sock = t
49 self.spoon = SpoonStream(self.sock)
50 self.active = property(fget=self.__get_active, fset=self.__set_active,\
51 doc="""Will be True as long as the transport is active, will be false if it is inactive.
52 Transports are made inactive if any exceptions are encountered.""")
53 if network:
54 self.mtypes = {LMTYPE_NETWORK:network, LMTYPE_NETWORK_PROTO:network}
55 else:
56 self.mtypes = dict()
57 self.nodeId = None
58 self.thread = None
59 self.__active = False
60 self.__wlock = Semaphore()
61 self.__rlock = Semaphore()
62
64 return "SpoonTransport(%s, %s)"%(repr(self.sock), repr(self.mtypes[LMTYPE_NETWORK]))
65
67 if not self.active:
68 raise TransportException("SpoonTransport %s not active."%(repr(self)))
69 self.__wlock.acquire()
70 try:
71 try:
72 self.spoon.write(obj)
73 except Exception, ex:
74 self.active = False
75 raise ex
76 finally:
77 self.__wlock.release()
78
80 if not self.active:
81 raise TransportException("SpoonTransport %s not active."%(repr(self)))
82 self.__rlock.acquire()
83 try:
84 try:
85 return self.spoon.read()
86 except Exception, ex:
87 self.active = False
88
89 raise ex
90 finally:
91 self.__rlock.release()
92
94 """
95 Returns the fileno for use in a select or poll call if one exists for the socket or file wrapped by this SpoonTransport.
96 If the socket or file does not have a fileno method, None will be returned. For proper behavior with paramiko, fileno
97 on the socket isn't called any time before fileno is called on the SpoonTransport.
98 """
99 if hasattr(self.sock, "fileno"):
100 return self.sock.fileno()
101 else:
102 return None
103
107
109 """
110 Starts the spoon protocol on the socket. Must be called before writing/reading with the SpoonTransport object.
111 Will cause the Transport to be registered with TransportHub.
112 """
113 TransportHub.addTransport(self)
114 self.__active = True
115 self.thread = SpoonTransportThread(self)
116 self.thread.start()
117
119 """
120 override this if your class does any pre authentication.
121 """
122 return None
123
125 return self.__active
126
131
132
135
138 self.sock = t
139 Thread.__init__(self, name="SpoonTransportThread for "+repr(t))
140
142 while self.sock.active:
143 obj = None
144 try:
145 obj = self.sock.read()
146 except Exception, ex:
147 TransportHub._log.error("Got exception '%s' while reading from socket '%s'"%(repr(ex), repr(self.sock)))
148 continue
149
150 if not isinstance(obj, LinkMessage):
151 TransportHub._log.warn("Decoded a message from %s that wasn't a LinkMessage, something's screwy here."%(repr(self.sock)))
152 return
153
154 if not self.sock.mtypes.has_key(obj.msgtype):
155 TransportHub._log.error("Unknown link message type receieved from '%s'"%(repr(self.sock)))
156 continue
157 try:
158 self.sock.mtypes[obj.msgtype].handleLinkMessage(self.sock, obj)
159 except Exception, ex:
160 TransportHub._log.error("Uncaught exception in link message handler for type %d on transport '%s'"%(obj.msgtype, self.sock), ex)
161 continue
162 TransportHub._log.debug("SpoonTransportThread stopping")
163