Files
epics-base/modules/ca/src/client/virtualCircuit.h
Dirk Zimoch 36a8b51d8e CleanupWhitespace
removed spaces at end of line

replaced tabs with spaces
2020-05-20 14:48:09 -07:00

422 lines
13 KiB
C++

/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef INC_virtualCircuit_H
#define INC_virtualCircuit_H
#include "tsDLList.h"
#include "comBuf.h"
#include "caServerID.h"
#include "netiiu.h"
#include "comQueSend.h"
#include "comQueRecv.h"
#include "tcpRecvWatchdog.h"
#include "tcpSendWatchdog.h"
#include "hostNameCache.h"
#include "SearchDest.h"
#include "compilerDependencies.h"
class callbackManager;
// a modified ca header with capacity for large arrays
struct caHdrLargeArray {
ca_uint32_t m_postsize; // size of message extension
ca_uint32_t m_count; // operation data count
ca_uint32_t m_cid; // channel identifier
ca_uint32_t m_available; // protocol stub dependent
ca_uint16_t m_dataType; // operation data type
ca_uint16_t m_cmmd; // operation to be performed
};
class ipAddrToAsciiEngine;
class tcpRecvThread : private epicsThreadRunable {
public:
tcpRecvThread (
class tcpiiu & iiuIn, epicsMutex & cbMutexIn, cacContextNotify &,
const char * pName, unsigned int stackSize, unsigned int priority );
virtual ~tcpRecvThread ();
void start ();
void exitWait ();
bool exitWait ( double delay );
void interruptSocketRecv ();
void show ( unsigned level ) const;
private:
epicsThread thread;
class tcpiiu & iiu;
epicsMutex & cbMutex;
cacContextNotify & ctxNotify;
void run ();
void connect (
epicsGuard < epicsMutex > & guard );
bool validFillStatus (
epicsGuard < epicsMutex > & guard,
const statusWireIO & stat );
};
class tcpSendThread : private epicsThreadRunable {
public:
tcpSendThread (
class tcpiiu & iiuIn, const char * pName,
unsigned int stackSize, unsigned int priority );
virtual ~tcpSendThread ();
void start ();
void exitWait ();
void interruptSocketSend ();
void show ( unsigned level ) const;
private:
epicsThread thread;
class tcpiiu & iiu;
void run ();
};
class SearchDestTCP : public SearchDest {
public:
SearchDestTCP ( cac &, const osiSockAddr & );
void searchRequest ( epicsGuard < epicsMutex > & guard,
const char * pbuf, size_t len );
void show ( epicsGuard < epicsMutex > & guard, unsigned level ) const;
void setCircuit ( tcpiiu * );
void disable ();
void enable ();
private:
tcpiiu * _ptcpiiu;
cac & _cac;
const osiSockAddr _addr;
bool _active;
};
class tcpiiu :
public netiiu, public tsDLNode < tcpiiu >,
public tsSLNode < tcpiiu >, public caServerID,
private wireSendAdapter, private wireRecvAdapter {
friend void SearchDestTCP::searchRequest ( epicsGuard < epicsMutex > & guard,
const char * pbuf, size_t len );
public:
tcpiiu ( cac & cac, epicsMutex & mutualExclusion, epicsMutex & callbackControl,
cacContextNotify &, double connectionTimeout, epicsTimerQueue & timerQueue,
const osiSockAddr & addrIn, comBufMemoryManager &, unsigned minorVersion,
ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn,
SearchDestTCP * pSearchDestIn = NULL);
~tcpiiu ();
void start (
epicsGuard < epicsMutex > & );
void responsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void sendTimeoutNotify (
callbackManager & cbMgr,
epicsGuard < epicsMutex > & guard );
void receiveTimeoutNotify(
callbackManager &,
epicsGuard < epicsMutex > & );
void beaconAnomalyNotify (
epicsGuard < epicsMutex > & );
void beaconArrivalNotify (
epicsGuard < epicsMutex > & );
void probeResponseNotify (
epicsGuard < epicsMutex > & );
void flushRequest (
epicsGuard < epicsMutex > & );
unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & mutualExclusionGuard );
void flush (
epicsGuard < epicsMutex > & mutualExclusionGuard );
void show ( unsigned level ) const;
bool setEchoRequestPending (
epicsGuard < epicsMutex > & );
void requestRecvProcessPostponedFlush (
epicsGuard < epicsMutex > & );
void clearChannelRequest (
epicsGuard < epicsMutex > &,
ca_uint32_t sid, ca_uint32_t cid );
bool ca_v41_ok (
epicsGuard < epicsMutex > & ) const;
bool ca_v42_ok (
epicsGuard < epicsMutex > & ) const;
bool ca_v44_ok (
epicsGuard < epicsMutex > & ) const;
bool ca_v49_ok (
epicsGuard < epicsMutex > & ) const;
unsigned getHostName (
epicsGuard < epicsMutex > &,
char *pBuf, unsigned bufLength ) const throw ();
bool alive (
epicsGuard < epicsMutex > & ) const;
bool connecting (
epicsGuard < epicsMutex > & ) const;
bool receiveThreadIsBusy (
epicsGuard < epicsMutex > & );
osiSockAddr getNetworkAddress (
epicsGuard < epicsMutex > & ) const;
int printFormated (
epicsGuard < epicsMutex > & cbGuard,
const char *pformat, ... );
unsigned channelCount (
epicsGuard < epicsMutex > & );
void disconnectAllChannels (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, class udpiiu & );
void unlinkAllChannels (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void installChannel (
epicsGuard < epicsMutex > &, nciu & chan,
unsigned sidIn, ca_uint16_t typeIn, arrayElementCount countIn );
void uninstallChan (
epicsGuard < epicsMutex > & guard, nciu & chan );
bool connectNotify (
epicsGuard < epicsMutex > &, nciu & chan );
void searchRespNotify (
const epicsTime &, const caHdrLargeArray & );
void versionRespNotify ( const caHdrLargeArray & );
void * operator new ( size_t size,
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & ))
private:
hostNameCache hostNameCacheInstance;
tcpRecvThread recvThread;
tcpSendThread sendThread;
tcpRecvWatchdog recvDog;
tcpSendWatchdog sendDog;
comQueSend sendQue;
comQueRecv recvQue;
// nciu state field tells us which list
// protected by the callback mutex
tsDLList < nciu > createReqPend;
tsDLList < nciu > createRespPend;
tsDLList < nciu > v42ConnCallbackPend;
tsDLList < nciu > subscripReqPend;
tsDLList < nciu > connectedList;
tsDLList < nciu > unrespCircuit;
tsDLList < nciu > subscripUpdateReqPend;
caHdrLargeArray curMsg;
arrayElementCount curDataMax;
arrayElementCount curDataBytes;
comBufMemoryManager & comBufMemMgr;
cac & cacRef;
char * pCurData;
SearchDestTCP * pSearchDest;
epicsMutex & mutex;
epicsMutex & cbMutex;
unsigned minorProtocolVersion;
enum iiu_conn_state {
iiucs_connecting, // pending circuit connect
iiucs_connected, // live circuit
iiucs_clean_shutdown, // live circuit will shutdown when flush completes
iiucs_disconnected, // socket informed us of disconnect
iiucs_abort_shutdown // socket has been closed
} state;
epicsEvent sendThreadFlushEvent;
epicsEvent flushBlockEvent;
SOCKET sock;
unsigned contigRecvMsgCount;
unsigned blockingForFlush;
unsigned socketLibrarySendBufferSize;
unsigned unacknowledgedSendBytes;
unsigned channelCountTot;
bool _receiveThreadIsBusy;
bool busyStateDetected; // only modified by the recv thread
bool flowControlActive; // only modified by the send process thread
bool echoRequestPending;
bool oldMsgHeaderAvailable;
bool msgHeaderAvailable;
bool earlyFlush;
bool recvProcessPostponedFlush;
bool discardingPendingData;
bool socketHasBeenClosed;
bool unresponsiveCircuit;
bool processIncoming (
const epicsTime & currentTime, callbackManager & );
unsigned sendBytes ( const void *pBuf,
unsigned nBytesInBuf, const epicsTime & currentTime );
void recvBytes (
void * pBuf, unsigned nBytesInBuf, statusWireIO & );
const char * pHostName (
epicsGuard < epicsMutex > & ) const throw ();
double receiveWatchdogDelay (
epicsGuard < epicsMutex > & ) const;
void unresponsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void initiateCleanShutdown (
epicsGuard < epicsMutex > & );
void initiateAbortShutdown (
epicsGuard < epicsMutex > & );
void disconnectNotify (
epicsGuard < epicsMutex > & );
bool bytesArePendingInOS () const;
void decrementBlockingForFlushCount (
epicsGuard < epicsMutex > & guard );
bool isNameService () const;
// send protocol stubs
void echoRequest (
epicsGuard < epicsMutex > & );
void versionMessage (
epicsGuard < epicsMutex > &, const cacChannel::priLev & priority );
void disableFlowControlRequest (
epicsGuard < epicsMutex > & );
void enableFlowControlRequest (
epicsGuard < epicsMutex > & );
void hostNameSetRequest (
epicsGuard < epicsMutex > & );
void userNameSetRequest (
epicsGuard < epicsMutex > & );
void createChannelRequest (
nciu &, epicsGuard < epicsMutex > & );
void writeRequest (
epicsGuard < epicsMutex > &, nciu &,
unsigned type, arrayElementCount nElem, const void *pValue );
void writeNotifyRequest (
epicsGuard < epicsMutex > &, nciu &,
netWriteNotifyIO &, unsigned type,
arrayElementCount nElem, const void *pValue );
void readNotifyRequest (
epicsGuard < epicsMutex > &, nciu &,
netReadNotifyIO &, unsigned type,
arrayElementCount nElem );
void subscriptionRequest (
epicsGuard < epicsMutex > &,
nciu &, netSubscription & subscr );
void subscriptionUpdateRequest (
epicsGuard < epicsMutex > &,
nciu & chan, netSubscription & subscr );
void subscriptionCancelRequest (
epicsGuard < epicsMutex > &,
nciu & chan, netSubscription & subscr );
void flushIfRecvProcessRequested (
epicsGuard < epicsMutex > & );
bool sendThreadFlush (
epicsGuard < epicsMutex > & );
// netiiu stubs
void uninstallChanDueToSuccessfulSearchResponse (
epicsGuard < epicsMutex > &, nciu &, const class epicsTime & );
bool searchMsg (
epicsGuard < epicsMutex > &, ca_uint32_t id,
const char * pName, unsigned nameLength );
friend class tcpRecvThread;
friend class tcpSendThread;
tcpiiu ( const tcpiiu & );
tcpiiu & operator = ( const tcpiiu & );
void operator delete ( void * );
};
inline void * tcpiiu::operator new ( size_t size,
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & mgr )
{
return mgr.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void tcpiiu::operator delete ( void * pCadaver,
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & mgr )
{
mgr.release ( pCadaver );
}
#endif
inline bool tcpiiu::ca_v41_ok (
epicsGuard < epicsMutex > & ) const
{
return CA_V41 ( this->minorProtocolVersion );
}
inline bool tcpiiu::ca_v44_ok (
epicsGuard < epicsMutex > & ) const
{
return CA_V44 ( this->minorProtocolVersion );
}
inline bool tcpiiu::ca_v49_ok (
epicsGuard < epicsMutex > & ) const
{
return CA_V49 ( this->minorProtocolVersion );
}
inline bool tcpiiu::alive (
epicsGuard < epicsMutex > & ) const
{
return ( this->state == iiucs_connecting ||
this->state == iiucs_connected );
}
inline bool tcpiiu::connecting (
epicsGuard < epicsMutex > & ) const
{
return ( this->state == iiucs_connecting );
}
inline bool tcpiiu::receiveThreadIsBusy (
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
return this->_receiveThreadIsBusy;
}
inline void tcpiiu::beaconAnomalyNotify (
epicsGuard < epicsMutex > & guard )
{
//guard.assertIdenticalMutex ( this->cacRef.mutexRef () );
this->recvDog.beaconAnomalyNotify ( guard );
}
inline void tcpiiu::beaconArrivalNotify (
epicsGuard < epicsMutex > & guard )
{
//guard.assertIdenticalMutex ( this->cacRef.mutexRef () );
this->recvDog.beaconArrivalNotify ( guard );
}
inline void tcpiiu::probeResponseNotify (
epicsGuard < epicsMutex > & cbGuard )
{
this->recvDog.probeResponseNotify ( cbGuard );
}
inline bool tcpiiu::isNameService () const
{
return ( this->pSearchDest != NULL );
}
inline void SearchDestTCP::setCircuit ( tcpiiu * piiu )
{
_ptcpiiu = piiu;
}
#endif // ifdef INC_virtualCircuit_H