This is Unofficial EPICS BASE Doxygen Site
udpiiu.cpp File Reference
#include "envDefs.h"
#include "dbDefs.h"
#include "osiProcess.h"
#include "osiWireFormat.h"
#include "epicsAlgorithm.h"
#include "errlog.h"
#include "locationException.h"
#include "addrList.h"
#include "caerr.h"
#include "udpiiu.h"
#include "iocinf.h"
#include "inetAddrID.h"
#include "cac.h"
#include "disconnectGovernorTimer.h"
+ Include dependency graph for udpiiu.cpp:

Go to the source code of this file.

Macros

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

Functions

void epicsStdCall caRepeaterRegistrationMessage (SOCKET sock, unsigned repeaterPort, unsigned attemptNumber)
 
void epicsStdCall caStartRepeaterIfNotInstalled (unsigned repeaterPort)
 

Macro Definition Documentation

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

Definition at line 25 of file udpiiu.cpp.

Function Documentation

void epicsStdCall caRepeaterRegistrationMessage ( SOCKET  sock,
unsigned  repeaterPort,
unsigned  attemptNumber 
)

Definition at line 464 of file udpiiu.cpp.

466 {
467  osiSockAddr saddr;
468  caHdr msg;
469  int status;
470  int len;
471 
472  assert ( repeaterPort <= USHRT_MAX );
473  unsigned short port = static_cast <unsigned short> ( repeaterPort );
474 
475  /*
476  * In 3.13 beta 11 and before the CA repeater calls local_addr()
477  * to determine a local address and does not allow registration
478  * messages originating from other addresses. In these
479  * releases local_addr() returned the address of the first enabled
480  * interface found, and this address may or may not have been the loop
481  * back address. Starting with 3.13 beta 12 local_addr() was
482  * changed to always return the address of the first enabled
483  * non-loopback interface because a valid non-loopback local
484  * address is required in the beacon messages. Therefore, to
485  * guarantee compatibility with past versions of the repeater
486  * we alternate between the address returned by local_addr()
487  * and the loopback address here.
488  *
489  * CA repeaters in R3.13 beta 12 and higher allow
490  * either the loopback address or the address returned
491  * by local address (the first non-loopback address found)
492  */
493  if ( attemptNumber & 1 ) {
494  saddr = osiLocalAddr ( sock );
495  if ( saddr.sa.sa_family != AF_INET ) {
496  /*
497  * use the loop back address to communicate with the CA repeater
498  * if this os does not have interface query capabilities
499  *
500  * this will only work with 3.13 beta 12 CA repeaters or later
501  */
502  saddr.ia.sin_family = AF_INET;
503  saddr.ia.sin_addr.s_addr = htonl ( INADDR_LOOPBACK );
504  saddr.ia.sin_port = htons ( port );
505  }
506  else {
507  saddr.ia.sin_port = htons ( port );
508  }
509  }
510  else {
511  saddr.ia.sin_family = AF_INET;
512  saddr.ia.sin_addr.s_addr = htonl ( INADDR_LOOPBACK );
513  saddr.ia.sin_port = htons ( port );
514  }
515 
516  memset ( (char *) &msg, 0, sizeof (msg) );
518  msg.m_available = saddr.ia.sin_addr.s_addr;
519 
520  /*
521  * Intentionally sending a zero length message here
522  * until most CA repeater daemons have been restarted
523  * (and only then will they accept the above protocol)
524  * (repeaters began accepting this protocol
525  * starting with EPICS 3.12)
526  */
527 # if defined ( DOES_NOT_ACCEPT_ZERO_LENGTH_UDP )
528  len = sizeof (msg);
529 # else
530  len = 0;
531 # endif
532 
533  status = sendto ( sock, (char *) &msg, len, 0,
534  &saddr.sa, sizeof ( saddr ) );
535  if ( status < 0 ) {
536  int errnoCpy = SOCKERRNO;
537  /*
538  * Different OS return different codes when the repeater isnt running.
539  * Its ok to supress these messages because I print another warning message
540  * if we time out registerring with the repeater.
541  *
542  * Linux returns SOCK_ECONNREFUSED
543  * Windows 2000 returns SOCK_ECONNRESET
544  */
545  if ( errnoCpy != SOCK_EINTR &&
546  errnoCpy != SOCK_ECONNREFUSED &&
547  errnoCpy != SOCK_ECONNRESET ) {
548  char sockErrBuf[64];
550  sockErrBuf, sizeof ( sockErrBuf ) );
551  fprintf ( stderr, "error sending registration message to CA repeater daemon was \"%s\"\n",
552  sockErrBuf );
553  }
554  }
555 }
#define SOCK_ECONNREFUSED
Definition: osdSock.h:58
#define INADDR_LOOPBACK
Definition: osdSock.h:76
#define REPEATER_REGISTER
Definition: caProto.h:107
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
struct sockaddr sa
Definition: osiSock.h:158
ca_uint32_t m_available
Definition: caProto.h:166
struct sockaddr_in ia
Definition: osiSock.h:157
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
#define SOCK_ECONNRESET
Definition: osdSock.h:53
LIBCOM_API osiSockAddr epicsStdCall osiLocalAddr(SOCKET socket)
Definition: osdNetIntf.c:347
ca_uint16_t m_cmmd
Definition: caProto.h:161
#define SOCKERRNO
Definition: osdSock.h:33
#define SOCK_EINTR
Definition: osdSock.h:64
#define stderr
Definition: epicsStdio.h:32
void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned  repeaterPort)

