static void acceptNewClient ( void *pParam )
{
    osiSocklen_t addrSize;
    struct sockaddr_in addr;
    int status;

    addrSize = sizeof ( addr );
    insock = epicsSocketAccept ( sock, (struct sockaddr *)&addr, &addrSize );
    testOk(insock != INVALID_SOCKET && addrSize >= sizeof (addr),
        "Accepted new client");

    status = fdmgr_add_callback(pfdctx, insock, fdi_read,
        readFromClient,  NULL);

    testOk(status >= 0, "Client read configured");
}
Beispiel #2
0
/*
 *	acceptNewClient()
 *
 */
static void acceptNewClient ( void *pParam )
{
	struct ioc_log_server *pserver = (struct ioc_log_server *) pParam;
	struct iocLogClient	*pclient;
	osiSocklen_t addrSize;
	struct sockaddr_in addr;
	int status;
	osiSockIoctl_t optval;

	pclient = ( struct iocLogClient * ) malloc ( sizeof ( *pclient ) );
	if ( ! pclient ) {
		return;
	}

	addrSize = sizeof ( addr );
	pclient->insock = epicsSocketAccept ( pserver->sock, (struct sockaddr *)&addr, &addrSize );
	if ( pclient->insock==INVALID_SOCKET || addrSize < sizeof (addr) ) {
        static unsigned acceptErrCount;
        static int lastErrno;
        int thisErrno;

		free ( pclient );
		if ( SOCKERRNO == SOCK_EWOULDBLOCK || SOCKERRNO == SOCK_EINTR ) {
            return;
		}

        thisErrno = SOCKERRNO;
        if ( acceptErrCount % 1000 || lastErrno != thisErrno ) {
            fprintf ( stderr, "Accept Error %d\n", SOCKERRNO );
        }
        acceptErrCount++;
        lastErrno = thisErrno;

		return;
	}

	/*
	 * Set non blocking IO
	 * to prevent dead locks
	 */
	optval = TRUE;
	status = socket_ioctl(
					pclient->insock,
					FIONBIO,
					&optval);
	if(status<0){
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
		fprintf(stderr, "%s:%d ioctl FBIO client er %s\n", 
			__FILE__, __LINE__, sockErrBuf);
		epicsSocketDestroy ( pclient->insock );
		free(pclient);
		return;
	}

	pclient->pserver = pserver;
	pclient->nChar = 0u;

	ipAddrToA (&addr, pclient->name, sizeof(pclient->name));

	logTime(pclient);
	
#if 0
	status = fprintf(
		pclient->pserver->poutfile,
		"%s %s ----- Client Connect -----\n",
		pclient->name,
		pclient->ascii_time);
	if(status<0){
		handleLogFileError();
	}
#endif

	/*
	 * turn on KEEPALIVE so if the client crashes
	 * this task will find out and exit
	 */
	{
		long true = 1;

		status = setsockopt(
				pclient->insock,
				SOL_SOCKET,
				SO_KEEPALIVE,
				(char *)&true,
				sizeof(true) );
		if(status<0){
			fprintf(stderr, "Keepalive option set failed\n");
		}
	}

	status = shutdown(pclient->insock, SHUT_WR);
	if(status<0){
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
		fprintf (stderr, "%s:%d shutdown err %s\n", __FILE__, __LINE__,
				sockErrBuf);
        epicsSocketDestroy ( pclient->insock );
		free(pclient);

		return;
	}

	status = fdmgr_add_callback(
			pserver->pfdctx, 
			pclient->insock, 
			fdi_read,
			readFromClient,
			pclient);
	if (status<0) {
		epicsSocketDestroy ( pclient->insock );
		free(pclient);
		fprintf(stderr, "%s:%d client fdmgr_add_callback() failed\n", 
			__FILE__, __LINE__);
		return;
	}
}
Beispiel #3
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;
            }
        }
    }
}
Beispiel #4
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;
}
void BlockingTCPAcceptor::run() {
    // rise level if port is assigned dynamically
    char ipAddrStr[48];
    ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));
    LOG(logLevelDebug, "Accepting connections at %s.", ipAddrStr);

    bool socketOpen = true;
    char strBuffer[64];

    while(socketOpen) {

        {
            Lock guard(_mutex);
            if (_destroyed)
                break;
        }

        osiSockAddr address;
        osiSocklen_t len = sizeof(sockaddr);

        SOCKET newClient = epicsSocketAccept(_serverSocketChannel, &address.sa, &len);
        if(newClient!=INVALID_SOCKET) {
            // accept succeeded
            ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
            LOG(logLevelDebug, "Accepted connection from PVA client: %s.", ipAddrStr);

            // enable TCP_NODELAY (disable Nagle's algorithm)
            int optval = 1; // true
            int retval = ::setsockopt(newClient, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(int));
            if(retval<0) {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                LOG(logLevelDebug, "Error setting TCP_NODELAY: %s.", strBuffer);
            }

            // enable TCP_KEEPALIVE
            retval = ::setsockopt(newClient, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(int));
            if(retval<0) {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                LOG(logLevelDebug, "Error setting SO_KEEPALIVE: %s.", strBuffer);
            }

            // do NOT tune socket buffer sizes, this will disable auto-tunning

            // get TCP send buffer size
            osiSocklen_t intLen = sizeof(int);
            int _socketSendBufferSize;
            retval = getsockopt(newClient, SOL_SOCKET, SO_SNDBUF, (char *)&_socketSendBufferSize, &intLen);
            if(retval<0) {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                LOG(logLevelDebug, "Error getting SO_SNDBUF: %s.", strBuffer);
            }

            /**
             * Create transport, it registers itself to the registry.
             */
            detail::BlockingServerTCPTransportCodec::shared_pointer transport =
                detail::BlockingServerTCPTransportCodec::create(
                    _context,
                    newClient,
                    _responseHandler,
                    _socketSendBufferSize,
                    _receiveBufferSize);

            // validate connection
            if(!validateConnection(transport, ipAddrStr)) {
                // TODO
                // wait for negative response to be sent back and
                // hold off the client for retrying at very high rate
                epicsThreadSleep(1.0);

                transport->close();
                LOG(
                    logLevelDebug,
                    "Connection to PVA client %s failed to be validated, closing it.",
                    ipAddrStr);
                continue;
            }

            LOG(logLevelDebug, "Serving to PVA client: %s.", ipAddrStr);

        }// accept succeeded
        else
            socketOpen = false;
    } // while
}
Beispiel #6
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;
}