def _JitSessionToOtherSide(self, clientID): clientTransportID = self.machoNet.transportIDbyClientID[clientID] clientTransport = self.machoNet.transportsByID[clientTransportID] remoteSessionVersion = clientTransport.dependants.get( self.transportID, 0) sess = clientTransport.sessions[clientID] if remoteSessionVersion != sess.version: sessData = {} self.machoNet.LogInfo('JITing session ', sess.sid, ' (clientID ', clientID, '), localVer = ', sess.version, ' remoteVer = ', remoteSessionVersion) if remoteSessionVersion == 0: for v in sess.GetDistributedProps(0): sessData[v] = getattr(sess, v) sessionprops = SessionInitialStateNotification( source=MachoAddress(clientID=clientID), destination=MachoAddress(nodeID=self.nodeID), sid=sess.sid, sessionType=sess.sessionType, initialstate=sessData) else: for v in sess.GetDistributedProps(1): sessData[v] = (None, getattr(sess, v)) sessionprops = SessionChangeNotification( source=MachoAddress(clientID=clientID), destination=MachoAddress(nodeID=self.nodeID), sid=sess.sid, change=(1, sessData)) clientTransport.dependants[self.transportID] = sess.version self.Write(sessionprops, jitSession=0)
def __init__(self, *args, **keywords): self.userID = None self.compressedPart = 0 self.source = MachoAddress() self.destination = MachoAddress() self.contextKey = None self.applicationID = None self.languageID = None self.oob = {} dtc = 0 for each in keywords.iterkeys(): if each != 'donttypecheck': setattr(self, each, keywords[each]) else: dtc = 1 self.command = self.__machodesc__['command'] if not dtc: for each in self.__machodesc__['params']: if each[-1:] != '?': if not hasattr(self, each): raise TypeError('%s requires %s to be specified' % (self.__class__.__name__, each)) self.pickleSize = 0
def GetMachoAddressOfOtherSide(self): if macho.mode == 'client': return MachoAddress(nodeID=self.machoNet.myProxyNodeID) elif self.clientID: return MachoAddress(clientID=self.clientID) else: return MachoAddress(nodeID=self.nodeID)
def __init__(self, sess, gpcs, objectID, pa, refID): try: self.__dict__['session'] = weakref.proxy(sess) except TypeError: self.__dict__['session'] = sess sys.exc_clear() self.__dict__['objectID'] = objectID self.__dict__['sessionCheck'] = None self.__dict__['persistantObjectID'] = objectID self.__dict__['gpcs'] = weakref.proxy(gpcs) self.__dict__['__publicattributes__'] = pa self.__dict__['objectChangeHandlers'] = weakref.WeakKeyDictionary({}) mask = sess.Masquerade() try: self.__dict__['clisid'] = gpcs.machoNet.GetClientSessionID() finally: mask.UnMask() if objectID[0] == 'C': self.__dict__['blocking'] = 0 cid, oid = objectID.split(':') cid = cid.split('=')[1] self.__dict__['destination'] = MachoAddress(clientID=long(cid)) else: self.__dict__['blocking'] = 1 nid, oid = objectID.split(':') nid = nid.split('=')[1] self.__dict__['destination'] = MachoAddress(nodeID=long(nid)) self.__dict__['deleted'] = 0 sess.RegisterMachoObjectConnection(objectID, self, refID)
def InvalidateCachedObjects(self, objectIDs, forward=1): deleted = 0 for each in objectIDs: if each in self.cachedMethodCalls: del self.cachedMethodCalls[each] self.__CacheIsDirty('cachedMethodCalls', each) if type(each) in (types.TupleType, types.ListType): objectID = each[0] version = each[1] else: objectID = each version = None if objectID in self.cachedObjects and not isinstance( self.cachedObjects[objectID], uthread.Semaphore): if version is None or self.__OlderVersion( self.cachedObjects[objectID].version, version): del self.cachedObjects[objectID] self.__CacheIsDirty('cachedObjects', objectID) gpcs = sm.services['machoNet'] gpcs.GetGPCS() if macho.mode == 'client': return if macho.mode == 'proxy': for eachNodeID in sm.services['machoNet'].GetConnectedSolNodes(): gpcs.RemoteServiceNotify( self.session, MachoAddress(nodeID=eachNodeID, service='objectCaching'), 'objectCaching', 'InvalidateCachedObjects', objectIDs, 0) elif forward and sm.services['machoNet'].GetConnectedProxyNodes(): eachNodeID = random.choice( sm.services['machoNet'].GetConnectedProxyNodes()) gpcs.RemoteServiceNotify( self.session, MachoAddress(nodeID=eachNodeID, service='objectCaching'), 'objectCaching', 'InvalidateCachedObjects', objectIDs, 0)
def ConnectToClientService(self, svc, idtype, theID): if machobase.mode == 'proxy': s = self.GetSessionFromParams(idtype, theID) return sm.services['machoNet'].ConnectToRemoteService( svc, MachoAddress(clientID=s.clientID, service=svc), s) proxyNodeID = self.GetProxyNodeFromID(idtype, theID) try: return self.GetProxySessionManager( proxyNodeID).ConnectToClientService(svc, idtype, theID) except UnMachoDestination: sys.exc_clear() if not refreshed: return self.GetProxySessionManager( self.GetProxyNodeFromID(idtype, theID, 1)).ConnectToClientService( svc, idtype, theID)
class MachoPacket(): __guid__ = 'macho.MachoPacket' __intorstringtype__ = (types.IntType, types.StringType, types.UnicodeType) __bizzarrerouters__ = ( const.cluster.MACHONETMSG_TYPE_SESSIONCHANGENOTIFICATION, const.cluster.MACHONETMSG_TYPE_SESSIONINITIALSTATENOTIFICATION, const.cluster.MACHONETMSG_TYPE_PING_REQ, const.cluster.MACHONETMSG_TYPE_PING_RSP) def __init__(self, *args, **keywords): self.userID = None self.compressedPart = 0 self.source = MachoAddress() self.destination = MachoAddress() self.contextKey = None self.applicationID = None self.languageID = None self.oob = {} dtc = 0 for each in keywords.iterkeys(): if each != 'donttypecheck': setattr(self, each, keywords[each]) else: dtc = 1 self.command = self.__machodesc__['command'] if not dtc: for each in self.__machodesc__['params']: if each[-1:] != '?': if not hasattr(self, each): raise TypeError('%s requires %s to be specified' % (self.__class__.__name__, each)) self.pickleSize = 0 def __getstate__(self): params = self.__machodesc__['params'] body = [None] * len(params) for i in range(len(params)): if params[i].endswith('?'): tmp = params[i][:-1] if hasattr(self, tmp): body[i] = getattr(self, tmp) else: body.pop(-1) break else: body[i] = getattr(self, params[i]) oob = None if self.oob or self.compressedPart: oob = self.oob if self.compressedPart: oob['compressedPart'] = self.compressedPart return (self.command, self.source, self.destination, self.userID, tuple(body), oob, self.contextKey, self.applicationID, self.languageID) def __setstate__(self, state): self.command, self.source, self.destination, self.userID, body, self.oob, self.contextKey, self.applicationID, self.languageID = state if self.oob is None: self.oob = {} self.compressedPart = self.oob.get('compressedPart', 0) params = self.__machodesc__['params'] l = len(params) if len(body) < l: l = len(body) for i in range(l): if params[i].endswith('?'): tmp = params[i][:-1] else: tmp = params[i] setattr(self, tmp, body[i]) def Response(self, *args, **keywords): if not self.__machodesc__.has_key('response'): raise AttributeError( self.__class__.__name__, 'Response', 'There is no such thing as a response to a %s' % self.__class__.__name__) theResponse = apply(self.__machodesc__['response'], (), {'donttypecheck': 1}) theResponse.source = self.destination theResponse.destination = self.source theResponse.userID = self.userID theResponse.contextKey = None theResponse.applicationID = None theResponse.languageId = None responseParams = theResponse.__machodesc__['params'] i = 0 for each in responseParams: if each.endswith('?'): if len(args) > i: setattr(theResponse, each[:-1], args[i]) break else: if len(args) <= i: break setattr(theResponse, each, args[i]) i = i + 1 for each in keywords.iterkeys(): if each not in responseParams: raise TypeError('%s.Response does not take %s as a parameter' % (self.__class__.__name__, each)) setattr(theResponse, each, keywords[each]) for each in responseParams: if not each.endswith('?') and not hasattr(theResponse, each): raise TypeError( '%s.Response requires %s as a parameter, but it was not specified' % (self.__class__.__name__, each)) return theResponse def ErrorResponse(self, code, payload): theResponse = ErrorResponse(originalCommand=self.command, code=code, payload=payload) theResponse.source = self.destination theResponse.destination = self.source theResponse.userID = self.userID theResponse.contextKey = None theResponse.applicationID = None theResponse.languageID = None return theResponse def SetPickle(self, thePickle): self.__dict__['thePickle'] = thePickle self.__dict__['pickleSize'] = len(self.thePickle) def GetPickle(self): if not hasattr(self, 'thePickle'): self.__dict__['thePickle'] = machobase.Dumps(self) self.__dict__['pickleSize'] = len(self.thePickle) return self.thePickle def GetPickleSize(self, machoNet): if not self.pickleSize: self.GetPickle() return self.pickleSize def Changed(self): if hasattr(self, 'thePickle'): delattr(self, 'thePickle') def RoutesTo(self, towhat): if self.command in self.__bizzarrerouters__: return 1 if self.command == const.cluster.MACHONETMSG_TYPE_AUTHENTICATION_REQ and machobase.mode == 'proxy': return 0 return self.destination.RoutesTo(towhat, self.source) def __setattr__(self, attr, value): if hasattr(self, 'thePickle'): if hasattr(self, attr): curr = getattr(self, attr) if type(curr) not in self.__intorstringtype__ or type( value ) not in self.__intorstringtype__ or curr != value: self.Changed() else: self.Changed() self.__dict__[attr] = value def __repr__(self): try: if self.__guid__ == 'macho.AuthenticationReq': return 'Packet::AuthenticationReq(%s,%s,%s,%s,%s)' % ( self.source, self.destination, self.clientinfo, self.userName, getattr(self, 'address', None)) self.GetPickle() if len(self.thePickle) > 1500000: return 'Packet::%s (%s,%s,GENOCIDAL PAYLOAD(%d bytes),%s, %s)' % ( self.__class__.__name__, self.source, self.destination, len(self.thePickle), self.oob, self.contextKey) if len(self.thePickle) > 1000000: return 'Packet::%s (%s,%s,MURDEROUS PAYLOAD(%d bytes),%s, %s)' % ( self.__class__.__name__, self.source, self.destination, len(self.thePickle), self.oob, self.contextKey) if len(self.thePickle) > 100000: return 'Packet::%s (%s,%s,GARGANTUAN PAYLOAD(%d bytes),%s, %s)' % ( self.__class__.__name__, self.source, self.destination, len(self.thePickle), self.oob, self.contextKey) if len(self.thePickle) > 10000: return 'Packet::%s (%s,%s,HUGE PAYLOAD(%d bytes),%s, %s)' % ( self.__class__.__name__, self.source, self.destination, len(self.thePickle), self.oob, self.contextKey) if len(self.thePickle) > 1000: return 'Packet::%s (%s,%s,LARGE PAYLOAD(%d bytes),%s, %s)' % ( self.__class__.__name__, self.source, self.destination, len(self.thePickle), self.oob, self.contextKey) try: l = len(self.thePickle) params = [] for each in self.__machodesc__['params']: if each[-1:] == '?': tmp = each[:-1] if hasattr(self, tmp): params.append(getattr(self, tmp)) else: params.append(getattr(self, each)) if hasattr(self, 'strayload'): return 'Packet::%s (%s,%s,%s bytes,%s,%s, %s)' % ( self.__class__.__name__, self.source, self.destination, l, self.strayload, self.oob, self.contextKey) return 'Packet::%s (%s,%s,%s bytes,%s,%s, %s)' % ( self.__class__.__name__, self.source, self.destination, l, params, self.oob, self.contextKey) except Exception: log.LogException() return 'Packet::%s (CRAPPY TUPLE)' % self.__class__.__name__ except Exception: log.LogException() return 'Packet containing crappy data' __str__ = __repr__
def Read(self): self.currentReaders += 1 try: thePickle = self.transport.Read() finally: self.currentReaders -= 1 if getattr(self, 'userID', None) and len(thePickle) > 100000: self.machoNet.LogWarn( 'Read a ', len(thePickle), ' byte packet (before decompression) from userID=', getattr(self, 'userID', 'non-user'), ' on address ', self.transport.address) elif len(thePickle) > 5000000: self.machoNet.LogWarn( 'Read a ', len(thePickle), ' byte packet (before decompression) from userID=', getattr(self, 'userID', 'non-user'), ' on address ', self.transport.address) if thePickle[0] not in '}~': before = len(thePickle) try: with bluepy.Timer( 'machoNet::MachoTransport::Read::DeCompress'): thePickle = zlib.decompress(thePickle) except zlib.error as e: raise RuntimeError('Decompression Failure: ' + strx(e)) after = len(thePickle) if after <= before: self.machoNet.LogError('Decompress shrank data from ', before, ' to ', after, ' bytes') else: self.machoNet.decompressedBytes.Add(after - before) if getattr(self, 'userID', None) and len(thePickle) > 100000: self.machoNet.LogWarn( 'Read a ', len(thePickle), ' byte packet (after decompression, if appropriate) from userID=', getattr(self, 'userID', 'non-user'), ' on address ', self.transport.address) elif len(thePickle) > 5000000: self.machoNet.LogWarn( 'Read a ', len(thePickle), ' byte packet (after decompression, if appropriate) from userID=', getattr(self, 'userID', 'non-user'), ' on address ', self.transport.address) if self.clientID: self.machoNet.dataReceived.Add(len(thePickle)) else: self.machoNet.dataReceived.AddFrom(self.nodeID, len(thePickle)) try: message = macho.Loads(thePickle) except GPSTransportClosed as e: self.transport.Close(**e.GetCloseArgs()) raise except StandardError: if self.transportName == 'tcp:packet:client': self._LogPotentialAttackAndClose(thePickle) raise message.SetPickle(thePickle) if macho.mode == 'client' and message.source.addressType == const.ADDRESS_TYPE_NODE and message.destination.addressType == const.ADDRESS_TYPE_BROADCAST: message.oob['sn'] = self.machoNet.notifySequenceIDByNodeID[ message.source.nodeID] self.machoNet.notifySequenceIDByNodeID[message.source.nodeID] += 1 if self.transportName == 'tcp:packet:client': message.source = MachoAddress(clientID=self.clientID, callID=message.source.callID) if message.contextKey is not None or message.applicationID is not None or message.languageID is not None: self._LogPotentialAttackAndClose(thePickle) raise StandardError( 'Packet containing contextKey received on a client transport. Hack?' ) if hasattr(self, 'userID'): message.userID = self.userID if message.command != const.cluster.MACHONETMSG_TYPE_MOVEMENTNOTIFICATION or MACHONET_LOGMOVEMENT: self.LogInfo('Read: ', message) if macho.mode == 'proxy': for objectID, refID in message.oob.get('OID-', {}).iteritems(): s = self.sessions.get(self.clientID, None) if s is None: s = self.sessions.get(self.nodeID, None) if s is not None: s.UnregisterMachoObject(objectID, refID) if macho.mode == 'server': ls = localstorage.GetLocalStorage() ls['applicationID'] = message.applicationID ls['languageID'] = message.languageID return message