Example #1
0
unsigned long CIpSocket::Send( const void *x_pData, unsigned long x_uSize, unsigned long *x_puSent, unsigned long x_uFlags )
{
	// Initialize bytes sent
	if ( x_puSent )
		*x_puSent = 0;

	// Must have a socket handle
	if ( !IsSocket() )
		return 0;

	// Attempt to send the data
	setWouldBlock( 0 );
	int nRet = v_send( (SOCKET)m_hSocket, x_pData, (int)x_uSize, (int)x_uFlags );

	// Get the last error code
	m_uLastError = WSAGetLastError();
	if ( WSAEWOULDBLOCK == m_uLastError )
		m_uLastError = 0;

	m_uWrites++;
	m_lActivity++;

	// Check for error
	if ( SOCKET_ERROR == nRet || 0 > nRet )
	{
		// Is the socket blocking?
		if ( !getWouldBlock() && m_uLastError )
		{	m_uConnectState |= eCsError;
			return 0;
		} // end if

		// Not an error
		m_uConnectState &= ~eCsError;

		// Number of bytes sent
		if ( x_puSent )
			*x_puSent = 0;

		// no bytes sent
		return 0;

	} // end if

	// Save the number of bytes sent
	if ( x_puSent )
		*x_puSent = nRet;

	return nRet;
}
Example #2
0
ssize_t ConnectedDescriptor::Send(const uint8_t *buffer,
                                  unsigned int size) {
  if (!ValidWriteDescriptor())
    return 0;

  ssize_t bytes_sent;
#ifdef _WIN32
  if (WriteDescriptor().m_type == PIPE_DESCRIPTOR) {
    DWORD bytes_written = 0;
    if (!WriteFile(ToHandle(WriteDescriptor()),
                   buffer,
                   size,
                   &bytes_written,
                   NULL)) {
      OLA_WARN << "WriteFile() failed with " << GetLastError();
      bytes_sent = -1;
    } else {
      bytes_sent = bytes_written;
    }
  } else if (WriteDescriptor().m_type == SOCKET_DESCRIPTOR) {
    bytes_sent = send(ToFD(WriteDescriptor()),
                      reinterpret_cast<const char*>(buffer),
                      size,
                      0);
  } else {
    OLA_WARN << "Send() called on unsupported descriptor type";
    return 0;
  }
#else
  // BSD Sockets
#if HAVE_DECL_MSG_NOSIGNAL
  if (IsSocket()) {
    bytes_sent = send(WriteDescriptor(), buffer, size, MSG_NOSIGNAL);
  } else {
#endif
    bytes_sent = write(WriteDescriptor(), buffer, size);
#if HAVE_DECL_MSG_NOSIGNAL
  }
#endif

#endif

  if (bytes_sent < 0 || static_cast<unsigned int>(bytes_sent) != size) {
    OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
      strerror(errno);
  }
  return bytes_sent;
}
Example #3
0
int CIpSocket::Accept( CIpSocket &x_is )
{
    // Punt if no socket
	if ( !IsSocket() )
		return 0;

    // Lose any current connection there might be
    x_is.Destroy();

	// Accept the connection
	sockaddr saAddr;
	socklen_t iAddr = sizeof( saAddr );

	// Accept and encapsulate the socket
	int bSuccess = x_is.Attach( (t_SOCKET)tcULongToPtr( accept( tcPtrToULong( m_hSocket ), &saAddr, &iAddr ) ) );

	if ( !bSuccess )
	{
		m_uLastError = errno;
		
		if ( EAGAIN != m_uLastError )
			m_uEventState |= eCloseEvent;

		else 
			m_uEventState = 0;

		return 0;

	} // end if
		
	else
		m_uLastError = 0;

    // Grab the address
    CIpSocket_GetAddressInfo( &m_addrPeer, &saAddr );

	// Capture all events
	x_is.EventSelect();

	// Accepted
	m_uAccepts++;
	m_lActivity++;

	// Child is connecting
	x_is.m_uConnectState |= eCsConnecting;

    return 1;
}
Example #4
0
int CIpSocket::EventSelect( long x_lEvents )
{
#if defined( HTM_NOSOCKET2 )
	return 0;
#else
	// Punt if no socket
	if ( !IsSocket() )
		return 0;

	// Must have event handle
	if ( !IsEventHandle() )
		CreateEventHandle();

	return ( WSAEventSelect( (SOCKET)m_hSocket, (WSAEVENT)m_hSocketEvent, x_lEvents ) == 0 );
#endif
}
Example #5
0
int CIpSocket::Connect( const CIpAddress &x_rIpAddress )
{
	// Punt if not initialized
	if ( !IsInitialized() )
		return 0;

	// Ensure we were passed a valid address
	if ( !x_rIpAddress.ValidateAddress() )
	{	Destroy(); return 0; }

	// Create socket if there is none
	if ( !IsSocket() && !Create() )
	{	m_uConnectState |= eCsError;
		Destroy();
		return 0;
	} // end if

	// Save the address
	m_addrPeer = x_rIpAddress;

	SOCKADDR_IN si;
	memset( &si, 0, sizeof( si ) );
	si.sin_family = m_uSocketFamily;
	CIpSocket_SetAddressInfo( &m_addrPeer, &si );

	// Attempt to connect
	int nRet = connect( (SOCKET)m_hSocket, (PSOCKADDR)&si, sizeof( si ) );

	// Save the last error code
	m_uLastError = WSAGetLastError();
	if ( WSAEWOULDBLOCK == m_uLastError )
		m_uLastError = 0, nRet = 0;

	// Check for error
	if ( nRet )
	{	m_uConnectState |= eCsError;
		return 0;
	} // end if

	// We're trying to connect
	m_lActivity++;
	m_uConnectState |= eCsConnecting;

	// Return the result
	return 1;
}
Example #6
0
int CIpSocket::Connect( const CIpAddress &x_rIpAddress )
{
	// Punt if not initialized
	if ( !IsInitialized() )
		return 0;

	// Ensure we were passed a valid address
	if ( !x_rIpAddress.ValidateAddress() )
	{	Destroy(); return 0; }

	// Create socket if there is none
	if ( !IsSocket() && !Create() )
	{	m_uConnectState |= eCsError;
		Destroy();
		return 0;
	} // end if

	// Save the address
	m_addrPeer = x_rIpAddress;

    sockaddr_in si;
    memset( &si, 0, sizeof( si ) );
    si.sin_family = m_uSocketFamily;
    CIpSocket_SetAddressInfo( &m_addrPeer, &si );

    // Attempt to connect
    int nRet = connect( tcPtrToULong( m_hSocket ), (sockaddr*)&si, sizeof( si ) );

	m_uLastError = errno;

	// Check result
	if ( -1 == nRet && EINPROGRESS != m_uLastError )
	{	m_uConnectState |= eCsError;
    	m_uLastError = errno;
		return 0;
	} // end if

	m_uLastError = 0;

	// We're trying to connect
	m_lActivity++;
	m_uConnectState |= eCsConnecting;

	return 1;
}
Example #7
0
int CIpSocket::Attach( t_SOCKET x_hSocket, int x_bFree )
{
	// Lose the old socket
    Destroy();

	// Save socket handle
    m_hSocket = x_hSocket;

	// Should we free the socket?
	m_bFree = x_bFree;

	// Call on attach
	if ( !OnAttach() )
		Destroy();

	// How'd it go?
    return IsSocket();
}
Example #8
0
BOOL CWinSocket::Listen(UINT uMaxConnections)
{_STT();

	// Punt if not initialized
	if ( !IsInitialized() ) { TRACE( "CWinSocket: Error - Call InitSockets()" ); return FALSE; }

	// Must have socket
	if ( !IsSocket() ) return FALSE;

	// Valid number of connections?
	if ( uMaxConnections == 0 ) return FALSE;

	// Start the socket listening
	int nRet = listen( m_hSocket, (int)uMaxConnections );

	// Save the last error code
	m_uLastError = WSAGetLastError();

	return nRet;
}
Example #9
0
bool ConnectedDescriptor::SetNoSigPipe(DescriptorHandle fd) {
  if (!IsSocket())
    return true;

#if HAVE_DECL_SO_NOSIGPIPE
  int sig_pipe_flag = 1;
  int ok = setsockopt(fd,
                      SOL_SOCKET,
                      SO_NOSIGPIPE,
                      &sig_pipe_flag,
                      sizeof(sig_pipe_flag));
  if (ok == -1) {
    OLA_INFO << "Failed to disable SIGPIPE on " << fd << ": " <<
      strerror(errno);
    return false;
  }
#else
  (void) fd;
#endif
  return true;
}
Example #10
0
int CIpSocket::EventSelect( long x_lEvents )
{
#if defined( HTM_NOEPOLL )
	return 0;
#else
    // Punt if no socket
	if ( !IsSocket() )
		return 0;

	// Enable non-blocking mode
	int flags = fcntl( tcPtrToULong( m_hSocket ), F_GETFL, 0 );
	fcntl( tcPtrToULong( m_hSocket ), F_SETFL, flags | O_NONBLOCK );

    // Must have event handle
    if ( !IsEventHandle() || !m_pEventObject )
        CreateEventHandle();

	// Clear events
	m_uEventState = 0;

	epoll_event ev;
	memset( &ev, 0, sizeof( ev ) );
	ev.data.fd = tcPtrToULong( m_hSocket );
	ev.events = EPOLLERR | FlagWinToNix( x_lEvents );

	// Set the event masks
	int nRes = epoll_ctl( tcPtrToULong( m_hSocketEvent ),
						  m_bEventsHooked ? EPOLL_CTL_MOD : EPOLL_CTL_ADD,
						  tcPtrToULong( m_hSocket ), &ev );

	if ( -1 == nRes )
    {	m_uLastError = errno;
		return 0;
	} // end if

	m_bEventsHooked = 1;

	return 1;
#endif
}
Example #11
0
int CIpSocket::Listen( unsigned int x_uMaxConnections )
{
	// Punt if not initialized
	if ( !IsInitialized() )
		return 0;

	// Must have socket
	if ( !IsSocket() )
	{	m_uConnectState |= eCsError;
		return 0;
	} // end if

	// Valid number of connections?
	if ( x_uMaxConnections == 0 )
		x_uMaxConnections = 16;
//		x_uMaxConnections = SOMAXCONN;

	// Start the socket listening
	int nRet = listen( (SOCKET)m_hSocket, (int)( x_uMaxConnections ? x_uMaxConnections : SOMAXCONN ) );

	// Save the last error code
	m_uLastError = WSAGetLastError();
	if ( WSAEWOULDBLOCK == m_uLastError )
		m_uLastError = 0, nRet = 0;

	// Error?
	if ( c_SocketError == (t_SOCKET)nRet )
	{	m_uConnectState |= eCsError;
		return 0;
	} // end if

	// We're trying to connect
	m_lActivity++;
	m_uConnectState |= eCsConnecting;

	// Return the result
	return 1;
}
Example #12
0
BOOL CWinSocket::Create( int af, int type, int protocol )
{_STT();

	// Punt if not initialized
	if ( !IsInitialized() ) { TRACE( "CWinSocket: Error - Call InitSockets()" ); return FALSE; }

	// Close any open socket
	Destroy();

	// Create a scocket
	m_hSocket = socket( af, type, protocol );
	
	// Save the last error code
	m_uLastError = WSAGetLastError();

	// Create the event handle
	CreateEventHandle();

	// Capture all events
	EventSelect();

	return IsSocket();
}
Example #13
0
int CIpSocket::Accept( CIpSocket &x_is )
{
	// Punt if no socket
	if ( !IsSocket() )
		return 0;

	// Lose any current connection there might be
	x_is.Destroy();

	// Accept the connection
	SOCKADDR saAddr; int iAddr = sizeof( saAddr );

	// Accept and encapsulate the socket
	BOOL bSuccess = x_is.Attach( (t_SOCKET)accept( (SOCKET)m_hSocket, &saAddr, &iAddr ) );

	// Check for error
	if ( !bSuccess )
	{   m_uLastError = WSAGetLastError();
		return 0;
	} // end if

	// Grab the address
	CIpSocket_GetAddressInfo( &m_addrPeer, &saAddr );

	// Capture all events
	x_is.EventSelect();

	m_uAccepts++;
	m_lActivity++;

	// Child is connecting
	x_is.m_lActivity++;
	x_is.m_uConnectState |= eCsConnecting;

	return 1;
}
Example #14
0
int CIpSocket::Bind( unsigned int x_uPort )
{
	// Punt if not initialized
	if ( !IsInitialized() )
		return 0;

	// Create socket if there is none
	if ( !IsSocket() && !Create() )
	{	Destroy();
		m_uConnectState |= eCsError;
		return 0;
	} // end if

	sockaddr_in sai;
	ZeroMemory( &sai, sizeof( sai ) );
	sai.sin_family = PF_INET;
	sai.sin_port = htons( (WORD)x_uPort );

	// Attempt to bind the socket
	int nRet = bind( (SOCKET)m_hSocket, (sockaddr*)&sai, sizeof( sockaddr_in ) );

	// Save the last error code
	m_uLastError = WSAGetLastError();
	if ( WSAEWOULDBLOCK == m_uLastError )
		m_uLastError = 0, nRet = 0;

	// Grab the address
	CIpSocket_GetAddressInfo( &m_addrLocal, &sai );

	if ( nRet )
	{	m_uConnectState |= eCsError;
		return 0;
	} // end if

	return 1;
}
Example #15
0
UINT CWinSocket::Recv(LPVOID pData, UINT uSize, UINT *puRead, UINT uFlags)
{
	// Initialize bytes read
	if ( puRead ) *puRead = 0;

	// Must have a socket handle
	if ( !IsSocket() ) return FALSE;

	// Receive data from socket
	int nRet = recv( m_hSocket, (LPSTR)pData, (int)uSize, (int)uFlags );

	// Get the last error code
	m_uLastError = WSAGetLastError();

    // Check for closed socket
	if ( !nRet ) return SOCKET_ERROR;

	// Check for socket error
	if ( SOCKET_ERROR == nRet )
	{
		// Is the socket blocking?
		if ( WSAEWOULDBLOCK != m_uLastError )
			return SOCKET_ERROR;

		// All bytes read
		if ( puRead ) *puRead = uSize;

		return uSize;

	} // end if

	// Save the number of bytes read
	if ( puRead ) *puRead = nRet;

	return nRet;
}
Example #16
0
/*
 * Write data to this descriptor.
 * @param buffer the data to write
 * @param size the length of the data
 * @return the number of bytes sent
 */
