<commit_before># encoding: ascii-8bit

module Bitcoin::Node

  # Node network connection to a peer. Handles all the communication with a specific peer.
  class ConnectionHandler < EM::Connection

    include Bitcoin
    include Bitcoin::Blockchain

    attr_reader :host, :port, :version, :direction

    # :new, :handshake, :connected, :disconnected
    attr_reader :state

    # latency of this connection based on last ping/pong
    attr_reader :latency_ms

    def log
      @log ||= Logger::LogWrapper.new("#@host:#@port", @node.log)
    end

    # how long has this connection been open?
    def uptime
      @started ? (Time.now - @started).to_i : 0
    end

    # create connection to +host+:+port+ for given +node+
    def initialize node, host, port, direction
      @node, @host, @port, @direction = node, host, port, direction
      @parser = Bitcoin::Protocol::Parser.new(self)
      @state = :new
      @version = nil
      @started = Time.now
      @port, @host = *Socket.unpack_sockaddr_in(get_peername)  if get_peername
      @ping_nonce = nil
      @latency_ms = @node.config[:connection_timeout] * 1000
      @lock = Monitor.new
      @last_getblocks = []  # the last few getblocks messages received
    rescue
      log.fatal { "Error in #initialize" }
      p $!; puts $@; exit
    end

    # check if connection is wanted, begin handshake if it is, disconnect if not
    def post_init
      begin_handshake  if incoming?
    rescue
      log.fatal { "Error in #post_init" }
      p $!; puts *$@
    end

    # only called for outgoing connection
    def connection_completed
      @connection_completed = true
      begin_handshake
    rescue
      log.fatal { "Error in #connection_completed" }
      p $!; puts *$@
    end

    # receive data from peer and invoke Protocol::Parser
    def receive_data data
      #log.debug { "Receiving data (#{data.size} bytes)" }
      @lock.synchronize { @parser.parse(data) }
    rescue
      log.warn { "Error handling data: #{data.hth}" }
      p $!; puts *$@
    end

    # connection closed; notify listeners and cleanup connection from node
    def unbind
      log.info { (outgoing? && !@connection_completed) ? "Connection failed" : "Disconnected" }
      @node.push_notification(:connection, {type: :disconnected, host: @host, port: @port})
      @state = :disconnected
      @node.connections.delete(self)
    end

    # begin handshake
    def begin_handshake
      if incoming? && !@node.accept_connections?
        return close_connection  unless @node.config[:connect].include?([@host, @port.to_s])
      end
      log.info { "Established #{@direction} connection" }
      @node.connections << self
      @state = :handshake

      EM.add_timer(@node.config[:connection_timeout]) do
        unless @state == :connected
          log.debug { "Handshake timed out." }
          close_connection
        end
      end

      send_version

    rescue
      log.fatal { "Error in #begin_handshake" }
      p $!; puts *$@
    end

    # complete handshake; set state, started time, notify listeners and add address to Node
    def complete_handshake
      return unless @state == :handshake
      log.debug { 'Handshake completed' }
      @state = :connected
      @latency_ms = Time.now - @started
      @started = Time.now
      @node.push_notification(:connection, info.merge(type: :connected))
      @node.addrs << addr
      send_data P::Addr.pkt(@node.addr)  if @node.config[:announce]
    end

    # error parsing a message, log as warning but otherwise ignore
    def on_error(type, data)
      log.warn { "error: #{type} (#{data})" }<commit_msg>output parse error data as hex to not mess up the terminal<commit_after># encoding: ascii-8bit

module Bitcoin::Node

  # Node network connection to a peer. Handles all the communication with a specific peer.
  class ConnectionHandler < EM::Connection

    include Bitcoin
    include Bitcoin::Blockchain

    attr_reader :host, :port, :version, :direction

    # :new, :handshake, :connected, :disconnected
    attr_reader :state

    # latency of this connection based on last ping/pong
    attr_reader :latency_ms

    def log
      @log ||= Logger::LogWrapper.new("#@host:#@port", @node.log)
    end

    # how long has this connection been open?
    def uptime
      @started ? (Time.now - @started).to_i : 0
    end

    # create connection to +host+:+port+ for given +node+
    def initialize node, host, port, direction
      @node, @host, @port, @direction = node, host, port, direction
      @parser = Bitcoin::Protocol::Parser.new(self)
      @state = :new
      @version = nil
      @started = Time.now
      @port, @host = *Socket.unpack_sockaddr_in(get_peername)  if get_peername
      @ping_nonce = nil
      @latency_ms = @node.config[:connection_timeout] * 1000
      @lock = Monitor.new
      @last_getblocks = []  # the last few getblocks messages received
    rescue
      log.fatal { "Error in #initialize" }
      p $!; puts $@; exit
    end

    # check if connection is wanted, begin handshake if it is, disconnect if not
    def post_init
      begin_handshake  if incoming?
    rescue
      log.fatal { "Error in #post_init" }
      p $!; puts *$@
    end

    # only called for outgoing connection
    def connection_completed
      @connection_completed = true
      begin_handshake
    rescue
      log.fatal { "Error in #connection_completed" }
      p $!; puts *$@
    end

    # receive data from peer and invoke Protocol::Parser
    def receive_data data
      #log.debug { "Receiving data (#{data.size} bytes)" }
      @lock.synchronize { @parser.parse(data) }
    rescue
      log.warn { "Error handling data: #{data.hth}" }
      p $!; puts *$@
    end

    # connection closed; notify listeners and cleanup connection from node
    def unbind
      log.info { (outgoing? && !@connection_completed) ? "Connection failed" : "Disconnected" }
      @node.push_notification(:connection, {type: :disconnected, host: @host, port: @port})
      @state = :disconnected
      @node.connections.delete(self)
    end

    # begin handshake
    def begin_handshake
      if incoming? && !@node.accept_connections?
        return close_connection  unless @node.config[:connect].include?([@host, @port.to_s])
      end
      log.info { "Established #{@direction} connection" }
      @node.connections << self
      @state = :handshake

      EM.add_timer(@node.config[:connection_timeout]) do
        unless @state == :connected
          log.debug { "Handshake timed out." }
          close_connection
        end
      end

      send_version

    rescue
      log.fatal { "Error in #begin_handshake" }
      p $!; puts *$@
    end

    # complete handshake; set state, started time, notify listeners and add address to Node
    def complete_handshake
      return unless @state == :handshake
      log.debug { 'Handshake completed' }
      @state = :connected
      @latency_ms = Time.now - @started
      @started = Time.now
      @node.push_notification(:connection, info.merge(type: :connected))
      @node.addrs << addr
      send_data P::Addr.pkt(@node.addr)  if @node.config[:announce]
    end

    # error parsing a message, log as warning but otherwise ignore
    def on_error(type, data)
      log.warn { "error: #{type} (#{data.hth})" }
{'fraction_non_alphanumeric': 0.10788211103495544, 'fraction_numerical': 0.0016449623029472242, 'mean_word_length': 2.7473035439137132, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2256895', 'n_tokens_mistral': 2231, 'n_tokens_neox': 2139, 'n_words': 651}