Exemplo n.º 1
0
/*
 * makeSocket()
 */
static bool makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock )
{
    int status;
	union {
		struct sockaddr_in ia;
		struct sockaddr sa;
	} bd;

    SOCKET sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, 0 );     
    if ( sock == INVALID_SOCKET ) {
        return false;
    }

    /*
     * no need to bind if unconstrained
     */
    if ( port != PORT_ANY ) {

        memset ( (char *) &bd, 0, sizeof (bd) );
        bd.ia.sin_family = AF_INET;
        bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); 
        bd.ia.sin_port = htons ( port );  
        status = bind ( sock, &bd.sa, (int) sizeof(bd) );
        if ( status < 0 ) {
            epicsSocketDestroy ( sock );
            return false;
        }
        if ( reuseAddr ) {
            epicsSocketEnableAddressReuseDuringTimeWaitState ( sock );
        }
    }
    *pSock = sock;
    return true;
}
Exemplo n.º 2
0
/*
 *  logClientMakeSock ()
 */
static void logClientMakeSock (logClient *pClient)
{
    
#   ifdef DEBUG
        fprintf (stderr, "log client: creating socket...");
#   endif

    epicsMutexMustLock (pClient->mutex);
   
    /* 
     * allocate a socket 
     */
    pClient->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, 0 );
    if ( pClient->sock == INVALID_SOCKET ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf ( stderr, "log client: no socket error %s\n", 
            sockErrBuf );
    }
    
    epicsMutexUnlock (pClient->mutex);

#   ifdef DEBUG
        fprintf (stderr, "done\n");