ssize_t ConnectedDescriptor::Send(const uint8_t *buffer,
                                  unsigned int size) {
  if (!ValidWriteDescriptor())
    return 0;

  ssize_t bytes_sent;
#if HAVE_DECL_MSG_NOSIGNAL
  if (IsSocket())
    bytes_sent = send(WriteDescriptor(), buffer, size, MSG_NOSIGNAL);
  else
#endif
#ifdef _WIN32
    if (WriteDescriptor().m_type == HANDLE_DESCRIPTOR) {
      DWORD bytes_written = 0;
      if (!WriteFile(WriteDescriptor().m_handle.m_handle,
                     buffer,
                     size,
                     &bytes_written,
                     NULL)) {
        OLA_WARN << "WriteFile() failed with " << GetLastError();
        bytes_sent = -1;
      } else {
        bytes_sent = bytes_written;
      }
    } else {
      bytes_sent = write(WriteDescriptor().m_handle.m_fd, buffer, size);
    }
#else
    bytes_sent = write(WriteDescriptor(), buffer, size);
#endif

  if (bytes_sent < 0 || static_cast<unsigned int>(bytes_sent) != size)
    OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
      strerror(errno);
  return bytes_sent;
}
Example #17
0
BOOL CWinSocket::Bind(UINT uPort)
{_STT();

	// Punt if not initialized
	if ( !IsInitialized() ) { TRACE( "CWinSocket: Error - Call InitSockets()" ); return FALSE; }

	// Create socket if there is none
	if ( !IsSocket() && !Create() ) 
	{	Destroy(); return FALSE; }

	sockaddr_in sai;
	ZeroMemory( &sai, sizeof( sai ) );

	sai.sin_family = PF_INET;
	sai.sin_port = htons( (WORD)uPort );

	// Attempt to bind the socket
	int nRet = bind( m_hSocket, (sockaddr*)&sai, sizeof( sockaddr_in ) );

	// Save the last error code
	m_uLastError = WSAGetLastError();

	return !nRet;
}
Example #18
0
ssize_t ConnectedDescriptor::Send(IOQueue *ioqueue) {
  if (!ValidWriteDescriptor())
    return 0;

  int iocnt;
  const struct IOVec *iov = ioqueue->AsIOVec(&iocnt);

  ssize_t bytes_sent = 0;

#ifdef _WIN32
  /* There is no scatter/gather functionality for generic descriptors on
   * Windows, so this is implemented as a write loop. Derived classes should
   * re-implement Send() using scatter/gather I/O where available.
   */
  int bytes_written = 0;
  for (int io = 0; io < iocnt; ++io) {
    bytes_written = Send(reinterpret_cast<const uint8_t*>(iov[io].iov_base),
                         iov[io].iov_len);
    if (bytes_written == 0) {
      OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
        strerror(errno);
      bytes_sent = -1;
      break;
    }
    bytes_sent += bytes_written;
  }
#else
#if HAVE_DECL_MSG_NOSIGNAL
  if (IsSocket()) {
    struct msghdr message;
    memset(&message, 0, sizeof(message));
    message.msg_name = NULL;
    message.msg_namelen = 0;
    message.msg_iov = reinterpret_cast<iovec*>(const_cast<IOVec*>(iov));
    message.msg_iovlen = iocnt;
    bytes_sent = sendmsg(WriteDescriptor(), &message, MSG_NOSIGNAL);
  } else {
#else
  {
#endif
    bytes_sent = writev(WriteDescriptor(),
                        reinterpret_cast<const struct iovec*>(iov), iocnt);
  }
#endif

  ioqueue->FreeIOVec(iov);
  if (bytes_sent < 0) {
    OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
      strerror(errno);
  } else {
    ioqueue->Pop(bytes_sent);
  }
  return bytes_sent;
}

int ConnectedDescriptor::Receive(uint8_t *buffer,
                                 unsigned int size,
                                 unsigned int &data_read) { // NOLINT
  int ret;
  uint8_t *data = buffer;
  data_read = 0;
  if (!ValidReadDescriptor())
    return -1;

  while (data_read < size) {
#ifdef _WIN32
    if (ReadDescriptor().m_type == PIPE_DESCRIPTOR) {
      if (!ReadDescriptor().m_async_data_size) {
        OLA_WARN << "No async data buffer for descriptor " << ReadDescriptor();
        return -1;
      }
      // Check if data was read by the async ReadFile() call
      DWORD async_data_size = *ReadDescriptor().m_async_data_size;
      if (async_data_size > 0) {
        DWORD size_to_copy = std::min(static_cast<DWORD>(size),
            async_data_size);
        memcpy(buffer, ReadDescriptor().m_async_data, size_to_copy);
        data_read = size_to_copy;
        if (async_data_size > size) {
          memmove(ReadDescriptor().m_async_data,
                  &(ReadDescriptor().m_async_data[size_to_copy]),
                  async_data_size - size_to_copy);
        }
        *ReadDescriptor().m_async_data_size -= size_to_copy;
      }
      return 0;
    } else if (ReadDescriptor().m_type == SOCKET_DESCRIPTOR) {
      ret = recv(ToFD(ReadDescriptor()), reinterpret_cast<char*>(data),
                 size - data_read, 0);
      if (ret < 0) {
        if (WSAGetLastError() == WSAEWOULDBLOCK) {
          return 0;
        } else if (WSAGetLastError() != WSAEINTR) {
          OLA_WARN << "read failed, " << WSAGetLastError();
          return -1;
        }
      } else if (ret == 0) {
        return 0;
      }
      data_read += ret;
      data += data_read;
    } else {
      OLA_WARN << "Descriptor type not implemented for reading: "
               << ReadDescriptor().m_type;
      return -1;
    }
  }
#else
    if ((ret = read(ReadDescriptor(), data, size - data_read)) < 0) {
      if (errno == EAGAIN)
        return 0;
      if (errno != EINTR) {
        OLA_WARN << "read failed, " << strerror(errno);
        return -1;
      }
    } else if (ret == 0) {
      return 0;
    }
    data_read += ret;
    data += data_read;
  }
Example #19
0
/**
 * Send an IOQueue.
 * This attempts to send as much of the IOQueue data as possible. The IOQueue
 * may be non-empty when this completes if the descriptor buffer is full.
 * @returns the number of bytes sent.
 */
ssize_t ConnectedDescriptor::Send(IOQueue *ioqueue) {
  if (!ValidWriteDescriptor())
    return 0;

  int iocnt;
  const struct IOVec *iov = ioqueue->AsIOVec(&iocnt);

  ssize_t bytes_sent = 0;

#ifdef _WIN32
  /* There is no scatter/gather functionality for generic descriptors on
   * Windows, so this is implemented as a write loop. Derived classes should
   * re-implement Send() using scatter/gather I/O where available.
   */
  int bytes_written = 0;
  for (int io = 0; io < iocnt; ++io) {
    bytes_written = write(WriteDescriptor().m_handle.m_fd, iov[io].iov_base,
                          iov[io].iov_len);
    if (bytes_written == -1) {
      OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
        strerror(errno);
      break;
    }
    bytes_sent += bytes_written;
  }
#else
#if HAVE_DECL_MSG_NOSIGNAL
  if (IsSocket()) {
    struct msghdr message;
    memset(&message, 0, sizeof(message));
    message.msg_name = NULL;
    message.msg_namelen = 0;
    message.msg_iov = reinterpret_cast<iovec*>(const_cast<IOVec*>(iov));
    message.msg_iovlen = iocnt;
    bytes_sent = sendmsg(WriteDescriptor(), &message, MSG_NOSIGNAL);
  } else {
#else
  {
#endif
    bytes_sent = writev(WriteDescriptor(),
                        reinterpret_cast<const struct iovec*>(iov), iocnt);
  }
#endif

  ioqueue->FreeIOVec(iov);
  if (bytes_sent < 0) {
    OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
      strerror(errno);
  } else {
    ioqueue->Pop(bytes_sent);
  }
  return bytes_sent;
}


/*
 * Read data from this descriptor.
 * @param buffer a pointer to the buffer to store new data in
 * @param size the size of the buffer
 * @param data_read a value result argument which returns the amount of data
 * copied into the buffer
 * @returns -1 on error, 0 on success.
 */
int ConnectedDescriptor::Receive(uint8_t *buffer,
                                 unsigned int size,
                                 unsigned int &data_read) { // NOLINT
  int ret;
  uint8_t *data = buffer;
  data_read = 0;
  if (!ValidReadDescriptor())
    return -1;

  while (data_read < size) {
#ifdef _WIN32
    if ((ret = read(ReadDescriptor().m_handle.m_fd, data, size - data_read))
        < 0) {
#else
    if ((ret = read(ReadDescriptor(), data, size - data_read)) < 0) {
#endif
      if (errno == EAGAIN)
        return 0;
      if (errno != EINTR) {
        OLA_WARN << "read failed, " << strerror(errno);
        return -1;
      }
    } else if (ret == 0) {
      return 0;
    }
    data_read += ret;
    data += data_read;
  }
  return 0;
}


/*
 * Check if the remote end has closed the connection.
 * @return true if the socket is closed, false otherwise
 */
bool ConnectedDescriptor::IsClosed() const {
  return DataRemaining() == 0;
}

// LoopbackDescriptor
// ------------------------------------------------


/*
 * Setup this loopback socket
 */
bool LoopbackDescriptor::Init() {
  if (m_handle_pair[0] != INVALID_DESCRIPTOR ||
      m_handle_pair[1] != INVALID_DESCRIPTOR)
    return false;

  if (!CreatePipe(m_handle_pair))
    return false;

  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  return true;
}


/*
 * Close the loopback socket
 * @return true if close succeeded, false otherwise
 */
bool LoopbackDescriptor::Close() {
  if (m_handle_pair[0] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[0].m_handle.m_handle);
#else
    close(m_handle_pair[0]);
#endif
  }

  if (m_handle_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[1].m_handle.m_handle);
#else
    close(m_handle_pair[1]);
#endif
  }

  m_handle_pair[0] = INVALID_DESCRIPTOR;
  m_handle_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


/*
 * Close the write portion of the loopback socket
 * @return true if close succeeded, false otherwise
 */
bool LoopbackDescriptor::CloseClient() {
  if (m_handle_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[1].m_handle.m_handle);
#else
    close(m_handle_pair[1]);
#endif
  }

  m_handle_pair[1] = INVALID_DESCRIPTOR;
  return true;
}



// PipeDescriptor
// ------------------------------------------------

/*
 * Create a new pipe socket
 */
bool PipeDescriptor::Init() {
  if (m_in_pair[0] != INVALID_DESCRIPTOR ||
      m_out_pair[1] != INVALID_DESCRIPTOR)
    return false;

  if (!CreatePipe(m_in_pair))
    return false;

  if (!CreatePipe(m_out_pair)) {
#ifdef _WIN32
    CloseHandle(m_in_pair[0].m_handle.m_handle);
    CloseHandle(m_in_pair[1].m_handle.m_handle);
#else
    close(m_in_pair[0]);
    close(m_in_pair[1]);
#endif
    m_in_pair[0] = m_in_pair[1] = INVALID_DESCRIPTOR;
    return false;
  }

  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  return true;
}


/*
 * Fetch the other end of the pipe socket. The caller now owns the new
 * PipeDescriptor.
 * @returns NULL if the socket wasn't initialized correctly.
 */
PipeDescriptor *PipeDescriptor::OppositeEnd() {
  if (m_in_pair[0] == INVALID_DESCRIPTOR ||
      m_out_pair[1] == INVALID_DESCRIPTOR)
    return NULL;

  if (!m_other_end) {
    m_other_end = new PipeDescriptor(m_out_pair, m_in_pair, this);
    m_other_end->SetReadNonBlocking();
  }
  return m_other_end;
}


/*
 * Close this PipeDescriptor
 */
bool PipeDescriptor::Close() {
  if (m_in_pair[0] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_in_pair[0].m_handle.m_handle);
#else
    close(m_in_pair[0]);
#endif
  }

  if (m_out_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_out_pair[1].m_handle.m_handle);
#else
    close(m_out_pair[1]);
#endif
  }

  m_in_pair[0] = INVALID_DESCRIPTOR;
  m_out_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


/*
 * Close the write portion of this PipeDescriptor
 */
bool PipeDescriptor::CloseClient() {
  if (m_out_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_out_pair[1].m_handle.m_handle);
#else
    close(m_out_pair[1]);
#endif
  }

  m_out_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


// UnixSocket
// ------------------------------------------------

/*
 * Create a new unix socket
 */
bool UnixSocket::Init() {
#ifdef _WIN32
  return false;
#else
  int pair[2];
  if ((m_handle != INVALID_DESCRIPTOR) || m_other_end)
    return false;

  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) {
    OLA_WARN << "socketpair() failed, " << strerror(errno);
    return false;
  }

  m_handle = pair[0];
  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  m_other_end = new UnixSocket(pair[1], this);
  m_other_end->SetReadNonBlocking();
  return true;
#endif
}


/*
 * Fetch the other end of the unix socket. The caller now owns the new
 * UnixSocket.
 * @returns NULL if the socket wasn't initialized correctly.
 */
UnixSocket *UnixSocket::OppositeEnd() {
  return m_other_end;
}


/*
 * Close this UnixSocket
 */
bool UnixSocket::Close() {
#ifdef _WIN32
  return true;
#else
  if (m_handle != INVALID_DESCRIPTOR) {
    close(m_handle);
  }

  m_handle = INVALID_DESCRIPTOR;
  return true;
#endif
}


