⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpcifclient.cpp

📁 VXWORKS源代码
💻 CPP
字号:
/* RpcIfClient -- Encapsulates Remote Method Invocations *//* Copyright (c) 1999 Wind River Systems, Inc. *//*modification history--------------------01t,17dec01,nel  Add include symbol for diab.01s,10oct01,dbs  add AddKnownInterface() method to IOrpcClientChannel01r,02oct01,nel  Move debug hooks into SockStream class.01q,26sep01,nel  Modify hooks to pass IP and Port.01p,21aug01,nel  Add hooks to optionally display decoded packet traffic.01o,24jul01,dbs  take fix from SPR#6823401n,13jul01,dbs  add pres ctx ID to request pdu01m,29mar01,nel  SPR#35873. Add extra code to hold the client side context IDs                 for bound interfaces and modify the bindToIID method to send                 alter context for already bound interfaces rather than always                 sending bind.01l,20jun00,dbs  fix client BIND/ALTER_CONTEXT handling01k,24may00,dbs  add fault diagnostics01j,04may00,nel  Add log output for client side requests.01i,20aug99,aim  return SERVER_NOT_AVAILABLE when connect fails01h,30jul99,aim  added S_INFO messages01g,22jul99,dbs  enforce serialisation on method-calls01f,19jul99,dbs  add client-side authn support01e,13jul99,aim  syslog api changes01d,06jul99,aim  new ctors01c,02jul99,aim  added RpcInvocation functionality01b,08jun99,aim  rework01a,05jun99,aim  created*/#include "RpcIfClient.h"#include "Reactor.h"#include "Syslog.h"#include "RpcPduFactory.h"#include "comErr.h"#include "SCM.h"#include "private/comSysLib.h"#include "private/DebugHooks.h"/* Include symbol for diab */extern "C" int include_vxdcom_RpcIfClient (void)    {    return 0;    }RpcIfClient::CALL_IDRpcIfClient::s_callId = 0;RpcIfClient::~RpcIfClient ()    {    TRACE_CALL;    // Remove records of this channel from NTLM authn service    NTLMSSP* ssp = SCM::ssp ();    if (ssp)	ssp->channelRemove (channelId ());    }RpcIfClient::RpcIfClient (const INETSockAddr& peerAddr)  : m_peerAddr (peerAddr),    m_boundIIDs (),    m_stream (),    m_connector (),    m_connected (false),    m_dwRefCount (0)    {    }RpcIfClient::RpcIfClient (const RpcStringBinding& binding)  : m_peerAddr (),    m_boundIIDs (),    m_stream (),    m_connector (),    m_connected (false),    m_dwRefCount (0)    {    m_peerAddr = INETSockAddr (binding.ipAddress (),			       binding.portNumber ());    }int RpcIfClient::connect (const INETSockAddr& peerAddr, HRESULT& hresult)    {    TRACE_CALL;    hresult = S_OK;    if (m_connected)	return 0;    if (m_connector.connect (stream (), peerAddr) < 0)	{	S_ERR (LOG_RPC | LOG_ERRNO, "cannot connect to " << peerAddr);	hresult = MAKE_HRESULT (SEVERITY_ERROR,				FACILITY_WIN32,				RPC_S_SERVER_UNAVAILABLE);	}    else	{	INETSockAddr pa;		if (stream().peerAddrGet (pa) < 0)	    {	    hresult = MAKE_HRESULT (SEVERITY_ERROR,				    FACILITY_WIN32,				    RPC_S_SERVER_UNAVAILABLE);	    m_connected = false;	    stream().close ();	    }	else	    {	    S_DEBUG (LOG_RPC, "connected to " << pa);	    hresult = S_OK;	    m_connected = true;	    // Add this channel to SSP's records so we can perform	    // authentication in future if required...	    NTLMSSP* pssp = SCM::ssp ();	    if (pssp)		pssp->channelAdd (channelId ());	    }	}    return SUCCEEDED (hresult) ? 0 : -1;    }int RpcIfClient::connect ()    {    TRACE_CALL;    HRESULT hr;    connect (m_peerAddr, hr);    return hr;    }SockStream& RpcIfClient::stream ()    {    return m_stream;    }bool RpcIfClient::connected () const    {    return m_connected;    }int RpcIfClient::sendPdu (RpcPdu& pdu)    {    size_t len;    char *buf = 0;    int result = -1;    if (pdu.makeReplyBuffer (buf, len) < 0)        stream().close ();    else 	{	stream ().processDebugOutput (pRpcClientOutput, (BYTE *)buf, (DWORD)len);	if (stream().send (buf, len) == len)	    {	    result = 0;	    S_DEBUG (LOG_RPC, "sendPdu: " << pdu);	    }	}    if (buf != NULL)	{	delete [] buf;	}    return result;    }RpcIfClient::CALL_ID RpcIfClient::nextCallId ()    {    return ++s_callId;    }int RpcIfClient::recvPdu (RpcPdu& pdu)    {    TRACE_CALL;    const int buflen = 1024;    DWORD totalLen = 0;    char buf[buflen];    while (1)	{	ssize_t n = stream().recv (buf, buflen);	// no data or the peer closed the connection	if (n <= 0)	    return -1;	totalLen += (DWORD)n;	pdu.append (buf, n);	if (pdu.complete ())	    {	    stream ().processDebugOutput (pRpcClientInput, (BYTE *)buf, (DWORD)buflen);	    S_DEBUG (LOG_RPC, "recvPdu: " << pdu);	    return 0;	    }	}    return -1;    }int RpcIfClient::channelId () const    {    return reinterpret_cast<int> (this);    }////////////////////////////////////////////////////////////////////////////// RpcIfClient::interfaceIsBound - is the given IID already bound?//// This method tests if the interface ID <iid> is already bound,// i.e. we have at some point in the past, sent a BIND packet and// successfully allocated a presentation-context ID for it.//// If we have, then it returns 'true' and sets the value of// <presCtxId> appropriately. If not, then it returns 'false' and a// new presentation context ID will need to be generated.//bool RpcIfClient::interfaceIsBound (const IID& iid, USHORT& presCtxId)    {    // Search through the vector and if the interface ID is in the    // table, then set the presentation-context ID value and return    // true. If we reach the end of the table, and the IID is not    // present, return false (and do not set 'presCtxId' at all).    InterfaceVec::iterator i;    for (i = m_boundIIDs.begin (); i != m_boundIIDs.end (); i++)    	{    	if ((*i) == iid) 	    {	    presCtxId = i - m_boundIIDs.begin ();	    return true;	    }	}    return false;    }////////////////////////////////////////////////////////////////////////////// RpcIfClient::bindToIID - bind this channel to the given IID//int RpcIfClient::bindToIID    (    const IID&	iid,    const GUID*	objid,    HRESULT&	hresult,    USHORT&     presCtxId    )    {    // Check if we are already bound to this IID. If so, we can use    // that pres-ctx ID directly, and don't need to send either BIND    // or ALTER_CONTEXT first...    bool alreadyBound = interfaceIsBound (iid, presCtxId);    // If we have already bound to this IID, then we can possibly    // short-cut if its also the current IID (i.e. the last one we    // sent a BIND or ALTER_CONTEXT for)...    if (alreadyBound)        {        // If its the current IID, take the shortcut -- the        // presentation context ID will be set to the right value        // already...        if (iid == m_currentIID)            {            hresult = S_OK;            return 0;            }        // If its not the current IID, we need to fall through and do        // an ALTER_CONTEXT anyway...        }    else        {        // We need to generate a new presentation context ID...    	presCtxId = m_boundIIDs.size ();        }        // Locate default SSP for this machine    NTLMSSP* pssp = SCM::ssp ();    // Create BIND (or ALTER_CONTEXT) packet...    ULONG assocGroupId = 0;    RpcPdu bindPdu;    RpcPduFactory::formatBindPdu (bindPdu,                                   iid,                                   nextCallId (),                                   assocGroupId,                                   alreadyBound,                                  presCtxId);    // Add any required auth-trailer...    hresult = pssp->clientAuthnRequestAdd (channelId (), bindPdu);    if (FAILED (hresult))	return -1;    // Send the PDU to the server...    if (sendPdu (bindPdu) < 0)	{	hresult = RPC_E_DISCONNECTED;	return -1;	}    // Receive reply (should be BIND-ACK or BIND-NAK)...    RpcPdu reply;    if (recvPdu (reply) < 0)	{	hresult = RPC_E_DISCONNECTED;	return -1;	}    // What kind of response did we get?    if (reply.isBindAck ())	{	// Process BIND-ACK packet, we may require to send an AUTH3 to	// complete the authentication process. First record the bound	// IID value...        AddKnownInterface (iid);	m_currentIID = iid;		// Now process the rest of the authentication steps...	RpcPdu auth3Pdu;	bool sendAuth3 = false;	RpcPduFactory::formatAuth3Pdu (auth3Pdu, reply.callId ());	// Generate the AUTH3 trailer, the NTLM object will decide	// whether we need to send it or not...	hresult = pssp->clientAuthnResponse (channelId (),					     reply,					     &sendAuth3,					     auth3Pdu);	if (SUCCEEDED (hresult) && sendAuth3)	    {	    if (sendPdu (auth3Pdu) < 0)		hresult = RPC_E_DISCONNECTED;	    }	}    else if (reply.isAlterContextResp ())	{        // We got an ALTER_CONTEXT_RESPONSE so just set the current        // IID to this IID...	m_currentIID = iid;	}    else if (reply.isBindNak ())	{        // We got a BIND_NAK, that means the server end doesn't        // support the IID on this channel...	hresult = MAKE_HRESULT (SEVERITY_ERROR,				FACILITY_RPC,				RPC_S_INTERFACE_NOT_FOUND);	}    else        {        // Any other kind of packet is not what we can deal with...	hresult = RPC_E_UNEXPECTED;        }        return SUCCEEDED (hresult) ? 0 : -1;    }////////////////////////////////////////////////////////////////////////////// RpcIfClient::sendMethod - send a REQUEST and get back a RESPONSE////int RpcIfClient::sendMethod    (    RpcPdu&	pdu,    RpcPdu&	resultPdu,    HRESULT&	hresult    )    {    // Send the REQUEST packet...    if (sendPdu (pdu) < 0)	{	hresult = RPC_E_DISCONNECTED;	return -1;	}    // Await the response...    if (recvPdu (resultPdu) < 0)	{	hresult = RPC_E_DISCONNECTED;	return -1;	}    // Is it the right kind of packet?    if (resultPdu.isResponse ())	hresult = S_OK;    else if (resultPdu.isFault ())	{	S_ERR (LOG_RPC, "TxREQUEST:" << pdu);	S_ERR (LOG_RPC, "RxFAULT:" << resultPdu);	hresult = resultPdu.fault().status;	}    else	hresult = RPC_E_UNEXPECTED;    return SUCCEEDED (hresult) ? 0 : -1;    }////////////////////////////////////////////////////////////////////////////// RpcIfClient::InvokeMethod - invoke a method on a remote machine//HRESULT RpcIfClient::InvokeMethod    (    const IID&	        iid,    const GUID*	        objid,    USHORT              opnum,    const MSHL_BUFFER*  pMshlBufIn,    MSHL_BUFFER*        pMshlBufOut    )    {    USHORT presCtxId;    HRESULT hr;        // Wrap each method-invocation up in a critical-section, in case    // this object is being shared between tasks...    VxCritSec cs (m_mutex);    // Make sure we are connected to the remote server...    if (connect (m_peerAddr, hr) < 0)        return hr;                                 // Bind the channel to the right IID...    if (bindToIID (iid, objid, hr, presCtxId) < 0)	return hr;    // Make a REQUEST PDU ready to send...    RpcPdu pdu;        RpcPduFactory::formatRequestPdu (pdu,                                     nextCallId (),                                     opnum,                                     objid,                                     presCtxId);        pdu.stubDataAppend (pMshlBufIn->buf, pMshlBufIn->len);    // Add any authentication data necessary...    NTLMSSP* pssp = SCM::ssp ();    if (pssp)	pssp->clientAuthn (channelId (), pdu);    // Call the actual method, getting the resulting RESPONSE PDU back    // containing the result stub-data...    RpcPdu resultPdu;        if (sendMethod (pdu, resultPdu, hr) < 0)        return hr;    // Copy the returned stub-data into the MSHL_BUFFER...    AllocBuffer (pMshlBufOut, resultPdu.stubDataLen ());    memcpy (pMshlBufOut->buf, resultPdu.stubData (), resultPdu.stubDataLen ());    pMshlBufOut->drep = resultPdu.drep ();        return S_OK;    }////////////////////////////////////////////////////////////////////////////// AllocBuffer - allocate a buffer for this channel//HRESULT RpcIfClient::AllocBuffer    (    MSHL_BUFFER*        pBuf,    DWORD               nBytes    )    {    void* pv = comSysAlloc (nBytes);    if (! pv)        return E_OUTOFMEMORY;    pBuf->buf = (byte*) pv;    pBuf->len = nBytes;    return S_OK;    }////////////////////////////////////////////////////////////////////////////// FreeBuffer - free a previously-allocated channel buffer//HRESULT RpcIfClient::FreeBuffer    (    MSHL_BUFFER*        pBuf    )    {    comSysFree (pBuf->buf);    pBuf->buf = 0;    pBuf->len = 0;    return S_OK;    }////////////////////////////////////////////////////////////////////////////ULONG RpcIfClient::AddRef ()    {    return comSafeInc (&m_dwRefCount);    }////////////////////////////////////////////////////////////////////////////ULONG RpcIfClient::Release ()    {    DWORD n = comSafeDec (&m_dwRefCount);    if (n == 0)	delete this;    return n;    }////////////////////////////////////////////////////////////////////////////HRESULT RpcIfClient::QueryInterface (REFIID riid, void** ppv)    {    if ((riid == IID_IOrpcClientChannel) ||        (riid == IID_IUnknown))        {        *ppv = this;        AddRef ();        return S_OK;        }    return E_NOINTERFACE;    }////////////////////////////////////////////////////////////////////////////HRESULT RpcIfClient::AddKnownInterface (REFIID iid)    {    // Add it to the list of 'bound' IIDs...    m_boundIIDs.push_back (iid);    return S_OK;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -