rpc.h #1

  • //
  • guest/
  • perforce_software/
  • p4/
  • 2014-1/
  • rpc/
  • rpc.h
  • View
  • Commits
  • Open Download .zip Download (10 KB)
/*
 * Copyright 1995, 1996 Perforce Software.  All rights reserved.
 *
 * This file is part of Perforce - the FAST SCM System.
 */

/*
 * Rpc.h - remote procedure service
 *
 * Classes Defined:
 *
 *	Rpc - an actual Rpc association
 *	RpcService - a send/receive remote procedure service endpoint
 *
 * Public Methods:
 *
 *	RpcService::RpcService() - provide IPC address for Connect
 *	RpcService::Dispatcher() - add functions to call on received RPC
 *	RpcService::Listen() - convert RpcService from client to server
 *	RpcService::ListenCheck() - see if we can listen on the given address
 *	RpcService::CheaterCheck() - check if supplied port is the licensed one
 *	RpcService::Unlisten() - cancel Listen() (still a server, tho)
 *	RpcService::SetProtocol() - set a protocol capability
 *	RpcService::IsSingle() - is this protocol single threading?
 *	RpcService::SetBreak() - keepalive callback for user interrupt.
 *	RpcService::GetHost() - manipulate a peer address for MITM crypto
 *
 *	Rpc::Connect() - create an RPC to/from the named peer
 *	Rpc::Disconnect() - tear down RPC
 *	Rpc::GetAddress() - return address of this endpoint
 *	Rpc::GetPeerAddress() - return address of the peer
 *
 *	Rpc::MakeVar() - return StrBuf for variable contents
 *	Rpc::SetVar() - allocate variable and set contents
 *	Rpc::SetVarV() - set variable using var=value syntax
 *	Rpc::SetArgv() - copy char **argv into as variable settings
 *	Rpc::Invoke() - send buffer full of variables to peer
 *	Rpc::Release() - wrapper to call Invoke() with 'release' op
 *	
 *	Rpc::Dispatch() - dispatch uncoming RPC's until 'release' received
 *	Rpc::GetVar() - get a variable from receive buffer
 *	Rpc::CopyVars() - copy all variables from receive to send buffer
 *
 *	Rpc::InvokeDuplex() - Invoke(), but poll for same data sent back
 *	Rpc::InvokeDuplexRev() - Invoke(), but poll for lots of data sent back
 *	Rpc::FlushDuplex() - flush responses to all Invoke() calls
 *
 *	Rpc::Dropped() - connection is no longer serviceable
 *	Rpc::IoError() - pointer to error struct describing dropped connection
 *
 *	Rpc::StartCompression() -- initiate full link compression
 *
 * Methods for rpcservice routines:
 *
 *	Rpc::GotFlushed() - note receipt of "flush" sent by InvokeDuplex()
 *	Rpc::GotReleased() - note receipt of "release" sent by Release()
 * 	Rpc::GotRecvCompress() -- turn on recv half compression
 *	Rpc::GotSendCompress() -- turn on send half compression
 *
 * Public structures:
 *
 *	RpcDispatch - a procedure name/function call mapping
 */

# ifdef OS_NT
// On Windows, one of the OpenSSL includes in rpc.cc brings in a
// system header that includes its own <rpc.h>, so we need to
// guard against that here.
# pragma once
# endif

class Rpc;
class RpcRecvBuffer;
class RpcSendBuffer;
class RpcTransport;
class RpcDispatcher;
class NetEndPoint;
class KeepAlive;
class RpcService;
class RpcForward;
class Timer;

typedef void (*RpcCallback)( Rpc *, Error * );

struct RpcDispatch {
	const char	*opName;
	RpcCallback	function;
} ;

enum RPC_OPEN_TYPE { RPC_NOOPEN, RPC_LISTEN, RPC_CONNECT };

/*
 * NOTE: If you add a new RPC type to this list update the
 * matching string array (const char *RpcTypeNames[]) in rpc.cc
 */
enum RpcType {
    RPC_CLIENT = 0,
    RPC_REMOTE,
    RPC_PX,
    RPC_RH,
    RPC_BACKGROUND,
    RPC_PXCLIENT,
    RPC_RPL,
    RPC_BROKER,
    RPC_BROKER_TO_SERVER,
    RPC_RMTAUTH,
    RPC_SANDBOX,
    RPC_UNKNOWN,
    RPC_DMRPC
};