#   endif

}
Exemplo n.º 3
0
int E2050Reboot(char * inetAddr)
{
    struct sockaddr_in serverAddr;
    SOCKET fd;
    int status;
    int nbytes;

    errno = 0;
    fd = epicsSocketCreate(PF_INET, SOCK_STREAM, 0);
    if(fd == -1) {
        printf("can't create socket %s\n",strerror(errno));
        return(-1);
    }
    memset((char*)&serverAddr, 0, sizeof(struct sockaddr_in));
    serverAddr.sin_family = PF_INET;
    /* 23 is telnet port */
    status = aToIPAddr(inetAddr,23,&serverAddr);
    if(status) {
        printf("aToIPAddr failed\n");
        return(-1); 
    }
    errno = 0;
    status = connect(fd,(struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(status) {
        printf("can't connect %s\n",strerror (errno));
        epicsSocketDestroy(fd);
        return(-1);
    }
    nbytes = send(fd,"reboot\ny\n",9,0);
    if(nbytes!=9) printf("nbytes %d expected 9\n",nbytes);
    epicsSocketDestroy(fd);
    epicsThreadSleep(20.0);
    return(0);
}
Exemplo n.º 4
0
/**
 * Load configuration.
 */
void ServerContextImpl::loadConfiguration()
{
    Configuration::shared_pointer config = getConfiguration();

    // TODO for now just a simple switch
    int32 debugLevel = config->getPropertyAsInteger(PVACCESS_DEBUG, 0);
    if (debugLevel > 0)
        SET_LOG_LEVEL(logLevelDebug);

    // TODO multiple addresses
    _ifaceAddr.ia.sin_family = AF_INET;
    _ifaceAddr.ia.sin_addr.s_addr = htonl(INADDR_ANY);
    _ifaceAddr.ia.sin_port = 0;
    config->getPropertyAsAddress("EPICS_PVAS_INTF_ADDR_LIST", &_ifaceAddr);

    _beaconAddressList = config->getPropertyAsString("EPICS_PVA_ADDR_LIST", _beaconAddressList);
    _beaconAddressList = config->getPropertyAsString("EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);

    _autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVA_AUTO_ADDR_LIST", _autoBeaconAddressList);
    _autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVAS_AUTO_BEACON_ADDR_LIST", _autoBeaconAddressList);

    _beaconPeriod = config->getPropertyAsFloat("EPICS_PVA_BEACON_PERIOD", _beaconPeriod);
    _beaconPeriod = config->getPropertyAsFloat("EPICS_PVAS_BEACON_PERIOD", _beaconPeriod);

    _serverPort = config->getPropertyAsInteger("EPICS_PVA_SERVER_PORT", _serverPort);
    _serverPort = config->getPropertyAsInteger("EPICS_PVAS_SERVER_PORT", _serverPort);
    _ifaceAddr.ia.sin_port = htons(_serverPort);

    _broadcastPort = config->getPropertyAsInteger("EPICS_PVA_BROADCAST_PORT", _broadcastPort);
    _broadcastPort = config->getPropertyAsInteger("EPICS_PVAS_BROADCAST_PORT", _broadcastPort);

    _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVA_MAX_ARRAY_BYTES", _receiveBufferSize);
    _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVAS_MAX_ARRAY_BYTES", _receiveBufferSize);

    _channelProviderNames = config->getPropertyAsString("EPICS_PVA_PROVIDER_NAMES", _channelProviderNames);
    _channelProviderNames = config->getPropertyAsString("EPICS_PVAS_PROVIDER_NAMES", _channelProviderNames);

    //
    // introspect network interfaces
    //

    SOCKET sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
    if (!sock) {
        THROW_BASE_EXCEPTION("Failed to create a socket needed to introspect network interfaces.");
    }

    if (discoverInterfaces(_ifaceList, sock, &_ifaceAddr))
    {
        THROW_BASE_EXCEPTION("Failed to introspect network interfaces.");
    }
    else if (_ifaceList.size() == 0)
    {
        THROW_BASE_EXCEPTION("No (specified) network interface(s) available.");
    }
    epicsSocketDestroy(sock);
}
Exemplo n.º 5
0
int Eiger::connect (void)
{
    const char *functionName = "connect";

    if(!mSockClosed)
        return EXIT_SUCCESS;

    mSockFd = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(mSockFd == INVALID_SOCKET)
    {
        ERR("couldn't create socket");
        return EXIT_FAILURE;
    }

    setNonBlock(true);

    if(::connect(mSockFd, (struct sockaddr*)&mAddress, sizeof(mAddress)) < 0)
    {
        // Connection actually failed
        if(errno != EINPROGRESS)
        {
            char error[MAX_BUF_SIZE];
            epicsSocketConvertErrnoToString(error, sizeof(error));
            ERR_ARGS("failed to connect to %s:%d [%s]", mHostname, HTTP_PORT, error);
            epicsSocketDestroy(mSockFd);
            return EXIT_FAILURE;
        }
        // Server didn't respond immediately, wait a little
        else
        {
            fd_set set;
            struct timeval tv;
            int ret;

            FD_ZERO(&set);
            FD_SET(mSockFd, &set);
            tv.tv_sec  = DEFAULT_TIMEOUT_CONNECT;
            tv.tv_usec = 0;

            ret = select(mSockFd + 1, NULL, &set, NULL, &tv);
            if(ret <= 0)
            {
                const char *error = ret == 0 ? "TIMEOUT" : "select failed";
                ERR_ARGS("failed to connect to %s:%d [%s]", mHostname, HTTP_PORT, error);
                epicsSocketDestroy(mSockFd);
                return EXIT_FAILURE;
            }
        }
    }

    setNonBlock(false);
    mSockClosed = false;
    return EXIT_SUCCESS;
}
    Transport::shared_pointer BlockingUDPConnector::connect(TransportClient::shared_pointer const & /*client*/,
                auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& bindAddress,
                int8 transportRevision, int16 /*priority*/) {
                    
            LOG(logLevelDebug, "Creating datagram socket to: %s.",
                    inetAddressToString(bindAddress).c_str());

            SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if(socket==INVALID_SOCKET) {
                char errStr[64];
                epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
                LOG(logLevelError, "Error creating socket: %s.", errStr);
                return Transport::shared_pointer();
            }

            int optval = _broadcast ? 1 : 0;
            int retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval));
            if(retval<0)
            {
                char errStr[64];
                epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
                LOG(logLevelError, "Error setting SO_BROADCAST: %s.", errStr);
                epicsSocketDestroy (socket);
                return Transport::shared_pointer();
            }
            
            /*
            IPv4 multicast addresses are defined by the leading address bits of 1110,
            originating from the classful network design of the early Internet when this
            group of addresses was designated as Class D. The Classless Inter-Domain Routing (CIDR)
            prefix of this group is 224.0.0.0/4.
            The group includes the addresses from 224.0.0.0 to 239.255.255.255.
            Address assignments from within this range are specified in RFC 5771,
            an Internet Engineering Task Force (IETF) Best Current Practice document (BCP 51).*/
            
            
            // set SO_REUSEADDR or SO_REUSEPORT, OS dependant
            if (_reuseSocket)
                epicsSocketEnableAddressUseForDatagramFanout(socket);

            retval = ::bind(socket, (sockaddr*)&(bindAddress.sa), sizeof(sockaddr));
            if(retval<0) {
                char errStr[64];
                epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
                LOG(logLevelError, "Error binding socket: %s.", errStr);
                epicsSocketDestroy (socket);
                return Transport::shared_pointer();
            }

            // sockets are blocking by default
            Transport::shared_pointer transport = BlockingUDPTransport::create(_serverFlag,
                                                                               responseHandler, socket, bindAddress, transportRevision);
            return transport;
        }
Exemplo n.º 7
0
int E5810Reboot(char * inetAddr,char *password)
{
    struct sockaddr_in serverAddr;
    SOCKET fd;
    int status;
    int nbytes;

    if(password==0 || strlen(password)<2) password = defaultPassword;
    errno = 0;
    fd = epicsSocketCreate(PF_INET, SOCK_STREAM, 0);
    if(fd == -1) {
        printf("can't create socket %s\n",strerror(errno));
        return(-1);
    }
    memset((char*)&serverAddr, 0, sizeof(struct sockaddr_in));
    serverAddr.sin_family = PF_INET;
    /* 23 is telnet port */
    status = aToIPAddr(inetAddr,23,&serverAddr);
    if(status) {
        printf("aToIPAddr failed\n");
        return(-1); 
    }
    errno = 0;
    status = connect(fd,(struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(status) {
        printf("can't connect %s\n",strerror (errno));
        epicsSocketDestroy(fd);
        return(-1);
    }
    nbytes = send(fd,"reboot\n",7,0);
    if(nbytes!=7) printf("nbytes %d expected 7\n",nbytes);
    epicsThreadSleep(1.0);
    nbytes = send(fd,password,(int)strlen(password),0);
    if(nbytes!=strlen(password)) 
        printf("nbytes %d expected %d\n",nbytes,(int)strlen(password));
    epicsThreadSleep(1.0);
    nbytes = send(fd,"\ny\n",3,0);
    if(nbytes!=3) printf("nbytes %d expected 3\n",nbytes);
    epicsThreadSleep(1.0);
    epicsSocketDestroy(fd);
    epicsThreadSleep(20.0);
    return(0);
}
Exemplo n.º 8
0
SOCKET shCreateSocket(int domain, int type, int protocol)
{
    SOCKET sd = epicsSocketCreate(domain, type, protocol);
    int ret;
    osiSockIoctl_t flag;

    if(sd==INVALID_SOCKET)
        return sd;

    /* set non-blocking IO */
    flag = 1;
    ret = socket_ioctl(sd, FIONBIO, &flag);

    if(ret) {
        epicsSocketDestroy(sd);
        sd = INVALID_SOCKET;
    }

    return sd;
}
Exemplo n.º 9
0
int TDS3000Reboot(char * inetAddr)
{
    struct sockaddr_in serverAddr;
    int fd;
    int status;
    int nbytes;
    char *url;
    int urlLen;

    url = "GET /resetinst.cgi HTTP/1.0\n\n";
    urlLen = strlen(url);
    errno = 0;
    fd = epicsSocketCreate(PF_INET, SOCK_STREAM, 0);
    if(fd == -1) {
        printf("can't create socket %s\n",strerror(errno));
        return(-1);
    }
    memset((char*)&serverAddr, 0, sizeof(struct sockaddr_in));
    serverAddr.sin_family = PF_INET;
    /* 80 is http port */
    status = aToIPAddr(inetAddr,80,&serverAddr);
    if(status) {
        printf("aToIPAddr failed\n");
        return(-1); 
    }
    errno = 0;
    status = connect(fd,(struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(status) {
        printf("can't connect %s\n",strerror (errno));
        close(fd);
        return(-1);
    }
    nbytes = send(fd,url,urlLen,0);
    if(nbytes!=urlLen) printf("nbytes %d expected %d\n",nbytes,urlLen);
    close(fd);
    return(0);
}
SOCKET BlockingTCPConnector::tryConnect(osiSockAddr& address, int tries) {

    char strBuffer[64];
    ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));

    for(int tryCount = 0; tryCount<tries; tryCount++) {

        LOG(logLevelDebug,
            "Opening socket to PVA server %s, attempt %d.",
            strBuffer, tryCount+1);

        SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (socket == INVALID_SOCKET)
        {
            epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
            std::ostringstream temp;
            temp<<"Socket create error: "<<strBuffer;
            THROW_EXCEPTION2(std::runtime_error, temp.str());
        }
        else {
            // TODO: use non-blocking connect() to have controllable timeout
            if(::connect(socket, &address.sa, sizeof(sockaddr))==0) {
                return socket;
            }
            else {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                char saddr[32];
                sockAddrToDottedIP(&address.sa, saddr, sizeof(saddr));
                epicsSocketDestroy (socket);
                std::ostringstream temp;
                temp<<"error connecting to "<<saddr<<" : "<<strBuffer;
                throw std::runtime_error(temp.str());
            }
        }
    }
    return INVALID_SOCKET;
}
Exemplo n.º 11
0
/*
 *  caStartRepeaterIfNotInstalled ()
 *
 *  Test for the repeater already installed
 *
 *  NOTE: potential race condition here can result
 *  in two copies of the repeater being spawned
 *  however the repeater detects this, prints a message,
 *  and lets the other task start the repeater.
 *
 *  QUESTION: is there a better way to test for a port in use? 
 *  ANSWER: none that I can find.
 *
 *  Problems with checking for the repeater installed
 *  by attempting to bind a socket to its address
 *  and port.
 *
 *  1) Closed socket may not release the bound port
 *  before the repeater wakes up and tries to grab it.
 *  Attempting to bind the open socket to another port
 *  also does not work.
 *
 *  072392 - problem solved by using SO_REUSEADDR
 */
void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repeaterPort )
{
    bool installed = false;
    int status;
    SOCKET tmpSock;
    union {
        struct sockaddr_in ia; 
        struct sockaddr sa;
    } bd;

    if ( repeaterPort > 0xffff ) {
        fprintf ( stderr, "caStartRepeaterIfNotInstalled () : strange repeater port specified\n" );
        return;
    }

    tmpSock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
    if ( tmpSock != INVALID_SOCKET ) {
        ca_uint16_t port = static_cast < ca_uint16_t > ( repeaterPort );
        memset ( (char *) &bd, 0, sizeof ( bd ) );
        bd.ia.sin_family = AF_INET;
        bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); 
        bd.ia.sin_port = htons ( port );   
        status = bind ( tmpSock, &bd.sa, sizeof ( bd ) );
        if ( status < 0 ) {
            if ( SOCKERRNO == SOCK_EADDRINUSE ) {
                installed = true;
            }
            else {
                fprintf ( stderr, "caStartRepeaterIfNotInstalled () : bind failed\n" );
            }
        }
    }

    /*
     * turn on reuse only after the test so that
     * this works on kernels that support multicast
     */
    epicsSocketEnableAddressReuseDuringTimeWaitState ( tmpSock );

    epicsSocketDestroy ( tmpSock );

    if ( ! installed ) {
        
	    /*
	     * This is not called if the repeater is known to be 
	     * already running. (in the event of a race condition 
	     * the 2nd repeater exits when unable to attach to the 
	     * repeater's port)
	     */
		
		/* 
		 * look for a caRepeater in the same directory as CA.DLL 
		 * and use this if present instead of a PATH search
		 */
		char carep_path[256];
		strcpy(carep_path, "caRepeater");
#ifdef _WIN32		
		char caDLLPath[MAX_PATH];
		HMODULE hmod = GetModuleHandle("CA.DLL");
		if (hmod != NULL) {
		   if (GetModuleFileName(hmod, caDLLPath, sizeof(caDLLPath)) > 0) {
		       char* base_path = strrchr(caDLLPath, '\\');
			   if (base_path != NULL) {
			       *base_path = '\0';   // caDLLPath is now the directory containing CA.DLL
				   _snprintf(carep_path, sizeof(carep_path), "%s\\caRepeater.exe", caDLLPath);
					if (access(carep_path, 04) != 0) {
					    strcpy(carep_path, "caRepeater");  // Not found, so will search PATH instead for caRepeater
					}
			   }
		   }
		}
#endif /* _WIN32 */
		   
        osiSpawnDetachedProcessReturn osptr = 
            osiSpawnDetachedProcess ( "CA Repeater", carep_path );
        if ( osptr == osiSpawnDetachedProcessNoSupport ) {
            epicsThreadId tid;

            tid = epicsThreadCreate ( "CAC-repeater", epicsThreadPriorityLow,
                    epicsThreadGetStackSize ( epicsThreadStackMedium ), caRepeaterThread, 0);
            if ( tid == 0 ) {
                fprintf ( stderr, "caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n" );
            }
        }
        else if ( osptr == osiSpawnDetachedProcessFail ) {
            fprintf ( stderr, "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" );
        }
    }
}
Exemplo n.º 12
0
/*
 *
 *  req_server()
 *
 *  CA server task
 *
 *  Waits for connections at the CA port and spawns a task to
 *  handle each of them
 *
 */
static void req_server (void *pParm)
{
    unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
    unsigned priorityOfBeacons;
    epicsThreadBooleanStatus tbs;
    struct sockaddr_in serverAddr;  /* server's address */
    osiSocklen_t addrSize;
    int status;
    SOCKET clientSock;
    epicsThreadId tid;
    int portChange;

    epicsSignalInstallSigPipeIgnore ();

    taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL );
    
    rsrvCurrentClient = epicsThreadPrivateCreate ();

    if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) {
        ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }
    else {
        ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }

    if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) {
        epicsSocketDestroy ( IOC_sock );
    }
    
    /*
     * Open the socket. Use ARPA Internet address format and stream
     * sockets. Format described in <sys/socket.h>.
     */
    if ( ( IOC_sock = epicsSocketCreate (AF_INET, SOCK_STREAM, 0) ) == INVALID_SOCKET ) {
        errlogPrintf ("CAS: Socket creation error\n");
        epicsThreadSuspendSelf ();
    }

    epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock );

    /* Zero the sock_addr structure */
    memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) );
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); 
    serverAddr.sin_port = htons ( ca_server_port );

    /* get server's Internet address */
    status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
	if ( status < 0 ) {
		if ( SOCKERRNO == SOCK_EADDRINUSE ) {
			/*
			 * enable assignment of a default port
			 * (so the getsockname() call below will
			 * work correctly)
			 */
			serverAddr.sin_port = ntohs (0);
			status = bind ( IOC_sock, 
                (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
		}
		if ( status < 0 ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf ( "CAS: Socket bind error was \"%s\"\n",
                sockErrBuf );
            epicsThreadSuspendSelf ();
		}
        portChange = 1;
	}
    else {
        portChange = 0;
    }

	addrSize = ( osiSocklen_t ) sizeof ( serverAddr );
	status = getsockname ( IOC_sock, 
			(struct sockaddr *)&serverAddr, &addrSize);
	if ( status ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
		errlogPrintf ( "CAS: getsockname() error %s\n", 
			sockErrBuf );
        epicsThreadSuspendSelf ();
	}

    ca_server_port = ntohs (serverAddr.sin_port);

    if ( portChange ) {
        errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
        errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", 
            ca_server_port );
        errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
        errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
        errlogPrintf ( "cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" );
    }

    /* listen and accept new connections */
    if ( listen ( IOC_sock, 20 ) < 0 ) {
        errlogPrintf ("CAS: Listen error\n");
        epicsSocketDestroy (IOC_sock);
        epicsThreadSuspendSelf ();
    }

    tbs  = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfBeacons );
    if ( tbs != epicsThreadBooleanStatusSuccess ) {
        priorityOfBeacons = priorityOfSelf;
    }

    beacon_startStopEvent = epicsEventMustCreate(epicsEventEmpty);
    beacon_ctl = ctlPause;

    tid = epicsThreadCreate ( "CAS-beacon", priorityOfBeacons,
        epicsThreadGetStackSize (epicsThreadStackSmall),
        rsrv_online_notify_task, 0 );
    if ( tid == 0 ) {
        epicsPrintf ( "CAS: unable to start beacon thread\n" );
    }

    epicsEventMustWait(beacon_startStopEvent);
    epicsEventSignal(castcp_startStopEvent);

    while (TRUE) {
        struct sockaddr     sockAddr;
        osiSocklen_t        addLen = sizeof(sockAddr);

        while (castcp_ctl == ctlPause) {
            epicsThreadSleep(0.1);
        }

        clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen );
        if ( clientSock == INVALID_SOCKET ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf("CAS: Client accept error was \"%s\"\n",
                sockErrBuf );
            epicsThreadSleep(15.0);
            continue;
        } 
        else {
            epicsThreadId id;
            struct client *pClient;

            /* socket passed in is closed if unsuccessful here */
            pClient = create_tcp_client ( clientSock );
            if ( ! pClient ) {
                epicsThreadSleep ( 15.0 );
                continue;
            }

            LOCK_CLIENTQ;
            ellAdd ( &clientQ, &pClient->node );
            UNLOCK_CLIENTQ;

            id = epicsThreadCreate ( "CAS-client", epicsThreadPriorityCAServerLow,
                    epicsThreadGetStackSize ( epicsThreadStackBig ),
                    camsgtask, pClient );
            if ( id == 0 ) {
                LOCK_CLIENTQ;
                ellDelete ( &clientQ, &pClient->node );
                UNLOCK_CLIENTQ;
                destroy_tcp_client ( pClient );
                errlogPrintf ( "CAS: task creation for new client failed\n" );
                epicsThreadSleep ( 15.0 );
                continue;
            }
        }
    }
}
Exemplo n.º 13
0
static long init_record(void *precord, int pass)
{
  aliveRecord *prec;
  struct rpvtStruct *prpvt;

  epicsTimeStamp start_time;

  int i, flag;
  char *p;
  

  prec = precord;

  if( pass == 0) 
    {
      // last element of struct rpvtStruct keeps coming out as 
      // zero length array, so pad it a bit to do a kludge fix
      prec->rpvt = calloc(1, sizeof(struct rpvtStruct) + 16);

      return 0;
    }

  prec->val = 0;
  
  sprintf( prec->ver, "%d-%d-%d", ALIVE_VERSION, ALIVE_REVISION,
           ALIVE_MODIFICATION );

  prpvt = prec->rpvt;

  // save value to local structure, set to zero until initialized.
  prpvt->orig_port = prec->iport;
  prec->iport = 0;

  // if period is set to 0, use default of 15
  if( !prec->hprd)
    prec->hprd = 15;

  prpvt->fault_flag = 0;
  prpvt->ready_flag = 0;
  prpvt->flags = 0;  // first bit set when port initialized

  epicsTimeGetCurrent(&start_time);
  prpvt->incarnation = (uint32_t) start_time.secPastEpoch;
  
  for( i = 0; i < ENV_CNT; i++)
    {
      flag = sscanf( *(&prec->env1 + i), "%s", prpvt->env[i]);
      if( !flag)
        prpvt->env[i][0] = '\0';
    }

  if( (prpvt->socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0)) == 
      INVALID_SOCKET)
    {
      errlogSevPrintf( errlogFatal, "%s", "alive record: "
                       "Won't start, can't open DGRAM socket.\n");
      prpvt->fault_flag = 1;
      return 1;
    }
