merged with upstream/master

This commit is contained in:
csoler 2015-12-19 19:15:48 -05:00
commit 462f969da7
16 changed files with 253 additions and 103 deletions

View File

@ -71,6 +71,7 @@ Chat
E [ ] add flags to allow distant chat from contact list only / everyone / noone / only signed ids. E [ ] add flags to allow distant chat from contact list only / everyone / noone / only signed ids.
Libretroshare Libretroshare
E [ ] groups small packets in pqistreamer::handleoutgoing_locked(), and see if that removes some padding overhead
E [ ] make sure at least one location is kept when removing old locations as it avoids lots of connection problems. E [ ] make sure at least one location is kept when removing old locations as it avoids lots of connection problems.
M [ ] improve serialisation system. Lots of serialisation tasks (header, verifications, serialiser=>template, can be factored) M [ ] improve serialisation system. Lots of serialisation tasks (header, verifications, serialiser=>template, can be factored)
M [ ] separate chat stuff from rsmsgs.h into rschat.h M [ ] separate chat stuff from rsmsgs.h into rschat.h

View File

@ -32,7 +32,9 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#ifndef WIN32
#include <sys/select.h> #include <sys/select.h>
#endif
/*** /***
* #define UDP_ENABLE_BROADCAST 1 * #define UDP_ENABLE_BROADCAST 1

View File

@ -0,0 +1,41 @@
#include "ApiPluginHandler.h"
namespace resource_api
{
ApiPluginHandler::ApiPluginHandler(StateTokenServer* statetokenserver, const RsPlugInInterfaces& ifaces)
{
for(int i = 0; i < ifaces.mPluginHandler->nbPlugins(); i++)
{
RsPlugin* plugin = ifaces.mPluginHandler->plugin(i);
// if plugin is not loaded, pointer is null
if(plugin == 0)
continue;
std::string entrypoint;
ResourceRouter* child = plugin->new_resource_api_handler(ifaces, statetokenserver, entrypoint);
if(child != 0)
{
mChildren.push_back(child);
if(isNameUsed(entrypoint))
{
std::cerr << "Cannot add plugin api entry point with name=" << entrypoint << ", becaus ethis name is already in use!" << std::endl;
}
else
{
std::cerr << "Added libresapi plugin with entrypoint " << entrypoint << std::endl;
addResourceHandler(entrypoint, child, &ResourceRouter::handleRequest);
}
}
}
}
ApiPluginHandler::~ApiPluginHandler()
{
for(std::vector<ResourceRouter*>::iterator vit = mChildren.begin(); vit != mChildren.end(); ++vit)
{
delete *vit;
}
mChildren.clear();
}
} // namespace resource_api

View File

@ -0,0 +1,20 @@
#pragma once
#include "ResourceRouter.h"
#include <retroshare/rsplugin.h>
namespace resource_api
{
// forwards all incoming requests to retroshare plugins
class ApiPluginHandler: public ResourceRouter
{
public:
ApiPluginHandler(StateTokenServer* statetokenserver, const RsPlugInInterfaces& ifaces);
virtual ~ApiPluginHandler();
private:
std::vector<ResourceRouter*> mChildren;
};
} // namespace resource_api

View File

@ -13,6 +13,8 @@
#include "JsonStream.h" #include "JsonStream.h"
#include "StateTokenServer.h" // for the state token serialisers #include "StateTokenServer.h" // for the state token serialisers
#include "ApiPluginHandler.h"
/* /*
data types in json http://json.org/ data types in json http://json.org/
string (utf-8 unicode) string (utf-8 unicode)
@ -226,10 +228,11 @@ public:
mPeersHandler(sts, ifaces.mNotify, ifaces.mPeers, ifaces.mMsgs), mPeersHandler(sts, ifaces.mNotify, ifaces.mPeers, ifaces.mMsgs),
mIdentityHandler(ifaces.mIdentity), mIdentityHandler(ifaces.mIdentity),
mForumHandler(ifaces.mGxsForums), mForumHandler(ifaces.mGxsForums),
mServiceControlHandler(rsServiceControl), // TODO: don't use global variable here mServiceControlHandler(ifaces.mServiceControl),
mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles), mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles),
mTransfersHandler(sts, ifaces.mFiles), mTransfersHandler(sts, ifaces.mFiles),
mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler) mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler),
mApiPluginHandler(sts, ifaces)
{ {
// the dynamic cast is to not confuse the addResourceHandler template like this: // the dynamic cast is to not confuse the addResourceHandler template like this:
// addResourceHandler(derived class, parent class) // addResourceHandler(derived class, parent class)
@ -249,6 +252,8 @@ public:
&TransfersHandler::handleRequest); &TransfersHandler::handleRequest);
router.addResourceHandler("chat", dynamic_cast<ResourceRouter*>(&mChatHandler), router.addResourceHandler("chat", dynamic_cast<ResourceRouter*>(&mChatHandler),
&ChatHandler::handleRequest); &ChatHandler::handleRequest);
router.addResourceHandler("apiplugin", dynamic_cast<ResourceRouter*>(&mApiPluginHandler),
&ChatHandler::handleRequest);
} }
PeersHandler mPeersHandler; PeersHandler mPeersHandler;
@ -258,6 +263,7 @@ public:
FileSearchHandler mFileSearchHandler; FileSearchHandler mFileSearchHandler;
TransfersHandler mTransfersHandler; TransfersHandler mTransfersHandler;
ChatHandler mChatHandler; ChatHandler mChatHandler;
ApiPluginHandler mApiPluginHandler;
}; };
ApiServer::ApiServer(): ApiServer::ApiServer():

View File

@ -173,10 +173,8 @@ void ChatHandler::tick()
} }
} }
ChatId id = ChatId::makeBroadcastId();
{ {
Lobby l; Lobby l;
l.id = id.toLobbyId();
l.name = "BroadCast"; l.name = "BroadCast";
l.topic = "Retroshare broadcast chat: messages are sent to all connected friends."; l.topic = "Retroshare broadcast chat: messages are sent to all connected friends.";
l.subscribed = true; l.subscribed = true;

View File

@ -7,6 +7,7 @@
#include <retroshare/rsdisc.h> #include <retroshare/rsdisc.h>
#include <retroshare/rsdht.h> #include <retroshare/rsdht.h>
#include <retroshare/rsnotify.h> #include <retroshare/rsnotify.h>
#include <retroshare/rsservicecontrol.h>
#include <retroshare/rsidentity.h> #include <retroshare/rsidentity.h>
#include <retroshare/rsgxscircles.h> #include <retroshare/rsgxscircles.h>
@ -28,6 +29,8 @@ bool getPluginInterfaces(RsPlugInInterfaces& interfaces)
interfaces.mDisc = rsDisc; interfaces.mDisc = rsDisc;
interfaces.mDht = rsDht; interfaces.mDht = rsDht;
interfaces.mNotify = rsNotify; interfaces.mNotify = rsNotify;
interfaces.mServiceControl = rsServiceControl;
interfaces.mPluginHandler = rsPlugins;
// gxs // gxs
interfaces.mGxsDir = ""; interfaces.mGxsDir = "";

View File

@ -55,4 +55,17 @@ ResponseTask* ResourceRouter::handleRequest(Request& req, Response& resp)
return 0; return 0;
} }
bool ResourceRouter::isNameUsed(std::string name)
{
std::vector<std::pair<std::string, HandlerBase*> >::iterator vit;
for(vit = mHandlers.begin(); vit != mHandlers.end(); vit++)
{
if(vit->first == name)
{
return true;
}
}
return false;
}
} // namespace resource_api } // namespace resource_api

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "ApiTypes.h" #include "ApiTypes.h"
#include <iostream>
namespace resource_api namespace resource_api
{ {
@ -20,6 +21,8 @@ public:
void addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp)); void addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp));
template <class T> template <class T>
void addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp)); void addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp));
bool isNameUsed(std::string name);
private: private:
class HandlerBase class HandlerBase
{ {
@ -61,6 +64,10 @@ private:
template <class T> template <class T>
void ResourceRouter::addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp)) void ResourceRouter::addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp))
{ {
if(isNameUsed(name))
{
std::cerr << "ResourceRouter::addResourceHandler ERROR: name=" << name << " alerady in use. Not adding new Handler!" << std::endl;
}
Handler<T>* handler = new Handler<T>(); Handler<T>* handler = new Handler<T>();
handler->instance = instance; handler->instance = instance;
handler->method = callback; handler->method = callback;
@ -69,6 +76,10 @@ void ResourceRouter::addResourceHandler(std::string name, T* instance, ResponseT
template <class T> template <class T>
void ResourceRouter::addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp)) void ResourceRouter::addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp))
{ {
if(isNameUsed(name))
{
std::cerr << "ResourceRouter::addResourceHandler ERROR: name=" << name << " alerady in use. Not adding new Handler!" << std::endl;
}
InstantResponseHandler<T>* handler = new InstantResponseHandler<T>(); InstantResponseHandler<T>* handler = new InstantResponseHandler<T>();
handler->instance = instance; handler->instance = instance;
handler->method = callback; handler->method = callback;

View File

@ -65,7 +65,8 @@ SOURCES += \
api/ChatHandler.cpp \ api/ChatHandler.cpp \
api/LivereloadHandler.cpp \ api/LivereloadHandler.cpp \
api/TmpBlobStore.cpp \ api/TmpBlobStore.cpp \
util/ContentTypes.cpp util/ContentTypes.cpp \
api/ApiPluginHandler.cpp
HEADERS += \ HEADERS += \
api/ApiServer.h \ api/ApiServer.h \
@ -89,4 +90,5 @@ HEADERS += \
api/ChatHandler.h \ api/ChatHandler.h \
api/LivereloadHandler.h \ api/LivereloadHandler.h \
api/TmpBlobStore.h \ api/TmpBlobStore.h \
util/ContentTypes.h util/ContentTypes.h \
api/ApiPluginHandler.h

View File

@ -343,7 +343,6 @@ int RsGxsNetService::tick()
mLastCleanRejectedMessages = now ; mLastCleanRejectedMessages = now ;
cleanRejectedMessages() ; cleanRejectedMessages() ;
} }
return 1; return 1;
} }

View File

@ -49,6 +49,7 @@ class RsMsgs ;
class RsGxsForums; class RsGxsForums;
class RsGxsChannels; class RsGxsChannels;
class RsNotify; class RsNotify;
class RsServiceControl;
class p3LinkMgr ; class p3LinkMgr ;
class MainPage ; class MainPage ;
class QIcon ; class QIcon ;
@ -75,6 +76,12 @@ class RsGcxs;
class PgpAuxUtils; class PgpAuxUtils;
class p3Config; class p3Config;
namespace resource_api
{
class ResourceRouter;
class StateTokenServer;
}
// Plugin API version. Not used yet, but will be in the future the // Plugin API version. Not used yet, but will be in the future the
// main value that decides for compatibility. // main value that decides for compatibility.
// //
@ -108,6 +115,8 @@ public:
RsUtil::inited_ptr<RsDisc> mDisc; RsUtil::inited_ptr<RsDisc> mDisc;
RsUtil::inited_ptr<RsDht> mDht; RsUtil::inited_ptr<RsDht> mDht;
RsUtil::inited_ptr<RsNotify> mNotify; RsUtil::inited_ptr<RsNotify> mNotify;
RsUtil::inited_ptr<RsServiceControl> mServiceControl;
RsUtil::inited_ptr<RsPluginHandler> mPluginHandler;
// gxs // gxs
std::string mGxsDir; std::string mGxsDir;
@ -147,6 +156,12 @@ class RsPlugin
virtual p3Config *p3_config() const { return NULL ; } virtual p3Config *p3_config() const { return NULL ; }
virtual uint16_t rs_service_id() const { return 0 ; } virtual uint16_t rs_service_id() const { return 0 ; }
// creates a new resource api handler object. ownership is transferred to the caller.
// the caller should supply a statetokenserver, and keep it valid until destruction
// the plugin should return a entry point name. this is to make the entry point name independent from file names
virtual resource_api::ResourceRouter* new_resource_api_handler(const RsPlugInInterfaces& ifaces, resource_api::StateTokenServer* sts, std::string &entrypoint) const { return 0;}
// Shutdown // Shutdown
virtual void stop() {} virtual void stop() {}

View File

@ -1523,6 +1523,8 @@ int RsServer::StartupRetroShare()
interfaces.mDisc = rsDisc; interfaces.mDisc = rsDisc;
interfaces.mDht = rsDht; interfaces.mDht = rsDht;
interfaces.mNotify = mNotify; interfaces.mNotify = mNotify;
interfaces.mServiceControl = serviceCtrl;
interfaces.mPluginHandler = mPluginsManager;
// gxs // gxs
interfaces.mGxsDir = currGxsDir; interfaces.mGxsDir = currGxsDir;
interfaces.mIdentity = mGxsIdService; interfaces.mIdentity = mGxsIdService;

View File

@ -300,16 +300,16 @@ void SearchDialog::initialiseFileTypeMappings()
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO,
"aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma"); "aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma");
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE,
"7z bz2 gz pkg rar sea sit sitx tar zip"); "7z bz2 gz pkg rar sea sit sitx tar zip tgz");
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE,
"iso nrg mdf"); "iso nrg mdf bin");
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_DOCUMENT, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_DOCUMENT,
"doc odt ott rtf pdf ps txt log msg wpd wps" ); "doc odt ott rtf pdf ps txt log msg wpd wps ods xls epub" );
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE,
"3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm " "3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm "
"pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf"); "pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf");
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM,
"app bat cgi com bin exe js pif py pl sh vb ws "); "app bat cgi com bin exe js pif py pl sh vb ws bash");
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO, SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO,
"3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv"); "3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv");
SearchDialog::initialised = true; SearchDialog::initialised = true;

View File

@ -53,6 +53,8 @@
#define COLUMN_ID 3 #define COLUMN_ID 3
#define COLUMN_COUNT 4 #define COLUMN_COUNT 4
#define ROLE_SORT Qt::UserRole + 1
const static uint32_t timeToInactivity = 60 * 10; // in seconds const static uint32_t timeToInactivity = 60 * 10; // in seconds
/** Default constructor */ /** Default constructor */
@ -80,10 +82,25 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
distantChatAct = new QAction(QIcon(":/images/chat_24.png"), tr("Start private chat"), this); distantChatAct = new QAction(QIcon(":/images/chat_24.png"), tr("Start private chat"), this);
sendMessageAct = new QAction(QIcon(":/images/mail_new.png"), tr("Send Message"), this); sendMessageAct = new QAction(QIcon(":/images/mail_new.png"), tr("Send Message"), this);
QActionGroup *sortgrp = new QActionGroup(this);
actionSortByName = new QAction(QIcon(), tr("Sort by Name"), this);
actionSortByName->setCheckable(true);
actionSortByName->setChecked(true);
actionSortByName->setActionGroup(sortgrp);
actionSortByActivity = new QAction(QIcon(), tr("Sort by Activity"), this);
actionSortByActivity->setCheckable(true);
actionSortByActivity->setChecked(false);
actionSortByActivity->setActionGroup(sortgrp);
connect(muteAct, SIGNAL(triggered()), this, SLOT(changePartipationState())); connect(muteAct, SIGNAL(triggered()), this, SLOT(changePartipationState()));
connect(distantChatAct, SIGNAL(triggered()), this, SLOT(distantChatParticipant())); connect(distantChatAct, SIGNAL(triggered()), this, SLOT(distantChatParticipant()));
connect(sendMessageAct, SIGNAL(triggered()), this, SLOT(sendMessage())); connect(sendMessageAct, SIGNAL(triggered()), this, SLOT(sendMessage()));
connect(actionSortByName, SIGNAL(triggered()), this, SLOT(sortParcipants()));
connect(actionSortByActivity, SIGNAL(triggered()), this, SLOT(sortParcipants()));
// Add a button to invite friends. // Add a button to invite friends.
// //
inviteFriendsButton = new QToolButton ; inviteFriendsButton = new QToolButton ;
@ -94,7 +111,7 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
inviteFriendsButton->setToolTip(tr("Invite friends to this lobby")); inviteFriendsButton->setToolTip(tr("Invite friends to this lobby"));
mParticipantCompareRole = new RSTreeWidgetItemCompareRole; mParticipantCompareRole = new RSTreeWidgetItemCompareRole;
mParticipantCompareRole->setRole(0, Qt::UserRole); mParticipantCompareRole->setRole(COLUMN_ACTIVITY, ROLE_SORT);
{ {
QIcon icon ; QIcon icon ;
@ -179,6 +196,9 @@ void ChatLobbyDialog::participantsTreeWidgetCustomPopupMenu(QPoint)
contextMnu.addAction(sendMessageAct); contextMnu.addAction(sendMessageAct);
contextMnu.addSeparator(); contextMnu.addSeparator();
contextMnu.addAction(muteAct); contextMnu.addAction(muteAct);
contextMnu.addSeparator();
contextMnu.addAction(actionSortByActivity);
contextMnu.addAction(actionSortByName);
muteAct->setCheckable(true); muteAct->setCheckable(true);
@ -451,6 +471,9 @@ void ChatLobbyDialog::updateParticipantsList()
time_t tLastAct=widgetitem->text(COLUMN_ACTIVITY).toInt(); time_t tLastAct=widgetitem->text(COLUMN_ACTIVITY).toInt();
time_t now = time(NULL); time_t now = time(NULL);
widgetitem->setSizeHint(COLUMN_ICON, QSize(20,20));
if(isParticipantMuted(it2->first)) if(isParticipantMuted(it2->first))
widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_red_128.png")); widgetitem->setIcon(COLUMN_ICON, QIcon(":/icons/bullet_red_128.png"));
else if (tLastAct + timeToInactivity < now) else if (tLastAct + timeToInactivity < now)
@ -472,7 +495,7 @@ void ChatLobbyDialog::updateParticipantsList()
} }
} }
ui.participantsList->setSortingEnabled(true); ui.participantsList->setSortingEnabled(true);
ui.participantsList->sortItems(COLUMN_NAME, Qt::AscendingOrder); sortParcipants();
} }
/** /**
@ -762,3 +785,14 @@ void ChatLobbyDialog::showDialog(uint chatflags)
dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby))->setCurrentChatPage(this) ; dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby))->setCurrentChatPage(this) ;
} }
} }
void ChatLobbyDialog::sortParcipants()
{
if (actionSortByActivity->isChecked()) {
ui.participantsList->sortItems(COLUMN_ACTIVITY, Qt::DescendingOrder);
} else if (actionSortByName->isChecked()) {
ui.participantsList->sortItems(COLUMN_NAME, Qt::AscendingOrder);
}
}

View File

@ -47,6 +47,7 @@ public:
void setIdentity(const RsGxsId& gxs_id); void setIdentity(const RsGxsId& gxs_id);
bool isParticipantMuted(const RsGxsId &participant); bool isParticipantMuted(const RsGxsId &participant);
ChatLobbyId id() const { return lobbyId ;} ChatLobbyId id() const { return lobbyId ;}
void sortParcipants();
private slots: private slots:
void participantsTreeWidgetCustomPopupMenu( QPoint point ); void participantsTreeWidgetCustomPopupMenu( QPoint point );
@ -104,6 +105,8 @@ private:
QAction *muteAct; QAction *muteAct;
QAction *distantChatAct; QAction *distantChatAct;
QAction *actionSortByName;
QAction *actionSortByActivity;
QWidgetAction *checkableAction; QWidgetAction *checkableAction;
QAction *sendMessageAct; QAction *sendMessageAct;