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)