#ifdef vxWorks
  bzero( (void *) &(prpvt->h_addr), sizeof(struct sockaddr_in) );
#else
  memset( (void *) &(prpvt->h_addr), 0, sizeof(struct sockaddr_in) );
#endif
  prpvt->h_addr.sin_family = AF_INET;
  prpvt->h_addr.sin_port = htons(prec->rport);
#if defined (vxWorks)
  prpvt->h_addr.sin_len = (u_char) sizeof (struct sockaddr_in); 
  if( (prpvt->h_addr.sin_addr.s_addr = inet_addr (prec->rhost)) != ERROR)
#elif defined (_WIN32)
  if ((prpvt->h_addr.sin_addr.s_addr = inet_addr(prec->rhost)) != INADDR_NONE)
#else
  if( inet_aton( prec->rhost, &(prpvt->h_addr.sin_addr)) )
#endif
    prpvt->ready_flag = 1;

  p = prec->iocnm;
  while(*p != '\0')
    {
      if( (*p != ' ') && (*p != '\t'))
        break;
      p++;
    }
  if( *p != '\0')
    {
      strncpy(prpvt->ioc_name, p, 39);
      prpvt->ioc_name[39] = '\0';

      strcpy( prec->nmvar, "----");
    }
  else
    {
      p = getenv(prec->nmvar);
      if( p == NULL)
        {
          errlogSevPrintf( errlogFatal, "%s", "alive record: "
                           "Won't start, can't get IOC name environment variable.\n");
          prpvt->fault_flag = 1;
          return 1;
        }
      // condition is sanity check, as the output buffer is static
      if( strlen( p) > 39)
        {
          errlogSevPrintf( errlogFatal, "%s", "alive record: "
                           "Won't start, environment variable IOC too long.\n");
          prpvt->fault_flag = 1;
          return 1;
        }
      strncpy(prpvt->ioc_name, p, 39);
      prpvt->ioc_name[39] = '\0';
      strncpy(prec->iocnm, prpvt->ioc_name, 40);
    }

  prpvt->listen_thread = 
    epicsThreadCreate("alive_tcp_listen_thread", 51, 
                      epicsThreadGetStackSize(epicsThreadStackMedium),
                      (EPICSTHREADFUNC) ioc_alive_listen, (void *) precord);
  prpvt->send_thread = 
    epicsThreadCreate("alive_udp_send_thread", 50, 
                      epicsThreadGetStackSize(epicsThreadStackMedium),
                      (EPICSTHREADFUNC) ioc_alive_send, (void *) precord);
  
  return 0;
}
Exemplo n.º 14
0
void *ioc_alive_listen(void *data)
{
  aliveRecord *prec = (aliveRecord *) data;
  struct rpvtStruct *prpvt;

  SOCKET tcp_sockfd;
  int sflag;

  SOCKET client_sockfd;

  struct sockaddr_in l_addr;

  osiSocklen_t socklen;

  char *q;
  
  // key and value lengths, key length of zero means it doesn't exist
  int env_len[ENV_CNT][2]; 

  uint32_t msg32;
  uint16_t msg16, len16;
  uint8_t  len8;

  int length;
  int number;
  int type;

#if defined (vxWorks)
  BOOT_PARAMS bootparams;
#endif
#if defined (linux) || defined (darwin)
  char *user;
  char *group;
  char *hostname;
  char hostname_buffer[129];
#endif
#if defined (_WIN32)
  char *user;
  char user_buffer[80];
  char *machine;
  char machine_buffer[20];
#endif

  int i;

  prpvt = prec->rpvt;

#if defined (vxWorks)
  type = 1;
#elif defined (linux)
  type = 2;
#elif defined (darwin)
  type = 3;
#elif defined (_WIN32)
  type = 4;
#else
  type = 0;
#endif
  
#ifdef vxWorks
  bzero( (char *) &l_addr, sizeof( struct sockaddr_in) );
  l_addr.sin_len = sizeof( struct sockaddr_in);
#else
  memset( &l_addr, 0, sizeof( struct sockaddr_in) );
#endif
  l_addr.sin_family = AF_INET;
  l_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  l_addr.sin_port = htons(prpvt->orig_port);

  if( (tcp_sockfd = epicsSocketCreate(AF_INET, SOCK_STREAM, 0))
      == INVALID_SOCKET )
    {
      perror("socket");
      prec->ipsts = aliveIPSTS_INOPERABLE;
      monitor_field(prec, (void *) &prec->ipsts);
      return NULL;
    }

  sflag = 1;
  // not the end of the world if this option doesn't work
  setsockopt(tcp_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &sflag,
             sizeof(sflag));


  if( bind(tcp_sockfd, (struct sockaddr *) &l_addr, 
           sizeof(struct sockaddr_in)) )
    {
      perror("TCP bind");
      prec->ipsts = aliveIPSTS_INOPERABLE;
      monitor_field(prec, (void *) &prec->ipsts);
      return NULL;
    }
  
  socklen = sizeof(struct sockaddr_in);
  if( getsockname( tcp_sockfd, (struct sockaddr *) &l_addr, &socklen) )
    {
      perror("TCP getsockname");
      prec->ipsts = aliveIPSTS_INOPERABLE;
      monitor_field(prec, (void *) &prec->ipsts);
      return NULL;
    }    
  // wait to use result until we know listen() works

  if( listen(tcp_sockfd, 5) )
    {
      perror("TCP listen");
      prec->ipsts = aliveIPSTS_INOPERABLE;
      monitor_field(prec, (void *) &prec->ipsts);
      return NULL;
    }

  prec->iport = ntohs(l_addr.sin_port);
  monitor_field(prec, (void *) &prec->iport);
  prec->ipsts = aliveIPSTS_OPERABLE;
  monitor_field(prec, (void *) &prec->ipsts);

  // request remote read
  prpvt->flags |= ((uint16_t) 1);
  
  while(1)
    {
      struct sockaddr r_addr;
      osiSocklen_t r_len = sizeof( r_addr);

      client_sockfd = epicsSocketAccept( tcp_sockfd, &r_addr, &r_len);
      if (client_sockfd == INVALID_SOCKET)
        continue;

      // fault flag can't happen, but just in case
      if( prec->isup || prpvt->fault_flag || !prpvt->ready_flag || 
          ( ((struct sockaddr_in *)&r_addr)->sin_addr.s_addr != prpvt->h_addr.sin_addr.s_addr) )
        {
          epicsSocketDestroy(client_sockfd);
          continue;
        }

      // TCP protocol version
      msg16 = htons(PROTOCOL_VERSION);
      send( client_sockfd, (void *) &msg16, sizeof(uint16_t), 0);

      // IOC type, currently 1 = vxworks, 2 = linux, 3 = darwin
      msg16 = htons(type);
      send( client_sockfd, (void *) &msg16, sizeof(uint16_t), 0);

      number = 0;
      length = 10;  // from version + type + number + length
#if defined (vxWorks)
      memset( &bootparams, 0, sizeof( BOOT_PARAMS) );
      bootStringToStruct( sysBootLine, &bootparams);
      // don't check to see if it returns EOS, as it's zeroed out

      length += 12; // bootparams.unitNum, bootparams.procNum, bootparams.flags
      length += 12; // 8-bit lengths below
      length += ((uint8_t) strlen(bootparams.bootDev) );
      length += ((uint8_t) strlen(bootparams.hostName) );
      length += ((uint8_t) strlen(bootparams.bootFile) );
      length += ((uint8_t) strlen(bootparams.ead) );
      length += ((uint8_t) strlen(bootparams.bad) );
      length += ((uint8_t) strlen(bootparams.had) );
      length += ((uint8_t) strlen(bootparams.gad) );
      length += ((uint8_t) strlen(bootparams.usr) );
      length += ((uint8_t) strlen(bootparams.passwd) );
      length += ((uint8_t) strlen(bootparams.targetName) );
      length += ((uint8_t) strlen(bootparams.startupScript) );
      length += ((uint8_t) strlen(bootparams.other) );
#endif
#if defined (linux) || defined (darwin)
      {
        uid_t user_id;
        gid_t group_id;
        struct passwd *passwd_entry;
        struct group *group_entry;

        user_id = getuid();
        passwd_entry = getpwuid(user_id);
        if( passwd_entry != NULL)
          user = passwd_entry->pw_name;
        else
          user = NULL;

        group_id = getgid();
        group_entry = getgrgid(group_id);
        if( group_entry != NULL)
          group = group_entry->gr_name;
        else
          group = NULL;

        if( gethostname( hostname_buffer, 128) )
          hostname = NULL;
        else
          {
            hostname_buffer[128] = '\0';
            hostname = hostname_buffer;
          }
      }

      //      flag == 2 or 3
      length += 1; // 8-bit string length
      if( user != NULL)
        length += ((uint8_t) strlen(user) );
      length += 1; // 8-bit string length
      if( group != NULL)
        length += ((uint8_t) strlen(group) );
      length += 1; // 8-bit string length
      if( hostname != NULL)
        length += ((uint8_t) strlen(hostname) );
#endif
#if defined (_WIN32)
      {
        uint32_t size;

        length += 2; // two variable lengths

        size = 80;
        if (GetUserNameA(user_buffer, &size))
          {
            user = user_buffer;
            length += ((uint8_t)strlen(user));
          }
        else
          user = NULL;

        size = 20;
        if (GetComputerNameA(machine_buffer, &size))
          {
            machine = machine_buffer;
            length += ((uint8_t)strlen(machine));
          }
        else
          machine = NULL;
      }
#endif
      for( i = 0; i < ENV_CNT; i++)
        {
          if( prpvt->env[i][0] == '\0')
            env_len[i][0] = 0;
          else
            {
              number++;
              length += 3; // 8-bit key & 16-bit value string lengths
              env_len[i][0] = strlen(prpvt->env[i]);
              length += env_len[i][0];
              q = getenv(prpvt->env[i]);
              if( q == NULL)
                env_len[i][1] = 0;
              else
                {
                  env_len[i][1] = strlen(q);
                  // if size is greater that 16-bit max, truncate to zero
                  if( env_len[i][1] > 65535)
                    env_len[i][1] = 0;
                  length += env_len[i][1];
                }
            }
        }

      /* printf("%d\n", length); fflush(stdout); */

      msg32 = htonl( length);
      send( client_sockfd, (void *) &msg32, sizeof(uint32_t), 0);
      msg16 = htons( number);
      send( client_sockfd, (void *) &msg16, sizeof(uint16_t), 0);

      for( i = 0; i < ENV_CNT; i++)
        {
          if( env_len[i][0] == 0)
            continue;

          len8 = env_len[i][0];
          send( client_sockfd, (void *) &len8, sizeof(uint8_t), 0);
          send( client_sockfd, prpvt->env[i], len8, 0);

          q = getenv(prpvt->env[i]);
          len16 = env_len[i][1];
          msg16 = htons( len16);
          send( client_sockfd, (void *) &msg16, sizeof(uint16_t), 0);
          if( len16)
            send( client_sockfd, q, len16, 0);
        }

#ifdef vxWorks
      bootparam_send( client_sockfd, bootparams.bootDev);
      msg32 = htonl(bootparams.unitNum);
      send( client_sockfd, (void *) &msg32, sizeof(uint32_t), 0);
      msg32 = htonl(bootparams.procNum);
      send( client_sockfd, (void *) &msg32, sizeof(uint32_t), 0);
      bootparam_send( client_sockfd, bootparams.hostName);
      bootparam_send( client_sockfd, bootparams.bootFile);
      bootparam_send( client_sockfd, bootparams.ead);
      bootparam_send( client_sockfd, bootparams.bad);
      bootparam_send( client_sockfd, bootparams.had);
      bootparam_send( client_sockfd, bootparams.gad);
      bootparam_send( client_sockfd, bootparams.usr);
      bootparam_send( client_sockfd, bootparams.passwd);
      msg32 = htonl( bootparams.flags);
      send( client_sockfd, (void *) &msg32, sizeof(uint32_t), 0);
      bootparam_send( client_sockfd, bootparams.targetName);
      bootparam_send( client_sockfd, bootparams.startupScript);
      bootparam_send( client_sockfd, bootparams.other);
#endif
#if defined (linux) || defined (darwin)
      if( user == NULL)
        len8 = 0;
      else
        len8 = strlen( user);
      send( client_sockfd, (void *) &len8, sizeof(uint8_t), 0);
      if( user != NULL)
        send( client_sockfd, user, len8, 0);

      if( group == NULL)
        len8 = 0;
      else
        len8 = strlen( group);
      send( client_sockfd, (void *) &len8, sizeof(uint8_t), 0);
      if( group != NULL)
        send( client_sockfd, group, len8, 0);

      if( hostname == NULL)
        len8 = 0;
      else
        len8 = strlen( hostname);
      send( client_sockfd, (void *) &len8, sizeof(uint8_t), 0);
      if( hostname != NULL)
        send( client_sockfd, hostname, len8, 0);
#endif
#if defined (_WIN32)
	  if (user == NULL)
		  len8 = 0;
	  else
		  len8 = strlen(user);
	  send(client_sockfd, (void *)&len8, sizeof(uint8_t), 0);
	  if (user != NULL)
		  send(client_sockfd, user, len8, 0);

	  if (machine == NULL)
		  len8 = 0;
	  else
		  len8 = strlen(machine);
	  send(client_sockfd, (void *)&len8, sizeof(uint8_t), 0);
	  if (machine != NULL)
		  send(client_sockfd, machine, len8, 0);
#endif
      epicsSocketDestroy( client_sockfd);

      // turn off request flag
      prpvt->flags &= ~((uint16_t) 1);
      // if itrigger was set, unset it
      if( prec->itrig)
        {
          prec->itrig = 0; 

          monitor_field(prec, (void *) &prec->itrig);
        }
    }

  return NULL;
}
Exemplo n.º 15
0
/*
 * CAST_SERVER
 *
 * service UDP messages
 * 
 */
