This is Unofficial EPICS BASE Doxygen Site
repeater.cpp File Reference
#include <string>
#include <stdexcept>
#include <stdio.h>
#include "tsDLList.h"
#include "envDefs.h"
#include "tsFreeList.h"
#include "osiWireFormat.h"
#include "taskwd.h"
#include "errlog.h"
#include "iocinf.h"
#include "caProto.h"
#include "udpiiu.h"
#include "repeaterClient.h"
#include "addrList.h"
+ Include dependency graph for repeater.cpp:

Go to the source code of this file.

Macros

#define epicsAssertAuthor   "Jeff Hill johill@lanl.gov"
 

Functions

void ca_repeater ()
 
void caRepeaterThread (void *)
 

Macro Definition Documentation

#define epicsAssertAuthor   "Jeff Hill johill@lanl.gov"

Definition at line 63 of file repeater.cpp.

Function Documentation

void ca_repeater ( void  )

Definition at line 482 of file repeater.cpp.

483 {
485  int size;
486  SOCKET sock;
487  osiSockAddr from;
488  unsigned short port;
489  char * pBuf;
490 
491  pBuf = new char [MAX_UDP_RECV];
492 
493  {
494  bool success = osiSockAttach();
495  assert ( success );
496  }
497 
499  static_cast <unsigned short> (CA_REPEATER_PORT) );
500  if ( int sockerrno = makeSocket ( port, true, & sock ) ) {
501  /*
502  * test for server was already started
503  */
504  if ( sockerrno == SOCK_EADDRINUSE ) {
505  osiSockRelease ();
506  debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
507  delete [] pBuf;
508  return;
509  }
510  char sockErrBuf[64];
512  sockErrBuf, sizeof ( sockErrBuf ), sockerrno );
513  fprintf ( stderr, "%s: Unable to create repeater socket because \"%s\" - fatal\n",
514  __FILE__, sockErrBuf );
515  osiSockRelease ();
516  delete [] pBuf;
517  return;
518  }
519 
520 #ifdef IP_ADD_MEMBERSHIP
521  /*
522  * join UDP socket to any multicast groups
523  */
524  {
525  ELLLIST casBeaconAddrList = ELLLIST_INIT;
526  ELLLIST casMergeAddrList = ELLLIST_INIT;
527 
528  /*
529  * collect user specified beacon address list;
530  * check BEACON_ADDR_LIST list first; if no result, take CA_ADDR_LIST
531  */
532  if(!addAddrToChannelAccessAddressList(&casMergeAddrList,&EPICS_CAS_BEACON_ADDR_LIST,port,0)) {
533  addAddrToChannelAccessAddressList(&casMergeAddrList,&EPICS_CA_ADDR_LIST,port,0);
534  }
535 
536  /* First clean up */
537  removeDuplicateAddresses(&casBeaconAddrList, &casMergeAddrList , 0);
538 
539  osiSockAddrNode *pNode;
540  for(pNode = (osiSockAddrNode*)ellFirst(&casBeaconAddrList);
541  pNode;
542  pNode = (osiSockAddrNode*)ellNext(&pNode->node))
543  {
544 
545  if(pNode->addr.ia.sin_family==AF_INET) {
546  epicsUInt32 top = ntohl(pNode->addr.ia.sin_addr.s_addr)>>24;
547  if(top>=224 && top<=239) {
548 
549  /* This is a multi-cast address */
550  struct ip_mreq mreq;
551 
552  memset(&mreq, 0, sizeof(mreq));
553  mreq.imr_multiaddr = pNode->addr.ia.sin_addr;
554  mreq.imr_interface.s_addr = INADDR_ANY;
555 
556  if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
557  (char *) &mreq, sizeof(mreq)) != 0) {
558  char name[40];
559  char sockErrBuf[64];
560  epicsSocketConvertErrnoToString (sockErrBuf, sizeof ( sockErrBuf ) );
561  ipAddrToDottedIP (&pNode->addr.ia, name, sizeof(name));
562  errlogPrintf("caR: Socket mcast join to %s failed: %s\n", name, sockErrBuf );
563  }
564  }
565  }
566  }
567  }
568 #endif
569 
570  debugPrintf ( ( "CA Repeater: Attached and initialized\n" ) );
571 
572  while ( true ) {
573  osiSocklen_t from_size = sizeof ( from );
574  size = recvfrom ( sock, pBuf, MAX_UDP_RECV, 0,
575  &from.sa, &from_size );
576  if ( size < 0 ) {
577  int errnoCpy = SOCKERRNO;
578  // Avoid spurious ECONNREFUSED bug in linux
579  if ( errnoCpy == SOCK_ECONNREFUSED ) {
580  continue;
581  }
582  // Avoid ECONNRESET from connected socket in windows
583  if ( errnoCpy == SOCK_ECONNRESET ) {
584  continue;
585  }
586  char sockErrBuf[64];
588  sockErrBuf, sizeof ( sockErrBuf ) );
589  fprintf ( stderr, "CA Repeater: unexpected UDP recv err: %s\n",
590  sockErrBuf );
591  continue;
592  }
593 
594  caHdr * pMsg = ( caHdr * ) pBuf;
595 
596  /*
597  * both zero length message and a registration message
598  * will register a new client
599  */
600  if ( ( (size_t) size) >= sizeof (*pMsg) ) {
602  register_new_client ( from, freeList );
603 
604  /*
605  * strip register client message
606  */
607  pMsg++;
608  size -= sizeof ( *pMsg );
609  if ( size==0 ) {
610  continue;
611  }
612  }
614  if ( pMsg->m_available == 0u ) {
615  pMsg->m_available = from.ia.sin_addr.s_addr;
616  }
617  }
618  }
619  else if ( size == 0 ) {
620  register_new_client ( from, freeList );
621  continue;
622  }
623 
624  fanOut ( from, pMsg, size, freeList );
625  }
626 }
#define SOCK_ECONNREFUSED
Definition: osdSock.h:58
LIBCA_API void epicsStdCall removeDuplicateAddresses(struct ELLLIST *pDestList, ELLLIST *pSrcList, int silent)
Definition: iocinf.cpp:123
#define CA_REPEATER_PORT
Definition: caProto.h:54
#define REPEATER_REGISTER
Definition: caProto.h:107
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
osiSockAddr addr
Definition: osiSock.h:163
#define SOCK_EADDRINUSE
Definition: osdSock.h:56
int osiSocklen_t
Definition: osdSock.h:36
void osiSockRelease()
Definition: osdSock.c:62
struct sockaddr sa
Definition: osiSock.h:158
LIBCA_API int epicsStdCall addAddrToChannelAccessAddressList(struct ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port, int ignoreNonDefaultPort)
Definition: iocinf.cpp:74
ca_uint32_t m_available
Definition: caProto.h:166
struct sockaddr_in ia
Definition: osiSock.h:157
unsigned int epicsUInt32
Definition: epicsTypes.h:43
#define ELLLIST_INIT
Value of an empty list.
Definition: ellLib.h:63
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
#define SOCK_ECONNRESET
Definition: osdSock.h:53
ca_uint16_t m_cmmd
Definition: caProto.h:161
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
LIBCOM_API const ENV_PARAM EPICS_CA_REPEATER_PORT
LIBCOM_API unsigned short epicsStdCall envGetInetPortConfigParam(const ENV_PARAM *pEnv, unsigned short defaultPort)
Get value of a port number configuration parameter.
Definition: envSubr.c:398
int SOCKET
Definition: osdSock.h:31
LIBCOM_API const ENV_PARAM EPICS_CA_ADDR_LIST
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
LIBCOM_API const ENV_PARAM EPICS_CAS_BEACON_ADDR_LIST
#define SOCKERRNO
Definition: osdSock.h:33
#define MAX_UDP_RECV
Definition: caProto.h:61
ELLNODE node
Definition: osiSock.h:162
int osiSockAttach()
Definition: osdSock.c:54
#define debugPrintf(argsInParen)
Definition: iocinf.h:30
#define stderr
Definition: epicsStdio.h:32
List header type.
Definition: ellLib.h:56
#define CA_PROTO_RSRV_IS_UP
Definition: caProto.h:96
void epicsSocketConvertErrorToString(char *pBuf, unsigned bufSize, int theSockError)
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
Definition: osiSock.c:144
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
void caRepeaterThread ( void *  )

Definition at line 631 of file repeater.cpp.

632 {
634  ca_repeater ();
635 }
void taskwdInsert(epicsThreadId tid, TASKWDFUNC callback, void *usr)
Definition: taskwd.c:176
void ca_repeater()
Definition: repeater.cpp:482
#define NULL
Definition: catime.c:38
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810