Remoto - VFS: VFS_tcp_export_client.cpp Source File
Remoto - VFS
VFS_tcp_export_client.cpp
Go to the documentation of this file.
1 
2 #include "VFS.h"
3 #include "VFS_creator.h"
4 #include "utilities/rutils.h"
5 
8 
9 #include "VFS_base/VFS_acl.h"
10 #include "VFS_tcp_mount.h"
11 
29 VFS_tcp_export_client::VFS_tcp_export_client(QTcpSocket *socket, QString exportRoot, bool ssl, QSslConfiguration sslConfiguration, QByteArray icon)
30 : VFS_tcp_client(socket,ssl,sslConfiguration)
31 , _exportRoot(exportRoot)
32 , _icon(icon)
33 {
34  connect( this, SIGNAL(readyMessage(QByteArray)), this, SLOT(receiveMessage(QByteArray)) );
35 
36  connect( VFS::root(), SIGNAL(codeDirectoryUpdated()), this, SLOT(sendCodeDirectory()) );
37 
38  //send codeDirectory to new connection
39  connect( this, SIGNAL(connected()), this, SLOT(sendCodeDirectory()) );
40  //sendCodeDirectory();
41 }
42 
44 {
45  QMap<QString, QList<VFS_tcp_export_request *> >::iterator it = _queuedRequests.begin();
46  while (it != _queuedRequests.end())
47  {
48  QList<VFS_tcp_export_request *> l = it.value();
49  while (l.length())
50  {
51  VFS_request *r = l.takeFirst();
52  delete r;
53  }
54 
55  it++;
56  }
57 }
58 
67 {
68  #ifdef COMPRESS_TCP_MOUNT
69  message = qUncompress(message);
70  if (message.length() == 0)
71  VFS::ERROR("(1) Uncompressed message size was 0.");
72  #endif
73 
74  #ifdef SHOW_JSON
75  printf("%s received: %s\n",qUtf8Printable(className()),qUtf8Printable(message));
76  #endif
77 
79 
80  if (r)
81  {
82  if (!r->_pendingSession)
84  }
85  else
86  VFS::ERROR( QString("Can't satisfy %1 request without sender or valid json message.").arg(className()) );
87 }
88 
98 {
99  if (r->_id == POST_ID_PING)
100  {
101  VFS::LOG( QString("%1 :: ping").arg(className()), 9 );
102  delete r;
103  return;
104  }
105 
106  if (r->_id == POST_ID_SESSION_DATA)
107  {
108  //printf("received session data: %s\n",qUtf8Printable(r->toJson(0,true,true)));
109 
110  //register the session
111  QString id = r->_metadata["sessionid"].toString();
112 
113  if (r->_data.isNull())
114  printf("Received invalid session information. FIXME: remove the request and abort.");
115 
116  QJsonObject data = r->_data.object();
117  VFS_session *s = new VFS_session(this,nullptr,data);
119 
120  //set _session on each item in the queue
121  QList< VFS_tcp_export_request *> queue = _queuedRequests.take(id);
122  for( int i=0; i<queue.count(); ++i )
123  queue[i]->_session = s;
124 
125  //execute the queue
126  for( int i=0; i<queue.count(); ++i )
127  executeMessageRequest( queue[i] );
128 
129  delete r;
130  return;
131  }
132 
133  //check to see if access is allowed on the _exportRoot
134  if (r->_session)
135  {
136  //printf("checking access on %s\n",qUtf8Printable(_exportRoot));
137 
139  {
140  VFS::ERROR( r->_reason = QString("ACL access was denied for user '%1' on '%2' (%3)").arg(r->_user).arg(_exportRoot).arg(r->_initialPath) );
141  r->_success = false;
142  receiveResponse(r);
143  return;
144  }
145  //else
146  // printf("access granted to %s on %s\n",qUtf8Printable(r->_session->fetchSessionValue("user").toString()),qUtf8Printable(_exportRoot));
147  }
148 
149  switch(r->_requestType)
150  {
152  VFS::ERROR( QString("Requested code directory"), 9, r->_user );
153 
154  QString error;
155  QJsonObject o = VFS_creator::codeDirectory(error);
156  r->_data.setObject(o);
157  r->_success = true;
158 
159  receiveResponse(r);
160  }
161 
162  break;
163 
164  case VFS_request::code: {
166 
167  if (c->hasCallback()) //it needs to be dispatched
168  {
169  //issueRequest(c);
170 
171  //this is almost certainly on a different thread
172  QMetaObject::invokeMethod(c->_origin,"executeRequest",Qt::AutoConnection,Q_ARG(VFS_request*, c));
173  }
174  else
175  {
176  //issueResponse(c);
177  //c->execute();
178  receiveResponse(c);
179  }
180  }
181 
182  break;
183 
185  VFS::LOG( QString("'%1' request on '%2' (%3)").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path).arg(r->_metadata["unsubscriptions"].toInt(0)), 9, r->_user );
186 
187  if (r->_path.startsWith( _exportRoot+"/__ACL__/"))
188  {
189  QString p = r->_path.mid( QString(_exportRoot+"/__ACL__/").length() );
190  //r->_path = r->_initialPath = p;
191  r->_path = p;
192  issueRequest(r);
193  }
194  else
195  issueRequest(r);
196  }
197 
198  break;
199 
200 
201  case VFS_request::subscribe: {
202  VFS::LOG( QString("'%1' request on '%2' (%3)").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path).arg(r->_metadata["subscriptions"].toInt(0)), 9, r->_user );
203 
204  //printf("subscribe: %s %s\n",qUtf8Printable(r->_path),qUtf8Printable(_exportRoot+"/__ACL__"));
205 
206  if (r->_path.startsWith( _exportRoot+"/__ACL__/"))
207  {
208  QString p = r->_path.mid( QString(_exportRoot+"/__ACL__/").length() );
209  //r->_path = r->_initialPath = p;
210  r->_path = p;
211  //printf("new path: %s\n",qUtf8Printable(p));
212  issueRequest(r);
213  }
214  else
215  issueRequest(r);
216  }
217 
218  break;
219 
220  case VFS_request::submit: {
221  //VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
222 
223  if (r->_path.startsWith( _exportRoot+"/__ACL__/"))
224  {
225  QString p = r->_path.mid( QString(_exportRoot+"/__ACL__/").length() );
226  r->_path = r->_initialPath = p;
227  VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
228  issueRequest(r);
229  }
230  else
231  {
232  VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
233  issueRequest(r);
234  }
235  }
236 
237  break;
238 
239  case VFS_request::metadata: {
240  VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
241 
242  if (r->_path.startsWith( _exportRoot+"/__ACL__/"))
243  {
244  QString p = r->_path.mid( QString(_exportRoot+"/__ACL__/").length() );
245  r->_path = r->_initialPath = p;
246  issueRequest(r);
247  }
248  else
249  issueRequest(r);
250  }
251 
252  break;
253 
254  case VFS_request::read: {
255  VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
256 
257  if (r->_path.endsWith("__ACL__"))
258  {
259  QStringList l = VFS_acl::fetchACLPaths();
260  QJsonObject o;
261  for (int i=0;i<l.length();i++)
262  {
263  o[ l[i] ] = false;
264  }
265 
266  /*
267  QMutexLocker m(&VFS_tcp_mount::_mountsLock);
268  QList<VFS_tcp_mount *> mounts = VFS_tcp_mount::_mounts;
269 
270  for (int i=0;i<mounts.length();i++)
271  {
272  if (mounts[i]->isMounted())
273  {
274  o[ mounts[i]->path()+"/__ACL__" ] = true;
275  }
276  }
277  */
278 
279  r->_data.setObject(o);
280  r->_success = true;
281 
282  receiveResponse(r);
283  }
284  else
285  issueRequest(r);
286  }
287 
288  break;
289 
290  default: {
291  VFS::LOG( QString("'%1' request on '%2'").arg(VFS_request::requestTypeStrings[r->_requestType]).arg(r->_path), 9, r->_user );
292  issueRequest(r);
293  }
294  break;
295  }
296 }
297 
305 {
306  //printf("CLIENT APPLY DIFF!\n");
307 
309 
310  VFS_node *source = t->_origin;
311 
312  if (_sourcePathMap.contains(source))
313  {
314  //update t->_path to reflect the path on the other side of the mount
315  t->_path = rutils::cleanPath( _sourcePathMap.value(source)+"/"+t->_path );
316  }
317  else
318  {
319  VFS::ERROR( QString("Could not find _sourcePathMap reference for 0x%1 (%2). Not applying diff for '%3'").arg((quintptr)source, QT_POINTER_SIZE * 2, 16, QChar('0')).arg(source->className()).arg(t->_originPath), 0, t->_user );
320  printf("BAD DIFF: %s\n",qUtf8Printable(t->toJson(0,true,true)));
321  t->_success = false;
322  return;
323  }
324 
325  QByteArray diff = t->toJson(POST_ID_DIFF);
326 
327  #ifdef SHOW_JSON
328  printf("%s sends: %s\n",qUtf8Printable(className()),qUtf8Printable(diff));
329  #endif
330 
331  #ifdef COMPRESS_TCP_MOUNT
332  diff = qCompress(diff);
333  #endif
334 
336 }
337 
338 
346 {
347  //VFS_node::receiveResponse(t);
348 
349  //if (t->_success)
350  switch(t->_requestType)
351  {
352  case VFS_request::subscribe: {
353  VFS_node *s = t->_responder;
354  if (s && t->_success)
355  {
356  //addSourcePathMap(s,t->_prefixPath.join('/'));
357  //printf("PREFIX PATH: %s\n",qUtf8Printable(t->_prefixPath.join('/')));
358 
359  if ( t->_initialPath.startsWith("__ACL__") )
361  //printf("ACL subscribe: %s\n",qUtf8Printable(t->_initialPath));
362  }
363  else
364  {
365  QString pp = t->_prefixPath.join('/');
366  pp = pp.mid(_exportRoot.length()+1);
368  }
369 
370  //this export may have an icon override
371  if (t->_path == "" && _icon != "")
372  {
373  if (t->_metadata.contains("icon"))
374  {
375  t->_metadata["icon"] = QString(_icon);
376  }
377  }
378  }
379  else
380  { //VFS::ERROR( QString("%1 no subscribe responder, or _success=false. Not adding to sourcePathMap.").arg(className()) );
381  //if (!s)
382  // VFS::ERROR( QString("%1 no subscribe responder. Not adding to sourcePathMap.").arg(className()) );
383  }
384  }
385  break;
386 
388  VFS_node *s = t->_responder;
389  if (s && t->_success)
390  {
391  //VFS::ERROR("removing subscription path");
392 
393  //FIXME: there may be multiple subscriptions from the mount to this path... don't delete the entry unless the node is deleted.
394 
395  /*
396  int c = -1;
397  if ( _subscribers.contains(t->_initialPath) &&
398  _subscribers[t->_initialPath].contains(t->_originPath) &&
399  _subscribers[t->_initialPath][t->_originPath].contains(s) )
400  c = _subscribers[t->_initialPath][t->_originPath].value(s,-2);
401 
402  printf("unsubscribe count: %d\n",c);
403 
404  if (c==-1)
405  {
406  printf("KEYS: '%s'\n",qUtf8Printable(_subscribers.keys().join("'\n'")));
407  foreach(QString k,_subscribers.keys())
408  {
409  printf(" KEYS2: '%s' '%s'\n",qUtf8Printable(k),qUtf8Printable(_subscribers[k].keys().join("'\n'")));
410  }
411  printf("originPath: %s\n",qUtf8Printable(t->_originPath));
412  printf("REQ: %s\n",qUtf8Printable(t->toJson(0,true,true)));
413  }
414  */
415 
416  //FIXME: for now, we just leave the entry
417  //removeSourcePathMap(s);
418  }
419  //else
420  // VFS::ERROR( QString("%1 no unsubscribe responder, or _success=false").arg(className()) );
421  }
422  break;
423 
424  case VFS_request::write:
425  case VFS_request::submit: {
426  //if (!t->_success) //no need to send the data back
427  {
428  t->_data = QJsonDocument();
429  }
430  //else
431  // but we don't kill it here so the requestor receives acknowledgement and can clean up the initial VFS_request
432  }
433  break;
434 
435  default: break;
436  }
437 
438 // VFS_tcp_export_request *rq = dynamic_cast<VFS_tcp_export_request *>(t);
439 // if (!rq)
440 // {
441 // VFS::ERROR("need a copy constructor thing like VFS_remotoserver_client::receiveResponse!");
442 // }
443 
445 }
446 
461 {
462  QMutexLocker l(&_lock);
463 
464  if (!source)
465  { VFS::ERROR("NO SOURCE, WON'T ADD!\n");
466  return;
467  }
468 
469  if (!_sourcePathMap.contains(source))
470  { _sourcePathMap.insert(source,path);
471  connect(source, SIGNAL(unmounted(VFS_node*)), this, SLOT(removeSourcePathMap(VFS_node*)));
472  }
473  else
474  {
475  if (_sourcePathMap[source] != path)
476  if (!path.startsWith("__ACL__"))
477  VFS::WARN( QString("Not duplicating path %1 in pathMap. Attempted: '%2', existing: '%3'").arg((quintptr)source).arg(path).arg(_sourcePathMap[source]) );
478  }
479 }
480 
481 
488 {
489  QMutexLocker l(&_lock);
490 
491  if (s)
492  { if (_sourcePathMap.contains(s))
493  { //QString p = _sourcePathMap.value(s);
494  _sourcePathMap.remove(s);
495  }
496  // else
497  // VFS::WARN( QString("Could not remove non-existent entry %1 from sourcePathMap.").arg((quintptr)s) );
498  }
499  else
500  VFS::WARN( QString("Could not remove null sender %1 from sourcePathMap.").arg((quintptr)sender()) );
501 }
502 
503 
509 {
510  VFS::LOG("Sending code directory.",9,className());
511 
512  QString error;
513  QJsonObject o = VFS_creator::codeDirectory(error);
514  //VFS_request *r = createRequest(VFS_request::codeDirectory,"",className(),QJsonDocument(o));
517  r->_user = className();
519  r->_data.setObject(o);
520  r->_success = true;
521  r->execute();
522  delete r;
523 }
524 
538 : VFS_request(VFS_request::none,origin)
539 , _id(POST_ID_NONE)
540 , _exportRoot(exportRoot)
541 , _pendingSession(false)
542 {
543 }
544 
546 {
547 }
548 
559 void VFS_tcp_export_request::fromJsonObject(QJsonObject json, bool includeInitialPath)
560 {
561  VFS_request::fromJsonObject(json,includeInitialPath);
562 
563  // We only replace the _id if it has not been set yet.
564  // if it has been set, it is part of a chained request,
565  // like if a mount is being re-exported
566  if (_id == POST_ID_NONE)
567  _id = static_cast<postID>(json["id"].toInt());
568 
571 
572  if (json.contains("session"))
573  {
574  //printf("SESSION: %s\n",qUtf8Printable(json["session"].toString()));
575 
576  //get the session, or request it from the server if it doesn't exist
577  QString session = json["session"].toString();
579 
580  if (!s)
581  {
583 
584  if (c)
585  { _pendingSession = true;
586  c->_queuedRequests[session] << this;
588  }
589  else
590  VFS::WARN("Can't queue request on non-VFS_tcp_export_client!");
591  }
592  else
593  this->_session = s;
594  }
595 }
596 
605 {
606  QJsonDocument d = QJsonDocument::fromJson( message );
607 
608  if (!d.isNull())
609  {
610  VFS_tcp_export_request *r = new VFS_tcp_export_request(origin,exportRoot);
611  r->fromJsonObject( d.object(), true );
612  return r;
613  }
614 
615  return nullptr;
616 }
617 
630 QByteArray VFS_tcp_export_request::toJson(postID id, bool ignoreSuccess, bool includeInitialPath)
631 {
632  QJsonDocument d;
633  QJsonObject o;
634 
635  //_id = id;
636 
637  o["id"] = id;
638  o["type"] = _requestType;
639  //o["originPath"] = _originPath;
640  //o["path"] = rutils::cleanPath( _path.mid(_exportRoot.length()) ); //don't want this! It's already removed by find()
641  o["path"] = rutils::cleanPath(_path);
642  o["user"] = _user;
643 
644  if (includeInitialPath)
645  o["initialPath"] = _initialPath;
646 
647  //so we're not sending back the same data we received, or useless data if there's a failure
648  if (_success || ignoreSuccess)
649  {
650  if (!_metadata.empty())
651  o["metadata"] = _metadata;
652 
653  if (!_data.isEmpty())
654  o["data"] = _data.object();
655 
656  if (!_rawData.isEmpty())
657  o["rawdata"] = QJsonValue::fromVariant( _rawData.toBase64() );
658  }
659  else
660  o["reason"] = _reason;
661 
662  o["success"] = _success;
663 
664  //o["session"] = ??
665 
666  //if this request is a diff, it's likely that the diff originated from a submit request
667  //record the id of the request so _notifyExceptions can be updated on the receiving side
668  if (id == POST_ID_DIFF)
669  o["sourceID"] = _id;
670 
671  d.setObject(o);
672  return d.toJson();
673 }
674 
685 {
686  //VFS_request *r = new VFS_tcp_export_request(VFS_request::diff,origin,_path,_user,_data,_metadata);
687  VFS_tcp_client *c = dynamic_cast<VFS_tcp_client *>(_origin);
690  r->_origin = origin;
691  r->_path = _path;
692  r->_initialPath = _path;
693  r->_user = _user;
694  r->_data = _data;
695  r->_metadata = _metadata;
696 
697  r->_id = _id;
698 
700  //r->_prefixPath = _prefixPath;
701  //r->_notifyExceptions = _notifyExceptions; //we don't want this! It needs to be a new request.
702  r->_originPath = originPath;
703 
704 
705  return r;
706 }
707 
713 {
714  VFS_tcp_client *c = dynamic_cast<VFS_tcp_client *>(_origin);
715 
716  if (c)
717  {
718  if (!_success)
720  VFS::WARN( QString("VFS_tcp_export_request id %1 (%3) on '%2' has failed without providing a reason... reporting error to mount.").arg(_id).arg(_initialPath).arg(VFS_request::requestTypeStrings[_requestType]), 0, _user );
721  //VFS::WARN( _reason, 0, _user );
722  }
723 
724  QByteArray response = toJson(_id);
725 
726  #ifdef SHOW_JSON
727  printf("VFS_tcp_export_request sends: %s\n",qUtf8Printable(response));
728  #endif
729 
730  #ifdef COMPRESS_TCP_MOUNT
731  response = qCompress(response);
732  #endif
733 
734  c->writeMessage(response);
735  }
736  else
737  // VFS::WARN( QString("VFS_tcp_export_request could not cast to client... failing.") );
739 }
740 
quint16 postID
Definition: VFS_node.h:24
#define POST_ID_CODE_DIRECTORY
Definition: VFS_node.h:20
#define POST_ID_SESSION_DATA
Definition: VFS_node.h:18
#define POST_ID_PING
Definition: VFS_node.h:17
#define POST_ID_NONE
Definition: VFS_node.h:16
#define POST_ID_DIFF
Definition: VFS_node.h:19
static bool checkAllowAccess(VFS_session *s, QString path, QString feature="")
Check if a session has access to a resource.
Definition: VFS_acl.cpp:407
static QStringList fetchACLPaths()
Fetch the VFS path to each registered ACL file.
Definition: VFS_acl.cpp:597
static QJsonObject codeDirectory(QString &error)
Gather and return a directory of code namespaces served by this VFS instance.
static VFS_request * code(VFS_request *r)
Resolve a request for code.
VFS_node is the base class from which all other VFS_node classes derive.
Definition: VFS_node.h:143
virtual void issueRequest(VFS_request *t)
A convenience function.
Definition: VFS_node.cpp:1933
void unmounted(VFS_node *self)
Emitted when a node is unmount()ed.
void diff(VFS_node *origin, VFS_request *t)
Emit a diff, which will trigger notifySubscribers() for a mounted node.
QString className()
Return the class name of a node.
Definition: VFS_node.cpp:2039
QMutex _lock
A recursive mutex that is local to this node.
Definition: VFS_node.h:178
friend class VFS_session
Definition: VFS_node.h:146
virtual void applyDiff(VFS_request *r)
Apply a diff received via subscription.
Definition: VFS_node.cpp:1463
virtual void receiveResponse(VFS_request *t)
Once a VFS_request has been completed, a response will be issued back to its _origin.
Definition: VFS_node.cpp:1870
The base class for all requests between nodes.
Definition: VFS_node.h:54
static const char * requestTypeStrings[]
A printable string for each request type.
Definition: VFS_node.h:127
@ diff
send a diff (7)
Definition: VFS_node.h:71
@ read
read full contents (4)
Definition: VFS_node.h:68
@ unsubscribe
unsubscribe from a path (10)
Definition: VFS_node.h:74
@ metadata
read metadata (6)
Definition: VFS_node.h:70
@ write
write full contents (5)
Definition: VFS_node.h:69
@ code
request code from a node (15)
Definition: VFS_node.h:79
@ codeDirectory
request a listing of code served by a node (16)
Definition: VFS_node.h:80
@ subscribe
subscribe to a path (9)
Definition: VFS_node.h:73
@ submit
apply a diff (8)
Definition: VFS_node.h:72
VFS_node * _responder
the receiver of the request
Definition: VFS_node.h:92
VFS_node * _origin
the origin of the request
Definition: VFS_node.h:89
QByteArray _rawData
the request payload, but raw data
Definition: VFS_node.h:103
bool hasCallback()
Check if this request has a callback set.
Definition: VFS_node.cpp:336
requestType _requestType
the action this request is performing or requesting
Definition: VFS_node.h:87
QString _initialPath
the target path when the request was made (relative to the responder)
Definition: VFS_node.h:93
QStringList _prefixPath
the prefix elements found while searching for the target
Definition: VFS_node.h:94
QString _user
who initiated this request, mostly for logging
Definition: VFS_node.h:106
virtual void fromJsonObject(QJsonObject json, bool includeInitialPath=false)
Deserialize a JSON string into a VFS_request.
Definition: VFS_node.cpp:466
virtual void execute()
after a request has completed, a request may have a special execute function.
Definition: VFS_node.cpp:255
VFS_session * _session
The session associated with this request. This is an optional value, and care should be taken to chec...
Definition: VFS_node.h:105
QString _reason
if something (probably bad) happened, this is the reason
Definition: VFS_node.h:108
QString _path
the target path remnant... the remaining path element once the request has found its target
Definition: VFS_node.h:95
QString _originPath
the subpath of the origin node
Definition: VFS_node.h:90
bool _success
if the request was successfully completed
Definition: VFS_node.h:107
QJsonDocument _data
the request payload
Definition: VFS_node.h:102
virtual QByteArray toJson(postID id=0, bool ignoreSuccess=false, bool includeInitialPath=false)
Serialize this request.
Definition: VFS_node.cpp:415
QJsonObject _metadata
the request payload
Definition: VFS_node.h:101
The VFS_session object represents a single session.
Definition: VFS_session.h:14
void error(QAbstractSocket::SocketError)
Emitted when a socket error occurs.
void connected()
Emitted when a connection has been made.
void readyMessage(QByteArray message)
Emitted when a message is ready for processing.
virtual void writeMessage(QByteArray data)
DOCME.
The socket client created by VFS_tcp_export.
QByteArray _icon
An icon that can override the icon provided by the shared node.
QMap< QString, QList< VFS_tcp_export_request * > > _queuedRequests
The requests that have been queued, per session id, due to a session definition request.
virtual void applyDiff(VFS_request *t)
virtual void receiveMessage(QByteArray message)
virtual void receiveResponse(VFS_request *t)
VFS_tcp_export_client(QTcpSocket *socket, QString exportRoot, bool ssl=false, QSslConfiguration sslConfiguration=QSslConfiguration(), QByteArray icon="")
virtual void removeSourcePathMap(VFS_node *n)
Remove a _sourcePathMap entry, if found.
virtual void addSourcePathMap(VFS_node *source, QString path)
Add a VFS_tcp_export_client::_sourcePathMap entry for a path from a client's perspective to a VFS_nod...
virtual void sendCodeDirectory()
DOCME.
QMap< VFS_node *, QString > _sourcePathMap
Map between nodes and subscription paths.
QString _exportRoot
The VFS path to export.
virtual void executeMessageRequest(VFS_tcp_export_request *r)
Execute a message request.
The VFS_tcp_export class needs path information to translate between mounted VFS instances.
virtual VFS_request * createDiff(VFS_node *origin, QString originPath)
VFS_tcp_export_request::createDiff.
bool _pendingSession
This request is pending a session definition.
virtual QByteArray toJson(postID id=0, bool ignoreSuccess=false, bool includeInitialPath=false)
Serialize this request.
static VFS_tcp_export_request * fromMessage(QByteArray message, QString exportRoot, VFS_tcp_client *origin)
postID _id
The ID of this request.
virtual void fromJsonObject(QJsonObject json, bool includeInitialPath=false)
Deserialize a JSON string into a VFS_request.
QString _exportRoot
The VFS node being exported.
VFS_tcp_export_request(VFS_tcp_client *origin, QString exportRoot)
virtual void execute()
DOCME.
static bool registerSession(QString id, VFS_session *session)
Register a session with the session registry.
static VFS_session * fetchSession(QString id)
Fetch a session by id.
static bool requestSession(QString id, VFS_tcp_export_client *client)
Request a session by id from a given VFS_tcp_export_client.
static VFS * root()
Return the root node of the VFS filesystem.
Definition: VFS.cpp:399
static void LOG(QString message, int level=0, QString user="server")
Send a message to the VFS::_messages VFS_stream.
Definition: VFS.cpp:209
static void ERROR(QString message, int level=0, QString user="server")
Send a message to the VFS::_errors VFS_stream.
Definition: VFS.cpp:307
static void WARN(QString message, int level=0, QString user="server")
Send a message to the VFS::_warnings VFS_stream.
Definition: VFS.cpp:258
message(m)
Change the message of an existing arrowMessage.
getter path
a getter DOCME
QString cleanPath(QString path)
Clean and normalize a VFS path.
Definition: rutils.cpp:32