Package spoon :: Package transports :: Module spoontransport
[hide private]
[frames] | no frames]

Source Code for Module spoon.transports.spoontransport

  1  # 
  2  # Copyright (C) 2006, Matt Sullivan <matts@zarrf.com> 
  3  # 
  4  # Permission is hereby granted, free of charge, to any person obtaining 
  5  # a copy of this software and associated documentation files (the 
  6  # "Software"), to deal in the Software without restriction, including 
  7  # without limitation the rights to use, copy, modify, merge, publish, 
  8  # distribute, sublicense, and/or sell copies of the Software, and to 
  9  # permit persons to whom the Software is furnished to do so, subject to 
 10  # the following conditions: 
 11  #  
 12  # The above copyright notice and this permission notice shall be included 
 13  # in all copies or substantial portions of the Software. 
 14  #  
 15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 16  # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 17  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 18  # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 19  # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 20  # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 21  # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 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   
29 -class SpoonTransport(object):
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 """
41 - def __init__(self, t, network=None):
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
63 - def __repr__(self):
64 return "SpoonTransport(%s, %s)"%(repr(self.sock), repr(self.mtypes[LMTYPE_NETWORK]))
65
66 - def write(self, obj):
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
79 - def read(self):
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
93 - def fileno(self):
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
104 - def close(self):
105 TransportHub.removeTransport(self) 106 self.sock.close()
107
108 - def start(self):
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
118 - def getAuthedNodeId(self):
119 """ 120 override this if your class does any pre authentication. 121 """ 122 return None
123
124 - def __get_active(self):
125 return self.__active
126
127 - def __set_active(self, newval):
128 if (newval == False) and (self.__active): 129 self.__active = newval 130 TransportHub.removeTransport(self)
131 # Do nothing if trying to do anything else 132
133 - def getNetwork(self):
134 return self.mtypes.get(LMTYPE_NETWORK, None)
135
136 -class SpoonTransportThread(Thread):
137 - def __init__(self, t):
138 self.sock = t 139 Thread.__init__(self, name="SpoonTransportThread for "+repr(t))
140
141 - def run(self):
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