def _tcp_sock_from_meta(self, meta): assert meta.host if meta.ia is None: meta.ia = self.addr.isd_as if meta.path is None: meta.path = SCIONPath() dst = meta.get_addr() first_ip, first_port = self._get_first_hop(meta.path, dst) active = True try: # Create low-level TCP socket and connect sock = SCIONTCPSocket() sock.bind((self.addr, 0)) sock.connect(dst, meta.port, meta.path, first_ip, first_port, flags=meta.flags) except SCIONTCPError: log_exception( "TCP: connection init error, marking socket inactive") sock = None active = False # Create and return TCPSocketWrapper return TCPSocketWrapper(sock, dst, meta.path, active)
def _cached_entries_handler(self, raw_entries): """ Handles cached (through ZK) TRCs and Cert Chains. """ for entry in raw_entries: try: pkt = SCIONL4Packet(raw=entry) pkt.parse_payload() # FIXME(PSz): some checks are necessary, as filesystem may not # be synced with ZK. Also, when we change topology, new TRCs and # certs are generated, while old ones are still in ZK. It looks # to CS like an attack. This will be fixed when more elements # of trust infrastructure are specified and implemented (like # TRC cross-signing). except SCIONParseError: log_exception("Error parsing cached entry: %s" % entry, level=logging.ERROR) continue payload = pkt.get_payload() if isinstance(payload, CertChainReply): self.process_cert_chain_reply(pkt, from_zk=True) elif isinstance(payload, TRCReply): self.process_trc_reply(pkt, from_zk=True) else: logging.warning("Entry with unsupported type: %s" % entry)
def test_less_arg(self, log, format_exc): format_exc.return_value = MagicMock(spec_set=['split']) format_exc.return_value.split.return_value = ['line0', 'line1'] log_exception('msg', 'arg0', arg1='arg1') calls = [call(logging.CRITICAL, 'msg', 'arg0', arg1='arg1'), call(logging.CRITICAL, 'line0'), call(logging.CRITICAL, 'line1')] log.assert_has_calls(calls)
def test(self, log, format_exc): format_exc.return_value = MagicMock(spec_set=['split']) format_exc.return_value.split.return_value = ['line0', 'line1'] log_exception('msg', 'arg0', level=123, arg1='arg1') log.assert_has_calls([ call(123, 'msg', 'arg0', arg1='arg1'), call(123, 'line0'), call(123, 'line1') ])
def _unix_client_socket(self): soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logging.debug("Connecting to %s:%s" % self.target_proxy) try: soc.connect(self.target_proxy) except OSError: log_exception("Error while connecting to %s:%s" % self.target_proxy) cleanup(soc) return None logging.debug("Connected to target proxy %s:%s" % self.target_proxy) return soc
def handle_request(self, packet, _, from_local_socket=True, sock=None): """ Main routine to handle incoming SCION packets. :param bytes packet: The incoming packet to handle. :param tuple sender: Tuple of sender IP, port. :param bool from_local_socket: True, if the packet was received on the local socket. """ from_local_as = from_local_socket pkt = self._parse_packet(packet) if not pkt: return if pkt.ext_hdrs: logging.debug("Got packet (from_local_as? %s):\n%s", from_local_as, pkt) try: flags = self.handle_extensions(pkt, True, from_local_as) except SCMPError as e: self._scmp_validate_error(pkt, e) return stop, needs_local = self._process_flags(flags, pkt, from_local_as) if stop: logging.debug("Stopped processing") return try: needs_local |= self._needs_local_processing(pkt) except SCMPError as e: self._scmp_validate_error(pkt, e) return if needs_local: try: pkt.parse_payload() except SCIONBaseError: log_exception("Error parsing payload:\n%s" % hex_str(packet)) return handler = self._get_handler(pkt) else: # It's a normal packet, just forward it. handler = self.handle_data logging.debug( "handle_request (from_local_as? %s):" "\n %s\n %s\n handler: %s", from_local_as, pkt.cmn_hdr, pkt.addrs, handler) if not handler: return try: handler(pkt, from_local_as) except SCMPError as e: self._scmp_validate_error(pkt, e) except SCIONBaseError: log_exception("Error handling packet: %s" % pkt)
def _fetch_segments(self, req): """ Called to fetch the requested path. """ try: addr, port = self.dns_query_topo(PATH_SERVICE)[0] except SCIONServiceLookupError: log_exception("Error querying path service:") return logging.debug("Sending path request (%s) to [%s]:%s", req.short_desc(), addr, port) meta = self._build_meta(host=addr, port=port) self.send_meta(CtrlPayload(PathMgmt(req)), meta)
def _fetch_segments(self, req): """ Called to fetch the requested path. """ try: addr, port = self.dns_query_topo(ServiceType.PS)[0] except SCIONServiceLookupError: log_exception("Error querying path service:") return req_id = mk_ctrl_req_id() logging.debug("Sending path request (%s) to [%s]:%s [id: %016x]", req.short_desc(), addr, port, req_id) meta = self._build_meta(host=addr, port=port) self.send_meta(CtrlPayload(PathMgmt(req), req_id=req_id), meta)
def main_wrapper(main, *args, **kwargs): """ Run the supplied function with any args and kwargs specified, catching any raised exceptions and dealing with them appropriately. """ try: main(*args, **kwargs) except SystemExit: logging.info("Exiting") raise except: log_exception("Exception in main process:") logging.critical("Exiting") sys.exit(1)
def _get_msg(self): if len(self._buf) < 4: return None msg_len = struct.unpack("!I", self._buf[:4])[0] if msg_len + 4 > len(self._buf): return None msg = self._buf[4:4 + msg_len] self._buf = self._buf[4 + msg_len:] try: return msg_from_raw(msg) except SCIONBaseError: log_exception("Error parsing message: %s" % hex_str(msg), level=logging.ERROR) return None
def _fetch_segments(self, key): """ Called to fetch the requested path. """ dst_ia, flags = key try: addr, port = self.dns_query_topo(PATH_SERVICE)[0] except SCIONServiceLookupError: log_exception("Error querying path service:") return req = PathSegmentReq.from_values(self.addr.isd_as, dst_ia, flags=flags) logging.debug("Sending path request: %s", req.short_desc()) meta = self.DefaultMeta.from_values(host=addr, port=port) self.send_meta(req, meta)
def thread_safety_net(func, *args, **kwargs): """ Wrapper function to handle uncaught thread exceptions, log them, then kill the process. :type name: string :param func: function to call :type func: function """ name = threading.current_thread().name try: return func(*args, **kwargs) except: log_exception("Exception in %s thread:", name) kill_self()
def run(self): """ Main routine to receive packets and pass them to :func:`handle_request()`. """ self._tcp_start() threading.Thread( target=thread_safety_net, args=(self.packet_recv,), name="Elem.packet_recv", daemon=True).start() try: self._packet_process() except SCIONBaseError: log_exception("Error processing packet.") finally: self.stop()
def _tcp_accept_loop(self): while self.run_flag.is_set(): try: logging.debug("TCP: waiting for connections") self._tcp_conns_put(TCPSocketWrapper(*self._tcp_sock.accept())) logging.debug("TCP: accepted connection") except SCIONTCPTimeout: pass except SCIONTCPError: log_exception("TCP: error on accept()") logging.error("TCP: leaving the accept loop") break try: self._tcp_sock.close() except SCIONTCPError: log_exception("TCP: error on closing _tcp_sock")
def _parse_packet(self, packet): try: pkt = SCIONL4Packet(packet) except SCMPError as e: self._scmp_parse_error(packet, e) return None except SCIONBaseError: log_exception("Error parsing packet: %s" % hex_str(packet), level=logging.ERROR) return None try: pkt.validate(len(packet)) except SCMPError as e: self._scmp_validate_error(pkt, e) return None except SCIONChecksumFailed: logging.debug("Dropping packet due to failed checksum:\n%s", pkt) return pkt
def handle_msg_meta(self, msg, meta): """ Main routine to handle incoming SCION messages. """ if isinstance(meta, SCMPMetadata): handler = self._get_scmp_handler(meta.pkt) else: handler = self._get_ctrl_handler(msg) if not handler: logging.error("handler not found: %s", msg) return try: # SIBRA operates on parsed packets. if (isinstance(meta, UDPMetadata) and msg.type() == PayloadClass.SIBRA): handler(meta.pkt) else: handler(msg, meta) except SCIONBaseError: log_exception("Error handling message:\n%s" % msg)
def _connect_to(self, netloc): """ Establishes a connection to the target host. :param netloc: The hostname (and port) of the target to be connected to. :type netloc: string :returns: The socket that is used to connect. :rtype: socket """ soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if ':' in netloc: host, port = netloc.split(':') else: host, port = netloc, 80 logging.debug("Connecting to %s:%s" % (host, port)) try: soc.connect((host, int(port))) except OSError: log_exception("Error while connecting to %s:%s" % (host, port)) return False logging.debug("Connected to %s:%s" % (host, port)) return soc
def handle_request(self, packet, sender, from_local_socket=True, sock=None): """ Main routine to handle incoming SCION packets. Subclasses may override this to provide their own functionality. """ pkt = self._parse_packet(packet) if not pkt: return try: pkt.parse_payload() except SCIONBaseError: log_exception("Error parsing payload:\n%s" % pkt) return handler = self._get_handler(pkt) if not handler: return try: handler(pkt) except SCIONBaseError: log_exception("Error handling packet:\n%s" % pkt)
def log_exception(self, typ, value, tb): log.log_exception(self, typ, value, tb)
def handle_error(self, *args, **kwargs): log_exception("Error when serving DNS request:") kill_self()
haddr_parse("IPV4", "127.2.26.254"), dst_isd=2, dst_ad=26, dst_port=rcv_sock.port, payload=payload, path=paths[0]) (next_hop, port) = sender.get_first_hop(spkt) assert next_hop is not None logging.info("Sending %d payload bytes (%d packets x %d bytes )" % (PACKETS_NO * PAYLOAD_SIZE, PACKETS_NO, PAYLOAD_SIZE)) for _ in range(PACKETS_NO): sender.send(spkt, next_hop, port) time.sleep(SLEEP) logging.info("Sending finished") recv_t.join() if self.rate < 10.0: sys.exit(0) else: sys.exit(int(self.rate)) if __name__ == "__main__": init_logging("logs/bw_test", console_level=logging.DEBUG) handle_signals() try: TestBandwidth().test() except SystemExit: logging.info("Exiting") raise except: log_exception("Exception in main process:") logging.critical("Exiting") sys.exit(1)