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 **)&parameters[pi++], p.getName());
+      }
+      else if(type == "string"){
+        onelab::string p; p.fromChar(msg[i]); set(p, false);
+        _parameterSpace->getPtr((onelab::string **)&parameters[pi++], p.getName());
+      }
+      else if(type == "region"){
+        onelab::region p; p.fromChar(msg[i]); set(p, false);
+        _parameterSpace->getPtr((onelab::region **)&parameters[pi++], p.getName());
+      }
+      else if(type == "function"){
+        onelab::function p; p.fromChar(msg[i]); set(p, false);
+        _parameterSpace->getPtr((onelab::function **)&parameters[pi++], p.getName());
+      }
+      else
+        return false;
+      if(pi == 4 || i==msg.size()-1) {
+        OnelabProtocol msg(OnelabProtocol::OnelabUpdate);
+        for(unsigned int j = 0; j < pi; j++)
+          msg.attrs.push_back(parameters[j]);
+        request(msg);
+        pi=0;
+      }
+    }
+    return true;
+  }
+  bool fromFile(FILE *fp, const std::string &client="")
+  {
+    std::vector<std::string> msg;
+    if(onelab::parameter::fromFile(msg, fp)) return fromChar(msg, client);
+    return false;
+  }
+	virtual void onNewParameter(onelab::parameter *){}
+  virtual void onUpdateParameter(onelab::parameter *){}
+  virtual void onRemoveParameter(onelab::parameter *){} // TODO call on clear
+	// network specific method
+	bool connect();
+	bool isConnected(){return _connected;}
+	void recvfrom(OnelabProtocol &msg);
+	int recvfrom(UInt8 *buff, UInt16 maxlen);
+	void sendto(UInt8 *buff, UInt16 len);
+	void disconnect();
+	void setRemoteIP(unsigned long ip){if(!_connected) _ip.address=ip;}
+	void setRemotePort(unsigned short port){if(!_connected) _ip.port=port;}
+
+  void run() {}
+  void stop() {}
+};
+
+#endif
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 **)&parameter, attr->getName(), cli->getName());
+										break;
+									case OnelabAttr::String:
+										OnelabServer::instance()->set(*(onelab::string *)attr, cli->getName());
+										OnelabServer::instance()->getPtr((onelab::string **)&parameter, attr->getName(), cli->getName());
+										break;
+									case OnelabAttr::Region:
+										OnelabServer::instance()->set(*(onelab::region *)attr, cli->getName());
+										OnelabServer::instance()->getPtr((onelab::region **)&parameter, attr->getName(), cli->getName());
+										break;
+									case OnelabAttr::Function:
+										OnelabServer::instance()->set(*(onelab::function *)attr, cli->getName());
+										OnelabServer::instance()->getPtr((onelab::function **)&parameter, 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