extern "C" const char *RpcTypeNames[];

/*
 * These are defined here as well as in "net/netsupport.h"
 * so that rpc clients don't need to include the net dir,
 * but they need to be in net to avoid a circular dependency.
 * The two sets of definitions must remain in sync!
 * See "net/netsupport.h" for more details.
 */
# define RAF_NAME 0x01	// get symbolic name
# define RAF_PORT 0x02	// append port number

struct RpcTrack {
	int		trackable;
	int		sendCount;
	P4INT64		sendBytes;
	int		recvCount;
	P4INT64		recvBytes;
	int		rpc_hi_mark_fwd;
	int		rpc_hi_mark_rev;
	int		sendTime;
	int		recvTime;
} ;

class RpcService {

    public:
			RpcService();
			~RpcService();

	void		SetEndpoint( const char *addr, Error *e );
	void		Dispatcher( const RpcDispatch *dispatch );
	void		SetProtocol( const char *var, const StrRef &val );
	void		SetProtocolV( const char *arg );
	void		Listen( Error *e );
	void		ListenCheck( Error *e );
	int		CheaterCheck( const char *port );
	void		Unlisten();
	int		IsSingle();
	void		GetHost( StrPtr *peerAddr, StrBuf & hostBuf, Error *e );
	virtual void	GetMyFingerprint(StrBuf &value);
	void		GetExpiration( StrBuf &buf );

	// Set Protocol varieties

	void		SetProtocol( const char *var )
			{ SetProtocol( var, StrRef::Null() ); }
			
	void		SetProtocol( const char *var, const char *val )
			{ SetProtocol( var, StrRef( val ) ); }

	void		SetProtocol( const char *var, int val )
			{ SetProtocol( var, StrNum( val ) ); }

    friend class Rpc;		// needs the following privates
#ifdef USE_ZK
    friend class RpcZksClient;  // needs access to endpoint
#endif /* USE_ZK */

    private:

	RPC_OPEN_TYPE	openFlag;		// inbound or outbound

	RpcDispatcher	*dispatcher;		// incoming function dispatch
	NetEndPoint	*endPoint;		// transport's endpoint
	RpcSendBuffer	*protoSendBuffer;	// proto/values to send
} ;

class Rpc : public StrDict {

    public:
			Rpc( RpcService *s );
	virtual		~Rpc();

	void		Unlisten() { service->Unlisten(); }
	int		IsSingle() { return service->IsSingle(); }

	void		Connect( Error *e );
	void		Disconnect();
	void		DoHandshake( Error *e );
	void		CheckKnownHost( Error *e, const StrRef & trustfile );
	void    	ClientMismatch( Error *e );
	void            GetEncryptionType( StrBuf &value );
	void            GetPeerFingerprint(StrBuf &value);
	void            GetExpiration(StrBuf &value);

	StrPtr *	GetAddress( int raf_flags );
	StrPtr *	GetPeerAddress( int raf_flags = 0 );
	int		GetPortNum();
	bool		IsSockIPv6();
	KeepAlive	*GetKeepAlive();
	void		SetBreak( KeepAlive *breakCallback );
	void		SetProtocolDynamic( const char *var, const StrRef &val );
	void		ClearProtocolDynamic( const char *var );

	// Invoke/Dispatch

	virtual void	Invoke( const char *opName );
	void		InvokeDuplex( const char *opName );
	void		InvokeDuplexRev( const char *opName );
	void		InvokeOver( const char *opName );
	void		FlushDuplex();

	void		Release();
	void		ReleaseFinal();

	enum DispatchFlag { DfComplete, DfDuplex, DfFlush, DfOver };

	void		Dispatch( DispatchFlag f, RpcDispatcher *d );

	void		Dispatch() { 
			    Dispatch( DfComplete, service->dispatcher ); 
			}

	void		DispatchFlush() { 
			    Dispatch( DfFlush, service->dispatcher ); 
			}

	// Variable setting/getting
	// The V* are virtuals of StrDict

	StrBuf *	MakeVar( const char *var );
	void		VSetVar( const StrPtr &var, const StrPtr &val );
	StrPtr *	VGetVar( const StrPtr &var );
	int		VGetVarX( int x, StrRef &var, StrRef &val );
	void		VClear();
	void		VRemoveVar( const StrPtr &var );

	virtual int	GetArgc();
	virtual StrPtr *GetArgv();
	StrPtr *	GetArgi( int i, Error *e );
	StrPtr *	GetArgi( int i );

	void		CopyVars();

	// fake out message being sent as being just received
	void		Loopback( Error * );

	// Connection is still alive in spite of send errors if we are
	// expecting acks from earlier sends (i.e. duplexing).

	int		Dropped() { 
			    return re.Test() || !duplexFrecv && se.Test(); 
			}

	Error *		IoError() { return se.Test() ? &se : &re; }
	bool		ReadErrors() { return re.Test(); }
	int		SendErrors() { return se.Test(); }

	void		StartCompression( Error *e );

	void		SetHiMark( int sndbuf, int rcvbuf );

	int		protocolServer;		// 'server'/'server2' protocol

    public:

	// Not really public, but needed by the rpcservice.cc routines.

	void		GotFlushed();
	void		GotReleased() { endDispatch = 1; }
	void		GotSendCompressed( Error *e );
	void		GotRecvCompressed( Error *e );
	int		InvokeOne( const char *opName );

	void		FlushTransport();
	int		GetRecvBuffering() ;


    public:
	// for proxying

	void		SetForwarder( RpcForward *f ) { forward = f; }
	RpcForward *	GetForwarder() { return forward; }

	void		DispatchOne( RpcDispatcher *dispatcher );
	void		DispatchOne() { DispatchOne( service->dispatcher ); }
	int		DispatchDepth() { return dispatchDepth; }

	int		recvBuffering; // For flush1 handling in rpcfwd,pxclient

    public:
    
    	// for performance tracking

	void		TrackStart();
	int		Trackable( int level );
	void		TrackReport( int level, StrBuf &out );
	void		GetTrack( int level, RpcTrack *track );
	void		ForceGetTrack( RpcTrack *track );

    protected:

	virtual RpcType	GetRpcType() { return RPC_UNKNOWN; };

    private:

	RpcService	*service;
	RpcTransport	*transport;		// send/receive transport
	RpcForward	*forward;		// for proxying

	RpcSendBuffer	*sendBuffer;		// var/values to send
	RpcRecvBuffer	*recvBuffer;		// var/values received 
	StrDict		*protoDynamic;

	int		duplexFsend;		// bytes InvokeDuplex sent
	int		duplexFrecv;		// and data received back...
	int		duplexRsend;		// bytes InvokeDuplexRev sent 
	int		duplexRrecv;		// and data received back...

	int		dispatchDepth;		// count nested calls
	int		endDispatch;		// cause Dispatch() to return

	int		protocolSent;		// protoSendBuffer sent

	Error		se;			// send errors
	Error		re;			// recv errors
	Error		ue;			// dispatch errors

	int		rpc_lo_mark;
	int		rpc_hi_mark_fwd;	// InvokeDuplex()
	int		rpc_hi_mark_rev;	// InvokeDuplexRev()

	int		sendCount;		// performance tracking
	P4INT64		sendBytes;
	int		recvCount;
	P4INT64		recvBytes;
	int		sendTime;
	int		recvTime;

	Timer		*timer;
} ;

enum RpcUtilityType {
	Generate_Uninitialized = 0,
	Generate_Credentials,
	Generate_Fingerprint
};

class RpcUtility
{
public:

    void Generate(RpcUtilityType type, Error *e );
};
# Change User Description Committed
#1 15902 Matt Attaway A second renaming that I will not obliterate as a badge of shame
//guest/perforce_software/p4/2014_1/rpc/rpc.h
#1 15901 Matt Attaway Clean up code to fit modern Workshop naming standards
//guest/perforce_software/p4/2014.1/rpc/rpc.h
#1 12188 Matt Attaway Move 'main' p4 into a release specific directory in prep for new releases
//guest/perforce_software/p4/rpc/rpc.h
#1 9129 Matt Attaway Initial commit of the 2014.1 p4/p4api source code