void cast_server(void *pParm)
{
    struct sockaddr_in  sin;    
    int                 status;
    int                 count=0;
    struct sockaddr_in  new_recv_addr;
    osiSocklen_t        recv_addr_size;
    unsigned short      port;
    osiSockIoctl_t      nchars;

    if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) {
        port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }
    else {
        port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }

    recv_addr_size = sizeof(new_recv_addr);

    if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) {
        epicsSocketDestroy ( IOC_cast_sock );
    }

    /* 
     *  Open the socket.
     *  Use ARPA Internet address format and datagram socket.
     */

    if ( ( IOC_cast_sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0) ) == INVALID_SOCKET ) {
        epicsPrintf ("CAS: cast socket creation error\n");
        epicsThreadSuspendSelf ();
    }

    /*
     * some concern that vxWorks will run out of mBuf's
     * if this change is made
     *
     * joh 11-10-98
     */
#if 0
    {
        /*
         *
         * this allows for faster connects by queuing
         * additional incomming UDP search frames
         *
         * this allocates a 32k buffer
         * (uses a power of two)
         */
        int size = 1u<<15u;
        status = setsockopt (IOC_cast_sock, SOL_SOCKET,
                        SO_RCVBUF, (char *)&size, sizeof(size));
        if (status<0) {
            epicsPrintf ("CAS: unable to set cast socket size\n");
        }
    }
#endif

    epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock );
    
    /*  Zero the sock_addr structure */
    memset((char *)&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    sin.sin_port = htons(port);
    
    /* get server's Internet address */
    if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        epicsPrintf ("CAS: UDP server port bind error was \"%s\"\n", sockErrBuf );
        epicsSocketDestroy ( IOC_cast_sock );
        epicsThreadSuspendSelf ();
    }

    /*
     * setup new client structure but reuse old structure if
     * possible
     *
     */
    while ( TRUE ) {
        prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP );
        if ( prsrv_cast_client ) {
            break;
        }
        epicsThreadSleep(300.0);
    }

    casAttachThreadToClient ( prsrv_cast_client );

    /*
     * add placeholder for the first version message should it be needed
     */
    rsrv_version_reply ( prsrv_cast_client );

    epicsEventSignal(casudp_startStopEvent);

    while (TRUE) {
        status = recvfrom (
            IOC_cast_sock,
            prsrv_cast_client->recv.buf,
            prsrv_cast_client->recv.maxstk,
            0,
            (struct sockaddr *)&new_recv_addr, 
            &recv_addr_size);
        if (status < 0) {
            if (SOCKERRNO != SOCK_EINTR) {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                epicsPrintf ("CAS: UDP recv error (errno=%s)\n",
                        sockErrBuf);
                epicsThreadSleep(1.0);
            }
        }
        else if (casudp_ctl == ctlRun) {
            prsrv_cast_client->recv.cnt = (unsigned) status;
            prsrv_cast_client->recv.stk = 0ul;
            epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv);

            prsrv_cast_client->minor_version_number = 0;
            prsrv_cast_client->seqNoOfReq = 0;

            /*
             * If we are talking to a new client flush to the old one 
             * in case we are holding UDP messages waiting to 
             * see if the next message is for this same client.
             */
            if (prsrv_cast_client->send.stk>sizeof(caHdr)) {
                status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size);
                if(status){     
                    /* 
                     * if the address is different 
                     */
                    cas_send_dg_msg(prsrv_cast_client);
                    prsrv_cast_client->addr = new_recv_addr;
                }
            }
            else {
                prsrv_cast_client->addr = new_recv_addr;
            }

            if (CASDEBUG>1) {
                char    buf[40];
    
                ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
                errlogPrintf ("CAS: cast server msg of %d bytes from addr %s\n", 
                    prsrv_cast_client->recv.cnt, buf);
            }

            if (CASDEBUG>2)
                count = ellCount (&prsrv_cast_client->chanList);

            status = camessage ( prsrv_cast_client );
            if(status == RSRV_OK){
                if(prsrv_cast_client->recv.cnt != 
                    prsrv_cast_client->recv.stk){
                    char buf[40];
        
                    ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));

                    epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n",
                        prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf);
                }
            }
            else {
                char buf[40];
    
                ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));

                epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf);
            }

            if (CASDEBUG>2) {
                if ( ellCount (&prsrv_cast_client->chanList) ) {
                    errlogPrintf ("CAS: Fnd %d name matches (%d tot)\n",
                        ellCount(&prsrv_cast_client->chanList)-count,
                        ellCount(&prsrv_cast_client->chanList));
                }
            }
        }

        /*
         * allow messages to batch up if more are comming
         */
        nchars = 0; /* supress purify warning */
        status = socket_ioctl(IOC_cast_sock, FIONREAD, &nchars);
        if (status<0) {
            errlogPrintf ("CA cast server: Unable to fetch N characters pending\n");
            cas_send_dg_msg (prsrv_cast_client);
            clean_addrq ();
        }
        else if (nchars == 0) {
            cas_send_dg_msg (prsrv_cast_client);
            clean_addrq ();
        }
    }
}
Exemplo n.º 16
0
/*
 * Create a link
*/
static asynStatus
connectIt(void *drvPvt, asynUser *pasynUser)
{
    ttyController_t *tty = (ttyController_t *)drvPvt;
    SOCKET fd;
    int i;

    /*
     * Sanity check
     */
    assert(tty);
    asynPrint(pasynUser, ASYN_TRACE_FLOW,
              "Open connection to %s  reason:%d  fd:%d\n", tty->IPDeviceName,
              pasynUser->reason,
              tty->fd);

    if (tty->fd != INVALID_SOCKET) {
        epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                      "%s: Link already open!", tty->IPDeviceName);
        return asynError;
    } else if(tty->flags & FLAG_SHUTDOWN) {
        epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                      "%s: Link shutdown!", tty->IPDeviceName);
        return asynError;
    }

    /* If pasynUser->reason > 0) then use this as the file descriptor */
    if (pasynUser->reason > 0) {
        fd = pasynUser->reason;
    } else {

        /*
         * Create the socket
         */
        if ((fd = epicsSocketCreate(tty->farAddr.oa.sa.sa_family, tty->socketType, 0)) < 0) {
            epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                          "Can't create socket: %s", strerror(SOCKERRNO));
            return asynError;
        }

        /*
         * Enable broadcasts if so requested
         */
        i = 1;
        if ((tty->flags & FLAG_BROADCAST)
                && (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void *)&i, sizeof i) < 0)) {
            epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                          "Can't set %s socket BROADCAST option: %s",
                          tty->IPDeviceName, strerror(SOCKERRNO));
            epicsSocketDestroy(fd);
            return asynError;
        }

        /*
         * Convert host name/number to IP address.
         * We delay doing this until now in case a device
         * has just appeared in a DNS database.
         */
        if (tty->flags & FLAG_NEED_LOOKUP) {
            if(hostToIPAddr(tty->IPHostName, &tty->farAddr.oa.ia.sin_addr) < 0) {
                epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                              "Unknown host \"%s\"", tty->IPHostName);
                epicsSocketDestroy(fd);
                return asynError;
            }
            tty->flags &= ~FLAG_NEED_LOOKUP;
            tty->flags |=  FLAG_DONE_LOOKUP;
        }

        /*
         * Bind to the local IP address if it was specified.
         * This is a very unusual configuration
         */
        if (tty->localAddrSize > 0) {
            if (bind(fd, &tty->localAddr.sa, tty->localAddrSize)) {
                epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                              "unable to bind to local port: %s", strerror(SOCKERRNO));
                epicsSocketDestroy(fd);
                return asynError;
            }
        }

        /*
         * Connect to the remote host
         * If the connect fails, arrange for another DNS lookup in case the
         * problem is just that the device has DHCP'd itself an new number.
         */
        if (tty->socketType != SOCK_DGRAM) {
            if (connect(fd, &tty->farAddr.oa.sa, (int)tty->farAddrSize) < 0) {
                epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                              "Can't connect to %s: %s",
                              tty->IPDeviceName, strerror(SOCKERRNO));
                epicsSocketDestroy(fd);
                if (tty->flags & FLAG_DONE_LOOKUP)
                    tty->flags |=  FLAG_NEED_LOOKUP;
                return asynError;
            }
        }
    }
    i = 1;
    if ((tty->socketType == SOCK_STREAM)
            && (tty->farAddr.oa.sa.sa_family == AF_INET)
            && (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof i) < 0)) {
        epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                      "Can't set %s socket NODELAY option: %s",
                      tty->IPDeviceName, strerror(SOCKERRNO));
        epicsSocketDestroy(fd);
        return asynError;
    }
