Skip to content
Snippets Groups Projects
Select Git revision
  • 6add3ad1dd2a238858b0cde45e0584685b7717b0
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

MeshBuilderBase.cpp

Blame
  • Socket.cpp 6.02 KiB
    #include <utils/Exceptions.hpp>
    #include <utils/Socket.hpp>
    
    #include <utils/Messenger.hpp>
    
    #include <arpa/inet.h>
    #include <cstring>
    #include <iostream>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <stdexcept>
    #include <sys/socket.h>
    #include <unistd.h>
    
    class Socket::Internals
    {
     private:
      int m_socket_fd;
      sockaddr_in m_address;
    
      const bool m_is_server_socket;
    
     public:
      friend Socket createServerSocket(int port_number);
      friend Socket acceptClientSocket(const Socket& server);
      friend Socket connectServerSocket(const std::string& server_name, int port_number);
    
      friend std::ostream&
      operator<<(std::ostream& os, const Socket::Internals& internals)
      {
        // This function's coverage is not performed since it's quite
        // complex to create its various conditions
        //
        // LCOV_EXCL_START
        char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
        if (::getnameinfo(reinterpret_cast<const sockaddr*>(&internals.m_address), sizeof(internals.m_address), hbuf,
                          sizeof(hbuf), sbuf, sizeof(sbuf), NI_NAMEREQD) == 0) {
          os << hbuf << ':' << sbuf;
        } else if (::getnameinfo(reinterpret_cast<const sockaddr*>(&internals.m_address), sizeof(internals.m_address), hbuf,
                                 sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0) {
          if (std ::string{hbuf} == "0.0.0.0") {
            if (::gethostname(hbuf, NI_MAXHOST) == 0) {
              os << hbuf << ':' << sbuf;
            } else {
              os << "localhost:" << sbuf;
            }
          } else {
            os << hbuf << ':' << sbuf;
          }
        } else {
          os << "<unknown host>";
        }
        // LCOV_EXCL_STOP
        return os;
      }
    
      bool
      isServerSocket() const
      {
        return m_is_server_socket;
      }
    
      int
      portNumber() const
      {
        return ntohs(m_address.sin_port);
      }
    
      int
      fileDescriptor() const
      {
        return m_socket_fd;
      }
    
      Internals(const Internals&) = delete;
      Internals(Internals&&)      = delete;
    
      Internals(bool is_server_socket = false) : m_is_server_socket{is_server_socket}
      {
        if (parallel::size() > 1) {
          // LCOV_EXCL_START
          throw NotImplementedError("Sockets are not managed in parallel");
          // LCOV_EXCL_STOP
        }
      }
    
      ~Internals()
      {
        close(m_socket_fd);
      }
    };
    
    std::ostream&
    operator<<(std::ostream& os, const Socket& socket)
    {
      return os << *socket.m_internals;
    }
    
    int
    Socket::portNumber() const
    {
      return m_internals->portNumber();
    }
    
    Socket
    createServerSocket(int port_number)
    {
      auto p_socket_internals             = std::make_shared<Socket::Internals>(true);
      Socket::Internals& socket_internals = *p_socket_internals;
    
      socket_internals.m_socket_fd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (socket_internals.m_socket_fd < 0) {
        // This should never happen
        throw UnexpectedError(strerror(errno));   // LCOV_EXCL_LINE
      }
    
      socket_internals.m_address.sin_family      = AF_INET;
      socket_internals.m_address.sin_addr.s_addr = INADDR_ANY;
      socket_internals.m_address.sin_port        = htons(port_number);
    
      int on = 1;
      ::setsockopt(socket_internals.m_socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    
      socklen_t length = sizeof(socket_internals.m_address);
    
      if (::bind(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&socket_internals.m_address), length) < 0) {
        throw NormalError(strerror(errno));
      }
    
      if (::getsockname(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&socket_internals.m_address), &length) ==
          -1) {
        // This should never happen
        throw UnexpectedError(strerror(errno));   // LCOV_EXCL_LINE
      }
    
      ::listen(socket_internals.m_socket_fd, 1);
    
      return Socket{p_socket_internals};
    }
    
    Socket
    acceptClientSocket(const Socket& server)
    {
      auto p_socket_internals             = std::make_shared<Socket::Internals>();
      Socket::Internals& socket_internals = *p_socket_internals;
    
      socklen_t address_lenght     = sizeof(socket_internals.m_address);
      socket_internals.m_socket_fd = ::accept(server.m_internals->m_socket_fd,
                                              reinterpret_cast<sockaddr*>(&socket_internals.m_address), &address_lenght);
    
      if (socket_internals.m_socket_fd < 0) {
        // This should never happen
        throw UnexpectedError(strerror(errno));   // LCOV_EXCL_LINE
      }
    
      return Socket{p_socket_internals};
    }
    
    Socket
    connectServerSocket(const std::string& server_name, int port_number)
    {
      auto p_socket_internals             = std::make_shared<Socket::Internals>();
      Socket::Internals& socket_internals = *p_socket_internals;
    
      socket_internals.m_socket_fd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (socket_internals.m_socket_fd < 0) {
        // This should never happen
        throw UnexpectedError(strerror(errno));   // LCOV_EXCL_LINE
      }
    
      hostent* server = ::gethostbyname(server_name.c_str());
      if (server == NULL) {
        throw NormalError(strerror(errno));
      }
    
      sockaddr_in& serv_addr = socket_internals.m_address;
      ::memset(reinterpret_cast<char*>(&serv_addr), 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
    
      ::memcpy(reinterpret_cast<char*>(&serv_addr.sin_addr.s_addr), reinterpret_cast<char*>(server->h_addr),
               server->h_length);
    
      serv_addr.sin_port = htons(port_number);
    
      if (::connect(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&serv_addr), sizeof(serv_addr))) {
        throw NormalError(strerror(errno));
      }
    
      return Socket{p_socket_internals};
    }
    
    void
    Socket::_write(const char* data, const size_t lenght) const
    {
      if (this->m_internals->isServerSocket()) {
        throw NormalError("Server cannot write to server socket");
      }
    
      if (::write(this->m_internals->fileDescriptor(), data, lenght) < 0) {
        // Quite complex to test
        throw NormalError(strerror(errno));   // LCOV_EXCL_LINE
      }
    }
    
    void
    Socket::_read(char* data, const size_t length) const
    {
      if (this->m_internals->isServerSocket()) {
        throw NormalError("Server cannot read from server socket");
      }
    
      size_t received = 0;
      while (received < length) {
        int n = ::read(this->m_internals->fileDescriptor(), reinterpret_cast<char*>(data) + received, length - received);
        if (n <= 0) {
          throw NormalError("Could not read data");
        }
        received += n;
      }
    }