63 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"    85 static const unsigned short PORT_ANY = 0u;
    90 static int makeSocket ( 
unsigned short port, 
bool reuseAddr, 
SOCKET * pSock )
   102     if ( port != PORT_ANY ) {
   105             struct sockaddr_in ia;
   109         memset ( (
char *) &bd, 0, 
sizeof (bd) );
   110         bd.ia.sin_family = AF_INET;
   111         bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
   112         bd.ia.sin_port = htons ( port );
   113         status = bind ( sock, &bd.sa, (
int) 
sizeof(bd) );
   131     unsigned port = ntohs ( from.ia.sin_port );
   140     if ( 
int sockerrno = makeSocket ( PORT_ANY, 
false, & this->
sock ) ) {
   143             sockErrBuf, 
sizeof ( sockErrBuf ), sockerrno );
   144         fprintf ( 
stderr, 
"%s: no client sock because \"%s\"\n",
   145                 __FILE__, sockErrBuf );
   149     status = 
::connect ( this->
sock, &this->from.sa, sizeof ( this->from.sa ) );
   153             sockErrBuf, 
sizeof ( sockErrBuf ) );
   154         fprintf ( 
stderr, 
"%s: unable to connect client sock because \"%s\"\n",
   155             __FILE__, sockErrBuf );
   167     memset ( (
char *) &confirm, 
'\0', 
sizeof (confirm) );
   169     confirm.
m_available = this->from.ia.sin_addr.s_addr;
   170     status = send ( this->
sock, (
char *) &confirm,
   171                     sizeof (confirm), 0 );
   173         assert ( status == 
sizeof ( confirm ) );
   182             sockErrBuf, 
sizeof ( sockErrBuf ) );
   183         debugPrintf ( ( 
"CA Repeater: confirm req err was \"%s\"\n", sockErrBuf) );
   192     status = send ( this->
sock, (
char *) pBuf, bufSize, 0 );
   194         assert ( static_cast <unsigned> ( status ) == bufSize );
   206             debugPrintf ( (
"Client refused message %u\n", port ) );
   212             debugPrintf ( ( 
"CA Repeater: UDP send err was \"%s\"\n", sockErrBuf) );
   229 void repeaterClient::operator 
delete ( 
void * )
   236     errlogPrintf ( 
"%s:%d this compiler is confused about placement delete - memory was probably leaked",
   237         __FILE__, __LINE__ );
   240 void * repeaterClient::operator 
