Exemple #1
0
void TCPSocket::SetTimeout(int socket)
{
  if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout.Timeval(), sizeof(timeout.Timeval())) < 0)
    throw NetworkSystemError(errno);
    
  if (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout.Timeval(), sizeof(timeout.Timeval())) < 0)
    throw NetworkSystemError(errno);
}
Exemple #2
0
void Interfaces::Load()
{
  struct ifaddrs* ifaddr, *ifa;
  if (getifaddrs(&ifaddr) == -1) return throw NetworkSystemError(errno);
  std::shared_ptr<struct ifaddrs> ifaddrGuard(ifaddr, freeifaddrs);

  IPAddress ip;
  for (ifa = ifaddr; ifa; ifa = ifa->ifa_next)
  {
    if (!ifa->ifa_addr) continue;

    if (ifa->ifa_addr->sa_family == AF_INET)
    {
      struct sockaddr_in* addr4 =
        reinterpret_cast<struct sockaddr_in*>(ifa->ifa_addr);
      ip = IPAddress(&addr4->sin_addr, sizeof(addr4->sin_addr));
    }
    else if (ifa->ifa_addr->sa_family == AF_INET6)
    {
      struct sockaddr_in6* addr6 =
        reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr);
      ip = IPAddress(&addr6->sin6_addr, sizeof(addr6->sin6_addr));
    }
    else
      continue;
    
    std::string name = ifa->ifa_name;
    std::map<std::string, Interface>::iterator it =
      interfaces.insert(std::make_pair(name, Interface(name))).first;
    it->second.addresses.emplace_back(ip);
  }
}
Exemple #3
0
void TCPSocket::Write(const char* buffer, size_t bufferLen)
{
  if (tls.get())
  {
    tls->Write(buffer, bufferLen);
    return;
  }
  
  size_t written = 0;
  ssize_t result;
  while (bufferLen - written > 0)
  {
    while ((result = write(socket, buffer + written, bufferLen - written)) < 0)
    {
      boost::this_thread::interruption_point();
      if (errno != EINTR)
      {
        if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ETIMEDOUT)
          throw TimeoutError();
        else
          throw NetworkSystemError(errno);
      }
    } 
    boost::this_thread::interruption_point();
    written += result;
  }
}
Exemple #4
0
void TCPSocket::Accept(TCPListener& listener)
{
  struct sockaddr_storage addrStor;
  socklen_t addrLen = sizeof(addrStor);
  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addrStor);

  int socket;
  while ((socket = accept(listener.Socket(), addr, &addrLen)) < 0)
  {
    boost::this_thread::interruption_point();
    if (errno != EINTR)
    {
      if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ETIMEDOUT)
        throw TimeoutError();
      else
        throw NetworkSystemError(errno);
    }
  }
  
  auto socketGuard = util::MakeScopeError([&socket]() { close(socket); }); (void) socketGuard;
  
  boost::this_thread::interruption_point();
  PopulateRemoteEndpoint(socket);
  PopulateLocalEndpoint(socket);
  
  std::lock_guard<std::mutex> lock(socketMutex);
  this->socket = socket;
}
Exemple #5
0
void TCPSocket::Connect(const Endpoint& remoteEndpoint, const Endpoint* localEndpoint)
{
  assert(socket < 0);
  int socket = ::socket(static_cast<int>(remoteEndpoint.Family()), SOCK_STREAM, 0);
  if (socket < 0) throw NetworkSystemError(errno);

  auto socketGuard = util::MakeScopeError([&socket]() { close(socket); }); (void) socketGuard;
  
  int optVal = 1;
  setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));

  SetTimeout(socket);
  
  if (localEndpoint)
  {
    socklen_t addrLen = localEndpoint->Length();
    struct sockaddr_storage addrStor;
    memcpy(&addrStor, localEndpoint->Addr(), addrLen);
    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addrStor);

    if (bind(socket, addr, addrLen) < 0)
    {
      int errno_ = errno;
      throw util::net::NetworkSystemError(errno_);
    }
  }
  
  while (connect(socket, remoteEndpoint.Addr(), remoteEndpoint.Length()) < 0)
  {
    boost::this_thread::interruption_point();
    if (errno != EINTR)
    {
      int errno_ = errno;
      if (errno_ == EWOULDBLOCK || errno_ == EAGAIN || errno_ == ETIMEDOUT)
        throw TimeoutError();
      else
        throw NetworkSystemError(errno_);
    }
  }
  
  boost::this_thread::interruption_point();
  PopulateRemoteEndpoint(socket);
  PopulateLocalEndpoint(socket);
  
  std::lock_guard<std::mutex> lock(socketMutex);
  this->socket = socket;
}
Exemple #6
0
void IPAddress::ToStringv6() const
{
  char str[INET6_ADDRSTRLEN];
  if (!inet_ntop(static_cast<int>(IPFamily::IPv6),
                 &data, str, sizeof(str)))
    throw NetworkSystemError(errno);
  asString = str;
}
Exemple #7
0
void TCPSocket::PopulateRemoteEndpoint(int socket)
{
  struct sockaddr_storage remoteAddrStor;
  socklen_t remoteLen = sizeof(remoteAddrStor);
  struct sockaddr* remoteAddr = reinterpret_cast<struct sockaddr*>(&remoteAddrStor);

  if (getpeername(socket, (struct sockaddr*) remoteAddr, &remoteLen) < 0)
    throw NetworkSystemError(errno);
    
  remoteEndpoint = Endpoint(*remoteAddr, remoteLen);
}
Exemple #8
0
void TCPSocket::PopulateLocalEndpoint(int socket)
{
  struct sockaddr_storage localAddrStor;
  socklen_t localLen = sizeof(localAddrStor);
  struct sockaddr* localAddr = reinterpret_cast<struct sockaddr*>(&localAddrStor);
    
  if (getsockname(socket, (struct sockaddr*) localAddr, &localLen) < 0)
    throw NetworkSystemError(errno);

  localEndpoint = Endpoint(*localAddr, localLen);
}
Exemple #9
0
void Resolver::Resolve()
{
  const char* charService = nullptr;
  if (port >= 0)
  {
    std::string service;
    try
    {
      service = boost::lexical_cast<std::string>(port);
    }
    catch (const boost::bad_lexical_cast&)
    {
      throw NetworkError("Invalid port number");
    }
    
    charService = service.c_str();
  }

  struct addrinfo hints;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = PF_UNSPEC;
  hints.ai_flags = AI_PASSIVE;
  hints.ai_socktype = static_cast<int>(socketType);

  const char* charHostname = nullptr;
  if (!hostname.empty()) charHostname = hostname.c_str();
  
  int error = getaddrinfo(charHostname, charService, &hints, &res);
  if (error)
  {
    if (error == EAI_SYSTEM) throw NetworkSystemError(errno);
    else throw ResolverError(error);
  }

  struct addrinfo* current = res;
  while (current)
  {
    results.emplace_back(Endpoint(*current->ai_addr, current->ai_addrlen));
    current = current->ai_next;
  }

  freeaddrinfo(res);
  res = nullptr;
}
Exemple #10
0
size_t TCPSocket::Read(char* buffer, size_t bufferSize)
{
  if (tls.get()) return tls->Read(buffer, bufferSize);

  ssize_t result;
  while ((result = read(socket, buffer, bufferSize)) < 0)
  {
    boost::this_thread::interruption_point();
    if (errno != EINTR)
    {
      if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ETIMEDOUT)
        throw TimeoutError();
      else
        throw NetworkSystemError(errno);
    }
  }

  boost::this_thread::interruption_point();
  if (!result) throw EndOfStream();
  
  return result;
}