#ifdef USE_POLL
    if (setNonBlock(fd, 1) < 0) {
        epicsSnprintf(pasynUser->errorMessage,pasynUser->errorMessageSize,
                      "Can't set %s O_NONBLOCK option: %s",
                      tty->IPDeviceName, strerror(SOCKERRNO));
        epicsSocketDestroy(fd);
        return asynError;
    }
#endif

    asynPrint(pasynUser, ASYN_TRACE_FLOW,
              "Opened connection to %s\n", tty->IPDeviceName);
    tty->fd = fd;
    return asynSuccess;
}
Exemplo n.º 17
0
int BlockingTCPAcceptor::initialize() {

    char ipAddrStr[48];
    ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));

    int tryCount = 0;
    while(tryCount<2) {
        char strBuffer[64];

        LOG(logLevelDebug, "Creating acceptor to %s.", ipAddrStr);

        _serverSocketChannel = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(_serverSocketChannel==INVALID_SOCKET) {
            epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
            ostringstream temp;
            temp<<"Socket create error: "<<strBuffer;
            LOG(logLevelError, "%s", temp.str().c_str());
            THROW_BASE_EXCEPTION(temp.str().c_str());
        }
        else {

            //epicsSocketEnableAddressReuseDuringTimeWaitState(_serverSocketChannel);

            // try to bind
            int retval = ::bind(_serverSocketChannel, &_bindAddress.sa, sizeof(sockaddr));
            if(retval<0) {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                LOG(logLevelDebug, "Socket bind error: %s.", strBuffer);
                if(_bindAddress.ia.sin_port!=0) {
                    // failed to bind to specified bind address,
                    // try to get port dynamically, but only once
                    LOG(
                        logLevelDebug,
                        "Configured TCP port %d is unavailable, trying to assign it dynamically.",
                        ntohs(_bindAddress.ia.sin_port));
                    _bindAddress.ia.sin_port = htons(0);
                }
                else {
                    epicsSocketDestroy(_serverSocketChannel);
                    break; // exit while loop
                }
            }
            else { // if(retval<0)
                // bind succeeded

                // update bind address, if dynamically port selection was used
                if(ntohs(_bindAddress.ia.sin_port)==0) {
                    osiSocklen_t sockLen = sizeof(sockaddr);
                    // read the actual socket info
                    retval = ::getsockname(_serverSocketChannel, &_bindAddress.sa, &sockLen);
                    if(retval<0) {
                        // error obtaining port number
                        epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                        LOG(logLevelDebug, "getsockname error: %s", strBuffer);
                    }
                    else {
                        LOG(
                            logLevelInfo,
                            "Using dynamically assigned TCP port %d.",
                            ntohs(_bindAddress.ia.sin_port));
                    }
                }

                retval = ::listen(_serverSocketChannel, 4);
                if(retval<0) {
                    epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                    ostringstream temp;
                    temp<<"Socket listen error: "<<strBuffer;
                    LOG(logLevelError, "%s", temp.str().c_str());
                    THROW_BASE_EXCEPTION(temp.str().c_str());
                }

                _thread.start();

                // all OK, return
                return ntohs(_bindAddress.ia.sin_port);
            } // successful bind
        } // successfully obtained socket
        tryCount++;
    } // while

    ostringstream temp;
    temp<<"Failed to create acceptor to "<<ipAddrStr;
    THROW_BASE_EXCEPTION(temp.str().c_str());
}
Exemplo n.º 18
0
/*
 * Tests the log prefix code
 * The prefix is only applied to log messages as they go out to the socket,
 * so we need to create a server listening on a port, accept connections etc.
 * This code is a reduced version of the code in iocLogServer.
 */
static void testLogPrefix(void) {
    struct sockaddr_in serverAddr;
    int status;
    struct timeval timeout;
    struct sockaddr_in actualServerAddr;
    osiSocklen_t actualServerAddrSize;
    char portstring[16];


    testDiag("Testing iocLogPrefix");

    timeout.tv_sec = 5; /* in seconds */
    timeout.tv_usec = 0;

    memset((void*)prefixmsgbuffer, 0, sizeof prefixmsgbuffer);

    /* Clear "errlog: <n> messages were discarded" status */
    errlogPrintfNoConsole(".");
    errlogFlush();

    sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
        testAbort("epicsSocketCreate failed.");
    }

    /* We listen on a an available port. */
    memset((void *)&serverAddr, 0, sizeof serverAddr);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(0);

    status = bind (sock, (struct sockaddr *)&serverAddr,
                   sizeof (serverAddr) );
    if (status < 0) {
        testAbort("bind failed; all ports in use?");
    }

    status = listen(sock, 10);
    if (status < 0) {
        testAbort("listen failed!");
    }

    /* Determine the port that the OS chose */
    actualServerAddrSize = sizeof actualServerAddr;
    memset((void *)&actualServerAddr, 0, sizeof serverAddr);
    status = getsockname(sock, (struct sockaddr *) &actualServerAddr,
         &actualServerAddrSize);
    if (status < 0) {
        testAbort("Can't find port number!");
    }

    sprintf(portstring, "%d", ntohs(actualServerAddr.sin_port));
    testDiag("Listening on port %s", portstring);

    /* Set the EPICS environment variables for logging. */
    epicsEnvSet ( "EPICS_IOC_LOG_INET", "localhost" );
    epicsEnvSet ( "EPICS_IOC_LOG_PORT", portstring );

    pfdctx = (void *) fdmgr_init();
    if (status < 0) {
        testAbort("fdmgr_init failed!");
    }

    status = fdmgr_add_callback(pfdctx, sock, fdi_read,
        acceptNewClient, &serverAddr);

    if (status < 0) {
        testAbort("fdmgr_add_callback failed!");
    }

    testOk1(iocLogInit() == 0);
    fdmgr_pend_event(pfdctx, &timeout);

    testPrefixLogandCompare(prefixactualmsg[0]);

    iocLogPrefix(prefixstring);
    testPrefixLogandCompare(prefixactualmsg[1]);
    testPrefixLogandCompare(prefixactualmsg[2]);
    epicsSocketDestroy(sock);
}
Exemplo n.º 19
0
/*
 *  RSRV_ONLINE_NOTIFY_TASK
 */
void rsrv_online_notify_task(void *pParm)
{
    unsigned                    priorityOfSelf = epicsThreadGetPrioritySelf ();
    osiSockAddrNode             *pNode;
    double                      delay;
    double                      maxdelay;
    long                        longStatus;
    double                      maxPeriod;
    caHdr                       msg;
    int                         status;
    SOCKET                      sock;
    int                         intTrue = TRUE;
    unsigned short              port;
    ca_uint32_t                 beaconCounter = 0;
    char                        * pStr;
    int                         autoBeaconAddr;
    ELLLIST                     autoAddrList;
    char                        buf[16];
    unsigned                    priorityOfUDP;
    epicsThreadBooleanStatus    tbs;
    epicsThreadId               tid;
    
    taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
    
    if ( envGetConfigParamPtr ( & EPICS_CAS_BEACON_PERIOD ) ) {
        longStatus = envGetDoubleConfigParam ( & EPICS_CAS_BEACON_PERIOD, & maxPeriod );
    }
    else {
        longStatus = envGetDoubleConfigParam ( & EPICS_CA_BEACON_PERIOD, & maxPeriod );
    }
    if (longStatus || maxPeriod<=0.0) {
        maxPeriod = 15.0;
        epicsPrintf ("EPICS \"%s\" float fetch failed\n",
                        EPICS_CAS_BEACON_PERIOD.name);
        epicsPrintf ("Setting \"%s\" = %f\n",
            EPICS_CAS_BEACON_PERIOD.name, maxPeriod);
    }
    
    delay = 0.02; /* initial beacon period in sec */
    maxdelay = maxPeriod;
    
    /* 
     *  Open the socket.
     *  Use ARPA Internet address format and datagram socket.
     *  Format described in <sys/socket.h>.
     */
    if ( (sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
        errlogPrintf ("CAS: online socket creation error\n");
        epicsThreadSuspendSelf ();
    }
    
    status = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, 
                (char *)&intTrue, sizeof(intTrue));
    if (status<0) {
        errlogPrintf ("CAS: online socket set up error\n");
        epicsThreadSuspendSelf ();
    }

    {
        /*
         * this connect is to supress a warning message on Linux
         * when we shutdown the read side of the socket. If it
         * fails (and it will on old ip kernels) we just ignore 
         * the failure.
         */
        osiSockAddr sockAddr;
        sockAddr.ia.sin_family = AF_UNSPEC;
        sockAddr.ia.sin_port = htons ( 0 );
        sockAddr.ia.sin_addr.s_addr = htonl (0);
        connect ( sock, & sockAddr.sa, sizeof ( sockAddr.sa ) );
        shutdown ( sock, SHUT_RD );
    }
    
    memset((char *)&msg, 0, sizeof msg);
    msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP);
    msg.m_count = htons (ca_server_port);
    msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
    
    ellInit ( & beaconAddrList );
    ellInit ( & autoAddrList );

    pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf);
    if ( ! pStr ) {
	    pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf);
    }
	if (pStr) {
		if (strstr(pStr,"no")||strstr(pStr,"NO")) {
			autoBeaconAddr = FALSE;
		}
		else if (strstr(pStr,"yes")||strstr(pStr,"YES")) {
			autoBeaconAddr = TRUE;
		}
		else {
			fprintf(stderr, 
		"CAS: EPICS_CA(S)_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr);
			autoBeaconAddr = TRUE;
		}
	}
	else {
		autoBeaconAddr = TRUE;
	}

    /*
     * load user and auto configured
     * broadcast address list
     */
    if (envGetConfigParamPtr(&EPICS_CAS_BEACON_PORT)) {
        port = envGetInetPortConfigParam (&EPICS_CAS_BEACON_PORT, 
            (unsigned short) CA_REPEATER_PORT );
    }
    else {
        port = envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT, 
            (unsigned short) CA_REPEATER_PORT );
    }

    /*
     * discover beacon addresses associated with this interface
     */
    if ( autoBeaconAddr ) {
        osiSockAddr addr;
		ELLLIST tmpList;

		ellInit ( &tmpList );
        addr.ia.sin_family = AF_UNSPEC;
        osiSockDiscoverBroadcastAddresses (&tmpList, sock, &addr); 
        forcePort ( &tmpList, port );
		removeDuplicateAddresses ( &autoAddrList, &tmpList, 1 );
    }
            
    /*
     * by default use EPICS_CA_ADDR_LIST for the
     * beacon address list
     */
    {
        const ENV_PARAM *pParam;
        
        if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || 
            envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) {
            pParam = &EPICS_CAS_BEACON_ADDR_LIST;
        }
        else {
            pParam = &EPICS_CA_ADDR_LIST;
        }
    
        /* 
         * add in the configured addresses
         */
        addAddrToChannelAccessAddressList (
            &autoAddrList, pParam, port,  pParam == &EPICS_CA_ADDR_LIST );
    }
 
    removeDuplicateAddresses ( &beaconAddrList, &autoAddrList, 0 );

    if ( ellCount ( &beaconAddrList ) == 0 ) {
        errlogPrintf ("The CA server's beacon address list was empty after initialization?\n");
    }
  