new ( 
size_t size,
   243     return freeList.allocate ( size );
   246 #ifdef CXX_PLACEMENT_DELETE   247 void repeaterClient::operator 
delete ( 
void *pCadaver,
   250     freeList.release ( pCadaver );
   256     return ntohs ( this->from.ia.sin_port );
   261     if ( fromIn.
sa.sa_family == this->from.sa.sa_family ) {
   262         if ( fromIn.
ia.sin_port == this->from.ia.sin_port) {
   263             if ( fromIn.
ia.sin_addr.s_addr == this->from.ia.sin_addr.s_addr ) {
   273     if ( fromIn.
sa.sa_family == this->from.sa.sa_family ) {
   274         if ( fromIn.
ia.sin_port == this->from.ia.sin_port) {
   284     int sockerrno = makeSocket ( this->
port (), 
false, & tmpSock );
   291     if ( sockerrno == 0 ) {
   298             sockErrBuf, 
sizeof ( sockErrBuf ), sockerrno );
   299         fprintf ( 
stderr, 
"CA Repeater: Bind test error \"%s\"\n",
   314     while ( ( pclient = client_list.
get () ) ) {
   315         if ( pclient->
verify () ) {
   316             theClients.
add ( *pclient );
   323     client_list.
add ( theClients );
   329 static void fanOut ( 
const osiSockAddr & from, 
const void * pMsg,
   335     while ( ( pclient = client_list.
get () ) ) {
   336         theClients.
add ( *pclient );
   343             if ( ! pclient->
verify () ) {
   344                 theClients.
remove ( *pclient );
   351     client_list.
add ( theClients );
   357 static void register_new_client ( 
osiSockAddr & from,
   360     bool newClient = 
false;
   363     if ( from.
sa.sa_family != AF_INET ) {
   372         static bool init = 
false;
   376             if ( 
int sockerrno = makeSocket ( PORT_ANY, 
true, & sock ) ) {
   379                     sockErrBuf, 
sizeof ( sockErrBuf ), sockerrno );
   380                 fprintf ( 
stderr, 
"%s: Unable to create repeater bind test socket because \"%s\"\n",
   381                     __FILE__, sockErrBuf );
   402             addr.
ia.sin_port = PORT_ANY;
   405             status = bind ( testSock, &addr.
sa, sizeof ( addr ) );
   416     while ( pclient.
valid () ) {
   424     if ( pclient.
valid () ) {
   425         pNewClient = pclient.
pointer ();
   429         if ( ! pNewClient ) {
   430             fprintf ( 
stderr, 
"%s: no memory for new client\n", __FILE__ );
   433         if ( ! pNewClient->
connect () ) {
   435             freeList.
release ( pNewClient );
   438         client_list.
add ( *pNewClient );
   443         client_list.
remove ( *pNewClient );
   445         freeList.
release ( pNewClient );
   448             debugPrintf ( ( 
"Deleted repeater client=%u (error while sending ack)\n",
   458     memset ( (
char *) &noop, 
'\0', 
sizeof ( noop ) );
   460     fanOut ( from, &noop, 
sizeof ( noop ), freeList );
   474         verifyClients ( freeList );
   500     if ( 
int sockerrno = makeSocket ( port, 
true, & sock ) ) {
   506             debugPrintf ( ( 
"CA Repeater: exiting because a repeater is already running\n" ) );
   512             sockErrBuf, 
sizeof ( sockErrBuf ), sockerrno );
   513         fprintf ( 
stderr, 
"%s: Unable to create repeater socket because \"%s\" - fatal\n",
   514             __FILE__, sockErrBuf );
   520 #ifdef IP_ADD_MEMBERSHIP   545             if(pNode->
addr.
ia.sin_family==AF_INET) {
   547                 if(top>=224 && top<=239) {
   552                     memset(&mreq, 0, 
sizeof(mreq));
   553                     mreq.imr_multiaddr = pNode->
addr.
ia.sin_addr;
   554                     mreq.imr_interface.s_addr = INADDR_ANY;
   556                     if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
   557                         (
char *) &mreq, 
sizeof(mreq)) != 0) {
   562                         errlogPrintf(
"caR: Socket mcast join to %s failed: %s\n", name, sockErrBuf );
   570     debugPrintf ( ( 
"CA Repeater: Attached and initialized\n" ) );
   575                     &from.
sa, &from_size );
   588                 sockErrBuf, 
sizeof ( sockErrBuf ) );
   589             fprintf ( 
stderr, 
"CA Repeater: unexpected UDP recv err: %s\n",
   600         if ( ( (
size_t) size) >= 
sizeof (*pMsg) ) {
   602                 register_new_client ( from, freeList );
   608                 size -= 
sizeof ( *pMsg );
   619         else if ( size == 0 ) {
   620             register_new_client ( from, freeList );
   624         fanOut ( from, pMsg, size, freeList );
 #define SOCK_ECONNREFUSED
 
LIBCA_API void epicsStdCall removeDuplicateAddresses(struct ELLLIST *pDestList, ELLLIST *pSrcList, int silent)
 
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
 
#define REPEATER_REGISTER
 
void taskwdInsert(epicsThreadId tid, TASKWDFUNC callback, void *usr)
 
#define assert(exp)
Declare that a condition should be true. 
 
LIBCA_API int epicsStdCall addAddrToChannelAccessAddressList(struct ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port, int ignoreNonDefaultPort)
 
unsigned short epicsUInt16
 
Routines to get and set EPICS environment parameters. 
 
tsDLIterConst< T > firstIter() const 
 
epicsPlacementDeleteOperator((void *, tsFreeList< repeaterClient, 0x20 > &)) private SOCKE sock)
 
unsigned short port() const 
 
#define ELLLIST_INIT
Value of an empty list. 
 
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
 
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
 
void caRepeaterThread(void *)
 
#define ellNext(PNODE)
Find the next node in list. 
 
LIBCOM_API const ENV_PARAM EPICS_CA_REPEATER_PORT
 
LIBCOM_API void epicsStdCall epicsSocketEnableAddressReuseDuringTimeWaitState(SOCKET s)
 
LIBCOM_API unsigned short epicsStdCall envGetInetPortConfigParam(const ENV_PARAM *pEnv, unsigned short defaultPort)
Get value of a port number configuration parameter. 
 
repeaterClient(const osiSockAddr &from)
 
LIBCOM_API const ENV_PARAM EPICS_CA_ADDR_LIST
 
int errlogPrintf(const char *pFormat,...)
 
LIBCOM_API const ENV_PARAM EPICS_CAS_BEACON_ADDR_LIST
 
bool identicalPort(const osiSockAddr &from)
 
#define debugPrintf(argsInParen)
 
bool sendMessage(const void *pBuf, unsigned bufSize)
 
bool identicalAddress(const osiSockAddr &from)
 
#define CA_PROTO_RSRV_IS_UP
 
void epicsSocketConvertErrorToString(char *pBuf, unsigned bufSize, int theSockError)
 
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
 
#define ellFirst(PLIST)
Find the first node in list. 
 
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)