Skip to content
Snippets Groups Projects
Commit 707f0f21 authored by Maxime Graulich's avatar Maxime Graulich
Browse files

Initial commit for ONELAB2

parent 637fc0ba
No related branches found
No related tags found
No related merge requests found
Showing
with 2538 additions and 2 deletions
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#cmakedefine HAVE_ONELAB #cmakedefine HAVE_ONELAB
#cmakedefine HAVE_ONELAB2 #cmakedefine HAVE_ONELAB2
#cmakedefine HAVE_ONELAB_METAMODEL #cmakedefine HAVE_ONELAB_METAMODEL
#cmakedefine HAVE_UDT
#cmakedefine HAVE_OPENGL #cmakedefine HAVE_OPENGL
#cmakedefine HAVE_OPTHOM #cmakedefine HAVE_OPTHOM
#cmakedefine HAVE_OSMESA #cmakedefine HAVE_OSMESA
......
...@@ -38,10 +38,19 @@ ...@@ -38,10 +38,19 @@
#include <sstream> #include <sstream>
#include "GmshSocket.h" #include "GmshSocket.h"
#ifdef HAVE_ONELAB2
#include "NetworkUtils.h"
#include "OnelabAttributes.h"
#endif
namespace onelab{ namespace onelab{
// The base parameter class. // The base parameter class.
class parameter{ #ifdef HAVE_ONELAB2
class parameter : public OnelabAttr{
#else
class parameter {
#endif
private: private:
// the name of the parameter, including its '/'-separated path in the // the name of the parameter, including its '/'-separated path in the
// parameter hierarchy. Parameters or subpaths can start with numbers to // parameter hierarchy. Parameters or subpaths can start with numbers to
...@@ -292,6 +301,86 @@ namespace onelab{ ...@@ -292,6 +301,86 @@ namespace onelab{
} }
return true; return true;
} }
#ifdef HAVE_ONELAB2
static UInt16 attributeType() {return 0x05;}
virtual inline UInt16 getAttributeType() const {return this->attributeType();}
virtual inline UInt16 getAttributeLength() const {
UInt16 len = _name.length()+_label.length()+_help.length()+10;
for(std::map<std::string, bool>::const_iterator it = getClients().begin(); it != getClients().end(); it++)
len += it->first.size()+2;
for(std::map<std::string, std::string>::const_iterator it = _attributes.begin(); it != _attributes.end(); it++)
len += it->first.size()+it->second.size()+2;
return len;
}
virtual UInt8 *encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, (UInt8 *)_name.c_str(), this->_name.length()+1);
dst = encode(dst, (UInt8 *)_label.c_str(), this->_label.length()+1);
dst = encode(dst, (UInt8 *)_help.c_str(), this->_help.length()+1);
dst = encode(dst, (UInt8)_readOnly);
dst = encode(dst, (UInt8)_neverChanged);
dst = encode(dst, (UInt8)_visible);
dst = encode(dst, (UInt16)_attributes.size());
for(std::map<std::string, std::string>::const_iterator it = _attributes.begin(); it != _attributes.end(); it++) {
dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1);
dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1);
}
dst = encode(dst, (UInt16)_clients.size());
for(std::map<std::string, bool>::const_iterator it = getClients().begin(); it != getClients().end(); it++) {
dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1);
dst = encode(dst, (UInt8)it->second);
}
return dst;
}
virtual UInt8 *parseAttribute(UInt8 *src, UInt32 length)
{
UInt8 tmp;
UInt16 n;
src = parse(src, _name, '\0');
src = parse(src, _label, '\0');
src = parse(src, _help, '\0');
src = parse(src, tmp);
this->_readOnly = (bool)tmp;
src = parse(src, tmp);
this->_neverChanged = (bool)tmp;
src = parse(src, tmp);
this->_visible = (bool)tmp;
src = parse(src, n);
for(int i=0; i<n; i++) {
std::string key, value;
src = parse(src, key, '\0');
src = parse(src, value, '\0');
setAttribute(key, value);
}
src = parse(src, n);
for(int i=0; i<n; i++) {
std::string client;
src = parse(src, client, '\0');
src = parse(src, tmp);
addClient(client, (bool)tmp);
}
return src;
}
void showAttribute()
{
std::cout << "Name: " << getName() << std::endl
<< "Label: " << getLabel() << std::endl
<< "Help: " << getHelp() << std::endl
<< "Never changed: " << getNeverChanged() << std::endl
<< "Changed: " << getChanged() << std::endl
<< "Visible: " << getVisible() << std::endl;
}
#endif
}; };
class parameterLessThan{ class parameterLessThan{
...@@ -412,6 +501,73 @@ namespace onelab{ ...@@ -412,6 +501,73 @@ namespace onelab{
} }
return pos; return pos;
} }
#ifdef HAVE_ONELAB2
static UInt16 attributeType() {return 0x06;}
virtual inline UInt16 getAttributeType() const {return this->attributeType();}
virtual inline UInt16 getAttributeLength() const {
UInt16 len = parameter::getAttributeLength()+sizeof(double)*4+8+sizeof(double)*_choices.size();
for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); it != _valueLabels.end(); it++)
len += it->second.size()+1+sizeof(double);
return len;
}
UInt8 *encodeAttribute(UInt8 *dst)
{
dst = parameter::encodeAttribute(dst);
dst = encode(dst, _value);
dst = encode(dst, _min);
dst = encode(dst, _max);
dst = encode(dst, _step);
dst = encode(dst, (UInt32)_index);
dst = encode(dst, (UInt16)_choices.size());
for(unsigned int i = 0; i < _choices.size(); i++)
dst = encode(dst, _choices[i]);
dst = encode(dst, (UInt16)_valueLabels.size());
for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); it != _valueLabels.end(); it++) {
dst = encode(dst, it->first);
dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1);
}
return dst;
}
UInt8 *parseAttribute(UInt8 *src, UInt32 length)
{
UInt16 n;
src = parameter::parseAttribute(src, length);
src = parse(src, _value);
src = parse(src, _min);
src = parse(src, _max);
src = parse(src, _step);
src = parse(src, *(UInt32 *)&_index);
src = parse(src, n);
_choices.resize(n);
for(unsigned int i = 0; i < n; i++)
src = parse(src, _choices[i]);
src = parse(src, n);
for(int i=0; i<n; i++) {
double value;
std::string label;
src = parse(src, value);
src = parse(src, label, '\0');
setValueLabel(value, label);
}
return src;
}
void showAttribute()
{
parameter::showAttribute();
std::cout << "Value: " << this->_value << std::endl
<< "Min: " << this->_min << std::endl
<< "Max: " << this->_max << std::endl;
}
#endif
}; };
// The string class. A string has a mutable "kind": we do not derive // The string class. A string has a mutable "kind": we do not derive
...@@ -476,6 +632,51 @@ namespace onelab{ ...@@ -476,6 +632,51 @@ namespace onelab{
_choices[i] = getNextToken(msg, pos); _choices[i] = getNextToken(msg, pos);
return pos; return pos;
} }
#ifdef HAVE_ONELAB2
static UInt16 attributeType() {return 0x07;}
virtual inline UInt16 getAttributeType() const {return this->attributeType();}
virtual inline UInt16 getAttributeLength() const
{
UInt16 len = parameter::getAttributeLength();
len += _value.size()+_kind.size()+4;
for(unsigned int i = 0; i < _choices.size(); i++)
len += _choices[i].size()+1;
return len;
}
UInt8 *encodeAttribute(UInt8 *dst)
{
dst = parameter::encodeAttribute(dst);
dst = encode(dst, (UInt8 *)_value.c_str(), _value.size()+1);
dst = encode(dst, (UInt8 *)_kind.c_str(), _kind.size()+1);
dst = encode(dst, (UInt16)_choices.size());
for(unsigned int i = 0; i < _choices.size(); i++)
dst = encode(dst, (UInt8 *)_choices[i].c_str(), _choices[i].size()+1);
return dst;
}
UInt8 *parseAttribute(UInt8 *src, UInt32 length)
{
UInt16 n;
src = parameter::parseAttribute(src, length);
src = parse(src, _value, '\0');
src = parse(src, _kind, '\0');
src = parse(src, n);
_choices.resize(n);
for(unsigned int i=0; i<n; i++) {
src = parse(src, _choices[i], '\0');
}
return src;
}
void showAttribute()
{
parameter::showAttribute();
std::cout << "Value: " << this->_value << std::endl;
}
#endif
}; };
// The region class. A region can be any kind of geometrical entity, // The region class. A region can be any kind of geometrical entity,
...@@ -558,6 +759,63 @@ namespace onelab{ ...@@ -558,6 +759,63 @@ namespace onelab{
} }
return pos; return pos;
} }
#ifdef HAVE_ONELAB2
static UInt16 attributeType() {return 0x08;}
virtual inline UInt16 getAttributeType() const {return this->attributeType();}
virtual inline UInt16 getAttributeLength() const {
UInt16 len = parameter::getAttributeLength();
len += 2;
for(std::set<std::string>::const_iterator it = _value.begin(); it != _value.end(); it++)
len += it->size()+1;
len += 4;
len += 2;
for(unsigned int i = 0; i < _choices.size(); i++){
len += 2;
for(std::set<std::string>::const_iterator it = _choices[i].begin(); it != _choices[i].end(); it++)
len += it->size()+1;
}
return len;
}
UInt8 *encodeAttribute(UInt8 *dst)
{
dst = parameter::encodeAttribute(dst);
dst = encode(dst, (UInt16)this->_value.size());
for(std::set<std::string>::const_iterator it = _value.begin(); it != _value.end(); it++)
dst = encode(dst, (UInt8 *)it->c_str(), it->size()+1);
dst = encode(dst, (UInt32)_dimension);
dst = encode(dst, (UInt16)_choices.size());
for(unsigned int i = 0; i < _choices.size(); i++){
dst = encode(dst, (UInt16)_choices[i].size());
for(std::set<std::string>::const_iterator it = _choices[i].begin(); it != _choices[i].end(); it++)
dst = encode(dst, (UInt8 *)it->c_str(), it->size()+1);
}
return dst;
}
UInt8 *parseAttribute(UInt8 *src, UInt32 len)
{
src = parameter::parseAttribute(src, len);
UInt16 m = 0, n = 0;
std::string value;
src = parse(src, n);
for(int i=0; i<n; i++) {
src = parse(src, value, '\0');
_value.insert(value);
}
src = parse(src, *(UInt32 *)&_dimension);
src = parse(src, n);
_choices.resize(n);
for(int i=0; i<n; i++) {
src = parse(src, m);
for(int j=0; j<m; j++) {
src = parse(src, value, '\0');
_choices[i].insert(value);
}
}
return src;
}
void showAttribute() {}
#endif
}; };
// The (possibly piece-wise defined on regions) function class. Functions are // The (possibly piece-wise defined on regions) function class. Functions are
...@@ -642,6 +900,69 @@ namespace onelab{ ...@@ -642,6 +900,69 @@ namespace onelab{
} }
return pos; return pos;
} }
#ifdef HAVE_ONELAB2
static UInt16 attributeType() {return 0x09;}
virtual inline UInt16 getAttributeType() const {return this->attributeType();}
virtual inline UInt16 getAttributeLength() const {
UInt16 len = parameter::getAttributeLength();
len += 2;
for(std::map<std::string, std::string>::const_iterator it = _value.begin();
it != _value.end(); it++)
len += 2+it->first.size()+it->second.size();
for(unsigned int i = 0; i < _choices.size(); i++){
len += 2;
for(std::map<std::string, std::string>::const_iterator it = _choices[i].begin();
it != _choices[i].end(); it++) {
len += 2+it->first.size()+it->second.size();
}
}
return len;
}
UInt8 *encodeAttribute(UInt8 *dst)
{
dst = parameter::encodeAttribute(dst),
dst = encode(dst, (UInt16)this->_value.size());
for(std::map<std::string, std::string>::const_iterator it = _value.begin();
it != _value.end(); it++) {
dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1);
dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1);
}
dst = encode(dst, (UInt16)_choices.size());
for(unsigned int i = 0; i < _choices.size(); i++){
dst = encode(dst, (UInt16)_choices[i].size());
for(std::map<std::string, std::string>::const_iterator it = _choices[i].begin();
it != _choices[i].end(); it++) {
dst = encode(dst, (UInt8 *)it->first.c_str(), it->first.size()+1);
dst = encode(dst, (UInt8 *)it->second.c_str(), it->second.size()+1);
}
}
return dst;
}
UInt8 *parseAttribute(UInt8 *src, UInt32 len)
{
src = parameter::parseAttribute(src, len);
UInt16 m = 0, n = 0;
std::string key, value;
src = parse(src, n);
for(int i=0; i<n; i++) {
src = parse(src, key, '\0');
src = parse(src, value, '\0');
_value[key] = value;
}
src = parse(src, n);
_choices.resize(n);
for(int i=0; i<n; i++) {
src = parse(src, m);
for(int j=0; j<m; j++) {
src = parse(src, key, '\0');
src = parse(src, value, '\0');
_choices[i][key] = value;
}
}
return src;
}
void showAttribute() {}
#endif
}; };
// The parameter space, i.e., the set of parameters stored and handled by the // The parameter space, i.e., the set of parameters stored and handled by the
...@@ -695,6 +1016,9 @@ namespace onelab{ ...@@ -695,6 +1016,9 @@ namespace onelab{
} }
else{ else{
T* newp = new T(p); T* newp = new T(p);
#ifdef HAVE_ONELAB2
newp->isInDatabase(true);
#endif
if(client.size()) newp->addClient(client, true); if(client.size()) newp->addClient(client, true);
ps.insert(newp); ps.insert(newp);
} }
...@@ -770,6 +1094,31 @@ namespace onelab{ ...@@ -770,6 +1094,31 @@ namespace onelab{
const std::string &client=""){ return _get(ps, name, client, _regions); } const std::string &client=""){ return _get(ps, name, client, _regions); }
bool get(std::vector<function> &ps, const std::string &name="", bool get(std::vector<function> &ps, const std::string &name="",
const std::string &client=""){ return _get(ps, name, client, _functions); } const std::string &client=""){ return _get(ps, name, client, _functions); }
void getPtr(number **ptr, const std::string name, const std::string client="")
{*ptr = _getPtr(name, client, _numbers);}
void getPtr(string **ptr, const std::string name, const std::string client="")
{*ptr = _getPtr(name, client, _strings);}
void getPtr(region **ptr, const std::string name, const std::string client="")
{*ptr = _getPtr(name, client, _regions);}
void getPtr(function **ptr, const std::string name, const std::string client="")
{*ptr = _getPtr(name, client, _functions);}
template <class T> T* _getPtr(std::string name, const std::string client, std::set<T*, parameterLessThan> ps)
{
T tmp(name);
typename std::set<T*, parameterLessThan>::iterator it = ps.find(&tmp);
if(it != ps.end()){
if(client.size()) (*it)->addClient(client, true);
return *it;
}
return NULL;
}
void getAllParameters(std::set<parameter*, parameterLessThan> &ps) const
{
ps.insert(_numbers.begin(), _numbers.end());
ps.insert(_strings.begin(), _strings.end());
ps.insert(_regions.begin(), _regions.end());
ps.insert(_functions.begin(), _functions.end());
}
unsigned int getNumParameters() unsigned int getNumParameters()
{ {
return (int)(_numbers.size() + _strings.size() + _regions.size() + _functions.size()); return (int)(_numbers.size() + _strings.size() + _regions.size() + _functions.size());
...@@ -935,7 +1284,6 @@ namespace onelab{ ...@@ -935,7 +1284,6 @@ namespace onelab{
return false; return false;
} }
}; };
// The onelab server: a singleton that stores the parameter space and // The onelab server: a singleton that stores the parameter space and
// interacts with onelab clients. // interacts with onelab clients.
class server{ class server{
......
...@@ -34,6 +34,9 @@ typedef unsigned long intptr_t; ...@@ -34,6 +34,9 @@ typedef unsigned long intptr_t;
#include "pluginWindow.h" #include "pluginWindow.h"
#include "helpWindow.h" #include "helpWindow.h"
#include "onelabGroup.h" #include "onelabGroup.h"
#ifdef HAVE_ONELAB2
#include "onelab2Group.h"
#endif
#include "gmshLocalNetworkClient.h" #include "gmshLocalNetworkClient.h"
#include "fileDialogs.h" #include "fileDialogs.h"
#include "extraDialogs.h" #include "extraDialogs.h"
...@@ -3010,6 +3013,11 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu) ...@@ -3010,6 +3013,11 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu)
if(main && !detachedMenu){ if(main && !detachedMenu){
#if defined(HAVE_ONELAB2) #if defined(HAVE_ONELAB2)
// Hey Maxime, this is for you! // Hey Maxime, this is for you!
_onelab = NULL;
onelab2Group *_onelab2 = new onelab2Group(0, mh, twidth, height - mh - sh);
_tile->add(_onelab2);
_onelab2->resize(_tile->x(), _tile->y(), twidth, _tile->h());
_tile->redraw();
#else #else
_onelab = new onelabGroup(0, mh, twidth, height - mh - sh); _onelab = new onelabGroup(0, mh, twidth, height - mh - sh);
_onelab->enableTreeWidgetResize(false); _onelab->enableTreeWidgetResize(false);
......
#include "onelab2Group.h"
#include "FlGui.h"
#include <FL/Fl_Box.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Menu_Item.H>
#include "inputRange.h"
#include "outputRange.h"
#include "inputRegion.h"
#include "OnelabDatabase.h"
#include "Options.h"
#include "Context.h"
OnelabDatabase *OnelabDatabase::_instance = NULL;
void connect_cb(Fl_Widget *w, void *arg)
{
onelab2Group *obj = (onelab2Group *)arg;
obj->clearTree();
GmshNetworkClient *cli = OnelabDatabase::instance()->useAsNetworkClient(obj->getServerIP(), obj->getServerPort());
cli->setCallback(obj);
// FIXME just for debug
FILE *fp = fopen("/tmp/onelab.db", "rb");
if(fp){
std::cout << "Get database from onelab.db" << std::endl;
OnelabDatabase::instance()->fromFile(fp);
fclose(fp);
}
}
void onelab2_cb(Fl_Widget *w, void *data)
{
if(!data) return;
std::string action((const char*)data);
OnelabDatabase::instance()->onelab_cb(action);
}
static bool getFlColor(const std::string &str, Fl_Color &c)
{
if(str == "1"){
c = FL_YELLOW;
return true;
}
int r, g, b;
if(str.size() && GetRGBForString(str.c_str(), r, g, b)){
c = fl_color_cube(r * (FL_NUM_RED - 1) / 255,
g * (FL_NUM_GREEN - 1) / 255,
b * (FL_NUM_BLUE - 1) / 255);
return true;
}
c = FL_BLACK;
return false;
}
onelab2Group::onelab2Group(int x, int y, int w, int h, const char *l)
: Fl_Group(x, y, w, h, l), _stop(false), _enableTreeWidgetResize(false)
{
int col = FL_BACKGROUND2_COLOR;
color(col);
box(GMSH_SIMPLE_RIGHT_BOX);
int dx = Fl::box_dx(box());
int dy = Fl::box_dy(box());
int dw = Fl::box_dw(box());
int dh = Fl::box_dh(box());
_tree = new Fl_Tree(x + dx, y + dy + 6*BH, w - dw, h - dh - BH - 2 * WB - 6*BH);
_tree->color(col);
// TODO _tree->callback(onelab_tree_cb);
_tree->connectorstyle(FL_TREE_CONNECTOR_SOLID);
_tree->showroot(0);
_tree->box(FL_FLAT_BOX);
_tree->scrollbar_size(std::max(10, FL_NORMAL_SIZE - 2));
_tree->end();
int BB2 = BB / 2 + 4;
_butt[0] = new Fl_Button(x + w - 3 * WB - 3 * BB2, y + h - WB - BH, BB2, BH, "Check");
_butt[0]->callback(onelab2_cb, (void*)"check");
_butt[1] = new Fl_Button(x + w - 2 * WB - 2 * BB2, y + h - WB - BH, BB2, BH, "Run");
_butt[1]->callback(onelab2_cb, (void*)"compute");
Fl_Check_Button *useServer = new Fl_Check_Button(x+WB, y, w-2*WB, BH, "Use a distant server"); // TODO
Fl_Box *ip_lbl = new Fl_Box(x+WB , y+BH, w-2*WB, BH, "Server IP address:");
server_ip = new Fl_Input(x+WB, y+2*BH, w-2*WB, BH, "ip");
server_ip->value("127.0.0.1");
Fl_Box *port_lbl = new Fl_Box(x+WB , y+3*BH, w-2*WB, BH, "Server port:");
server_port = new Fl_Input(x+WB, y+4*BH, w-2*WB, BH, "port");
server_port->value("3456");
Fl_Button *connect_btn = new Fl_Button(x+WB, y+5*BH, w-2*WB, BH, "Connect");
connect_btn->callback(connect_cb, this);
_computeWidths();
_widgetLabelRatio = 0.48;
OnelabDatabase::instance()->useAsClient()->setCallback(this);
}
onelab2Group::~onelab2Group()
{
Fl::delete_widget(_tree);
}
void onelab2Group::clearTree(bool deleteWidgets)
{
_tree->clear();
_tree->sortorder(FL_TREE_SORT_ASCENDING);
_tree->selectmode(FL_TREE_SELECT_NONE);
std::vector<Fl_Widget*> delWidgets;
std::vector<char*> delStrings;
if(deleteWidgets){
delWidgets = _treeWidgets;
delStrings = _treeStrings;
_treeWidgets.clear();
_treeStrings.clear();
}
FlGui::check();
if(deleteWidgets){
for(unsigned int i = 0; i < delWidgets.size(); i++)
Fl::delete_widget(delWidgets[i]);
for(unsigned int i = 0; i < delStrings.size(); i++)
free(delStrings[i]);
}
}
template <class T>
void onelab2Group::addParameter(T &p)
{
std::cout << "add " << p.getName() << " to the tree (visible = " << p.getVisible() << ')' << std::endl;
if(!p.getVisible() || CTX::instance()->solver.showInvisibleParameters) return;
bool highlight = false;
Fl_Color c;
if(getFlColor(p.getAttribute("Highlight"), c)) highlight = true;
Fl_Tree_Item *n = _tree->add(p.getName().c_str());
n->labelsize(FL_NORMAL_SIZE + 4);
int ww = _baseWidth - (n->depth() + 1) * _indent;
ww *= _widgetLabelRatio; // FIXME CHANGE THIS
int hh = n->labelsize() + 4;
Fl_Group *grp = new Fl_Group(1, 1, ww, hh);
Fl_Widget *widget = _addParameterWidget(p, ww, hh, n, highlight, c);
grp->end();
if(!_enableTreeWidgetResize) grp->resizable(0);
_treeWidgets.push_back(grp);
widget->copy_label(p.getShortName().c_str());
std::string help = p.getLabel().size() ? p.getLabel() : p.getShortName();
if(p.getHelp().size()) help += ":\n" + p.getHelp();
widget->copy_tooltip(help.c_str());
n->widget(grp);
_tree->end();
_tree->redraw();
}
Fl_Widget *onelab2Group::_addParameterWidget(onelab::parameter &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
{
int type = p.getAttributeType();
if(type == onelab::number::attributeType())
return _addParameterWidget(*(onelab::number *)&p, ww, hh, n, highlight, c);
if(type == onelab::string::attributeType())
return _addParameterWidget(*(onelab::string *)&p, ww, hh, n, highlight, c);
if(type == onelab::region::attributeType())
return _addParameterWidget(*(onelab::region *)&p, ww, hh, n, highlight, c);
if(type == onelab::function::attributeType())
return _addParameterWidget(*(onelab::function *)&p, ww, hh, n, highlight, c);
return NULL;
}
// callback for number
static void onelab_number_input_range_cb(Fl_Widget *w, void *data)
{
if(!data) return;
std::string name((char*)data);
std::cout << name << std::endl;
std::vector<onelab::number> numbers;
OnelabDatabase::instance()->get(numbers, name);
if(numbers.size()){
inputRange *o = (inputRange*)w;
onelab::number old = numbers[0];
if(o->doCallbackOnValues()){
numbers[0].setValue(o->value());
numbers[0].setMin(o->minimum());
numbers[0].setMax(o->maximum());
numbers[0].setStep(o->step());
numbers[0].setChoices(o->choices());
}
o->doCallbackOnValues(true);
numbers[0].setAttribute("Loop", o->loop());
numbers[0].setAttribute("Graph", o->graph());
//setGmshOption(numbers[0]);
OnelabDatabase::instance()->set(numbers[0]);
//updateGraphs();
//autoCheck(old, numbers[0]);
}
}
static void onelab_number_choice_cb(Fl_Widget *w, void *data)
{
if(!data) return;
std::string name((char*)data);
std::vector<onelab::number> numbers;
OnelabDatabase::instance()->get(numbers, name);
if(numbers.size()){
Fl_Choice *o = (Fl_Choice*)w;
std::vector<double> choices = numbers[0].getChoices();
onelab::number old = numbers[0];
if(o->value() < (int)choices.size()) numbers[0].setValue(choices[o->value()]);
//setGmshOption(numbers[0]);
OnelabDatabase::instance()->set(numbers[0]);
//autoCheck(old, numbers[0]);
}
}
static void onelab_number_check_button_cb(Fl_Widget *w, void *data)
{
if(!data) return;
std::string name((char*)data);
std::vector<onelab::number> numbers;
OnelabDatabase::instance()->get(numbers, name);
if(numbers.size()){
Fl_Check_Button *o = (Fl_Check_Button*)w;
onelab::number old = numbers[0];
numbers[0].setValue(o->value());
//setGmshOption(numbers[0]);
OnelabDatabase::instance()->set(numbers[0]);
//autoCheck(old, numbers[0]);
}
}
// add a parameter number to the tree
Fl_Widget *onelab2Group::_addParameterWidget(onelab::number &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
{
char *path = strdup(getPath(n).c_str());
_treeStrings.push_back(path);
// enumeration (display choices as value labels, not numbers)
if(p.getChoices().size() &&
p.getChoices().size() == p.getValueLabels().size()){
Fl_Choice *but = new Fl_Choice(1, 1, ww, hh);
std::vector<Fl_Menu_Item> menu;
std::map<double, std::string> labels(p.getValueLabels());
for(std::map<double, std::string>::iterator it = labels.begin();
it != labels.end(); it++){
char *str = strdup(it->second.c_str());
_treeStrings.push_back(str);
Fl_Menu_Item menuItem = {str, 0, 0, 0, 0};
if(highlight) menuItem.labelcolor(c);
menu.push_back(menuItem);
}
Fl_Menu_Item it = {0};
menu.push_back(it);
but->copy(&menu[0]);
for(unsigned int i = 0; i < p.getChoices().size(); i++){
if(p.getValue() == p.getChoices()[i]){
but->value(i);
break;
}
}
but->callback(onelab_number_choice_cb, (void*)path);
but->align(FL_ALIGN_RIGHT);
if(p.getReadOnly()) but->deactivate();
return but;
}
// check box (boolean choice)
if(p.getChoices().size() == 2 &&
p.getChoices()[0] == 0 && p.getChoices()[1] == 1){
n->labelsize(FL_NORMAL_SIZE + 2);
Fl_Check_Button *but = new Fl_Check_Button(1, 1, ww / _widgetLabelRatio, hh);
but->box(FL_FLAT_BOX);
but->color(_tree->color());
but->value(p.getValue());
but->callback(onelab_number_check_button_cb, (void*)path);
if(highlight) but->color(c);
if(p.getReadOnly()) but->deactivate();
return but;
}
// non-editable value
if(p.getReadOnly()){
outputRange *but = new outputRange(1, 1, ww, hh);
//TODO but->callback(onelab_number_output_range_cb, (void*)path);
but->value(p.getValue());
but->align(FL_ALIGN_RIGHT);
but->graph(p.getAttribute("Graph"));
if(highlight) but->color(c);
return but;
}
// general number input
inputRange *but = new inputRange(1, 1, ww, hh, onelab::parameter::maxNumber(),
p.getAttribute("ReadOnlyRange") == "1");
but->value(p.getValue());
but->minimum(p.getMin());
but->maximum(p.getMax());
but->step(p.getStep());
but->choices(p.getChoices());
but->loop(p.getAttribute("Loop"));
but->graph(p.getAttribute("Graph"));
but->callback(onelab_number_input_range_cb, (void*)path);
but->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY);
but->align(FL_ALIGN_RIGHT);
if(highlight) but->color(c);
return but;
}
// callback for string
static void onelab_string_input_choice_cb(Fl_Widget *w, void *data)
{
if(!data) return;
std::string name((char*)data);
std::vector<onelab::string> strings;
OnelabDatabase::instance()->get(strings, name);
if(strings.size()){
Fl_Input_Choice *o = (Fl_Input_Choice*)w;
onelab::string old = strings[0];
strings[0].setValue(o->value());
std::string choices;
for(int i = 0; i < o->menubutton()->menu()->size(); i++){
if(o->menubutton()->menu()[i].flags & FL_MENU_TOGGLE){
if(o->menubutton()->menu()[i].flags & FL_MENU_VALUE)
choices += "1";
else
choices += "0";
}
}
if(choices.size())
strings[0].setAttribute("MultipleSelection", choices);
//setGmshOption(strings[0]);
OnelabDatabase::instance()->set(strings[0]);
//autoCheck(old, strings[0]);
}
}
// add parameter string to tree
Fl_Widget *onelab2Group::_addParameterWidget(onelab::string &p, int ww, int hh,
Fl_Tree_Item *n, bool highlight, Fl_Color c)
{
char *path = strdup(getPath(n).c_str());
_treeStrings.push_back(path);
// macro button
if(p.getAttribute("Macro") == "Gmsh"){
Fl_Button *but = new Fl_Button(1, 1, ww / _widgetLabelRatio, hh);
but->box(FL_FLAT_BOX);
but->color(_tree->color());
but->selection_color(_tree->color());
but->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
//TODO but->callback(onelab_string_button_cb, (void*)path);
if(highlight) but->color(c);
return but;
}
// non-editable value
if(p.getReadOnly()){
Fl_Output *but = new Fl_Output(1, 1, ww, hh);
but->value(p.getValue().c_str());
but->align(FL_ALIGN_RIGHT);
if(highlight) but->color(c);
return but;
}
// simple string (no menu)
if(p.getChoices().empty() && p.getKind() != "file"){
Fl_Input *but = new Fl_Input(1, 1, ww, hh);
but->value(p.getValue().c_str());
//TODO but->callback(onelab_string_input_cb, (void*)path);
but->when(FL_WHEN_ENTER_KEY);
but->align(FL_ALIGN_RIGHT);
if(highlight) but->color(c);
return but;
}
// general string input
Fl_Input_Choice *but = new Fl_Input_Choice(1, 1, ww, hh);
std::string multipleSelection = p.getAttribute("MultipleSelection");
if(multipleSelection.size())
;//but->menubutton()->callback(multiple_selection_menu_cb, but);
std::vector<Fl_Menu_Item> menu;
for(unsigned int j = 0; j < p.getChoices().size(); j++){
char *str = strdup(p.getChoices()[j].c_str());
_treeStrings.push_back(str);
bool divider = (p.getKind() == "file" &&
j == p.getChoices().size() - 1);
int choice = multipleSelection.size() ? FL_MENU_TOGGLE : 0;
if(multipleSelection.size() > j && multipleSelection[j] == '1')
choice |= FL_MENU_VALUE;
Fl_Menu_Item it = {str, 0, 0, 0, divider ? FL_MENU_DIVIDER : choice};
menu.push_back(it);
}
//if(p.getKind() == "file"){
// Fl_Menu_Item it = {"Choose...", 0, onelab_input_choice_file_chooser_cb, (void*)n};
// menu.push_back(it);
// Fl_Menu_Item it2 = {"Edit...", 0, onelab_input_choice_file_edit_cb, (void*)n};
// menu.push_back(it2);
// if(GuessFileFormatFromFileName(p.getValue()) >= 0){
// Fl_Menu_Item it3 = {"Merge...", 0, onelab_input_choice_file_merge_cb, (void*)n};
// menu.push_back(it3);
// }
//}
Fl_Menu_Item it = {0};
menu.push_back(it);
but->menubutton()->copy(&menu[0]);
but->value(p.getValue().c_str());
but->callback(onelab_string_input_choice_cb, (void*)path);
but->input()->when(FL_WHEN_ENTER_KEY);
but->align(FL_ALIGN_RIGHT);
if(highlight) but->input()->color(c);
return but;
}
Fl_Widget *onelab2Group::_addParameterWidget(onelab::region &p, int ww, int hh,
Fl_Tree_Item *n, bool highlight, Fl_Color c)
{
char *path = strdup(getPath(n).c_str());
_treeStrings.push_back(path);
// non-editable value
if(p.getReadOnly()){
inputRegion *but = new inputRegion(1, 1, ww, hh, true);
but->value(p.getValue());
but->align(FL_ALIGN_RIGHT);
if(highlight) but->color(c);
return but;
}
inputRegion *but = new inputRegion(1, 1, ww, hh, false);
but->value(p.getValue());
but->align(FL_ALIGN_RIGHT);
//TODO but->callback(onelab_region_input_cb, (void*)path);
if(highlight) but->color(c);
return but;
}
Fl_Widget *onelab2Group::_addParameterWidget(onelab::function &p, int ww, int hh,
Fl_Tree_Item *n, bool highlight, Fl_Color c)
{
// non-editable value
if(1 || p.getReadOnly()){
Fl_Output *but = new Fl_Output(1, 1, ww, hh);
but->value("TODO function");
but->align(FL_ALIGN_RIGHT);
if(highlight) but->color(c);
return but;
}
}
void onelab2Group::updateParameter(onelab::parameter &p)
{
int type = p.getAttributeType();
if(type == onelab::number::attributeType())
return updateParameter(*(onelab::number *)&p);
if(type == onelab::string::attributeType())
return updateParameter(*(onelab::string *)&p);
}
void onelab2Group::updateParameter(onelab::number &p)
{
Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
if(!n) {
addParameter(p);
return;
}
Fl_Group *grp = (Fl_Group *)n->widget();
// enumeration (display choices as value labels, not numbers)
if(p.getChoices().size() &&
p.getChoices().size() == p.getValueLabels().size()){
Fl_Choice *but = (Fl_Choice *)grp->child(0);
//std::vector<Fl_Menu_Item> menu;
//std::map<double, std::string> labels(p.getValueLabels());
//for(std::map<double, std::string>::iterator it = labels.begin();
// it != labels.end(); it++){
// char *str = strdup(it->second.c_str());
// _treeStrings.push_back(str);
// Fl_Menu_Item menuItem = {str, 0, 0, 0, 0};
// if(highlight) menuItem.labelcolor(c);
// menu.push_back(menuItem);
//}
//Fl_Menu_Item it = {0};
//menu.push_back(it);
//but->copy(&menu[0]);
for(unsigned int i = 0; i < p.getChoices().size(); i++){
if(p.getValue() == p.getChoices()[i]){
but->value(i);
break;
}
}
return;
}
// check box (boolean choice)
if(p.getChoices().size() == 2 &&
p.getChoices()[0] == 0 && p.getChoices()[1] == 1){
Fl_Check_Button *but = (Fl_Check_Button *)grp->child(0);
but->value(p.getValue());
return;
}
// non-editable value FIXME
if(p.getReadOnly()){
outputRange *but = (outputRange *)grp->child(0);;
but->value(p.getValue());
but->graph(p.getAttribute("Graph"));
return;
}
// general number input
inputRange *but = (inputRange *)grp->child(0);
but->value(p.getValue());
but->minimum(p.getMin());
but->maximum(p.getMax());
but->step(p.getStep());
but->choices(p.getChoices());
but->loop(p.getAttribute("Loop"));
but->graph(p.getAttribute("Graph"));
}
void onelab2Group::updateParameter(onelab::string &p)
{
Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
if(!n) {
addParameter(p);
return;
}
Fl_Group *grp = (Fl_Group *)n->widget();
// macro button
if(p.getAttribute("Macro") == "Gmsh"){
return;
}
// non-editable value FIXME
if(p.getReadOnly()){
Fl_Output *but = (Fl_Output *)grp->child(0);
but->value(p.getValue().c_str());
return;
}
// simple string (no menu)
if(p.getChoices().empty() && p.getKind() != "file"){
Fl_Input *but = (Fl_Input *)grp->child(0);
but->value(p.getValue().c_str());
return;
}
// general string input TODO
Fl_Input_Choice *but = (Fl_Input_Choice *)grp->child(0);
but->value(p.getValue().c_str());
}
void onelab2Group::removeParameter(onelab::parameter &p)
{
Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
_tree->remove(n);
}
void onelab2Group::_computeWidths()
{
_baseWidth = (int)(_tree->w() - _tree->marginleft());
_indent = (int)(_tree->connectorwidth() / 2. + _tree->openicon()->w() / 2.);
}
std::string onelab2Group::getPath(Fl_Tree_Item *item)
{
if(!item){
Msg::Error("No item for path");
return "";
}
char path[1024];
if(_tree->item_pathname(path, sizeof(path), item)){
Msg::Error("Could not get path for item");
return "";
}
return std::string(path);
}
#ifndef _ONELAB2_GROUP_H_
#define _ONELAB2_GROUP_H_
#include <vector>
#include <set>
#include <string>
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Tree.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Input.H>
#include "NetworkUtils.h"
#include "onelab.h"
class onelab2Group : public Fl_Group{
private:
Fl_Input *server_ip, *server_port;
Fl_Tree *_tree;
Fl_Button *_butt[2];
Fl_Menu_Button *_gear;
int _gearOptionsStart, _gearOptionsEnd;
std::vector<Fl_Widget*> _treeWidgets;
std::vector<char*> _treeStrings;
bool _stop;
int _baseWidth, _indent;
int _minWindowWidth, _minWindowHeight;
double _widgetLabelRatio;
std::set<std::string> _manuallyClosed;
bool _enableTreeWidgetResize;
Fl_Widget *_addParameterWidget(onelab::parameter &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
Fl_Widget *_addParameterWidget(onelab::number &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
Fl_Widget *_addParameterWidget(onelab::string &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
Fl_Widget *_addParameterWidget(onelab::function &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
Fl_Widget *_addParameterWidget(onelab::region &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
void _computeWidths();
public:
onelab2Group(int x, int y, int w, int h, const char *l=0);
~onelab2Group();
void clearTree(bool deleteWidgets=true);
void createRemoteTree(bool keepLocal=true);
UInt32 getServerIP() {return ip4_inet_pton(server_ip->value());}
UInt16 getServerPort() {return (UInt16)strtoul(server_port->value(), NULL, 0);}
template <class T> void addParameter(T &p);
void updateParameter(onelab::parameter &p);
void updateParameter(onelab::number &p);
void updateParameter(onelab::string &p);
void removeParameter(onelab::parameter &p);
std::string getPath(Fl_Tree_Item *item);
};
void connect_cb(Fl_Widget *w, void *arg);
#endif
set(SRC
NetworkUtils.cpp
OnelabAttributes.cpp
OnelabProtocol.cpp
OnelabLocalNetworkClient.cpp
OnelabServer.cpp
OnelabNetworkClient.cpp)
file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
append_gmsh_src(contrib/onelab2 "${SRC};${HDR}")
# build only the server
if(HAVE_UDT)
find_package(Threads REQUIRED)
find_path(UDT_INCLUDE_DIR NAMES udt.h PATH_SUFFIXES udt/)
find_library(UDT_LIBRARY NAMES udt)
if(UDT_INCLUDE_DIR AND UDT_LIBRARY AND CMAKE_THREAD_LIBS_INIT)
list(APPEND EXTERNAL_INCLUDES ${UDT_INCLUDE_DIR})
list(APPEND EXTERNAL_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
list(APPEND EXTERNAL_LIBRARIES ${UDT_LIBRARY})
else(UDT_INCLUDE_DIR AND UDT_LIBRARY AND CMAKE_THREAD_LIBS_INIT)
message(FATAL_ERROR "Unable to find UDT library")
endif(UDT_INCLUDE_DIR AND UDT_LIBRARY AND CMAKE_THREAD_LIBS_INIT)
endif(HAVE_UDT)
include_directories(${CMAKE_SOURCE_DIR}/Common/) # for onelab.h
include_directories(${CMAKE_BINARY_DIR}/Common/) # for GmshConfig.h
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/)
include_directories(${EXTERNAL_INCLUDES}) # for UDT
add_executable (onelabserver Onelab.cpp OnelabServer.cpp OnelabNetworkClient.cpp OnelabLocalNetworkClient.cpp NetworkUtils.cpp OnelabProtocol.cpp OnelabAttributes.cpp)
target_link_libraries(onelabserver ${EXTERNAL_LIBRARIES})
#ifndef _GMSHLOCLACLIENT_H_
#define _GMSHLOCALCLIENT_H_
#include "OnelabLocalClient.h"
class GmshLocalClient : public OnelabLocalClient
{
private:
onelab2Group *_cb_obj;
public:
GmshLocalClient(std::string name, onelab::parameterSpace *parameterSpace)
: OnelabLocalClient(name, parameterSpace){
}
~GmshLocalClient(){}
void setCallback(onelab2Group *cb) {_cb_obj = cb;}
void onNewParameter(onelab::parameter *p){_cb_obj->addParameter(*p);}
void onUpdateParameter(onelab::parameter *p){_cb_obj->updateParameter(*p);}
void onRemoveParameter(onelab::parameter *p){_cb_obj->removeParameter(*p);}
};
#endif
#ifndef _GMSHCLIENT_H_
#define _GMSHCLIENT_H_
#include <vector>
#include "VirtualClient.h"
#include "NetworkUtils.h"
#include "OnelabNetworkClient.h"
#include "OnelabProtocol.h"
class onelab2Group;
class GmshNetworkClient : public OnelabNetworkClient
{
private:
onelab2Group *_cb_obj;
public:
GmshNetworkClient(std::string name) : OnelabNetworkClient(name) {}
GmshNetworkClient(std::string name, unsigned int ip, unsigned short port) : OnelabNetworkClient(name, ip, port) {}
~GmshNetworkClient() {}
void setCallback(onelab2Group *cb) {_cb_obj = cb;}
void onNewParameter(onelab::parameter *p){_cb_obj->addParameter(*p);}
void onUpdateParameter(onelab::parameter *p){_cb_obj->updateParameter(*p);}
void onRemoveParameter(onelab::parameter *p){_cb_obj->removeParameter(*p);}
};
#endif
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <iostream>
#include <unistd.h>
#include "NetworkUtils.h"
UInt32 ip4_inet_pton(const char *ip)
{
struct in_addr dst;
if(inet_pton(AF_INET, ip, &dst) == 0)
return 0; // the string seems to contain an invalid ip
return ntohl(dst.s_addr);
}
UInt32 ip4_inet_resolve(const char *hostname)
{
struct hostent *he;
struct in_addr **addr_list;
if((he = gethostbyname(hostname)) == NULL)
return 0;
addr_list = (struct in_addr **) he->h_addr_list;
for(int i = 0; addr_list[i] != NULL; i++)
return ntoh32(addr_list[i]->s_addr);
return 0;
}
void ip4_socket_ip(Socket fd, IPv4 &ip)
{
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if(getsockname(fd, (struct sockaddr *)&sin, &len) != -1){
ip.address = ntoh32(sin.sin_addr.s_addr);
ip.port = ntoh16(sin.sin_port);
}
}
UInt32 ip4_default_iface()
{
struct ifaddrs *ifas = NULL;
UInt32 ip = 0;
getifaddrs(&ifas);
for (struct ifaddrs *ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
if(ifa->ifa_addr->sa_family == AF_INET) {
UInt32 tmp = ntoh32((UInt32)((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr);
if(!ip4_is_loopback(tmp)) {
ip = tmp;
break;
}
}
}
freeifaddrs(ifas);
return ip;
}
Socket ip4_socket(IPv4 ip, int socketType)
{
Socket fd;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = hton32((ip.address==0)? INADDR_ANY : ip.address);
addr.sin_port = hton16(ip.port);
if((fd = socket(AF_INET, socketType, 0)) < 0) throw ERROR_SOCKET_CREATE;
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) throw ERROR_SOCKET_BIND;
return fd;
}
void ip4_socket_timeout(Socket fd, long tos, long tous)
{
struct timeval tv;
tv.tv_sec = tos; // seconds
tv.tv_usec = tous; // microseconds
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
}
int ip4_socket_send(Socket fd, UInt8 *src, int length)
{
ssize_t sent = send(fd, src, length, 0);
// TODO handle error (length != sent) for ??? and (sent < 0) for local error
std::cout << "ip: send " << sent << "/" << length << "bytes" << std::endl;
return (int)sent;
}
int ip4_socket_send(Socket fd, UInt8 *src, int length, IPv4 dst)
{
struct sockaddr_in to;
socklen_t tol = sizeof(to);
memset(&to, 0, tol);
to.sin_family = AF_INET;
to.sin_port = hton16(dst.port);
to.sin_addr.s_addr = hton32(dst.address);
ssize_t sent = sendto(fd, src, length, 0, (struct sockaddr *)&to, tol);
// TODO handle error (length != sent) for ??? and (sent < 0) for local error
std::cout << "ip: send " << sent << "/" << length << "bytes to " << ip4_inet_ntop(dst.address)<< ':' << dst.port << std::endl;
//usleep(100000);
return (int)sent;
}
int ip4_socket_recv(Socket fd, UInt8 *dst, int maxlength)
{
ssize_t recved = recv(fd, dst, maxlength, 0);
// TODO handle error if(recvlength < 0)
std::cout << "ip: recv " << recved << "bytes" << std::endl;
return recved;
}
int ip4_socket_recv(Socket fd, UInt8 *dst, int maxlength, IPv4 &src)
{
struct sockaddr_in from;
socklen_t froml = sizeof(from);
memset(&from, 0, froml);
ssize_t recvlength = recvfrom(fd, dst, maxlength, 0, (struct sockaddr *)&from, &froml);
src.port = ntoh16(from.sin_port);
src.address = ntoh32(from.sin_addr.s_addr);
// TODO handle error if(recvlength < 0)
std::cout << "ip: recv " << recvlength << "bytes from " << ip4_inet_ntop(src.address)<< ':' << src.port << std::endl;
return recvlength;
}
bool ip4_socket_get_local_address(Socket fd, IPv4 &ip)
{
struct sockaddr_in addr_in;
socklen_t len = sizeof(addr_in);
if(getsockname(fd, (struct sockaddr *)&addr_in, &len) != -1) {
ip.port = ntoh16(addr_in.sin_port);
ip.address = ntoh32(addr_in.sin_addr.s_addr);
return true;
}
return false;
}
#ifndef _NETWORKUTILS_H_
#define _NETWORKUTILS_H_
#include <cstring>
#include <sstream>
#include <unistd.h>
#include <arpa/inet.h>
#define ERROR_SOCKET_CREATE 10
#define ERROR_SOCKET_BIND 11
#define ERROR_SOCKET_CONNECT 12
#define ERROR_SOCKET_LISTEN 13
#define ERROR_SOCKET_RECV 14
#ifdef WIN32
typedef SOCKET Socket;
typedef int socklen_t;
#else
typedef int Socket;
#endif
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef unsigned long long UInt64;
typedef struct {unsigned char bytes[16];} UInt128;
typedef struct {UInt32 address; UInt16 port;} IPv4;
// host to network (and network to host) order, Reference RFC 791
#define hton64 ntoh64
#define hton32 htonl
#define ntoh32 ntohl
#define hton16 htons
#define ntoh16 ntohs
#if BYTE_ORDER == BIG_ENDIAN
inline UInt64 ntoh64(UInt64 n) {return n;}
inline double ntoh64(double n) {return n;}
#else
inline UInt64 ntoh64(UInt64 n) {
union
{
UInt64 d;
UInt8 b[8];
}in, out;
in.d = n;
out.b[0] = in.b[7];
out.b[1] = in.b[6];
out.b[2] = in.b[5];
out.b[3] = in.b[4];
out.b[4] = in.b[3];
out.b[5] = in.b[2];
out.b[6] = in.b[1];
out.b[7] = in.b[0];
return out.d;
}
inline double ntoh64(double n) {
union
{
double d;
UInt8 b[8];
}in, out;
in.d = n;
out.b[0] = in.b[7];
out.b[1] = in.b[6];
out.b[2] = in.b[5];
out.b[3] = in.b[4];
out.b[4] = in.b[3];
out.b[5] = in.b[2];
out.b[6] = in.b[1];
out.b[7] = in.b[0];
return out.d;
}
#endif
inline UInt8 *encode(UInt8 *dst, UInt8 data) {memcpy(dst, reinterpret_cast<void*>(&data), sizeof(UInt8));return dst+ sizeof(UInt8);}
inline UInt8 *encode(UInt8 *dst, UInt16 data) {data = hton16(data);memcpy(dst, reinterpret_cast<void*>(&data), sizeof(UInt16));return dst+ sizeof(UInt16);}
inline UInt8 *encode(UInt8 *dst, UInt32 data) {data = hton32(data);memcpy(dst, reinterpret_cast<void*>(&data), sizeof(UInt32));return dst+ sizeof(UInt32);}
inline UInt8 *encode(UInt8 *dst, UInt64 data) {data = hton64(data);memcpy(dst, reinterpret_cast<void*>(&data), sizeof(UInt64));return dst+ sizeof(UInt64);}
inline UInt8 *encode(UInt8 *dst, UInt8 *data, unsigned int length) {memcpy(dst, reinterpret_cast<void*>(data), length);return dst+ length;}
inline UInt8 *encode(UInt8 *dst, double data) {data = hton64(data);memcpy(dst, reinterpret_cast<void*>(&data), sizeof(double));return dst+ sizeof(double);}
inline UInt8 *parse(UInt8 *src, UInt8 &data) {memcpy(reinterpret_cast<void*>(&data), src, sizeof(UInt8)); return src+ sizeof(UInt8);}
inline UInt8 *parse(UInt8 *src, UInt16 &data) {memcpy(reinterpret_cast<void*>(&data), src, sizeof(UInt16));data = ntoh16(data);return src+ sizeof(UInt16);}
inline UInt8 *parse(UInt8 *src, UInt32 &data) {memcpy(reinterpret_cast<void*>(&data), src, sizeof(UInt32));data = ntoh32(data);return src+ sizeof(UInt32);}
inline UInt8 *parse(UInt8 *src, UInt64 &data) {memcpy(reinterpret_cast<void*>(&data), src, sizeof(UInt64));data = ntoh64(data);return src+ sizeof(UInt64);}
inline UInt8 *parse(UInt8 *src, UInt8 *data, UInt16 length) {memcpy(reinterpret_cast<void*>(data), src, length);return src+length;}
inline UInt8 *parse(UInt8 *src, double &data) {memcpy(reinterpret_cast<void*>(&data), src, sizeof(double));data = ntoh64(data);return src+ sizeof(double);}
inline UInt8 *parse(UInt8 *src, std::string &data, UInt16 length) {data.assign((char *)src, length-1); return src+length;}
inline UInt8 *parse(UInt8 *src, std::string &data, char limiter) {UInt16 len = strchr((char *)src, limiter)-(char*)src+1; return parse(src, data, len);}
inline bool ip4_is_loopback(const unsigned int ip) { // Reference RFC 1122
return (unsigned int)(ip & 0xFF000000) == (unsigned int)0x7F000000; // 127.0.0.0/8
}
inline bool ip4_is_private(const unsigned int ip) { // Refercence RFC 1918
return (unsigned int)(ip & 0xFFFF0000) == (unsigned int)0xC0A80000 || // 192.168.0.0/16
(unsigned int)(ip & 0xFFF00000) == (unsigned int)0xAC100000 || // 172.16.0.0/12
(unsigned int)(ip & 0xFF000000) == (unsigned int)0x0A000000; // 10.0.0.0/8
}
UInt32 ip4_inet_pton(const char *);
UInt32 ip4_inet_resolve(const char *hostname);
UInt32 ip4_default_iface();
inline std::string ip4_inet_ntop(UInt32 address) {
std::ostringstream oss;
oss << ((address >> 24) & 0xFF) << '.'
<< ((address >> 16) & 0xFF) << '.'
<< ((address >> 8) & 0xFF) << '.'
<< (address & 0xFF);
return oss.str();
}
void ip4_socket_ip(Socket fd, IPv4 &ip);
Socket ip4_socket(IPv4 ip, int socketType);
int ip4_socket_send(Socket fd, UInt8 *src, int length);
int ip4_socket_send(Socket fd, UInt8 *src, int length, IPv4 dst);
int ip4_socket_recv(Socket fd, UInt8 *dst, int maxlength, IPv4 &src);
int ip4_socket_recv(Socket fd, UInt8 *dst, int maxlength);
inline void ip4_socket_listen(Socket fd, int maxconnection=1024)
{
if(-1 == listen(fd, maxconnection)) throw ERROR_SOCKET_LISTEN;
}
inline Socket ip4_socket_accept(Socket fd, IPv4 &ip)
{
Socket cli;
struct sockaddr_in addr;
unsigned int addrl = sizeof(addr);
cli = accept(fd, (struct sockaddr*)&addr, &addrl);
ip.address = ntoh32(addr.sin_addr.s_addr);
ip.port = ntoh16(addr.sin_port);
return cli;
}
inline int ip4_socket_connect(Socket fd, IPv4 &ip)
{
struct sockaddr_in addr;
unsigned int addrl = sizeof(addr);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = hton32(ip.address);
addr.sin_port = hton16(ip.port);
return connect(fd, (struct sockaddr*)&addr, addrl);
}
bool ip4_socket_get_local_address(Socket fd, IPv4 &ip);
void ip4_socket_timeout(Socket d, long tos, long tous=0);
inline void ip4_socket_reuse_address(Socket fd, bool reuse=true) {setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse);}
inline void ip4_socket_close(Socket fd) {/*if(-1 == */close(fd);}
#endif
#include <iostream>
#include "OnelabServer.h"
#include "OnelabNetworkClient.h"
#include "NetworkUtils.h"
OnelabServer *OnelabServer::_server = 0;
void usage()
{
//TODO std::cout << std::endl;
}
int server(unsigned short port=0)
{
OnelabServer::instance(0, port);
OnelabServer::instance()->Run();
}
int main(int argc, char **argv)
{
bool isServer = false;
unsigned int ip = 0;
unsigned short port = 0;
for(int arg=1; arg<argc; arg++) {
if(strcmp(argv[arg], "-l") == 0 || strcmp(argv[arg], "--listen") == 0)
isServer = true;
else if(strcmp(argv[arg], "-p") == 0 || strcmp(argv[arg], "--port") == 0) {
if(++arg >= argc) {
usage();
return 1;
}
port = atoi(argv[arg]);
}
else if(strcmp(argv[arg], "-i") == 0 || strcmp(argv[arg], "--ip") == 0) {
if(++arg >= argc) {
usage();
return 1;
}
ip = ip4_inet_pton(argv[arg]);
}
else {
usage();
return 1;
}
}
try {
if(isServer && port != 0)
server(port);
else {
usage();
return -1;
}
}
catch(int &e) {
if(e == ERROR_SOCKET_CREATE || e == ERROR_SOCKET_BIND || e == ERROR_SOCKET_CONNECT || e == ERROR_SOCKET_LISTEN || e == ERROR_SOCKET_RECV)
std::cerr << "UDT fail: " << UDT::getlasterror().getErrorMessage() << std::endl;
std::cerr << "Fail with code " << e << std::endl;
return e;
}
catch(const char*e) {
std::cout << e << std::endl;
return 1;
}
return 0;
}
#include <cstring>
#include <iostream>
#include "OnelabAttributes.h"
UInt8 *OnelabAttrStart::encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, (UInt8 *)_name.c_str(), _name.size());
return dst;
}
UInt8 *OnelabAttrStart::parseAttribute(UInt8 *src, UInt32 length)
{
_name.assign((char *)src, (int)length);
return src+length;
}
void OnelabAttrStart::showAttribute()
{
std::cout << "\033[1m" << "Attribute start:"<< getAttributeType() << "\033[0m"<< std::endl
<< "name: " << _name << std::endl;
}
UInt8 *OnelabAttrParameterQuery::encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, _ptype);
dst = encode(dst, (UInt8 *)_pname.c_str(), _pname.size());
return dst;
}
UInt8 *OnelabAttrParameterQuery::parseAttribute(UInt8 *src, UInt32 length)
{
if(length < 1) throw ERROR_INVALID_ATTRIBUTE_SIZE;
src = parse(src, _ptype);
_pname.assign((char *)src, (int)(length-1));
return src+length;
}
void OnelabAttrParameterQuery::showAttribute()
{
std::cout << "\033[1m" << "Attribute parameter query:"<< getAttributeType() << "\033[0m"<< std::endl
<< "type: " << this->_ptype << std::endl
<< "name: " << this->_pname << std::endl;
}
UInt8 *OnelabAttrMessage::encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, _level);
dst = encode(dst, _message, _messageLength);
return dst;
}
UInt8 *OnelabAttrMessage::parseAttribute(UInt8 *src, UInt32 length)
{
if(length < 1) throw ERROR_INVALID_ATTRIBUTE_SIZE;
src = parse(src, _level);
_messageLength = length-1;
if(_message != NULL) free(_message);
_message = (UInt8 *)malloc(_messageLength);
src = parse(src, _message, _messageLength);
return src;
}
void OnelabAttrMessage::showAttribute()
{
std::cout << "Attribute message:" << std::endl
<< "Level: " << _level << std::endl
<< "Message: " << _message << std::endl;
}
UInt8 *OnelabAttrAction::encodeAttibute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, (UInt8 *)_client.c_str(), _client.size()+1);
dst = encode(dst, (UInt8 *)_action.c_str(), _action.size());
return dst;
}
UInt8 *OnelabAttrAction::parseAttibute(UInt8 *src, UInt32 length)
{
_client.assign((char *)src);
src += _client.size()+1;
_action.assign((char *)src, length-_client.size()-1);
src += _action.size();
return src;
}
UInt8 *OnelabAttrFileQuery::encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, (UInt8 *)_name, _length);
dst = encode(dst, (UInt8 *)_client.c_str(), _client.length()+1);
return dst;
}
UInt8 *OnelabAttrFileQuery::parseAttribute(UInt8 *src, UInt32 length)
{
if(_name != NULL) free(_name);
_length = length;
_name = (char *)malloc(_length+1);
src = parse(src, (UInt8 *)_name, _length);
_name[_length] = '\0';
return src;
}
void OnelabAttrFileQuery::setFilename(const std::string name)
{
if(_name != NULL) free(_name);
_length = name.size();
_name = strndup(name.c_str(), _length);
}
UInt8 *OnelabAttrFile::encodeAttribute(UInt8 *dst)
{
dst = encode(dst, getAttributeType());
dst = encode(dst, getAttributeLength());
dst = encode(dst, _filelength);
dst = encode(dst, (UInt8 *)_name, strlen(_name)+1);
return dst;
}
UInt8 *OnelabAttrFile::parseAttribute(UInt8 *src, UInt32 length)
{
if(length < 5) throw ERROR_INVALID_ATTRIBUTE_SIZE;
if(_name != NULL) free(_name);
src = parse(src, _filelength);
_name = strndup((char *)src, length-4);
return src+length-4;
}
#ifndef _ONELAB_ATTRIBUTES_H
#define _ONELAB_ATTRIBUTES_H
#define SESSION_SIZE 32
#define ERROR_BUFFER_TOO_SMALL 50
#define ERROR_INVALID_ATTRIBUTE_SIZE 51
#include <stdlib.h>
#include <stdio.h>
#include "NetworkUtils.h"
class OnelabAttr
{
protected:
// Header :
//UInt16 _type;
//UInt16 _size;
bool _stored; // is the attribute in the database ?
public:
OnelabAttr() {}
virtual ~OnelabAttr(){}
virtual UInt8 *encodeAttribute(UInt8 *dst) = 0;
virtual UInt8 *parseAttribute(UInt8 *src, UInt32 length) = 0;
virtual void showAttribute() = 0;
virtual inline UInt16 getAttributeType() const = 0;
virtual inline UInt16 getAttributeLength() const = 0;
bool isInDatabase() const {return this->_stored;}
void isInDatabase(bool isInDb) {this->_stored = isInDb;}
// attributes type to connect peers
static const UInt16 Peer = 0x01;
static const UInt16 Server = 0x02;
static const UInt16 Session = 0x03;
// attributes type for onelab
static const UInt16 Start = 0x04;
static const UInt16 Parameter = 0x05;
static const UInt16 Number = 0x06;
static const UInt16 String = 0x07;
static const UInt16 Region = 0x08;
static const UInt16 Function = 0x09;
// other message for onelab
static const UInt16 Message = 0x0A;
};
class OnelabAttrStart : public OnelabAttr
{
private:
std::string _name;
public:
OnelabAttrStart() {}
OnelabAttrStart(const std::string name) {_name = name;}
~OnelabAttrStart(){}
UInt8 *encodeAttribute(UInt8 *dst);
UInt8 *parseAttribute(UInt8 *src, UInt32 length);
void showAttribute();
static UInt16 attributeType() {return 0x04;}
inline UInt16 getAttributeType() const {return this->attributeType();}
inline UInt16 getAttributeLength() const {return _name.size();}
std::string name(){return _name;}
};
class OnelabAttrParameterQuery : public OnelabAttr
{
private:
UInt8 _ptype;
std::string _pname;
public:
OnelabAttrParameterQuery() {}
OnelabAttrParameterQuery(const std::string name, UInt8 parameter) {_ptype = parameter; _pname = name;}
~OnelabAttrParameterQuery() {}
UInt8 *encodeAttribute(UInt8 *buff);
UInt8 *parseAttribute(UInt8 *buff, UInt32 length);
void showAttribute();
static UInt16 attributeType() {return 0x05;}
inline UInt16 getAttributeType() const {return this->attributeType();}
inline UInt16 getAttributeLength() const {return 1+_pname.size();}
inline UInt8 paramType() const {return this->_ptype;}
std::string getName() const {return this->_pname;}
};
class OnelabAttrMessage : public OnelabAttr
{
private:
UInt8 _level;
UInt8 *_message;
UInt16 _messageLength;
public:
OnelabAttrMessage() {this->_message = NULL; this->_level = 0;}
OnelabAttrMessage(std::string message, const int level=OnelabAttrMessage::Debug) {setMessage(message, level);}
~OnelabAttrMessage(){if(_message != NULL) free(_message);};
UInt8 *encodeAttribute(UInt8 *dst);
UInt8 *parseAttribute(UInt8 *src, UInt32 length);
void showAttribute();
static UInt16 attributeType() {return 0x0A;}
inline UInt16 getAttributeType() const {return this->attributeType();}
inline UInt16 getAttributeLength() const {return 1+_messageLength;}
void setMessage(std::string message, const int level=OnelabAttrMessage::Debug) {
_messageLength = message.size();
if(_messageLength == 0) return;
_level = level;
if(_message != NULL) free(_message);
_message = (UInt8 *)strndup(message.c_str(), _messageLength);
}
const char *getMessage() {return (char *)_message;}
int getLevel() {return _level;}
typedef enum {
Debug=99,
Info=5,
Warning=3,
Error=2,
Fatal=1
} OnelabMessageLvl;
};
class OnelabAttrAction : public OnelabAttr
{
private:
std::string _action;
std::string _client;
public:
OnelabAttrAction() : _action(""), _client("") {}
OnelabAttrAction(std::string action, std::string client) : _action(action), _client(client) {}
~OnelabAttrAction() {}
static UInt16 attributeType() {return 0x10;}
inline UInt16 getAttibuteType() const {return attributeType();}
inline UInt16 getAttibuteLength() const {return _client.size()+1+_action.size();}
UInt8 *encodeAttibute(UInt8 *dst);
UInt8 *parseAttibute(UInt8 *src, UInt32 lenght);
void showAttribute() {}
void setAction(std::string action) {_action = action;}
void setClient(std::string client) {_client = client;}
std::string getAction() {return _action;}
std::string getClient() {return _client;}
};
class OnelabAttrFileQuery : public OnelabAttr
{
private:
char *_name;
UInt16 _length;
std::string _client;
public:
OnelabAttrFileQuery() : _name(NULL), _length(0){}
OnelabAttrFileQuery(const std::string filename) : _name(NULL), _length(0) {setFilename(filename);}
~OnelabAttrFileQuery() {if(_name != NULL) free(_name);}
UInt8 *encodeAttribute(UInt8 *dst);
UInt8 *parseAttribute(UInt8 *src, UInt32 length);
void showAttribute(){}
static UInt16 attributeType() {return 0x0B;}
inline UInt16 getAttributeType() const {return attributeType();}
inline UInt16 getAttributeLength() const {return _length+_client.length()+1;}
void setFilename(std::string name);
void setClient(std::string client) {_client = client;}
const char *getFilename() {return _name;}
};
class OnelabAttrFile : public OnelabAttr
{
private:
char *_name;
FILE *_fd;
UInt32 _filelength;
public:
OnelabAttrFile() : _name(NULL), _filelength(0) {}
OnelabAttrFile(const std::string filename, FILE *fd) {setFile(filename, fd);}
~OnelabAttrFile() {if(_name != NULL) free(_name);}
UInt8 *encodeAttribute(UInt8 *dst);
UInt8 *parseAttribute(UInt8 *src, UInt32 length);
void showAttribute(){}
static UInt16 attributeType() {return 0x0C;}
inline UInt16 getAttributeType() const {return attributeType();}
inline UInt16 getAttributeLength() const {return 4+strlen(_name);}
void setFile(std::string name, FILE *fd)
{
if(_name != NULL) free(_name);
_name = strndup(name.c_str(), name.size()+1);
_fd = fd;
long pos = ftell(fd); fseek(fd, 0, SEEK_END);
_filelength = (UInt32)ftell(fd); fseek(fd, pos, SEEK_SET);
}
const char *getFilename() {return _name;}
unsigned int getFileSize() {return _filelength;}
};
#endif
#include <signal.h>
#include <stdio.h>
#include "GmshMessage.h"
#include "OnelabServer.h"
#include "GmshNetworkClient.h"
#include "GmshLocalClient.h"
#include "onelabUtils.h"
#ifndef WIN32
void *OnelabDatabase_listen(void *arg);
void *OnelabDatabase_server(void *arg);
#else
DWORD WINAPI OnelabDatabase_listen(LPVOID arg);
DWORD WINAPI OnelabDatabase_server(void *arg);
#endif
OnelabServer *OnelabServer::_server = NULL;
// OnelabDatabase is a singleton that get/set/... parameters from server/clients
class OnelabDatabase {
private:
static OnelabDatabase *_instance;
#ifndef WIN32
pthread_t _listenThread, _serverThread;
#else
HANDLER _listenThread, _serverThread;
#endif
GmshNetworkClient *_client;
GmshLocalClient *_localClient;
void _clear() {
#ifndef WIN32
// TODO send message to thread to exit the thread
//pthread_kill(_serverThread, 9);
//if(_client) pthread_kill(_listenThread, 9);
#else
// TODO
#endif
if(_client) delete _client;
if(_localClient) delete _localClient;
_client = NULL; _localClient = NULL;
}
public:
OnelabDatabase() {
_localClient = NULL; _client = NULL;
}
static OnelabDatabase *instance() {
if(!_instance) _instance = new OnelabDatabase;
return _instance;
}
GmshLocalClient *useAsClient(){
// the server is in the same memory space
_clear();
OnelabServer::instance(0x7F000001, 0);
//OnelabServer::instance(0, 0);
_localClient = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
OnelabServer::instance()->addClient(_localClient); // TODO remove from server in _clear()
#ifndef WIN32
pthread_create(&_serverThread, NULL, OnelabDatabase_server, NULL);
#else
_serverThread = CreateThread(NULL, 0, NULL, OnelabDatabase_server, 0, NULL);
#endif
return _localClient;
}
GmshNetworkClient *useAsNetworkClient(UInt32 address, UInt16 port){
// use this as a network client (take server address/port)
_clear();
_client = new GmshNetworkClient("GUI", address, port);
if(_client->connect()) {
#ifndef WIN32
pthread_create(&_listenThread, NULL, OnelabDatabase_listen, NULL);
#else
_listenThread = CreateThread(NULL, 0, NULL, OnelabDatabase_listen, 0, NULL);
#endif
return _client;
}
else
Msg::Error("Unable to connect to the server!");
return NULL;
}
int listen(UInt8 *buff, unsigned int maxlen){
if(_client) return _client->recvfrom(buff, maxlen);
return 0;
}
void sendbytes(UInt8 *buff, unsigned int len){
if(_client) _client->sendto(buff, len);
}
GmshLocalClient *useAsServer(UInt32 address, UInt16 port){
// use this as a network server (take interface/port to listen to)
_clear();
OnelabServer::instance(address, port);
_localClient = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
#ifndef WIN32
pthread_create(&_serverThread, NULL, OnelabDatabase_server, NULL);
#else
_serverThread = CreateThread(NULL, 0, NULL, OnelabDatabase_server, 0, NULL);
#endif
return _localClient;
}
template <class T> bool set(const T &p, bool update=true) {
if(_client) return _client->set(p, update);
//if(_localClient) return _localClient->set(p);
return OnelabServer::instance()->set(p, "");
}
template <class T> bool set(const T &p, const std::string &client) {
return OnelabServer::instance()->set(p, client);
}
template <class T> bool get(std::vector<T> &ps, const std::string &name="", const std::string &client="") {
if(_client) return _client->get(ps, name);
//if(_localClient) _localClient->get(ps, name);
return OnelabServer::instance()->get(ps, name, client);
}
bool fromFile(FILE *fp, const std::string &client="")
{
if(_client) return _client->fromFile(fp, client);
return OnelabServer::instance()->fromFile(fp, client);
}
void onelab_cb(std::string action) {
if(_client) return; // TODO send action to the server
if(action == "stop"){
//FlGui::instance()->onelab->stop(true);
if(_client) _client->stop();
}
//TODO if(action == "compute") initializeLoops();
do {
for (std::vector<OnelabLocalNetworkClient>::iterator it = OnelabServer::instance()->getClients().begin() ; it != OnelabServer::instance()->getClients().end(); ++it)
{
onelab::string o((*it).getName() + "/Action", action);
o.setVisible(false);
o.setNeverChanged(true);
this->set(o);
(*it).run();
}
} while(action == "compute" &&
//TODO incrementLoops() &&
!false/*TODO onelab->stop*/);
}
};
#ifndef WIN32
void *OnelabDatabase_listen(void *arg)
#else
DWORD WINAPI OnelabDatabase_listen(LPVOID arg)
#endif
{
OnelabProtocol msg(-1);
UInt8 buff[1024];
int recvlen = 0;
while(1) {
recvlen = OnelabDatabase::instance()->listen(buff, 1024);
if(recvlen == 1 && buff[0] == 'S')
break;
msg.parseMsg(buff, recvlen);
msg.showMsg();
switch(msg.msgType()) {
case OnelabProtocol::OnelabStop:
return NULL;
case OnelabProtocol::OnelabMessage:
Msg::Info("Message from onelab"); // TODO
break;
case OnelabProtocol::OnelabResponse:
case OnelabProtocol::OnelabUpdate:
for(std::vector<OnelabAttr *>::iterator it = msg.attrs.begin() ; it != msg.attrs.end(); ++it) {
if((*it)->getAttributeType() == OnelabAttr::Number) {
onelab::number *attr = (onelab::number *)*it;
OnelabDatabase::instance()->set(*attr, false);
}
else if((*it)->getAttributeType() == OnelabAttr::String) {
onelab::string *attr = (onelab::string *)*it;
OnelabDatabase::instance()->set(*attr, false);
}
else if((*it)->getAttributeType() == OnelabAttr::Region) {
onelab::region *attr = (onelab::region *)*it;
OnelabDatabase::instance()->set(*attr, false);
}
else if((*it)->getAttributeType() == OnelabAttr::Function) {
onelab::function *attr = (onelab::function *)*it;
OnelabDatabase::instance()->set(*attr, false);
}
else if((*it)->getAttributeType() == OnelabAttrFileQuery::attributeType()) {
OnelabAttrFileQuery *attr = (OnelabAttrFileQuery *)*it;
const char *filename = attr->getFilename();
// FIXME path/filename ?
std::clog << "try to open " << filename << " for reading" << std::endl;
FILE *fp = fopen(filename, "rb");
if(fp != NULL){
OnelabProtocol rep(OnelabProtocol::OnelabUpdate);
rep.attrs.push_back(new OnelabAttrFile(std::string(filename), fp));
recvlen = rep.encodeMsg(buff, 1024);
OnelabDatabase::instance()->sendbytes(buff, recvlen);
while((recvlen = fread(buff, 1, 1024, fp)) > 0)
OnelabDatabase::instance()->sendbytes(buff, recvlen);
}
}
else if((*it)->getAttributeType() == OnelabAttrFile::attributeType()) {
OnelabAttrFile *attr = (OnelabAttrFile *)*it;
const char *filename = attr->getFilename();
std::clog << "try to open " << filename << " for writing" << std::endl;
FILE *fp = fopen(filename, "wb");
if(fp != NULL){
unsigned int filesize = ((OnelabAttrFile *)attr)->getFileSize();
unsigned int downloadsize = 0;
while(downloadsize < filesize) {
recvlen = OnelabDatabase::instance()->listen(buff, 1024);
downloadsize += recvlen;
fwrite(buff, 1, recvlen, fp);
}
}
}
else if((*it)->getAttributeType() == OnelabAttrAction::attributeType()) {
OnelabAttrAction *attr = (OnelabAttrAction *)*it;
OnelabLocalNetworkClient *target = OnelabServer::instance()->getClient(attr->getClient());
target->sendto(buff, recvlen);
}
}
break;
}
}
}
#ifndef WIN32
void *OnelabDatabase_server(void *arg)
#else
DWORD WINAPI OnelabDatabase_server(LPVOID arg)
#endif
{
OnelabServer::instance()->Run();
}
#ifndef _ONELABLOCALCLIENT_H_
#define _ONELABLOCALCLIENT_H_
#include "VirtualClient.h"
/**
@class OnelabLocalClient
@brief This class is used for client in the same memory space as the server.
*/
class OnelabLocalClient : public VirtualClient
{
public:
OnelabLocalClient(std::string name, onelab::parameterSpace *parameterSpace)
: VirtualClient(name, parameterSpace){
}
template <class T> bool set(const T &p){
return _parameterSpace->set(p, this->_name);
}
template <class T> bool get(std::vector<T> &ps, const std::string &name=""){
return _parameterSpace->get(ps, name, this->_name);
}
virtual ~OnelabLocalClient(){}
void onNewParameter(onelab::parameter *p){}
void onUpdateParameter(onelab::parameter *p){}
void onRemoveParameter(onelab::parameter *p){}
void run() {}
void stop() {}
};
#endif
#include "OnelabLocalNetworkClient.h"
#include "OnelabProtocol.h"
//#ifdef HAVE_UDT
OnelabLocalNetworkClient::OnelabLocalNetworkClient(std::string name, UDTSOCKET fd, unsigned int ip, unsigned short port, bool UDT)
{
_name = name;
_fds = 0;
_fdu = fd;
_ip.address = ip;
_ip.port = port;
}
//#endif
OnelabLocalNetworkClient::OnelabLocalNetworkClient(std::string name, Socket fd, unsigned int ip, unsigned short port)
{
_name = name;
_fdu = 0;
_fds = fd;
_ip.address = ip;
_ip.port = port;
}
void OnelabLocalNetworkClient::sendto(UInt8 *buff, unsigned int len)
{
//#ifdef HAVE_UDT
if(_fds) ip4_socket_send(_fds, buff, len, _ip);
else udt_socket_send(_fdu, buff, len);
//#else
// return ip4_socket_send(_fds, buff, maxlen);
//#endif
}
int OnelabLocalNetworkClient::recvfrom(UInt8 *buff, unsigned int maxlen)
{
IPv4 unused;
//#ifdef HAVE_UDT
if(_fds) return ip4_socket_recv(_fds, buff, maxlen, unused);
return udt_socket_recv(_fdu, buff, maxlen);
//#else
// return ip4_socket_recv(_fds, buff, maxlen);
//#endif
}
void OnelabLocalNetworkClient::updateParameter(onelab::parameter *p)
{
OnelabProtocol msg(OnelabProtocol::OnelabUpdate);
msg.attrs.push_back(p);
UInt8 buff[1024];
unsigned int recvlen = msg.encodeMsg(buff, 1024);
sendto(buff, recvlen);
}
#ifndef _ONELABLOCALNETWORKCLIENT_H_
#define _ONELABLOCALNETWORKCLIENT_H_
#include <string>
#include "onelab.h"
//#ifdef HAVE_UDT
#include "UdtUtils.h"
//#else
//#include "NetworkUtils.h"
//#endif
class OnelabLocalNetworkClient
{
private:
Socket _fds;
//#ifdef HAVE_UDT
UDTSOCKET _fdu;
//#endif
IPv4 _ip;
std::string _name;
public:
//#ifdef HAVE_UDT
OnelabLocalNetworkClient(std::string name, UDTSOCKET fd, unsigned int ip, unsigned short port, bool UDT);
//#endif
OnelabLocalNetworkClient(std::string name, Socket fd, unsigned int ip, unsigned short port);
void sendto(UInt8 *buff, unsigned int len);
int recvfrom(UInt8 *buff, unsigned int maxlen);
UDTSOCKET getSSocket() {return _fds;}
UDTSOCKET getUSocket() {return _fdu;}
virtual ~OnelabLocalNetworkClient(){}
std::string getName() {return _name;}
void updateParameter(onelab::parameter *);
unsigned int getIp() {return _ip.address;}
unsigned short getPort() {return _ip.port;}
void run() {}
void stop() {}
};
#endif
#include <iostream>
#include "OnelabNetworkClient.h"
#ifdef HAVE_UDT
OnelabNetworkClient::OnelabNetworkClient(std::string name, bool UDT)
: VirtualClient(name)
{
_fds = 0;
_fdu = 0;
_ip.address = 0;
_ip.port = 0;
_connected = false;
IPv4 local;
local.address = 0;// FIXME ip4_default_iface();
local.port = 0;
UDT::startup();
if(UDT) _fdu = udt_socket(local, SOCK_STREAM);
else _fds = ip4_socket(local, SOCK_STREAM);
}
OnelabNetworkClient::OnelabNetworkClient(std::string name, unsigned int ip, unsigned short port, bool UDT)
: VirtualClient(name)
{
_fds = 0;
_fdu = 0;
_ip.address = ip;
_ip.port = port;
_connected = false;
IPv4 local;
local.address = 0;//ip4_default_iface();
local.port = 0;
UDT::startup();
if(UDT) _fdu = udt_socket(local, SOCK_STREAM);
else _fds = ip4_socket(local, SOCK_STREAM);
}
#else
OnelabNetworkClient::OnelabNetworkClient(std::string name)
: VirtualClient(name)
{
_ip.address = 0;
_ip.port = 0;
_connected = false;
IPv4 local;
local.address = 0;// FIXME ip4_default_iface();
local.port = 0;
_fds = ip4_socket(local, SOCK_STREAM);
}
OnelabNetworkClient::OnelabNetworkClient(std::string name, unsigned int ip, unsigned short port)
: VirtualClient(name)
{
_ip.address = ip;
_ip.port = port;
_connected = false;
IPv4 local;
local.address = 0;//ip4_default_iface();
local.port = 0;
_fds = ip4_socket(local, SOCK_STREAM);
}
#endif
void OnelabNetworkClient::sendto(UInt8 *buff, UInt16 len)
{
#ifndef HAVE_UDT
ip4_socket_send(_fds, buff, len, _ip);
#else
if(_fds) ip4_socket_send(_fds, buff, len);
else udt_socket_send(_fdu, buff, len);
#endif
}
int OnelabNetworkClient::recvfrom(UInt8 *buff, UInt16 maxlen)
{
IPv4 unused;
#ifndef HAVE_UDT
return ip4_socket_recv(_fds, buff, maxlen, unused); // FIXME check unused == _ip ?
#else
if(_fds) return ip4_socket_recv(_fds, buff, maxlen); // FIXME check unused == _ip ?
return udt_socket_recv(_fdu, buff, maxlen);
#endif
}
void OnelabNetworkClient::recvfrom(OnelabProtocol &msg)
{
UInt16 bufflen = 1024, recvlen = 0;
UInt8 buff[1024];
recvlen = this->recvfrom(buff, bufflen);
msg.parseMsg(buff, recvlen);
}
bool OnelabNetworkClient::connect()
{
UInt16 bufflen = 1024;
int recvlen = 0;
UInt8 buff[1024];
OnelabProtocol msg(OnelabProtocol::OnelabStart);
if(_connected) return true;
#ifdef HAVE_UDT
if(_fds) ip4_socket_connect(_fds, _ip);
else udt_socket_connect(_fdu, _ip);
#else
ip4_socket_connect(_fds, _ip);
#endif
msg.attrs.push_back(new OnelabAttrStart(_name));
recvlen = msg.encodeMsg(buff, bufflen);
sendto(buff, recvlen);
#ifdef HAVE_UDT
udt_socket_timeout(_fdu, 3);
#endif
ip4_socket_timeout(_fds, 3);
recvlen = recvfrom(buff, bufflen);
#ifdef HAVE_UDT
udt_socket_timeout(_fdu, -1);
#endif
ip4_socket_timeout(_fds, 0);
if(recvlen <= 0) return false;
msg.parseMsg(buff, recvlen);
if(recvlen > 0 && msg.msgType() == OnelabProtocol::OnelabStart) _connected = true;
return _connected;
}
void OnelabNetworkClient::disconnect()
{
// Send a message to the server to say the client stop (the server have to reply)
UInt16 bufflen = 1024, recvlen = 0;
UInt8 buff[1024];
OnelabProtocol msg(OnelabProtocol::OnelabStop);
if(!_connected) return;
recvlen = msg.encodeMsg(buff, bufflen);
this->sendto(buff, recvlen);
_connected = false;
}
void OnelabNetworkClient::request(OnelabProtocol &msg)
{
UInt16 bufflen = 1024, recvlen = 0;
UInt8 buff[1024];
recvlen = msg.encodeMsg(buff, bufflen);
this->sendto(buff, recvlen);
}
void OnelabNetworkClient::requestParameters()
{
OnelabProtocol msg(OnelabProtocol::OnelabRequest);
this->request(msg);
}
#ifndef _ONELABCLIENT_H_
#define _ONELABCLIENT_H_
#include <vector>
#include "NetworkUtils.h"
#include "VirtualClient.h"
#include "OnelabLocalNetworkClient.h"
#include "OnelabProtocol.h"
class OnelabNetworkClient : VirtualClient
{
private:
#ifdef HAVE_UDT
UDTSOCKET _fdu;
#endif
Socket _fds;
bool _connected;
IPv4 _ip;
void request(OnelabProtocol &msg);
template <class T> bool requestParameter(std::vector<T> &ps, const std::string &name=""){
OnelabProtocol msg(OnelabProtocol::OnelabRequest);
msg.attrs.push_back(new OnelabAttrParameterQuery(name.c_str(), T::attributeType()));
this->request(msg);
return true;
}
void requestParameters(); // request all parameter for this client
public:
#ifdef HAVE_UDT
OnelabNetworkClient(std::string name, bool UDT=false);
OnelabNetworkClient(std::string name, unsigned int ip, unsigned short port, bool UDT=false);
virtual ~OnelabNetworkClient() {UDT::cleanup();}
#else
OnelabNetworkClient(std::string name);
OnelabNetworkClient(std::string name, unsigned int ip, unsigned short port);
virtual ~OnelabNetworkClient() {}
#endif
template <class T> bool existInDatabase(const T p) {
std::vector<T> ps;
_parameterSpace->get(ps, p.getName(), _name);
return ps.size() > 0;
}
template <class T> bool set(const T &p, bool update=true){
bool isInDatabase = existInDatabase(p);
if(_parameterSpace->set(p, _name)) {
T *pp;
_parameterSpace->getPtr(&pp, p.getName(), _name);
if(update) {
OnelabProtocol msg(OnelabProtocol::OnelabUpdate);
msg.attrs.push_back(pp);
request(msg);
}
if(!isInDatabase) onNewParameter(pp);
else onUpdateParameter(pp);
return true;
}
return false;
}
template <class T> bool get(std::vector<T> &ps, const std::string &name=""){
if(_parameterSpace->get(ps, name, this->_name) && ps.size() == 0)
return requestParameter(ps, name);
return true;
}
FILE *openFile(const std::string name, const char *mode="rb")
{
FILE *fp = fopen(name.c_str(), mode);
if(fp == NULL){ // File is not local, download it
OnelabProtocol msg(OnelabProtocol::OnelabUpdate);
msg.attrs.push_back(new OnelabAttrFileQuery(name));
request(msg);
// TODO
}
return fp;
}
bool fromChar(const std::vector<std::string> &msg, const std::string &client="")
{
onelab::parameter *parameters[4];
unsigned int pi = 0;
for(unsigned int i = 0; i < msg.size(); i++){
std::string version, type, name;
onelab::parameter::getInfoFromChar(msg[i], version, type, name);
if(onelab::parameter::version() != version) return false;
if(type == "number"){
onelab::number p; p.fromChar(msg[i]); set(p, false);
_parameterSpace->getPtr((onelab::number **)&parameters[pi++], p.getName());
}
else if(type == "string"){
onelab::string p; p.fromChar(msg[i]); set(p, false);
_parameterSpace->getPtr((onelab::string **)&parameters[pi++], p.getName());
}
else if(type == "region"){
onelab::region p; p.fromChar(msg[i]); set(p, false);
_parameterSpace->getPtr((onelab::region **)&parameters[pi++], p.getName());
}
else if(type == "function"){
onelab::function p; p.fromChar(msg[i]); set(p, false);
_parameterSpace->getPtr((onelab::function **)&parameters[pi++], p.getName());
}
else
return false;
if(pi == 4 || i==msg.size()-1) {
OnelabProtocol msg(OnelabProtocol::OnelabUpdate);
for(unsigned int j = 0; j < pi; j++)
msg.attrs.push_back(parameters[j]);
request(msg);
pi=0;
}
}
return true;
}
bool fromFile(FILE *fp, const std::string &client="")
{
std::vector<std::string> msg;
if(onelab::parameter::fromFile(msg, fp)) return fromChar(msg, client);
return false;
}
virtual void onNewParameter(onelab::parameter *){}
virtual void onUpdateParameter(onelab::parameter *){}
virtual void onRemoveParameter(onelab::parameter *){} // TODO call on clear
// network specific method
bool connect();
bool isConnected(){return _connected;}
void recvfrom(OnelabProtocol &msg);
int recvfrom(UInt8 *buff, UInt16 maxlen);
void sendto(UInt8 *buff, UInt16 len);
void disconnect();
void setRemoteIP(unsigned long ip){if(!_connected) _ip.address=ip;}
void setRemotePort(unsigned short port){if(!_connected) _ip.port=port;}
void run() {}
void stop() {}
};
#endif
#include <iostream>
#include "OnelabProtocol.h"
#include "onelab.h"
#include "NetworkUtils.h"
OnelabProtocol::OnelabProtocol(UInt16 type)
{
_type = type;
_size = 0;
}
void OnelabProtocol::clearAttrs()
{
for (std::vector<OnelabAttr*>::iterator it = this->attrs.begin() ; it != this->attrs.end(); ++it) {
if((*it) != NULL && !(*it)->isInDatabase()) delete *it;
}
this->attrs.clear();
}
unsigned short OnelabProtocol::encodeMsg(UInt8 *buff, UInt32 len)
{
if(len < 4) throw ERROR_BUFFER_TOO_SMALL;
UInt8 *ptr = encode(buff, (UInt8)ONELAB_VERSION);
ptr = encode(ptr, _type);
UInt8 *sizeptr = ptr;
_size = 0;
ptr = encode(sizeptr, _size);
for (std::vector<OnelabAttr*>::iterator it = this->attrs.begin() ; it != this->attrs.end(); ++it) {
UInt16 attrLen = (*it)->getAttributeLength();
if(4+_size+attrLen > len) {
// FIXME
encode(sizeptr, _size);
return (unsigned short)(ptr-buff);
// size = 0;
}
ptr = (*it)->encodeAttribute(ptr);
_size+=attrLen+4;
}
encode(sizeptr, _size);
return (unsigned short)(ptr-buff);
}
UInt32 OnelabProtocol::parseMsg(UInt8 *buff, UInt32 len)
{
this->clearAttrs();
if(len < 4) throw ERROR_BUFFER_TOO_SMALL;
UInt8 *ptr = buff;
UInt8 version = 0;
ptr = parse(ptr, version);
if(version != ONELAB_VERSION) throw ERROR_ONELAB_VERSION;
ptr = parse(ptr, _type);
ptr = parse(ptr, _size);
std::cout << "current version is " << (int)ONELAB_VERSION << ", message version is " << (int)version << "(length is " << len << ", size is "<< _size <<" )" << std::endl; // TODO send to gmsh ?
UInt8 *payload = ptr;
unsigned short parsed = 4;
unsigned short size = _size;
while(size >= 4) {
UInt16 attrType = 0;
UInt16 attrSize = 0;
ptr = parse(ptr, attrType);
ptr = parse(ptr, attrSize);
size -= 4;
std::cout << "Try to parse an attribute of type 0x" << std::hex << (UInt16)attrType << std::dec << " and size : " << attrSize << std::endl;
if(attrSize > size) throw ERROR_BUFFER_TOO_SMALL;
switch(attrType) {
case OnelabAttr::Message:
this->attrs.push_back(new OnelabAttrMessage());
((OnelabAttrMessage *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::Number:
this->attrs.push_back(new onelab::number());
((onelab::number *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::String:
this->attrs.push_back(new onelab::string());
((onelab::string *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::Region:
this->attrs.push_back(new onelab::region());
((onelab::region *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::Function:
this->attrs.push_back(new onelab::region());
((onelab::function *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::Start:
this->attrs.push_back(new OnelabAttrStart());
((onelab::string *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case OnelabAttr::Parameter:
this->attrs.push_back(new OnelabAttrParameterQuery());
((OnelabAttrParameterQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case 0x0b:
this->attrs.push_back(new OnelabAttrFileQuery());
((OnelabAttrFileQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
case 0x0c:
this->attrs.push_back(new OnelabAttrFile());
((OnelabAttrFile *)this->attrs.back())->parseAttribute(ptr, attrSize);
break;
default:
// FIXME unknown attribute
//if(attrSize != 0) throw "Size of attr must be 0!";
/*this->attrs.push_back(new OnelabAttr(attrType));
this->attrs.back()->parseAttribute(ptr, &attrSize);*/
break;
}
ptr += attrSize;
size -= attrSize;
parsed += attrSize+4;
}
// TODO the boundary of the packet is not correct, keep the last bytes in a buffer (the rest is comming)
if(parsed != len) {std::cout << "parse - size left:" << len-parsed << '-' << size << "(len is "<< len <<" and parsed is "<< parsed <<" )" << std::endl;}
return len-parsed;
}
void OnelabProtocol::showMsg()
{
std::cout << "\033[1m" << "\033[4m" << "Message type: 0x" << std::hex << (int)_type << "\033[0m" << std::endl
<< "And have " << std::dec << this->attrs.size() << " attribute(s)" << std::endl;
for (std::vector<OnelabAttr*>::iterator it = this->attrs.begin() ; it != this->attrs.end(); ++it)
(*it)->showAttribute();
std::cout << std::endl;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment