WIP: adding service files, still not working
This commit is contained in:
+9
-2
@@ -7,13 +7,17 @@ bin_PROGRAMS = lms
|
|||||||
|
|
||||||
lms_SOURCES = \
|
lms_SOURCES = \
|
||||||
$(top_srcdir)/main/main.cpp \
|
$(top_srcdir)/main/main.cpp \
|
||||||
$(top_srcdir)/main/LmsApplication.cpp \
|
$(top_srcdir)/main/ServiceManager.cpp \
|
||||||
|
$(top_srcdir)/main/DatabaseRefreshService.cpp \
|
||||||
|
$(top_srcdir)/main/RemoteServerService.cpp \
|
||||||
|
$(top_srcdir)/main/WebServerService.cpp \
|
||||||
$(top_srcdir)/av/CodecContext.cpp \
|
$(top_srcdir)/av/CodecContext.cpp \
|
||||||
$(top_srcdir)/av/Common.cpp \
|
$(top_srcdir)/av/Common.cpp \
|
||||||
$(top_srcdir)/av/Dictionary.cpp \
|
$(top_srcdir)/av/Dictionary.cpp \
|
||||||
$(top_srcdir)/av/FormatContext.cpp \
|
$(top_srcdir)/av/FormatContext.cpp \
|
||||||
$(top_srcdir)/av/InputFormatContext.cpp \
|
$(top_srcdir)/av/InputFormatContext.cpp \
|
||||||
$(top_srcdir)/av/Stream.cpp \
|
$(top_srcdir)/av/Stream.cpp \
|
||||||
|
$(top_srcdir)/ui/LmsApplication.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioWidget.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioDatabaseWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioDatabaseWidget.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioMediaPlayerWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioMediaPlayerWidget.cpp \
|
||||||
@@ -35,6 +39,9 @@ lms_SOURCES = \
|
|||||||
$(top_srcdir)/database/SqlQuery.cpp \
|
$(top_srcdir)/database/SqlQuery.cpp \
|
||||||
$(top_srcdir)/database/Path.cpp \
|
$(top_srcdir)/database/Path.cpp \
|
||||||
$(top_srcdir)/database/Video.cpp \
|
$(top_srcdir)/database/Video.cpp \
|
||||||
|
$(top_srcdir)/remote/server/Connection.cpp \
|
||||||
|
$(top_srcdir)/remote/server/ConnectionManager.cpp \
|
||||||
|
$(top_srcdir)/remote/server/Server.cpp \
|
||||||
$(top_srcdir)/transcode/AvConvTranscoder.cpp \
|
$(top_srcdir)/transcode/AvConvTranscoder.cpp \
|
||||||
$(top_srcdir)/transcode/Format.cpp \
|
$(top_srcdir)/transcode/Format.cpp \
|
||||||
$(top_srcdir)/transcode/Parameters.cpp \
|
$(top_srcdir)/transcode/Parameters.cpp \
|
||||||
@@ -43,5 +50,5 @@ lms_SOURCES = \
|
|||||||
$(top_srcdir)/metadata/Extractor.cpp \
|
$(top_srcdir)/metadata/Extractor.cpp \
|
||||||
$(top_srcdir)/metadata/Utils.cpp
|
$(top_srcdir)/metadata/Utils.cpp
|
||||||
|
|
||||||
lms_CXXFLAGS=-std=c++11 -Wall -I$(top_srcdir)/boost/ -I$(top_srcdir)/ui
|
lms_CXXFLAGS=-std=c++11 -Wall -I$(top_srcdir)/boost/ -I$(top_srcdir)/ui -I$(top_srcdir)/remote
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
[Users]
|
[Users]
|
||||||
- Do the feature
|
- Do the feature
|
||||||
|
|
||||||
[Pictures]
|
|
||||||
- Do the feature (merge the Video/Pictures feature? i.e. for personal holiday data sharing...)
|
|
||||||
|
|
||||||
[Database]
|
[Database]
|
||||||
- When removing a track, make sure to remove genre/artist/release if last
|
- When removing a track, make sure to remove genre/artist/release if last
|
||||||
- Use Inotify like system to watch modified/added files
|
- Use Inotify like system to watch modified/added files
|
||||||
- Implement a video database cleanup
|
- Implement a video database cleanup
|
||||||
- User access for Video/Pictures (really needed for Audio?)
|
- User access for Video/Pictures (really needed for Audio?)
|
||||||
- Create a new type: "share", that handles every other types in a directory based share?
|
- Create a new type: "share", that handles every other types in a directory based share?
|
||||||
|
- Group video in "video groups". Each video may has sub groups (current "Path" class)
|
||||||
|
- Simplify database and remove the Path class
|
||||||
|
|
||||||
[Audio]
|
[Audio]
|
||||||
- TableViewFilter: <All> -> Track count for this speccial category
|
- TableViewFilter: <All> -> Track count for this speccial category
|
||||||
@@ -20,9 +19,15 @@
|
|||||||
- TrackView : select only relevant columns to speed up queries (do not get eveything)
|
- TrackView : select only relevant columns to speed up queries (do not get eveything)
|
||||||
- OGG metadata -> properly handle metadata nested in the audio stream
|
- OGG metadata -> properly handle metadata nested in the audio stream
|
||||||
|
|
||||||
|
[Video]
|
||||||
|
- View the Videos in a WtTableView ?
|
||||||
|
|
||||||
[Remote API]
|
[Remote API]
|
||||||
- Think about a remote API to get/retrieve transcoded files (i.e. for mobile apps)?
|
- Think about a remote API to get/retrieve media (i.e. for mobile apps)
|
||||||
|
|
||||||
[Layout]
|
[Layout]
|
||||||
- Make it mobile browser compatible
|
- Make it mobile browser compatible
|
||||||
- Style eveything nicely...
|
- Style eveything nicely...
|
||||||
|
|
||||||
|
[Logs]
|
||||||
|
- Use a logging facility
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ AC_CHECK_HEADERS([Wt/WApplication extractor.h],
|
|||||||
# [],
|
# [],
|
||||||
# [AC_MSG_ERROR([Header not found or unusable !])])
|
# [AC_MSG_ERROR([Header not found or unusable !])])
|
||||||
|
|
||||||
|
AC_CHECK_LIB([pthread],
|
||||||
|
[pthread_create],
|
||||||
|
,
|
||||||
|
[AC_MSG_ERROR([libpthread not found!])])
|
||||||
|
|
||||||
AC_CHECK_LIB([avutil],
|
AC_CHECK_LIB([avutil],
|
||||||
[av_free],
|
[av_free],
|
||||||
,
|
,
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
#include "DatabaseRefreshService.hpp"
|
||||||
|
|
||||||
|
DatabaseRefreshService::DatabaseRefreshService(const boost::filesystem::path& p)
|
||||||
|
: _metadataParser(),
|
||||||
|
_database( p, _metadataParser)
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO read from the database itself!
|
||||||
|
// Move this code in the database class
|
||||||
|
_database.watchDirectory( WatchedDirectory("/storage/common/Media/Son/Metal", WatchedDirectory::Audio) );
|
||||||
|
_database.watchDirectory( WatchedDirectory("/storage/common/Media/Video", WatchedDirectory::Video) );
|
||||||
|
|
||||||
|
// TODO launch thread
|
||||||
|
// boost::thread refreshThread(boost::bind(&Database::refresh, &database));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DatabaseRefreshService::start(void)
|
||||||
|
{
|
||||||
|
std::cout << "DatabaseRefreshService::start, not implemented" << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DatabaseRefreshService::stop(void)
|
||||||
|
{
|
||||||
|
std::cout << "DatabaseRefreshService::stop, not implemented" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DatabaseRefreshService::restart(void)
|
||||||
|
{
|
||||||
|
std::cout << "DatabaseRefreshService::restart, not implemented" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef DB_REFRESH_SERVICE_HPP
|
||||||
|
#define DB_REFRESH_SERVICE_HPP
|
||||||
|
|
||||||
|
#include "metadata/AvFormat.hpp"
|
||||||
|
#include "database/Database.hpp"
|
||||||
|
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
class DatabaseRefreshService : public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DatabaseRefreshService(const boost::filesystem::path& p);
|
||||||
|
|
||||||
|
void start(void);
|
||||||
|
void stop(void);
|
||||||
|
void restart(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MetaData::AvFormat _metadataParser;
|
||||||
|
Database _database;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
#include "RemoteServerService.hpp"
|
||||||
|
|
||||||
|
RemoteServerService::RemoteServerService(const Remote::Server::Server::endpoint_type& endpoint)
|
||||||
|
: _server(endpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteServerService::start(void)
|
||||||
|
{
|
||||||
|
std::cout << "émoteServerService::start, starting..." << std::endl;
|
||||||
|
_server.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteServerService::stop(void)
|
||||||
|
{
|
||||||
|
std::cout << "émoteServerService::stop, stopping..." << std::endl;
|
||||||
|
_server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteServerService::restart(void)
|
||||||
|
{
|
||||||
|
std::cout << "émoteServerService::restart, not implemented!" << std::endl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef REMOTE_SERVER_SERVICE_HPP
|
||||||
|
#define REMOTE_SERVER_SERVICE_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
#include "remote/server/Server.hpp"
|
||||||
|
|
||||||
|
class RemoteServerService : public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RemoteServerService(const Remote::Server::Server::endpoint_type& endpoint);
|
||||||
|
|
||||||
|
void start(void);
|
||||||
|
void stop(void);
|
||||||
|
void restart(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Remote::Server::Server _server;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef SERVICE_HPP
|
||||||
|
#define SERVICE_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
// Interface class wrapper for running services
|
||||||
|
class Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Service> pointer;
|
||||||
|
|
||||||
|
Service(const Service&) = delete;
|
||||||
|
Service& operator=(const Service&) = delete;
|
||||||
|
|
||||||
|
Service() {}
|
||||||
|
virtual ~Service() {}
|
||||||
|
|
||||||
|
virtual void start(void) = 0;
|
||||||
|
virtual void stop(void) = 0;
|
||||||
|
virtual void restart(void) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include "ServiceManager.hpp"
|
||||||
|
|
||||||
|
ServiceManager::ServiceManager()
|
||||||
|
: _signalSet(_ioService)
|
||||||
|
{
|
||||||
|
_signalSet.add(SIGINT);
|
||||||
|
_signalSet.add(SIGTERM);
|
||||||
|
#if defined(SIGQUIT)
|
||||||
|
_signalSet.add(SIGQUIT);
|
||||||
|
#endif // defined(SIGQUIT)
|
||||||
|
|
||||||
|
_signalSet.add(SIGHUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::run()
|
||||||
|
{
|
||||||
|
|
||||||
|
asyncWaitSignals();
|
||||||
|
|
||||||
|
// Wait for events
|
||||||
|
_ioService.run();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::asyncWaitSignals(void)
|
||||||
|
{
|
||||||
|
_signalSet.async_wait(boost::bind(&ServiceManager::handleSignal,
|
||||||
|
this,
|
||||||
|
boost::asio::placeholders::error,
|
||||||
|
boost::asio::placeholders::signal_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::startService(Service::pointer service)
|
||||||
|
{
|
||||||
|
_services.insert(service);
|
||||||
|
service->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::stopService(Service::pointer service)
|
||||||
|
{
|
||||||
|
_services.erase(service);
|
||||||
|
service->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::stopServices(void)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(Service::pointer service, _services)
|
||||||
|
service->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::restartServices(void)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(Service::pointer service, _services)
|
||||||
|
service->restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceManager::handleSignal(boost::system::error_code /*ec*/, int signo)
|
||||||
|
{
|
||||||
|
std::cout << "Received signal " << signo << std::endl;
|
||||||
|
|
||||||
|
switch (signo)
|
||||||
|
{
|
||||||
|
case SIGINT:
|
||||||
|
case SIGTERM:
|
||||||
|
case SIGQUIT:
|
||||||
|
std::cout << "Stopping services..." << std::endl;
|
||||||
|
stopServices();
|
||||||
|
|
||||||
|
// Do not listen for signals, this will make the ioservice.run return
|
||||||
|
break;
|
||||||
|
case SIGHUP:
|
||||||
|
std::cout << "Restarting services..." << std::endl;
|
||||||
|
|
||||||
|
restartServices();
|
||||||
|
asyncWaitSignals();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef SERVICE_CONTROLER_HPP
|
||||||
|
#define SERVICE_CONTROLER_HPP
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
// Start/Stop/Reload Services
|
||||||
|
class ServiceManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ServiceManager();
|
||||||
|
|
||||||
|
void stopService(Service::pointer service);
|
||||||
|
void startService(Service::pointer service);
|
||||||
|
|
||||||
|
// Return in case of failure/stop by user
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void restartServices(void);
|
||||||
|
void stopServices(void);
|
||||||
|
|
||||||
|
void asyncWaitSignals(void);
|
||||||
|
|
||||||
|
void handleSignal(boost::system::error_code error, int signo);
|
||||||
|
|
||||||
|
boost::asio::io_service _ioService;
|
||||||
|
|
||||||
|
// Listen for interesting signals
|
||||||
|
boost::asio::signal_set _signalSet;
|
||||||
|
|
||||||
|
std::set<Service::pointer> _services;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
#include "WebServerService.hpp"
|
||||||
|
#include "ui/LmsApplication.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* You could read information from the environment to decide whether
|
||||||
|
* the user has permission to start a new application
|
||||||
|
*/
|
||||||
|
return new LmsApplication(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WebServerService::WebServerService( int argc, char* argv[])
|
||||||
|
: _server(argv[0])
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO configure server
|
||||||
|
_server.setServerConfiguration (argc, argv, WTHTTP_CONFIGURATION);
|
||||||
|
|
||||||
|
// bind entry point
|
||||||
|
|
||||||
|
_server.addEntryPoint(Wt::Application, createApplication);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebServerService::start(void)
|
||||||
|
{
|
||||||
|
_server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebServerService::stop(void)
|
||||||
|
{
|
||||||
|
_server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebServerService::restart(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef WEB_SERVER_SERVICE_HPP
|
||||||
|
#define WEB_SERVER_SERVICE_HPP
|
||||||
|
|
||||||
|
#include <Wt/WServer>
|
||||||
|
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
class WebServerService : public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebServerService( int argc, char* argv[]);
|
||||||
|
|
||||||
|
void start(void);
|
||||||
|
void stop(void);
|
||||||
|
void restart(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Wt::WServer _server;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+30
-37
@@ -1,53 +1,46 @@
|
|||||||
#include <boost/thread.hpp>
|
#include <memory>
|
||||||
|
#include <Wt/WServer>
|
||||||
#include "LmsApplication.hpp"
|
|
||||||
|
|
||||||
#include "metadata/AvFormat.hpp"
|
|
||||||
#include "metadata/Extractor.hpp"
|
|
||||||
#include "database/Database.hpp"
|
|
||||||
|
|
||||||
#include "transcode/AvConvTranscoder.hpp"
|
#include "transcode/AvConvTranscoder.hpp"
|
||||||
|
|
||||||
#include "av/Common.hpp"
|
#include "av/Common.hpp"
|
||||||
|
|
||||||
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
|
#include "ServiceManager.hpp"
|
||||||
{
|
#include "DatabaseRefreshService.hpp"
|
||||||
/*
|
#include "WebServerService.hpp"
|
||||||
* You could read information from the environment to decide whether
|
#include "RemoteServerService.hpp"
|
||||||
* the user has permission to start a new application
|
|
||||||
*/
|
|
||||||
return new LmsApplication(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
Av::AvInit();
|
int res = EXIT_FAILURE;
|
||||||
Transcode::AvConvTranscoder::init();
|
|
||||||
|
|
||||||
// std::locale::global(std::locale(""));
|
try
|
||||||
MetaData::AvFormat metadataParser;
|
{
|
||||||
// MetaData::Extractor metadataParser;
|
ServiceManager serviceManager;
|
||||||
|
|
||||||
// Set up the long living database session
|
// lib init
|
||||||
Database database("test.db", metadataParser);
|
Av::AvInit();
|
||||||
|
Transcode::AvConvTranscoder::init();
|
||||||
|
|
||||||
// database.watchDirectory( WatchedDirectory("/storage/common/Media/Son", WatchedDirectory::Audio ));
|
serviceManager.startService( std::make_shared<DatabaseRefreshService>( "test.db" ) );
|
||||||
database.watchDirectory(WatchedDirectory("/storage/common/Media/Son/Metal", WatchedDirectory::Audio));
|
serviceManager.startService( std::make_shared<WebServerService>(argc, argv) );
|
||||||
// database.watchDirectory("/storage/common/Media/Son/Metal/Iced Earth/2004 - The Glorious Burden");
|
serviceManager.startService( std::make_shared<RemoteServerService>( Remote::Server::Server::endpoint_type() ) );
|
||||||
// database.watchDirectory("/storage/common/Media/Son/Metal/System Of a Down");
|
|
||||||
// database.watchDirectory("/storage/common/Media/Son/Metal/Leprous");
|
|
||||||
// database.watchDirectory("/storage/common/Media/Son/Electro");
|
|
||||||
// database.watchDirectory( WatchedDirectory("/storage/common/Media/Son/Electro", WatchedDirectory::Audio) );
|
|
||||||
// database.watchDirectory("/storage/common/Media/Son/Metal/Lacuna Coil");
|
|
||||||
database.watchDirectory( WatchedDirectory("/storage/common/Media/Video", WatchedDirectory::Video) );
|
|
||||||
// database.watchDirectory( WatchedDirectory("/storage/common/Media/Video/Films", WatchedDirectory::Video) );
|
|
||||||
// database.watchDirectory( WatchedDirectory("/storage/common/Media/Video/Series", WatchedDirectory::Video) );
|
|
||||||
|
|
||||||
std::cout << "Starting refresh..." << std::endl;
|
serviceManager.run();
|
||||||
// boost::thread refreshThread(boost::bind(&Database::refresh, &database));
|
|
||||||
|
|
||||||
|
res = EXIT_SUCCESS;
|
||||||
|
|
||||||
return Wt::WRun(argc, argv, &createApplication);
|
}
|
||||||
|
catch( Wt::WServer::Exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Caught WServer::Exception: " << e.what() << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch( std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Caught std::exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ namespace Remote
|
|||||||
|
|
||||||
class Header
|
class Header
|
||||||
{
|
{
|
||||||
static const std::size_t size = 8;
|
public:
|
||||||
|
static const std::size_t size = 8;
|
||||||
}
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
namespace Remote {
|
namespace Remote {
|
||||||
namespace Server {
|
namespace Server {
|
||||||
|
|
||||||
Connection::Connection(boost::asio::io_service& ioService, Connection_manager& manager, RequestHandler& handler)
|
Connection::Connection(boost::asio::ip::tcp::socket socket,
|
||||||
: _socket(ioService),
|
ConnectionManager& manager,
|
||||||
|
RequestHandler& handler)
|
||||||
|
: _socket(std::move(socket)),
|
||||||
_connectionManager(manager),
|
_connectionManager(manager),
|
||||||
request_handler_(handler)
|
_requestHandler(handler)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -58,16 +61,16 @@ Connection::handleRead(const boost::system::error_code& error, std::size_t bytes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::handleWrite(const boost::system::error_code& e)
|
void Connection::handleWrite(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if (!e)
|
if (!error)
|
||||||
{
|
{
|
||||||
// Initiate graceful Connection closure.
|
// Initiate graceful Connection closure.
|
||||||
boost::system::error_code ignored_ec;
|
boost::system::error_code ignored_ec;
|
||||||
_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e != boost::asio::error::operation_aborted)
|
if (error != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
std::cerr << "Connection::handleWrite: " << error.message() << std::endl;
|
std::cerr << "Connection::handleWrite: " << error.message() << std::endl;
|
||||||
_connectionManager.stop(shared_from_this());
|
_connectionManager.stop(shared_from_this());
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#ifndef REMOTE_CONNECTION_HPP
|
#ifndef REMOTE_CONNECTION_HPP
|
||||||
#define REMOTE_CONNECTION_HPP
|
#define REMOTE_CONNECTION_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <array.hpp>
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
|
||||||
|
|
||||||
#include "reply.hpp"
|
|
||||||
#include "request.hpp"
|
|
||||||
#include "RequestHandler.hpp"
|
#include "RequestHandler.hpp"
|
||||||
#include "request_parser.hpp"
|
|
||||||
|
|
||||||
namespace http {
|
#include "messages/Header.hpp"
|
||||||
namespace server {
|
|
||||||
|
namespace Remote {
|
||||||
|
|
||||||
|
namespace Server {
|
||||||
|
|
||||||
class ConnectionManager;
|
class ConnectionManager;
|
||||||
|
|
||||||
/// Represents a single connection from a client.
|
/// Represents a single connection from a client.
|
||||||
class Connection : public boost::enable_shared_from_this<Connection>, boost::noncopyable
|
class Connection : public std::enable_shared_from_this<Connection>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::shared_ptr<connection> pointer;
|
Connection(const Connection&) = delete;
|
||||||
|
Connection& operator=(const Connection&) = delete;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Connection> pointer;
|
||||||
|
|
||||||
/// Construct a connection with the given io_service.
|
/// Construct a connection with the given io_service.
|
||||||
Connection(boost::asio::io_service& io_service,
|
explicit Connection(boost::asio::ip::tcp::socket socket,
|
||||||
ConnectionManager& manager, RequestHandler& handler);
|
ConnectionManager& manager, RequestHandler& handler);
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& socket();
|
boost::asio::ip::tcp::socket& socket();
|
||||||
@@ -50,10 +50,10 @@ class Connection : public boost::enable_shared_from_this<Connection>, boost::non
|
|||||||
boost::asio::ip::tcp::socket _socket;
|
boost::asio::ip::tcp::socket _socket;
|
||||||
|
|
||||||
/// The manager for this connection.
|
/// The manager for this connection.
|
||||||
ConnectionManager& _ConnectionManager;
|
ConnectionManager& _connectionManager;
|
||||||
|
|
||||||
/// The handler used to process the incoming requests.
|
/// The handler used to process the incoming requests.
|
||||||
RequestHandler& _RequestHandler;
|
RequestHandler& _requestHandler;
|
||||||
|
|
||||||
// TODO use streambuffers
|
// TODO use streambuffers
|
||||||
|
|
||||||
@@ -70,9 +70,10 @@ class Connection : public boost::enable_shared_from_this<Connection>, boost::non
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace server
|
} // namespace Server
|
||||||
} // namespace http
|
|
||||||
|
|
||||||
#endif // HTTP_CONNECTION_HPP
|
} // namespace Remote
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
#include "ConnectionManager.hpp"
|
#include "ConnectionManager.hpp"
|
||||||
|
|
||||||
@@ -8,24 +8,29 @@ namespace Remote {
|
|||||||
|
|
||||||
namespace Server {
|
namespace Server {
|
||||||
|
|
||||||
|
ConnectionManager::ConnectionManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ConnectionManager::start(connection::pointer c)
|
ConnectionManager::start(Connection::pointer c)
|
||||||
{
|
{
|
||||||
_connections.insert(c);
|
_connections.insert(c);
|
||||||
c->start();
|
c->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConnectionManager::stop(connection::pointer c)
|
ConnectionManager::stop(Connection::pointer c)
|
||||||
{
|
{
|
||||||
_connections.erase(c);
|
_connections.erase(c);
|
||||||
c->stop();
|
c->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConnectionManager::stop_all()
|
ConnectionManager::stopAll()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(connection::pointer c, _connections)
|
BOOST_FOREACH(Connection::pointer c, _connections)
|
||||||
{
|
{
|
||||||
c->stop();
|
c->stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include "Connection.hpp"
|
||||||
|
|
||||||
#include "connection.hpp"
|
|
||||||
|
|
||||||
namespace Remote {
|
namespace Remote {
|
||||||
|
|
||||||
@@ -14,21 +12,26 @@ namespace Server {
|
|||||||
/// Manages open connections so that they may be cleanly stopped when the server
|
/// Manages open connections so that they may be cleanly stopped when the server
|
||||||
/// needs to shut down.
|
/// needs to shut down.
|
||||||
|
|
||||||
class ConnectionManager : boost::noncopyable
|
class ConnectionManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ConnectionManager(const ConnectionManager&) = delete;
|
||||||
|
ConnectionManager& operator=(const ConnectionManager&) = delete;
|
||||||
|
|
||||||
|
ConnectionManager();
|
||||||
|
|
||||||
/// Add the specified connection to the manager and start it.
|
/// Add the specified connection to the manager and start it.
|
||||||
void start(connection::pointer c);
|
void start(Connection::pointer c);
|
||||||
|
|
||||||
/// Stop the specified connection.
|
/// Stop the specified connection.
|
||||||
void stop(connection::pointer c);
|
void stop(Connection::pointer c);
|
||||||
|
|
||||||
/// Stop all connections.
|
/// Stop all connections.
|
||||||
void stop_all();
|
void stopAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The managed connections.
|
/// The managed connections.
|
||||||
std::set<connection::pointer> _connections;
|
std::set<Connection::pointer> _connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Server
|
} // namespace Server
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
#ifndef REMOTE_REQUEST_HANDLER
|
#ifndef REMOTE_REQUEST_HANDLER
|
||||||
#define REMOTE_REQUEST_HANDLER
|
#define REMOTE_REQUEST_HANDLER
|
||||||
|
|
||||||
|
// #include "remote/messages/
|
||||||
|
|
||||||
class RequestHandler
|
class RequestHandler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+10
-11
@@ -9,18 +9,17 @@ namespace Remote {
|
|||||||
|
|
||||||
namespace Server {
|
namespace Server {
|
||||||
|
|
||||||
server::server(boost::asio::io_service& ioService, const endpoint_type& endpoint)
|
Server::Server(const endpoint_type& endpoint)
|
||||||
: _ioService(ioService),
|
:
|
||||||
_acceptor(_ioService),
|
_acceptor(_ioService),
|
||||||
_connectionManager(),
|
_connectionManager(),
|
||||||
_socket(io_service_),
|
_socket(_ioService)
|
||||||
_requestHandler(doc_root)
|
|
||||||
{
|
{
|
||||||
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
|
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
|
||||||
boost::asio::ip::tcp::resolver resolver(_ioService);
|
boost::asio::ip::tcp::resolver resolver(_ioService);
|
||||||
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(endpoint);
|
boost::asio::ip::tcp::endpoint resolvedEndpoint = *resolver.resolve(endpoint);
|
||||||
|
|
||||||
_acceptor.open(endpoint.protocol());
|
_acceptor.open(resolvedEndpoint.protocol());
|
||||||
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||||
_acceptor.bind(endpoint);
|
_acceptor.bind(endpoint);
|
||||||
_acceptor.listen();
|
_acceptor.listen();
|
||||||
@@ -33,11 +32,11 @@ Server::run()
|
|||||||
// While the server is running, there is always at least one
|
// While the server is running, there is always at least one
|
||||||
// asynchronous operation outstanding: the asynchronous accept call waiting
|
// asynchronous operation outstanding: the asynchronous accept call waiting
|
||||||
// for new incoming connections.
|
// for new incoming connections.
|
||||||
async_accept();
|
asyncAccept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Server::async_accept()
|
Server::asyncAccept()
|
||||||
{
|
{
|
||||||
_acceptor.async_accept(_socket, boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
_acceptor.async_accept(_socket, boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
@@ -54,9 +53,9 @@ Server::handleAccept(boost::system::error_code ec)
|
|||||||
|
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
_connectionManager.start(std::make_shared<connection>(std::move(_socket), _connectionManager, _requestHandler));
|
_connectionManager.start(std::make_shared<Connection>(std::move(_socket), _connectionManager, _requestHandler));
|
||||||
|
|
||||||
async_accept();
|
asyncAccept();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cerr << "handleAccept: " << ec.message() << std::endl;
|
std::cerr << "handleAccept: " << ec.message() << std::endl;
|
||||||
@@ -69,7 +68,7 @@ Server::stop()
|
|||||||
// The server is stopped by cancelling all outstanding asynchronous
|
// The server is stopped by cancelling all outstanding asynchronous
|
||||||
// operations.
|
// operations.
|
||||||
_acceptor.close();
|
_acceptor.close();
|
||||||
_connectionManager.stop_all();
|
_connectionManager.stopAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Server
|
} // namespace Server
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "Connection.hpp"
|
#include "Connection.hpp"
|
||||||
#include "ConnectionManager.hpp"
|
#include "ConnectionManager.hpp"
|
||||||
|
|
||||||
@@ -18,11 +16,13 @@ class Server
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::string endpoint_type;
|
Server(const Server&) = delete;
|
||||||
|
Server& operator=(const Server&) = delete;
|
||||||
|
|
||||||
|
typedef boost::asio::ip::tcp::endpoint endpoint_type;
|
||||||
|
|
||||||
// Serve up data from the given database
|
// Serve up data from the given database
|
||||||
Server(boost::asio::io_service& ioService,
|
Server(const endpoint_type& endpoint);
|
||||||
const endpoint_type& endpoint);
|
|
||||||
|
|
||||||
// Run the server's io_service loop.
|
// Run the server's io_service loop.
|
||||||
void run();
|
void run();
|
||||||
@@ -34,13 +34,13 @@ class Server
|
|||||||
void asyncAccept();
|
void asyncAccept();
|
||||||
void handleAccept(boost::system::error_code ec);
|
void handleAccept(boost::system::error_code ec);
|
||||||
|
|
||||||
boost::asio::io_service& _ioService;
|
boost::asio::io_service _ioService;
|
||||||
|
|
||||||
/// Acceptor used to listen for incoming connections.
|
/// Acceptor used to listen for incoming connections.
|
||||||
boost::asio::ip::tcp::acceptor _acceptor;
|
boost::asio::ip::tcp::acceptor _acceptor;
|
||||||
|
|
||||||
/// The connection manager which owns all live connections.
|
/// The connection manager which owns all live connections.
|
||||||
connection_manager _connectionManager;
|
ConnectionManager _connectionManager;
|
||||||
|
|
||||||
/// The next socket to be accepted.
|
/// The next socket to be accepted.
|
||||||
boost::asio::ip::tcp::socket _socket;
|
boost::asio::ip::tcp::socket _socket;
|
||||||
|
|||||||
Reference in New Issue
Block a user