mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge pull request #528 from sehraf/pr-drop-ssh-protobuf
remove deprecated ssh/protobuf code
This commit is contained in:
commit
9a3eb1cf9a
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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> ®istered, std::list<RpcQueuedMsg> &events);
|
||||
};
|
||||
|
||||
|
||||
#endif /* RS_PROTO_CHAT_H */
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -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> ®istered, std::list<RpcQueuedMsg> &events);
|
||||
|
||||
// Not actually used yet.
|
||||
int cleanup_checkForEvents(uint32_t event, const std::list<RpcEventRegister> ®istered);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* RS_PROTO_STREAM_H */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
@ -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> ®istered, 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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> ®istered, 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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -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
|
||||
//
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user