Skip to content
Snippets Groups Projects
Select Git revision
  • 5866c8cb7fef28847ad1415c0a1f443ebd014b14
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

Context.h

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    GmshSocket.h 12.29 KiB
    // Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
    //
    // Permission is hereby granted, free of charge, to any person
    // obtaining a copy of this software and associated documentation
    // files (the "Software"), to deal in the Software without
    // restriction, including without limitation the rights to use, copy,
    // modify, merge, publish, distribute, and/or sell copies of the
    // Software, and to permit persons to whom the Software is furnished
    // to do so, provided that the above copyright notice(s) and this
    // permission notice appear in all copies of the Software and that
    // both the above copyright notice(s) and this permission notice
    // appear in supporting documentation.
    //
    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    // NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
    // COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
    // ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
    // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
    // WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
    // ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
    // OF THIS SOFTWARE.
    // 
    // Please report all bugs and problems to <gmsh@geuz.org>.
    
    #ifndef _GMSH_SOCKET_H_
    #define _GMSH_SOCKET_H_
    
    #include "GmshConfig.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #if defined(_AIX)
    #include <strings.h>
    #endif
    
    #if !defined(WIN32) || defined(__CYGWIN__)
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/stat.h>
    #include <sys/un.h>
    #include <sys/time.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #if defined(HAVE_NO_SOCKLEN_T)
    typedef int socklen_t;
    #endif
    #else
    #include <winsock.h>
    #include <process.h>
    typedef int socklen_t;
    #endif
    
    class GmshSocket{
     public:
      // types of messages that can be exchanged (never use values greater
      // that 65535: if we receive a type > 65535 we assume that we
      // receive data from a machine with a different byte ordering, and
      // we swap the bytes in the payload)
      enum MessageType{ 
        GMSH_START        = 1,
        GMSH_STOP         = 2,
        GMSH_INFO         = 10,
        GMSH_WARNING      = 11,
        GMSH_ERROR        = 12,
        GMSH_PROGRESS     = 13,
        GMSH_MERGE_FILE   = 20,
        GMSH_PARSE_STRING = 21,
        GMSH_VERTEX_ARRAY = 22,
        GMSH_SPEED_TEST   = 30,
        GMSH_OPTION_1     = 100,
        GMSH_OPTION_2     = 101,
        GMSH_OPTION_3     = 102,
        GMSH_OPTION_4     = 103,
        GMSH_OPTION_5     = 104};
     protected:
      // the socket descriptor
      int _sock;
      // the socket name
      const char *_sockname;
      // send some data over the socket
      void _SendData(const void *buffer, int bytes)
      {
        const char *buf = (const char *)buffer;
        int sofar = 0;
        int remaining = bytes;
        do {
          int len = send(_sock, buf + sofar, remaining, 0); 
          sofar += len;
          remaining -= len;
        } while(remaining > 0);
      }
      // receive some data over the socket
      int _ReceiveData(void *buffer, int bytes)
      {
        char *buf = (char *)buffer;
        int sofar = 0;
        int remaining = bytes;
        do {
          int len = recv(_sock, buf + sofar, remaining, 0);
          if(len == 0) break; // we're done!
          if(len < 0) return -1; // error
          sofar += len;
          remaining -= len;
        } while(remaining > 0);
        return bytes;
      }
      // utility function to swap bytes in an array
      void _SwapBytes(char *array, int size, int n)
      {
        char *x = new char[size];
        for(int i = 0; i < n; i++) {
          char *a = &array[i * size];
          memcpy(x, a, size);
          for(int c = 0; c < size; c++)
            a[size - 1 - c] = x[c];
        }
        delete [] x;
      }
      // sleep for some milliseconds
      void _Sleep(int ms)
      {
    #if !defined(WIN32) || defined(__CYGWIN__)
        usleep(1000 * ms);
    #else
        Sleep(ms);
    #endif
      }
     public:
      GmshSocket() : _sock(0), _sockname(0)
      {
    #if defined(WIN32) && !defined(__CYGWIN__)
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2, 2), &wsaData);
    #endif
      }
      ~GmshSocket()
      {
    #if defined(WIN32) && !defined(__CYGWIN__)
        WSACleanup();
    #endif
      }
      // utility function to wait for some data to read on a socket (if
      // seconds and microseconds == 0 we check for available data and
      // return immediately, i.e., we do polling). Returns 0 when data is
      // available.
      int Select(int seconds, int microseconds, int socket=-1)
      {
        int s = (socket < 0) ? _sock : socket;
        struct timeval tv;
        tv.tv_sec = seconds;
        tv.tv_usec = microseconds;
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(s, &rfds);
        // select checks all IO descriptors between 0 and its first arg,
        // minus 1... hence the +1 below
        return select(s + 1, &rfds, NULL, NULL, &tv);
      }
      void SendMessage(int type, int length, const void *msg)
      {
        // send header (type + length)
        _SendData(&type, sizeof(int));
        _SendData(&length, sizeof(int));
        // send body
        _SendData(msg, length);
      }
      void SendString(int type, const char *str)
      {
        SendMessage(type, strlen(str), str);
      }
      void Info(const char *str){ SendString(GMSH_INFO, str); }
      void Warning(const char *str){ SendString(GMSH_WARNING, str); }
      void Error(const char *str){ SendString(GMSH_ERROR, str); }
      void Progress(const char *str){ SendString(GMSH_PROGRESS, str); }
      void MergeFile(const char *str){ SendString(GMSH_MERGE_FILE, str); }
      void ParseString(const char *str){ SendString(GMSH_PARSE_STRING, str); }
      void SpeedTest(const char *str){ SendString(GMSH_SPEED_TEST, str); }
      void Option(int num, const char *str)
      {
        if(num < 1) num = 1;
        if(num > 5) num = 5;
        SendString(GMSH_OPTION_1 + num - 1, str);
      }
      int ReceiveHeader(int *type, int *len, int *swap)
      {
        *swap = 0;
        if(_ReceiveData(type, sizeof(int))){
          if(*type < 0) return 0;
          if(*type > 65535){ 
            // the data comes from a machine with different endianness and
            // we must swap the bytes
            *swap = 1;
            _SwapBytes((char*)type, sizeof(int), 1);
          }
          if(_ReceiveData(len, sizeof(int))){
            if(*len < 0) return 0;
            if(*swap) _SwapBytes((char*)len, sizeof(int), 1);
            return 1;
          }
        }
        return 0;
      }
      // str should be allocated with size (len+1)
      int ReceiveString(int len, char *str)
      {
        if(_ReceiveData(str, len) == len) {
          str[len] = '\0';
          return 1;
        }
        return 0;
      }
      void CloseSocket(int s)
      {
    #if !defined(WIN32) || defined(__CYGWIN__)
        close(s);
    #else
        closesocket(s);
    #endif
      }
      void ShutdownSocket(int s)
      {
    #if !defined(WIN32) || defined(__CYGWIN__)
        shutdown(s, SHUT_RDWR);
    #endif
      }
    };
    
    class GmshClient : public GmshSocket {
     public:
      GmshClient() : GmshSocket() {}
      ~GmshClient(){}
      int Connect(const char *sockname)
      {
        // slight delay to make sure that the socket is bound by the
        // server before we attempt to connect to it
        _Sleep(100);
    
        if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){
    #if !defined(WIN32) || defined(__CYGWIN__)
          // UNIX socket (testing ":" is not enough with Windows paths)
          _sock = socket(PF_UNIX, SOCK_STREAM, 0);
          if(_sock < 0) return -1;
          // try to connect socket to given name
          struct sockaddr_un addr_un;
          memset((char *) &addr_un, 0, sizeof(addr_un));
          addr_un.sun_family = AF_UNIX;
          strcpy(addr_un.sun_path, sockname);
          for(int tries = 0; tries < 5; tries++) {
            if(connect(_sock, (struct sockaddr *)&addr_un, sizeof(addr_un)) >= 0)
              return _sock;
            _Sleep(100);
          }
    #else
          return -1; // Unix sockets are not available on Windows
    #endif
        }
        else{
          // TCP/IP socket
          _sock = socket(AF_INET, SOCK_STREAM, 0);
          if(_sock < 0) return -1;
          // try to connect socket to host:port
          const char *port = strstr(sockname, ":");
          int portno = atoi(port + 1);
          int remotelen = strlen(sockname) - strlen(port);
          char remote[256];
          if(remotelen > 0)
            strncpy(remote, sockname, remotelen);
          remote[remotelen] = '\0';
          struct hostent *server;
          if(!(server = gethostbyname(remote))){
            CloseSocket(_sock);
            return -3; // no such host
          }
          struct sockaddr_in addr_in;
          memset((char *) &addr_in, 0, sizeof(addr_in));
          addr_in.sin_family = AF_INET;
          memcpy((char *)&addr_in.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
          addr_in.sin_port = htons(portno);
          for(int tries = 0; tries < 5; tries++) {
            if(connect(_sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) >= 0)
              return _sock;
            _Sleep(100);
          }
        }
        CloseSocket(_sock);
        return -2; // couldn't connect
      }
      void Start()
      {
        char tmp[256];
    #if !defined(WIN32) || defined(__CYGWIN__)
        sprintf(tmp, "%d", getpid());
    #else
        sprintf(tmp, "%d", _getpid());
    #endif
        SendString(GMSH_START, tmp);
      }
      void Stop(){ SendString(GMSH_STOP, "Goodbye!"); }
      void Disconnect(){ CloseSocket(_sock); }
    };
    
    class GmshServer : public GmshSocket{
     private:
      int _portno;
     public:
      GmshServer() : GmshSocket(), _portno(-1) {}
      virtual ~GmshServer(){}
      virtual int SystemCall(const char *str) = 0;
      virtual int NonBlockingWait(int socket, double waitint, double timeout) = 0;
      int Start(const char *command, const char *sockname, double timeout)
      {
        if(!sockname) throw "Invalid (null) socket name";
        _sockname = sockname;
        int tmpsock;
        if(strstr(_sockname, "/") || strstr(_sockname, "\\") || !strstr(_sockname, ":")){
          // UNIX socket (testing ":" is not enough with Windows paths)
          _portno = -1;
    #if !defined(WIN32) || defined(__CYGWIN__)
          // delete the file if it already exists
          unlink(_sockname);
          // create a socket
          tmpsock = socket(PF_UNIX, SOCK_STREAM, 0);
          if(tmpsock < 0) throw "Couldn't create socket";
          // bind the socket to its name
          struct sockaddr_un addr_un;
          memset((char *) &addr_un, 0, sizeof(addr_un));
          strcpy(addr_un.sun_path, _sockname);
          addr_un.sun_family = AF_UNIX;
          if(bind(tmpsock, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0){
            CloseSocket(tmpsock);
            throw "Couldn't bind socket to name";
          }
          // change permissions on the socket name in case it has to be rm'd later
          chmod(_sockname, 0666);
    #else
          throw "Unix sockets not available on Windows";
    #endif
        }
        else{
          // TCP/IP socket
          const char *port = strstr(_sockname, ":");
          _portno = atoi(port + 1);
          // create a socket
          tmpsock = socket(AF_INET, SOCK_STREAM, 0);
    #if !defined(WIN32) || defined(__CYGWIN__)
          if(tmpsock < 0)
    #else
          if(tmpsock == INVALID_SOCKET)
    #endif
            throw "Couldn't create socket";
          // bind the socket to its name
          struct sockaddr_in addr_in;
          memset((char *) &addr_in, 0, sizeof(addr_in));
          addr_in.sin_family = AF_INET;
          addr_in.sin_addr.s_addr = INADDR_ANY;
          addr_in.sin_port = htons(_portno);
          if(bind(tmpsock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0){
            CloseSocket(tmpsock);
            throw "Couldn't bind socket to name";
          }
        }
    
        if(command && strlen(command)){
          SystemCall(command); // start the solver
        }
        else{
          timeout = 0.; // no command launched: don't set a timeout
        }
    
        // listen on socket (queue up to 20 connections before having
        // them automatically rejected)
        if(listen(tmpsock, 20)){
          CloseSocket(tmpsock);
          throw "Socket listen failed";
        }
        
        // wait until we get data
        int ret = NonBlockingWait(tmpsock, 0.5, timeout);
        if(ret){
          CloseSocket(tmpsock);
          if(ret == 2){
            throw "Socket listening timeout";
          }
          else{
            return -1; // stopped listening
          }
        }
    
        // accept connection request
        if(_portno < 0){
    #if !defined(WIN32) || defined(__CYGWIN__)
          struct sockaddr_un from_un;
          socklen_t len = sizeof(from_un);
          _sock = accept(tmpsock, (struct sockaddr *)&from_un, &len);
    #endif
        }
        else{
          struct sockaddr_in from_in;
          socklen_t len = sizeof(from_in);
          _sock = accept(tmpsock, (struct sockaddr *)&from_in, &len);
        }
        CloseSocket(tmpsock);
    
        if(_sock < 0)
          throw "Socket accept failed";
        return _sock;
      }
      int Shutdown()
      {
    #if !defined(WIN32) || defined(__CYGWIN__)
        if(_portno < 0)
          unlink(_sockname);
    #endif
        ShutdownSocket(_sock);
        CloseSocket(_sock);
        return 0;
      }
    };  
    
    #endif