def handleAccept(self, rc, evt): if self.disconnecting or self.disconnected: return False # possible errors: # (WSAEMFILE, WSAENOBUFS, WSAENFILE, WSAENOMEM, WSAECONNABORTED) if rc: log.msg("Could not accept new connection -- %s (%s)" % (errno.errorcode.get(rc, 'unknown error'), rc)) return False else: evt.newskt.setsockopt(socket.SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, struct.pack('I', self.socket.fileno())) family, lAddr, rAddr = _iocp.get_accept_addrs(evt.newskt.fileno(), evt.buff) assert family == self.addressFamily protocol = self.factory.buildProtocol( address._ServerFactoryIPv4Address('TCP', rAddr[0], rAddr[1])) if protocol is None: evt.newskt.close() else: s = self.sessionno self.sessionno = s+1 transport = Server(evt.newskt, protocol, address.IPv4Address('TCP', rAddr[0], rAddr[1], 'INET'), address.IPv4Address('TCP', lAddr[0], lAddr[1], 'INET'), s, self.reactor) protocol.makeConnection(transport) return True
def __getstate__(self): log.msg("WARNING: serializing ephemeral %s" % self) import gc if getattr(gc, 'get_referrers', None): for r in gc.get_referrers(self): log.msg(" referred to by %s" % (r, )) return None
def connectionLost(self, reason): """ Cleans up the socket. """ log.msg('(Port %s Closed)' % self._realPortNumber) self._realPortNumber = None d = None if hasattr(self, "deferred"): d = self.deferred del self.deferred self.disconnected = True self.reactor.removeActiveHandle(self) self.connected = False self._closeSocket() del self.socket del self.getFileHandle try: self.factory.doStop() except: self.disconnecting = False if d is not None: d.errback(failure.Failure()) else: raise else: self.disconnecting = False if d is not None: d.callback(None)
def _doReadOrWrite(self, source, condition, faildict={ error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()), }): why = None inRead = False if condition & POLL_DISCONNECTED and not (condition & gobject.IO_IN): if source in self._reads: why = main.CONNECTION_DONE inRead = True else: why = main.CONNECTION_LOST else: try: if condition & gobject.IO_IN: why = source.doRead() inRead = True if not why and condition & gobject.IO_OUT: # if doRead caused connectionLost, don't call doWrite # if doRead is doWrite, don't call it again. if not source.disconnected: why = source.doWrite() except: why = sys.exc_info()[1] log.msg('Error In %s' % source) log.deferr() if why: self._disconnectSelectable(source, why, inRead)
def reapProcess(self): """ Try to reap a process (without blocking) via waitpid. This is called when sigchild is caught or a Process object loses its "connection" (stdout is closed) This ought to result in reaping all zombie processes, since it will be called twice as often as it needs to be. (Unfortunately, this is a slightly experimental approach, since UNIX has no way to be really sure that your process is going to go away w/o blocking. I don't want to block.) """ try: try: pid, status = os.waitpid(self.pid, os.WNOHANG) except OSError, e: if e.errno == errno.ECHILD: # no child process pid = None else: raise except: log.msg('Failed to reap %d:' % self.pid) log.err() pid = None if pid: self.processEnded(status) unregisterReapProcessHandler(pid, self)
def handleAccept(self, rc, evt): if self.disconnecting or self.disconnected: return False # possible errors: # (WSAEMFILE, WSAENOBUFS, WSAENFILE, WSAENOMEM, WSAECONNABORTED) if rc: log.msg("Could not accept new connection -- %s (%s)" % (errno.errorcode.get(rc, 'unknown error'), rc)) return False else: evt.newskt.setsockopt(socket.SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, struct.pack('I', self.socket.fileno())) family, lAddr, rAddr = _iocp.get_accept_addrs( evt.newskt.fileno(), evt.buff) assert family == self.addressFamily protocol = self.factory.buildProtocol( address._ServerFactoryIPv4Address('TCP', rAddr[0], rAddr[1])) if protocol is None: evt.newskt.close() else: s = self.sessionno self.sessionno = s + 1 transport = Server( evt.newskt, protocol, address.IPv4Address('TCP', rAddr[0], rAddr[1], 'INET'), address.IPv4Address('TCP', lAddr[0], lAddr[1], 'INET'), s, self.reactor) protocol.makeConnection(transport) return True
def __call__(self, *args, **kw): import traceback log.msg('instance method %s.%s' % (reflect.qual(self.my_class), self.name)) log.msg('being called with %r %r' % (args, kw)) traceback.print_stack(file=log.logfile) assert 0
def doWaitForMultipleEvents(self, timeout): log.msg(channel='system', event='iteration', reactor=self) if timeout is None: #timeout = INFINITE timeout = 100 else: timeout = int(timeout * 1000) if not (self._events or self._writes): # sleep so we don't suck up CPU time time.sleep(timeout / 1000.0) return canDoMoreWrites = 0 for fd in self._writes.keys(): if log.callWithLogger(fd, self._runWrite, fd): canDoMoreWrites = 1 if canDoMoreWrites: timeout = 0 handles = self._events.keys() or [self.dummyEvent] val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT | QS_ALLEVENTS) if val == WAIT_TIMEOUT: return elif val == WAIT_OBJECT_0 + len(handles): exit = win32gui.PumpWaitingMessages() if exit: self.callLater(0, self.stop) return elif val >= WAIT_OBJECT_0 and val < WAIT_OBJECT_0 + len(handles): fd, action = self._events[handles[val - WAIT_OBJECT_0]] log.callWithLogger(fd, self._runAction, action, fd)
def __getstate__(self): log.msg( "WARNING: serializing ephemeral %s" % self ) import gc if getattr(gc, 'get_referrers', None): for r in gc.get_referrers(self): log.msg( " referred to by %s" % (r,)) return None
def unpickleModule(name): 'support function for copy_reg to unpickle module refs' if oldModules.has_key(name): log.msg("Module has moved: %s" % name) name = oldModules[name] log.msg(name) return __import__(name,{},{},'x')
def unpickleModule(name): 'support function for copy_reg to unpickle module refs' if oldModules.has_key(name): log.msg("Module has moved: %s" % name) name = oldModules[name] log.msg(name) return __import__(name, {}, {}, 'x')
def _readAndWrite(self, source, condition): # note: gtk-1.2's gtk_input_add presents an API in terms of gdk # constants like INPUT_READ and INPUT_WRITE. Internally, it will add # POLL_HUP and POLL_ERR to the poll() events, but if they happen it # will turn them back into INPUT_READ and INPUT_WRITE. gdkevents.c # maps IN/HUP/ERR to INPUT_READ, and OUT/ERR to INPUT_WRITE. This # means there is no immediate way to detect a disconnected socket. # The g_io_add_watch() API is more suited to this task. I don't think # pygtk exposes it, though. why = None didRead = None try: if condition & gtk.GDK.INPUT_READ: why = source.doRead() didRead = source.doRead if not why and condition & gtk.GDK.INPUT_WRITE: # if doRead caused connectionLost, don't call doWrite # if doRead is doWrite, don't call it again. if not source.disconnected and source.doWrite != didRead: why = source.doWrite() didRead = source.doWrite # if failed it was in write except: why = sys.exc_info()[1] log.msg('Error In %s' % source) log.deferr() if why: self._disconnectSelectable(source, why, didRead == source.doRead)
def unpickleMethod(im_name, im_self, im_class): 'support function for copy_reg to unpickle method refs' try: unbound = getattr(im_class,im_name) if im_self is None: return unbound bound=instancemethod(unbound.im_func, im_self, im_class) return bound except AttributeError: log.msg("Method",im_name,"not on class",im_class) assert im_self is not None,"No recourse: no instance to guess from." # Attempt a common fix before bailing -- if classes have # changed around since we pickled this method, we may still be # able to get it by looking on the instance's current class. unbound = getattr(im_self.__class__,im_name) log.msg("Attempting fixup with",unbound) if im_self is None: return unbound bound=instancemethod(unbound.im_func, im_self, im_self.__class__) return bound
def startListening(self): """Create and bind my socket, and begin listening on it. This is called on unserialization, and must be called after creating a server to begin listening on the specified port. """ log.msg("%s starting on %r" % (self.factory.__class__, repr(self.port))) if self.wantPID: self.lockFile = lockfile.FilesystemLock(self.port + ".lock") if not self.lockFile.lock(): raise CannotListenError, (None, self.port, "Cannot acquire lock") else: if not self.lockFile.clean: try: # This is a best-attempt at cleaning up # left-over unix sockets on the filesystem. # If it fails, there's not much else we can # do. The bind() below will fail with an # exception that actually propegates. if stat.S_ISSOCK(os.stat(self.port).st_mode): os.remove(self.port) except: pass self.factory.doStart() try: skt = self.createInternetSocket() skt.bind(self.port) except socket.error, le: raise CannotListenError, (None, self.port, le)
def _doReadOrWrite( self, source, condition, faildict={ error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()), }): why = None inRead = False if condition & POLL_DISCONNECTED and not (condition & gobject.IO_IN): if source in self._reads: why = main.CONNECTION_DONE inRead = True else: why = main.CONNECTION_LOST else: try: if condition & gobject.IO_IN: why = source.doRead() inRead = True if not why and condition & gobject.IO_OUT: # if doRead caused connectionLost, don't call doWrite # if doRead is doWrite, don't call it again. if not source.disconnected: why = source.doWrite() except: why = sys.exc_info()[1] log.msg('Error In %s' % source) log.deferr() if why: self._disconnectSelectable(source, why, inRead)
def throttleReads(self): """ Throttle reads on all protocols. """ log.msg("Throttling reads on %s" % self) for p in self.protocols.keys(): p.throttleReads()
def throttleWrites(self): """ Throttle writes on all protocols. """ log.msg("Throttling writes on %s" % self) for p in self.protocols.keys(): p.throttleWrites()
def jelly(self, obj): try: ao = self.jellyToAO(obj) return ao except: log.msg("Error jellying object! Stacktrace follows::") log.msg(string.join(self.stack, '\n')) raise
def processExited(self, reason): msg('processExited(%r)' % (reason, )) # Protect the Deferred from the failure so that it follows # the callback chain. This doesn't use the errback chain # because it wants to make sure reason is a Failure. An # Exception would also make an errback-based test pass, and # that would be wrong. exited.callback([reason])
def processExited(self, reason): msg('processExited(%r)' % (reason,)) # Protect the Deferred from the failure so that it follows # the callback chain. This doesn't use the errback chain # because it wants to make sure reason is a Failure. An # Exception would also make an errback-based test pass, and # that would be wrong. exited.callback([reason])
def lineReceived(self, line): if not self.queries: log.msg("Unexpected server response: %r" % (line,)) else: d, _, _ = self.queries.pop(0) self.parseResponse(d, line) if self.queries: self.sendLine('%d, %d' % (self.queries[0][1], self.queries[0][2]))
def unthrottleWrites(self): """ Stop throttling writes on all protocols. """ self.unthrottleWritesID = None log.msg("Stopped throttling writes on %s" % self) for p in self.protocols.keys(): p.unthrottleWrites()
def _bindSocket(self): log.msg("%s starting on %s"%(self.protocol.__class__, repr(self.port))) try: skt = self.createInternetSocket() # XXX: haha misnamed method if self.port: skt.bind(self.port) except socket.error, le: raise error.CannotListenError, (None, self.port, le)
def buildProtocol(self): if self.ircui: log.msg("already logged in") return None i = IRCUserInterface() i.factory = self self.ircui = i return i
def _bindSocket(self): log.msg("%s starting on %s" % (self.protocol.__class__, repr(self.port))) try: skt = self.createInternetSocket() # XXX: haha misnamed method if self.port: skt.bind(self.port) except socket.error, le: raise error.CannotListenError, (None, self.port, le)
def lineReceived(self, line): if not self.queries: log.msg("Unexpected server response: %r" % (line, )) else: d, _, _ = self.queries.pop(0) self.parseResponse(d, line) if self.queries: self.sendLine('%d, %d' % (self.queries[0][1], self.queries[0][2]))
def __getattr__(self, key): try: return getattr(self.mainMod, key) except AttributeError: if self.initRun: raise else: log.msg("Warning! Loading from __main__: %s" % key) return styles.Ephemeral()
def logPacketData(data): lines = len(data)/16 if lines*16 != len(data): lines=lines+1 for i in range(lines): d = tuple(data[16*i:16*i+16]) hex = map(lambda x: "%02X"%ord(x),d) text = map(lambda x: (len(repr(x))>3 and '.') or x, d) log.msg(' '.join(hex)+ ' '*3*(16-len(d)) +''.join(text)) log.msg('')
def proceed(protos, port): log.msg('PROCEEDING WITH THE TESTATHRON') self.assert_(protos[0]) self.assert_(protos[1]) protos = protos[0][1], protos[1][1] protos[0].transport.write( 'x' * (2 * protos[0].transport.readBufferSize) + 'y' * (2 * protos[0].transport.readBufferSize)) return sf.stop_d.addCallback(cleanup, protos, port)
def doStart(self): """Make sure startProtocol is called. This will be called by makeConnection(), users should not call it. """ if not self.numPorts: if self.noisy: log.msg("Starting protocol %s" % self) self.startProtocol() self.numPorts = self.numPorts + 1
def doStart(self): """Make sure startFactory is called. Users should not call this function themselves! """ if not self.numPorts: if self.noisy: log.msg("Starting factory %r" % self) self.startFactory() self.numPorts = self.numPorts + 1
def __getattr__(self, name): """ A getattr method to cause a class to be refreshed. """ if name == '__del__': raise AttributeError("Without this, Python segfaults.") updateInstance(self) log.msg("(rebuilding stale %s instance (%s))" % (reflect.qual(self.__class__), name)) result = getattr(self, name) return result
def oscar_Cookie(self,data): snac=readSNAC(data[1]) if self.icq: i=snac[5].find("\000") snac[5]=snac[5][i:] tlvs=readTLVs(snac[5]) if tlvs.has_key(6): self.cookie=tlvs[6] server,port=string.split(tlvs[5],":") d = self.connectToBOS(server, int(port)) d.addErrback(lambda x: log.msg("Connection Failed! Reason: %s" % x)) if self.deferred: d.chainDeferred(self.deferred) self.disconnect() elif tlvs.has_key(8): errorcode=tlvs[8] errorurl=tlvs[4] if errorcode=='\000\030': error="You are attempting to sign on again too soon. Please try again later." elif errorcode=='\000\005': error="Invalid Username or Password." else: error=repr(errorcode) self.error(error,errorurl) else: log.msg('hmm, weird tlvs for %s cookie packet' % str(self)) log.msg(tlvs) log.msg('snac') log.msg(str(snac)) return "None"
def versionUpgrade(self): """(internal) Do a version upgrade. """ bases = _aybabtu(self.__class__) # put the bases in order so superclasses' persistenceVersion methods # will be called first. bases.reverse() bases.append(self.__class__) # don't forget me!! # first let's look for old-skool versioned's if self.__dict__.has_key("persistenceVersion"): # Hacky heuristic: if more than one class subclasses Versioned, # we'll assume that the higher version number wins for the older # class, so we'll consider the attribute the version of the older # class. There are obviously possibly times when this will # eventually be an incorrect assumption, but hopefully old-school # persistenceVersion stuff won't make it that far into multiple # classes inheriting from Versioned. pver = self.__dict__['persistenceVersion'] del self.__dict__['persistenceVersion'] highestVersion = 0 highestBase = None for base in bases: if not base.__dict__.has_key('persistenceVersion'): continue if base.persistenceVersion > highestVersion: highestBase = base highestVersion = base.persistenceVersion if highestBase: self.__dict__['%s.persistenceVersion' % reflect.qual(highestBase)] = pver for base in bases: # ugly hack, but it's what the user expects, really if (Versioned not in base.__bases__ and not base.__dict__.has_key('persistenceVersion')): continue currentVers = base.persistenceVersion pverName = '%s.persistenceVersion' % reflect.qual(base) persistVers = (self.__dict__.get(pverName) or 0) if persistVers: del self.__dict__[pverName] assert persistVers <= currentVers, "Sorry, can't go backwards in time." while persistVers < currentVers: persistVers = persistVers + 1 method = base.__dict__.get('upgradeToVersion%s' % persistVers, None) if method: log.msg("Upgrading %s (of %s @ %s) to version %s" % (reflect.qual(base), reflect.qual( self.__class__), id(self), persistVers)) method(self) else: log.msg('Warning: cannot upgrade %s to version %s' % (base, persistVers))
def oscar_Cookie(self, data): snac = readSNAC(data[1]) if self.icq: i = snac[5].find("\000") snac[5] = snac[5][i:] tlvs = readTLVs(snac[5]) if tlvs.has_key(6): self.cookie = tlvs[6] server, port = string.split(tlvs[5], ":") d = self.connectToBOS(server, int(port)) d.addErrback(lambda x: log.msg("Connection Failed! Reason: %s" % x)) if self.deferred: d.chainDeferred(self.deferred) self.disconnect() elif tlvs.has_key(8): errorcode = tlvs[8] errorurl = tlvs[4] if errorcode == "\000\030": error = "You are attempting to sign on again too soon. Please try again later." elif errorcode == "\000\005": error = "Invalid Username or Password." else: error = repr(errorcode) self.error(error, errorurl) else: log.msg("hmm, weird tlvs for %s cookie packet" % str(self)) log.msg(tlvs) log.msg("snac") log.msg(str(snac)) return "None"
def unjelly(self, ao): try: l = [None] self.unjellyInto(l, 0, ao) for callable, v in self.afterUnjelly: callable(v[0]) return l[0] except: log.msg("Error jellying object! Stacktrace follows::") log.msg(string.join(map(repr, self.stack), "\n")) raise
def sendMessage(self, destURL, message): """Send a message. @param destURL: C{URL}. This should be a *physical* URL, not a logical one. @param message: The message to send. """ if destURL.transport not in ("udp", None): raise RuntimeError, "only UDP currently supported" if self.debug: log.msg("Sending %r to %r" % (message.toString(), destURL)) self.transport.write(message.toString(), (destURL.host, destURL.port or self.PORT))
def doStop(self): """Make sure stopProtocol is called. This will be called by the port, users should not call it. """ assert self.numPorts > 0 self.numPorts = self.numPorts - 1 self.transport = None if not self.numPorts: if self.noisy: log.msg("Stopping protocol %s" % self) self.stopProtocol()
def datagramReceived(self, data, addr): self.parser.dataReceived(data) self.parser.dataDone() for m in self.messages: self._fixupNAT(m, addr) if self.debug: log.msg("Received %r from %r" % (m.toString(), addr)) if isinstance(m, Request): self.handle_request(m, addr) else: self.handle_response(m, addr) self.messages[:] = []
def tearDown(self): """ Restore the original SIGCHLD handler and reap processes as long as there seem to be any remaining. """ if self.originalHandler is not None: signal.signal(signal.SIGCHLD, self.originalHandler) if process is not None: while process.reapProcessHandlers: log.msg("ReactorBuilder.tearDown reaping some processes %r" % (process.reapProcessHandlers, )) process.reapAllProcesses()
def run(self, installSignalHandlers=True): """ Start the reactor. """ self._postQueue = Queue.Queue() if not hasattr(self, "wxapp"): log.msg("registerWxApp() was not called on reactor, " "registering my own wxApp instance.") self.registerWxApp(wxPySimpleApp()) # start select() thread: self.interleave(self._runInMainThread, installSignalHandlers=installSignalHandlers) if installSignalHandlers: self.callLater(0, self._installSignalHandlersAgain) # add cleanup events: self.addSystemEventTrigger("after", "shutdown", self._stopWx) self.addSystemEventTrigger("after", "shutdown", lambda: self._postQueue.put(None)) # On Mac OS X, work around wx bug by starting timer to ensure # wxCallAfter calls are always processed. We don't wake up as # often as we could since that uses too much CPU. if runtime.platform.isMacOSX(): t = ProcessEventsTimer(self.wxapp) t.Start(2) # wake up every 2ms self.wxapp.MainLoop() wxapp = self.wxapp del self.wxapp if not self._stopping: # wx event loop exited without reactor.stop() being # called. At this point events from select() thread will # be added to _postQueue, but some may still be waiting # unprocessed in wx, thus the ProcessPendingEvents() # below. self.stop() wxapp.ProcessPendingEvents() # deal with any queued wxCallAfters while 1: try: f = self._postQueue.get(timeout=0.01) except Queue.Empty: continue else: if f is None: break try: f() except: log.err()