remove deprecated ssh/protobuf code

This commit is contained in:
sehraf 2016-10-08 12:59:27 +02:00
parent 7cd31aa788
commit ada1cee2c8
44 changed files with 5 additions and 12091 deletions

View File

@ -1,907 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "menu/menu.h"
#include <retroshare/rsconfig.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsiface.h>
#include <iostream>
#include <time.h>
#include "util/rsstring.h"
#define MENU_DEBUG 1
/**********************************************************
* Menu Base Interface.
*/
// RsTermServer Interface.
void MenuInterface::reset(uint32_t /* chan_id */)
{
mBase->reset();
mCurrentMenu = mBase;
mInputRequired = false;
mUpdateTime = 0;
}
int MenuInterface::tick()
{
#ifdef MENU_DEBUG
std::cerr << "MenuInterface::tick()";
std::cerr << std::endl;
#endif // MENU_DEBUG
/* try to read a char */
bool haveInput = false;
uint8_t keypress;
std::string output;
uint32_t chan_id = 1; // dummy - for menu system.
int read = mComms->recv(chan_id, &keypress, 1);
#ifdef MENU_DEBUG
std::cerr << "MenuInterface::tick() read " << read << " bytes";
std::cerr << std::endl;
#endif // MENU_DEBUG
if (read == 0)
{
haveInput = false;
/* make a harmless key */
keypress = ' ';
}
else if (read == 1)
{
haveInput = true;
}
else
{
/* error, NON BLOCKING is handled by recv returning 0 */
mComms->error(chan_id, "Bad Input");
return -1;
}
/**** Main logic bit ****/
/**** slow down the updates / refresh ****/
time_t now = time(NULL);
#define UPDATE_TIME 5
if (!haveInput)
{
// If Input is Required,
if (mInputRequired)
{
std::cerr << "MenuInterface::tick() No Input & Required-No Output";
std::cerr << std::endl;
return 0;
}
// Output will just almost the same, so occasionally.
if (now < mUpdateTime + UPDATE_TIME)
{
std::cerr << "MenuInterface::tick() No Input-Slow Update";
std::cerr << std::endl;
return 0;
}
std::cerr << "MenuInterface::tick() No Input - but doing update.";
std::cerr << std::endl;
}
uint32_t rt = process(keypress, mDrawFlags, output);
mInputRequired = (rt == MENU_PROCESS_NEEDDATA);
mUpdateTime = now;
if (rt == MENU_PROCESS_QUIT)
{
return -1;
}
if (output.size() > 0)
{
mComms->send(chan_id, output);
}
return (haveInput);
}
int tailrec_printparents(Menu *m, std::string &buffer)
{
Menu *p = m->parent();
if (p)
{
tailrec_printparents(p, buffer);
}
buffer += m->ShortFnDesc();
buffer += " => ";
return 1;
}
uint32_t MenuInterface::process(char key, uint32_t drawFlags, std::string &buffer)
{
#ifdef MENU_DEBUG
std::cout << "MenuInterface::process(" << key << ")";
std::cout << std::endl;
#endif // MENU_DEBUG
/* call process on current menu */
uint32_t rt = mCurrentMenu->process(key);
bool doRedraw = true;
bool showError = false;
bool showHelp = false;
#ifdef MENU_DEBUG
std::cout << "MenuInterface::process() currentMenu says: " << rt;
std::cout << std::endl;
#endif // MENU_DEBUG
uint32_t base_rt = (rt & MENU_PROCESS_MASK);
bool needData = (rt & MENU_PROCESS_NEEDDATA);
switch(base_rt)
{
case MENU_PROCESS_NONE:
if (needData)
{
/* no redraw, this could be called many times */
doRedraw = false;
}
break;
case MENU_PROCESS_DONE:
/* no changes - operation performed, or noop */
break;
case MENU_PROCESS_ERROR:
/* Show Error at top of Page */
showError = true;
break;
case MENU_PROCESS_HELP:
/* Show Help at top of Page */
showHelp = true;
break;
case MENU_PROCESS_MENU:
/* new menu to switch to */
if (mCurrentMenu->selectedMenu())
{
std::cout << "MenuInterface::process() Switching Menus";
std::cout << std::endl;
mCurrentMenu = mCurrentMenu->selectedMenu();
}
else
{
std::cout << "MenuInterface::process() ERROR";
std::cout << " SelectedMenu == NULL";
std::cout << std::endl;
}
break;
case MENU_PROCESS_TOP:
/* switch to Base Menu */
mCurrentMenu = mBase;
break;
case MENU_PROCESS_QUIT:
return MENU_PROCESS_QUIT;
break;
}
if (drawFlags & MENU_DRAW_FLAGS_ECHO)
{
buffer += key;
}
/* now we redraw, and wait for next data */
if (!doRedraw)
{
return MENU_PROCESS_NEEDDATA;
}
/* HEADER */
for(int i = 0; i < 20; i++)
{
buffer += "\r\n";
}
/* ERROR */
if (showError)
{
mCurrentMenu->showError();
}
/* HELP */
else if (showHelp)
{
mCurrentMenu->showHelp();
}
/* MENU PAGE */
drawHeader(drawFlags, buffer);
mCurrentMenu->drawPage(drawFlags, buffer);
if (needData)
return MENU_PROCESS_NEEDDATA;
return MENU_PROCESS_NONE;
}
uint32_t MenuInterface::drawHeader(uint32_t drawFlags, std::string &buffer)
{
buffer += "=======================================================\r\n";
buffer += "Retroshare Terminal Menu V2.xxxx ======================\r\n";
unsigned int nTotal = 0;
unsigned int nConnected = 0;
rsPeers->getPeerCount(&nTotal, &nConnected, false);
uint32_t netState = rsConfig->getNetState();
std::string natState("Unknown");
switch(netState)
{
default:
case RSNET_NETSTATE_BAD_UNKNOWN:
natState = "YELLOW:Unknown";
break;
case RSNET_NETSTATE_BAD_OFFLINE:
natState = "GRAY:Offline";
break;
case RSNET_NETSTATE_BAD_NATSYM:
natState = "RED:Nasty Firewall";
break;
case RSNET_NETSTATE_BAD_NODHT_NAT:
natState = "RED:NoDht & Firewalled";
break;
case RSNET_NETSTATE_WARNING_RESTART:
natState = "YELLOW:Restarting";
break;
case RSNET_NETSTATE_WARNING_NATTED:
natState = "YELLOW:Firewalled";
break;
case RSNET_NETSTATE_WARNING_NODHT:
natState = "YELLOW:DHT Disabled";
break;
case RSNET_NETSTATE_GOOD:
natState = "GREEN:Good!";
break;
case RSNET_NETSTATE_ADV_FORWARD:
natState = "GREEN:Forwarded Port";
break;
}
float downKb = 0;
float upKb = 0;
rsConfig->GetCurrentDataRates(downKb, upKb);
rs_sprintf_append(buffer, "Friends %d / %d Network: %s\r\n",
nConnected, nTotal, natState.c_str());
rs_sprintf_append(buffer, "Down: %2.2f Up %2.2f\r\n", downKb, upKb);
std::string menuState;
tailrec_printparents(mCurrentMenu, menuState);
buffer += "Menu State: ";
buffer += menuState;
buffer += "\r\n";
buffer += "=======================================================\r\n";
return 1;
}
/**********************************************************
* Menu (Base)
*/
Menu::~Menu()
{
/* cleanup children */
mParent = NULL;
mSelectedMenu = NULL;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
delete (it->second);
}
mChildren.clear();
}
int Menu::addMenuItem(char key, Menu *child)
{
std::map<uint8_t, Menu *>::iterator it;
it = mChildren.find(key);
if (it != mChildren.end())
{
std::cout << "Menu::addMenuItem() ERROR DUPLICATE MENU ITEM";
std::cout << std::endl;
return 0;
}
mChildren[key] = child;
child->setParent(this);
return 1;
}
void Menu::reset()
{
mSelectedMenu = NULL;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
it->second->reset();
}
}
uint32_t Menu::process(char key)
{
/* try standard list ones */
uint32_t rt = std_process(key);
if (rt)
{
return rt;
}
/* now try children */
rt = process_children(key);
if (rt)
{
return rt;
}
return MENU_PROCESS_NONE;
}
uint32_t Menu::std_process(char key)
{
switch(key)
{
case MENU_KEY_QUIT:
return MENU_PROCESS_QUIT;
break;
case MENU_KEY_HELP:
return MENU_PROCESS_HELP;
break;
case MENU_KEY_TOP:
return MENU_PROCESS_TOP;
break;
case MENU_KEY_UP:
setSelectedMenu(parent());
return MENU_PROCESS_MENU;
break;
}
return MENU_PROCESS_NONE;
}
uint32_t Menu::process_children(char key)
{
std::map<uint8_t, Menu *>::iterator it;
it = mChildren.find(key);
if (it == mChildren.end())
{
return MENU_PROCESS_NONE;
}
/* have a child */
/* now return, depending on type */
switch(it->second->op())
{
case MENU_OP_NEEDDATA:
setSelectedMenu(it->second);
return MENU_PROCESS_MENU | MENU_PROCESS_NEEDDATA;
break;
case MENU_OP_SUBMENU:
setSelectedMenu(it->second);
return MENU_PROCESS_MENU;
break;
default:
case MENU_OP_INSTANT:
/* done already! */
setSelectedMenu(NULL);
return MENU_PROCESS_DONE;
break;
case MENU_OP_ERROR:
/* done already! */
setSelectedMenu(NULL);
return MENU_PROCESS_ERROR;
break;
}
}
uint32_t Menu::drawPage(uint32_t drawFlags, std::string &buffer)
{
buffer += "Universal Commands ( ";
if (!(drawFlags & MENU_DRAW_FLAGS_NOQUIT))
{
buffer += (char) MENU_KEY_QUIT;
buffer += ":Quit ";
}
buffer += (char) MENU_KEY_HELP;
buffer += ":Help ";
buffer += (char) MENU_KEY_TOP;
buffer += ":Top ";
buffer += (char) MENU_KEY_UP;
buffer += ":Up ";
buffer += ")";
buffer += "\r\n";
buffer += "Specific Commands ( ";
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
buffer += (char) it->first;
buffer += ":";
buffer += it->second->ShortFnDesc();
buffer += " ";
}
buffer += ")";
buffer += "\r\n";
return 1;
}
uint32_t Menu::drawHelpPage(uint32_t drawFlags, std::string &buffer)
{
std::cout << "Menu Help: Universal Commands are:";
std::cout << std::endl;
std::cout << "\tKey: " << (char) MENU_KEY_QUIT << " => Quit";
std::cout << std::endl;
std::cout << "\tKey: " << (char) MENU_KEY_HELP << " => Help";
std::cout << std::endl;
std::cout << "\tKey: " << (char) MENU_KEY_TOP << " => Top Menu";
std::cout << std::endl;
std::cout << "\tKey: " << (char) MENU_KEY_UP << " => Up a Menu";
std::cout << std::endl;
std::cout << "Specific Commands are:";
std::cout << std::endl;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
std::cout << "\tKey: " << (char) it->first << " => ";
std::cout << it->second->ShortFnDesc();
std::cout << std::endl;
}
return 1;
}
/**********************************************************
* Menu List (Base)
*/
uint32_t MenuList::drawPage(uint32_t drawFlags, std::string &buffer)
{
Menu::drawPage(drawFlags, buffer);
buffer += "Navigation Commands (";
buffer += (char) MENULIST_KEY_NEXT;
buffer += ":Next ";
buffer += (char) MENULIST_KEY_PREV;
buffer += ":Prev ";
buffer += ")";
buffer += "\r\n";
rs_sprintf_append(buffer, "MenuList::Internals ListSize: %d, SelectIdx: %d Cursor: %d\r\n",
getListCount(), mSelectIdx, mCursor);
int i = 0;
int listCount = getListCount();
int startCount = mCursor + 1;
int endCount = mCursor + 10;
if (endCount > listCount)
{
endCount = listCount;
}
if (mSelectIdx >= 0)
{
rs_sprintf_append(buffer, "Current Selection Idx: %d : ", mSelectIdx);
std::string desc;
if (getEntryDesc(mSelectIdx, desc) & (desc != ""))
{
buffer += desc;
}
else
{
buffer += "Missing Description";
}
buffer += "\r\n";
}
else
{
buffer += "No Current Selection: Use 0 - 9 to choose an Entry";
buffer += "\r\n";
}
rs_sprintf_append(buffer, "Showing %d to %d of %d Entries\r\n",
startCount, endCount, listCount);
std::list<std::string>::iterator it;
for (it = mList.begin(); it != mList.end(); it++, i++)
{
int curIdx = i - mCursor;
if ((curIdx >= 0) && (curIdx < 10))
{
if (i == mSelectIdx)
{
rs_sprintf_append(buffer, "SELECTED (%d) ", curIdx);
}
else
{
rs_sprintf_append(buffer, "\t(%d) ", curIdx);
}
std::string desc;
if (getEntryDesc(i, desc) & (desc != ""))
{
buffer += desc;
}
else
{
buffer += *it;
buffer += " => ";
buffer += "Missing Description";
}
buffer += "\r\n";
}
}
buffer += "\r\n";
buffer += "Make Your Choice > ";
return 1;
}
uint32_t MenuList::drawHelpPage(uint32_t drawFlags, std::string &buffer)
{
Menu::drawHelpPage(drawFlags, buffer);
std::cout << "MenuList Help: Navigation Commands are:";
std::cout << std::endl;
//std::cout << "\tKey: " << (char) MENULIST_KEY_LIST << " => List";
//std::cout << std::endl;
std::cout << "\tKey: " << (char) MENULIST_KEY_NEXT << " => Next Page";
std::cout << std::endl;
std::cout << "\tKey: " << (char) MENULIST_KEY_PREV << " => Prev Page";
std::cout << std::endl;
std::cout << "MenuList::drawPage() Internal Details";
std::cout << std::endl;
std::cout << "List Size: " << getListCount();
std::cout << std::endl;
std::cout << "SelectIdx: " << mSelectIdx;
std::cout << std::endl;
std::cout << "Cursor: " << mCursor;
std::cout << std::endl;
return 1;
}
void MenuList::reset()
{
Menu::reset(); // clears children too.
mList.clear();
mSelectIdx = -1;
mCursor = 0;
}
uint32_t MenuList::op()
{
mList.clear();
mSelectIdx = -1;
mCursor = 0;
return MENU_OP_ERROR; // SUBMENU -> only for inherited classes;
}
uint32_t MenuList::getListCount()
{
return mList.size();
}
int MenuList::getCurrentKey(std::string &key)
{
return getListEntry(mSelectIdx, key);
}
int MenuList::getCurrentIdx(int &idx)
{
idx = mSelectIdx;
return 1;
}
int MenuList::getListEntry(int idx, std::string &key)
{
if (idx < 0)
{
return MENU_ENTRY_NONE;
}
std::list<std::string>::iterator it;
int i = 0;
for (it = mList.begin(); (i < idx) && (it != mList.end()); it++, i++) ;
if (it != mList.end())
{
key = *it;
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuList::getEntryDesc(int idx, std::string &desc)
{
desc = "Entry Description";
return MENU_ENTRY_OKAY;
}
uint32_t MenuList::process(char key)
{
/* try standard list ones */
uint32_t rt = Menu::process(key);
if (rt)
{
return rt;
}
rt = list_process(key);
return rt;
}
uint32_t MenuList::list_process(char key)
{
if (((key >= '0') && (key <= '9')) ||
((key >= 'a') && (key <= 'f')))
{
int idx = 0;
/* select index */
if ((key >= '0') && (key <= '9'))
{
idx = key - '0';
}
else
{
idx = key - 'a' + 9;
}
/* now change selection, dependent on pagination */
if (mCursor + idx < getListCount())
{
mSelectIdx = mCursor + idx;
std::cout << "MenuList::list_process() Selected Idx: " << mSelectIdx;
std::cout << std::endl;
}
else
{
std::cout << "MenuList::list_process() Idx Out of Range";
std::cout << std::endl;
}
return MENU_PROCESS_DONE; /* ready for next key stroke */
}
switch(key)
{
case MENULIST_KEY_LIST:
/* send a list to output */
return MENU_PROCESS_DONE; /* ready for next key stroke */
break;
case MENULIST_KEY_NEXT:
/* shift to next page */
if (mCursor + 10 < getListCount())
{
mCursor += 10;
}
return MENU_PROCESS_DONE;
break;
case MENULIST_KEY_PREV:
/* shift to prev page */
if (((int) mCursor) - 10 >= 0)
{
mCursor -= 10;
}
return MENU_PROCESS_DONE;
break;
}
return MENU_PROCESS_NONE;
}
uint32_t MenuOpBasicKey::op_basic(std::string key)
{
parent()->setErrorMessage("MenuOpBasicKey Not Overloaded Correctly");
return MENU_OP_ERROR;
}
uint32_t MenuOpBasicKey::op()
{
std::string key;
Menu *Parent=parent();
MenuList *p = dynamic_cast<MenuList *>(Parent);
if (!p)
{
if (Parent)
{
Parent->setErrorMessage("Invalid (Basic) Menu Structure");
}
return MENU_OP_ERROR;
}
if (p->getCurrentKey(key))
{
return op_basic(key);
}
if (Parent)
{
Parent->setErrorMessage("Invalid Current Keys");
}
return MENU_OP_ERROR;
}
uint32_t MenuOpTwoKeys::op_twokeys(std::string parentkey, std::string key)
{
parent()->setErrorMessage("MenuOpTwoKeys Not Overloaded Correctly");
return MENU_OP_ERROR;
}
uint32_t MenuOpTwoKeys::op()
{
std::string parentkey;
std::string key;
Menu *Parent=parent();
MenuList *p = dynamic_cast<MenuList *>(Parent);
Menu *grandParent=parent()->parent();
MenuList *gp = dynamic_cast<MenuList *>(grandParent);
if ((!gp) || (!p))
{
if (Parent)
{
Parent->setErrorMessage("Invalid (TwoKeys) Menu Structure");
}
return MENU_OP_ERROR;
}
if ((gp->getCurrentKey(parentkey)) && (p->getCurrentKey(key)))
{
return op_twokeys(parentkey, key);
}
if (Parent)
{
Parent->setErrorMessage("Invalid Current Keys");
}
return MENU_OP_ERROR;
}
/**********************************************************
* Menu Op Line Input (Base)
*/
uint32_t MenuOpLineInput::op()
{
return MENU_OP_NEEDDATA;
}
uint32_t MenuOpLineInput::process_lines(std::string input)
{
std::cout << "MenuOpLineInput::process_lines() => SHOULD BE OVERLOADED";
std::cout << "Input Was: ";
std::cout << std::endl;
std::cout << "==================================================";
std::cout << std::endl;
std::cout << input;
std::cout << "==================================================";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
uint32_t MenuOpLineInput::process(char key)
{
/* read data in and add to buffer */
mInput += key;
if ((key != '\n') && (key != '\r'))
{
return MENU_PROCESS_NEEDDATA;
}
uint32_t rt = process_lines(mInput);
switch(rt)
{
case MENU_PROCESS_NEEDDATA:
break;
case MENU_PROCESS_ERROR:
std::cout << "MenuOpLineInput::process() => ERROR";
std::cout << std::endl;
case MENU_PROCESS_DONE:
/* cleanup for next command */
std::cout << "MenuOpLineInput::process() Clearing Buffer";
std::cout << std::endl;
mInput.clear();
/* go back to parent menu */
rt = MENU_PROCESS_MENU;
setSelectedMenu(parent());
break;
}
return rt;
}

View File

@ -1,249 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RSNOGUI_MENU_H
#define RSNOGUI_MENU_H
#include <inttypes.h>
#include <string>
#include <map>
#include <list>
#include "rpcsystem.h" // generic processing command.
#define MENU_PROCESS_MASK 0x0fff
#define MENU_PROCESS_NONE 0x0000
#define MENU_PROCESS_TOP 0x0001
#define MENU_PROCESS_MENU 0x0002
#define MENU_PROCESS_DONE 0x0004
#define MENU_PROCESS_QUIT 0x0008
#define MENU_PROCESS_SHUTDOWN 0x0010
#define MENU_PROCESS_HELP 0x0020
#define MENU_PROCESS_ERROR 0x0040
#define MENU_PROCESS_NEEDDATA 0x1000 // Able to be OR'd with ANOTHER CASE.
#define MENU_KEY_QUIT 'Q'
#define MENU_KEY_HELP 'h'
#define MENU_KEY_TOP 't'
#define MENU_KEY_REPEAT 'r'
#define MENU_KEY_UP 'u'
#define MENULIST_KEY_LIST 'l' // Don't need this.
#define MENULIST_KEY_NEXT 'n'
#define MENULIST_KEY_PREV 'p'
#define MENU_OP_ERROR 0
#define MENU_OP_INSTANT 1
#define MENU_OP_SUBMENU 2
#define MENU_OP_NEEDDATA 3
#define MENU_ENTRY_NONE 0
#define MENU_ENTRY_OKAY 1
#define MENU_DRAW_FLAGS_STD 0
#define MENU_DRAW_FLAGS_HTML 1
#define MENU_DRAW_FLAGS_ECHO 2
#define MENU_DRAW_FLAGS_NOQUIT 4
class Menu;
class Screen;
class Menu
{
public:
Menu(std::string shortDesc): mParent(NULL), mShortDesc(shortDesc) { return; }
virtual ~Menu();
void setParent(Menu *p) { mParent = p; }
Menu *parent() { return mParent; }
Menu *selectedMenu() { return mSelectedMenu; }
int addMenuItem(char key, Menu *child);
virtual void reset();
virtual uint32_t op() { return MENU_OP_SUBMENU; } /* what type is it? returns SUBMENU, INSTANT, NEEDINPUT */
virtual uint32_t process(char key);
// THE BIT STILL TO BE DEFINED!
std::string ShortFnDesc() { return mShortDesc; }// Menu Text (for Help).
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer);
//virtual std::string menuText() = 0;
//virtual std::string menuHelp() = 0;
virtual void setOpMessage(std::string msg) { return; }
virtual void setErrorMessage(std::string msg) { return; }
virtual uint32_t showError() { return 1; } //= 0;
virtual uint32_t showHelp() { return 1; } //= 0;
protected:
virtual uint32_t std_process(char key); /* for H/T/R/Q */
virtual uint32_t process_children(char key); /* check for children ops */
void setSelectedMenu(Menu *m) { mSelectedMenu = m; }
private:
Menu *mParent;
Menu *mSelectedMenu;
std::string mShortDesc;
std::map<uint8_t, Menu *> mChildren;
};
/**********************************************************
* Generic MenuList... provides a list of KEYS, which
* can be iterated through.
*
* Maintains: List + Current + Next / Previous.
* Single Child, which is called for all.
*/
class MenuList: public Menu
{
public:
MenuList(std::string shortDesc): Menu(shortDesc) { return; }
virtual void reset();
virtual uint32_t op();
virtual uint32_t process(char key);
// List Info.
uint32_t getListCount();
int getCurrentIdx(int &idx);
int getCurrentKey(std::string &key);
int getListEntry(int idx, std::string &key);
virtual int getEntryDesc(int idx, std::string &desc);
// Output.
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer);
protected:
virtual uint32_t list_process(char key);
int32_t mSelectIdx; /* -1 => none */
uint32_t mCursor; /* offset for list display */
std::list<std::string> mList;
private:
};
class MenuOpBasicKey: public Menu
{
public:
MenuOpBasicKey(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
protected:
virtual uint32_t op_basic(std::string key);
};
class MenuOpTwoKeys: public Menu
{
public:
MenuOpTwoKeys(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
protected:
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
/* Read input, line by line...
*/
class MenuOpLineInput: public Menu
{
public:
MenuOpLineInput(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
virtual uint32_t process(char key);
protected:
virtual uint32_t process_lines(std::string input);
std::string mInput;
};
#if 0
class MenuInterface: public RsTermServer
{
public:
MenuInterface(Menu *b, uint32_t drawFlags) :mCurrentMenu(b), mBase(b), mDrawFlags(drawFlags), mInputRequired(false) { return; }
uint32_t process(char key, uint32_t drawFlags, std::string &buffer);
uint32_t drawHeader(uint32_t drawFlags, std::string &buffer);
// RsTermServer Interface.
virtual void reset();
virtual int tick(bool haveInput, char keypress, std::string &output);
private:
Menu *mCurrentMenu;
Menu *mBase;
uint32_t mDrawFlags;
bool mInputRequired;
};
#endif
class MenuInterface: public RpcSystem
{
public:
MenuInterface(RpcComms *c, Menu *b, uint32_t drawFlags)
:mComms(c), mCurrentMenu(b), mBase(b), mDrawFlags(drawFlags), mInputRequired(false) { return; }
uint32_t process(char key, uint32_t drawFlags, std::string &buffer);
uint32_t drawHeader(uint32_t drawFlags, std::string &buffer);
// RsSystem Interface.
virtual void reset(uint32_t chan_id);
virtual int tick();
private:
RpcComms *mComms;
Menu *mCurrentMenu;
Menu *mBase;
uint32_t mDrawFlags;
bool mInputRequired;
time_t mUpdateTime;
};
#endif

View File

@ -1,833 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include <retroshare/rspeers.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rsturtle.h>
#include "util/rsstring.h"
#include "util/rsdir.h"
#include "menu/menus.h"
// Can't use: Q, H, T, U (universal)
// or L, N, P (list ops).
// or 0-9,a-f (list selection).
#define MENU_FRIENDS_KEY_ADD 'a'
#define MENU_FRIENDS_KEY_VIEW 'v'
#define MENU_FRIENDS_KEY_REMOVE 'd'
#define MENU_FRIENDS_KEY_CHAT 'c'
#define MENU_TRANSFER_KEY_STOP 's'
#define MENU_TRANSFER_KEY_CANCEL 'c'
#define MENU_SEARCH_KEY_ADD 'a'
#define MENU_SEARCH_KEY_REMOVE 'd'
#define MENU_SEARCH_KEY_VIEW 'v'
#define MENU_SEARCH_KEY_DOWNLOAD 'g'
#define MENU_FORUMS_KEY_ADD 'a'
#define MENU_FORUMS_KEY_VIEW 'v'
#define MENU_FORUMS_KEY_REMOVE 'd'
#define MENU_FORUMS_KEY_CHAT 'c'
#define MENU_SHARED_KEY_EXPAND 'e'
#define MENU_SHARED_KEY_UNSHARE 's'
#define MENU_SHARED_KEY_ADD 'a'
#define MENU_SHARED_KEY_PUBLIC 'c'
#define MENU_SHARED_KEY_BROWSABLE 'b'
#define MENU_TOPLEVEL_KEY_FRIENDS 'f'
#define MENU_TOPLEVEL_KEY_NETWORK 'w'
#define MENU_TOPLEVEL_KEY_TRANSFER 'd'
#define MENU_TOPLEVEL_KEY_SEARCH 's'
#define MENU_TOPLEVEL_KEY_FORUMS 'o'
#define MENU_TOPLEVEL_KEY_SHARED 'k' //If you know of a key which fits better, just change it ;-)
#define MENU_TOPLEVEL_KEY_UPLOADS 'e'
Menu *CreateMenuStructure(NotifyTxt *notify)
{
/* construct Friends Menu */
MenuList *friends = new MenuListFriends();
// No Friends Operations Completed Yet!
//friends->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd());
//friends->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail());
//friends->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove());
//friends->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat());
MenuList *network = new MenuListNetwork();
MenuList *transfers = new MenuListTransfer();
//transfers->addMenuItem(MENU_TRANSFER_KEY_STOP, new MenuOpTransferStop());
transfers->addMenuItem(MENU_TRANSFER_KEY_CANCEL, new MenuOpTransferCancel());
MenuList *search = new MenuListSearch(notify);
MenuList *searchlist = new MenuListSearchList(notify);
search->addMenuItem(MENU_SEARCH_KEY_ADD, new MenuOpSearchNew(notify));
//search->addMenuItem(MENU_SEARCH_KEY_REMOVE, new MenuOpSearchDelete());
search->addMenuItem(MENU_SEARCH_KEY_VIEW, searchlist);
searchlist->addMenuItem(MENU_SEARCH_KEY_DOWNLOAD, new MenuOpSearchListDownload());
// Forums - TODO.
//MenuList *forums = new MenuListForums();
//forums->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd());
//forums->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail());
//forums->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove());
//forums->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat());
// Shared folders Menu
MenuList *shared = new MenuListShared();
shared->addMenuItem(MENU_SHARED_KEY_ADD , new MenuListSharedAddShare());
shared->addMenuItem(MENU_SHARED_KEY_UNSHARE , new MenuListSharedUnshare());
shared->addMenuItem(MENU_SHARED_KEY_PUBLIC , new MenuListSharedTogglePublic());
shared->addMenuItem(MENU_SHARED_KEY_BROWSABLE , new MenuListSharedToggleBrowsable());
/* Top Level Menu */
Menu *tlm = new Menu("Top Level Menu");
tlm->addMenuItem(MENU_TOPLEVEL_KEY_FRIENDS, friends);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_NETWORK, network);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_TRANSFER, transfers);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_SEARCH, search);
//tlm->addMenuItem(MENU_TOPLEVEL_KEY_FORUMS, forums);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_SHARED, shared);
return tlm;
}
/************
* Friends Menu
*/
uint32_t MenuListFriends::op()
{
MenuList::op();
rsPeers->getGPGAcceptedList(mList);
//rsPeers->getGPGValidList(mList);
return MENU_OP_SUBMENU;
}
int MenuListFriends::getEntryDesc(int idx, std::string &desc)
{
std::string gpgId;
if (!getListEntry(idx, gpgId))
{
/* error */
return 0;
}
RsPeerDetails details;
if (rsPeers->getPeerDetails(gpgId, details))
{
if (details.accept_connection)
{
desc = "Friend: ";
}
else
{
desc = "Neighbour: ";
}
desc += "<" + gpgId + "> ";
desc += details.name;
}
return 1;
}
uint32_t MenuListNetwork::op()
{
MenuList::op();
rsPeers->getGPGValidList(mList);
//rsPeers->getGPGAcceptedList(mList);
return MENU_OP_SUBMENU;
}
uint32_t MenuOpFriendsAdd::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsViewDetail::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsRemove::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsChat::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
/************
* Transfer Menu
*/
uint32_t MenuListTransfer::op()
{
MenuList::op();
/* load friend list*/
rsFiles->FileDownloads(mList);
return MENU_OP_SUBMENU;
}
int MenuListTransfer::getEntryDesc(int idx, std::string &desc)
{
std::string hash;
if (!getListEntry(idx, hash))
{
std::cout << "MenuListTransfer::getEntryDesc() No ListEntry";
std::cout << std::endl;
return 0;
}
FileInfo info;
if (!rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info))
{
std::cout << "MenuListTransfer::getEntryDesc() No FileDetails";
std::cout << std::endl;
return 0;
}
float frac = 100.0 * (float) info.transfered / info.size;
if (frac != 1.0)
{
if (info.tfRate > 0)
{
rs_sprintf(desc, "<%s> Downloading %3.2f%% from %d Peers @%3.1fKB/s. Name: %s",
info.hash.c_str(), frac, info.peers.size(), info.tfRate, info.fname.c_str());
}
else
{
rs_sprintf(desc, "<%s> Stalled %3.2f%% Name: %s",
info.hash.c_str(), frac, info.fname.c_str());
}
}
else
{
rs_sprintf(desc, "<%s> Done! Name: %s", info.hash.c_str(), info.fname.c_str());
}
return MENU_OP_INSTANT;
}
uint32_t MenuOpTransferStop::op_basic(std::string key)
{
rsFiles->FileCancel(key);
parent()->setOpMessage("Stopped Transfer");
return MENU_OP_INSTANT;
}
uint32_t MenuOpTransferCancel::op_basic(std::string key)
{
rsFiles->FileCancel(key);
parent()->setOpMessage("Stopped Transfer");
return MENU_OP_INSTANT;
}
/************
* Search Menu
*/
uint32_t MenuListSearch::op()
{
mSelectIdx = -1;
mCursor = 0;
/* Don't reset List -> done dynamically */
return MENU_OP_SUBMENU;
}
int MenuListSearch::getEntryDesc(int idx, std::string &desc)
{
std::string strSearchId;
if (!getListEntry(idx, strSearchId))
{
/* error */
return 0;
}
std::map<std::string, std::string>::iterator it;
std::map<std::string, uint32_t>::iterator sit;
it = mSearchTerms.find(strSearchId);
sit = mSearchIds.find(strSearchId);
if ((it == mSearchTerms.end()) || (sit == mSearchIds.end()))
{
/* error */
return 0;
}
rs_sprintf(desc, "Search(\"%s\") Found %d matches so far",
it->second.c_str(), mNotify->getSearchResultCount(sit->second));
return 1;
}
int MenuListSearch::getCurrentSearchId(uint32_t &id)
{
std::string strSearchId;
if (!getListEntry(mSelectIdx, strSearchId))
{
/* error */
return 0;
}
std::map<std::string, uint32_t>::iterator sit;
sit = mSearchIds.find(strSearchId);
if (sit == mSearchIds.end())
{
/* error */
return 0;
}
id = sit->second;
return 1;
}
int MenuListSearch::storeSearch(uint32_t searchId, std::string match_string)
{
std::cout << "MenuListSearch::storeSearch(" << searchId << " => ";
std::cout << match_string;
std::cout << std::endl;
std::string strSearchId;
rs_sprintf(strSearchId, "%lu", searchId);
mList.push_back(strSearchId);
mSearchTerms[strSearchId] = match_string;
mSearchIds[strSearchId] = searchId;
return 1;
}
int MenuListSearch::removeSearch(std::string strSearchId)
{
std::cout << "MenuListSearch::removeSearch(" << strSearchId << ")";
std::cout << std::endl;
std::map<std::string, uint32_t>::iterator it;
it = mSearchIds.find(strSearchId);
if (it != mSearchIds.end())
{
/* cancel search */
// CAN'T DO!!!
/* clear results from Notify Collector */
mNotify->clearSearchId(it->second);
/* cleanup local maps */
mSearchIds.erase(it);
/* cleanup terms maps (TODO) */
}
return 1;
}
uint32_t MenuOpSearchNew::drawPage(uint32_t drawFlags, std::string &buffer)
{
buffer += "Enter New Search Term > ";
return 1;
}
uint32_t MenuOpSearchNew::process_lines(std::string input)
{
/* launch search */
if (input.size() < 4)
{
std::cout << "MenuOpSearchNew::process_lines() ERROR Input too small";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
std::string search = input.substr(0, input.size() - 1); // remove \n.
uint32_t searchId = (uint32_t) rsTurtle->turtleSearch(search);
mNotify->collectSearchResults(searchId);
/* store request in parent */
MenuListSearch *ms = dynamic_cast<MenuListSearch *>(parent());
if (ms)
{
ms->storeSearch(searchId, search);
}
return MENU_PROCESS_DONE;
}
uint32_t MenuOpSearchDelete::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuListSearchList::op()
{
MenuList::op();
return refresh();
}
uint32_t MenuListSearchList::refresh()
{
Menu* p = parent();
MenuListSearch *mls = dynamic_cast<MenuListSearch *>(p);
if (!mls)
{
std::cout << "MenuListSearchList::refresh() mls not there";
std::cout << std::endl;
return MENU_OP_ERROR;
}
/* load friend list*/
mList.clear();
uint32_t searchId;
if (!mls->getCurrentSearchId(searchId))
{
std::cout << "MenuListSearchList::refresh() currentIdx invalid";
std::cout << std::endl;
return MENU_OP_ERROR;
}
std::cout << "MenuListSearchList::refresh() searchId: " << searchId;
std::cout << std::endl;
std::list<TurtleFileInfo>::iterator it;
mNotify->getSearchResults(searchId, mSearchResults);
/* convert into useful list */
for(it = mSearchResults.begin(); it != mSearchResults.end(); it++)
{
mList.push_back(it->hash);
}
mSelectIdx = -1;
mCursor = 0;
return MENU_OP_SUBMENU;
}
int MenuListSearchList::getEntryDesc(int idx, std::string &desc)
{
std::list<TurtleFileInfo>::iterator it;
int i = 0;
for (it = mSearchResults.begin();
(i < idx) && (it != mSearchResults.end()); it++, i++) ;
if (it != mSearchResults.end())
{
rs_sprintf(desc, "<%s> Size: %llu Name:%s",
it->hash.c_str(), it->size, it->name.c_str());
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuListSearchList::downloadSelected()
{
if (mSelectIdx < 0)
{
std::cout << "MenuListSearchList::downloadSelected() Invalid Selection";
std::cout << std::endl;
return MENU_ENTRY_NONE;
}
std::list<TurtleFileInfo>::iterator it;
int i = 0;
for (it = mSearchResults.begin();
(i < mSelectIdx) && (it != mSearchResults.end()); it++, i++) ;
if (it != mSearchResults.end())
{
std::list<std::string> srcIds;
if (rsFiles -> FileRequest(it->name, it->hash, it->size,
"", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds))
{
std::cout << "MenuListSearchList::downloadSelected() Download Started";
std::cout << std::endl;
}
else
{
std::cout << "MenuListSearchList::downloadSelected() Error Starting Download";
std::cout << std::endl;
}
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
uint32_t MenuOpSearchListDownload::op_basic(std::string key)
{
Menu* p = parent();
MenuListSearchList *mlsl = dynamic_cast<MenuListSearchList *>(p);
if (!mlsl)
{
std::cout << "MenuOpSearchListDownload::op_basic() ERROR";
std::cout << std::endl;
return MENU_OP_ERROR;
}
mlsl->downloadSelected();
return MENU_OP_INSTANT;
}
/************
* Forums Menu
*/
uint32_t MenuListForums::op()
{
/* load friend list*/
mList.clear();
rsPeers->getGPGAcceptedList(mList);
mSelectIdx = 0;
return MENU_OP_SUBMENU;
}
int MenuListForums::getEntryDesc(int idx, std::string &desc)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumDetails::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumSubscribe::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumUnsubscribe::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumCreate::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuListForumMsgs::op()
{
/* load friend list*/
mList.clear();
rsPeers->getGPGAcceptedList(mList);
mSelectIdx = 0;
return MENU_OP_SUBMENU;
}
int MenuListForumMsgs::getEntryDesc(int idx, std::string &desc)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgView::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgReply::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgWrite::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}
/************
* Shared folders Menu
*/
uint32_t MenuListShared::op()
{
MenuList::op();
mList.clear();
std::list<SharedDirInfo> dirs;
rsFiles->getSharedDirectories(dirs);
std::list<SharedDirInfo>::iterator it;
for(it = dirs.begin(); it != dirs.end(); it++)
{
mList.push_back ((*it).virtualname) ;
}
return MENU_OP_SUBMENU;
}
int MenuListShared::getEntryDesc(int idx, std::string &desc)
{
std::list<SharedDirInfo> dirs;
rsFiles->getSharedDirectories(dirs);
std::list<SharedDirInfo>::iterator it;
std::string shareflag;
int i=0;
for (it = dirs.begin(); (i < idx) && (it != dirs.end()); it++, i++);
if (it != dirs.end())
{
bool networkwide = (it->shareflags & DIR_FLAGS_NETWORK_WIDE_OTHERS);
bool browsable = (it->shareflags & DIR_FLAGS_BROWSABLE_OTHERS);
if (networkwide && browsable)
{
shareflag = "networkwide - browsable";
}
else if (browsable)
{
shareflag = "private - browsable";
}
else if (networkwide)
{
shareflag = "networkwide - anonymous";
}
else
{
shareflag = "not shared";
}
rs_sprintf(desc, "Path: %s Share Type:%s", it->filename.c_str(), shareflag.c_str());
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuListShared::unshareSelected()
{
if (mSelectIdx < 0)
{
std::cout << "MenuListSearchList::unshareSelected() Invalid Selection";
std::cout << std::endl;
return MENU_ENTRY_NONE;
}
std::list<SharedDirInfo> dirs;
rsFiles->getSharedDirectories(dirs);
std::list<SharedDirInfo>::iterator it;
int i=0;
for (it = dirs.begin(); (i < mSelectIdx) && (it != dirs.end()); it++, i++);
if (it != dirs.end())
{
rsFiles->removeSharedDirectory(it->filename);
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuListShared::toggleFlagSelected(FileStorageFlags shareflags)
{
if (mSelectIdx < 0)
{
std::cout << "MenuListSearchList::unshareSelected() Invalid Selection";
std::cout << std::endl;
return MENU_ENTRY_NONE;
}
std::list<SharedDirInfo> dirs;
rsFiles->getSharedDirectories(dirs);
std::list<SharedDirInfo>::iterator it;
int i=0;
for (it = dirs.begin(); (i < mSelectIdx) && (it != dirs.end()); it++, i++);
if (it != dirs.end())
{
if(FileStorageFlags(it->shareflags & shareflags) == shareflags)
{
it->shareflags = FileStorageFlags(it->shareflags & ~shareflags); //disable shareflags
rsFiles->updateShareFlags(*it);
}
else
{
it->shareflags = FileStorageFlags(it->shareflags | shareflags); //anable shareflags
rsFiles->updateShareFlags(*it);
}
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
uint32_t MenuListSharedUnshare::op_basic(std::string key)
{
Menu* p = parent();
MenuListShared *mls = dynamic_cast<MenuListShared *>(p);
if (!mls)
{
std::cout << "MenuListShared::op_basic() ERROR";
std::cout << std::endl;
return MENU_OP_ERROR;
}
mls->unshareSelected();
return MENU_OP_INSTANT;
}
uint32_t MenuListSharedTogglePublic::op_basic(std::string key)
{
Menu* p = parent();
MenuListShared *mls = dynamic_cast<MenuListShared *>(p);
if (!mls)
{
std::cout << "MenuListShared::op_basic() ERROR";
std::cout << std::endl;
return MENU_OP_ERROR;
}
mls->toggleFlagSelected(DIR_FLAGS_NETWORK_WIDE_OTHERS);
return MENU_OP_INSTANT;
}
uint32_t MenuListSharedToggleBrowsable::op_basic(std::string key)
{
Menu* p = parent();
MenuListShared *mls = dynamic_cast<MenuListShared *>(p);
if (!mls)
{
std::cout << "MenuListShared::op_basic() ERROR";
std::cout << std::endl;
return MENU_OP_ERROR;
}
mls->toggleFlagSelected(DIR_FLAGS_BROWSABLE_OTHERS);
return MENU_OP_INSTANT;
}
uint32_t MenuListSharedAddShare::drawPage(uint32_t drawFlags, std::string &buffer)
{
buffer += "Enter New path 'path' 'virtualfolder' > ";
return 1;
}
uint32_t MenuListSharedAddShare::process_lines(std::string input)
{
/* launch search */
if (input.size() < 4)
{
std::cout << "MenuOpSearchNew::process_lines() ERROR Input too small";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
std::string dir = input.substr(0, input.size() - 1); // remove \n.
// check that the directory exists!
if (!RsDirUtil::checkDirectory(dir))
{
std::cout << "MenuOpSearchNew::process_lines() ERROR Directory doesn't exist";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
// extract top level as the virtual name.
std::string topdir = RsDirUtil::getTopDir(input);
if (topdir.size() < 1)
{
std::cout << "MenuOpSearchNew::process_lines() ERROR TopDir is invalid";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
SharedDirInfo shareddir;
shareddir.filename = dir;
shareddir.virtualname = topdir;
shareddir.shareflags = FileStorageFlags(0x0);
if (!rsFiles->addSharedDirectory(shareddir))
{
std::cout << "MenuOpSearchNew::process_lines() ERROR Adding SharedDir";
std::cout << std::endl;
return MENU_PROCESS_ERROR;
}
return MENU_PROCESS_DONE;
}

View File

@ -1,346 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "menu/menu.h"
#include <retroshare/rsturtle.h>
#include "notifytxt.h" /* needed to access search results */
#include <map>
Menu *CreateMenuStructure(NotifyTxt *notify);
/************
* Friends Menu
*/
class MenuListFriends: public MenuList
{
public:
MenuListFriends() :MenuList("Friends") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
protected:
MenuListFriends(std::string name) :MenuList(name) { return; } // For Network.
};
class MenuListNetwork: public MenuListFriends
{
public:
MenuListNetwork() :MenuListFriends("Network") { return; }
virtual uint32_t op();
};
class MenuOpFriendsAdd: public MenuOpBasicKey
{
public:
MenuOpFriendsAdd() :MenuOpBasicKey("Add") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsViewDetail: public MenuOpBasicKey
{
public:
MenuOpFriendsViewDetail() :MenuOpBasicKey("View") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsRemove: public MenuOpBasicKey
{
public:
MenuOpFriendsRemove() :MenuOpBasicKey("Remove") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsChat: public MenuOpBasicKey
{
public:
MenuOpFriendsChat() :MenuOpBasicKey("Chat") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Transfer Menu
*/
class MenuListTransfer: public MenuList
{
public:
MenuListTransfer() :MenuList("Downloads") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpTransferStop: public MenuOpBasicKey
{
public:
MenuOpTransferStop() :MenuOpBasicKey("Stop") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpTransferCancel: public MenuOpBasicKey
{
public:
MenuOpTransferCancel() :MenuOpBasicKey("Cancel") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Search Menu
*/
class MenuListSearch: public MenuList
{
public:
MenuListSearch(NotifyTxt *notify)
:MenuList("Search"), mNotify(notify) { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
/* specific Search Functions */
int getCurrentSearchId(uint32_t &id);
int storeSearch(uint32_t searchId, std::string match_string);
int removeSearch(std::string strSearchId);
private:
std::map<std::string, uint32_t> mSearchIds;
std::map<std::string, std::string> mSearchTerms;
NotifyTxt *mNotify;
};
class MenuOpSearchNew: public MenuOpLineInput
{
public:
MenuOpSearchNew(NotifyTxt *notify)
:MenuOpLineInput("New"), mNotify(notify) { return; }
virtual uint32_t process_lines(std::string input);
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
private:
NotifyTxt *mNotify;
};
class MenuOpSearchDelete: public MenuOpBasicKey
{
public:
MenuOpSearchDelete() :MenuOpBasicKey("Delete") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuListSearchList: public MenuList
{
public:
MenuListSearchList(NotifyTxt *notify)
:MenuList("Results"), mNotify(notify) { return; }
virtual uint32_t op();
uint32_t refresh();
int getEntryDesc(int idx, std::string &desc);
int downloadSelected();
private:
NotifyTxt *mNotify;
std::list<TurtleFileInfo> mSearchResults; // local cache for consistency.
};
class MenuOpSearchListDownload: public MenuOpBasicKey
{
public:
MenuOpSearchListDownload() :MenuOpBasicKey("Download") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Forums Menu
*/
class MenuListForums: public MenuList
{
public:
MenuListForums() :MenuList("Forums SubMenu") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpForumDetails: public MenuOpBasicKey
{
public:
MenuOpForumDetails() :MenuOpBasicKey("Show Forum Details") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumSubscribe: public MenuOpBasicKey
{
public:
MenuOpForumSubscribe() :MenuOpBasicKey("Subscribe To Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumUnsubscribe: public MenuOpBasicKey
{
public:
MenuOpForumUnsubscribe() :MenuOpBasicKey("Unsubscribe To Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumCreate: public MenuOpBasicKey
{
public:
MenuOpForumCreate() :MenuOpBasicKey("Create Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuListForumMsgs: public MenuList
{
public:
MenuListForumMsgs() :MenuList("List Forum Msgs") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpForumMsgView: public MenuOpTwoKeys
{
public:
MenuOpForumMsgView() :MenuOpTwoKeys("View Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
class MenuOpForumMsgReply: public MenuOpTwoKeys
{
public:
MenuOpForumMsgReply() :MenuOpTwoKeys("Reply to Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
class MenuOpForumMsgWrite: public MenuOpTwoKeys
{
public:
MenuOpForumMsgWrite() :MenuOpTwoKeys("Write Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
/************
* Shared folders Menu
*/
class MenuListShared: public MenuList
{
public:
MenuListShared() :MenuList("My Shared Directories") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
int unshareSelected();
int toggleFlagSelected(FileStorageFlags shareflags);
};
class MenuListSharedUnshare: public MenuOpBasicKey
{
public:
MenuListSharedUnshare() :MenuOpBasicKey("Stop Sharing Selected") { return; }
virtual uint32_t op_basic(std::string key);
};
class MenuListSharedTogglePublic: public MenuOpBasicKey
{
public:
MenuListSharedTogglePublic() :MenuOpBasicKey("Enable/Disable Networkwide Sharing") { return; }
virtual uint32_t op_basic(std::string key);
};
class MenuListSharedToggleBrowsable: public MenuOpBasicKey
{
public:
MenuListSharedToggleBrowsable() :MenuOpBasicKey("Enable/Disable Browsing Of Selected") { return; }
virtual uint32_t op_basic(std::string key);
};
class MenuListSharedAddShare: public MenuOpLineInput
{
public:
MenuListSharedAddShare() :MenuOpLineInput("Add new Share") { return; }
virtual uint32_t process_lines(std::string input);
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
};

View File

@ -1,94 +0,0 @@
#include <iostream>
#include "menu/menu.h"
class MenuTest
{
public:
MenuTest(MenuInterface *i, std::istream &in, std::ostream &out)
:mMenus(i), mIn(in), mOut(out)
{
return;
}
int tick()
{
int c = mIn.get();
uint8_t key = (uint8_t) c;
uint32_t drawFlags = 0;
std::string buffer;
mMenus->process(key, drawFlags, buffer);
return 1;
}
private:
MenuInterface *mMenus;
std::istream &mIn;
std::ostream &mOut;
};
#include <unistd.h>
#include <fcntl.h>
#include "rstermserver.h"
class RsConsole
{
public:
RsConsole(RsTermServer *s, int infd, int outfd)
:mServer(s), mIn(infd), mOut(outfd)
{
const int fcflags = fcntl(mIn,F_GETFL);
if (fcflags < 0)
{
std::cerr << "RsConsole() ERROR getting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
if (fcntl(mIn,F_SETFL,fcflags | O_NONBLOCK) <0)
{
std::cerr << "RsConsole() ERROR setting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
}
int tick()
{
char buf;
std::string output;
int size = read(mIn, &buf, 1);
bool haveInput = (size > 0);
int rt = mServer->tick(haveInput, buf, output);
if (output.size() > 0)
{
write(mOut, output.c_str(), output.size());
}
if (rt < 0)
{
std::cerr << "Exit Request";
exit(1);
}
if (!haveInput)
{
return 0;
}
return 1;
}
private:
RsTermServer *mServer;
int mIn, mOut;
};

View File

@ -1,183 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "menu/stdiocomms.h"
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
StdioComms::StdioComms(int infd, int outfd)
:mIn(infd), mOut(outfd)
{
// fcntl not available on Windows, search alternative when needed
#ifndef WINDOWS_SYS
#if 1
// THIS Code is strange...
// It seems to mess up stderr.
// But if you redirect it -> is comes out fine. Very Weird.
// HELP!!!
std::cerr << "StdioComms() STDERR msg 0";
std::cerr << std::endl;
const int fcflags = fcntl(mIn,F_GETFL);
if (fcflags < 0)
{
std::cerr << "StdioComms() ERROR getting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
if (fcntl(mIn,F_SETFL,fcflags | O_NONBLOCK) <0)
{
std::cerr << "StdioComms() ERROR setting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
std::cerr << "StdioComms() STDERR msg 1";
std::cerr << std::endl;
#endif
#endif // WINDOWS_SYS
}
int StdioComms::isOkay()
{
return 1;
}
int StdioComms::active_channels(std::list<uint32_t> &chan_ids)
{
if (isOkay())
{
chan_ids.push_back(1); // only one possible here (stdin/stdout)
}
return 1;
}
int StdioComms::error(uint32_t chan_id, std::string msg)
{
std::cerr << "StdioComms::error(" << msg << ")";
std::cerr << std::endl;
return 1;
}
int StdioComms::recv_ready(uint32_t chan_id)
{
/* should be proper poll / select! - but we don't use this at the moment */
return 1;
}
int StdioComms::recv(uint32_t chan_id, uint8_t *buffer, int bytes)
{
int size = read(mIn, buffer, bytes);
std::cerr << "StdioComms::recv() returned: " << size;
std::cerr << std::endl;
if (size == -1)
{
std::cerr << "StdioComms::recv() ERROR: " << errno;
std::cerr << std::endl;
if (errno == EAGAIN)
{
return 0; // OKAY;
}
}
return size;
}
int StdioComms::recv(uint32_t chan_id, std::string &buffer, int bytes)
{
uint8_t tmpbuffer[bytes];
int size = read(mIn, tmpbuffer, bytes);
for(int i = 0; i < size; i++)
{
buffer += tmpbuffer[i];
}
return size;
}
// these make it easier...
int StdioComms::recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes)
{
int totalread = 0;
while(totalread < bytes)
{
int size = read(mIn, &(buffer[totalread]), bytes - totalread);
if (size < 0)
{
if (totalread)
break; // partial read.
else
return size; // error.
}
totalread += size;
usleep(1000); // minisleep - so we don't 100% CPU.
std::cerr << "StdioComms::recv_blocking() read so far: " << size;
std::cerr << " / " << totalread;
std::cerr << std::endl;
}
return totalread;
}
int StdioComms::recv_blocking(uint32_t chan_id, std::string &buffer, int bytes)
{
uint8_t tmpbuffer[bytes];
int size = recv_blocking(chan_id, tmpbuffer, bytes);
if (size < 0)
return size; // error.
for(int i = 0; i < size; i++)
buffer += tmpbuffer[i];
return size;
}
int StdioComms::send(uint32_t chan_id, uint8_t *buffer, int bytes)
{
write(mOut, buffer, bytes);
return bytes;
}
int StdioComms::send(uint32_t chan_id, const std::string &output)
{
if (output.size() > 0)
{
write(mOut, output.c_str(), output.size());
}
return output.size();
}

View File

@ -1,59 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_STDIO_COMMS_H
#define RS_STDIO_COMMS_H
#include "rpcsystem.h"
class StdioComms: public RpcComms
{
public:
StdioComms(int infd, int outfd);
virtual int isOkay();
virtual int error(uint32_t chan_id, std::string msg);
virtual int active_channels(std::list<uint32_t> &chan_ids);
virtual int recv_ready(uint32_t chan_id);
virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int recv(uint32_t chan_id, std::string &buffer, int bytes);
// these make it easier...
virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes);
virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int send(uint32_t chan_id, const std::string &buffer);
private:
int mIn, mOut;
};
#endif

View File

@ -4,7 +4,6 @@ TEMPLATE = app
TARGET = RetroShare06-nogui
CONFIG += bitdht
#CONFIG += introserver
#CONFIG += sshserver
CONFIG -= qt xml gui
CONFIG += link_prl
@ -84,8 +83,6 @@ win32 {
LIBS += -luuid -lole32 -liphlpapi -lcrypt32
LIBS += -lole32 -lwinmm
PROTOCPATH=$$BIN_DIR
RC_FILE = resources/retroshare_win.rc
DEFINES *= WINDOWS_SYS _USE_32BIT_TIME_T
@ -97,11 +94,11 @@ win32 {
##################################### MacOS ######################################
macx {
# ENABLE THIS OPTION FOR Univeral Binary BUILD.
# CONFIG += ppc x86
# ENABLE THIS OPTION FOR Univeral Binary BUILD.
# CONFIG += ppc x86
LIBS += -Wl,-search_paths_first
LIBS += -lssl -lcrypto -lz
LIBS += -lssl -lcrypto -lz
for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a}
LIBS += -framework CoreFoundation
LIBS += -framework Security
@ -111,13 +108,7 @@ macx {
DEPENDPATH += . $$INC_DIR
INCLUDEPATH += . $$INC_DIR
sshserver {
LIBS += -L../../../lib
#LIBS += -L../../../lib/libssh-0.6.0
}
QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen
QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen
}
##################################### FreeBSD ######################################
@ -193,173 +184,3 @@ libresapihttpserver {
SOURCES += \
TerminalApiClient.cpp
}
sshserver {
# This Requires libssh-0.5.* to compile.
# Please use this path below.
# (You can modify it locally if required - but dont commit it!)
#LIBSSH_DIR = $PWD/../../../lib/libssh-0.5.2
LIBSSH_DIR = $PWD/../../../libssh-0.6.0rc1
#
# Use the following commend to generate a Server RSA Key.
# Key should be in current directory - when run/
# ssh-keygen -t rsa -f rs_ssh_host_rsa_key
#
# You can connect from a standard ssh, eg: ssh -p 7022 127.0.0.1
#
# The Menu system is available from the command-line (-T) and SSH (-S)
# if it get covered by debug gunk, just press <return> to refresh.
#
# ./retroshare-nogui -h provides some more instructions.
#
win32 {
DEFINES *= LIBSSH_STATIC
}
DEPENDPATH += $$LIBSSH_DIR/include/
INCLUDEPATH += $$LIBSSH_DIR/include/
win32 {
LIBS += -lssh
LIBS += -lssh_threads
} else {
SSH_OK = $$system(pkg-config --atleast-version 0.5.4 libssh && echo yes)
isEmpty(SSH_OK) {
exists($$LIBSSH_DIR/build/src/libssh.a):exists($$LIBSSH_DIR/build/src/threads/libssh_threads.a) {
LIBS += $$LIBSSH_DIR/build/src/libssh.a
LIBS += $$LIBSSH_DIR/build/src/threads/libssh_threads.a
}
else {
! exists($$LIBSSH_DIR/build/src/libssh.a):message($$LIBSSH_DIR/build/src/libssh.a does not exist)
! exists($$LIBSSH_DIR/build/src/threads/libssh_threads.a):message($$LIBSSH_DIR/build/src/threads/libssh_threads.a does not exist)
message(You need to download and compile libssh)
message(See http://sourceforge.net/p/retroshare/code/6163/tree/trunk/)
}
} else {
LIBS += -lssh
LIBS += -lssh_threads
}
}
HEADERS += ssh/rssshd.h
SOURCES += ssh/rssshd.cc
# For the Menu System
HEADERS += menu/menu.h \
menu/menus.h \
menu/stdiocomms.h \
SOURCES += menu/menu.cc \
menu/menus.cc \
menu/stdiocomms.cc \
# For the RPC System
HEADERS += rpc/rpc.h \
rpc/rpcserver.h \
rpc/rpcsetup.h \
rpc/rpcecho.h \
rpcsystem.h \
SOURCES += rpc/rpc.cc \
rpc/rpcserver.cc \
rpc/rpcsetup.cc \
rpc/rpcecho.cc \
# Actual protocol files to go here...
#HEADERS += rpc/proto/rpcecho.h \
#SOURCES += rpc/proto/rpcecho.cc \
DEFINES *= RS_SSH_SERVER
# Include Protobuf classes.
CONFIG += protorpc
}
protorpc {
# Proto Services
PROTOS = core.proto peers.proto system.proto chat.proto search.proto files.proto stream.proto
DESTPATH = $$PWD/rpc/proto/gencc
PROTOPATH = $$PWD/../../rsctrl/src/definition
CMD = echo Building protobuf files
for(pf, PROTOS):CMD += && $${PROTOCPATH}protoc --cpp_out=$${DESTPATH} --proto_path=$${PROTOPATH} $${PROTOPATH}/$${pf}
protobuf_gen.commands = $${CMD}
QMAKE_EXTRA_TARGETS += protobuf_gen
PRE_TARGETDEPS += protobuf_gen
HEADERS += rpc/proto/rpcprotopeers.h \
rpc/proto/rpcprotosystem.h \
rpc/proto/rpcprotochat.h \
rpc/proto/rpcprotosearch.h \
rpc/proto/rpcprotofiles.h \
rpc/proto/rpcprotostream.h \
rpc/proto/rpcprotoutils.h \
SOURCES += rpc/proto/rpcprotopeers.cc \
rpc/proto/rpcprotosystem.cc \
rpc/proto/rpcprotochat.cc \
rpc/proto/rpcprotosearch.cc \
rpc/proto/rpcprotofiles.cc \
rpc/proto/rpcprotostream.cc \
rpc/proto/rpcprotoutils.cc \
# Offical Generated Code (protobuf 2.4.1)
HEADERS += rpc/proto/gencc/core.pb.h \
rpc/proto/gencc/peers.pb.h \
rpc/proto/gencc/system.pb.h \
rpc/proto/gencc/chat.pb.h \
rpc/proto/gencc/search.pb.h \
rpc/proto/gencc/files.pb.h \
rpc/proto/gencc/stream.pb.h \
SOURCES += rpc/proto/gencc/core.pb.cc \
rpc/proto/gencc/peers.pb.cc \
rpc/proto/gencc/system.pb.cc \
rpc/proto/gencc/chat.pb.cc \
rpc/proto/gencc/search.pb.cc \
rpc/proto/gencc/files.pb.cc \
rpc/proto/gencc/stream.pb.cc \
# Generated ProtoBuf Code the RPC System
# If you are developing, or have a different version of protobuf
# you can use these ones (run make inside rsctrl/src/ to generate)
#HEADERS += ../../rsctrl/src/gencc/core.pb.h \
# ../../rsctrl/src/gencc/peers.pb.h \
# ../../rsctrl/src/gencc/system.pb.h \
# ../../rsctrl/src/gencc/chat.pb.h \
# ../../rsctrl/src/gencc/search.pb.h \
# ../../rsctrl/src/gencc/files.pb.h \
# ../../rsctrl/src/gencc/stream.pb.h \
#SOURCES += ../../rsctrl/src/gencc/core.pb.cc \
# ../../rsctrl/src/gencc/peers.pb.cc \
# ../../rsctrl/src/gencc/system.pb.cc \
# ../../rsctrl/src/gencc/chat.pb.cc \
# ../../rsctrl/src/gencc/search.pb.cc \
# ../../rsctrl/src/gencc/files.pb.cc \
# ../../rsctrl/src/gencc/stream.pb.cc \
DEPENDPATH *= rpc/proto/gencc
INCLUDEPATH *= rpc/proto/gencc
!win32 {
# unrecognized option
QMAKE_CFLAGS += -pthread
QMAKE_CXXFLAGS += -pthread
}
LIBS += -lprotobuf -lpthread
win32 {
DEPENDPATH += $$LIBS_DIR/include/protobuf
INCLUDEPATH += $$LIBS_DIR/include/protobuf
}
macx {
PROTOPATH = ../../../protobuf-2.4.1
INCLUDEPATH += $${PROTOPATH}/src
}
}

View File

@ -40,20 +40,6 @@
#include "introserver.h"
#endif
#ifdef RS_SSH_SERVER
#include "ssh/rssshd.h"
#include "menu/menus.h"
#include "menu/stdiocomms.h"
#include "rpc/rpcsetup.h"
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
#include "rpc/proto/rpcprotosystem.h"
void generatePasswordHash() ;
#endif
#ifdef ENABLE_WEBUI
#include <stdarg.h>
#include "api/ApiServerMHD.h"
@ -151,123 +137,6 @@ int main(int argc, char **argv)
**/
bool strictCheck = true;
#ifdef RS_SSH_SERVER
/* parse commandline for additional nogui options */
int c;
// libretroshare's getopt str - so don't use any of these: "hesamui:p:c:w:l:d:U:r:R:"
// need options for
// enable SSH. (-S)
// set user/password for SSH. -L "user:pwdhash"
// accept RSA Key Auth. -K "RsaPubKeyFile"
// Terminal mode. -T
bool enableRpc = false;
bool enableSsh = false;
bool enableSshHtml = false;
bool enableTerminal = false;
bool enableSshRsa = false;
bool genPwdHash = false;
std::string sshUser = "user";
std::string sshPwdHash = "";
std::string sshRsaFile = "";
uint16_t extPort = 0;
uint16_t sshPort = 7022;
bool extPortSet = false;
bool displayRPCInfo = false ;
argstream as(argc,argv) ;
as >> option('X',"enable-ssh" ,enableSsh ,"Enable SSH" )
>> option('T',"enable-terminal",enableTerminal ,"Enable terminal interface." )
>> option('C',"enable-rpc" ,enableRpc ,"Enable RPC protocol. To be used with e.g. -X (SSH).")
>> option('G',"gen-password" ,genPwdHash ,"Generate password hash (to supply to option -P)")
#if 0
>> option('H',"enable-ssh-html",enableSshHtml ,"Enable SSH html." )
#endif
>> parameter('S',"ssh-port" ,sshPort ,"port" ,"SSH port to contact the interface.",false)
>> parameter('E',"ext-port" ,extPort ,"port" ,"Specify Alternative External Port (provided to Clients)",false)
>> parameter('L',"ssh-user" ,sshUser ,"name" ,"Ssh login user",false)
>> parameter('P',"ssh-p-hash" ,sshPwdHash ,"hash" ,"Ssh login password hash (Generated by retroshare-nogui -G)",false)
>> parameter('K',"ssh-key-file" ,sshRsaFile ,"RSA key file", "RSA key file for SSH login (not yet implemented).",false )// NOT FINISHED YET.
#ifdef __APPLE__
>> help('h',"help","Display this Help");
#else
>> help() ;
#endif
// Normally argstream would handle this by itself, if we called
// as.defaultErrorHandling() ;
//
// but we have other parameter handling functions after, so we don't want to quit if help is requested.
//
if (as.helpRequested())
{
std::cerr << "\nSpecific Help Options:" << std::endl;
std::cerr << as.usage() << std::endl;
std::cerr << "\t To setup rs-nogui as a SSH Server is a three step process: " << std::endl;
std::cerr << "\t 1) Generate a RSA keypair in the current directory: \"ssh-keygen -t rsa -f rs_ssh_host_rsa_key\" " << std::endl;
std::cerr << "\t 2) Generate a password hash for the RPC login: \"./retroshare-nogui -G\" " << std::endl;
std::cerr << "\t 3) Launch the RS with remote control enabled: \"./retroshare-nogui -X/-T [-C] -S [port] -L <user> -P <passwordhash>\" " << std::endl;
std::cerr << "\nAdditional options: \n" << std::endl;
}
if (!as.isOk())
{
std::cerr << as.errorLog();
return 1;
}
if (genPwdHash)
{
generatePasswordHash() ;
return 0 ;
}
/* enforce conditions */
if ((!sshRsaFile.empty() || !sshPwdHash.empty()) && (!enableSsh))
{
std::cerr << "ERROR: SSH Server (-X) must be enabled to specify SSH Pwd (-P) or SSH RSA (-K)";
std::cerr << std::endl;
return 1 ;
}
if (enableSsh && (!enableSshRsa) && sshPwdHash.empty())
{
std::cerr << "ERROR: One of (or both) SSH Pwd (-P) and SSH RSA (-K) must be specified with SSH Server (-X)";
std::cerr << std::endl;
return 1 ;
}
if (enableRpc && (!enableSsh))
{
std::cerr << "ERROR: RPC Mode (-C) requires SSH Server (-X) enabled";
std::cerr << std::endl;
return 1 ;
}
/* parse -S, -L & -K parameters */
if (enableSshRsa)
{
/* check the file exists */
/* TODO */
}
if (enableSsh)
{
/* try parse it */
/* TODO */
}
#else
std::cerr << "\nRetroshare command line interface." << std::endl;
#endif
RsInit::InitRsConfig();
int initResult = RsInit::InitRetroShare(argc, argv, strictCheck);
@ -318,38 +187,6 @@ int main(int argc, char **argv)
return 1;
}
#ifdef RS_SSH_SERVER
// Says it must be called before all the threads are launched! */
// NB: this port number is not currently used.
RsSshd *ssh = NULL;
if (enableSsh)
{
std::ostringstream os ;
os << sshPort ;
ssh = RsSshd::InitRsSshd(os.str(), "rs_ssh_host_rsa_key");
// TODO Parse Option
if (enableSshRsa)
{
//ssh->adduser("anrsuser", "test");
}
if (!sshPwdHash.empty())
{
ssh->adduserpwdhash(sshUser, sshPwdHash);
}
if (!extPortSet)
{
extPort = sshPort;
}
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
RpcProtoSystem::mExtPort = extPort;
}
#endif
/* Start-up libretroshare server threads */
RsControl::instance() -> StartupRetroShare();
@ -357,47 +194,6 @@ int main(int argc, char **argv)
RsIntroServer rsIS;
#endif
#ifdef RS_SSH_SERVER
uint32_t baseDrawFlags = 0;
if (enableSshHtml)
{
baseDrawFlags = MENU_DRAW_FLAGS_HTML;
}
if (enableSsh)
{
if (enableRpc)
{
/* Build RPC Server */
RpcMediator *med = CreateRpcSystem(ssh, notify);
ssh->setRpcSystem(med);
ssh->setSleepPeriods(0.01, 0.1);
}
else
{
/* create menu system for SSH */
Menu *baseMenu = CreateMenuStructure(notify);
MenuInterface *menuInterface = new MenuInterface(ssh, baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_ECHO);
ssh->setRpcSystem(menuInterface);
ssh->setSleepPeriods(0.05, 0.5);
}
ssh->start();
}
MenuInterface *terminalMenu = NULL;
if (enableTerminal)
{
/* Terminal Version */
RpcComms *stdioComms = new StdioComms(fileno(stdin), fileno(stdout));
Menu *baseMenu = CreateMenuStructure(notify);
terminalMenu = new MenuInterface(stdioComms, baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_NOQUIT);
//menuTerminal = new RsConsole(menuInterface, fileno(stdin), fileno(stdout));
}
#endif
/* pass control to the GUI */
while(1)
{
@ -408,13 +204,6 @@ int main(int argc, char **argv)
#endif
int rt = 0;
#ifdef RS_SSH_SERVER
if (terminalMenu)
{
rt = terminalMenu->tick();
}
#endif
// If we have a MenuTerminal ...
// only want to sleep if there is no input. (rt == 0).
if (rt == 0)
@ -430,73 +219,4 @@ int main(int argc, char **argv)
}
return 1;
}
#ifdef RS_SSH_SERVER
void generatePasswordHash()
{
std::string saltBin;
std::string pwdHashRadix64;
std::string sshPwdForHash = "";
std::string passwd1,passwd2 ;
bool cancel ;
if(!NotifyTxt().askForPassword("","Type your password (at least 8 chars) : ",false,passwd1,cancel)) exit(1) ;
if(passwd1.length() < 8)
{
std::cerr << "Password must be at least 8 characters long." << std::endl;
exit(1);
}
if(!NotifyTxt().askForPassword("","Type your password (checking) : ",false,passwd2,cancel)) exit(1) ;
if(passwd1 != passwd2)
{
std::cerr << "Passwords differ. Please retry." << std::endl;
exit(1);
}
sshPwdForHash = passwd1 ;
//std::cerr << "Chosen Password : " << sshPwdForHash;
std::cerr << std::endl;
GenerateSalt(saltBin);
if (!GeneratePasswordHash(saltBin, sshPwdForHash, pwdHashRadix64))
{
std::cerr << "Error Generating Password Hash, password probably too short";
std::cerr << pwdHashRadix64;
std::cerr << std::endl;
exit(1);
}
std::cout << "Generated Password Hash for rs-nogui: ";
std::cout << pwdHashRadix64;
std::cout << std::endl;
std::cout << std::endl;
/* checking match */
if (CheckPasswordHash(pwdHashRadix64, sshPwdForHash))
{
std::cerr << "Passed Check Okay!";
std::cerr << std::endl;
}
else
{
std::cerr << "ERROR: Failed CheckPassword!";
std::cerr << std::endl;
exit(1);
}
std::cerr << "Usage:";
std::cerr << std::endl;
std::cerr << " - for SSH access: ./retroshare-nogui -X -S [port] -L <username> -P " << pwdHashRadix64;
std::cerr << std::endl;
std::cerr << " - for RPC access: ./retroshare-nogui -C -X -S [port] -L <username> -P " << pwdHashRadix64;
std::cerr << std::endl;
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_CHAT_H
#define RS_RPC_PROTO_CHAT_H
#include "rpc/rpcserver.h"
// Registrations.
#define REGISTRATION_EVENT_CHAT 1
class RpcProtoChat: public RpcQueueService
{
public:
RpcProtoChat(uint32_t serviceId);
virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
protected:
int processReqChatLobbies(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqCreateLobby(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqJoinOrLeaveLobby(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqSetLobbyNickname(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqRegisterEvents(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqSendMessage(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqChatHistory(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
// EVENTS.
virtual int locked_checkForEvents(uint32_t event, const std::list<RpcEventRegister> &registered, std::list<RpcQueuedMsg> &events);
};
#endif /* RS_PROTO_CHAT_H */

View File

@ -1,630 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotofiles.h"
#include "rpc/proto/gencc/files.pb.h"
#include <retroshare/rsfiles.h>
#include <retroshare/rspeers.h>
#include "util/rsstring.h"
#include "util/rsdir.h"
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
bool fill_file_from_details(rsctrl::core::File *file, DirDetails &details);
bool fill_file_as_dir(rsctrl::core::File *file, const std::string &dir_name);
RpcProtoFiles::RpcProtoFiles(uint32_t serviceId)
:RpcQueueService(serviceId)
{
return;
}
int RpcProtoFiles::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* check the msgId */
uint8_t topbyte = getRpcMsgIdExtension(msg_id);
uint16_t service = getRpcMsgIdService(msg_id);
uint8_t submsg = getRpcMsgIdSubMsg(msg_id);
bool isResponse = isRpcMsgIdResponse(msg_id);
std::cerr << "RpcProtoFiles::processMsg() topbyte: " << (int32_t) topbyte;
std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg;
std::cerr << std::endl;
if (isResponse)
{
std::cerr << "RpcProtoFiles::processMsg() isResponse() - not processing";
std::cerr << std::endl;
return 0;
}
if (topbyte != (uint8_t) rsctrl::core::CORE)
{
std::cerr << "RpcProtoFiles::processMsg() Extension Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (service != (uint16_t) rsctrl::core::FILES)
{
std::cerr << "RpcProtoFiles::processMsg() Service Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (!rsctrl::files::RequestMsgIds_IsValid(submsg))
{
std::cerr << "RpcProtoFiles::processMsg() SubMsg Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
switch(submsg)
{
case rsctrl::files::MsgId_RequestTransferList:
processReqTransferList(chan_id, msg_id, req_id, msg);
break;
case rsctrl::files::MsgId_RequestControlDownload:
processReqControlDownload(chan_id, msg_id, req_id, msg);
break;
case rsctrl::files::MsgId_RequestShareDirList:
processReqShareDirList(chan_id, msg_id, req_id, msg);
break;
default:
std::cerr << "RpcProtoFiles::processMsg() ERROR should never get here";
std::cerr << std::endl;
return 0;
}
/* must have matched id to get here */
return 1;
}
int RpcProtoFiles::processReqTransferList(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoFiles::processReqTransferList()";
std::cerr << std::endl;
// parse msg.
rsctrl::files::RequestTransferList req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoFiles::processReqTransferList() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::files::ResponseTransferList resp;
bool success = true;
std::string errorMsg;
std::list<std::string> file_list;
FileSearchFlags hints(0);
/* convert msg parameters into local ones */
switch(req.direction())
{
case rsctrl::files::DIRECTION_UPLOAD:
{
rsFiles->FileUploads(file_list);
hints = RS_FILE_HINTS_UPLOAD;
break;
}
case rsctrl::files::DIRECTION_DOWNLOAD:
{
rsFiles->FileDownloads(file_list);
hints = RS_FILE_HINTS_DOWNLOAD;
break;
}
default:
std::cerr << "RpcProtoFiles::processReqTransferList() ERROR Unknown Dir";
std::cerr << std::endl;
success = false;
errorMsg = "Unknown Direction";
break;
}
std::list<std::string>::iterator lit;
for(lit = file_list.begin(); lit != file_list.end(); lit++)
{
rsctrl::files::FileTransfer *transfer = resp.add_transfers();
transfer->set_direction(req.direction());
FileInfo info;
if (!rsFiles->FileDetails(*lit, hints, info))
{
/* error */
continue;
}
/* copy file details */
rsctrl::core::File *filedetails = transfer->mutable_file();
filedetails->set_hash(info.hash);
filedetails->set_size(info.size);
filedetails->set_name(info.fname);
transfer->set_fraction( (float) info.transfered / info.size );
transfer->set_rate_kbs( info.tfRate );
switch(info.downloadStatus)
{
case FT_STATE_FAILED:
transfer->set_state(rsctrl::files::TRANSFER_FAILED);
break;
default:
case FT_STATE_OKAY:
transfer->set_state(rsctrl::files::TRANSFER_OKAY);
break;
case FT_STATE_PAUSED:
transfer->set_state(rsctrl::files::TRANSFER_PAUSED);
break;
case FT_STATE_QUEUED:
transfer->set_state(rsctrl::files::TRANSFER_QUEUED);
break;
case FT_STATE_WAITING:
transfer->set_state(rsctrl::files::TRANSFER_WAITING);
break;
case FT_STATE_DOWNLOADING:
transfer->set_state(rsctrl::files::TRANSFER_DOWNLOADING);
break;
case FT_STATE_CHECKING_HASH:
transfer->set_state(rsctrl::files::TRANSFER_CHECKING_HASH);
break;
case FT_STATE_COMPLETE:
transfer->set_state(rsctrl::files::TRANSFER_COMPLETE);
break;
}
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoFiles::processReqTransferList() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::FILES,
rsctrl::files::MsgId_ResponseTransferList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoFiles::processReqControlDownload(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoFiles::processReqControlDownload()";
std::cerr << std::endl;
// parse msg.
rsctrl::files::RequestControlDownload req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoFiles::processReqControlDownload() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::files::ResponseControlDownload resp;
bool success = true;
std::string errorMsg;
std::string filehash = req.file().hash();
switch(req.action())
{
case rsctrl::files::RequestControlDownload::ACTION_START:
{
std::list<std::string> srcIds;
std::string filename = req.file().name();
uint64_t filesize = req.file().size();
// We Set NETWORK_WIDE flag here -> as files will be found via search.
// If this changes, we might be adjust flag (or pass it in!)
if (!rsFiles -> FileRequest(filename, filehash, filesize,
"", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds))
{
success = false;
errorMsg = "FileRequest ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_CONTINUE:
{
if (!rsFiles->changeQueuePosition(filehash,QUEUE_TOP))
{
success = false;
errorMsg = "File QueuePosition(Top) ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_WAIT:
{
if (!rsFiles->changeQueuePosition(filehash,QUEUE_BOTTOM))
{
success = false;
errorMsg = "File QueuePosition(Bottom) ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_PAUSE:
{
if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_PAUSE))
{
success = false;
errorMsg = "FileControl(Pause) ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_RESTART:
{
if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_START))
{
success = false;
errorMsg = "FileControl(Start) ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_CHECK:
{
if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_FORCE_CHECK))
{
success = false;
errorMsg = "FileControl(Check) ERROR";
}
break;
}
case rsctrl::files::RequestControlDownload::ACTION_CANCEL:
{
if (!rsFiles->FileCancel(filehash))
{
success = false;
errorMsg = "FileCancel ERROR";
}
break;
}
default:
success = false;
errorMsg = "Invalid Action";
break;
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoFiles::processReqControlDownload() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::FILES,
rsctrl::files::MsgId_ResponseControlDownload, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoFiles::processReqShareDirList(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoFiles::processReqShareDirList()";
std::cerr << std::endl;
// parse msg.
rsctrl::files::RequestShareDirList req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoFiles::processReqShareDirList() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::files::ResponseShareDirList resp;
bool success = true;
std::string errorMsg;
std::string uid = req.ssl_id();
std::string path = req.path();
DirDetails details;
if (uid.empty())
{
uid = rsPeers->getOwnId();
}
std::cerr << "RpcProtoFiles::processReqShareDirList() For uid: " << uid << " & path: " << path;
std::cerr << std::endl;
if (path.empty())
{
/* we have to do a nasty hack to get anything useful.
* we do a ref=NULL to get the pointers to People,
* then use the correct one to get root directories
*/
std::cerr << "RpcProtoFiles::processReqShareDirList() Hack to get root Dirs!";
std::cerr << std::endl;
FileSearchFlags flags;
if (uid == rsPeers->getOwnId())
{
flags |= RS_FILE_HINTS_LOCAL;
}
DirDetails root_details;
if (!rsFiles->RequestDirDetails(NULL, root_details, flags))
{
std::cerr << "RpcProtoFiles::processReqShareDirList() ref=NULL Hack failed";
std::cerr << std::endl;
success = false;
errorMsg = "Root Directory Request Failed.";
}
else
{
void *person_ref = NULL;
std::list<DirStub>::iterator sit;
for(sit = root_details.children.begin(); sit != root_details.children.end(); sit++)
{
//std::cerr << "RpcProtoFiles::processReqShareDirList() Root.child->name : " << sit->name;
if (sit->name == uid)
{
person_ref = sit->ref;
break;
}
}
if (!person_ref)
{
std::cerr << "RpcProtoFiles::processReqShareDirList() Person match failed";
std::cerr << std::endl;
success = false;
errorMsg = "Missing Person Root Directory.";
}
else
{
// Doing the REAL request!
if (!rsFiles->RequestDirDetails(person_ref, details, flags))
{
std::cerr << "RpcProtoFiles::processReqShareDirList() Personal Shared Dir Hack failed";
std::cerr << std::endl;
success = false;
errorMsg = "Missing Person Shared Directories";
}
}
}
}
else
{
// Path must begin with / for proper matching.
if (path[0] != '/')
{
path = '/' + path;
}
if (!rsFiles->RequestDirDetails(uid, path, details))
{
std::cerr << "RpcProtoFiles::processReqShareDirList() ERROR Unknown Dir";
std::cerr << std::endl;
success = false;
errorMsg = "Directory Request Failed.";
}
}
if (success)
{
// setup basics of response.
resp.set_ssl_id(uid);
resp.set_path(path);
switch(details.type)
{
case DIR_TYPE_ROOT:
{
std::cerr << "RpcProtoFiles::processReqShareDirList() Details.type == ROOT ??";
std::cerr << std::endl;
resp.set_list_type(rsctrl::files::ResponseShareDirList::DIRQUERY_ROOT);
rsctrl::core::File *file = resp.add_files();
fill_file_as_dir(file, details.name);
}
break;
case DIR_TYPE_FILE:
{
std::cerr << "RpcProtoFiles::processReqShareDirList() Details.type == FILE";
std::cerr << std::endl;
resp.set_list_type(rsctrl::files::ResponseShareDirList::DIRQUERY_FILE);
rsctrl::core::File *file = resp.add_files();
fill_file_from_details(file, details);
}
break;
default:
std::cerr << "RpcProtoFiles::processReqShareDirList() Details.type == UNKNOWN => default to DIR";
std::cerr << std::endl;
case DIR_TYPE_PERSON:
case DIR_TYPE_DIR:
{
std::cerr << "RpcProtoFiles::processReqShareDirList() Details.type == DIR or PERSON";
std::cerr << std::endl;
resp.set_list_type(rsctrl::files::ResponseShareDirList::DIRQUERY_DIR);
//std::string dir_path = RsDirUtil::makePath(details.path, details.name);
std::string dir_path = details.path;
std::cerr << "RpcProtoFiles::processReqShareDirList() details.path: " << details.path;
std::cerr << " details.name: " << details.name;
std::cerr << std::endl;
std::list<DirStub>::iterator sit;
for(sit = details.children.begin(); sit != details.children.end(); sit++)
{
std::cerr << "RpcProtoFiles::processReqShareDirList() checking child: " << sit->name;
std::cerr << std::endl;
if (sit->type == DIR_TYPE_FILE)
{
std::cerr << "RpcProtoFiles::processReqShareDirList() is FILE, fetching details.";
std::cerr << std::endl;
DirDetails child_details;
std::string child_path = RsDirUtil::makePath(dir_path, sit->name);
if (rsFiles->RequestDirDetails(uid, child_path, child_details))
{
rsctrl::core::File *file = resp.add_files();
fill_file_from_details(file, child_details);
}
else
{
std::cerr << "RpcProtoFiles::processReqShareDirList() RequestDirDetails(" << child_path << ") Failed!!!";
std::cerr << std::endl;
}
}
else
{
std::cerr << "RpcProtoFiles::processReqShareDirList() is DIR";
std::cerr << std::endl;
rsctrl::core::File *file = resp.add_files();
fill_file_as_dir(file, sit->name);
}
}
}
break;
}
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoFiles::processReqTransferList() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::FILES,
rsctrl::files::MsgId_ResponseShareDirList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
/***** HELPER FUNCTIONS *****/
bool fill_file_from_details(rsctrl::core::File *file, DirDetails &details)
{
file->set_hash(details.hash);
file->set_name(details.name);
file->set_size(details.count);
return true;
}
bool fill_file_as_dir(rsctrl::core::File *file, const std::string &dir_name)
{
file->set_hash("");
file->set_name(dir_name);
file->set_size(0);
return true;
}

View File

@ -1,45 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_FILES_H
#define RS_RPC_PROTO_FILES_H
#include "rpc/rpcserver.h"
class RpcProtoFiles: public RpcQueueService
{
public:
RpcProtoFiles(uint32_t serviceId);
virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
protected:
int processReqTransferList(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqControlDownload(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqShareDirList(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg);
};
#endif /* RS_PROTO_FILES_H */

View File

@ -1,610 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotopeers.h"
#include "rpc/proto/gencc/peers.pb.h"
#include <retroshare/rspeers.h>
#include <retroshare/rsdisc.h>
#include <iostream>
#include <algorithm>
bool load_person_details(std::string pgp_id, rsctrl::core::Person *person,
bool getLocations, bool onlyConnected);
RpcProtoPeers::RpcProtoPeers(uint32_t serviceId)
:RpcQueueService(serviceId)
{
return;
}
//RpcProtoPeers::msgsAccepted(std::list<uint32_t> &msgIds); /* not used at the moment */
int RpcProtoPeers::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* check the msgId */
uint8_t topbyte = getRpcMsgIdExtension(msg_id);
uint16_t service = getRpcMsgIdService(msg_id);
uint8_t submsg = getRpcMsgIdSubMsg(msg_id);
bool isResponse = isRpcMsgIdResponse(msg_id);
std::cerr << "RpcProtoPeers::processMsg() topbyte: " << (int32_t) topbyte;
std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg;
std::cerr << std::endl;
if (isResponse)
{
std::cerr << "RpcProtoPeers::processMsg() isResponse() - not processing";
std::cerr << std::endl;
return 0;
}
if (topbyte != (uint8_t) rsctrl::core::CORE)
{
std::cerr << "RpcProtoPeers::processMsg() Extension Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (service != (uint16_t) rsctrl::core::PEERS)
{
std::cerr << "RpcProtoPeers::processMsg() Service Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (!rsctrl::peers::RequestMsgIds_IsValid(submsg))
{
std::cerr << "RpcProtoPeers::processMsg() SubMsg Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
switch(submsg)
{
case rsctrl::peers::MsgId_RequestPeers:
processRequestPeers(chan_id, msg_id, req_id, msg);
break;
case rsctrl::peers::MsgId_RequestAddPeer:
processAddPeer(chan_id, msg_id, req_id, msg);
break;
case rsctrl::peers::MsgId_RequestExaminePeer:
processExaminePeer(chan_id, msg_id, req_id, msg);
break;
//case rsctrl::peers::MsgId_RequestModifyPeer:
// processModifyPeer(chan_id, msg_id, req_id, msg);
// break;
default:
std::cerr << "RpcProtoPeers::processMsg() ERROR should never get here";
std::cerr << std::endl;
return 0;
}
/* must have matched id to get here */
return 1;
}
int RpcProtoPeers::processAddPeer(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoPeers::processAddPeer()";
std::cerr << std::endl;
// parse msg.
rsctrl::peers::RequestAddPeer req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoPeers::processAddPeer() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::peers::ResponsePeerList resp;
bool success = true;
std::string errorMsg;
/* check if the gpg_id is valid */
std::string pgp_id = req.pgp_id();
std::string ssl_id;
if (req.has_ssl_id())
{
ssl_id = req.ssl_id();
}
RsPeerDetails details;
if (!rsPeers->getGPGDetails(pgp_id, details))
{
success = false;
errorMsg = "Invalid PGP ID";
}
else
{
switch(req.cmd())
{
default:
success = false;
errorMsg = "Invalid AddCmd";
break;
case rsctrl::peers::RequestAddPeer::ADD:
// TODO. NEED TO HANDLE SERVICE PERMISSION FLAGS.
success = rsPeers->addFriend(ssl_id,pgp_id, RS_NODE_PERM_DEFAULT);
break;
case rsctrl::peers::RequestAddPeer::REMOVE:
success = rsPeers->removeFriend(pgp_id);
break;
}
if (success)
{
rsctrl::core::Person *person = resp.add_peers();
load_person_details(pgp_id, person, true, false);
}
}
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::NO_IMPL_YET);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoPeers::processAddPeer() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS,
rsctrl::peers::MsgId_ResponsePeerList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoPeers::processExaminePeer(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoPeers::processExaminePeer() NOT FINISHED";
std::cerr << std::endl;
// parse msg.
rsctrl::peers::RequestExaminePeer req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoPeers::processExaminePeer() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::peers::ResponsePeerList resp;
bool success = false;
if (success)
{
switch(req.cmd())
{
default:
success = false;
break;
case rsctrl::peers::RequestExaminePeer::IMPORT:
break;
case rsctrl::peers::RequestExaminePeer::EXAMINE:
// Gets the GPG details, but does not add the key to the keyring.
//virtual bool loadDetailsFromStringCert(const std::string& certGPG, RsPeerDetails &pd,uint32_t& error_code) = 0;
break;
}
}
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::NO_IMPL_YET);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoPeers::processAddPeer() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS,
rsctrl::peers::MsgId_ResponsePeerList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoPeers::processModifyPeer(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoPeers::processModifyPeer() NOT FINISHED";
std::cerr << std::endl;
// parse msg.
rsctrl::peers::RequestModifyPeer req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoPeers::processModifyPeer() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::peers::ResponsePeerList resp;
bool success = false;
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::NO_IMPL_YET);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoPeers::processModifyPeer() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS,
rsctrl::peers::MsgId_ResponsePeerList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoPeers::processRequestPeers(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoPeers::processRequestPeers()";
std::cerr << std::endl;
// parse msg.
rsctrl::peers::RequestPeers reqp;
if (!reqp.ParseFromString(msg))
{
std::cerr << "RpcProtoPeers::processRequestPeers() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::peers::ResponsePeerList respp;
bool success = true;
std::string errorMsg;
// Get the list of gpg_id to generate data for.
std::list<std::string> ids;
bool onlyConnected = false;
switch(reqp.set())
{
case rsctrl::peers::RequestPeers::OWNID:
{
std::cerr << "RpcProtoPeers::processRequestPeers() OWNID";
std::cerr << std::endl;
std::string own_id = rsPeers->getGPGOwnId();
ids.push_back(own_id);
break;
}
case rsctrl::peers::RequestPeers::LISTED:
{
std::cerr << "RpcProtoPeers::processRequestPeers() LISTED";
std::cerr << std::endl;
int no_pgp_ids = reqp.pgp_ids_size();
for (int i = 0; i < no_pgp_ids; i++)
{
std::string listed_id = reqp.pgp_ids(i);
std::cerr << "RpcProtoPeers::processRequestPeers() Adding Id: " << listed_id;
std::cerr << std::endl;
ids.push_back(listed_id);
}
break;
}
case rsctrl::peers::RequestPeers::ALL:
std::cerr << "RpcProtoPeers::processRequestPeers() ALL";
std::cerr << std::endl;
rsPeers->getGPGAllList(ids);
break;
case rsctrl::peers::RequestPeers::CONNECTED:
{
std::cerr << "RpcProtoPeers::processRequestPeers() CONNECTED";
std::cerr << std::endl;
/* this ones a bit hard too */
onlyConnected = true;
std::list<std::string> ssl_ids;
std::list<std::string>::const_iterator sit;
rsPeers->getOnlineList(ssl_ids);
for(sit = ssl_ids.begin(); sit != ssl_ids.end(); sit++)
{
std::string gpg_id = rsPeers->getGPGId(*sit);
if (gpg_id.size() > 0)
{
if (std::find(ids.begin(), ids.end(),gpg_id) == ids.end())
{
ids.push_back(gpg_id);
}
}
}
break;
}
case rsctrl::peers::RequestPeers::FRIENDS:
std::cerr << "RpcProtoPeers::processRequestPeers() FRIENDS";
std::cerr << std::endl;
rsPeers->getGPGAcceptedList(ids);
break;
case rsctrl::peers::RequestPeers::SIGNED:
std::cerr << "RpcProtoPeers::processRequestPeers() SIGNED";
std::cerr << std::endl;
rsPeers->getGPGSignedList(ids);
break;
case rsctrl::peers::RequestPeers::VALID:
std::cerr << "RpcProtoPeers::processRequestPeers() VALID";
std::cerr << std::endl;
rsPeers->getGPGSignedList(ids);
break;
}
// work out what data we need to request.
bool getLocations = false;
switch(reqp.info())
{
default:
case rsctrl::peers::RequestPeers::NAMEONLY:
case rsctrl::peers::RequestPeers::BASIC:
break;
case rsctrl::peers::RequestPeers::LOCATION:
case rsctrl::peers::RequestPeers::ALLINFO:
getLocations = true;
break;
}
/* now iterate through the peers and fill in the response. */
std::list<std::string>::const_iterator git;
for(git = ids.begin(); git != ids.end(); git++)
{
rsctrl::core::Person *person = respp.add_peers();
if (!load_person_details(*git, person, getLocations, onlyConnected))
{
std::cerr << "RpcProtoPeers::processRequestPeers() ERROR Finding GPGID: ";
std::cerr << *git;
std::cerr << std::endl;
/* cleanup peers */
success = false;
errorMsg = "Error Loading PeerID";
}
}
if (success)
{
rsctrl::core::Status *status = respp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = respp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!respp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoPeers::processRequestPeers() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS,
rsctrl::peers::MsgId_ResponsePeerList, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
bool load_person_details(std::string pgp_id, rsctrl::core::Person *person,
bool getLocations, bool onlyConnected)
{
RsPeerDetails details;
if (!rsPeers->getGPGDetails(pgp_id, details))
{
std::cerr << "RpcProtoPeers::processRequestPeers() ERROR Finding GPGID: ";
std::cerr << pgp_id;
std::cerr << std::endl;
return false;
}
/* fill in key gpg details */
person->set_gpg_id(pgp_id);
person->set_name(details.name);
std::cerr << "RpcProtoPeers::processRequestPeers() Adding GPGID: ";
std::cerr << pgp_id << " name: " << details.name;
std::cerr << std::endl;
//if (details.state & RS_PEER_STATE_FRIEND)
if (pgp_id == rsPeers->getGPGOwnId())
{
std::cerr << "RpcProtoPeers::processRequestPeers() Relation YOURSELF";
std::cerr << std::endl;
person->set_relation(rsctrl::core::Person::YOURSELF);
}
else if (rsPeers->isGPGAccepted(pgp_id))
{
std::cerr << "RpcProtoPeers::processRequestPeers() Relation FRIEND";
std::cerr << std::endl;
person->set_relation(rsctrl::core::Person::FRIEND);
}
else
{
std::list<std::string> common_friends;
rsDisc->getDiscPgpFriends(pgp_id, common_friends);
int size = common_friends.size();
if (size)
{
if (size > 2)
{
std::cerr << "RpcProtoPeers::processRequestPeers() Relation FRIEND_OF_MANY_FRIENDS";
std::cerr << std::endl;
person->set_relation(rsctrl::core::Person::FRIEND_OF_MANY_FRIENDS);
}
else
{
std::cerr << "RpcProtoPeers::processRequestPeers() Relation FRIEND_OF_FRIENDS";
std::cerr << std::endl;
person->set_relation(rsctrl::core::Person::FRIEND_OF_FRIENDS);
}
}
else
{
std::cerr << "RpcProtoPeers::processRequestPeers() Relation UNKNOWN";
std::cerr << std::endl;
person->set_relation(rsctrl::core::Person::UNKNOWN);
}
}
if (getLocations)
{
std::list<std::string> ssl_ids;
std::list<std::string>::const_iterator sit;
if (!rsPeers->getAssociatedSSLIds(pgp_id, ssl_ids))
{
std::cerr << "RpcProtoPeers::processRequestPeers() No Locations";
std::cerr << std::endl;
return true; /* end of this peer */
}
for(sit = ssl_ids.begin(); sit != ssl_ids.end(); sit++)
{
RsPeerDetails ssldetails;
if (!rsPeers->getPeerDetails(*sit, ssldetails))
{
continue; /* uhm.. */
}
if ((onlyConnected) &&
(!(ssldetails.state & RS_PEER_STATE_CONNECTED)))
{
continue;
}
rsctrl::core::Location *loc = person->add_locations();
std::cerr << "RpcProtoPeers::processRequestPeers() \t Adding Location: ";
std::cerr << *sit << " loc: " << ssldetails.location;
std::cerr << std::endl;
/* fill in ssl details */
loc->set_ssl_id(*sit);
loc->set_location(ssldetails.location);
/* set addresses */
rsctrl::core::IpAddr *laddr = loc->mutable_localaddr();
laddr->set_addr(ssldetails.localAddr);
laddr->set_port(ssldetails.localPort);
rsctrl::core::IpAddr *eaddr = loc->mutable_extaddr();
eaddr->set_addr(ssldetails.extAddr);
eaddr->set_port(ssldetails.extPort);
/* translate status */
uint32_t loc_state = 0;
//dont think this state should be here.
//if (ssldetails.state & RS_PEER_STATE_FRIEND)
if (ssldetails.state & RS_PEER_STATE_ONLINE)
{
loc_state |= (uint32_t) rsctrl::core::Location::ONLINE;
}
if (ssldetails.state & RS_PEER_STATE_CONNECTED)
{
loc_state |= (uint32_t) rsctrl::core::Location::CONNECTED;
}
if (ssldetails.state & RS_PEER_STATE_UNREACHABLE)
{
loc_state |= (uint32_t) rsctrl::core::Location::UNREACHABLE;
}
loc->set_state(loc_state);
}
}
return true; /* end of this peer */
}

View File

@ -1,46 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_PEERS_H
#define RS_RPC_PROTO_PEERS_H
#include "rpc/rpcserver.h"
class RpcProtoPeers: public RpcQueueService
{
public:
RpcProtoPeers(uint32_t serviceId);
// virtual msgsAccepted(std::list<uint32_t> &msgIds); /* not used at the moment */
virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
virtual int processRequestPeers(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
virtual int processAddPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
// these aren't implemented yet.
virtual int processExaminePeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
virtual int processModifyPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
};
#endif /* RS_PROTO_PEERS_H */

View File

@ -1,678 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotosearch.h"
#include "rpc/proto/gencc/search.pb.h"
#include "notifytxt.h"
#include <retroshare/rsturtle.h>
#include <retroshare/rsexpr.h>
#include "util/rsstring.h"
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
bool condenseSearchResults(const std::list<TurtleFileInfo> &searchResults, uint32_t limit,
rsctrl::search::SearchSet *result_set);
RpcProtoSearch::RpcProtoSearch(uint32_t serviceId, NotifyTxt *notify)
:RpcQueueService(serviceId), mNotify(notify), searchMtx("RpcProtoSearch")
{
return;
}
void RpcProtoSearch::reset(uint32_t chan_id)
{
RpcQueueService::reset(chan_id);
/* must clear all searches */
clear_searches(chan_id);
}
int RpcProtoSearch::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* check the msgId */
uint8_t topbyte = getRpcMsgIdExtension(msg_id);
uint16_t service = getRpcMsgIdService(msg_id);
uint8_t submsg = getRpcMsgIdSubMsg(msg_id);
bool isResponse = isRpcMsgIdResponse(msg_id);
std::cerr << "RpcProtoSearch::processMsg() topbyte: " << (int32_t) topbyte;
std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg;
std::cerr << std::endl;
if (isResponse)
{
std::cerr << "RpcProtoSearch::processMsg() isResponse() - not processing";
std::cerr << std::endl;
return 0;
}
if (topbyte != (uint8_t) rsctrl::core::CORE)
{
std::cerr << "RpcProtoSearch::processMsg() Extension Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (service != (uint16_t) rsctrl::core::SEARCH)
{
std::cerr << "RpcProtoSearch::processMsg() Service Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (!rsctrl::search::RequestMsgIds_IsValid(submsg))
{
std::cerr << "RpcProtoSearch::processMsg() SubMsg Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
switch(submsg)
{
case rsctrl::search::MsgId_RequestBasicSearch:
processReqBasicSearch(chan_id, msg_id, req_id, msg);
break;
case rsctrl::search::MsgId_RequestCloseSearch:
processReqCloseSearch(chan_id, msg_id, req_id, msg);
break;
case rsctrl::search::MsgId_RequestListSearches:
processReqListSearches(chan_id, msg_id, req_id, msg);
break;
case rsctrl::search::MsgId_RequestSearchResults:
processReqSearchResults(chan_id, msg_id, req_id, msg);
break;
default:
std::cerr << "RpcProtoSearch::processMsg() ERROR should never get here";
std::cerr << std::endl;
return 0;
}
/* must have matched id to get here */
return 1;
}
int RpcProtoSearch::processReqBasicSearch(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSearch::processReqBasicSearch()";
std::cerr << std::endl;
// parse msg.
rsctrl::search::RequestBasicSearch req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSearch::processReqBasicSearch() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::search::ResponseSearchIds resp;
bool success = true;
std::string errorMsg;
/* convert msg parameters into local ones */
std::list<std::string> terms;
int no_terms = req.terms_size();
for(int i = 0; i < no_terms; i++)
{
std::string term = req.terms(i);
/* check for valid term? */
if (term.size() > 0)
{
terms.push_back(term);
}
}
NameExpression nameexp(ContainsAllStrings, terms, true);
LinearizedExpression lexpr;
nameexp.linearize(lexpr);
uint32_t searchId = (uint32_t) rsTurtle->turtleSearch(lexpr);
mNotify->collectSearchResults(searchId);
/* add into search array */
add_search(chan_id, searchId);
/* add to answer */
resp.add_search_id(searchId);
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSearch::processReqBasicSearch() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH,
rsctrl::search::MsgId_ResponseSearchIds, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoSearch::processReqCloseSearch(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSearch::processReqCloseSearch()";
std::cerr << std::endl;
// parse msg.
rsctrl::search::RequestCloseSearch req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSearch::processReqCloseSearch() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::search::ResponseSearchIds resp;
bool success = true;
std::string errorMsg;
/* convert msg parameters into local ones */
uint32_t searchId = req.search_id();
/* remove into search array */
if (!remove_search(chan_id, searchId))
{
success = false;
errorMsg = "Unknown SearchId in List";
}
/* clear search results
* we cannot cancel a turtle search
* so we tell notify to ignore further results
*/
if (success)
{
if (!mNotify->clearSearchId(searchId))
{
success = false;
errorMsg = "Unknown SearchId in Notify";
}
}
/* add to answer */
if (success)
{
resp.add_search_id(searchId);
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSearch::processReqCloseSearch() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH,
rsctrl::search::MsgId_ResponseSearchIds, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoSearch::processReqListSearches(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSearch::processReqListSearches()";
std::cerr << std::endl;
// parse msg.
rsctrl::search::RequestListSearches req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSearch::processReqListSearches() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::search::ResponseSearchIds resp;
bool success = true;
std::string errorMsg;
/* convert msg parameters into local ones */
// Nothing to do.
std::list<uint32_t> reg_search_ids;
std::list<uint32_t>::iterator it;
if (!get_search_list(chan_id, reg_search_ids))
{
/* warning */
success = false;
errorMsg = "No Searches Active";
}
/* iterate through search array */
for(it = reg_search_ids.begin(); it != reg_search_ids.end(); it++)
{
/* add to answer */
resp.add_search_id(*it);
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSearch::processReqListSearches() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH,
rsctrl::search::MsgId_ResponseSearchIds, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoSearch::processReqSearchResults(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSearch::processReqSearchResults()";
std::cerr << std::endl;
// parse msg.
rsctrl::search::RequestSearchResults req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSearch::processReqSearchResults() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::search::ResponseSearchResults resp;
bool success = true;
std::string errorMsg;
/* convert msg parameters into local ones */
std::list<uint32_t> reg_search_ids;
std::list<uint32_t> requested_search_ids;
if (!get_search_list(chan_id, reg_search_ids))
{
/* warning */
}
int no_searches = req.search_ids_size();
if (no_searches)
{
/* painful check that they are our searches */
for(int i = 0; i < no_searches; i++)
{
uint32_t search_id = req.search_ids(i);
/* check that its in reg_search_ids */
if (reg_search_ids.end() != std::find(reg_search_ids.begin(), reg_search_ids.end(), search_id))
{
/* error */
continue;
}
requested_search_ids.push_back(search_id);
}
}
else
{
/* all current searches */
requested_search_ids = reg_search_ids;
}
std::list<uint32_t>::iterator rit;
for(rit = requested_search_ids.begin();
rit != requested_search_ids.end(); rit++)
{
rsctrl::search::SearchSet *set = resp.add_searches();
/* add to answer */
set->set_search_id(*rit);
/* no search details at the moment */
/* add into search array */
std::list<TurtleFileInfo>::iterator it;
std::list<TurtleFileInfo> searchResults;
mNotify->getSearchResults(*rit, searchResults);
condenseSearchResults(searchResults, req.result_limit(), set);
}
/* DONE - Generate Reply */
/* different to others - partial success possible */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSearch::processReqSearchResults() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH,
rsctrl::search::MsgId_ResponseSearchResults, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
/***** HELPER FUNCTIONS *****/
// These private functions use Mutex below and manipulate mActiveSearches.
int RpcProtoSearch::get_search_list(uint32_t chan_id, std::list<uint32_t> &search_ids)
{
std::cerr << "RpcProtoSearch::get_search_list(" << chan_id << ")";
std::cerr << std::endl;
RsStackMutex stack(searchMtx); /******* LOCKED *********/
std::map<uint32_t, std::list<uint32_t> >::iterator mit;
mit = mActiveSearches.find(chan_id);
if (mit == mActiveSearches.end())
{
return 0;
}
search_ids = mit->second;
return 1;
}
int RpcProtoSearch::add_search(uint32_t chan_id, uint32_t search_id)
{
std::cerr << "RpcProtoSearch::add_search(" << chan_id << ", " << search_id << ")";
std::cerr << std::endl;
RsStackMutex stack(searchMtx); /******* LOCKED *********/
std::map<uint32_t, std::list<uint32_t> >::iterator mit;
mit = mActiveSearches.find(chan_id);
if (mit == mActiveSearches.end())
{
std::list<uint32_t> emptyList;
mActiveSearches[chan_id] = emptyList;
mit = mActiveSearches.find(chan_id);
}
/* sanity check */
if (mit->second.end() != std::find(mit->second.begin(), mit->second.end(), search_id))
{
std::cerr << "RpcProtoSearch::add_search() ERROR search_id already exists";
std::cerr << std::endl;
return 0;
}
mit->second.push_back(search_id);
return 1;
}
int RpcProtoSearch::remove_search(uint32_t chan_id, uint32_t search_id)
{
std::cerr << "RpcProtoSearch::remove_search(" << chan_id << ", " << search_id << ")";
std::cerr << std::endl;
RsStackMutex stack(searchMtx); /******* LOCKED *********/
std::map<uint32_t, std::list<uint32_t> >::iterator mit;
mit = mActiveSearches.find(chan_id);
if (mit == mActiveSearches.end())
{
std::cerr << "RpcProtoSearch::remove_search() ERROR search set doesn't exist";
std::cerr << std::endl;
return 0;
}
bool removed = false;
std::list<uint32_t>::iterator lit;
for(lit = mit->second.begin(); lit != mit->second.end();)
{
if (*lit == search_id)
{
lit = mit->second.erase(lit);
if (removed)
{
std::cerr << "RpcProtoSearch::remove_search() ERROR removed multiple";
std::cerr << std::endl;
}
removed = true;
}
else
{
lit++;
}
}
if (removed)
return 1;
std::cerr << "RpcProtoSearch::remove_search() ERROR search_id not found";
std::cerr << std::endl;
return 0;
}
int RpcProtoSearch::clear_searches(uint32_t chan_id)
{
std::cerr << "RpcProtoSearch::clear_searches(" << chan_id << ")";
std::cerr << std::endl;
RsStackMutex stack(searchMtx); /******* LOCKED *********/
std::map<uint32_t, std::list<uint32_t> >::iterator mit;
mit = mActiveSearches.find(chan_id);
if (mit == mActiveSearches.end())
{
std::cerr << "RpcProtoSearch::clear_searches() WARNING search set not found";
std::cerr << std::endl;
return 0;
}
mActiveSearches.erase(mit);
return 1;
}
class RpcSearchInfo
{
public:
std::string hash;
std::string name;
uint64_t size;
std::map<std::string, uint32_t> name_map;
uint32_t hits;
};
bool condenseSearchResults(const std::list<TurtleFileInfo> &searchResults, uint32_t limit,
rsctrl::search::SearchSet *result_set)
{
std::map<std::string, RpcSearchInfo> searchMap;
std::map<std::string, RpcSearchInfo>::iterator mit;
std::list<TurtleFileInfo>::const_iterator it;
for(it = searchResults.begin(); it != searchResults.end(); it++)
{
mit = searchMap.find(it->hash);
if (mit != searchMap.end())
{
mit->second.hits++;
if (mit->second.name_map.find(it->name) == mit->second.name_map.end())
{
mit->second.name_map[it->name] = 1;
}
else
{
mit->second.name_map[it->name]++;
}
if (it->size != mit->second.size)
{
// ERROR.
}
}
else
{
RpcSearchInfo info;
info.hash = it->hash;
info.size = it->size;
info.name_map[it->name] = 1;
info.hits = 1;
searchMap[it->hash] = info;
}
}
unsigned int i = 0;
for(mit = searchMap.begin(); (mit != searchMap.end()) && (i < limit || limit == 0); mit++, i++)
{
std::map<std::string, uint32_t>::reverse_iterator nit;
nit = mit->second.name_map.rbegin();
/* add to answer */
rsctrl::search::SearchHit *hit = result_set->add_hits();
rsctrl::core::File *file = hit->mutable_file();
file->set_hash(mit->second.hash);
file->set_name(nit->first);
file->set_size(mit->second.size);
// Uhm not provided for now. default to NETWORK
hit->set_loc(rsctrl::search::SearchHit::NETWORK);
hit->set_no_hits(mit->second.hits); // No aggregation yet.
// guarenteed to have one item here.
for(nit++; nit != mit->second.name_map.rend(); nit++)
{
hit->add_alt_names(nit->first);
}
}
return true;
}

View File

@ -1,64 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_SEARCH_H
#define RS_RPC_PROTO_SEARCH_H
#include "rpc/rpcserver.h"
class NotifyTxt;
class RpcProtoSearch: public RpcQueueService
{
public:
RpcProtoSearch(uint32_t serviceId, NotifyTxt *notify);
virtual void reset(uint32_t chan_id);
virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
protected:
int processReqBasicSearch(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqCloseSearch(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqListSearches(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqSearchResults(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
private:
// These private functions use Mutex below and manipulate mActiveSearches.
int get_search_list(uint32_t chan_id, std::list<uint32_t> &search_ids);
int add_search(uint32_t chan_id, uint32_t search_id);
int remove_search(uint32_t chan_id, uint32_t search_id);
int clear_searches(uint32_t chan_id);
NotifyTxt *mNotify;
RsMutex searchMtx;
/* must store list of active searches per channel */
std::map<uint32_t, std::list<uint32_t> > mActiveSearches;
};
#endif /* RS_PROTO_SEARCH_H */

View File

@ -1,825 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotostream.h"
#include "rpc/proto/rpcprotoutils.h"
#include "rpc/proto/gencc/stream.pb.h"
#include "rpc/proto/gencc/core.pb.h"
#include <retroshare/rsexpr.h>
#include <retroshare/rsfiles.h>
// from libretroshare
#include "util/rsdir.h"
//#include <retroshare/rsmsgs.h>
//#include <retroshare/rspeers.h>
//#include <retroshare/rshistory.h>
#include "util/rsstring.h"
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#define MAX_DESIRED_RATE 1000.0 // 1Mb/s
#define MIN_STREAM_CHUNK_SIZE 10
#define MAX_STREAM_CHUNK_SIZE 100000
#define STREAM_STANDARD_MIN_DT 0.1
#define STREAM_BACKGROUND_MIN_DT 0.5
bool fill_stream_details(rsctrl::stream::ResponseStreamDetail &resp,
const std::list<RpcStream> &streams);
bool fill_stream_desc(rsctrl::stream::StreamDesc &desc,
const RpcStream &stream);
bool fill_stream_data(rsctrl::stream::StreamData &data, const RpcStream &stream);
bool createQueuedStreamMsg(const RpcStream &stream, rsctrl::stream::ResponseStreamData &resp, RpcQueuedMsg &qmsg);
RpcProtoStream::RpcProtoStream(uint32_t serviceId)
:RpcQueueService(serviceId)
{
mNextStreamId = 1;
return;
}
void RpcProtoStream::reset(uint32_t chan_id)
{
// We should be using a mutex for all stream operations!!!!
// TODO
//RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::list<uint32_t> toRemove;
std::map<uint32_t, RpcStream>::iterator it;
for(it = mStreams.begin(); it != mStreams.end(); it++)
{
if (it->second.chan_id == chan_id)
{
toRemove.push_back(it->first);
}
}
std::list<uint32_t>::iterator rit;
for(rit = toRemove.begin(); rit != toRemove.end(); rit++)
{
it = mStreams.find(*rit);
if (it != mStreams.end())
{
mStreams.erase(it);
}
}
// Call the rest of reset.
RpcQueueService::reset(chan_id);
}
//RpcProtoStream::msgsAccepted(std::list<uint32_t> &msgIds); /* not used at the moment */
int RpcProtoStream::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* check the msgId */
uint8_t topbyte = getRpcMsgIdExtension(msg_id);
uint16_t service = getRpcMsgIdService(msg_id);
uint8_t submsg = getRpcMsgIdSubMsg(msg_id);
bool isResponse = isRpcMsgIdResponse(msg_id);
std::cerr << "RpcProtoStream::processMsg() topbyte: " << (int32_t) topbyte;
std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg;
std::cerr << std::endl;
if (isResponse)
{
std::cerr << "RpcProtoStream::processMsg() isResponse() - not processing";
std::cerr << std::endl;
return 0;
}
if (topbyte != (uint8_t) rsctrl::core::CORE)
{
std::cerr << "RpcProtoStream::processMsg() Extension Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (service != (uint16_t) rsctrl::core::STREAM)
{
std::cerr << "RpcProtoStream::processMsg() Service Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (!rsctrl::stream::RequestMsgIds_IsValid(submsg))
{
std::cerr << "RpcProtoStream::processMsg() SubMsg Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
switch(submsg)
{
case rsctrl::stream::MsgId_RequestStartFileStream:
processReqStartFileStream(chan_id, msg_id, req_id, msg);
break;
case rsctrl::stream::MsgId_RequestControlStream:
processReqControlStream(chan_id, msg_id, req_id, msg);
break;
case rsctrl::stream::MsgId_RequestListStreams:
processReqListStreams(chan_id, msg_id, req_id, msg);
break;
// case rsctrl::stream::MsgId_RequestRegisterStreams:
// processReqRegisterStreams(chan_id, msg_id, req_id, msg);
// break;
default:
std::cerr << "RpcProtoStream::processMsg() ERROR should never get here";
std::cerr << std::endl;
return 0;
}
/* must have matched id to get here */
return 1;
}
int RpcProtoStream::processReqStartFileStream(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoStream::processReqStartFileStream()";
std::cerr << std::endl;
// parse msg.
rsctrl::stream::RequestStartFileStream req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoStream::processReqStartFileStream() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::stream::ResponseStreamDetail resp;
bool success = true;
std::string errorMsg;
// SETUP STREAM.
// FIND the FILE.
std::list<std::string> hashes;
hashes.push_back(req.file().hash());
//HashExpression exp(StringOperator::EqualsString, hashes);
HashExpression exp(EqualsString, hashes);
std::list<DirDetails> results;
FileSearchFlags flags = RS_FILE_HINTS_LOCAL;
int ans = rsFiles->SearchBoolExp(&exp, results, flags);
// CREATE A STREAM OBJECT.
if (results.size() < 1)
{
success = false;
errorMsg = "No Matching File";
}
else
{
DirDetails &dirdetail = results.front();
RpcStream stream;
stream.chan_id = chan_id;
stream.req_id = req_id;
stream.stream_id = getNextStreamId();
stream.state = RpcStream::RUNNING;
// Convert to Full local path.
std::string virtual_path = RsDirUtil::makePath(dirdetail.path, dirdetail.name);
if (!rsFiles->ConvertSharedFilePath(virtual_path, stream.path))
{
success = false;
errorMsg = "Cannot Match to Shared Directory";
}
stream.length = dirdetail.count;
stream.hash = dirdetail.hash;
stream.name = dirdetail.name;
stream.offset = 0;
stream.start_byte = 0;
stream.end_byte = stream.length;
stream.desired_rate = req.rate_kbs();
if (stream.desired_rate > MAX_DESIRED_RATE)
{
stream.desired_rate = MAX_DESIRED_RATE;
}
// make response
rsctrl::stream::StreamDesc *desc = resp.add_streams();
if (!fill_stream_desc(*desc, stream))
{
success = false;
errorMsg = "Failed to Invalid Action";
}
else
{
// insert.
mStreams[stream.stream_id] = stream;
// register the stream too.
std::cerr << "RpcProtoStream::processReqStartFileStream() Registering the stream event.";
std::cerr << std::endl;
registerForEvents(chan_id, req_id, REGISTRATION_STREAMS);
}
std::cerr << "RpcProtoStream::processReqStartFileStream() List of Registered Streams:";
std::cerr << std::endl;
printEventRegister(std::cerr);
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoStream::processReqStartFileStream() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::STREAM,
rsctrl::stream::MsgId_ResponseStreamDetail, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoStream::processReqControlStream(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoStream::processReqControlStream()";
std::cerr << std::endl;
// parse msg.
rsctrl::stream::RequestControlStream req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoStream::processReqControlStream() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::stream::ResponseStreamDetail resp;
bool success = true;
std::string errorMsg;
// FIND MATCHING STREAM.
std::map<uint32_t, RpcStream>::iterator it;
it = mStreams.find(req.stream_id());
if (it != mStreams.end())
{
// TWEAK
if (it->second.state == RpcStream::STREAMERR)
{
if (req.action() == rsctrl::stream::RequestControlStream::STREAM_STOP)
{
it->second.state = RpcStream::FINISHED;
}
else
{
success = false;
errorMsg = "Stream Error";
}
}
else
{
switch(req.action())
{
case rsctrl::stream::RequestControlStream::STREAM_START:
if (it->second.state == RpcStream::PAUSED)
{
it->second.state = RpcStream::RUNNING;
}
break;
case rsctrl::stream::RequestControlStream::STREAM_STOP:
it->second.state = RpcStream::FINISHED;
break;
case rsctrl::stream::RequestControlStream::STREAM_PAUSE:
if (it->second.state == RpcStream::RUNNING)
{
it->second.state = RpcStream::PAUSED;
it->second.transfer_time = 0; // reset timings.
}
break;
case rsctrl::stream::RequestControlStream::STREAM_CHANGE_RATE:
it->second.desired_rate = req.rate_kbs();
break;
case rsctrl::stream::RequestControlStream::STREAM_SEEK:
if (req.seek_byte() < it->second.end_byte)
{
it->second.offset = req.seek_byte();
}
break;
default:
success = false;
errorMsg = "Invalid Action";
}
}
// FILL IN REPLY.
if (success)
{
rsctrl::stream::StreamDesc *desc = resp.add_streams();
if (!fill_stream_desc(*desc, it->second))
{
success = false;
errorMsg = "Invalid Action";
}
}
// Cleanup - TODO, this is explicit at the moment. - should be automatic after finish.
if (it->second.state == RpcStream::FINISHED)
{
deregisterForEvents(it->second.chan_id, it->second.req_id, REGISTRATION_STREAMS);
mStreams.erase(it);
}
}
else
{
success = false;
errorMsg = "No Matching Stream";
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoStream::processReqControlStream() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::STREAM,
rsctrl::stream::MsgId_ResponseStreamDetail, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoStream::processReqListStreams(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoStream::processReqListStreams()";
std::cerr << std::endl;
// parse msg.
rsctrl::stream::RequestListStreams req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoStream::processReqListStreams() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// response.
rsctrl::stream::ResponseStreamDetail resp;
bool success = false;
std::string errorMsg;
std::map<uint32_t, RpcStream>::iterator it;
for(it = mStreams.begin(); it != mStreams.end(); it++)
{
bool match = true;
// TODO fill in match!
/* check that it matches */
if (! match)
{
continue;
}
rsctrl::stream::StreamDesc *desc = resp.add_streams();
if (!fill_stream_desc(*desc, it->second))
{
success = false;
errorMsg = "Some Details Failed to Fill";
}
}
/* DONE - Generate Reply */
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg(errorMsg);
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoStream::processReqListStreams() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::STREAM,
rsctrl::stream::MsgId_ResponseStreamDetail, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
// EVENTS. (STREAMS)
int RpcProtoStream::locked_checkForEvents(uint32_t event, const std::list<RpcEventRegister> & /* registered */, std::list<RpcQueuedMsg> &stream_msgs)
{
/* only one event type for now */
if (event != REGISTRATION_STREAMS)
{
std::cerr << "ERROR Invalid Stream Event Type";
std::cerr << std::endl;
/* error */
return 0;
}
/* iterate through streams, and get next chunk of data.
* package up and send it.
* NOTE we'll have to something more complex for VoIP!
*/
double ts = getTimeStamp();
double dt = ts - mStreamRates.last_ts;
uint32_t data_sent = 0;
#define FILTER_K (0.75)
if (dt < 5.0) //mStreamRates.last_ts != 0)
{
mStreamRates.avg_dt = FILTER_K * mStreamRates.avg_dt
+ (1.0 - FILTER_K) * dt;
}
else
{
std::cerr << "RpcProtoStream::locked_checkForEvents() Large dT - resetting avg";
std::cerr << std::endl;
mStreamRates.avg_dt = 0.0;
}
mStreamRates.last_ts = ts;
std::map<uint32_t, RpcStream>::iterator it;
for(it = mStreams.begin(); it != mStreams.end(); it++)
{
RpcStream &stream = it->second;
if (!(stream.state == RpcStream::RUNNING))
{
continue;
}
double stream_dt = ts - stream.transfer_time;
switch(stream.transfer_type)
{
case RpcStream::REALTIME:
// let it go through always.
break;
case RpcStream::STANDARD:
if (stream_dt < STREAM_STANDARD_MIN_DT)
{
continue;
}
break;
case RpcStream::BACKGROUND:
if (stream_dt < STREAM_BACKGROUND_MIN_DT)
{
continue;
}
break;
}
if (!stream.transfer_time)
{
std::cerr << "RpcProtoStream::locked_checkForEvents() Null stream.transfer_time .. resetting";
std::cerr << std::endl;
stream.transfer_avg_dt = STREAM_STANDARD_MIN_DT;
}
else
{
std::cerr << "RpcProtoStream::locked_checkForEvents() stream.transfer_avg_dt: " << stream.transfer_avg_dt;
std::cerr << " stream_dt: " << stream_dt;
std::cerr << std::endl;
stream.transfer_avg_dt = FILTER_K * stream.transfer_avg_dt
+ (1.0 - FILTER_K) * stream_dt;
std::cerr << "RpcProtoStream::locked_checkForEvents() ==> stream.transfer_avg_dt: " << stream.transfer_avg_dt;
std::cerr << std::endl;
}
uint32_t size = stream.desired_rate * 1000.0 * stream.transfer_avg_dt;
stream.transfer_time = ts;
if (size < MIN_STREAM_CHUNK_SIZE)
{
size = MIN_STREAM_CHUNK_SIZE;
}
if (size > MAX_STREAM_CHUNK_SIZE)
{
size = MAX_STREAM_CHUNK_SIZE;
}
/* get data */
uint64_t remaining = stream.end_byte - stream.offset;
if (remaining < size)
{
size = remaining;
stream.state = RpcStream::FINISHED;
std::cerr << "RpcProtoStream::locked_checkForEvents() Sending Remaining: " << size;
std::cerr << std::endl;
}
std::cerr << "RpcProtoStream::locked_checkForEvents() Handling Stream: " << stream.stream_id << " state: " << stream.state;
std::cerr << std::endl;
std::cerr << "path: " << stream.path;
std::cerr << std::endl;
std::cerr << "offset: " << stream.offset;
std::cerr << " avg_dt: " << stream.transfer_avg_dt;
std::cerr << " x desired_rate: " << stream.desired_rate;
std::cerr << " => chunk_size: " << size;
std::cerr << std::endl;
/* fill in the answer */
rsctrl::stream::ResponseStreamData resp;
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
rsctrl::stream::StreamData *data = resp.mutable_data();
data->set_stream_id(stream.stream_id);
// convert state.
switch(stream.state)
{
case RpcStream::RUNNING:
data->set_stream_state(rsctrl::stream::STREAM_STATE_RUN);
break;
// This case cannot happen.
case RpcStream::PAUSED:
data->set_stream_state(rsctrl::stream::STREAM_STATE_PAUSED);
break;
// This can only happen at last chunk.
default:
case RpcStream::FINISHED:
data->set_stream_state(rsctrl::stream::STREAM_STATE_FINISHED);
break;
}
rsctrl::core::Timestamp *ts = data->mutable_send_time();
setTimeStamp(ts);
data->set_offset(stream.offset);
data->set_size(size);
if (fill_stream_data(*data, stream))
{
/* increment seek_location - for next request */
stream.offset += size;
RpcQueuedMsg qmsg;
if (createQueuedStreamMsg(stream, resp, qmsg))
{
std::cerr << "Created Stream Msg.";
std::cerr << std::endl;
stream_msgs.push_back(qmsg);
}
else
{
std::cerr << "ERROR Creating Stream Msg";
std::cerr << std::endl;
}
}
else
{
stream.state = RpcStream::STREAMERR;
std::cerr << "ERROR Filling Stream Data";
std::cerr << std::endl;
}
}
return 1;
}
// TODO
int RpcProtoStream::cleanup_checkForEvents(uint32_t /* event */, const std::list<RpcEventRegister> & /* registered */)
{
std::list<uint32_t> to_remove;
std::list<uint32_t>::iterator rit;
for(rit = to_remove.begin(); rit != to_remove.end(); rit++)
{
/* kill the stream! */
std::map<uint32_t, RpcStream>::iterator it;
it = mStreams.find(*rit);
if (it != mStreams.end())
{
mStreams.erase(it);
}
}
return 1;
}
/***** HELPER FUNCTIONS *****/
bool createQueuedStreamMsg(const RpcStream &stream, rsctrl::stream::ResponseStreamData &resp, RpcQueuedMsg &qmsg)
{
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoStream::createQueuedEventSendMsg() ERROR SerialiseToString()";
std::cerr << std::endl;
return false;
}
// Correctly Name Message.
qmsg.mMsgId = constructMsgId(rsctrl::core::CORE, rsctrl::core::STREAM,
rsctrl::stream::MsgId_ResponseStreamData, true);
qmsg.mChanId = stream.chan_id;
qmsg.mReqId = stream.req_id;
qmsg.mMsg = outmsg;
return true;
}
/****************** NEW HELPER FNS ******************/
bool fill_stream_details(rsctrl::stream::ResponseStreamDetail &resp,
const std::list<RpcStream> &streams)
{
std::cerr << "fill_stream_details()";
std::cerr << std::endl;
bool val = true;
std::list<RpcStream>::const_iterator it;
for (it = streams.begin(); it != streams.end(); it++)
{
rsctrl::stream::StreamDesc *desc = resp.add_streams();
val &= fill_stream_desc(*desc, *it);
}
return val;
}
bool fill_stream_desc(rsctrl::stream::StreamDesc &desc, const RpcStream &stream)
{
std::cerr << "fill_stream_desc()";
std::cerr << std::endl;
return true;
}
bool fill_stream_data(rsctrl::stream::StreamData &data, const RpcStream &stream)
{
/* fill the StreamData from stream */
/* open file */
FILE *fd = RsDirUtil::rs_fopen(stream.path.c_str(), "rb");
if (!fd)
{
std::cerr << "fill_stream_data() Failed to open file: " << stream.path;
std::cerr << std::endl;
return false;
}
uint32_t data_size = data.size();
uint64_t base_loc = data.offset();
void *buffer = malloc(data_size);
/* seek to correct spot */
fseeko64(fd, base_loc, SEEK_SET);
/* copy data into bytes */
if (1 != fread(buffer, data_size, 1, fd))
{
std::cerr << "fill_stream_data() Failed to get data. data_size=" << data_size << ", base_loc=" << base_loc << " !";
std::cerr << std::endl;
free(buffer);
return false;
}
data.set_stream_data(buffer, data_size);
free(buffer);
fclose(fd);
return true;
}
uint32_t RpcProtoStream::getNextStreamId()
{
return mNextStreamId++;
}

View File

@ -1,124 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_STREAM_H
#define RS_RPC_PROTO_STREAM_H
#include "rpc/rpcserver.h"
// Registrations.
#define REGISTRATION_STREAMS 1
class RpcStream
{
public:
RpcStream(): chan_id(0), req_id(0), stream_id(0), state(0),
offset(0), length(0), start_byte(0), end_byte(0), desired_rate(0),
transfer_type(0), transfer_time(0), transfer_avg_dt(0)
{ return; }
static const uint32_t STREAMERR = 0x00000;
static const uint32_t RUNNING = 0x00001;
static const uint32_t PAUSED = 0x00002;
static const uint32_t FINISHED = 0x00003;
uint32_t chan_id;
uint32_t req_id;
uint32_t stream_id;
uint32_t state;
std::string name;
std::string hash;
std::string path;
uint64_t offset; // where we currently are.
uint64_t length; // filesize.
uint64_t start_byte;
uint64_t end_byte;
float desired_rate; // Kb/s
// Transfer Type
static const uint32_t STANDARD = 0x00000;
static const uint32_t REALTIME = 0x00001;
static const uint32_t BACKGROUND = 0x00002;
uint32_t transfer_type;
double transfer_time;
double transfer_avg_dt;
};
class RpcStreamRates
{
public:
RpcStreamRates(): avg_data_rate(0), avg_dt(1), last_data_rate(0), last_ts(0) { return; }
double avg_data_rate;
double avg_dt;
double last_data_rate;
double last_ts;
};
class RpcProtoStream: public RpcQueueService
{
public:
RpcProtoStream(uint32_t serviceId);
virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
virtual void reset(uint32_t chan_id);
uint32_t getNextStreamId();
protected:
int processReqStartFileStream(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqControlStream(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqListStreams(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int processReqRegisterStreams(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
uint32_t mNextStreamId;
RpcStreamRates mStreamRates;
std::map<uint32_t, RpcStream> mStreams;
// EVENTS.
virtual int locked_checkForEvents(uint32_t event, const std::list<RpcEventRegister> &registered, std::list<RpcQueuedMsg> &events);
// Not actually used yet.
int cleanup_checkForEvents(uint32_t event, const std::list<RpcEventRegister> &registered);
};
#endif /* RS_PROTO_STREAM_H */

View File

@ -1,354 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotosystem.h"
#include "rpc/proto/gencc/system.pb.h"
#include <retroshare/rspeers.h>
#include <retroshare/rsconfig.h>
#include <retroshare/rsiface.h>
#include <retroshare/rsdht.h>
#include <iostream>
#include <algorithm>
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
uint16_t RpcProtoSystem::mExtPort = 0;
RpcProtoSystem::RpcProtoSystem(uint32_t serviceId)
:RpcQueueService(serviceId)
{
return;
}
//RpcProtoSystem::msgsAccepted(std::list<uint32_t> &msgIds); /* not used at the moment */
int RpcProtoSystem::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* check the msgId */
uint8_t topbyte = getRpcMsgIdExtension(msg_id);
uint16_t service = getRpcMsgIdService(msg_id);
uint8_t submsg = getRpcMsgIdSubMsg(msg_id);
bool isResponse = isRpcMsgIdResponse(msg_id);
std::cerr << "RpcProtoSystem::processMsg() topbyte: " << (int32_t) topbyte;
std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg;
std::cerr << std::endl;
if (isResponse)
{
std::cerr << "RpcProtoSystem::processMsg() isResponse() - not processing";
std::cerr << std::endl;
return 0;
}
if (topbyte != (uint8_t) rsctrl::core::CORE)
{
std::cerr << "RpcProtoSystem::processMsg() Extension Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (service != (uint16_t) rsctrl::core::SYSTEM)
{
std::cerr << "RpcProtoSystem::processMsg() Service Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
if (!rsctrl::system::RequestMsgIds_IsValid(submsg))
{
std::cerr << "RpcProtoSystem::processMsg() SubMsg Mismatch - not processing";
std::cerr << std::endl;
return 0;
}
switch(submsg)
{
case rsctrl::system::MsgId_RequestSystemStatus:
processSystemStatus(chan_id, msg_id, req_id, msg);
break;
#if 0
case rsctrl::system::MsgId_RequestSystemQuit:
processSystemQuit(chan_id, msg_id, req_id, msg);
break;
#endif
case rsctrl::system::MsgId_RequestSystemExternalAccess:
processSystemExternalAccess(chan_id, msg_id, req_id, msg);
break;
default:
std::cerr << "RpcProtoSystem::processMsg() ERROR should never get here";
std::cerr << std::endl;
return 0;
}
/* must have matched id to get here */
return 1;
}
int RpcProtoSystem::processSystemStatus(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSystem::processSystemStatus()";
std::cerr << std::endl;
// parse msg.
rsctrl::system::RequestSystemStatus req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSystem::processSystemStatus() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// NO Options... so go straight to answer.
// response.
rsctrl::system::ResponseSystemStatus resp;
bool success = true;
unsigned int nTotal = 0;
unsigned int nConnected = 0;
rsPeers->getPeerCount(&nTotal, &nConnected, false);
float downKb = 0;
float upKb = 0;
rsConfig->GetCurrentDataRates(downKb, upKb);
// set the data.
resp.set_no_peers(nTotal);
resp.set_no_connected(nConnected);
rsctrl::core::Bandwidth *bw = resp.mutable_bw_total();
bw->set_up(upKb);
bw->set_down(downKb);
bw->set_name("Total Connection Bandwidth");
uint32_t netState = rsConfig->getNetState();
std::string natState("Unknown");
rsctrl::system::ResponseSystemStatus_NetCode protoCode;
switch(netState)
{
default:
case RSNET_NETSTATE_BAD_UNKNOWN:
protoCode = rsctrl::system::ResponseSystemStatus::BAD_UNKNOWN;
break;
case RSNET_NETSTATE_BAD_OFFLINE:
protoCode = rsctrl::system::ResponseSystemStatus::BAD_OFFLINE;
break;
case RSNET_NETSTATE_BAD_NATSYM:
protoCode = rsctrl::system::ResponseSystemStatus::BAD_NATSYM;
break;
case RSNET_NETSTATE_BAD_NODHT_NAT:
protoCode = rsctrl::system::ResponseSystemStatus::BAD_NODHT_NAT;
break;
case RSNET_NETSTATE_WARNING_RESTART:
protoCode = rsctrl::system::ResponseSystemStatus::WARNING_RESTART;
break;
case RSNET_NETSTATE_WARNING_NATTED:
protoCode = rsctrl::system::ResponseSystemStatus::WARNING_NATTED;
break;
case RSNET_NETSTATE_WARNING_NODHT:
protoCode = rsctrl::system::ResponseSystemStatus::WARNING_NODHT;
break;
case RSNET_NETSTATE_GOOD:
protoCode = rsctrl::system::ResponseSystemStatus::GOOD;
break;
case RSNET_NETSTATE_ADV_FORWARD:
protoCode = rsctrl::system::ResponseSystemStatus::ADV_FORWARD;
break;
}
resp.set_net_status(protoCode);
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg("Unknown ERROR");
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSystem::processSystemStatus() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SYSTEM,
rsctrl::system::MsgId_ResponseSystemStatus, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoSystem::processSystemQuit(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSystem::processSystemQuit()";
std::cerr << std::endl;
// parse msg.
rsctrl::system::RequestSystemQuit req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSystem::processSystemQuit() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// NO Options... so go straight to answer.
// response.
rsctrl::system::ResponseSystemQuit resp;
bool success = true;
switch(req.quit_code())
{
default:
case rsctrl::system::RequestSystemQuit::CLOSE_CHANNEL:
{
RpcServer *server = getRpcServer();
server->error(chan_id, "CLOSE_CHANNEL");
break;
}
case rsctrl::system::RequestSystemQuit::SHUTDOWN_RS:
{
RsControl::instance()->rsGlobalShutDown();
break;
}
}
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg("Unknown ERROR");
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSystem::processSystemQuit() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SYSTEM,
rsctrl::system::MsgId_ResponseSystemQuit, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}
int RpcProtoSystem::processSystemExternalAccess(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcProtoSystem::processSystemExternalAccess()";
std::cerr << std::endl;
// parse msg.
rsctrl::system::RequestSystemExternalAccess req;
if (!req.ParseFromString(msg))
{
std::cerr << "RpcProtoSystem::processSystemExternalAccess() ERROR ParseFromString()";
std::cerr << std::endl;
return 0;
}
// NO Options... so go straight to answer.
// response.
rsctrl::system::ResponseSystemExternalAccess resp;
bool success = true;
std::string dhtKey;
if (!rsDht->getOwnDhtId(dhtKey))
{
success = false;
}
// have to set something anyway!.
resp.set_dht_key(dhtKey);
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
resp.set_ext_port(mExtPort);
if (success)
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::SUCCESS);
}
else
{
rsctrl::core::Status *status = resp.mutable_status();
status->set_code(rsctrl::core::Status::FAILED);
status->set_msg("Unknown ERROR");
}
std::string outmsg;
if (!resp.SerializeToString(&outmsg))
{
std::cerr << "RpcProtoSystem::processSystemExternalAccess() ERROR SerialiseToString()";
std::cerr << std::endl;
return 0;
}
// Correctly Name Message.
uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SYSTEM,
rsctrl::system::MsgId_ResponseSystemExternalAccess, true);
// queue it.
queueResponse(chan_id, out_msg_id, req_id, outmsg);
return 1;
}

View File

@ -1,47 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_SYSTEM_H
#define RS_RPC_PROTO_SYSTEM_H
#include "rpc/rpcserver.h"
class RpcProtoSystem: public RpcQueueService
{
public:
RpcProtoSystem(uint32_t serviceId);
// virtual msgsAccepted(std::list<uint32_t> &msgIds); /* not used at the moment */
virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
virtual int processSystemStatus(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
virtual int processSystemQuit(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
virtual int processSystemExternalAccess(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
static uint16_t mExtPort;
};
#endif /* RS_PROTO_SYSTEM_H */

View File

@ -1,59 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/proto/rpcprotoutils.h"
#include <sys/time.h>
double getTimeStamp()
{
struct timeval tv;
double ts = 0;
if (0 == gettimeofday(&tv, NULL))
{
ts = tv.tv_sec + (tv.tv_usec / 1000000.0);
}
return ts;
}
bool setTimeStamp(rsctrl::core::Timestamp *ts)
{
struct timeval tv;
if (0 != gettimeofday(&tv, NULL))
{
ts->set_secs(tv.tv_sec);
ts->set_microsecs(tv.tv_usec);
return true;
}
else
{
ts->set_secs(0);
ts->set_microsecs(0);
return false;
}
return false;
}

View File

@ -1,35 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_PROTO_UTILS_H
#define RS_RPC_PROTO_UTILS_H
#include "rpc/proto/gencc/core.pb.h"
double getTimeStamp();
bool setTimeStamp(rsctrl::core::Timestamp *ts);
#endif /* RS_RPC_PROTO_UTILS_H */

View File

@ -1,307 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/rpc.h"
#include "rpc/rpcserver.h"
// This one is inside libretroshare (BAD)!!!
#include "serialiser/rsbaseserial.h"
#include <iostream>
const uint32_t kMsgHeaderSize = 16;
const uint32_t kMsgMagicCode = 0x137f0001; // Arbitary + 0x0001
RpcMediator::RpcMediator(RpcComms *c)
:mComms(c), mServer(NULL)
{
return;
}
void RpcMediator::reset(uint32_t chan_id)
{
mServer->reset(chan_id);
}
int RpcMediator::error(uint32_t chan_id, std::string msg)
{
return mComms->error(chan_id, msg);
}
int RpcMediator::tick()
{
bool worked = false;
if (recv())
{
worked = true;
}
if (mServer->checkPending())
{
worked = true;
}
if (mServer->checkEvents())
{
worked = true;
}
if (worked)
return 1;
else
return 0;
return 0;
}
int RpcMediator::recv()
{
int recvd = 0;
std::list<uint32_t> chan_ids;
std::list<uint32_t>::iterator it;
mComms->active_channels(chan_ids);
for(it = chan_ids.begin(); it != chan_ids.end(); it++)
{
while(recv_msg(*it))
{
recvd = 1;
}
}
return recvd;
}
int RpcMediator::recv_msg(uint32_t chan_id)
{
/* nothing in here needs a Mutex... */
if (!mComms->recv_ready(chan_id))
{
return 0;
}
std::cerr << "RpcMediator::recv_msg() Data Ready";
std::cerr << std::endl;
/* read in data */
uint8_t buffer[kMsgHeaderSize];
uint32_t bufsize = kMsgHeaderSize;
uint32_t msg_id;
uint32_t req_id;
uint32_t msg_size;
std::string msg_body;
std::cerr << "RpcMediator::recv_msg() get Header: " << bufsize;
std::cerr << " bytes" << std::endl;
int read = mComms->recv_blocking(chan_id, buffer, bufsize);
if (read != bufsize)
{
/* error */
std::cerr << "RpcMediator::recv_msg() Error Reading Header: " << bufsize;
std::cerr << " bytes" << std::endl;
mComms->error(chan_id, "Failed to Recv Header");
return 0;
}
if (!MsgPacker::deserialiseHeader(msg_id, req_id, msg_size, buffer, bufsize))
{
/* error */
std::cerr << "RpcMediator::recv_msg() Error Deserialising Header";
std::cerr << std::endl;
mComms->error(chan_id, "Failed to Deserialise Header");
return 0;
}
std::cerr << "RpcMediator::recv_msg() ChanId: " << chan_id;
std::cerr << " MsgId: " << msg_id;
std::cerr << " ReqId: " << req_id;
std::cerr << std::endl;
std::cerr << "RpcMediator::recv_msg() get Body: " << msg_size;
std::cerr << " bytes" << std::endl;
/* grab real size */
read = mComms->recv_blocking(chan_id, msg_body, msg_size);
if (read != msg_size)
{
/* error */
std::cerr << "RpcMediator::recv_msg() Error Reading Body: " << bufsize;
std::cerr << " bytes" << std::endl;
mComms->error(chan_id, "Failed to Recv MsgBody");
return 0;
}
mServer->processMsg(chan_id, msg_id, req_id, msg_body);
return 1;
}
int RpcMediator::send(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcMediator::send(" << msg_id << "," << req_id << ", len(";
std::cerr << msg.size() << ")) on chan_id: " << chan_id;
std::cerr << std::endl;
uint8_t buffer[kMsgHeaderSize];
uint32_t bufsize = kMsgHeaderSize;
uint32_t msg_size = msg.size();
bool okay = MsgPacker::serialiseHeader(msg_id, req_id, msg_size, buffer, bufsize);
if (!okay)
{
std::cerr << "RpcMediator::send() SerialiseHeader Failed";
std::cerr << std::endl;
/* error */
return 0;
}
if (!mComms->send(chan_id, buffer, bufsize))
{
std::cerr << "RpcMediator::send() Send Header Failed";
std::cerr << std::endl;
/* error */
mComms->error(chan_id, "Failed to Send Header");
return 0;
}
/* now send the body */
if (!mComms->send(chan_id, msg))
{
std::cerr << "RpcMediator::send() Send Body Failed";
std::cerr << std::endl;
/* error */
mComms->error(chan_id, "Failed to Send Msg");
return 0;
}
return 1;
}
/* Msg Packing */
int MsgPacker::headersize()
{
return kMsgHeaderSize;
}
#if 0
int MsgPacker::msgsize(Message *msg)
{
/* */
return 0;
}
int MsgPacker::pktsize(Message *msg)
{
/* */
return headersize() + msgsize();
}
#endif
bool MsgPacker::serialiseHeader(uint32_t msg_id, uint32_t req_id, uint32_t msg_size, uint8_t *buffer, uint32_t bufsize)
{
/* check size */
if (bufsize < kMsgHeaderSize)
{
return false;
}
/* pack the data (using libretroshare serialiser for now */
void *data = buffer;
uint32_t offset = 0;
uint32_t size = bufsize;
bool ok = true;
/* 4 x uint32_t for header */
ok &= setRawUInt32(data, size, &offset, kMsgMagicCode);
ok &= setRawUInt32(data, size, &offset, msg_id);
ok &= setRawUInt32(data, size, &offset, req_id);
ok &= setRawUInt32(data, size, &offset, msg_size);
return ok;
}
bool MsgPacker::deserialiseHeader(uint32_t &msg_id, uint32_t &req_id, uint32_t &msg_size, uint8_t *buffer, uint32_t bufsize)
{
/* check size */
if (bufsize < kMsgHeaderSize)
{
return false;
}
/* pack the data (using libretroshare serialiser for now */
void *data = buffer;
uint32_t offset = 0;
uint32_t size = bufsize;
uint32_t magic_code;
bool ok = true;
/* 4 x uint32_t for header */
ok &= getRawUInt32(data, size, &offset, &magic_code);
if (!ok)
{
std::cerr << "Failed to deserialise uint32_t(0)";
std::cerr << std::endl;
}
ok &= getRawUInt32(data, size, &offset, &msg_id);
if (!ok)
{
std::cerr << "Failed to deserialise uint32_t(1)";
std::cerr << std::endl;
}
ok &= getRawUInt32(data, size, &offset, &req_id);
if (!ok)
{
std::cerr << "Failed to deserialise uint32_t(2)";
std::cerr << std::endl;
}
ok &= getRawUInt32(data, size, &offset, &msg_size);
if (!ok)
{
std::cerr << "Failed to deserialise uint32_t(3)";
std::cerr << std::endl;
}
ok &= (magic_code == kMsgMagicCode);
if (!ok)
{
std::cerr << "Failed to Match MagicCode";
std::cerr << std::endl;
}
return ok;
}

View File

@ -1,72 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RPC_MEDIATOR_H
#define RPC_MEDIATOR_H
/*
* Interface between RpcServer and RpcComms.
*/
#include <string>
#include <inttypes.h>
#include "rpcsystem.h"
class RpcServer;
class RpcMediator: public RpcSystem
{
public:
RpcMediator(RpcComms *c);
void setRpcServer(RpcServer *s) { mServer = s; } /* Must only be called during setup */
// Overloaded from RpcSystem.
virtual void reset(uint32_t chan_id);
virtual int tick();
int recv();
int recv_msg(uint32_t chan_id);
int send(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
int error(uint32_t chan_id, std::string msg); // pass an error up to comms level.
private:
RpcComms *mComms;
RpcServer *mServer;
};
/* Msg Packing */
class MsgPacker
{
public:
static int headersize();
static bool serialiseHeader(uint32_t msg_id, uint32_t req_id, uint32_t msg_size, uint8_t *buffer, uint32_t bufsize);
static bool deserialiseHeader(uint32_t &msg_id, uint32_t &req_id, uint32_t &msg_size, uint8_t *buffer, uint32_t bufsize);
};
#endif /* RPC_MEDIATOR_H */

View File

@ -1,40 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/rpcecho.h"
RpcEcho::RpcEcho(uint32_t serviceId)
:RpcQueueService(serviceId)
{
return;
}
int RpcEcho::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
/* */
queueResponse(chan_id, msg_id, req_id, msg);
return 1;
}

View File

@ -1,38 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_ECHO_H
#define RS_RPC_ECHO_H
#include "rpc/rpcserver.h"
class RpcEcho: public RpcQueueService
{
public:
RpcEcho(uint32_t serviceId);
virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
};
#endif /* RS_RPC_ECHO_H */

View File

@ -1,538 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/rpcserver.h"
#include "rpc/rpc.h"
#include <iostream>
bool operator<(const RpcUniqueId &a, const RpcUniqueId &b)
{
if (a.mChanId == b.mChanId)
return (a.mReqId < b.mReqId);
return (a.mChanId < b.mChanId);
}
RpcServer::RpcServer(RpcMediator *med)
:mMediator(med), mRpcMtx("RpcMtx")
{
}
void RpcServer::reset(uint32_t chan_id)
{
std::cerr << "RpcServer::reset(" << chan_id << ")" << std::endl;
{
RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/
std::list<RpcService *>::iterator it;
for(it = mAllServices.begin(); it != mAllServices.end(); it++)
{
/* in mutex, but should be okay */
(*it)->reset(chan_id);
}
// clear existing queue.
mRpcQueue.clear();
}
return;
}
int RpcServer::error(uint32_t chan_id, std::string msg)
{
return mMediator->error(chan_id, msg);
}
int RpcServer::addService(RpcService *service)
{
RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/
service->setRpcServer(this);
mAllServices.push_back(service);
return 1;
}
int RpcServer::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
std::cerr << "RpcServer::processMsg(" << msg_id << "," << req_id;
std::cerr << ", len(" << msg.size() << ")) from channel: " << chan_id;
std::cerr << std::endl;
{
RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/
std::list<RpcService *>::iterator it;
for(it = mAllServices.begin(); it != mAllServices.end(); it++)
{
int rt = (*it)->processMsg(chan_id, msg_id, req_id, msg);
if (!rt)
continue;
/* remember request */
queueRequest_locked(chan_id, msg_id, req_id, (*it));
return 1;
}
}
std::cerr << "RpcServer::processMsg() No service to accepted it - discard";
std::cerr << std::endl;
return 0;
}
int RpcServer::queueRequest_locked(uint32_t chan_id, uint32_t /* msgId */, uint32_t req_id, RpcService *service)
{
std::cerr << "RpcServer::queueRequest_locked() req_id: " << req_id;
std::cerr << std::endl;
RpcQueuedObj obj;
obj.mChanId = chan_id;
obj.mReqId = req_id;
obj.mService = service;
mRpcQueue.push_back(obj);
return 1;
}
bool RpcServer::checkPending()
{
std::list<RpcQueuedMsg> msgsToSend;
bool someRemaining = false;
bool someToSend = false;
{
RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/
std::list<RpcQueuedObj>::iterator it;
for(it = mRpcQueue.begin(); it != mRpcQueue.end();)
{
uint32_t out_chan_id = it->mChanId;
uint32_t out_msg_id = 0;
uint32_t out_req_id = it->mReqId;
std::string out_msg;
if (it->mService->getResponse(out_chan_id, out_msg_id, out_req_id, out_msg))
{
std::cerr << "RpcServer::checkPending() Response: (";
std::cerr << out_msg_id << "," << out_req_id;
std::cerr << ", len(" << out_msg.size() << "))";
std::cerr << " for chan_id: " << out_chan_id;
std::cerr << std::endl;
/* store and send after queue is processed */
RpcQueuedMsg msg;
msg.mChanId = out_chan_id;
msg.mMsgId = out_msg_id;
msg.mReqId = out_req_id;
msg.mMsg = out_msg;
msgsToSend.push_back(msg);
it = mRpcQueue.erase(it);
someToSend = true;
}
else
{
it++;
someRemaining = true;
}
}
}
if (someToSend)
{
sendQueuedMsgs(msgsToSend);
}
return someRemaining;
}
bool RpcServer::checkEvents()
{
std::list<RpcQueuedMsg> msgsToSend;
bool someToSend = false;
{
RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/
std::list<RpcService *>::iterator it;
for(it = mAllServices.begin(); it != mAllServices.end(); it++)
{
if ((*it)->getEvents(msgsToSend))
someToSend = true;
}
}
if (someToSend)
{
sendQueuedMsgs(msgsToSend);
}
return someToSend;
}
bool RpcServer::sendQueuedMsgs(std::list<RpcQueuedMsg> &msgs)
{
/* No need for lock, as mOut is the only accessed item - and that has own protection */
std::cerr << "RpcServer::sendQueuedMsg() " << msgs.size() << " to send";
std::cerr << std::endl;
std::list<RpcQueuedMsg>::iterator it;
for (it = msgs.begin(); it != msgs.end(); it++)
{
mMediator->send(it->mChanId, it->mMsgId, it->mReqId, it->mMsg);
}
return true;
}
RpcQueueService::RpcQueueService(uint32_t serviceId)
:RpcService(serviceId), mQueueMtx("RpcQueueService")
{
return;
}
void RpcQueueService::reset(uint32_t chan_id)
{
clearEventsForChannel(chan_id);
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::list<RpcUniqueId> toRemove;
// iterate through and remove only chan_id items.
std::map<RpcUniqueId, RpcQueuedMsg>::iterator mit;
for(mit = mResponses.begin(); mit != mResponses.end(); mit++)
{
if (mit->second.mChanId == chan_id)
toRemove.push_back(mit->first);
}
/* remove items */
std::list<RpcUniqueId>::iterator rit;
for(rit = toRemove.begin(); rit != toRemove.end(); rit++)
{
mit = mResponses.find(*rit);
mResponses.erase(mit);
}
return;
}
int RpcQueueService::getResponse(uint32_t &chan_id, uint32_t &msg_id, uint32_t &req_id, std::string &msg)
{
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::map<RpcUniqueId, RpcQueuedMsg>::iterator it;
RpcUniqueId uid(chan_id, req_id);
it = mResponses.find(uid);
if (it == mResponses.end())
{
return 0;
}
// chan_id & req_id are already set.
msg_id = it->second.mMsgId;
msg = it->second.mMsg;
mResponses.erase(it);
return 1;
}
int RpcQueueService::queueResponse(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg)
{
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
RpcQueuedMsg qmsg;
qmsg.mChanId = chan_id;
qmsg.mMsgId = msg_id;
qmsg.mReqId = req_id;
qmsg.mMsg = msg;
RpcUniqueId uid(chan_id, req_id);
mResponses[uid] = qmsg;
return 1;
}
/********* Events & Registration ******/
int RpcQueueService::getEvents(std::list<RpcQueuedMsg> &events)
{
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::map<uint32_t, std::list<RpcEventRegister> >::iterator it;
for(it = mEventRegister.begin(); it != mEventRegister.end(); it++)
{
locked_checkForEvents(it->first, it->second, events);
}
if (events.empty())
{
return 0;
}
return 1;
}
int RpcQueueService::locked_checkForEvents(uint32_t event, const std::list<RpcEventRegister> &registered, std::list<RpcQueuedMsg> & /* events */)
{
std::cerr << "RpcQueueService::locked_checkForEvents() NOT IMPLEMENTED";
std::cerr << std::endl;
std::cerr << "\tRegistered for Event Type: " << event;
std::cerr << std::endl;
std::list<RpcEventRegister>::const_iterator it;
for(it = registered.begin(); it != registered.end(); it++)
{
std::cerr << "\t\t Channel ID: " << it->mChanId;
std::cerr << " Request ID: " << it->mReqId;
std::cerr << std::endl;
}
return 1;
}
int RpcQueueService::registerForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id)
{
std::cerr << "RpcQueueService::registerForEvents(ChanId: " << chan_id;
std::cerr << ", ReqId: " << req_id;
std::cerr << ", EventId: " << event_id;
std::cerr << ")";
std::cerr << std::endl;
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::map<uint32_t, std::list<RpcEventRegister> >::iterator mit;
mit = mEventRegister.find(event_id);
if (mit == mEventRegister.end())
{
std::list<RpcEventRegister> emptyList;
mEventRegister[event_id] = emptyList;
mit = mEventRegister.find(event_id);
}
RpcEventRegister reg;
reg.mChanId = chan_id;
reg.mReqId = req_id;
reg.mEventId = event_id;
mit->second.push_back(reg);
return 1;
}
int RpcQueueService::deregisterForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id)
{
std::cerr << "RpcQueueService::deregisterForEvents(ChanId: " << chan_id;
std::cerr << ", ReqId: " << req_id;
std::cerr << ", EventId: " << event_id;
std::cerr << ")";
std::cerr << std::endl;
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::map<uint32_t, std::list<RpcEventRegister> >::iterator mit;
mit = mEventRegister.find(event_id);
if (mit == mEventRegister.end())
{
std::cerr << "RpcQueueService::deregisterForEvents() ";
std::cerr << "ERROR no EventId: " << event_id;
std::cerr << std::endl;
return 0;
}
bool removed = false;
std::list<RpcEventRegister>::iterator lit;
for(lit = mit->second.begin(); lit != mit->second.end();)
{
/* remove all matches */
if ((lit->mReqId == req_id) && (lit->mChanId == chan_id))
{
lit = mit->second.erase(lit);
if (removed == true)
{
std::cerr << "RpcQueueService::deregisterForEvents() ";
std::cerr << "WARNING REMOVING MULTIPLE MATCHES";
std::cerr << std::endl;
}
removed = true;
}
else
{
lit++;
}
}
if (mit->second.empty())
{
std::cerr << "RpcQueueService::deregisterForEvents() ";
std::cerr << " Last Registrant for Event, removing List from Map";
std::cerr << std::endl;
mEventRegister.erase(mit);
}
return 1;
}
int RpcQueueService::clearEventsForChannel(uint32_t chan_id)
{
std::cerr << "RpcQueueService::clearEventsForChannel(" << chan_id;
std::cerr << ")";
std::cerr << std::endl;
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::list<uint32_t> toMapRemove;
std::map<uint32_t, std::list<RpcEventRegister> >::iterator mit;
for(mit = mEventRegister.begin(); mit != mEventRegister.end(); mit++)
{
std::list<RpcEventRegister>::iterator lit;
for(lit = mit->second.begin(); lit != mit->second.end();)
{
/* remove all matches */
if (lit->mChanId == chan_id)
{
std::cerr << "RpcQueueService::clearEventsForChannel() ";
std::cerr << " Removing ReqId: " << lit->mReqId;
std::cerr << " for EventId: " << lit->mEventId;
std::cerr << std::endl;
lit = mit->second.erase(lit);
}
else
{
lit++;
}
}
if (mit->second.empty())
{
toMapRemove.push_back(mit->first);
}
}
/* remove any empty lists now */
std::list<uint32_t>::iterator rit;
for(rit = toMapRemove.begin(); rit != toMapRemove.end(); rit++)
{
mit = mEventRegister.find(*rit);
mEventRegister.erase(mit);
}
return 1;
}
int RpcQueueService::printEventRegister(std::ostream &out)
{
out << "RpcQueueService::printEventRegister()";
out << std::endl;
RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/
std::list<uint32_t> toMapRemove;
std::map<uint32_t, std::list<RpcEventRegister> >::iterator mit;
for(mit = mEventRegister.begin(); mit != mEventRegister.end(); mit++)
{
out << "Event: " << mit->first;
out << std::endl;
std::list<RpcEventRegister>::iterator lit;
for(lit = mit->second.begin(); lit != mit->second.end(); lit++)
{
out << "\tRegistrant: ReqId: " << lit->mReqId;
out << "\t ChanId: " << lit->mChanId;
out << std::endl;
}
}
return 1;
}
// Lower 8 bits.
uint8_t getRpcMsgIdSubMsg(uint32_t msg_id)
{
return msg_id & 0xFF;
}
// Middle 16 bits.
uint16_t getRpcMsgIdService(uint32_t msg_id)
{
return (msg_id >> 8) & 0xFFFF;
}
// Top 8 bits.
uint8_t getRpcMsgIdExtension(uint32_t msg_id)
{
return (msg_id >> 24) & 0xFE; // Bottom Bit is for Request / Response
}
bool isRpcMsgIdResponse(uint32_t msg_id)
{
return (msg_id >> 24) & 0x01;
}
uint32_t constructMsgId(uint8_t ext, uint16_t service, uint8_t submsg, bool is_response)
{
if (is_response)
ext |= 0x01; // Set Bottom Bit.
else
ext &= 0xFE; // Clear Bottom Bit.
uint32_t msg_id = (ext << 24) + (service << 8) + (submsg);
return msg_id;
}

View File

@ -1,164 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_SERVER_H
#define RS_RPC_SERVER_H
#include <map>
#include <list>
#include <string>
#include <inttypes.h>
#include "util/rsthreads.h"
// Dividing up MsgIds into components:
uint8_t getRpcMsgIdSubMsg(uint32_t msg_id);
uint16_t getRpcMsgIdService(uint32_t msg_id); // Middle 16 bits.
uint8_t getRpcMsgIdExtension(uint32_t msg_id); // Top 7 of 8 bits. Bottom Bit is for Request / Response
bool isRpcMsgIdResponse(uint32_t msg_id);
uint32_t constructMsgId(uint8_t ext, uint16_t service, uint8_t submsg, bool is_response);
/*** This can be overloaded for plugins
* Also allows a natural seperation of the full interface into sections.
*/
// The Combination of ChanId & ReqId must be unique for each RPC call.
// This is used as an map index, so failure to make it unique, will lead to lost entries.
class RpcUniqueId
{
public:
RpcUniqueId():mChanId(0), mReqId(0) {return;}
RpcUniqueId(uint32_t chan_id, uint32_t req_id):mChanId(chan_id), mReqId(req_id) {return;}
uint32_t mChanId;
uint32_t mReqId;
};
bool operator<(const RpcUniqueId &a, const RpcUniqueId &b);
class RpcQueuedMsg
{
public:
uint32_t mChanId;
uint32_t mMsgId;
uint32_t mReqId;
std::string mMsg;
};
class RpcServer;
class RpcService
{
public:
RpcService(uint32_t /* serviceId */ ):mRpcServer(NULL) { return; }
virtual void reset(uint32_t /* chan_id */) { return; }
virtual int msgsAccepted(std::list<uint32_t> & /* msgIds */) { return 0; } /* not used at the moment */
virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) = 0; /* returns 0 - not handled, > 0, accepted */
virtual int getResponse(uint32_t &chan_id, uint32_t &msgId, uint32_t &req_id, std::string &msg) = 0; /* 0 - not ready, > 0 heres the response */
virtual int getEvents(std::list<RpcQueuedMsg> & /* events */) { return 0; } /* 0 = none, optional feature */
void setRpcServer(RpcServer *server) {mRpcServer = server; }
RpcServer *getRpcServer() { return mRpcServer; }
private:
RpcServer *mRpcServer;
};
class RpcEventRegister
{
public:
uint32_t mChanId;
uint32_t mReqId;
uint32_t mEventId; // THIS IS A LOCAL PARAMETER, Service Specific
};
/* Implements a Queue for quick implementation of Instant Response Services */
class RpcQueueService: public RpcService
{
public:
RpcQueueService(uint32_t serviceId);
virtual void reset(uint32_t chan_id);
virtual int getResponse(uint32_t &chan_id, uint32_t &msg_id, uint32_t &req_id, std::string &msg);
virtual int getEvents(std::list<RpcQueuedMsg> &events);
protected:
int queueResponse(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg);
virtual int locked_checkForEvents(uint32_t event, const std::list<RpcEventRegister> &registered, std::list<RpcQueuedMsg> &events); // Overload for functionality.
int registerForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id);
int deregisterForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id);
int clearEventsForChannel(uint32_t chan_id);
int printEventRegister(std::ostream &out);
private:
RsMutex mQueueMtx;
std::map<RpcUniqueId, RpcQueuedMsg> mResponses;
std::map<uint32_t, std::list<RpcEventRegister> > mEventRegister;
};
/* For Tracking responses */
class RpcQueuedObj
{
public:
uint32_t mChanId;
uint32_t mReqId;
RpcService *mService;
};
class RpcMediator;
class RpcServer
{
public:
RpcServer(RpcMediator *med);
int addService(RpcService *service);
int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg);
bool checkPending();
bool checkEvents();
void reset(uint32_t chan_id);
int error(uint32_t chan_id, std::string msg); // pass an error to mediator.
private:
bool sendQueuedMsgs(std::list<RpcQueuedMsg> &msgs);
int queueRequest_locked(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, RpcService *service);
RpcMediator *mMediator;
RsMutex mRpcMtx;
std::list<RpcQueuedObj> mRpcQueue;
std::list<RpcService *> mAllServices;
};
#endif /* RS_RPC_SERVER_H */

View File

@ -1,68 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "rpc/rpcsetup.h"
#include "rpc/rpcserver.h"
#include "rpc/proto/rpcprotopeers.h"
#include "rpc/proto/rpcprotosystem.h"
#include "rpc/proto/rpcprotochat.h"
#include "rpc/proto/rpcprotosearch.h"
#include "rpc/proto/rpcprotofiles.h"
#include "rpc/proto/rpcprotostream.h"
#include "rpc/rpcecho.h"
RpcMediator *CreateRpcSystem(RpcComms *comms, NotifyTxt *notify)
{
RpcMediator *med = new RpcMediator(comms);
RpcServer *server = new RpcServer(med);
/* add services */
RpcProtoPeers *peers = new RpcProtoPeers(1);
server->addService(peers);
RpcProtoSystem *system = new RpcProtoSystem(1);
server->addService(system);
RpcProtoChat *chat = new RpcProtoChat(1);
server->addService(chat);
RpcProtoSearch *search = new RpcProtoSearch(1, notify);
server->addService(search);
RpcProtoFiles *files = new RpcProtoFiles(1);
server->addService(files);
RpcProtoStream *streamer = new RpcProtoStream(1);
server->addService(streamer);
/* Finally an Echo Service - which will echo back any unprocesses commands. */
RpcEcho *echo = new RpcEcho(1);
server->addService(echo);
med->setRpcServer(server);
return med;
}

View File

@ -1,36 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RPC_SETUP_H
#define RPC_SETUP_H
#include "rpc/rpc.h"
class NotifyTxt;
RpcMediator *CreateRpcSystem(RpcComms *comms, NotifyTxt *notify);
#endif

View File

@ -1,64 +0,0 @@
/*
* RetroShare External Interface.
*
* Copyright 2012-2012 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef RS_RPC_SYSTEM_H
#define RS_RPC_SYSTEM_H
#include <list>
#include <string>
#include <inttypes.h>
class RpcComms
{
public:
virtual int isOkay() = 0;
virtual int error(uint32_t chan_id, std::string msg) = 0;
virtual int active_channels(std::list<uint32_t> &chan_ids) = 0;
virtual int recv_ready(uint32_t chan_id) = 0;
virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes) = 0;
virtual int recv(uint32_t chan_id, std::string &buffer, int bytes) = 0;
// these make it easier...
virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes) = 0;
virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes) = 0;
virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes) = 0;
virtual int send(uint32_t chan_id, const std::string &buffer) = 0;
virtual int setSleepPeriods(float /* busy */, float /* idle */) { return 0; }
};
class RpcSystem
{
public:
/* this must be regularly ticked to update the display */
virtual void reset(uint32_t chan_id) = 0;
virtual int tick() = 0;
};
#endif // RS_RPC_SERVER_H

View File

@ -1,913 +0,0 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
/*****
* Heavily Modified by Robert Fernie 2012... for retroshare project!
*
*/
#include <libssh/callbacks.h>
#include "ssh/rssshd.h"
#include <iostream>
#define RSSSHD_STATE_NULL 0
#define RSSSHD_STATE_INIT_OK 1
#define RSSSHD_STATE_CONNECTED 2
#define RSSSHD_STATE_ERROR 3
RsSshd *rsSshd = NULL; // External Reference Variable.
// NB: This must be called EARLY before all the threads are launched.
RsSshd *RsSshd::InitRsSshd(const std::string &portStr, const std::string &rsakeyfile)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
ssh_threads_set_callbacks(ssh_threads_get_pthread());
#endif
ssh_init();
rsSshd = new RsSshd(portStr);
if (rsSshd->init(rsakeyfile))
{
return rsSshd;
}
rsSshd = NULL;
return rsSshd;
}
RsSshd::RsSshd(std::string portStr)
:mSshMtx("sshMtx"), mPortStr(portStr), mChannel(0)
{
mState = RSSSHD_STATE_NULL;
mBindState = 0;
mRpcSystem = NULL;
mSession = NULL;
setSleepPeriods(0.01, 0.1);
return;
}
int RsSshd::init(const std::string &pathrsakey)
{
mBind=ssh_bind_new();
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, mPortStr.c_str());
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, arg);
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_HOSTKEY, arg);
ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, pathrsakey.c_str());
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
mState = RSSSHD_STATE_INIT_OK;
mBindState = 0;
return 1;
}
void RsSshd::run()
{
/* main loop */
/* listen */
bool sshOk = true;
while(sshOk)
{
std::cerr << "RsSshd::run() starting sshd cycle";
std::cerr << std::endl;
if (listenConnect())
{
std::cerr << "RsSshd::run() success connect => setup mSession";
std::cerr << std::endl;
if (setupSession())
{
std::cerr << "RsSshd::run() setup mSession => interactive";
std::cerr << std::endl;
mState = RSSSHD_STATE_CONNECTED;
interactive();
}
else
{
std::cerr << "RsSshd::run() setup mSession failed";
std::cerr << std::endl;
}
}
cleanupSession();
#ifndef WINDOWS_SYS
sleep(5); // have a break;
#else
Sleep(5000); // have a break;
#endif
}
}
int RsSshd::listenConnect()
{
std::cerr << "RsSshd::listenConnect()";
std::cerr << std::endl;
if (!mBindState)
{
if(ssh_bind_listen(mBind)<0)
{
printf("Error listening to socket: %s\n",ssh_get_error(mBind));
return 0;
}
mBindState = 1;
}
else
{
std::cerr << "RsSshd::listenConnect() Already Bound...";
std::cerr << std::endl;
}
mSession=ssh_new();
int r=ssh_bind_accept(mBind,mSession);
if(r==SSH_ERROR)
{
printf("error accepting a connection : %s\n",ssh_get_error(mBind));
return 0;
}
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
if (ssh_handle_key_exchange(mSession))
#else
if (ssh_accept(mSession))
#endif
{
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(mSession));
return 0;
}
return 1;
}
int RsSshd::setupSession()
{
std::cerr << "RsSshd::listenConnect()";
std::cerr << std::endl;
if (authUser())
{
std::cerr << "RsSshd::listenConnect() authUser SUCCESS";
std::cerr << std::endl;
if (setupChannel())
{
std::cerr << "RsSshd::listenConnect() setupChannel SUCCESS";
std::cerr << std::endl;
if (setupShell())
{
std::cerr << "RsSshd::listenConnect() setupShell SUCCESS";
std::cerr << std::endl;
return 1;
}
}
}
std::cerr << "RsSshd::listenConnect() Failed";
std::cerr << std::endl;
return 0;
}
int RsSshd::interactive()
{
std::cerr << "RsSshd::interactive()";
std::cerr << std::endl;
doRpcSystem();
//doEcho();
return 1;
}
int RsSshd::authUser()
{
std::cerr << "RsSshd::authUser()";
std::cerr << std::endl;
ssh_message message;
int auth = 0;
do {
message=ssh_message_get(mSession);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_REQUEST_AUTH:
switch(ssh_message_subtype(message)){
case SSH_AUTH_METHOD_PASSWORD:
printf("User %s wants to auth with pass %s\n",
ssh_message_auth_user(message),
ssh_message_auth_password(message));
if(auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message))){
auth=1;
ssh_message_auth_reply_success(message,0);
break;
}
// not authenticated, send default message
case SSH_AUTH_METHOD_NONE:
default:
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
ssh_message_reply_default(message);
break;
}
break;
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (!auth);
if(!auth){
printf("auth error: %s\n",ssh_get_error(mSession));
ssh_disconnect(mSession);
return 0;
}
std::cerr << "RsSshd::authuser() Success";
std::cerr << std::endl;
return 1;
}
int RsSshd::setupChannel()
{
std::cerr << "RsSshd::setupChannel()";
std::cerr << std::endl;
ssh_message message;
do {
message=ssh_message_get(mSession);
if(message){
switch(ssh_message_type(message)){
case SSH_REQUEST_CHANNEL_OPEN:
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
mChannel=ssh_message_channel_request_open_reply_accept(message);
break;
}
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
}
} while(message && !mChannel);
if(!mChannel){
printf("error : %s\n",ssh_get_error(mSession));
ssh_finalize();
return 0;
}
return 1;
}
int RsSshd::setupShell()
{
std::cerr << "RsSshd::setupShell()";
std::cerr << std::endl;
int shell = 0;
ssh_message message;
do {
message=ssh_message_get(mSession);
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
shell = 1;
ssh_message_channel_request_reply_success(message);
break;
}
if(!shell){
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (message && !shell);
if(!shell){
printf("error : %s\n",ssh_get_error(mSession));
return 0;
}
return 1;
}
// CLEANUP
int RsSshd::cleanupSession()
{
std::cerr << "RsSshd::cleanupSession()";
std::cerr << std::endl;
ssh_disconnect(mSession);
ssh_free(mSession);
return 1;
}
int RsSshd::cleanupAll()
{
std::cerr << "RsSshd::cleanupAll()";
std::cerr << std::endl;
cleanupSession();
if (mBindState)
{
ssh_bind_free(mBind);
mBindState = 0;
}
ssh_finalize();
return 1;
}
// Various Operating Modes.
int RsSshd::doEcho()
{
std::cerr << "RsSshd::doEcho()";
std::cerr << std::endl;
int i = 0;
char buf[2048];
do{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
i=ssh_channel_read(mChannel,buf, 2048, 0);
#else
i=channel_read(mChannel,buf, 2048, 0);
#endif
if(i>0) {
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
ssh_channel_write(mChannel, buf, i);
ssh_channel_write(mChannel, buf, i);
#else
channel_write(mChannel, buf, i);
channel_write(mChannel, buf, i);
#endif
if (write(1,buf,i) < 0) {
printf("error writing to buffer\n");
return 0;
}
}
} while (i>0);
std::cerr << "RsSshd::doEcho() Finished";
std::cerr << std::endl;
return 1;
}
int RsSshd::setRpcSystem(RpcSystem *s)
{
mRpcSystem = s;
return 1;
}
#if 0
int RsSshd::doTermServer()
{
std::cerr << "RsSshd::doTermServer()";
std::cerr << std::endl;
if (!mTermServer)
{
std::cerr << "RsSshd::doTermServer() ERROR Not Set";
std::cerr << std::endl;
return 0;
}
mTermServer->reset(); // clear everything for new user.
bool okay = true;
while(okay)
{
char buf;
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
int size = ssh_channel_read_nonblocking(mChannel, &buf, 1, 0);
#else
int size = channel_read_nonblocking(mChannel, &buf, 1, 0);
#endif
bool haveInput = (size > 0);
std::string output;
int rt = mTermServer->tick(haveInput, buf, output);
if (output.size() > 0)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
ssh_channel_write(mChannel, output.c_str(), output.size());
#else
channel_write(mChannel, output.c_str(), output.size());
#endif
}
if (!haveInput)
{
/* have a little sleep */
sleep(1); //0000000); // 1/10th sec.
//usleep(10000000); // 1/10th sec.
}
else
{
usleep(10000); // 1/100th sec.
}
if (rt < 0)
{
okay = false; // exit.
}
}
std::cerr << "RsSshd::doTermServer() Finished";
std::cerr << std::endl;
return 1;
}
#endif
int RsSshd::doRpcSystem()
{
std::cerr << "RsSshd::doRpcSystem()";
std::cerr << std::endl;
if (!mRpcSystem)
{
std::cerr << "RsSshd::doRpcSystem() ERROR Not Set";
std::cerr << std::endl;
return 0;
}
uint32_t dummy_chan_id = 1;
mRpcSystem->reset(dummy_chan_id); // clear everything for new user.
bool okay = true;
while(okay)
{
int rt = mRpcSystem->tick();
if (rt)
{
// Working - so small sleep,
usleep(mBusyUSleep);
}
else
{
// No work cycle, longer break.
usleep(mIdleUSleep);
}
if (rt < 0)
{
okay = false; // exit.
}
if (!isOkay())
{
okay = false;
}
}
mRpcSystem->reset(dummy_chan_id); // cleanup old channel items.
std::cerr << "RsSshd::doRpcSystem() Finished";
std::cerr << std::endl;
return 1;
}
// RpcComms Interface....
int RsSshd::isOkay()
{
return (mState == RSSSHD_STATE_CONNECTED);
}
std::list<uint32_t>::iterator it;
int RsSshd::active_channels(std::list<uint32_t> &chan_ids)
{
if (isOkay())
{
chan_ids.push_back(1); // dummy for now.
}
return 1;
}
int RsSshd::error(uint32_t chan_id, std::string msg)
{
std::cerr << "RsSshd::error(" << msg << ")";
std::cerr << std::endl;
mState = RSSSHD_STATE_ERROR;
return 1;
}
int RsSshd::recv_ready(uint32_t chan_id)
{
int bytes = ssh_channel_poll(mChannel, 0);
return bytes;
}
int RsSshd::recv(uint32_t chan_id, uint8_t *buffer, int bytes)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
int size = ssh_channel_read_nonblocking(mChannel, buffer, bytes, 0);
#else
int size = channel_read_nonblocking(mChannel, buffer, bytes, 0);
#endif
return size;
}
int RsSshd::recv(uint32_t chan_id, std::string &buffer, int bytes)
{
char input[bytes];
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
int size = ssh_channel_read_nonblocking(mChannel, input, bytes, 0);
#else
int size = channel_read_nonblocking(mChannel, input, bytes, 0);
#endif
for(int i = 0; i < size; i++)
{
buffer += input[i];
}
return size;
}
int RsSshd::recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
int size = ssh_channel_read(mChannel, buffer, bytes, 0);
#else
int size = channel_read(mChannel, buffer, bytes, 0);
#endif
return size;
}
int RsSshd::recv_blocking(uint32_t chan_id, std::string &buffer, int bytes)
{
char input[bytes];
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
int size = ssh_channel_read(mChannel, input, bytes, 0);
#else
int size = channel_read(mChannel, input, bytes, 0);
#endif
for(int i = 0; i < size; i++)
{
buffer += input[i];
}
return size;
}
int RsSshd::send(uint32_t chan_id, uint8_t *buffer, int bytes)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
ssh_channel_write(mChannel, buffer, bytes);
#else
channel_write(mChannel, buffer, bytes);
#endif
return 1;
}
int RsSshd::send(uint32_t chan_id, const std::string &buffer)
{
#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0)
ssh_channel_write(mChannel, buffer.c_str(), buffer.size());
#else
channel_write(mChannel, buffer.c_str(), buffer.size());
#endif
return 1;
}
int RsSshd::setSleepPeriods(float busy, float idle)
{
mBusyUSleep = busy * 1000000;
mIdleUSleep = idle * 1000000;
return 1;
}
/***********************************************************************************/
/* PASSWORDS */
/***********************************************************************************/
int RsSshd::auth_password(const char *name, const char *pwd)
{
#ifdef ALLOW_CLEARPWDS
if (auth_password_basic(name, pwd))
return 1;
#endif // ALLOW_CLEARPWDS
if (auth_password_hashed(name, pwd))
return 1;
return 0;
}
#define RSSSHD_MIN_PASSWORD 4
#define RSSSHD_MIN_USERNAME 3
#ifdef ALLOW_CLEARPWDS
int RsSshd::adduser(std::string username, std::string password)
{
if (password.length() < RSSSHD_MIN_PASSWORD)
{
std::cerr << "RsSshd::adduser() Password Too Short";
return 0;
}
if (username.length() < RSSSHD_MIN_USERNAME)
{
std::cerr << "RsSshd::adduser() Password Too Short";
return 0;
}
std::map<std::string, std::string>::iterator it;
it = mPasswords.find(username);
if (it != mPasswords.end())
{
std::cerr << "RsSshd::adduser() Warning username already exists";
}
mPasswords[username] = password;
return 1;
}
int RsSshd::auth_password_basic(char *name, char *pwd)
{
std::string username(name);
std::string password(pwd);
std::map<std::string, std::string>::iterator it;
it = mPasswords.find(username);
if (it == mPasswords.end())
{
std::cerr << "RsSshd::auth_password() Unknown username";
return 0;
}
if (it->second == password)
{
std::cerr << "RsSshd::auth_password() logged in " << username;
return 1;
}
std::cerr << "RsSshd::auth_password() Invalid pwd for " << username;
return 0;
}
#endif // ALLOW_CLEARPWDS
//#define RSSSHD_HASH_PWD_LENGTH 40
int RsSshd::adduserpwdhash(std::string username, std::string hash)
{
#if 0
if (hash.length() != RSSSHD_HASH_PWD_LENGTH)
{
std::cerr << "RsSshd::adduserpwdhash() Hash Wrong Length";
return 0;
}
#endif
if (username.length() < RSSSHD_MIN_USERNAME)
{
std::cerr << "RsSshd::adduserpwdhash() Username Too Short";
return 0;
}
std::map<std::string, std::string>::iterator it;
it = mPwdHashs.find(username);
if (it != mPwdHashs.end())
{
std::cerr << "RsSshd::adduser() Warning username already exists";
}
mPwdHashs[username] = hash;
return 1;
}
int RsSshd::auth_password_hashed(const char *name, const char *pwd)
{
std::string username(name);
std::string password(pwd);
std::map<std::string, std::string>::iterator it;
it = mPwdHashs.find(username);
if (it == mPwdHashs.end())
{
std::cerr << "RsSshd::auth_password_hashed() Unknown username";
return 0;
}
if (CheckPasswordHash(it->second, password))
{
std::cerr << "RsSshd::auth_password_hashed() logged in " << username;
return 1;
}
std::cerr << "RsSshd::auth_password_hashed() Invalid pwd for " << username;
return 0;
}
#include "util/radix64.h"
#include "util/rsrandom.h"
#include <openssl/evp.h>
#define RSSSHD_PWD_SALT_LEN 16
#define RSSSHD_PWD_MIN_LEN 8
#if 0
int printHex(const char *data, int len)
{
for(int i = 0; i < len; i++)
{
fprintf(stderr, "%02x", (uint8_t) data[i]);
}
return 1;
}
#endif
int GenerateSalt(std::string &saltBin)
{
/* get from random */
for(int i = 0; i < RSSSHD_PWD_SALT_LEN / 4; i++)
{
uint32_t rnd = RSRandom::random_u32();
saltBin += ((char *) &rnd)[0];
saltBin += ((char *) &rnd)[1];
saltBin += ((char *) &rnd)[2];
saltBin += ((char *) &rnd)[3];
}
#if 0
std::cerr << "HexSalt: ";
printHex(saltBin.c_str(), saltBin.size());
std::cerr << std::endl;
#endif
return 1;
}
int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64)
{
#if 0
std::cerr << "GeneratePasswordHash()";
std::cerr << std::endl;
std::cerr << "HexSalt: ";
printHex(saltBin.c_str(), saltBin.size());
std::cerr << std::endl;
#endif
if (saltBin.size() != RSSSHD_PWD_SALT_LEN)
{
return 0;
}
if (password.size() < RSSSHD_PWD_MIN_LEN)
{
return 0;
}
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, saltBin.c_str(), saltBin.size());
EVP_DigestUpdate(ctx, password.c_str(), password.size());
unsigned char hash[1024];
unsigned int s = 1024 - RSSSHD_PWD_SALT_LEN;
for(int i = 0; i < RSSSHD_PWD_SALT_LEN; i++)
{
hash[i] = saltBin[i];
}
EVP_DigestFinal(ctx, &(hash[RSSSHD_PWD_SALT_LEN]), &s);
Radix64::encode((char *)hash, s + RSSSHD_PWD_SALT_LEN, pwdHashRadix64);
#if 0
std::cerr << "Salt Length: " << RSSSHD_PWD_SALT_LEN;
std::cerr << std::endl;
std::cerr << "Hash Length: " << s;
std::cerr << std::endl;
std::cerr << "Total Length: " << s + RSSSHD_PWD_SALT_LEN;
std::cerr << std::endl;
std::cerr << "Encoded Length: " << pwdHashRadix64.size();
std::cerr << std::endl;
std::cerr << "GeneratePasswordHash() Output: " << pwdHashRadix64;
std::cerr << std::endl;
#endif
return 1;
}
int CheckPasswordHash(std::string pwdHashRadix64, std::string password)
{
char output[1024];
std::vector<uint8_t> buf = Radix64::decode(pwdHashRadix64);
size_t len = buf.size();
for(unsigned int i = 0; (i < len) && (i < 1024); i++)
{
output[i] = buf[i];
}
#if 0
std::cerr << "CheckPasswordHash() Input: " << pwdHashRadix64;
std::cerr << std::endl;
std::cerr << "Decode Length: " << len;
std::cerr << std::endl;
std::cerr << "HexDecoded: ";
printHex(output, len);
std::cerr << std::endl;
#endif
/* first N bytes are SALT */
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, output, RSSSHD_PWD_SALT_LEN);
EVP_DigestUpdate(ctx, password.c_str(), password.size());
#if 0
std::cerr << "HexSalt: ";
printHex(output, RSSSHD_PWD_SALT_LEN);
std::cerr << std::endl;
#endif
unsigned char hash[128];
unsigned int s = 128;
EVP_DigestFinal(ctx, hash, &s);
/* Final Comparison */
if (s != len - RSSSHD_PWD_SALT_LEN)
{
std::cerr << "Length Mismatch";
return 0;
}
if (0 == strncmp(&(output[RSSSHD_PWD_SALT_LEN]), (char *) hash, s))
{
return 1;
}
return 0;
}

View File

@ -1,157 +0,0 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
/*****
* Heavily Modified by Robert Fernie 2012... for retroshare project!
*
*/
#ifndef RS_SSHD_INTERFACE_H
#define RS_SSHD_INTERFACE_H
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// From inside libretroshare.a
#include "util/rsthreads.h"
#include <string>
#include <map>
#include "rpcsystem.h"
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
/******
*
* Minimal Options to start with
*
*/
//#define ALLOW_CLEARPWDS 1
class RsSshd;
extern RsSshd *rsSshd;
// TODO: NB: THIS FN DOES NOT USE A "SLOW" HASH FUNCTION.
// THE FIRST HALF OF THE HASH STRING IS THE SALT
int CheckPasswordHash(std::string pwdHashRadix64, std::string password);
int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64);
int GenerateSalt(std::string &saltBin);
class RsSshd: public RsThread, public RpcComms
{
public:
// NB: This must be called EARLY before all the threads are launched.
static RsSshd *InitRsSshd(const std::string& portStr, const std::string &rsakeyfile);
// Interface.
int setRpcSystem(RpcSystem *s);
int adduserpwdhash(std::string username, std::string hash);
// RsThreads Interface.
virtual void run(); /* called once the thread is started */
// RsComms Interface.
virtual int isOkay();
virtual int error(uint32_t chan_id, std::string msg);
virtual int active_channels(std::list<uint32_t> &chan_ids);
virtual int recv_ready(uint32_t chan_id);
virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int recv(uint32_t chan_id, std::string &buffer, int bytes);
virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes);
virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes);
virtual int send(uint32_t chan_id, const std::string &buffer);
virtual int setSleepPeriods(float busy, float idle);
private:
RsSshd(std::string portStr); /* private constructor => so can only create with */
int init(const std::string &pathrsakey);
// High level operations.
int listenConnect();
int setupSession();
int interactive();
// Lower Level Operations.
int authUser();
int setupChannel();
int setupShell();
int doEcho();
// Terminal Handling!
//int doTermServer();
int doRpcSystem();
int cleanupSession();
int cleanupAll();
/* Password Checking */
int auth_password(const char *name, const char *pwd);
int auth_password_hashed(const char *name, const char *pwd);
#ifdef ALLOW_CLEARPWDS
int auth_password_basic(char *name, char *pwd);
#endif // ALLOW_CLEARPWDS
// DATA.
RsMutex mSshMtx;
uint32_t mBusyUSleep;
uint32_t mIdleUSleep;
uint32_t mState;
uint32_t mBindState;
std::string mPortStr;
ssh_session mSession;
ssh_bind mBind;
ssh_channel mChannel;
RpcSystem *mRpcSystem;
#ifdef ALLOW_CLEARPWDS
std::map<std::string, std::string> mPasswords;
#endif // ALLOW_CLEARPWDS
std::map<std::string, std::string> mPwdHashs;
};
#endif

View File

@ -1,60 +0,0 @@
This document proposes the finer details of how to communicate with RS,
using SSH and protobuf classes.
==========================================================================
Message Format
====================
Protobuf serialisation does not identify Message Types or Message Size.
So we need to have an encapsulation header system
These headers describe the actual message via a MsgId and MsgSize.
Care must be taken to ensure these IDS are correct, as this is NOT enforced
by protobuf, and will lead to incorrect deserialisation!
In Each .proto there is a list of MsgIds as an ENUM.
The protocol message format is as follows:
[HEADER: 16 bytes: 4 x Network Order uint32_t][ VARIABLE LENGTH BODY ]
[ MAGIC_CODE ] [ MSG_ID ] [ REQ_ID ] [ BODY_SIZE ] [ ..... BODY ..... ]
MagicCode = 0x137f0001. will be incremented for new versions of the protocol.
MsgID = Corresponds to the format of the Body.
ReqID = Generated by Requester, Returned in Response,
make sure its unique. (undefined behaviour for duplicates)
BodySize = Byte Length of Body.
The Body will consist of a protobuf encoded message.
Usage
=================
* Create SSH connection to retroshare-nogui.
* Create Request Message(s), and send over SSH channel - You can send as meny requests as you want.
* They will processed, and responses sent back (potentially in an arbitary order).
MsgIDs
=================
In Each .proto there is a list of MsgIds as an ENUM.
0x00 XX XX xx => Reserved for libretroshare Requests. (XX - area, xxxx specific msg)
0x01 XX XX xx => Reserved for libretroshare Responses
eg. 0x00 (fa bc) [01] -> Request, 0x01 (fa bc) [01/02/03] -> responses
0x10 YY YY yy => Extensions for project YY (16k), with sub commands yy (256)
0x11 YY YY yy
... if we run out of YY's will use 0x20 etc.
Extensions
=================
These are welcome and encouraged.
We just need to make sure that MsgIDs don't clash.

View File

@ -1,246 +0,0 @@
package rsctrl.chat;
import "core.proto";
///////////////////////////////////////////////////////////////
// Private, Group and Chat Lobby RPC.
//
// OTHER COMMANDS TO ADD?
// Status Strings.
// Invite Friends to Private Lobbies.
// Chat History.
// ???
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestChatLobbies = 1;
MsgId_RequestCreateLobby = 2;
MsgId_RequestJoinOrLeaveLobby = 3;
MsgId_RequestSetLobbyNickname = 4;
MsgId_RequestRegisterEvents = 5;
MsgId_RequestSendMessage = 6;
MsgId_RequestChatHistory = 7;
}
enum ResponseMsgIds {
// STANDARD RESPONSES.
MsgId_ResponseChatLobbies = 1;
MsgId_ResponseSetLobbyNickname = 4;
MsgId_ResponseRegisterEvents = 5;
MsgId_ResponseSendMessage = 6;
MsgId_ResponseChatHistory = 7;
// EVENTS
MsgId_EventLobbyInvite = 101;
MsgId_EventChatMessage = 102;
}
///////////////////////////////////////////////////////////////
// BUILDING BLOCKS.
// This is a combination of ChatLobbyInfo & PublicChatLobbyRecord.
// Which seem very similar??
enum LobbyPrivacyLevel {
PRIVACY_PRIVATE = 1;
PRIVACY_PUBLIC = 2;
}
enum ChatType {
TYPE_PRIVATE = 1;
TYPE_LOBBY = 2;
TYPE_GROUP = 3;
}
message ChatLobbyInfo {
required string lobby_id = 1;
required string lobby_topic = 2;
required string lobby_name = 3;
required string lobby_nickname = 4; // empty for none set.
enum LobbyState {
LOBBYSTATE_JOINED = 1;
LOBBYSTATE_INVITED = 2;
LOBBYSTATE_VISIBLE = 3;
}
required LobbyPrivacyLevel privacy_level = 5;
required LobbyState lobby_state = 6;
required uint32 no_peers = 7;
required uint32 last_report_time = 8;
required uint32 last_activity = 9;
repeated string participating_friends = 10; // SSL_IDS?
repeated string nicknames = 11;
}
message ChatId {
required ChatType chat_type = 1;
required string chat_id = 2;
}
message ChatMessage {
required ChatId id = 1;
required string msg = 2;
optional string peer_nickname = 3;
optional uint32 chat_flags = 4;
optional uint32 send_time = 5;
optional uint32 recv_time = 6;
}
// RESPONSE: ResponseChatLobbies
// This is a generic Response - used often.
// lobbies, will contain a list of affected / requested Lobbies.
message ResponseChatLobbies {
required rsctrl.core.Status status = 1;
repeated ChatLobbyInfo lobbies = 2;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestChatLobbies
message RequestChatLobbies {
enum LobbySet {
LOBBYSET_ALL = 1;
LOBBYSET_JOINED = 2;
LOBBYSET_INVITED = 3;
LOBBYSET_VISIBLE = 4;
}
required LobbySet lobby_set = 1;
}
// RESPONSE: ResponseChatLobbies
///////////////////////////////////////////////////////////////
// REQUEST: RequestCreateLobby
message RequestCreateLobby {
required string lobby_name = 1;
required string lobby_topic = 2;
required LobbyPrivacyLevel privacy_level = 4;
repeated string invited_friends = 3; // SSL_IDS
}
// RESPONSE: ResponseChatLobbies
///////////////////////////////////////////////////////////////
// Accept / Deny Invite, Join / Leave Lobby (these can be combined?)
// REQUEST: RequestJoinOrLeaveLobby
message RequestJoinOrLeaveLobby {
enum LobbyAction {
JOIN_OR_ACCEPT = 1;
LEAVE_OR_DENY = 2;
}
required string lobby_id = 1;
required LobbyAction action = 2;
}
// RESPONSE: ResponseChatLobbies
///////////////////////////////////////////////////////////////
// Set Nickname.
// Get is done via requesting ChatLobby Info.
// Empty lobby_ids => default Nickname.
// REQUEST: RequestSetLobbyNickname
message RequestSetLobbyNickname {
required string nickname = 1;
repeated string lobby_ids = 2;
}
// RESPONSE: ResponseSetLobbyNickname
// Didnt think the whole Lobby status was necessary.
message ResponseSetLobbyNickname {
required rsctrl.core.Status status = 1;
}
///////////////////////////////////////////////////////////////
// Request Chat Events.
// This is done by registering for events.
// REQUEST: RequestRegisterEvents
message RequestRegisterEvents {
enum RegisterAction {
REGISTER = 1;
DEREGISTER = 2;
}
required RegisterAction action = 1;
}
// RESPONSE: ResponseRegisterEvents
message ResponseRegisterEvents {
required rsctrl.core.Status status = 1;
}
// RESPONSE: EventLobbyInvite
message EventLobbyInvite {
required ChatLobbyInfo lobby = 1;
}
// RESPONSE: EventChatMessage
message EventChatMessage {
required ChatMessage msg = 1;
}
///////////////////////////////////////////////////////////////
// Send Message.
// REQUEST: RequestSendMessage
message RequestSendMessage {
required ChatMessage msg = 1;
}
// RESPONSE: ResponseSendMessage
message ResponseSendMessage {
required rsctrl.core.Status status = 1;
}
///////////////////////////////////////////////////////////////
// Chat History.
// INITIALLY THIS WILL ONLY WORK WITH PRIVATE CHATS.
// NEED TO EXTEND INTERNALS TO HANDLE LOBBIES.
// REQUEST: RequestChatHistory
message RequestChatHistory {
required ChatId id = 1; /* lobby or chat, group id */
}
// RESPONSE: ResponseChatHistory
message ResponseChatHistory {
required rsctrl.core.Status status = 1;
required ChatId id = 2; /* lobby or chat, group id */
repeated ChatMessage msgs = 3;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

View File

@ -1,161 +0,0 @@
package rsctrl.core;
///////////////////////////////////////////////////////////////
// These are basic Messages, which are used as building blocks
// throughout the rest of the interface.
// They should not be sent RAW, but should be wrapped in another msg.
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Expected PackageIds.
enum ExtensionId { CORE = 0; }
enum PackageId {
PEERS = 1;
SYSTEM = 2;
CHAT = 3;
SEARCH = 4;
FILES = 5;
STREAM = 6;
// BELOW HERE IS STILL BEING DESIGNED.
//MSGS = 7;
// THEORETICAL ONES.
GXS = 1000;
}
///////////////////////////////////////////////////////////////
// Basic Status Response, should be in all responses
message Status {
enum StatusCode {
FAILED = 0;
NO_IMPL_YET = 1;
INVALID_QUERY = 2;
PARTIAL_SUCCESS = 3;
SUCCESS = 4;
READMSG = 5;
}
required StatusCode code = 1;
optional string msg = 2;
}
///////////////////////////////////////////////////////////////
message IpAddr {
required string addr = 1 [default = ""];
required uint32 port = 2 [default = 0]; // must be 16 bit, 0 for unknown.
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Peer structures, mainly rsctrl.peers related.
message Location {
enum StateFlags { // ORd together...
ONLINE = 1;
CONNECTED = 2;
UNREACHABLE = 4;
}
required string ssl_id = 1;
required string location = 2;
required IpAddr localaddr = 3;
required IpAddr extaddr = 4;
required uint32 state = 5; // Not an ENUM as ORd together.
}
message Person {
enum Relationship {
YOURSELF = 1;
FRIEND = 2;
FRIEND_OF_MANY_FRIENDS = 3; // 3+ at the moment.
FRIEND_OF_FRIENDS = 4; // 1 or 2.
UNKNOWN = 5;
}
required string gpg_id = 1;
required string name = 2;
required Relationship relation = 3;
repeated Location locations = 4;
}
///////////////////////////////////////////////////////////////
// File structures, mainly rsctrl.files related.
message File {
required string name = 1;
required string hash = 2;
required uint64 size = 3;
// THINK WE DONT WANT THESE HERE...
// BETTER TO KEEP File simple.
//optional string path = 4;
//optional string avail = 5;
}
message Dir {
required string name = 1;
required string path = 2;
repeated Dir subdirs = 3;
repeated File files = 4;
}
///////////////////////////////////////////////////////////////
message Timestamp {
required uint64 secs = 1;
required uint32 microsecs = 2;
}
///////////////////////////////////////////////////////////////
// System Status
message SystemStatus {
enum NetCode {
BAD_UNKNOWN = 0;
BAD_OFFLINE = 1;
BAD_NATSYM = 2;
BAD_NODHT_NAT = 3;
WARNING_RESTART = 4;
WARNING_NATTED = 5;
WARNING_NODHT = 6;
GOOD = 7;
ADV_FORWARD = 8;
}
required NetCode net_status = 1;
optional string msg = 2;
}
///////////////////////////////////////////////////////////////
// Bandwidth Measurements.
message Bandwidth {
required float up = 1; // kB/s
required float down = 2; // kB/s
optional string name = 3; // e.g. DHT, UDP, TCP, Stun, or Total.
}
message BandwidthSet {
repeated Bandwidth bandwidths = 1;
}
///////////////////////////////////////////////////////////////

View File

@ -1,143 +0,0 @@
package rsctrl.files;
import "core.proto";
///////////////////////////////////////////////////////////////
// List Transfers.
// Control Transfers.
//
// TODO:
// Share Directories.
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestTransferList = 1;
MsgId_RequestControlDownload = 2;
MsgId_RequestShareDirList = 3;
}
enum ResponseMsgIds {
MsgId_ResponseTransferList = 1;
MsgId_ResponseControlDownload = 2;
MsgId_ResponseShareDirList = 3;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Building Blocks
enum Direction {
DIRECTION_UPLOAD = 1;
DIRECTION_DOWNLOAD = 2;
}
enum TransferState {
TRANSFER_FAILED = 1;
TRANSFER_OKAY = 2;
TRANSFER_PAUSED = 3;
TRANSFER_QUEUED = 4;
TRANSFER_WAITING = 5;
TRANSFER_DOWNLOADING = 6;
TRANSFER_CHECKING_HASH = 7;
TRANSFER_COMPLETE = 8;
}
message FileTransfer {
required rsctrl.core.File file = 1;
required Direction direction = 2;
required float fraction = 3;
required float rate_kBs = 4;
required TransferState state = 5;
}
///////////////////////////////////////////////////////////////
// Transfer List.
// REQUEST: RequestTransferList
message RequestTransferList {
required Direction direction = 1;
}
// RESPONSE: ResponseTransferList
message ResponseTransferList {
required rsctrl.core.Status status = 1;
repeated FileTransfer transfers = 2;
}
///////////////////////////////////////////////////////////////
// Download.
// REQUEST: RequestControlDownload
// START requires name, hash & size.
// other actions only require file hash.
message RequestControlDownload {
enum Action {
ACTION_START = 1; // start download.
ACTION_CONTINUE = 2; // move to top of queue.
ACTION_WAIT = 3; // send to bottom of queue.
ACTION_PAUSE = 4; // hold indefinitely.
ACTION_RESTART = 5; // end pause, restart download.
ACTION_CHECK = 6; // force check.
ACTION_CANCEL = 7; // remove permenantly.
}
required rsctrl.core.File file = 1;
required Action action = 2;
}
// RESPONSE: ResponseControlDownload
message ResponseControlDownload {
required rsctrl.core.Status status = 1;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// SHARED FILES
// REQUEST: RequestShareDirList
message RequestShareDirList {
required string ssl_id = 1;
required string path = 2;
}
// RESPONSE: ResponseShareDirList
message ResponseShareDirList {
required rsctrl.core.Status status = 1;
enum ListType {
DIRQUERY_ROOT = 1; // the query refers to root.
DIRQUERY_PERSON = 2; // the query refers to person
DIRQUERY_FILE = 3; // the query refers to a file.
DIRQUERY_DIR = 4; // move to top of queue.
}
required string ssl_id = 2;
required string path = 3;
required ListType list_type = 4;
repeated rsctrl.core.File files = 5;
}
//// REQUEST: RequestChangeShares
//
//// REQUEST: RequestLiCloseSearch
//// REQUEST: RequestCloseSearch
//
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

View File

@ -1,287 +0,0 @@
package rsctrl.gxs;
import "core.proto";
///////////////////////////////////////////////////////////////
// Base Messages for GXS Interface.
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestPeers = 1;
MsgId_RequestAddPeer = 2;
MsgId_RequestModifyPeer = 3;
}
enum ResponseMsgIds {
MsgId_ResponsePeerList = 1;
MsgId_ResponseAddPeer = 2;
MsgId_ResponseModifyPeer = 3;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// BASE DATA TYPES
message Service {
//
required uint32 service_id = 1;
optional string service_name = 2;
}
message GroupMeta {
// FLAGS as ENUMs.
enum GroupFlags {
GF_FLAG1 = 1;
GF_FLAG2 = 2;
GF_FLAG3 = 4;
GF_FLAG4 = 8;
}
enum SignFlags {
SF_FLAG1 = 1;
SF_FLAG2 = 2;
}
enum SubscribeFlags {
SUBF_FLAG1 = 1;
SUBF_FLAG2 = 2;
}
enum StatusFlags {
STATF_FLAG1 = 1;
STATF_FLAG2 = 2;
}
// THIS IS FIXED: From NETWORK.
required string group_id = 1;
required string group_name = 2;
required uint32 group_flags = 3;
required uint32 sign_flags = 4;
required uint32 publish_ts = 5;
optional string author_id = 6;
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
required uint32 subscribe_flags = 7;
required uint32 group_status = 8;
optional string service_string = 9;
optional uint32 pop = 10; // USED?
optional uint32 msg_count = 11; // ???
optional int32 last_post = 12; // ???
}
message GroupGenericData {
required GroupMeta meta = 1;
required string encoded_data = 2;
}
message MsgMeta {
// FLAGS as ENUMs.
enum GroupFlags {
GF_FLAG1 = 1;
GF_FLAG2 = 2;
GF_FLAG3 = 4;
GF_FLAG4 = 8;
}
enum SignFlags {
SF_FLAG1 = 1;
SF_FLAG2 = 2;
}
enum SubscribeFlags {
SUBF_FLAG1 = 1;
SUBF_FLAG2 = 2;
}
enum StatusFlags {
STATF_FLAG1 = 1;
STATF_FLAG2 = 2;
}
// THIS IS FIXED: From NETWORK.
required string group_id = 1;
required string msg_id = 2;
required string thread_id = 3;
required uint32 parent_id = 4;
required uint32 origmsg_id = 5;
optional string author_id = 6;
required uint32 publish_ts = 7;
required uint32 msg_name = 8;
required uint32 msg_flags = 9;
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
required uint32 msg_status = 10;
required uint32 child_ts = 11;
optional string service_string = 12;
}
message MsgGenericData {
required MsgMeta meta = 1;
required string encoded_data = 2;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
message Filter {
required uint32 options = 1;
optional uint32 status_filter = 2;
optional uint32 status_mask = 3;
optional uint32 req_type = 4;
optional uint32 subscribe_filter = 5;
optional int32 before = 6;
optional int32 after = 7;
}
message MsgSet {
required string group_id = 1;
repeated string msg_id = 2;
}
message GroupMsgSet {
repeated MsgSet groups = 1;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// REQUEST: RequestGroupInfo
message RequestGroupInfo {
required Service service = 1;
required uint32 ans_type = 2;
required Filter options = 3;
repeated string group_ids = 4;
}
// RESPONSE: ResponseGroupList
message ResponseGroupList {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated string group_ids = 3;
}
// RESPONSE: ResponseGroupMeta
message ResponseGroupMeta {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated GroupMeta meta = 3;
}
// RESPONSE: ResponseGroupData
message ResponseGroupData {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated GroupGenericData data = 3;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestMsgInfo
message RequestMsgInfo {
required Service service = 1;
required uint32 ans_type = 2;
required Filter options = 3;
repeated GroupMsgSet msgs = 4;
}
// REQUEST: RequestMsgRelatedInfo
message RequestMsgRelatedInfo {
required Service service = 1;
required uint32 ans_type = 2;
required Filter options = 3;
repeated GroupMsgSet msgs = 4;
}
// RESPONSE: ResponseMsgList
message ResponseMsgList {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated GroupMsgSet msgs = 3;
}
// RESPONSE: ResponseMsgMeta
message ResponseMsgMeta {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated MsgMeta meta = 3;
}
// RESPONSE: ResponseMsgData
message ResponseMsgData {
required rsctrl.core.Status status = 1;
required Service service = 2;
repeated MsgGenericData data = 3;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// REQUEST: RequestCreateGroup
message RequestCreateGroup {
required Service service = 1;
repeated GroupGenericData data = 2;
}
// RESPONSE: ResponseMsgMeta
// As defined above.
// REQUEST: RequestCreateMsg
message RequestCreateMsg {
required Service service = 1;
repeated MsgGenericData data = 2;
}
// RESPONSE: ResponseMsgMeta
// As defined above.

View File

@ -1,108 +0,0 @@
package rsctrl.msgs;
import "core.proto";
///////////////////////////////////////////////////////////////
// Access, and Control your Friends / Peers and related Settings.
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestPeers = 1;
MsgId_RequestAddPeer = 2;
MsgId_RequestModifyPeer = 3;
}
enum ResponseMsgIds {
MsgId_ResponsePeerList = 1;
MsgId_ResponseAddPeer = 2;
MsgId_ResponseModifyPeer = 3;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestPeers
message RequestPeers {
// About Who?
enum SetOption {
OWNID = 1;
LISTED = 2;
ONLINE = 3;
FRIENDS = 4;
VALID = 5;
SIGNED = 6;
ALL = 7;
}
// What do you want?
enum InfoOption {
NAMEONLY = 1;
BASIC = 2;
LOCATION = 3;
ALLINFO = 4;
}
required SetOption set = 1;
required InfoOption info = 2;
repeated string gpg_ids = 3;
}
// RESPONSE: ResponsePeerList
message ResponsePeerList {
required rsctrl.core.Status status = 1;
repeated rsctrl.core.Person peers = 2;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestAddPeer
message RequestAddPeer {
enum AddCmd {
NOOP = 0; // No op.
ADD = 1; // Add existing from gpg_id.
REMOVE = 2; // Remove existing from gpg_id.
IMPORT = 3; // Import from cert, with gpg_id.
EXAMINE = 4; // Examine cert, but no action.
}
required string gpg_id = 1;
required AddCmd cmd = 2;
optional string cert = 3;
}
// RESPONSE: ResponseAddPeer
message ResponseAddPeer {
required rsctrl.core.Status status = 1;
repeated rsctrl.core.Person peers = 2;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestModifyPeer
message RequestModifyPeer {
enum ModCmd {
NOOP = 0;
ADDRESS = 1;
DYNDNS = 2;
//SOMETHING_ELSE = 0x0000010;
//SOMETHING_ELSE = 0x0000020;
//SOMETHING_ELSE = 0x0000040;
//SOMETHING_ELSE = 0x0000080;
}
required ModCmd cmd = 1;
//required int64 cmd = 1; // Could we OR the Cmds together?
repeated rsctrl.core.Person peers = 2;
}
// RESPONSE: ResponseModifyPeer
message ResponseModifyPeer {
required rsctrl.core.Status status = 1;
repeated rsctrl.core.Person peers = 2;
}
///////////////////////////////////////////////////////////////

View File

@ -1,111 +0,0 @@
package rsctrl.peers;
import "core.proto";
///////////////////////////////////////////////////////////////
// Access, and Control your Friends / Peers and related Settings.
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestPeers = 1;
MsgId_RequestAddPeer = 2;
MsgId_RequestExaminePeer = 3;
MsgId_RequestModifyPeer = 4;
}
enum ResponseMsgIds {
MsgId_ResponsePeerList = 1;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestPeers
message RequestPeers {
// About Who?
enum SetOption {
OWNID = 1;
LISTED = 2;
CONNECTED = 3;
FRIENDS = 4;
VALID = 5;
SIGNED = 6;
ALL = 7;
}
// What do you want?
enum InfoOption {
NAMEONLY = 1;
BASIC = 2;
LOCATION = 3;
ALLINFO = 4;
}
required SetOption set = 1;
required InfoOption info = 2;
repeated string pgp_ids = 3;
}
// RESPONSE: ResponsePeerList
message ResponsePeerList {
required rsctrl.core.Status status = 1;
repeated rsctrl.core.Person peers = 2;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestAddPeer
message RequestAddPeer {
enum AddCmd {
ADD = 1; // Add existing from gpg_id.
REMOVE = 2; // Remove existing from gpg_id.
}
required AddCmd cmd = 1;
required string pgp_id = 2;
optional string ssl_id = 3;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestExaminePeer
message RequestExaminePeer {
enum ExamineCmd {
IMPORT = 3; // Import from cert, with gpg_id.
EXAMINE = 4; // Examine cert, but no action.
}
// Must have GPG ID to import. Proves you've looked at it.
required string pgp_id = 1;
required ExamineCmd cmd = 2;
required string cert = 3;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestModifyPeer
// THIS IS INCOMPLETE... DON'T USE.
message RequestModifyPeer {
enum ModCmd {
NOOP = 0;
ADDRESS = 1;
DYNDNS = 2;
//SOMETHING_ELSE = 0x0000010;
//SOMETHING_ELSE = 0x0000020;
//SOMETHING_ELSE = 0x0000040;
//SOMETHING_ELSE = 0x0000080;
}
required ModCmd cmd = 1;
//required int64 cmd = 1; // Could we OR the Cmds together?
repeated rsctrl.core.Person peers = 2;
}
///////////////////////////////////////////////////////////////

View File

@ -1,120 +0,0 @@
package rsctrl.search;
import "core.proto";
///////////////////////////////////////////////////////////////
// Searches
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestBasicSearch = 1;
//MsgId_RequestAdvSearch = 2; // NOT IMPLEMENTED YET.
MsgId_RequestCloseSearch = 3;
MsgId_RequestListSearches = 4;
MsgId_RequestSearchResults = 5;
}
enum ResponseMsgIds {
MsgId_ResponseSearchIds = 1;
MsgId_ResponseSearchResults = 5;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Building Block
message SearchHit {
enum LocFlag {
LOCAL = 1; // We Have it.
FRIEND = 2; // Browsable
NETWORK = 4; // Network.
}
required rsctrl.core.File file = 1;
required uint32 loc = 2; // OR of LocFlag so uint field
required uint32 no_hits = 3; // NOT USED YET.
repeated string alt_names = 4;
}
message SearchSet {
required uint32 search_id = 1;
repeated SearchHit hits = 2;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// SEARCH (start).
// REQUEST: RequestBasicSearch
message RequestBasicSearch {
repeated string terms = 1;
}
// REQUEST: RequestAdvSearch
message RequestAdvSearch {
repeated string terms = 1;
}
// RESPONSE: ResponseSearchIds
message ResponseSearchIds {
required rsctrl.core.Status status = 1;
repeated uint32 search_id = 2;
}
///////////////////////////////////////////////////////////////
// SEARCH (cancel)
// REQUEST: RequestCloseSearch
message RequestCloseSearch {
required uint32 search_id = 1;
}
// RESPONSE: ResponseSearchIds
// As before.
///////////////////////////////////////////////////////////////
// SEARCH (list)
// REQUEST: RequestListSearches
message RequestListSearches {
// Nothing here.
}
// RESPONSE: ResponseSearchIds
// As before.
///////////////////////////////////////////////////////////////
// SEARCH (list)
// REQUEST: RequestSearchResults
// Empty search_ids => all results.
message RequestSearchResults {
optional uint32 result_limit = 1;
repeated uint32 search_ids = 2;
}
// RESPONSE: ResponseSearchResults
message ResponseSearchResults {
required rsctrl.core.Status status = 1;
repeated SearchSet searches = 2;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

View File

@ -1,152 +0,0 @@
package rsctrl.stream;
import "core.proto";
///////////////////////////////////////////////////////////////
// This protocol defines how to stream data from retroshare.
// It can be used for VoIP or Files, or whatever.
//
// There are two parts.
// Control and actual streaming.
//
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestStartFileStream = 1;
MsgId_RequestControlStream = 2;
MsgId_RequestListStreams = 3;
}
enum ResponseMsgIds {
MsgId_ResponseStreamDetail = 1; // RESPONSE to List and Control.
MsgId_ResponseStreamData = 101;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Building Blocks
enum StreamType {
STREAM_TYPE_ALL = 1; // all streams
STREAM_TYPE_FILES = 2; // files stream
STREAM_TYPE_VOIP = 3; // VoIP stream
STREAM_TYPE_OTHER = 4; // Who knows what else.
}
enum StreamState {
STREAM_STATE_ERROR = 0;
STREAM_STATE_RUN = 1;
STREAM_STATE_PAUSED = 2;
STREAM_STATE_FINISHED = 3;
}
message StreamFileDetail {
required rsctrl.core.File file = 1;
required uint64 offset = 5;
}
message StreamVoipDetail {
// THIS NEEDS MORE DEFINITION.
required string peer_id = 1;
required uint64 duration = 2;
required uint64 offset = 3;
}
message StreamDesc {
required uint32 stream_id = 1;
required StreamType stream_type = 2;
required StreamState stream_state = 3;
required float rate_kbs = 4;
optional StreamFileDetail file = 5;
optional StreamVoipDetail voip = 6;
}
message StreamData {
required uint32 stream_id = 1;
required StreamState stream_state = 2;
required rsctrl.core.Timestamp send_time = 3;
required uint64 offset = 4;
required uint32 size = 5;
required bytes stream_data = 6;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// REQUEST: RequestStartFileStream
message RequestStartFileStream {
required rsctrl.core.File file = 1;
required float rate_kbs = 2;
// byte range. allows to restart transfer!
optional uint64 start_byte = 3;
optional uint64 end_byte = 4;
}
// RESPONSE: ResponseStreamDetail
message ResponseStreamDetail {
required rsctrl.core.Status status = 1;
repeated StreamDesc streams = 2;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// REQUEST: RequestControlStream
message RequestControlStream {
enum StreamAction {
STREAM_START = 1; // start stream
STREAM_STOP = 2; // stop stream
STREAM_PAUSE = 3; // pause stream
STREAM_CHANGE_RATE = 4; // rate of the stream
STREAM_SEEK = 5; // move streaming position.
}
required uint32 stream_id = 1;
required StreamAction action = 2;
optional float rate_kbs = 3;
optional uint64 seek_byte = 4;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// REQUEST: RequestListStreams
message RequestListStreams {
required StreamType request_type = 1;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// RESPONSE: ResponseStreamData
message ResponseStreamData {
required rsctrl.core.Status status = 1;
required StreamData data = 2;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

View File

@ -1,121 +0,0 @@
package rsctrl.system;
import "core.proto";
///////////////////////////////////////////////////////////////
// Configuration and Stats.
///////////////////////////////////////////////////////////////
enum RequestMsgIds {
MsgId_RequestSystemStatus = 1;
MsgId_RequestSystemQuit = 2;
MsgId_RequestSystemExternalAccess = 3;
MsgId_RequestSystemAccount = 4;
}
enum ResponseMsgIds {
MsgId_ResponseSystemStatus = 1;
MsgId_ResponseSystemQuit = 2;
MsgId_ResponseSystemExternalAccess = 3;
MsgId_ResponseSystemAccount = 4;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestSystemStatus
message RequestSystemStatus {
// Nothing here?
}
// RESPONSE: ResponseSystemStatus
message ResponseSystemStatus {
enum NetCode {
BAD_UNKNOWN = 0;
BAD_OFFLINE = 1;
BAD_NATSYM = 2;
BAD_NODHT_NAT = 3;
WARNING_RESTART = 4;
WARNING_NATTED = 5;
WARNING_NODHT = 6;
GOOD = 7;
ADV_FORWARD = 8;
}
// Status of response.
required rsctrl.core.Status status = 1;
// Peers.
required uint32 no_peers = 2;
required uint32 no_connected = 3;
// Basic Network Information.
required NetCode net_status = 4;
required rsctrl.core.Bandwidth bw_total = 5;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestSystemQuit
message RequestSystemQuit {
enum QuitCode {
CLOSE_CHANNEL = 1;
SHUTDOWN_RS = 2; // NOT RECOMMENDED (but some people might like it)
}
required QuitCode quit_code = 1;
}
// RESPONSE: ResponseSystemQuit
// Effect potentially immediate (with loss of connection) - only expect a response error.
// Shutdown takes longer - so you should get a response.
message ResponseSystemQuit {
// Status of response.
required rsctrl.core.Status status = 1;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestSystemExternalAccess
message RequestSystemExternalAccess {
// Nothing here?
}
// RESPONSE: ResponseSystemExternalAccess
message ResponseSystemExternalAccess {
// Status of response.
required rsctrl.core.Status status = 1;
required uint32 ext_port = 2;
required string dht_key = 3;
}
///////////////////////////////////////////////////////////////
// REQUEST: RequestSystemAccount
message RequestSystemAccount {
// Nothing here?
}
// RESPONSE: ResponseSystemAccount
message ResponseSystemAccount {
// Status of response.
required rsctrl.core.Status status = 1;
required string pgp_name = 2;
required string location = 3;
required string pgp_id = 4;
required string ssl_id = 5;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////