<commit_before>require 'socket'
#require 'rpc_response'
#require 'vista_rpc'

module VistaRPC4r
  class RPCBrokerConnection
    # Header chunk types
    CHUNK_TYPE_HEADER = "1"
    CHUNK_TYPE_RPC = "2"
    CHUNK_TYPE_SECURITY = "3"
    CHUNK_TYPE_COMMAND = "4"
    CHUNK_TYPE_DATA = "5"
    XWB_HEADER = "[XWB]"
    # Header and protocol info
    VISTA_RPC_VERSION = "1"
    VISTA_RPC_TYPE_CMD = "0"
    VISTA_RPC_TYPE_RPC = "1"
    VISTA_RPC_LENV = 3
    VISTA_RPC_LENV_STR = "3"
    VISTA_RPC_RETURN_DATA = "0"
    VISTA_RPC_NO_RETURN_DATA = "1"
    END_MARKER = 4
    # Parameter types
    PARAM_LITERAL_MARKER = "0"
    PARAM_REFERENCE_MARKER = "1"
    PARAM_LIST_MARKER = "2"
    PARAM_GLOBAL_MARKER = "3"
    PARAM_EMPTY_MARKER = "4"
    
    public
    
    def initialize(host, port, access, verify, debug=FALSE)
      @sentConnect = false
      @signedOn = false
      @host=host
      @port=port
      @access=access
      @verify=verify
      @debug=debug
      @token=nil
      @socket = nil
      @encryptedAV = nil
      @writeBuffer = String.new
      @duz = "0"
      @currentContext = nil
    end
    
    def connect
      retVal = true
      if isConnected()
        warn " already connected, closing first"
        close
      end
      @socket = TCPSocket.open(@host, @port)    # Connect
      #            socket.setTcpNoDelay(true)
      tcpConnect = VistaRPC.new("TCPConnect", RPCResponse::SINGLE_VALUE, true)
      tcpConnect.params[0]= @socket.addr[4]  # local IP address
      tcpConnect.params[1]= "0" # callback port ?
      tcpConnect.params[2]= "OVID"
      connectResponse = execute(tcpConnect)
      if (connectResponse == nil || connectResponse.value == nil || connectResponse.value == "reject")
        raise "Handshake error" 
      end
      if (connectResponse.error_message != nil)
        raise "RPC Error: " + connectResponse.error_message 
      end
      @sentConnect = true
      
      signOn()
      retVal = logIn()
      return retVal
    end
    
    def close()
      if isConnected()
        if @sentConnect
          @sentConnect = false
          bye = VistaRPC.new("#BYE#", RPCResponse::SINGLE_VALUE, true)
          execute(bye)
          @socket.close()
          @socket = nil
        end
      end
    end
    
    def isConnected()
      return @socket != nil
    end
    
    def execute(rpc)
      retVal = executeOnce(rpc)
      if (retVal == nil && @signedOn) 
        #reconnect
        if (rpc.name == "#BYE#")
          # We're disconnecting anyway
          return nil
        end
        # attempt to log back on
        if (connect())
          if (@currentContext != nil) 
            context = !currentContext
            @currentContext = nil
            setContext(context)
          end
          retVal = executeOnce(rpc)
        end
      end
      if (retVal == nil)
        raise "Lost connection to server"
      end
      return retVal
    end

    # Call the RPC function
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  response type = one of the types in RPCResponse
    #  returns RPCResponse
    def call(rpcname, responsetype, args=nil)
      rpc = VistaRPC.new(rpcname, responsetype)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse
    end

    # Call the RPC function expecting to receive a string or SINGLE_VALUE
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  returns String
    def call_s(rpcname, args=nil)
      rpc = VistaRPC.new(rpcname, RPCResponse::SINGLE_VALUE)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse.value
    end

    # Call the RPC function expecting to receive a array of string ARRAY
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  returns Array
    def call_a(rpcname, args=nil)
      rpc = VistaRPC.new(rpcname, RPCResponse::ARRAY)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse.value
    end

    
    def setContext(context)
      if (context == @currentContext)
        warn "context is already set to " + context + "..."
        return
      end
      if (@currentContext != nil) 
        warn "changing context from " + currentContext + " to " + context
      end
      
      puts "Setting context to: " + context
      xwbCreateContext = VistaRPC.new("XWB CREATE CONTEXT", RPCResponse::SINGLE_VALUE)
      encryptedContext = xwbCreateContext.encrypt(context)
      xwbCreateContext.params[0] = encryptedContext
      response = execute(xwbCreateContext)
      if (response == nil || response.error_message != nil)
        raise "XWB CREATE CONTEXT failed: " + response.error_message
      end
      @currentContext = context
    end
    
    
    def getDUZ
      return @duz
    end
    
    
    
    private  
    
    def signOn() 
      signonResponse = execute(VistaRPC.new("XUS SIGNON SETUP", RPCResponse::ARRAY))
      if (signonResponse == nil || signonResponse.error_message != nil)
        raise "XUS SIGNON SETUP failed"
      end
      @signedOn = true
    end
    <commit_msg>Fixing close and context bugs<commit_after>require 'socket'
#require 'rpc_response'
#require 'vista_rpc'

