Class RpcConnection

  • Direct Known Subclasses:
    RpcStreamConnection

    public abstract class RpcConnection
    extends java.lang.Object
    Main abstract class for sending and receiving packets (etc.) to and from the Perforce server. There is currently only one known subclass, RpcStreamConnection, which implements the connection using java.io streams on top of sockets.

    Note that charset conversion should never be necessary on connections to non-Unicode servers, as any bytes in the incoming stream that are marked as "text" should be interpreted as ASCII (seven or eight bits). Unfortunately, in Java land, there's no such thing as non-interpreted bytes -- bytes are converted to strings according to *some* charset or other (and Java uses UTF-16 as the native encoding for strings under the covers). This explains why we always do a conversion below -- if we didn't use an explicit "from" charset, the current JVM's charset would be used, which would quite probably be wrong. Similar observations apply for conversions in the other direction -- all conversions must be with an explicit charset in case the JVM's charset isn't the one we actually need.

    Note that, in general, we "know" that the Perforce server on the other end of this connection is -- or should be -- a Unicode server by the fact that the incoming clientCharset is not null. This probably isn't infallible, but it's supposed to be true, so we use it as a proxy for IServer.supportsUnicode().

    See http://computer.perforce.com/newwiki/index.php?title=P4Java_and_Charset_Support for a detailed discussion of P4Java and server charset issues...

    • Field Detail

      • UNICODE_SERVER_CHARSET

        public static final java.nio.charset.Charset UNICODE_SERVER_CHARSET
        The charset used internally by a Perforce Unicode-enabled server. If a server is Unicode-enabled, then every non-binary RPC packet field is sent to and received from the Perforce server in this charset.

        Do not change this unless you want all hell to break loose.

      • UNICODE_SERVER_CHARSET_NAME

        public static final java.lang.String UNICODE_SERVER_CHARSET_NAME
        The name of the assumed Unicode server internal charset. Do not change this either.
      • NON_UNICODE_SERVER_CHARSET

        public static final java.nio.charset.Charset NON_UNICODE_SERVER_CHARSET
        Charset assumed when the server is non in Unicode mode. Do not change this field, either, unless you want problems...
      • NON_UNICODE_SERVER_CHARSET_NAME

        public static final java.lang.String NON_UNICODE_SERVER_CHARSET_NAME
        The name of the assumed non-Unicode server charset. Do not change this either.
      • UNKNOWN_SERVER_HOST

        protected static final java.lang.String UNKNOWN_SERVER_HOST
      • props

        protected java.util.Properties props
      • hostIp

        protected java.lang.String hostIp
      • ourIp

        protected java.lang.String ourIp
      • hostName

        protected java.lang.String hostName
      • hostPort

        protected int hostPort
      • ourPort

        protected int ourPort
      • usingCompression

        protected boolean usingCompression
      • unicodeServer

        protected boolean unicodeServer
      • secure

        protected boolean secure
      • fingerprint

        protected java.lang.String fingerprint
      • trusted

        protected boolean trusted
      • serverCerts

        protected java.security.cert.Certificate[] serverCerts
      • selfSigned

        protected boolean selfSigned
    • Constructor Detail

      • RpcConnection

        public RpcConnection​(java.lang.String serverHost,
                             int serverPort,
                             java.util.Properties props,
                             ServerStats stats,
                             P4Charset p4Charset)
                      throws ConnectionException
        Create a Perforce RPC connection to a given host and port number pair.

        This method will also implicitly connect to the server. Note that new connections are never using connection compression -- this has to come as an explicit command from the server after the connection has been established.

        Parameters:
        serverHost - non-null Perforce server host name or IP address.
        serverPort - Perforce server host port number.
        props - if not null, use the Properties for any connection- or implementation-specific values (such as buffer sizes, etc.).
        stats - if not null, attempt to fill in these connection stats appropriately.
        p4Charset - if non-null, sets the connection's idea of what the current client charset is. If null, CharsetDefs.DEFAULT is used.
        Throws:
        ConnectionException - if any user-reportable error occurred under the covers.
      • RpcConnection

        public RpcConnection​(@Nonnull
                             java.lang.String serverHost,
                             int serverPort,
                             java.util.Properties props,
                             ServerStats stats,
                             P4Charset p4Charset,
                             boolean secure)
                      throws ConnectionException
        Create a Perforce RPC connection to a given host and port number pair.

        This method will also implicitly connect to the server. Note that new connections are never using connection compression -- this has to come as an explicit command from the server after the connection has been established.

        Parameters:
        serverHost - non-null Perforce server host name or IP address.
        serverPort - Perforce server host port number.
        props - if not null, use the Properties for any connection- or implementation-specific values (such as buffer sizes, etc.).
        stats - if not null, attempt to fill in these connection stats appropriately.
        p4Charset - if non-null, sets the connection's idea of what the current client charset is. If null, CharsetDefs.DEFAULT is used.
        secure - indicate whether the connection is secure (SSL) or not.
        Throws:
        ConnectionException - if any user-reportable error occurred under the covers.
    • Method Detail

      • getServerCerts

        public java.security.cert.X509Certificate[] getServerCerts()
      • isSelfSigned

        public boolean isSelfSigned()
      • getServerIpPort

        public abstract java.lang.String getServerIpPort()
        Get the server's IP and port used for the RPC connection.
        Returns:
        - possibly null server IP and port
      • getServerHostNamePort

        public abstract java.lang.String getServerHostNamePort()
      • getClientIpPort

        public abstract java.lang.String getClientIpPort()
        Get the client's IP and port used for the RPC connection.
        Returns:
        - possibly null client IP and port
      • disconnect

        public abstract void disconnect​(RpcPacketDispatcher dispatcher)
                                 throws ConnectionException
        Disconnect this server. Assumes the connection is quiescent -- no further sends or receives will be possible after this call, and only the output stream is flushed (no attempt is made to look at anything still on the wire coming in to the socket).
        Parameters:
        dispatcher - dispatcher
        Throws:
        ConnectionException - on error
      • putRpcPacket

        public abstract long putRpcPacket​(RpcPacket rpcPacket)
                                   throws ConnectionException
        Put a Perforce RPC packet onto the output stream. The implementing method must make the appropriate charset translations and any other client- or server- (or whatever-) specific processing on the passed-in packet.

        Returns the number of bytes actually sent to the Perforce server, which may not bear any relationship at all to the size of the passed-in packet.

        Parameters:
        rpcPacket - rpcPacket
        Returns:
        number of bytes
        Throws:
        ConnectionException - on error
      • putRpcPackets

        public abstract long putRpcPackets​(RpcPacket[] rpcPackets)
                                    throws ConnectionException
        Put an array of RPC packets. A convenience method wrapping putRpcPacket(packet) in the obvious way.
        Parameters:
        rpcPackets - rpcPackets
        Returns:
        number of bytes
        Throws:
        ConnectionException - on error
      • getRpcPacket

        public abstract RpcPacket getRpcPacket()
                                        throws ConnectionException
        Get the next RPC packet from the receive queue. The implementing method must make the appropriate charset translations and any other client- or server- (or whatever-) specific processing on the packet returned from this method by the time it's returned.

        Will wait until either a timeout occurs (if the stream's been set up appropriately), the underlying stream returns EOF or error, or we get a complete packet.

        Returns:
        RpcPacket
        Throws:
        ConnectionException - on error
      • getSystemSendBufferSize

        public abstract int getSystemSendBufferSize()
        Return the system (i.e. underlying implementation) send buffer size.
        Returns:
        size
      • getSystemRecvBufferSize

        public abstract int getSystemRecvBufferSize()
        Return the system (i.e. underlying implementation) receive buffer size.
        Returns:
        size
      • marshalPacketField

        public byte[] marshalPacketField​(java.lang.String key,
                                         java.lang.Object value)
        Marshal a packet field into a key value byte array pair. This must respect the relevant charset settings, which can be a little counter-intuitive or confusing.
        Parameters:
        key - key
        value - value
        Returns:
        bytes
      • marshalPacketValue

        protected byte[] marshalPacketValue​(java.lang.Object value)
        Marshal a packet field value onto a byte array and return that array.

        For strings and similar types (e.g. StringBuilder, StringBuffer), we may need to do a translation to the server charset (normally UTF-8) before enbyteifying the underlying value. Other field types are sent as-is, and are assumed to have been encoded properly upstream (and are almost always just file contents).

        Note: if the value object passed in is a ByteBuffer, it must have been flipped ready for use; this method will (of course) have predictable side effects on that ByteBuffer.

        Parameters:
        value - value
        Returns:
        bytes
      • useConnectionCompression

        public void useConnectionCompression()
                                      throws ConnectionException
        If called, will set this connection to use (GZIP) compression for all traffic on this connection from this point on. Can not be turned back off again. See the main P4 help documentation (and C++ API code) for "client compression" (etc.) for details.
        Throws:
        ConnectionException - on error
      • getNormalizedBytes

        protected byte[] getNormalizedBytes​(java.lang.String str)
        Encode the passed-in string properly for the server. If the server is Unicode-enabled, this usually means converting to UTF-8 encoding for the stream. This can be a very CPU-intensive process...

        FIXME: use proper encoding / decoding with error handling -- HR.

        Parameters:
        str - str
        Returns:
        - normalized string
      • getNormalizedString

        protected java.lang.String getNormalizedString​(byte[] bytes)
        Decode the passed-in bytes from the server into a suitable string. In general, bytes from the server will be in ASCII (non-Unicode servers) or UTF-8 (Unicode servers), but there are exceptions.

        FIXME: use proper encoding / decoding with error handling -- HR.

        Parameters:
        bytes - bytes
        Returns:
        - normalized string
      • isUsingCompression

        public boolean isUsingCompression()
      • getProps

        public java.util.Properties getProps()
      • setProps

        public void setProps​(java.util.Properties props)
      • getClientCharset

        public java.nio.charset.Charset getClientCharset()
      • getP4Charset

        public P4Charset getP4Charset()
      • setClientCharset

        public void setClientCharset​(P4Charset p4Charset)
      • setStats

        public void setStats​(ServerStats stats)
      • getHostIp

        public java.lang.String getHostIp()
      • setHostIp

        public void setHostIp​(java.lang.String hostIp)
      • getHostName

        public java.lang.String getHostName()
      • setHostName

        public void setHostName​(java.lang.String hostName)
      • getHostPort

        public int getHostPort()
      • setHostPort

        public void setHostPort​(int hostPort)
      • setUsingCompression

        public void setUsingCompression​(boolean usingCompression)
      • isUnicodeServer

        public boolean isUnicodeServer()
      • setUnicodeServer

        public void setUnicodeServer​(boolean unicodeServer)
      • getFilesysUtf8bom

        public int getFilesysUtf8bom()
      • getFilesysRestrictedSymlinks

        public int getFilesysRestrictedSymlinks()
      • isSecure

        public boolean isSecure()
      • setSecure

        public void setSecure​(boolean secure)
      • getFingerprint

        public java.lang.String getFingerprint()
      • setFingerprint

        public void setFingerprint​(java.lang.String fingerprint)
      • isTrusted

        public boolean isTrusted()
      • setTrusted

        public void setTrusted​(boolean trusted)
      • getDigest

        public java.lang.String getDigest​(RpcPerforceFileType fileType,
                                          java.io.File file)