Definition at line 581 of file udpiiu.cpp.

582 {
583  bool installed = false;
584  int status;
585  SOCKET tmpSock;
586  union {
587  struct sockaddr_in ia;
588  struct sockaddr sa;
589  } bd;
590 
591  if ( repeaterPort > 0xffff ) {
592  fprintf ( stderr, "caStartRepeaterIfNotInstalled () : strange repeater port specified\n" );
593  return;
594  }
595 
596  tmpSock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
597  if ( tmpSock != INVALID_SOCKET ) {
598  ca_uint16_t port = static_cast < ca_uint16_t > ( repeaterPort );
599  memset ( (char *) &bd, 0, sizeof ( bd ) );
600  bd.ia.sin_family = AF_INET;
601  bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
602  bd.ia.sin_port = htons ( port );
603  status = bind ( tmpSock, &bd.sa, sizeof ( bd ) );
604  if ( status < 0 ) {
605  if ( SOCKERRNO == SOCK_EADDRINUSE ) {
606  installed = true;
607  }
608  else {
609  fprintf ( stderr, "caStartRepeaterIfNotInstalled () : bind failed\n" );
610  }
611  }
612  }
613 
614  /*
615  * turn on reuse only after the test so that
616  * this works on kernels that support multicast
617  */
619 
620  epicsSocketDestroy ( tmpSock );
621 
622  if ( ! installed ) {
623 
624  /*
625  * This is not called if the repeater is known to be
626  * already running. (in the event of a race condition
627  * the 2nd repeater exits when unable to attach to the
628  * repeater's port)
629  */
631  osiSpawnDetachedProcess ( "CA Repeater", "caRepeater" );
632  if ( osptr == osiSpawnDetachedProcessNoSupport ) {
633  epicsThreadId tid;
634 
635  tid = epicsThreadCreate ( "CAC-repeater", epicsThreadPriorityLow,
637  if ( tid == 0 ) {
638  fprintf ( stderr, "caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n" );
639  }
640  }
641  else if ( osptr == osiSpawnDetachedProcessFail ) {
642  fprintf ( stderr, "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" );
643  }
644  }
645 }
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
Definition: osdSock.c:117
#define INVALID_SOCKET
Definition: osdSock.h:32
#define SOCK_EADDRINUSE
Definition: osdSock.h:56
pvd::Status status
unsigned short ca_uint16_t
Definition: caProto.h:75
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
Definition: osdThread.c:466
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
Definition: epicsThread.cpp:33
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
Definition: osdSock.c:71
osiSpawnDetachedProcessReturn
Definition: osiProcess.h:35
void caRepeaterThread(void *)
Definition: repeater.cpp:631
LIBCOM_API void epicsStdCall epicsSocketEnableAddressReuseDuringTimeWaitState(SOCKET s)
#define epicsThreadPriorityLow
Definition: epicsThread.h:75
int SOCKET
Definition: osdSock.h:31
#define SOCKERRNO
Definition: osdSock.h:33
LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess(const char *pProcessName, const char *pBaseExecutableName)
Definition: osdProcess.c:61
#define stderr
Definition: epicsStdio.h:32