module VistaRPC4r
  class RPCBrokerConnection
    # Header chunk types
    CHUNK_TYPE_HEADER = "1"
    CHUNK_TYPE_RPC = "2"
    CHUNK_TYPE_SECURITY = "3"
    CHUNK_TYPE_COMMAND = "4"
    CHUNK_TYPE_DATA = "5"
    XWB_HEADER = "[XWB]"
    # Header and protocol info
    VISTA_RPC_VERSION = "1"
    VISTA_RPC_TYPE_CMD = "0"
    VISTA_RPC_TYPE_RPC = "1"
    VISTA_RPC_LENV = 3
    VISTA_RPC_LENV_STR = "3"
    VISTA_RPC_RETURN_DATA = "0"
    VISTA_RPC_NO_RETURN_DATA = "1"
    END_MARKER = 4
    # Parameter types
    PARAM_LITERAL_MARKER = "0"
    PARAM_REFERENCE_MARKER = "1"
    PARAM_LIST_MARKER = "2"
    PARAM_GLOBAL_MARKER = "3"
    PARAM_EMPTY_MARKER = "4"
    
    public
    
    def initialize(host, port, access, verify, debug=FALSE)
      @sentConnect = false
      @signedOn = false
      @host=host
      @port=port
      @access=access
      @verify=verify
      @debug=debug
      @token=<PASSWORD>
      @socket = nil
      @encryptedAV = nil
      @writeBuffer = String.new
      @duz = "0"
      @currentContext = nil
    end
    
    def connect
      retVal = true
      if isConnected()
        warn " already connected, closing first"
        close
      end
      @socket = TCPSocket.open(@host, @port)    # Connect
      #            socket.setTcpNoDelay(true)
      tcpConnect = VistaRPC.new("TCPConnect", RPCResponse::SINGLE_VALUE, true)
      tcpConnect.params[0]= @socket.addr[4]  # local IP address
      tcpConnect.params[1]= "0" # callback port ?
      tcpConnect.params[2]= "OVID"
      connectResponse = execute(tcpConnect)
      if (connectResponse == nil || connectResponse.value == nil || connectResponse.value == "reject")
        raise "Handshake error" 
      end
      if (connectResponse.error_message != nil)
        raise "RPC Error: " + connectResponse.error_message 
      end
      @sentConnect = true
      
      signOn()
      retVal = logIn()
      return retVal
    end
    
    def close()
      if isConnected()
        if @sentConnect
          @sentConnect = false  # set in connect()
          @signedOn=false  # set in signOn() inside connect()
          bye = VistaRPC.new("#BYE#", RPCResponse::SINGLE_VALUE, true)
          retval = execute(bye)
          @socket.close()
          @socket = nil
          @duz = "0"
          @currentContext = nil
          return retval
        end
      end
    end
    
    def isConnected()
      return @socket != nil
    end
    
    def execute(rpc)
      retVal = executeOnce(rpc)
      if (retVal == nil && @signedOn) 
        #reconnect
        if (rpc.name == "#BYE#")
          # We're disconnecting anyway
          return nil
        end
        # attempt to log back on
        if (connect())
          if (@currentContext != nil) 
            tempcontext = @currentContext
            @currentContext = nil
            setContext(tempcontext)
          end
          retVal = executeOnce(rpc)
        end
      end
      if (retVal == nil)
        raise "Lost connection to server"
      end
      return retVal
    end

    # Call the RPC function
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  response type = one of the types in RPCResponse
    #  returns RPCResponse
    def call(rpcname, responsetype, args=nil)
      rpc = VistaRPC.new(rpcname, responsetype)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse
    end

    # Call the RPC function expecting to receive a string or SINGLE_VALUE
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  returns String
    def call_s(rpcname, args=nil)
      rpc = VistaRPC.new(rpcname, RPCResponse::SINGLE_VALUE)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse.value
    end

    # Call the RPC function expecting to receive a array of string ARRAY
    #  rpcname = String containing name of RPC
    #  args = Array of arguments 0-based
    #  returns Array
    def call_a(rpcname, args=nil)
      rpc = VistaRPC.new(rpcname, RPCResponse::ARRAY)
      if !args.nil?
        rpc.params = args
      end
      rpcresponse = execute(rpc)
      return rpcresponse.value
    end

    
    def setContext(context)
      if (context == @currentContext)
        warn "context is already set to " + context + "..."
        return
      end
      if (@currentContext != nil) 
        warn "changing context from " + @currentContext + " to " + context
      end
      
      puts "Setting context to: " + context
      xwbCreateContext = VistaRPC.new("XWB CREATE CONTEXT", RPCResponse::SINGLE_VALUE)
      encryptedContext = xwbCreateContext.encrypt(context)
      xwbCreateContext.params[0] = encryptedContext
      response = execute(xwbCreateContext)
      if (response == nil || response.error_message != nil)
        raise "XWB CREATE CONTEXT failed: " + response.error_message
      end
      @currentContext = context
      return response
    end
    
    
    def getDUZ
      return @duz
    end
    
    
    
    private  
    
    def signOn() 
      signonResponse = execute(VistaRPC.new("XUS SIGNON SETUP", RPCResponse::ARRAY))
      if (signonResponse == nil || signonResponse.error_message != nil)
        raise "XUS SIGNON SETUP failed"
      end
      @signedOn = true
    end
    
{'fraction_non_alphanumeric': 0.08617795187465026, 'fraction_numerical': 0.005502704719268793, 'mean_word_length': 2.1135307781649244, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, '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': '5886310', 'n_tokens_mistral': 3367, 'n_tokens_neox': 3303, 'n_words': 878}