Skip to content
Snippets Groups Projects
Commit 3c7b1b8c authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

*** empty log message ***

parent e2488958
Branches
Tags
No related merge requests found
// you need gshhs data file, available on ftp://ftp.soest.hawaii.edu/
Field[1] = Box;
Field[1].VIn = 2000;
Field[1].VOut = 100000;
Field[1].XMax = 6000000;
Field[1].XMin = 3000000;
Field[1].YMin = -2000000;
Field[1].YMax = 1000000;
Field[1].ZMin = 3220000;
Field[1].ZMax = 6000000;
//Field[2] = MathEval;
//Field[2].F= "1.e3";
Plugin(GSHHS).iField=1;
Plugin(GSHHS).InFileName="gshhs_f.b";
Plugin(GSHHS).OutFileName="earth_adapt.geo";
Plugin(GSHHS).Run;
/*
Merge "earth_4km.geo";
Field[3] = Threshold;
Field[3].LcMin = 4e3;
Field[3].LcMax = 500e3;
Field[3].DistMax = 2000e3;
Field[3].DistMin = 0e3;
Field[3].IField = 2;
Field[4]=MathEval;
Field[4].F = "80e3";
Background Field = 3;
*/
// Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle // Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
// //
// Permission is hereby granted, free of charge, to any person // See the LICENSE.txt file for license information. Please report all
// obtaining a copy of this software and associated documentation // bugs and problems to <gmsh@geuz.org>.
// 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_CLIENT_H_ #ifndef _GMSH_SOCKET_H_
#define _GMSH_CLIENT_H_ #define _GMSH_SOCKET_H_
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef _AIX
#if defined(_AIX)
#include <strings.h> #include <strings.h>
#endif #endif
#if !defined(WIN32) || defined(__CYGWIN__) #if !defined(WIN32) || defined(__CYGWIN__)
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
...@@ -44,30 +23,38 @@ ...@@ -44,30 +23,38 @@
#include <sys/time.h> #include <sys/time.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#else
#else // pure windows
#include <winsock.h> #include <winsock.h>
#include <process.h> #include <process.h>
#endif #endif
class GmshClient { class GmshSocket{
private: public:
typedef enum{ CLIENT_START = 1, // types of messages that can be exchanged (never use values greater
CLIENT_STOP = 2, // that 65535: if we receive a type > 65535 we assume that we
CLIENT_INFO = 10, // receive data from a machine with a different byte ordering, and
CLIENT_WARNING = 11, // we swap the bytes in the payload)
CLIENT_ERROR = 12, enum MessageType{
CLIENT_PROGRESS = 13, CLIENT_START = 1,
CLIENT_MERGE_FILE = 20, // old name was CLIENT_VIEW CLIENT_STOP = 2,
CLIENT_PARSE_STRING = 21, CLIENT_INFO = 10,
CLIENT_OPTION_1 = 100, CLIENT_WARNING = 11,
CLIENT_OPTION_2 = 101, CLIENT_ERROR = 12,
CLIENT_OPTION_3 = 102, CLIENT_PROGRESS = 13,
CLIENT_OPTION_4 = 103, CLIENT_MERGE_FILE = 20, // old name: CLIENT_VIEW
CLIENT_OPTION_5 = 104 } MessageType; CLIENT_PARSE_STRING = 21,
CLIENT_SPEED_TEST = 30,
CLIENT_OPTION_1 = 100,
CLIENT_OPTION_2 = 101,
CLIENT_OPTION_3 = 102,
CLIENT_OPTION_4 = 103,
CLIENT_OPTION_5 = 104};
protected:
// the socket descriptor
int _sock; int _sock;
// the socket name
const char *_sockname;
// send some data over the socket
void _SendData(const void *buffer, int bytes) void _SendData(const void *buffer, int bytes)
{ {
const char *buf = (const char *)buffer; const char *buf = (const char *)buffer;
...@@ -79,14 +66,35 @@ class GmshClient { ...@@ -79,14 +66,35 @@ class GmshClient {
remaining -= len; remaining -= len;
} while(remaining > 0); } while(remaining > 0);
} }
void _SendString(int type, const char *str) // receive some data over the socket
int _ReceiveData(void *buffer, int bytes)
{ {
int len = strlen(str); char *buf = (char *)buffer;
_SendData(&type, sizeof(int)); int sofar = 0;
_SendData(&len, sizeof(int)); int remaining = bytes;
_SendData(str, len); do {
int len = recv(_sock, buf + sofar, remaining, 0);
if(len <= 0)
return 0;
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;
} }
void _Idle(int ms) // sleep for some milliseconds
void _Sleep(int ms)
{ {
#if !defined(WIN32) || defined(__CYGWIN__) #if !defined(WIN32) || defined(__CYGWIN__)
usleep(1000 * ms); usleep(1000 * ms);
...@@ -95,41 +103,89 @@ class GmshClient { ...@@ -95,41 +103,89 @@ class GmshClient {
#endif #endif
} }
public: public:
GmshClient() : _sock(0) {} GmshSocket() : _sock(0), _sockname(0)
~GmshClient(){}
int Connect(const char *sockname)
{ {
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
WSADATA wsaData; static bool first = true;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(first){
if(iResult != NO_ERROR) first = false;
return -4; // Error: Couldn't initialize Windows sockets WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
#endif #endif
}
~GmshSocket()
{
#if defined(WIN32) && !defined(__CYGWIN__)
WSACleanup();
#endif
}
// utility function to wait for some data to read on a socket (if
// seconds==0 we check for available data and return immediately,
// i.e., we do polling)
int Select(int socket, int seconds)
{
struct timeval tv;
tv.tv_sec = seconds;
tv.tv_usec = 0;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
// select checks all IO descriptors between 0 and its first arg,
// minus 1... hence the +1 below
return select(socket + 1, &rfds, NULL, NULL, &tv);
}
void SendString(int type, const char *str)
{
// send header (type + length)
_SendData(&type, sizeof(int));
int len = strlen(str);
_SendData(&len, sizeof(int));
// send body
_SendData(str, len);
}
int ReceiveHeader(int *type, int *len)
{
bool swap = false;
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 = true;
_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;
}
int ReceiveString(int len, char *str)
{
if(_ReceiveData(str, len) == len) {
str[len] = '\0';
return 1;
}
return 0;
}
};
class GmshClient : public GmshSocket {
public:
GmshClient() : GmshSocket() {}
~GmshClient(){}
int Connect(const char *sockname)
{
// slight delay to be sure that the socket is bound by the // slight delay to be sure that the socket is bound by the
// server before we attempt to connect to it... // server before we attempt to connect to it...
_Idle(100); _Sleep(100);
int portno;
char remote[256];
if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){ if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){
// UNIX socket (testing ":" is not enough with Windows paths)
portno = -1;
}
else{
// INET socket
char *port = strstr(sockname, ":");
portno = atoi(port + 1);
int remotelen = strlen(sockname) - strlen(port);
if(remotelen > 0)
strncpy(remote, sockname, remotelen);
remote[remotelen] = '\0';
}
// create socket
if(portno < 0){
#if !defined(WIN32) || defined(__CYGWIN__) #if !defined(WIN32) || defined(__CYGWIN__)
// UNIX socket (testing ":" is not enough with Windows paths)
_sock = socket(PF_UNIX, SOCK_STREAM, 0); _sock = socket(PF_UNIX, SOCK_STREAM, 0);
if(_sock < 0) if(_sock < 0)
return -1; // Error: Couldn't create socket return -1; // Error: Couldn't create socket
...@@ -141,21 +197,28 @@ class GmshClient { ...@@ -141,21 +197,28 @@ class GmshClient {
for(int tries = 0; tries < 5; tries++) { for(int tries = 0; tries < 5; tries++) {
if(connect(_sock, (struct sockaddr *)&addr_un, sizeof(addr_un)) >= 0) if(connect(_sock, (struct sockaddr *)&addr_un, sizeof(addr_un)) >= 0)
return _sock; return _sock;
_Idle(100); _Sleep(100);
} }
#else #else
// Unix sockets are not available on Windows without Cygwin return -1; // Unix sockets are not available on Windows
return -1;
#endif #endif
} }
else{ else{
// TCP/IP socket
_sock = socket(AF_INET, SOCK_STREAM, 0); _sock = socket(AF_INET, SOCK_STREAM, 0);
if(_sock < 0) if(_sock < 0)
return -1; // Error: Couldn't create socket return -1; // Error: Couldn't create socket
// try to connect socket to host:port
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; struct hostent *server;
if(!(server = gethostbyname(remote))) if(!(server = gethostbyname(remote)))
return -3; // Error: No such host return -3; // Error: No such host
// try to connect socket to given name
struct sockaddr_in addr_in; struct sockaddr_in addr_in;
memset((char *) &addr_in, 0, sizeof(addr_in)); memset((char *) &addr_in, 0, sizeof(addr_in));
addr_in.sin_family = AF_INET; addr_in.sin_family = AF_INET;
...@@ -164,7 +227,7 @@ class GmshClient { ...@@ -164,7 +227,7 @@ class GmshClient {
for(int tries = 0; tries < 5; tries++) { for(int tries = 0; tries < 5; tries++) {
if(connect(_sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) >= 0) if(connect(_sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) >= 0)
return _sock; return _sock;
_Idle(100); _Sleep(100);
} }
} }
return -2; // Error: Couldn't connect return -2; // Error: Couldn't connect
...@@ -177,46 +240,46 @@ class GmshClient { ...@@ -177,46 +240,46 @@ class GmshClient {
#else #else
sprintf(tmp, "%d", _getpid()); sprintf(tmp, "%d", _getpid());
#endif #endif
_SendString(CLIENT_START, tmp); SendString(CLIENT_START, tmp);
} }
void Stop() void Stop()
{ {
_SendString(CLIENT_STOP, "Goodbye!"); SendString(CLIENT_STOP, "Goodbye!");
} }
void Info(const char *str) void Info(const char *str)
{ {
_SendString(CLIENT_INFO, str); SendString(CLIENT_INFO, str);
} }
void Warning(const char *str) void Warning(const char *str)
{ {
_SendString(CLIENT_WARNING, str); SendString(CLIENT_WARNING, str);
} }
void Error(const char *str) void Error(const char *str)
{ {
_SendString(CLIENT_ERROR, str); SendString(CLIENT_ERROR, str);
} }
void Progress(const char *str) void Progress(const char *str)
{ {
_SendString(CLIENT_PROGRESS, str); SendString(CLIENT_PROGRESS, str);
} }
void View(const char *str) void View(const char *str)
{ {
// deprecated: use MergeFile(str) instead // deprecated: use MergeFile(str) instead
_SendString(CLIENT_MERGE_FILE, str); SendString(CLIENT_MERGE_FILE, str);
} }
void MergeFile(const char *str) void MergeFile(const char *str)
{ {
_SendString(CLIENT_MERGE_FILE, str); SendString(CLIENT_MERGE_FILE, str);
} }
void ParseString(const char *str) void ParseString(const char *str)
{ {
_SendString(CLIENT_PARSE_STRING, str); SendString(CLIENT_PARSE_STRING, str);
} }
void Option(int num, const char *str) void Option(int num, const char *str)
{ {
if(num < 1) num = 1; if(num < 1) num = 1;
if(num > 5) num = 5; if(num > 5) num = 5;
_SendString(CLIENT_OPTION_1 + num - 1, str); SendString(CLIENT_OPTION_1 + num - 1, str);
} }
void Disconnect() void Disconnect()
{ {
...@@ -224,9 +287,137 @@ class GmshClient { ...@@ -224,9 +287,137 @@ class GmshClient {
close(_sock); close(_sock);
#else #else
closesocket(_sock); closesocket(_sock);
WSACleanup();
#endif #endif
} }
}; };
class GmshServer : public GmshSocket{
private:
int _portno;
public:
GmshServer() : GmshSocket(), _portno(-1) {}
~GmshServer(){}
virtual int SystemCall(const char *str) = 0;
virtual int NonBlockingWait(int socket, int num, double waitint) = 0;
int StartClient(const char *command, const char *sockname=0, int maxdelay=4)
{
int justwait = (!command || !strlen(command));
_sockname = sockname;
// no socket? launch the command directly
if(!_sockname) {
SystemCall(command);
return 1;
}
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)
return -1; // Error: 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)
return -2; // Error: 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
return -7; // Unix sockets not available on Windows without Cygwin
#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
return -1; // Error: 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)
return -2; // Error: Couldn't bind socket to name
}
if(!justwait)
SystemCall(command); // Start the solver
// listen on socket (queue up to 20 connections before having
// them automatically rejected)
if(listen(tmpsock, 20))
return -3; // Error: Socket listen failed
if(justwait){
// wait indefinitely until we get data
if(NonBlockingWait(tmpsock, -1, 0.5))
return -6; // not an actual error: we just stopped listening
}
else{
// Wait at most maxdelay seconds for data, issue error if no
// connection in that amount of time
if(!Select(tmpsock, maxdelay))
return -4; // Error: Socket listening timeout
}
// accept connection request
#if defined(HAVE_NO_SOCKLEN_T)
int len;
#else
socklen_t len;
#endif
if(_portno < 0){
#if !defined(WIN32) || defined(__CYGWIN__)
struct sockaddr_un from_un;
len = sizeof(from_un);
_sock = accept(tmpsock, (struct sockaddr *)&from_un, &len);
#else
_sock = -7; // Unix sockets not available on Windows
#endif
}
else{
struct sockaddr_in from_in;
len = sizeof(from_in);
_sock = accept(tmpsock, (struct sockaddr *)&from_in, &len);
}
if(_sock < 0) return -5; // Error: Socket accept failed
// close temporary socket
#if !defined(WIN32) || defined(__CYGWIN__)
close(tmpsock);
#else
closesocket(tmpsock);
#endif
return _sock;
}
int StopClient()
{
#if !defined(WIN32) || defined(__CYGWIN__)
if(_portno < 0)
unlink(_sockname);
close(_sock);
#else
closesocket(_sock);
#endif
return 0;
}
};
#endif #endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment