diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in index 12baab72de7d6d108633f955e0e3f84079af93c5..98118893fd231f03afefc3a7b4ae2503fd6a88d8 100644 --- a/Common/GmshConfig.h.in +++ b/Common/GmshConfig.h.in @@ -49,6 +49,7 @@ #cmakedefine HAVE_ONELAB #cmakedefine HAVE_ONELAB2 #cmakedefine HAVE_ONELAB_METAMODEL +#cmakedefine HAVE_UDT #cmakedefine HAVE_OPENGL #cmakedefine HAVE_OPTHOM #cmakedefine HAVE_OSMESA diff --git a/Common/onelab.h b/Common/onelab.h index 8cd774a8d6fd84daded221563720197176d5f8aa..2333ce219dc09a2834b1e9e28f97a8e8fb1b301f 100644 --- a/Common/onelab.h +++ b/Common/onelab.h @@ -38,10 +38,19 @@ #include <sstream> #include "GmshSocket.h" +#ifdef HAVE_ONELAB2 +#include "NetworkUtils.h" +#include "OnelabAttributes.h" +#endif + namespace onelab{ // The base parameter class. - class parameter{ +#ifdef HAVE_ONELAB2 + class parameter : public OnelabAttr{ +#else + class parameter { +#endif private: // the name of the parameter, including its '/'-separated path in the // parameter hierarchy. Parameters or subpaths can start with numbers to @@ -292,6 +301,86 @@ namespace onelab{ } 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{ @@ -412,6 +501,73 @@ namespace onelab{ } 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 @@ -476,6 +632,51 @@ namespace onelab{ _choices[i] = getNextToken(msg, 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, @@ -558,6 +759,63 @@ namespace onelab{ } 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 @@ -642,6 +900,69 @@ namespace onelab{ } 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 @@ -695,6 +1016,9 @@ namespace onelab{ } else{ T* newp = new T(p); +#ifdef HAVE_ONELAB2 + newp->isInDatabase(true); +#endif if(client.size()) newp->addClient(client, true); ps.insert(newp); } @@ -770,6 +1094,31 @@ namespace onelab{ const std::string &client=""){ return _get(ps, name, client, _regions); } bool get(std::vector<function> &ps, const std::string &name="", 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() { return (int)(_numbers.size() + _strings.size() + _regions.size() + _functions.size()); @@ -935,7 +1284,6 @@ namespace onelab{ return false; } }; - // The onelab server: a singleton that stores the parameter space and // interacts with onelab clients. class server{ diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 3909284927e03dca7900734da84211f3be175764..12c54b984712e520def2ee7260199ecf5bfdae36 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -34,6 +34,9 @@ typedef unsigned long intptr_t; #include "pluginWindow.h" #include "helpWindow.h" #include "onelabGroup.h" +#ifdef HAVE_ONELAB2 +#include "onelab2Group.h" +#endif #include "gmshLocalNetworkClient.h" #include "fileDialogs.h" #include "extraDialogs.h" @@ -3010,6 +3013,11 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu) if(main && !detachedMenu){ #if defined(HAVE_ONELAB2) // 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 _onelab = new onelabGroup(0, mh, twidth, height - mh - sh); _onelab->enableTreeWidgetResize(false); diff --git a/Fltk/onelab2Group.cpp b/Fltk/onelab2Group.cpp new file mode 100644 index 0000000000000000000000000000000000000000..981924e3343c8a9825e30a57bbbcf398da440552 --- /dev/null +++ b/Fltk/onelab2Group.cpp @@ -0,0 +1,566 @@ +#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); +} + diff --git a/Fltk/onelab2Group.h b/Fltk/onelab2Group.h new file mode 100644 index 0000000000000000000000000000000000000000..cc36060762f71750273f9d36b474e4e33c6d1480 --- /dev/null +++ b/Fltk/onelab2Group.h @@ -0,0 +1,54 @@ +#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 diff --git a/contrib/onelab2/CMakeLists.txt b/contrib/onelab2/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..79f258c812db1cba64a064ca9848380932e8ba01 --- /dev/null +++ b/contrib/onelab2/CMakeLists.txt @@ -0,0 +1,31 @@ +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}) diff --git a/contrib/onelab2/GmshLocalClient.h b/contrib/onelab2/GmshLocalClient.h new file mode 100644 index 0000000000000000000000000000000000000000..69846e2510db92508305d8b7674680b1f48532a2 --- /dev/null +++ b/contrib/onelab2/GmshLocalClient.h @@ -0,0 +1,21 @@ +#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 diff --git a/contrib/onelab2/GmshNetworkClient.h b/contrib/onelab2/GmshNetworkClient.h new file mode 100644 index 0000000000000000000000000000000000000000..90b80687bdd95a3b0bc0bae22d13ad3b28ad3690 --- /dev/null +++ b/contrib/onelab2/GmshNetworkClient.h @@ -0,0 +1,27 @@ +#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 diff --git a/contrib/onelab2/NetworkUtils.cpp b/contrib/onelab2/NetworkUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71cbe9eb63ee9b19320cc590e20bcc821f6750a4 --- /dev/null +++ b/contrib/onelab2/NetworkUtils.cpp @@ -0,0 +1,147 @@ +#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; +} diff --git a/contrib/onelab2/NetworkUtils.h b/contrib/onelab2/NetworkUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..21cf19df5eb2637b0d79df3ff32e4fb9c2a81282 --- /dev/null +++ b/contrib/onelab2/NetworkUtils.h @@ -0,0 +1,149 @@ +#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 diff --git a/contrib/onelab2/Onelab.cpp b/contrib/onelab2/Onelab.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b3989de2ae6f370e5503cf6017577189ed45cea --- /dev/null +++ b/contrib/onelab2/Onelab.cpp @@ -0,0 +1,68 @@ +#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; +} diff --git a/contrib/onelab2/OnelabAttributes.cpp b/contrib/onelab2/OnelabAttributes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4910149be88caef69f27a6edb0e277bfa45a038a --- /dev/null +++ b/contrib/onelab2/OnelabAttributes.cpp @@ -0,0 +1,147 @@ +#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; +} diff --git a/contrib/onelab2/OnelabAttributes.h b/contrib/onelab2/OnelabAttributes.h new file mode 100644 index 0000000000000000000000000000000000000000..b7dac34e1cb11f79daef882e4ab88f52a5913b29 --- /dev/null +++ b/contrib/onelab2/OnelabAttributes.h @@ -0,0 +1,211 @@ +#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 diff --git a/contrib/onelab2/OnelabDatabase.h b/contrib/onelab2/OnelabDatabase.h new file mode 100644 index 0000000000000000000000000000000000000000..c190d7216654bc97edc6e8f17f6154c529763417 --- /dev/null +++ b/contrib/onelab2/OnelabDatabase.h @@ -0,0 +1,236 @@ +#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(); +} diff --git a/contrib/onelab2/OnelabLocalClient.h b/contrib/onelab2/OnelabLocalClient.h new file mode 100644 index 0000000000000000000000000000000000000000..5d0303ec5e1cc9d3545493ec86f55afee05dd6c1 --- /dev/null +++ b/contrib/onelab2/OnelabLocalClient.h @@ -0,0 +1,33 @@ +#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 diff --git a/contrib/onelab2/OnelabLocalNetworkClient.cpp b/contrib/onelab2/OnelabLocalNetworkClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e7d4a6a37da855e2144b666f9ba4c6a26d453b5 --- /dev/null +++ b/contrib/onelab2/OnelabLocalNetworkClient.cpp @@ -0,0 +1,48 @@ +#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); +} diff --git a/contrib/onelab2/OnelabLocalNetworkClient.h b/contrib/onelab2/OnelabLocalNetworkClient.h new file mode 100644 index 0000000000000000000000000000000000000000..cc2fe354ac927a9a5a9529cd034dba85976c0fac --- /dev/null +++ b/contrib/onelab2/OnelabLocalNetworkClient.h @@ -0,0 +1,39 @@ +#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 diff --git a/contrib/onelab2/OnelabNetworkClient.cpp b/contrib/onelab2/OnelabNetworkClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e497c617568b5fea0636f452a18abf8ae02aab3 --- /dev/null +++ b/contrib/onelab2/OnelabNetworkClient.cpp @@ -0,0 +1,142 @@ +#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); +} diff --git a/contrib/onelab2/OnelabNetworkClient.h b/contrib/onelab2/OnelabNetworkClient.h new file mode 100644 index 0000000000000000000000000000000000000000..b4f602217e0af043718eda38f347e4ad7097cdcc --- /dev/null +++ b/contrib/onelab2/OnelabNetworkClient.h @@ -0,0 +1,135 @@ +#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 **)¶meters[pi++], p.getName()); + } + else if(type == "string"){ + onelab::string p; p.fromChar(msg[i]); set(p, false); + _parameterSpace->getPtr((onelab::string **)¶meters[pi++], p.getName()); + } + else if(type == "region"){ + onelab::region p; p.fromChar(msg[i]); set(p, false); + _parameterSpace->getPtr((onelab::region **)¶meters[pi++], p.getName()); + } + else if(type == "function"){ + onelab::function p; p.fromChar(msg[i]); set(p, false); + _parameterSpace->getPtr((onelab::function **)¶meters[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 diff --git a/contrib/onelab2/OnelabProtocol.cpp b/contrib/onelab2/OnelabProtocol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..490ca67ea6386145fa2999cb2f3ef742dd3f045d --- /dev/null +++ b/contrib/onelab2/OnelabProtocol.cpp @@ -0,0 +1,125 @@ +#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; +} diff --git a/contrib/onelab2/OnelabProtocol.h b/contrib/onelab2/OnelabProtocol.h new file mode 100644 index 0000000000000000000000000000000000000000..c2b8497f7a3429fb5c5fd021fd7f859ba3ee4099 --- /dev/null +++ b/contrib/onelab2/OnelabProtocol.h @@ -0,0 +1,40 @@ +#ifndef _ONELAB_PROTOCOL_H +#define _ONELAB_PROTOCOL_H + +#define ERROR_ONELAB_VERSION 20 +#define ONELAB_VERSION 0x01 + +#include <vector> + +#include "OnelabAttributes.h" + +class OnelabProtocol +{ +private: + //UInt8 _version; + UInt8 _type; + UInt16 _size; +public: + std::vector<OnelabAttr*> attrs; + OnelabProtocol(UInt16 type); + ~OnelabProtocol() {clearAttrs();} + void clearAttrs(); + unsigned short encodeMsg(UInt8 *buff, UInt32 len); + UInt32 parseMsg(UInt8 *buff, UInt32 len); + void showMsg(); + + short msgType() {return _type;} + void msgType(short type) {this->clearAttrs(); _type = type;} + + static const UInt8 BindRequestMsg = 0x01; + static const UInt8 BindResponseMsg = 0x02; + static const UInt8 BindMessageMsg = 0x03; + + static const UInt8 OnelabStart = 0x10; + static const UInt8 OnelabStop = 0x11; + static const UInt8 OnelabMessage = 0x12; + static const UInt8 OnelabRequest = 0x13; + static const UInt8 OnelabResponse = 0x14; + static const UInt8 OnelabUpdate = 0x15; +}; +#endif diff --git a/contrib/onelab2/OnelabServer.cpp b/contrib/onelab2/OnelabServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e17a658e2290f04635b1cb0ce006b0b7e57b082d --- /dev/null +++ b/contrib/onelab2/OnelabServer.cpp @@ -0,0 +1,375 @@ +#include <cstdio> + +#ifndef WIN32 +#include <pthread.h> +#include <signal.h> +#else +#include <wspiapi.h> +#endif + +#include "OnelabServer.h" +#include "OnelabProtocol.h" +#include "OnelabAttributes.h" +#include "onelab.h" +#include "NetworkUtils.h" + +static bool haveToStop = false; + +void signalHandler(int unused) +{ + haveToStop = true; +} + +OnelabServer::OnelabServer(UInt32 iface, UInt16 port) +{ + _ip.address = iface; + _ip.port = port; + +#ifdef HAVE_UDT + UDT::startup(); + _fdu = udt_socket(_ip, SOCK_STREAM); +#endif + _fds = ip4_socket(_ip, SOCK_STREAM); + ip4_socket_ip(_fds, _ip); +} +OnelabServer::OnelabServer(UInt16 port) +{ + _ip.address = 0; + _ip.port = port; + +#ifdef HAVE_UDT + UDT::startup(); + _fdu = udt_socket(_ip, SOCK_STREAM); +#endif + _fds = ip4_socket(_ip, SOCK_STREAM); + ip4_socket_ip(_fds, _ip); +} +#ifdef HAVE_UDT +void OnelabServer::addClient(std::string name, UDTSOCKET fd, UInt32 ip, UInt16 port) +{ + this->_clients.push_back(OnelabLocalNetworkClient(name, fd, ip, port)); +} +OnelabLocalNetworkClient *OnelabServer::getClient(UDTSOCKET fd) // UDTSOCKET Socket +{ + for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) { + if(it->getUSocket() == fd) return &(*it); + if(it->getSSocket() == fd) return &(*it); + } + return NULL; +} +#endif +//void OnelabServer::addClient(std::string name, Socket fd, UInt32 ip, UInt16 port) +//{ +// if(ip == 0 || port == 0) throw "Unable to add client (invalid ip or port)"; +// this->_clients.push_back(OnelabLocalNetworkClient(name, fd, ip, port)); +//} +//OnelabLocalNetworkClient *OnelabServer::getClient(Socket fd) +//{ +// for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) { +// if(it->getSSocket() == fd) return &(*it); +// } +// return NULL; +//} +void OnelabServer::sendto(std::string client, UInt8 *buff, UInt32 len) +{ + for(std::vector<OnelabLocalNetworkClient>::iterator it = this->_clients.begin() ; it != this->_clients.end(); ++it) { + if((*it).getName() != client) continue; + (*it).sendto(buff, len); + return; + } +} +OnelabLocalNetworkClient *OnelabServer::getClient(UInt32 ip, UInt16 port) +{ + for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) { + if((*it).getIp() == ip && (*it).getPort() == port) + return &(*it); + } + return NULL; +} +OnelabLocalNetworkClient *OnelabServer::getClient(std::string name) +{ + for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) { + if((*it).getName() == name) + return &(*it); + } + return NULL; +} +void OnelabServer::removeClient(OnelabLocalNetworkClient *client) +{ + for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) { + if(&(*it) == client) { + _clients.erase(it); + return; + } + } +} +#ifdef HAVE_UDT +#ifndef WIN32 +void *listenOnClients(void *param) +#else +DWORD WINAPI listenOnClients(LPVOID param) +#endif +{ + IPv4 ip; + std::set<UDTSOCKET> fdus; + std::set<Socket> fdss; + int recvlen = 0; + UInt8 prev[1024]; + UInt32 unreaded = 0; + UInt8 buff[1024]; + OnelabProtocol msg(-1), rep(-1); + int eid = OnelabServer::instance()->getEID(); + while(UDT::ERROR != UDT::epoll_wait(eid, &fdus, NULL, -1, &fdss)) { + std::cout << "ok" << std::endl; + //for(std::set<UDTSOCKET>::iterator it = fdus.begin(); it != fdus.end(); ++it) { + for(std::set<Socket>::iterator it = fdss.begin(); it != fdss.end(); ++it) { + OnelabLocalNetworkClient *cli = OnelabServer::instance()->getClient(*it); + std::cout << "ok ->" << (void*)cli << std::endl; + if(cli == NULL) { + IPv4 ip; + //recvlen = udt_socket_recv(*it, buff, 1024); + recvlen = ip4_socket_recv(*it, buff, 1024, ip); + std::clog << "recv " << recvlen << std::endl; + msg.parseMsg(buff, recvlen); + msg.showMsg(); + if(msg.msgType() == OnelabProtocol::OnelabStart && msg.attrs.size() > 0 && msg.attrs[0]->getAttributeType() == OnelabAttr::Start) { + std::string name = std::string(((OnelabAttrStart *)msg.attrs[0])->name()); + if(OnelabServer::instance()->getClient(name) != NULL) { + rep.msgType(OnelabProtocol::OnelabMessage); + rep.attrs.push_back(new OnelabAttrMessage("A client exist with this name !", OnelabAttrMessage::Fatal)); + recvlen = rep.encodeMsg(buff, 1024); + //udt_socket_send(*it, buff, recvlen); + //TODO ip4_socket_send(*it, buff, recvlen); + //UDT::epoll_remove_usock(eid, *it); + UDT::epoll_remove_ssock(eid, *it); + UDT::close(*it); + continue; + } + OnelabServer::instance()->addClient(name, *it, ip.address, ip.port); + std::clog << "\033[0;31m" << "Add a new client: " << name << "\033[0m" << std::endl; + OnelabProtocol rep(OnelabProtocol::OnelabStart); + recvlen = rep.encodeMsg(buff, 1024); + cli = OnelabServer::instance()->getClient(*it); + cli->sendto(buff, recvlen); + //FIXME OnelabServer::instance()->sendAllParameter(cli); + continue; + } + else { + // cli shoud send a name first + //UDT::epoll_remove_usock(eid, *it); + UDT::epoll_remove_ssock(eid, *it); + UDT::close(*it); + continue; + } + } + else { + try { + //recvlen = cli->recvfrom(buff, 1024); + std::cout << "i've " << unreaded << "bytes from previous packet" << std::endl; + memcpy((char*)buff, (char*)prev, unreaded); + recvlen = cli->recvfrom(buff+unreaded, 1024-unreaded); + recvlen += unreaded; + } + catch(int &e) { // for UDT + if(UDT::getlasterror().getErrorCode() == 2001) { // ECONNLOST + std::cout << "\033[0;31m" << "Connection with client \"" << cli->getName() << "\" was broken, removing the client." << "\033[0m" << std::endl; // DEBUG + UDT::epoll_remove_usock(eid, *it); + OnelabServer::instance()->removeClient(cli); + UDT::close(*it); + } + continue; + } + if(recvlen == 0) { // for TCP + std::cout << "\033[0;31m" << "Connection with client \"" << cli->getName() << "\" was broken, removing the client." << "\033[0m" << std::endl; // DEBUG + UDT::epoll_remove_ssock(eid, *it); + OnelabServer::instance()->removeClient(cli); + UDT::close(*it); + continue; + } + //std::clog << "recv " << recvlen << " bytes on client " << cli->getName() << std::endl; + unreaded = msg.parseMsg(buff, recvlen); + if(unreaded > 0) { + memcpy((char*)prev, (char*)buff+(recvlen-unreaded), unreaded); + } + switch (msg.msgType()) { + case OnelabProtocol::OnelabStop: + std::cout << "\033[0;31m" << "Client \"" << cli->getName() << "\" is going to stop" << "\033[0m" << std::endl; // DEBUG + rep.msgType(OnelabProtocol::OnelabStop); + recvlen = rep.encodeMsg(buff, 1024); + cli->sendto(buff, recvlen); + //UDT::epoll_remove_usock(eid, *it); + UDT::epoll_remove_ssock(eid, *it); + OnelabServer::instance()->removeClient(cli); + UDT::close(*it); + break; + case OnelabProtocol::OnelabMessage: + // TODO + break; + case OnelabProtocol::OnelabRequest: + rep.msgType(OnelabProtocol::OnelabResponse); + if(msg.attrs.size() == 0) OnelabServer::instance()->sendAllParameter(cli); + else for(std::vector<OnelabAttr *>::iterator it = msg.attrs.begin() ; it != msg.attrs.end(); ++it) { + if((*it)->getAttributeType() == OnelabAttr::Parameter) { + OnelabAttrParameterQuery *attr = (OnelabAttrParameterQuery *)*it; + std::cout << "\033[0;31m" << "Client \"" << cli->getName() << " ask for parameter \"" << attr->getName() << "\"\033[0m" << std::endl; // DEBUG + onelab::parameter *p; + switch(attr->paramType()) { + case OnelabAttr::Number: + OnelabServer::instance()->getPtr((onelab::number **)&p, attr->getName(), cli->getName()); + break; + case OnelabAttr::String: + OnelabServer::instance()->getPtr((onelab::string **)&p, attr->getName(), cli->getName()); + break; + case OnelabAttr::Region: + OnelabServer::instance()->getPtr((onelab::region **)&p, attr->getName(), cli->getName()); + break; + case OnelabAttr::Function: + OnelabServer::instance()->getPtr((onelab::function **)&p, attr->getName(), cli->getName()); + break; + } + if(p != NULL) rep.attrs.push_back(p); + else rep.attrs.push_back(new OnelabAttrMessage("Unable to find the request parameter.", OnelabAttrMessage::Error)); + } + // else ?? + } + recvlen = rep.encodeMsg(buff, 1024); + cli->sendto(buff, recvlen); + break; + case OnelabProtocol::OnelabUpdate: + for(std::vector<OnelabAttr *>::iterator it = msg.attrs.begin() ; it != msg.attrs.end(); ++it) { + if((*it)->getAttributeType() >= OnelabAttr::Number && (*it)->getAttributeType() <= OnelabAttr::Function) { + onelab::parameter *attr = (onelab::parameter *)*it; + std::cout << "\033[0;31m" << "Client \"" << cli->getName() << " update parameter \"" << attr->getName() << "\"\033[0m" << std::endl; // DEBUG + onelab::parameter *parameter = NULL; + switch(attr->getAttributeType()) { + case OnelabAttr::Number: + OnelabServer::instance()->set(*(onelab::number *)attr, cli->getName()); + OnelabServer::instance()->getPtr((onelab::number **)¶meter, attr->getName(), cli->getName()); + break; + case OnelabAttr::String: + OnelabServer::instance()->set(*(onelab::string *)attr, cli->getName()); + OnelabServer::instance()->getPtr((onelab::string **)¶meter, attr->getName(), cli->getName()); + break; + case OnelabAttr::Region: + OnelabServer::instance()->set(*(onelab::region *)attr, cli->getName()); + OnelabServer::instance()->getPtr((onelab::region **)¶meter, attr->getName(), cli->getName()); + break; + case OnelabAttr::Function: + OnelabServer::instance()->set(*(onelab::function *)attr, cli->getName()); + OnelabServer::instance()->getPtr((onelab::function **)¶meter, attr->getName(), cli->getName()); + break; + } + // TODO + //rep.msgType(OnelabProtocol::OnelabUpdate); + //rep.attrs.push_back(parameter); + //recvlen = rep.encodeMsg(buff, 1024); + //std::map<std::string, bool> clients = attr->getClients(); + //for(std::map<std::string, bool>::const_iterator it = clients.begin(); it != clients.end(); it++) { + // OnelabLocalNetworkClient *tmp = OnelabServer::instance()->getClient(it->first); + // if(tmp == NULL || cli == tmp) continue; + // tmp->sendto(buff, recvlen); + //} + } + else + switch((*it)->getAttributeType()) { + case 0x0B: + { + // TODO check if file is on a specific client + const char *filename = ((OnelabAttrFileQuery *)*it)->getFilename(); + // FIXME path/filename ? + std::clog << "try to open " << filename << " to read" << std::endl; + FILE *fp = fopen(filename, "rb"); + if(fp != NULL){ + std::clog << "file open" << std::endl; + rep.msgType(OnelabProtocol::OnelabUpdate); + rep.attrs.push_back(new OnelabAttrFile(std::string(filename), fp)); + recvlen = rep.encodeMsg(buff, 1024); + cli->sendto(buff, recvlen); + while((recvlen = fread(buff, 1, 1024, fp)) > 0){ + cli->sendto(buff, recvlen); + } + } + std::clog << "file ok" << std::endl; + break; + } + case 0x0C: + const char *filename = ((OnelabAttrFile *)*it)->getFilename(); + std::clog << "try to open " << filename << " to write" << std::endl; + FILE *fp = fopen(filename, "wb"); + if(fp != NULL){ + std::clog << "file open" << std::endl; + int filesize = ((OnelabAttrFile *)*it)->getFileSize(); + int downloadsize = 0; + while(downloadsize < filesize) { + recvlen = cli->recvfrom(buff, 1024); + fwrite(buff, 1, recvlen, fp); + } + } + std::clog << "file ok" << std::endl; + break; + } + } + break; + } + } + } + } +} +#endif +void OnelabServer::sendAllParameter(OnelabLocalNetworkClient *cli) +{ + std::set<onelab::parameter*, onelab::parameterLessThan> ps; + OnelabProtocol msg = OnelabProtocol(OnelabProtocol::OnelabUpdate); + UInt32 bufflen = 1024, recvlen = 0; + UInt8 buff[1024]; + _parameterSpace.getAllParameters(ps); + for(std::set<onelab::parameter*, onelab::parameterLessThan>::iterator it = ps.begin(); it != ps.end(); it++) + if((*it)->hasClient(cli->getName())) msg.attrs.push_back(*it); + recvlen = msg.encodeMsg(buff, bufflen); + cli->sendto(buff, recvlen); +} +void OnelabServer::Run() +{ + UInt32 bufflen = 1024, recvlen = 0; + UInt8 buff[1024]; + IPv4 ip; + OnelabProtocol msg(-1), rep(OnelabProtocol::OnelabResponse); + OnelabLocalNetworkClient *currentClient = NULL; + +#ifdef HAVE_UDT + UDTSOCKET newcli = 0; +#ifndef WIN32 + pthread_t listen_thread; +#else + HANDLER listen_thread; +#endif + + _eid = UDT::epoll_create(); + + udt_socket_listen(_fdu); + ip4_socket_listen(_fds); + std::clog << "listen on " << ip4_inet_ntop(_ip.address) << ":" << _ip.port << "(tcp)" << std::endl + << "listen on " << ip4_inet_ntop(_ip.address) << ":" << _ip.port << "(udp/udt)" << std::endl; + //while(newcli = udt_socket_accept(_fdu, ip)) { // TODO accept ip4 + while(newcli = ip4_socket_accept(_fds, ip)) { // TODO accept ip4 + std::clog << "\033[0;31m" << "accpet peer : " << ip4_inet_ntop(ip.address)<< ':' << ip.port << "\033[0m" << std::endl; + //UDT::epoll_add_usock(_eid, newcli); + UDT::epoll_add_ssock(_eid, newcli); + if(_clients.size() == 0) +#ifndef WIN32 + pthread_create(&listen_thread, NULL, listenOnClients, NULL); +#else + listen_thread = CreateThread(NULL, 0, listenOnClients, NULL, 0, NULL); +#endif + } +#ifndef WIN32 + pthread_join(listen_thread, NULL); +#else + WaitForSingleObject(listen_thread, INFINITE); +#endif + udt_socket_close(_fdu); +#else + // TODO + ip4_socket_close(_fds); +#endif +} diff --git a/contrib/onelab2/OnelabServer.h b/contrib/onelab2/OnelabServer.h new file mode 100644 index 0000000000000000000000000000000000000000..81b773b9445b3b5749a0bfb7a26a15e72038cb50 --- /dev/null +++ b/contrib/onelab2/OnelabServer.h @@ -0,0 +1,126 @@ +#ifndef _ONELABSERVER_H_ +#define _ONELABSERVER_H_ + +#include <vector> +#include <string> + +#include "onelab.h" +#include "GmshSocket.h" +#include "NetworkUtils.h" +#ifdef HAVE_UDT +#include "UdtUtils.h" +#endif +#include "OnelabLocalNetworkClient.h" +#include "OnelabLocalClient.h" + +class OnelabLocalClient; + +class OnelabServer +{ +private: + static OnelabServer *_server; + IPv4 _ip; + std::vector<OnelabLocalNetworkClient> _clients; + std::vector<OnelabLocalClient *> _localClients; + onelab::parameterSpace _parameterSpace; + Socket _fds; +#ifdef HAVE_UDT + UDTSOCKET _fdu; + int _eid; + void sendto(std::string client, UInt8 *buff, UInt32 len); + std::string waitForClientName(UDTSOCKET fd); +#endif +public: + OnelabServer(UInt16 port); + OnelabServer(UInt32 iface, UInt16 port); + static OnelabServer *instance(const UInt32 iface=0, const UInt16 port=0) { + if(!_server) _server = new OnelabServer(iface, port); + return _server; + } + static void setInstance(OnelabServer *s) { _server = s; } + onelab::parameterSpace *getParameterSpace() {return &_parameterSpace;} +#ifdef HAVE_UDT + ~OnelabServer(){UDT::cleanup();} +#else + ~OnelabServer(){} +#endif + void Run(); + // Client methods +#ifdef HAVE_UDT + inline int getEID() {return _eid;} + void addClient(std::string name, UDTSOCKET fd, UInt32 ip, UInt16 port); + OnelabLocalNetworkClient *getClient(UDTSOCKET fd); +#else + void addClient(std::string name, UInt32 ip, UInt16 port); +#endif + void addClient(OnelabLocalClient *cli) {_localClients.push_back(cli);} + void removeClient(OnelabLocalNetworkClient *client); + std::vector<OnelabLocalNetworkClient> &getClients() {return _clients;} + std::vector<OnelabLocalClient *> &getLocalClients() {return _localClients;} + OnelabLocalNetworkClient *getClient(UInt32 ip, UInt16 port); + OnelabLocalNetworkClient *getClient(std::string name); + void sendAllParameter(OnelabLocalNetworkClient *cli); + // Parameters methods + void clear(const std::string &name="", const std::string &client="") { + _parameterSpace.clear(name, client); + } + template <class T> bool existInDatabase(const T &p) { + std::vector<T> ps; + _parameterSpace.get(ps, p.getName()); + return ps.size() > 0; + } + template <class T> bool set(const T &p, const std::string &client="") { + bool isNew = !existInDatabase(p); + _parameterSpace.set(p, client); + T *pp; + _parameterSpace.getPtr(&pp, p.getName()); + for(std::vector<OnelabLocalClient *>::iterator it = _localClients.begin() ; it != _localClients.end(); ++it) + if((*it)->getName() != client) + if(isNew)(*it)->onNewParameter(pp); + else (*it)->onUpdateParameter(pp); + std::map<std::string, bool> clients = p.getClients(); + for(std::map<std::string, bool>::const_iterator it = clients.begin(); it != clients.end(); it++) { + std::cout << "send " << p.getName() << " to " << it->first << " from " << client << std::endl; + if(it->first == client) continue; + OnelabLocalNetworkClient *tmp = getClient(it->first); + if(tmp == NULL) continue; + tmp->updateParameter(pp); + } + } + template <class T> bool get(std::vector<T> &ps, const std::string &name="", const std::string &client="") { + return _parameterSpace.get(ps, name, client); + } + template <class T> void getPtr(T **ptr, const std::string &name="", const std::string &client="") { + _parameterSpace.getPtr(ptr, name, client); + } + bool fromChar(const std::vector<std::string> &msg, const std::string &client="") + { + 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, client); + } + else if(type == "string"){ + onelab::string p; p.fromChar(msg[i]); set(p, client); + } + else if(type == "region"){ + onelab::region p; p.fromChar(msg[i]); set(p, client); + } + else if(type == "function"){ + onelab::function p; p.fromChar(msg[i]); set(p, client); + } + else + return false; + } + 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; + } +}; +#endif diff --git a/contrib/onelab2/UdtUtils.h b/contrib/onelab2/UdtUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..26e12a9d5c020b18fd8b67557cfdfa0d012efd9f --- /dev/null +++ b/contrib/onelab2/UdtUtils.h @@ -0,0 +1,80 @@ +#ifndef _UDTUTILS_H_ +#define _UDTUTILS_H_ +#include <iostream>// FIXME debug only +#include <udt.h> +#include "NetworkUtils.h" + +inline UDTSOCKET udt_socket(IPv4 ip, int socketType) +{ + UDTSOCKET 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(UDT::ERROR == (fd = UDT::socket(AF_INET, socketType, 0))) throw ERROR_SOCKET_CREATE; + + if(UDT::ERROR == UDT::bind(fd, (struct sockaddr*)&addr, sizeof(addr))) {std::cout << UDT::getlasterror().getErrorMessage() << std::endl; throw ERROR_SOCKET_BIND;} + + bool otrue = true; + UDT::setsockopt(fd, 0, UDT_REUSEADDR, &otrue, sizeof(bool)); + + return fd; +} + +inline void udt_socket_timeout(UDTSOCKET fd, long ms) +{ + setsockopt(fd, 0, UDT_SNDTIMEO, &ms, sizeof(long)); + setsockopt(fd, 0, UDT_RCVTIMEO, &ms, sizeof(long)); +} + +inline void udt_socket_listen(UDTSOCKET fd, int maxconnection=1024) +{ + if(UDT::ERROR == UDT::listen(fd, maxconnection)) throw ERROR_SOCKET_LISTEN; +} + +inline UDTSOCKET udt_socket_accept(UDTSOCKET fd, IPv4 &ip) +{ + UDTSOCKET cli; + struct sockaddr_in addr; + int addrl = sizeof(addr); + + cli = UDT::accept(fd, (struct sockaddr*)&addr, &addrl); + ip.address = ntoh32(addr.sin_addr.s_addr); + ip.port = ntoh16(addr.sin_port); + + return cli; +} + +inline void udt_socket_connect(UDTSOCKET fd, IPv4 ip) +{ + struct sockaddr_in addr; + socklen_t addrl = sizeof(addr); + memset(&addr, 0, addrl); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = hton32(ip.address); + addr.sin_port = hton16(ip.port); + if(UDT::ERROR == UDT::connect(fd, (struct sockaddr *)&addr, addrl)) { std::cout << UDT::getlasterror().getErrorMessage() << std::endl; throw ERROR_SOCKET_CONNECT;} +} + +inline int udt_socket_send(UDTSOCKET fd, UInt8 *src, int length) +{ + return UDT::send(fd, (char *)src, length, 0); +} + +inline int udt_socket_recv(UDTSOCKET fd, UInt8 *dst, int maxlength) +{ + int recvlen = 0; + if(UDT::ERROR == (recvlen = UDT::recv(fd, (char *)dst, maxlength, 0))) { std::cout << UDT::getlasterror().getErrorMessage() << std::endl; throw ERROR_SOCKET_RECV;} + return recvlen; +} + +inline void udt_socket_close(UDTSOCKET fd) +{ + UDT::close(fd); +} + +#endif diff --git a/contrib/onelab2/VirtualClient.h b/contrib/onelab2/VirtualClient.h new file mode 100644 index 0000000000000000000000000000000000000000..01c28bd48bd5a926b89e2db2bd7c5625b2401c83 --- /dev/null +++ b/contrib/onelab2/VirtualClient.h @@ -0,0 +1,45 @@ +#ifndef _VIRTUALCLIENT_H_ +#define _VIRTUALCLIENT_H_ + +#include <string> + +#include "onelab.h" + +class VirtualClient +{ +protected: + std::string _name; + onelab::parameterSpace *_parameterSpace; +private: + bool _parameterSpaceShouldBeDeleted; +public: + VirtualClient(std::string name, onelab::parameterSpace *parameterSpace=NULL){ + _name = name; + _parameterSpaceShouldBeDeleted = (parameterSpace==NULL); + if(_parameterSpaceShouldBeDeleted)_parameterSpace = new onelab::parameterSpace; + else _parameterSpace = parameterSpace; + } + virtual ~VirtualClient(){ + if(_parameterSpaceShouldBeDeleted && _parameterSpace != NULL) delete _parameterSpace; + } + std::string &getName() {return _name;} + template <class T> bool existInDatabase(const T p) const { + std::vector<T> ps; + _parameterSpace->get(ps, p.getName(), this->_name); + return ps.size() > 0; + } + 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, this->_name); + } + virtual void onNewParameter(onelab::parameter *) = 0; + virtual void onUpdateParameter(onelab::parameter *) = 0; + virtual void onRemoveParameter(onelab::parameter *) = 0; + + virtual void run() = 0; + virtual void stop() = 0; +}; + +#endif