#   ifdef DEBUG
        printChannelAccessAddressList (&beaconAddrList);
#   endif

    tbs  = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfUDP );
    if ( tbs != epicsThreadBooleanStatusSuccess ) {
        priorityOfUDP = priorityOfSelf;
    }

    casudp_startStopEvent = epicsEventMustCreate(epicsEventEmpty);
    casudp_ctl = ctlPause;

    tid = epicsThreadCreate ( "CAS-UDP", priorityOfUDP,
        epicsThreadGetStackSize (epicsThreadStackMedium),
        cast_server, 0 );
    if ( tid == 0 ) {
        epicsPrintf ( "CAS: unable to start UDP daemon thread\n" );
    }

    epicsEventMustWait(casudp_startStopEvent);
    epicsEventSignal(beacon_startStopEvent);

    while (TRUE) {
        pNode = (osiSockAddrNode *) ellFirst (&beaconAddrList);
        while (pNode) {
            char buf[64];

            status = connect (sock, &pNode->addr.sa, 
                sizeof(pNode->addr.sa));
            if (status<0) {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
                errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n",
                    __FILE__, buf, sockErrBuf);
            }
            else {
                struct sockaddr_in if_addr;

                osiSocklen_t size = sizeof (if_addr);
                status = getsockname (sock, (struct sockaddr *) &if_addr, &size);
                if (status<0) {
                    char sockErrBuf[64];
                    epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
                    errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n",
                        __FILE__, sockErrBuf);
                }
                else if (if_addr.sin_family==AF_INET) {
                    msg.m_available = if_addr.sin_addr.s_addr;
                    msg.m_cid = htonl ( beaconCounter );

                    status = send (sock, (char *)&msg, sizeof(msg), 0);
                    if (status < 0) {
                        char sockErrBuf[64];
                        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
                        ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
                        errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n",
                            __FILE__, buf, sockErrBuf);
                    }
                    else {
                        assert (status == sizeof(msg));
                    }
                }
            }
            pNode = (osiSockAddrNode *) pNode->node.next;
        }

        epicsThreadSleep(delay);
        if (delay<maxdelay) {
            delay *= 2.0;
            if (delay>maxdelay) {
                delay = maxdelay;
            }
        }

        beaconCounter++; /* expected to overflow */

        while (beacon_ctl == ctlPause) {
            epicsThreadSleep(0.1);
            delay = 0.02; /* Restart beacon timing if paused */
        }
    }
}
Exemplo n.º 20
0
int socketpair_compat(int af, int st, int p, SOCKET sd[2])
{
    SOCKET listener;
    int ret = -1;
    osiSockAddr ep[2];
    osiSocklen_t slen = sizeof(ep[0]);

    if(st!=SOCK_STREAM) {
        SOCKERRNOSET(SOCK_EINVAL);
        return -1;
    }

    listener = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
    sd[0] = INVALID_SOCKET;
    sd[1] = shCreateSocket(AF_INET, SOCK_STREAM, 0);

    if(listener==INVALID_SOCKET || sd[1]==INVALID_SOCKET) {
        SOCKERRNOSET(SOCK_EMFILE);
        goto fail;
    }

    memset(ep, 0, sizeof(ep));
    ep[0].ia.sin_family = AF_INET;
    ep[0].ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    if(bind(listener, &ep[0].sa, sizeof(ep[0])))
        goto fail;

    if(getsockname(listener, &ep[0].sa, &slen))
        goto fail;

    if(listen(listener, 2))
        goto fail;

    /* we can't possibly succeed immediately */
    if(connect(sd[1], &ep[0].sa, sizeof(ep[0]))!=-1)
        goto fail;

    if(SOCKERRNO!=SOCK_EINPROGRESS)
        goto fail;

    while(1) {
        int err;
        shSocket atemp;
        SOCKET temp;
        osiSocklen_t olen = sizeof(err);

        slen = sizeof(ep[1]);
        temp = epicsSocketAccept(listener, &ep[1].sa, &slen);

        if(temp==INVALID_SOCKET) {
            if(SOCKERRNO==SOCK_EINTR)
                continue;
            goto fail;
        }

        shSocketInit(&atemp);
        atemp.sd = sd[1];

        if(shWaitFor(&atemp, SH_CANTX, 0)) {
            /* someone raced us and won... */
            epicsSocketDestroy(temp);
            continue;
        }

        if(getsockopt(sd[1], SOL_SOCKET, SO_ERROR, (char*)&err, &olen))
            goto fail;

        if(err) {
            SOCKERRNOSET(err);
            goto fail;
        }

        sd[0] = temp;
        break;
    }

    {
        /* restore blocking IO */
        osiSockIoctl_t flag = 0;
        if(socket_ioctl(sd[1], FIONBIO, &flag))
            goto fail;
    }

    epicsSocketDestroy(listener);

    return 0;
fail:
    if(listener!=INVALID_SOCKET)
        epicsSocketDestroy(sd[0]);
    if(listener!=INVALID_SOCKET)
        epicsSocketDestroy(sd[0]);
    if(sd[1]!=INVALID_SOCKET)
        epicsSocketDestroy(sd[1]);
    return ret;
}
void* module_data_parser_thread(void* arg){
    int is_autocal_data, reg_data,i,j,k,code_depth,err;
    unsigned short *local_buffer_ptr,*temp_us_ptr,*conv,*process_buf_ptr,*netbuffer,frame_header[HEADER_LENGHT];
    unsigned short packet_tag,slot_id=0;
    unsigned char th_dac=0,loop_mode=0;
    unsigned short this_frame_has_aligment_errors;
    SOCKET data_socket;
    struct sockaddr_in sock_addr;
    int status;

    local_buffer_ptr=databuffer_allocation(PIXIEII_MODULES*MATRIX_DIM_WORDS*15);//la dimensione in byte di un intero frame
    if(local_buffer_ptr==NULL){
        printf("PROC:error allocating buffers\n");
        exit(-1);}
    else{
        if(verbose>=2)printf("PROC:Processing Thread Started\n");
    }
    /***TCP/IP monitor***************inizio********************dacounting_daq.cpp********************/
    sock_addr.sin_family=AF_INET; // indico il protocollo utilizzato (TCP/IP)
    sock_addr.sin_port=htons(4444); //indico la porta a cui connettere il socket
    if (hostToIPAddr("127.0.0.1", &sock_addr.sin_addr) < 0)
        printf("PROC:hostToIPAddr failed\n");
    // The following is not supported on Linux.  Is it needed?
    //sock_addr.sin_addr.S_un.S_un_b.s_b1=127; // indico l'indirizzo IP
    //sock_addr.sin_addr.S_un.S_un_b.s_b2=0;
    //sock_addr.sin_addr.S_un.S_un_b.s_b3=0;
    //sock_addr.sin_addr.S_un.S_un_b.s_b4=1;
    netbuffer=databuffer_allocation((MATRIX_DIM_WORDS*PIXIEII_MODULES)+HEADER_LENGHT);

    /*****TCP/IP monitor****************fine********************dacounting_daq.cpp********************/
    printf("PROC:data Parser Thread started\n");
    conv=conversion_table_allocation();

    while(1){
        status = epicsMessageQueueReceive(ptr_list, &process_buf_ptr, sizeof(&process_buf_ptr));
printf("module_data_parser_thread: got process_buf_ptr=%p\n", process_buf_ptr);
        if (status <= 0){
            printf("PROC: error epicsMessageQueueReceive returned %d\n", status);
            continue;
        }
        if (process_buf_ptr==NULL){
            printf("PROC: error process_buf_ptr=NULL\n");
            continue;
        }
        packet_tag=*(process_buf_ptr+PACKET_TAG_OFFSET*2);
        th_dac=(packet_tag>>(PIXIE_THDAC_OFFSET+DUMMY_0_OFFSET))&PIXIE_THDAC_MASK;
        loop_mode=(packet_tag>>(LOOP_MODE_OFFSET+DUMMY_1_OFFSET))&LOOP_MODE_MASK;
        if(verbose>=2)printf("\nPROC: packet_tag=%04xh\n",packet_tag);
        if(verbose>=2)printf("\nPROC: th_dac=%d, loop_mode=%02Xh\n",th_dac,loop_mode);
        slot_id=*((char*)process_buf_ptr+SLOT_ID_OFFSET)&SLOT_ID_MASK;
        if(verbose>=2)printf("PROC: slot_id=%04xh\n",slot_id);
        if(packet_tag & AUTOCAL_DATA){
            if(verbose>=2)printf("\nPROC:Autocal");
            code_depth=5;
            is_autocal_data=1;
        } else{
            if(verbose>=2)printf("\nPROC:Counters");
            code_depth=15;
            is_autocal_data=0;
        }
        if(packet_tag & REG_PACKET){
            if(verbose>=2)printf("\nPROC:REG 1 data\n");
            reg_data=1;
        } else{
            if(verbose>=2)printf("\nPROC:REG 0 data\n");
            reg_data=0;
        }
        if(packet_tag & FRAME_HAS_ALIGN_ERRORS){
            this_frame_has_aligment_errors=1;
        } else{
            this_frame_has_aligment_errors=0;
        }

        temp_us_ptr=process_buf_ptr+(PACKET_TAG_BYTES/2);
        if(verbose>=3)printf("local_buffer filling code_depth=%d\n",code_depth);
        for(i=0;i<PIXIEII_MODULES;i++) {
            for(j=0;j<COLS_PER_DOUT*PIXIE_ROWS;j++) {
                for(k=0;k<code_depth;k++){
                    my_bytes_swap(temp_us_ptr+i+(j*PIXIEII_MODULES*code_depth)+(k*PIXIEII_MODULES));
                    local_buffer_ptr[(i*COLS_PER_DOUT*PIXIE_ROWS*code_depth)+(j*code_depth)+k]=
                        temp_us_ptr[i+(j*PIXIEII_MODULES*code_depth)+(k*PIXIEII_MODULES)];
                }
            }
        }
        //printf("local_buffer has been filled with original data and data modules are grouped\n");
        //memcpy(buff+PACKET_TAG_BYTES,process_buf_ptr+PACKET_TAG_BYTES,PIXIEII_MODULES*MATRIX_DIM_WORDS*code_depth);
        for(i=0;i<PIXIEII_MODULES;i++){
            //printf("parsing %d module data\n",i);
            for(j=0;j<COLS_PER_DOUT*PIXIE_ROWS;j++) {
                convert_bit_stream_to_counts(code_depth,
                    local_buffer_ptr+(i*COLS_PER_DOUT*PIXIE_ROWS*code_depth)+(j*code_depth),
                    process_buf_ptr+(i*MATRIX_DIM_WORDS)+(j*PIXIE_DOUTS)+(PACKET_TAG_BYTES/2),PIXIE_DOUTS);

            }
        }
        //printf("data parsed\n");
        for(i=0;i<PIXIEII_MODULES;i++){
            //printf("processing module %d data\n,i);
            if(is_autocal_data==0 && convert_data==1)
                decode_pixie_data_buffer(conv,process_buf_ptr+(PACKET_TAG_BYTES/2)+i*MATRIX_DIM_WORDS);
            databuffer_sorting(process_buf_ptr+(PACKET_TAG_BYTES/2)+i*MATRIX_DIM_WORDS);
            map_data_buffer_on_pixie(process_buf_ptr+(PACKET_TAG_BYTES/2)+i*MATRIX_DIM_WORDS);
        }

        /*********************sendig data to TCPIP monitor*********************/
        for(i=0;i<HEADER_LENGHT;i++) frame_header[i]=0x8000;
        frame_header[0]=BUFFER_HDR_TAG;
        frame_header[1]|=(unsigned short)(this_frame_has_aligment_errors);
        frame_header[2]|=(unsigned short)(is_autocal_data);
        frame_header[3]|=(sh_code & 0x1);
        frame_header[4]|=(unsigned short)ceil((double)shutter_duration_ms);
        frame_header[5]|=(unsigned short)slot_id;
        if(reg_data==0)
            frame_header[6]|=REG_0_BUFF_CODE;
        else
            frame_header[6]|=REG_1_BUFF_CODE;
        for(i=0;i<HEADER_LENGHT;i++) netbuffer[i]=frame_header[i];
        for(i=0;i<MATRIX_DIM_WORDS*PIXIEII_MODULES;i++) netbuffer[i+HEADER_LENGHT]=process_buf_ptr[i+(PACKET_TAG_BYTES/2)];
        data_socket=epicsSocketCreate(PF_INET,SOCK_STREAM,0);
        err=connect(data_socket,(struct sockaddr*)&sock_addr,sizeof(struct sockaddr));
        if(!err) {
            if (verbose>=1)printf("\r\nI got Pixie!!");
        } else
            if (verbose>=1)printf("\r\nGot error attempting to connect to pixie = %s",strerror(errno));
        if(!err) send(data_socket,(const char*)netbuffer,(MATRIX_DIM*PIXIEII_MODULES)+(HEADER_LENGHT*2),0);
        if(!err)epicsSocketDestroy(data_socket);
        /*********************sendig data to TCPIP monitor*********************/
        free(process_buf_ptr);
        if (verbose>=1)printf("PROC:pocessing buffer released\n");

    }
    free(local_buffer_ptr);//qui non ci arriverà mai!!!!
}
int main(int argc, char**argv)
{
    struct sockaddr_in si_me;
    struct sockaddr_in moderator_udp_sockaddr;
    unsigned short packet_tag;
    unsigned int i,j,temp_NPACK;
    SOCKET s, moderator_udp_sock_fd;
    int this_frame_has_aligment_errors=0;
    char temp_char;
    unsigned int packet_id, local_packet_id;
    long packet_id_gap;
    int received_data_subsets=0;
    moderation_type moderation=NOUDPMOD;
    clock_t timer_a=0,timer_b;
    double  time_interval;
    char moderator_string[MAX_STRLEN];
    id_mode packet_id_mode;

    ptr_list = epicsMessageQueueCreate(MAX_PENDING_BUFFERS, sizeof(unsigned char *));
    if (ptr_list == 0) {
        printf("epicsMessageQueueCreate failed\n");
        return -1;
    }

    if (osiSockAttach() == 0) {
        printf("osiSockAttach failed\n");
        return -1;
    }

    if(argc==4){
        if (strcmp(argv[3],"UDPMOD")==0)
            moderation=UDPMOD;
        else
            moderation=NOUDPMOD;
        verbose=atoi(argv[2]);
        if (strcmp(argv[1],"FRAG_ID")==0)
            packet_id_mode=FRAG_ID;
        else
            packet_id_mode=NOFRAG_ID;
    }
    if(argc==3){
        verbose=atoi(argv[2]);
        if (strcmp(argv[1],"FRAG_ID")==0)
            packet_id_mode=FRAG_ID;
        else
            packet_id_mode=NOFRAG_ID;
    }
    else if(argc==2){
        verbose=0;
        if (strcmp(argv[1],"FRAG_ID")==0)
            packet_id_mode=FRAG_ID;
        else
            packet_id_mode=NOFRAG_ID;
    }
    else{
        verbose=0;
        packet_id_mode=FRAG_ID;
        moderation=NOUDPMOD;
    }

    buf=(unsigned char*)databuffer_allocation(MAX_PACK_LEN*DEFAULT_NPACK);


    if ((s=epicsSocketCreate(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    {
        printf("\r\nError creating socket error =%s", strerror(errno));
        scanf("%c%*c",&temp_char);
        return 1;
    }

    memset((char *) &si_me, 0, sizeof(si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORTA);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me))==-1)
    {
        printf("\r\nError in binding data receiver socket");
        //wait_akey();
        return 1;
    }


    if ((moderator_udp_sock_fd=epicsSocketCreate(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    {
        printf("\r\nError creating moderator socket error =%s", strerror(errno));
        scanf("%c%*c",&temp_char);
        return 1;
    }

    memset((char *) &moderator_udp_sockaddr, 0, sizeof(moderator_udp_sockaddr));
    moderator_udp_sockaddr.sin_family = AF_INET;
    moderator_udp_sockaddr.sin_port = htons(MOD_UDP_REMOTE_PORT);
    // The following is not support on Linux.  Is it needed?
    if (hostToIPAddr("192.168.0.255", &moderator_udp_sockaddr.sin_addr) < 0)
        printf("PROC:hostToIPAddr failed\n");
    //moderator_udp_sockaddr.sin_addr.S_un.S_un_b.s_b1=192; //l'indirizzo IP!!!
    //moderator_udp_sockaddr.sin_addr.S_un.S_un_b.s_b2=168;
    //moderator_udp_sockaddr.sin_addr.S_un.S_un_b.s_b3=0;
    //moderator_udp_sockaddr.sin_addr.S_un.S_un_b.s_b4=255;

    int buffsize;
    osiSocklen_t czm = sizeof( int);
    int received_bytes;
    buffsize = MAXBUF;
    if (setsockopt(s, SOL_SOCKET,
                   SO_RCVBUF,
                   (char*)&buffsize,
                   czm) != -1)
    {
        if(verbose>=2)printf("\r\nTrying to set Receive Buffer = %d", buffsize);
    }

    if (getsockopt(s, SOL_SOCKET,
                   SO_RCVBUF,
                   (char*)&buffsize,
                   &czm) != -1)
    {
        if(verbose>=2)printf("\r\nReceive buffer is now = %d  ", buffsize);
        if (buffsize == MAXBUF)
        {
            if(verbose>=2)printf("OK");
        }
        else
        {
            if(verbose>=2)printf("ERROR Buffer Size too big!");
        }
    }
    epicsThreadCreate("key_proc",
                       epicsThreadPriorityMedium,
                       epicsThreadGetStackSize(epicsThreadStackMedium),
                       (EPICSTHREADFUNC)key_proc, (void*)&i);

    epicsThreadCreate("module_data_parser_thread",
                       epicsThreadPriorityMedium,
                       epicsThreadGetStackSize(epicsThreadStackMedium),
                       (EPICSTHREADFUNC)module_data_parser_thread, NULL);

    while(looping){
//        sem_wait(&(ptr_list.put_sem));
        this_frame_has_aligment_errors=0;
        temp_NPACK=DEFAULT_NPACK;
        i=0;
        if(packet_id_mode==FRAG_ID){
            while(i<temp_NPACK ){
                j=0;
                while(j<DAQ_PACK_FRAGM){
                    received_bytes=recvfrom(s,(char*) buf+(i*MAX_PACK_LEN), MAX_PACK_LEN,0, NULL, 0);
                    if (received_bytes== -1)
                        printf("\rError receiveing datagram");
                    else if(received_bytes==MAX_PACK_LEN){
                        if(i==0)  timer_a=clock();

                        received_packets++;
                        packet_tag=*buf;
                        if(packet_tag & AUTOCAL_DATA)
                            temp_NPACK=AUTOCAL_NPACK;
                        else
                            temp_NPACK=DEFAULT_NPACK;

                        /********************************************************************/;
                        packet_id=buf[MAX_PACK_LEN*(i)+PACKET_ID_OFFSET]<<8;
                        packet_id+=buf[MAX_PACK_LEN*(i)+1+PACKET_ID_OFFSET];
                        packet_id=packet_id%DAQ_PACK_FRAGM;
                        packet_id_gap=(packet_id-j);

                        if(packet_id_gap!=0){
                            if(id_error_packets<10)
                                printf("ID: %d j= %d\n",packet_id,j);
                            id_error_packets++;
                            this_frame_has_aligment_errors=1;
                        }
                        if(packet_id_gap>=0){
                            j+=(packet_id_gap+1);
                            i+=(packet_id_gap+1);
                        }
                        else{
                            j=DAQ_PACK_FRAGM;
                            i+=DAQ_PACK_FRAGM;
                        }

                    }
                }
                if(moderation==UDPMOD){
                    sprintf(moderator_string,"DATASUBSET_RECEIVED %d %d\n",received_data_subsets,temp_NPACK/DAQ_PACK_FRAGM);
                    received_data_subsets++;
                    if (sendto(moderator_udp_sock_fd,
                               moderator_string,
                               strlen(moderator_string),
                               0,
                               (struct sockaddr*)&moderator_udp_sockaddr,
                               (osiSocklen_t)sizeof(moderator_udp_sockaddr))==-1)
                        printf("\r\n!!Error sending moderating datagram!!");
                }
            }
       } else{
            while(i<temp_NPACK ){
                received_bytes=recvfrom(s,(char*) buf+(i*MAX_PACK_LEN), MAX_PACK_LEN,0, NULL, 0);
                if (received_bytes== -1)
                    printf("\rError receiveing datagram");
                else if(received_bytes==MAX_PACK_LEN){
                    if(i==0)  timer_a=clock();
                    //i++;j++;
                    received_packets++;
                    packet_tag=*buf;
                    if(packet_tag & AUTOCAL_DATA)
                        temp_NPACK=AUTOCAL_NPACK;
                    else
                        temp_NPACK=DEFAULT_NPACK;

                    packet_id=buf[MAX_PACK_LEN*(i)+PACKET_ID_OFFSET]<<8;
                    packet_id+=buf[MAX_PACK_LEN*(i)+1+PACKET_ID_OFFSET];
                    packet_id_gap=(packet_id-i);//
                    if(packet_id_gap!=0){
                        id_error_packets++;
                        this_frame_has_aligment_errors=1;
                    }
                    if(packet_id_gap>=0){
                        i+=(packet_id_gap+1);
                    }
                    else{
                        i=temp_NPACK;
                    }


                    if((i%DAQ_PACK_FRAGM)==0 && i!=0 && moderation==UDPMOD){
                        sprintf(moderator_string,"DATASUBSET_RECEIVED %d %d\n",received_data_subsets,temp_NPACK/DAQ_PACK_FRAGM);
                        received_data_subsets++;
                        if (sendto(moderator_udp_sock_fd,
                                   moderator_string,
                                   strlen(moderator_string),
                                   0,
                                   (struct sockaddr*)&moderator_udp_sockaddr,
                                   sizeof(moderator_udp_sockaddr))==-1)
                            printf("\r\n!!Error sending moderating datagram!!");
                    }
                }
            }
        }


        received_data_subsets=0;

        if(verbose>=1){
            timer_b=clock();
            time_interval=(double)(timer_b-timer_a)/CLOCKS_PER_SEC;
            printf("MAIN:%d packets(%d bytes each) have been received in %.3f s ",i,MAX_PACK_LEN,time_interval);
            printf("(%.3f Mbps)\n",(i*MAX_PACK_LEN*8)/(time_interval*1024*1024));
        }

        i=0;
        local_packet_id=0;
        process_buf=(unsigned char*)databuffer_allocation((MAX_PACK_LEN-PACKET_EXTRA_BYTES+PACKET_TAG_BYTES)*DEFAULT_NPACK);
        if((buf==NULL)||(process_buf==NULL)){
            printf("error allocating buffers\n");
            exit(0);
            }
        else
            if(verbose>=1)
                printf("MAIN:New Processing Buffer Allocated\n");
        while((i<temp_NPACK))
        {
            memcpy(process_buf+PACKET_TAG_BYTES+(PACKET_SENSOR_DATA_BYTES*local_packet_id),
                   buf+PACKET_SENSOR_DATA_OFFSET+(MAX_PACK_LEN*i), PACKET_SENSOR_DATA_BYTES);
            for(j=0;j<PACKET_TAG_BYTES;j++)
                process_buf[PACKET_TAG_OFFSET+j]=buf[j];//copio il PACKET_TAG del buffer per processing
            if(this_frame_has_aligment_errors)
                process_buf[PACKET_TAG_OFFSET]|=FRAME_HAS_ALIGN_ERRORS;
            else
                process_buf[PACKET_TAG_OFFSET]&=(~FRAME_HAS_ALIGN_ERRORS);
            local_packet_id++;
            i++;
        }
printf("Main: sending process_buf=%p\n", process_buf);
        epicsMessageQueueSend(ptr_list, &process_buf, sizeof(&process_buf));


    }
    free(buf);
    free(process_buf);
    scanf("%c%*c",&temp_char);
    return EXIT_SUCCESS;
}
Exemplo n.º 23
0
/*
 *
 * main()
 *
 */
int main(void)
{
    struct sockaddr_in serverAddr;  /* server's address */
    struct timeval timeout;
    int status;
    struct ioc_log_server *pserver;

    osiSockIoctl_t  optval;

    status = getConfig();
    if (status<0) {
        fprintf(stderr, "iocLogServer: EPICS environment underspecified\n");
        fprintf(stderr, "iocLogServer: failed to initialize\n");
        return IOCLS_ERROR;
    }

    pserver = (struct ioc_log_server *) 
            calloc(1, sizeof *pserver);
    if (!pserver) {
        fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
        return IOCLS_ERROR;
    }

    pserver->pfdctx = (void *) fdmgr_init();
    if (!pserver->pfdctx) {
        fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
        return IOCLS_ERROR;
    }

    /*
     * Open the socket. Use ARPA Internet address format and stream
     * sockets. Format described in <sys/socket.h>.
     */
    pserver->sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
    if (pserver->sock == INVALID_SOCKET) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf(stderr, "iocLogServer: sock create err: %s\n", sockErrBuf);
        free(pserver);
        return IOCLS_ERROR;
    }
    
    epicsSocketEnableAddressReuseDuringTimeWaitState ( pserver->sock );

    /* Zero the sock_addr structure */
    memset((void *)&serverAddr, 0, sizeof serverAddr);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(ioc_log_port);

    /* get server's Internet address */
    status = bind ( pserver->sock, 
            (struct sockaddr *)&serverAddr, 
            sizeof (serverAddr) );
    if (status < 0) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf(stderr, "iocLogServer: bind err: %s\n", sockErrBuf );
        fprintf (stderr,
            "iocLogServer: a server is already installed on port %u?\n", 
            (unsigned)ioc_log_port);
        return IOCLS_ERROR;
    }

    /* listen and accept new connections */
    status = listen(pserver->sock, 10);
    if (status < 0) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf(stderr, "iocLogServer: listen err %s\n", sockErrBuf);
        return IOCLS_ERROR;
    }

    /*
     * Set non blocking IO
     * to prevent dead locks
     */
    optval = TRUE;
    status = socket_ioctl(
                    pserver->sock,
                    FIONBIO,
                    &optval);
    if (status < 0){
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
        fprintf(stderr, "iocLogServer: ioctl FIONBIO err %s\n", sockErrBuf);
        return IOCLS_ERROR;
    }

#   ifdef UNIX
        status = setupSIGHUP(pserver);
        if (status < 0) {
            return IOCLS_ERROR;
        }
#   endif

    status = openLogFile(pserver);
    if (status < 0) {
        fprintf(stderr,
            "File access problems to `%s' because `%s'\n", 
            ioc_log_file_name,
            strerror(errno));
        return IOCLS_ERROR;
    }

    status = fdmgr_add_callback(
            pserver->pfdctx, 
            pserver->sock, 
            fdi_read,
            acceptNewClient,
            pserver);
    if (status < 0) {
        fprintf(stderr,
            "iocLogServer: failed to add read callback\n");
        return IOCLS_ERROR;
    }


    while (TRUE) {
        timeout.tv_sec = 60; /* 1 min */
        timeout.tv_usec = 0;
        fdmgr_pend_event(pserver->pfdctx, &timeout);
        fflush(pserver->poutfile);
    }
}
Exemplo n.º 24
0
//
// udpiiu::udpiiu ()
//
udpiiu::udpiiu ( 
    epicsGuard < epicsMutex > & cacGuard,
    epicsTimerQueueActive & timerQueue, 
    epicsMutex & cbMutexIn, 
    epicsMutex & cacMutexIn,
    cacContextNotify & ctxNotifyIn,
    cac & cac,
    unsigned port,
    tsDLList < SearchDest > & searchDestListIn ) :
    recvThread ( *this, ctxNotifyIn, cbMutexIn, "CAC-UDP", 
        epicsThreadGetStackSize ( epicsThreadStackMedium ),
        cac::lowestPriorityLevelAbove (
            cac::lowestPriorityLevelAbove (
                cac.getInitializingThreadsPriority () ) ) ),
    m_repeaterTimerNotify ( *this ),
    repeaterSubscribeTmr (
        m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
    govTmr ( *this, timerQueue, cacMutexIn ),
    maxPeriod ( maxSearchPeriodDefault ),
    rtteMean ( minRoundTripEstimate ),
    rtteMeanDev ( 0 ),
    cacRef ( cac ),
    cbMutex ( cbMutexIn ),
    cacMutex ( cacMutexIn ),
    nBytesInXmitBuf ( 0 ),
    nTimers ( 0 ),
    beaconAnomalyTimerIndex ( 0 ),
    sequenceNumber ( 0 ),
    lastReceivedSeqNo ( 0 ),
    sock ( 0 ),
    repeaterPort ( 0 ),
    serverPort ( port ),
    localPort ( 0 ),
    shutdownCmd ( false ),
    lastReceivedSeqNoIsValid ( false )
{
    cacGuard.assertIdenticalMutex ( cacMutex );
    
    if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
        long longStatus = envGetDoubleConfigParam ( 
            & EPICS_CA_MAX_SEARCH_PERIOD, & this->maxPeriod );
        if ( ! longStatus ) {
            if ( this->maxPeriod < maxSearchPeriodLowerLimit ) {
                epicsPrintf ( "\"%s\" out of range (low)\n",
                                EPICS_CA_MAX_SEARCH_PERIOD.name );
                this->maxPeriod = maxSearchPeriodLowerLimit;
                epicsPrintf ( "Setting \"%s\" = %f seconds\n",
                    EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
            }
        }
        else {
            epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
                            EPICS_CA_MAX_SEARCH_PERIOD.name );
            epicsPrintf ( "Setting \"%s\" = %f seconds\n",
                EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
        }
    }

    double powerOfTwo = log ( this->maxPeriod / minRoundTripEstimate ) / log ( 2.0 );
    this->nTimers = static_cast < unsigned > ( powerOfTwo + 1.0 );
    if ( this->nTimers > channelNode::getMaxSearchTimerCount () ) {
        this->nTimers = channelNode::getMaxSearchTimerCount ();
        epicsPrintf ( "\"%s\" out of range (high)\n",
                        EPICS_CA_MAX_SEARCH_PERIOD.name );
        epicsPrintf ( "Setting \"%s\" = %f seconds\n",
            EPICS_CA_MAX_SEARCH_PERIOD.name, 
            (1<<(this->nTimers-1)) * minRoundTripEstimate );
    }

    powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
    this->beaconAnomalyTimerIndex = static_cast < unsigned > ( powerOfTwo + 1.0 );
    if ( this->beaconAnomalyTimerIndex >= this->nTimers ) {
        this->beaconAnomalyTimerIndex = this->nTimers - 1;
    }

    this->ppSearchTmr.reset ( new epics_auto_ptr < class searchTimer > [ this->nTimers ] );
    for ( unsigned i = 0; i < this->nTimers; i++ ) {
        this->ppSearchTmr[i].reset ( 
            new searchTimer ( *this, timerQueue, i, cacMutexIn, 
                i > this->beaconAnomalyTimerIndex ) ); 
    }

    this->repeaterPort = 
        envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT,
                                    static_cast <unsigned short> (CA_REPEATER_PORT) );

    this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
    if ( this->sock == INVALID_SOCKET ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        errlogPrintf ("CAC: unable to create datagram socket because = \"%s\"\n",
            sockErrBuf );
        throwWithLocation ( noSocket () );
    }

    int boolValue = true;
    int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST, 
                (char *) &boolValue, sizeof ( boolValue ) );
    if ( status < 0 ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        errlogPrintf ("CAC: IP broadcasting enable failed because = \"%s\"\n",
            sockErrBuf );
    }

#if 0
    {
        /*
         * some concern that vxWorks will run out of mBuf's
         * if this change is made joh 11-10-98
         *
         * bump up the UDP recv buffer
         */
        int size = 1u<<15u;
        status = setsockopt ( this->sock, SOL_SOCKET, SO_RCVBUF,
                (char *)&size, sizeof (size) );
        if (status<0) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf ( "CAC: unable to set socket option SO_RCVBUF because \"%s\"\n",
                sockErrBuf );
        }
    }
#endif

    // force a bind to an unconstrained address so we can obtain
    // the local port number below
    static const unsigned short PORT_ANY = 0u;
    osiSockAddr addr;
    memset ( (char *)&addr, 0 , sizeof (addr) );
    addr.ia.sin_family = AF_INET;
    addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); 
    addr.ia.sin_port = htons ( PORT_ANY );
    status = bind (this->sock, &addr.sa, sizeof (addr) );
    if ( status < 0 ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        epicsSocketDestroy (this->sock);
        errlogPrintf ( "CAC: unable to bind to an unconstrained address because = \"%s\"\n",
            sockErrBuf );
        throwWithLocation ( noSocket () );
    }
    
    {
        osiSockAddr tmpAddr;
        osiSocklen_t saddr_length = sizeof ( tmpAddr );
        status = getsockname ( this->sock, &tmpAddr.sa, &saddr_length );
        if ( status < 0 ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            epicsSocketDestroy ( this->sock );
            errlogPrintf ( "CAC: getsockname () error was \"%s\"\n", sockErrBuf );
            throwWithLocation ( noSocket () );
        }
        if ( tmpAddr.sa.sa_family != AF_INET) {
            epicsSocketDestroy ( this->sock );
            errlogPrintf ( "CAC: UDP socket was not inet addr family\n" );
            throwWithLocation ( noSocket () );
        }
        this->localPort = ntohs ( tmpAddr.ia.sin_port );
    }

    /*
     * load user and auto configured
     * broadcast address list
     */
    ELLLIST dest;
    ellInit ( & dest );
    configureChannelAccessAddressList ( & dest, this->sock, this->serverPort );
    while ( osiSockAddrNode * 
        pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
        SearchDestUDP & searchDest = * 
            new SearchDestUDP ( pNode->addr, *this );
        _searchDestList.add ( searchDest );
        free ( pNode );
    }

    /* add list of tcp name service addresses */
    _searchDestList.add ( searchDestListIn );
    
    caStartRepeaterIfNotInstalled ( this->repeaterPort );

    this->pushVersionMsg ();

    // start timers and receive thread
    for ( unsigned j =0; j < this->nTimers; j++ ) {
        this->ppSearchTmr[j]->start ( cacGuard ); 
    }
    this->govTmr.start ();
    this->repeaterSubscribeTmr.start ();
    this->recvThread.start ();
}