def buildProtocol(self, addr): remote_ip = ip_address(addr.host) if any(remote_ip in network for network in self.whitelist): return WrappingFactory.buildProtocol(self, addr) else: log.info("Attempted submission from non-whitelisted %s" % str(addr)) return None
def stringReceived(self, data): """ Called when we receive a string. The sender should only ever receive an ack or a nak, after which it should disconnect. """ log.debug("Got response from %s" % str(self.transport.getPeer())) try: incoming = xml_document(data) if incoming.get('role') == "ack": log.info("Acknowledgement received from %s" % str(self.transport.getPeer())) self.factory.ack = True elif incoming.get('role') == "nak": log.warn("Nak received: %s refused to accept VOEvent (%s)" % ( str(self.transport.getPeer()), incoming.findtext("Meta/Result", default="no reason given") ) ) else: log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.get("role")) ) except ParseError: log.warn("Unparsable message received from %s" % str(self.transport.getPeer())) finally: # After receiving a message, we shut down the connection. self.transport.loseConnection()
def stringReceived(self, data): """ Called when a complete new message is received. """ try: incoming = xml_document(data) except ParseError: d = log.warn("Unparsable message received from %s" % str(self.transport.getPeer())) else: # The root element of both VOEvent and Transport packets has a # "role" element which we use to identify the type of message we # have received. if incoming.element.get('role') in VOEVENT_ROLES: log.info( "VOEvent %s received from %s" % ( incoming.element.attrib['ivorn'], str(self.transport.getPeer()) ) ) d = self.process_event(incoming) else: d = log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.element.get("role")) ) finally: return d.addCallback( lambda x: self.transport.loseConnection() )
def __call__(self, event): log.info("Running external command: %s" % (self.cmd,)) d = defer.Deferred() if not os.access(self.cmd, os.X_OK): msg = "%s is not executable" % (self.cmd,) log.warn(msg) d.errback(Exception(msg)) else: def log_reason(reason): """ Catch a Failure returned from an unsuccessful process execution and log the return value, then re-raise the error. """ msg = "%s returned non-zero (%d)" % (self.cmd, reason.value.exitCode) log.warn(msg) return reason d.addErrback(log_reason) reactor.spawnProcess( SpawnCommandProtocol(d, event.raw_bytes), self.cmd, args=self.args, env=os.environ ) return d
def timeoutConnection(self): log.info( "No iamalive received from %s for %d seconds; disconecting" % (self.transport.getPeer(), self.ALIVE_INTERVAL), system="VOEventSubscriber" ) return TimeoutMixin.timeoutConnection(self)
def __call__(self, event): log.info("Running external command: %s" % (self.cmd, )) d = defer.Deferred() if not os.access(self.cmd, os.X_OK): msg = "%s is not executable" % (self.cmd, ) log.warn(msg) d.errback(Exception(msg)) else: def log_reason(reason): """ Catch a Failure returned from an unsuccessful process execution and log the return value, then re-raise the error. """ msg = "%s returned non-zero (%d)" % (self.cmd, reason.value.exitCode) log.warn(msg) return reason d.addErrback(log_reason) reactor.spawnProcess(SpawnCommandProtocol(d, event.raw_bytes), self.cmd, args=self.args, env=os.environ) return d
def stringReceived(self, data): """ Called when we receive a string. The sender should only ever receive an ack or a nak, after which it should disconnect. """ log.debug("Got response from %s" % str(self.transport.getPeer())) try: incoming = xml_document(data) if incoming.element.get('role') == "ack": log.info("Acknowledgement received from %s" % str(self.transport.getPeer())) self.factory.ack = True elif incoming.element.get('role') == "nak": log.warn("Nak received: %s refused to accept VOEvent (%s)" % (str(self.transport.getPeer()), incoming.element.findtext( "Meta/Result", default="no reason given"))) else: log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.element.get("role"))) except ParseError: log.warn("Unparsable message received from %s" % str(self.transport.getPeer())) finally: # After receiving a message, we shut down the connection. self.transport.loseConnection()
def log_response(incoming): """Default action to take on receiving an acknowledgement. The result is logged, the connection is closed (per the VTP spec) and the incoming packet is passed on to the next callback in the chain (if any). Parameters ---------- incoming : `comet.utility.xml_document` The acknowledgement received. Returns ------- incoming : `comet.utility.xml_document` The acknowledgement received. Notes ----- A NAK is not considered a failure (we do not call an errback). """ if incoming.role == "ack": log.info(f"ACK received: " f"{self.transport.getPeer()} accepted VOEvent") elif incoming.role == "nak": reason = incoming.element.findtext("Meta/Result", default="no reason given") log.warn(f"NAK received: " f"{self.transport.getPeer()} refused to accept VOEvent " f"({reason})") self.transport.loseConnection() return incoming
def stringReceived(self, data): """ Called when a complete new message is received. """ try: incoming = xml_document(data) except ParseError: log.warn("Unparsable message received") return # Reset the timeout counter and wait another 120 seconds before # disconnecting due to inactivity. self.resetTimeout() # The root element of both VOEvent and Transport packets has a # "role" element which we use to identify the type of message we # have received. if incoming.element.get("role") == "iamalive": log.debug("IAmAlive received from %s" % str(self.transport.getPeer())) self.send_xml(iamaliveresponse(self.factory.local_ivo, incoming.element.find("Origin").text)) elif incoming.element.get("role") == "authenticate": log.debug("Authenticate received from %s" % str(self.transport.getPeer())) self.send_xml( authenticateresponse(self.factory.local_ivo, incoming.element.find("Origin").text, self.filters) ) elif incoming.element.get("role") in VOEVENT_ROLES: log.info("VOEvent %s received from %s" % (incoming.element.attrib["ivorn"], str(self.transport.getPeer()))) # We don't send a NAK even if the event is invalid since we don't # want to be removed from upstream's distribution list. self.process_event(incoming, can_nak=False) else: log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.element.get("role")) )
def clientConnectionFailed(self, connector, reason): log.info( "Connection to %s failed; will retry in %d second%s" % (connector.getDestination(), self.delay, "" if self.delay == 1 else "s"), system="VOEventSubscriberFactory", ) ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
def check_filters(result): if not self.filters or any([value for success, value in result if success]): log.info("Event matches filter criteria: forwarding to %s" % (str(self.transport.getPeer()),)) self.send_xml(event) self.outstanding_ack += 1 else: log.info("Event rejected by filter")
def log_response(incoming): """Default action to take on receiving an acknowledgement. The result is logged, the connection is closed (per the VTP spec) and the incoming packet is passed on to the next callback in the chain (if any). Parameters ---------- incoming : `comet.utility.xml_document` The acknowledgement received. Returns ------- incoming : `comet.utility.xml_document` The acknowledgement received. Notes ----- A NAK is not considered a failure (we do not call an errback). """ if incoming.role == "ack": log.info(f"ACK received: " f"{self.transport.getPeer()} accepted VOEvent") elif incoming.role == "nak": reason = incoming.element.findtext("Meta/Result", default="no reason given") log.warn( f"NAK received: " f"{self.transport.getPeer()} refused to accept VOEvent " f"({reason})") self.transport.loseConnection() return incoming
def buildProtocol(self, addr): remote_ip = ip_address(addr.host) if any(remote_ip in network for network in self.whitelist): return WrappingFactory.buildProtocol(self, addr) else: log.info("Attempted %s from non-whitelisted %s" % (self.connection_type, str(addr))) return None
def clientConnectionFailed(self, connector, reason): log.info( "Connection to %s failed; will retry in %d second%s" % (connector.getDestination(), self.delay, "" if self.delay == 1 else "s"), system="VOEventSubscriberFactory" ) ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
def clientConnectionLost(self, connector, reason): log.info( "Connection to %s lost; will retry in %d second%s" % (connector.getDestination(), self.delay, "" if self.delay == 1 else "s"), system="VOEventSubscriberFactory" ) if self.reset_call.active(): self.reset_call.cancel() ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
def lengthLimitExceeded(self, length): """ This is called when a remote tries to send a massive string. Quite likely that's because it sends the prefix in little endian (rather than network) byte order. """ log.info("Length limit exceeded (%d bytes)." % (length, )) Int32StringReceiver.lengthLimitExceeded(self, length)
def lengthLimitExceeded(self, length): """ This is called when a remote tries to send a massive string. Quite likely that's because it sends the prefix in little endian (rather than network) byte order. """ log.info("Length limit exceeded (%d bytes)." % (length,)) Int32StringReceiver.lengthLimitExceeded(self, length)
def check_filters(result): if not self.filters or any( [value for success, value in result if success]): log.info("Event matches filter criteria: forwarding to %s" % (str(self.transport.getPeer()), )) self.send_xml(event) self.outstanding_ack += 1 else: log.info("Event rejected by filter")
def sendIAmAlive(self): if self.alive_count >= self.MAX_ALIVE_COUNT: log.info("Peer appears to be dead; dropping connection") self.transport.loseConnection() elif self.outstanding_ack >= self.MAX_OUTSTANDING_ACK: log.info("Peer is not acknowledging events; dropping connection") self.transport.loseConnection() else: self.send_xml(TransportMessage.iamalive(self.factory.local_ivo)) self.alive_count += 1
def sendIAmAlive(self): if self.alive_count >= self.MAX_ALIVE_COUNT: log.info("Peer appears to be dead; dropping connection") self.transport.loseConnection() elif self.outstanding_ack >= self.MAX_OUTSTANDING_ACK: log.info("Peer is not acknowledging events; dropping connection") self.transport.loseConnection() else: self.send_xml(iamalive(self.factory.local_ivo)) self.alive_count += 1
def handle_invalid(failure): log.info("Event rejected (%s); discarding" % (failure.value.subFailure.getErrorMessage(),)) if can_nak: log.debug("Sending NAK to %s" % (self.transport.getPeer())) self.send_xml(TransportMessage.nak(self.factory.local_ivo, event.element.attrib['ivorn'], "Event rejected: %s" % (failure.value.subFailure.getErrorMessage(),))) else: log.debug("Sending ACK to %s" % (self.transport.getPeer())) self.send_xml(TransportMessage.ack(self.factory.local_ivo, event.element.attrib['ivorn']))
def buildProtocol(self, addr): try: remote_ip = ip_address(addr.host) if not any(remote_ip in network for network in self.whitelist): log.info(f"Attempted {self.connection_type} from " f"non-whitelisted {addr}") return None except AttributeError: log.warn(f"Bypassing whitelist for {self.connection_type} " f"from {addr}") return WrappingFactory.buildProtocol(self, addr)
def handle_invalid(failure): log.info("Event rejected (%s); discarding" % (failure.value.subFailure.getErrorMessage(), )) if can_nak: log.debug("Sending NAK to %s" % (self.transport.getPeer())) self.send_xml( nak( self.factory.local_ivo, event.element.attrib['ivorn'], "Event rejected: %s" % (failure.value.subFailure.getErrorMessage(), ))) else: log.debug("Sending ACK to %s" % (self.transport.getPeer())) self.send_xml( ack(self.factory.local_ivo, event.element.attrib['ivorn']))
def expire_db(db_path, lock): remove = [] with lock: db = anydbm.open(os.path.join(self.root, db_path), 'c') # The database returned by anydbm is guaranteed to have a # .keys() method, but not necessarily .(iter)items(). for key in db.keys(): if int(time.time() - float(db[key])) >= expiry_time: # Rounding to nearest int avoids an issue when we call # call prune(0) *immediately* after an insertion and might # get hit by floating point weirdness. remove.append(key) log.info("Expiring %d events from %s" % (len(remove), db_path)) for key in remove: del db[key] db.close()
def stringReceived(self, data): """ Called when a complete new message is received. """ try: incoming = xml_document(data) except ParseError: log.warn("Unparsable message received") return # Reset the timeout counter and wait another 120 seconds before # disconnecting due to inactivity. self.resetTimeout() # The root element of both VOEvent and Transport packets has a # "role" element which we use to identify the type of message we # have received. if incoming.element.get('role') == "iamalive": log.debug("IAmAlive received from %s" % str(self.transport.getPeer())) self.send_xml( iamaliveresponse(self.factory.local_ivo, incoming.element.find('Origin').text) ) elif incoming.element.get('role') == "authenticate": log.debug("Authenticate received from %s" % str(self.transport.getPeer())) self.send_xml( authenticateresponse( self.factory.local_ivo, incoming.element.find('Origin').text, self.filters ) ) elif incoming.element.get('role') in VOEVENT_ROLES: log.info( "VOEvent %s received from %s" % ( incoming.element.attrib['ivorn'], str(self.transport.getPeer()) ) ) # We don't send a NAK even if the event is invalid since we don't # want to be removed from upstream's distribution list. self.process_event(incoming, can_nak=False) else: log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.element.get("role")) )
def __call__(self, event): """ Add an event to the celery processing queue """ log.debug("Passing to voeventdb: %s" % (event.attrib['ivorn'],)) session = Session(bind=dbengine) try: v = voeventparse.loads(event.text) dbconv.safe_insert_voevent(session, v) session.commit() except Exception as e: log.warn("Could not insert packet with ivorn {} into database {}".format( v.attrib['ivorn'], voeventdb_dbname)) self.deferred.errback(e) log.info("Loaded {} into database {}".format( v.attrib['ivorn'], voeventdb_dbname))
def __call__(self, event): """ Add an event to the celery processing queue """ v = None try: session = Session(bind=dbengine) v = voeventparse.loads(event.raw_bytes) dbconv.safe_insert_voevent(session, v) session.commit() except Exception as e: if v is None: log.warn("Could not parse event-bytes as voevent") else: log.warn( "Could not insert packet with ivorn {} into database {}". format(v.attrib['ivorn'], voeventdb_dbname)) self.deferred.errback(e) log.info("Loaded {} into database {}".format(v.attrib['ivorn'], voeventdb_dbname))
def stringReceived(self, data): """ Called when a complete new message is received. """ try: incoming = xml_document.infer_type(data) except ParseError: d = log.warn("Unparsable message received from %s" % str(self.transport.getPeer())) else: # The root element of both VOEvent and Transport packets has a # "role" element which we use to identify the type of message we # have received. if hasattr(incoming, "ivoid"): log.info("VOEvent %s received from %s" % (incoming.ivoid, str(self.transport.getPeer()))) d = self.process_event(incoming) else: d = log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.role)) finally: return d.addCallback(lambda x: self.transport.loseConnection())
def stringReceived(self, data): try: incoming = TransportMessage(data) except ParseError: log.warn("Unparsable message received") return if incoming.role == "iamalive": log.debug("IAmAlive received from %s" % str(self.transport.getPeer())) self.alive_count -= 1 elif incoming.role == "ack": log.debug("Ack received from %s" % str(self.transport.getPeer())) self.outstanding_ack -= 1 elif incoming.role == "nak": log.info("Nak received from %s; terminating" % str(self.transport.getPeer())) self.transport.loseConnection() elif incoming.role == "authenticate": log.debug("Authentication received from %s" % str(self.transport.getPeer())) self.filters = [] # Accept both "new-style" (<Param type="xpath-filter" />) and # old-style (<filter type="xpath" />) filters. for xpath in chain([ elem.get('value') for elem in incoming.element.findall( "Meta/Param[@name=\"xpath-filter\"]") ], [ elem.text for elem in incoming.element.findall( "Meta/filter[@type=\"xpath\"]") ]): log.info("Installing filter %s for %s" % (xpath, str(self.transport.getPeer()))) try: self.filters.append(ElementTree.XPath(xpath)) except ElementTree.XPathSyntaxError: log.info("Filter %s is not valid XPath" % (xpath, )) else: log.warn("Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.role))
def stringReceived(self, data): try: incoming = xml_document(data) except ParseError: log.warn("Unparsable message received") return if incoming.get('role') == "iamalive": log.debug("IAmAlive received from %s" % str(self.transport.getPeer())) self.alive_count -= 1 elif incoming.get('role') == "ack": log.debug("Ack received from %s" % str(self.transport.getPeer())) self.outstanding_ack -= 1 elif incoming.get('role') == "nak": log.info("Nak received from %s; terminating" % str(self.transport.getPeer())) self.transport.loseConnection() elif incoming.get('role') == "authenticate": log.debug("Authentication received from %s" % str(self.transport.getPeer())) self.filters = [] # Accept both "new-style" (<Param type="xpath-filter" />) and # old-style (<filter type="xpath" />) filters. for xpath in chain( [elem.get('value') for elem in incoming.findall("Meta/Param[@name=\"xpath-filter\"]")], [elem.text for elem in incoming.findall("Meta/filter[@type=\"xpath\"]")] ): log.info( "Installing filter %s for %s" % (xpath, str(self.transport.getPeer())) ) try: self.filters.append(ElementTree.XPath(xpath)) except ElementTree.XPathSyntaxError: log.info("Filter %s is not valid XPath" % (xpath,)) else: log.warn( "Incomprehensible data received from %s (role=%s)" % (self.transport.getPeer(), incoming.get("role")) )
def test_log_info_level_warning(self): log.LEVEL = log.Levels.WARNING self.assertFalse(self.observer.messages) d = log.info(DUMMY_MESSAGE) self.assertIsInstance(d, defer.Deferred) return d.addCallback(self._check_log_empty)
def connectionMade(self): log.info("New subscriber at %s" % str(self.transport.getPeer())) self.factory.broadcasters.append(self) self.alive_count = 0 self.send_xml(authenticate(self.factory.local_ivo)) self.outstanding_ack = 0
def stopFactory(self): if self.ack: log.info("Event was sent successfully") else: log.warn("Event was NOT sent successfully")
def connectionLost(self, *args): log.info("Subscriber at %s disconnected" % str(self.transport.getPeer())) self.factory.broadcasters.remove(self) return ElementSender.connectionLost(self, *args)
def test_log_info_level_info(self): log.LEVEL = log.Levels.INFO self.assertFalse(self.observer.messages) d = log.info(DUMMY_MESSAGE) self.assertIsInstance(d, defer.Deferred) return d.addCallback(self._check_log_full)
def connectionMade(self): log.info("New subscriber at %s" % str(self.transport.getPeer())) self.factory.broadcasters.append(self) self.alive_count = 0 self.send_xml(TransportMessage.authenticate(self.factory.local_ivo)) self.outstanding_ack = 0
def connectionMade(self): log.info("New connection from %s" % str(self.transport.getPeer())) self.setTimeout(self.TIMEOUT)
def timeoutConnection(self): log.info( "%s timed out after %d seconds" % (str(self.transport.getPeer()), self.TIMEOUT) ) return TimeoutMixin.timeoutConnection(self)
def timeoutConnection(self): log.info("%s timed out after %d seconds" % (str(self.transport.getPeer()), self.TIMEOUT)) return TimeoutMixin.timeoutConnection(self)