Ejemplo n.º 1
0
static void*
w5100_io_thread( void *arg )
{
  nic_w5100_t *self = arg;
  int i;

  while( !self->stop_io_thread ) {
    fd_set readfds, writefds;
    int active;
    compat_socket_t selfpipe_socket =
      compat_socket_selfpipe_get_read_fd( self->selfpipe );
    int max_fd = selfpipe_socket;

    FD_ZERO( &readfds );
    FD_ZERO( &writefds );

    FD_SET( selfpipe_socket, &readfds );

    for( i = 0; i < 4; i++ )
      nic_w5100_socket_add_to_sets( &self->socket[i], &readfds, &writefds,
        &max_fd );

    /* Note that if a socket is closed between when we added it to the sets
       above and when we call select() below, it will cause the select to fail
       with EBADF. We catch this and just run around the loop again - the
       offending socket will not be added to the sets again as it's now been
       closed */

    nic_w5100_debug( "w5100: io thread select\n" );

    active = select( max_fd + 1, &readfds, &writefds, NULL, NULL );

    nic_w5100_debug( "w5100: io thread wake; %d active\n", active );

    if( active != -1 ) {
      if( FD_ISSET( selfpipe_socket, &readfds ) ) {
        nic_w5100_debug( "w5100: discarding selfpipe data\n" );
        compat_socket_selfpipe_discard_data( self->selfpipe );
      }

      for( i = 0; i < 4; i++ )
        nic_w5100_socket_process_io( &self->socket[i], readfds, writefds );
    }
    else if( compat_socket_get_error() == compat_socket_EBADF ) {
      /* Do nothing - just loop again */
    }
    else {
      nic_w5100_debug( "w5100: select returned unexpected errno %d: %s\n",
                       compat_socket_get_error(),
                       compat_socket_get_strerror() );
    }
  }

  return NULL;
}
Ejemplo n.º 2
0
compat_socket_selfpipe_t *
compat_socket_selfpipe_alloc( void )
{
  unsigned long mode = 1;
  struct sockaddr_in sa;
  socklen_t sa_len = sizeof(sa);

  compat_socket_selfpipe_t *self = malloc( sizeof( *self ) );
  if( !self ) {
    ui_error( UI_ERROR_ERROR, "%s: %d: out of memory", __FILE__, __LINE__ );
    fuse_abort();
  }
  
  self->self_socket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
  if( self->self_socket == compat_socket_invalid ) {
    ui_error( UI_ERROR_ERROR,
              "%s: %d: failed to open socket; errno %d: %s\n",
              __FILE__, __LINE__, compat_socket_get_error(),
              compat_socket_get_strerror() );
    fuse_abort();
  }

  /* Set nonblocking mode */
  if( ioctlsocket( self->self_socket, FIONBIO, &mode ) == -1 ) {
    ui_error( UI_ERROR_ERROR, 
              "%s: %d: failed to set socket nonblocking; errno %d: %s\n",
              __FILE__, __LINE__, compat_socket_get_error(),
              compat_socket_get_strerror() );
    fuse_abort();
  }

  memset( &sa, 0, sizeof(sa) );
  sa.sin_family = AF_INET;
  sa.sin_addr.s_addr = htonl( INADDR_LOOPBACK );

  if( bind( self->self_socket, (struct sockaddr*)&sa, sizeof(sa) ) == -1 ) {
    ui_error( UI_ERROR_ERROR,
              "%s: %d: failed to bind socket; errno %d: %s\n",
              __FILE__, __LINE__, compat_socket_get_error(),
              compat_socket_get_strerror() );
    fuse_abort();
  }

  /* Get ephemeral port number */
  if( getsockname( self->self_socket, (struct sockaddr *)&sa, &sa_len ) == -1 ) {
    ui_error( UI_ERROR_ERROR,
              "%s: %d: failed to get socket name; errno %d: %s\n",
              __FILE__, __LINE__, compat_socket_get_error(),
              compat_socket_get_strerror() );
    fuse_abort();
  }

  self->port = ntohs( sa.sin_port );
 
  /* Test communications in order to detect blocking firewalls */
  if( selfpipe_test( self ) == -1 ) {
    ui_error( UI_ERROR_ERROR,
              "Networking: failed to test internal communications" );
    fuse_abort();
  }

  return self;
}