/*
 * Close the write portion of this UnixSocket
 */
bool UnixSocket::CloseClient() {
#ifndef _WIN32
  if (m_handle != INVALID_DESCRIPTOR)
    shutdown(m_handle, SHUT_WR);
#endif

  m_handle = INVALID_DESCRIPTOR;
  return true;
}


// DeviceDescriptor
// ------------------------------------------------
DeviceDescriptor::DeviceDescriptor(int fd) {
#ifdef _WIN32
  m_handle.m_handle.m_fd = fd;
  m_handle.m_type = GENERIC_DESCRIPTOR;
  m_handle.m_event_handle = 0;
#else
  m_handle = fd;
#endif
}
Example #20
0
long CIpSocket::WaitEvent( long x_lEventId, long x_lTimeout )
{
#if defined( HTM_NOEPOLL )
	return 0;
#else

	// Must have a socket handle
	if ( !IsSocket() )
        return 0;

    // Must have event handle
    if ( !IsEventHandle() || !m_pEventObject )
    {
    	if ( !CreateEventHandle() )
    		return 0;

    	if ( !EventSelect() )
            return 0;

    } // end if

	// +++ Ensure our event is being waited on?

	// Grab pointer to event object
	epoll_event *pev = (epoll_event*)m_pEventObject;

	// Check for default timeout
	if ( 0 > x_lTimeout )
		x_lTimeout = (long)m_lTimeout;

	// Save start time
	unsigned int uEnd = time( 0 ) + x_lTimeout / 1000;
	for( ; ; ) // forever
	{
        // What's the event state
        if ( 0 == ( m_uEventState & x_lEventId ) )
        {
			// Wait only for our specific event
			EventSelect( x_lEventId );

			// Wait for events
			int nRes;
			do { 
				nRes = epoll_wait( tcPtrToULong( m_hSocketEvent ), pev, eMaxEvents, x_lTimeout );

			} while ( -1 == nRes && EINTR == errno );

			if ( -1 == nRes )
			{
				// Log error
				m_uLastError = errno;

				// Disconnected?
				m_uConnectState |= eCsError;

				// Just ditch if they aren't waiting for the close event
				m_uEventState |= eCloseEvent;
				if ( !( x_lEventId & eCloseEvent ) )
					return 0;

			} // end if

			// Process all events
			if ( 0 < nRes )
				for ( long i = 0; i < nRes; i++ )
				{
					// Convert to windows flags
					unsigned long uFlags = FlagNixToWin( pev[ i ].events );

					// Save the status of all events
					if ( pev[ i ].data.fd == tcPtrToULong( m_hSocket ) )
					{	pev[ i ].events = 0;
						for ( unsigned long uMask = 1; uMask < eAllEvents; uMask <<= 1 )
							if ( uFlags & uMask )
							{
								// Get bit offset
								unsigned long uOffset = GetEventBit( uMask );

								// Save the event info
								m_uEventState |= uMask;
								m_uEventStatus[ uOffset ] = 0;

								// Attempt to detect connect error
								if ( 0 != ( uMask & eConnectEvent ) )
								{
/* +++ Nope, doesn't always work
									// use getpeername() to check for errors
									sockaddr_in sai; 
									memset( &sai, 0, sizeof( sai ) );
									socklen_t len = sizeof( sai );
									if ( -1 == getpeername( tcPtrToULong( m_hSocket ), (sockaddr*)&sai, &len ) )
									{	m_uLastError = errno;
										m_uEventStatus[ uOffset ] = errno;
										m_uConnectState |= eCsError;
									} // end if
*/
/* +++ gives error : Resource temporarily unavailable
									char buf[ 1 ];
									if ( -1 == recv( tcPtrToULong( m_hSocket ), buf, 0, 0 ) )
									{	m_uLastError = errno;
										m_uEventStatus[ uOffset ] = errno;
										m_uConnectState |= eCsError;
									} // end if
*/
								}

								// Handle close event
								if ( 0 != ( uMask & eCloseEvent ) )
									m_uConnectState &= ~eCsConnected;
								else
									m_uConnectState |= eCsActivity;

								// +++ Signal when we get a connect message
//								if ( 0 != ( ( EPOLLIN | EPOLLOUT ) & uMask ) )
//									m_uConnectState |= 2;

							} // end if

					} // end if

				} // end for

            // !!!  Kludge around missing connect message
            if ( !( m_uConnectState & eCsConnected ) && ( m_uConnectState & eCsActivity ) )
            {   m_uConnectState |= eCsConnected;
//				m_uConnectState &= ~eCsError;
                m_uEventState |= eConnectEvent;
                m_uEventStatus[ eConnectBit ] = 0;
            } // end if

        } // end if

		// Did our event go off?
		if ( 0 != ( m_uEventState & x_lEventId ) )
		{
            // Get the first event
            unsigned long uBit = GetEventBit( x_lEventId & m_uEventState );
            unsigned long uMask = 1 << uBit;

            // Acknowledge this event
            // m_uEventState &= ~uMask;

			// Save the error code
			if ( m_uEventStatus[ uBit ] )
				m_uLastError = m_uEventStatus[ uBit ];

			// Something is going on
			m_lActivity++;

			// We received the event
			return uMask;

		} // end if

		// Have we timed out?
		unsigned long uTick = time( 0 );
		if ( uEnd <= uTick )
            return 0;

		// Adjust timeout
		x_lTimeout = ( uEnd - uTick ) * 1000;

	} // end if

	// Can't get here...
	return 0;
#endif
}
Example #21
0
long CIpSocket::WaitEvent( long x_lEventId, long x_uTimeout )
{
#if defined( HTM_NOSOCKET2 )
	return 0;
#else
	// Must have a socket handle
	if ( !IsSocket() )
		return 0;

	// Must have event handle
	if ( !IsEventHandle() )
	{   if ( !CreateEventHandle() || !EventSelect() )
			return 0;
	} // end if

	if ( 0 > x_uTimeout )
		x_uTimeout = m_lTimeout;

	// Save start time
	UINT uEnd = GetTickCount() + x_uTimeout;
	for( ; ; )
	{
		// What's the event state
		if ( 0 == ( m_uEventState & x_lEventId ) )
		{
			if ( x_uTimeout )
			{
				// Wait for event
//				UINT uRet =
					WaitForSingleObject( m_hSocketEvent, x_uTimeout );

				// Check for timeout or error
//		        if ( uRet != WAIT_OBJECT_0 )
//                   return 0;

			} // end if

			// Reset the network event
			ResetEvent( m_hSocketEvent );

			// Get network events
			WSANETWORKEVENTS wne; memset( &wne, 0, sizeof( wne ) );
			if ( SOCKET_ERROR == WSAEnumNetworkEvents( (SOCKET)m_hSocket, m_hSocketEvent, &wne ) )
			{	m_uLastError = WSAGetLastError();
				return 0;
			} // end if

			// Save the status of all events
			for ( unsigned int uMask = 1; uMask && uMask <= eAllEvents; uMask <<= 1 )
				if ( wne.lNetworkEvents & uMask )
				{
					// Get bit offset
					unsigned int uOffset = GetEventBit( uMask );

					// Save the event info
					m_uEventState |= uMask;
					m_uEventStatus[ uOffset ] = wne.iErrorCode[ uOffset ];

					// Signal activity
					m_uConnectState |= eCsActivity;

					// Signal when we get a connect message
					if ( 0 != ( FD_CONNECT & wne.lNetworkEvents ) )
					{
						// Set connected status
						if ( !m_uEventStatus[ FD_CONNECT_BIT ] )
							m_uConnectState |= eCsConnected;

						// Handle connect error
						else
							m_uLastError = m_uEventStatus[ FD_CONNECT_BIT ],
							m_uConnectState &= ~( eCsConnected | eCsActivity );

						// Connecting process is over
						m_uConnectState &= ~eCsConnecting;

					} // end if

					// Check for socket close
					if ( 0 != ( FD_CLOSE & wne.lNetworkEvents ) )
						m_uConnectState &= ~( eCsConnected | eCsActivity | eCsConnecting );

				} // end if

			// !!!  Kludge around missing connect message
			//      If we're accepting a connection, we don't
			//      get a connect message.  ( At least on Windows )
			if ( !( m_uConnectState & 2 ) && ( m_uConnectState & 1 ) )
			{	m_uConnectState |= eCsConnected;
				m_uConnectState &= ~eCsConnecting;
				wne.lNetworkEvents |= FD_CONNECT;
				m_uEventState |= FD_CONNECT;
				m_uEventStatus[ FD_CONNECT_BIT ] = 0;
			} // end if

		} // end if

		// Did our event go off?
		if ( 0 != ( m_uEventState & x_lEventId ) )
		{
			// Get the first event
			unsigned int uBit = GetEventBit( x_lEventId & m_uEventState );
			unsigned int uMask = 1 << uBit;

			// Acknowledge this event
			m_uEventState &= ~uMask;

			// Save the error code
			m_uLastError = m_uEventStatus[ uBit ];

			// Something is going on
			m_lActivity++;

			// We received the event
			return uMask;

		} // end if

		// Have we timed out?
		unsigned int uTick = GetTickCount();
		if ( uEnd <= uTick )
			return 0;

		// Adjust timeout
		x_uTimeout = uEnd - uTick;

	} // end if

	// Can't get here...
	return 0;
#endif
}