WIP, Remote Client/Server...
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#include "AudioCollectionRequestHandler.hpp"
|
||||
|
||||
#include "database/AudioTypes.hpp"
|
||||
|
||||
namespace Remote {
|
||||
namespace Server {
|
||||
|
||||
AudioCollectionRequestHandler::AudioCollectionRequestHandler(DatabaseHandler& db)
|
||||
: _db(db)
|
||||
{}
|
||||
|
||||
|
||||
bool
|
||||
AudioCollectionRequestHandler::process(const AudioCollectionRequest& request, std::vector<ServerMessage> responses)
|
||||
{
|
||||
|
||||
switch (request.type())
|
||||
{
|
||||
case AudioCollectionRequest_Type_TypeGetArtistList:
|
||||
if (request.has_get_artists())
|
||||
return processGetArtists(request.get_artists(), responses);
|
||||
else
|
||||
std::cerr << "Bad AudioCollectionRequest_Type_TypeGetArtistList: message!" << std::endl;
|
||||
break;
|
||||
|
||||
case AudioCollectionRequest_Type_TypeGetReleaseList:
|
||||
break;
|
||||
|
||||
case AudioCollectionRequest_Type_TypeGetTrackList:
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "Unhandled AudioCollectionRequest_Type = " << request.type() << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioCollectionRequestHandler::processGetArtists(const AudioCollectionRequest::GetArtistList& request, std::vector<ServerMessage> responses)
|
||||
{
|
||||
|
||||
// sanity checks
|
||||
if (request.has_filter_name())
|
||||
std::cout << "Filter name = " << request.filter_name() << std::endl;
|
||||
|
||||
for (int id = 0; id < request.filter_genre_size(); ++id)
|
||||
{
|
||||
std::cout << "Filter genre " << id << " = '" << request.filter_genre(id) << "'" << std::endl;
|
||||
}
|
||||
|
||||
if (request.has_preferred_batch_size())
|
||||
std::cout << "Requested batch size = " << request.preferred_batch_size() << std::endl;
|
||||
|
||||
|
||||
// Now fetch requested data...
|
||||
|
||||
std::cout << "Getting artists..." << std::endl;
|
||||
|
||||
Wt::Dbo::Transaction transaction( _db.getSession() );
|
||||
|
||||
Wt::Dbo::collection<Artist::pointer> artists = Artist::getAll( _db.getSession() );
|
||||
|
||||
std::cout << "size = " << artists.size() << std::endl;
|
||||
|
||||
typedef Wt::Dbo::collection< Artist::pointer > Artists;
|
||||
|
||||
for (Artists::iterator it = artists.begin(); it != artists.end(); ++it)
|
||||
{
|
||||
std::cout << "Spotted artist = " << (*it)->getName() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Getting artists DONE" << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Remote
|
||||
} // namespace Server
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef REMOTE_AUDIO_COLLECTION_REQUEST_HANDLER
|
||||
#define REMOTE_AUDIO_COLLECTION_REQUEST_HANDLER
|
||||
|
||||
#include "messages/messages.pb.h"
|
||||
|
||||
#include "database/DatabaseHandler.hpp"
|
||||
|
||||
namespace Remote {
|
||||
namespace Server {
|
||||
|
||||
class AudioCollectionRequestHandler
|
||||
{
|
||||
public:
|
||||
AudioCollectionRequestHandler(DatabaseHandler& db);
|
||||
|
||||
bool process(const AudioCollectionRequest& request, std::vector<ServerMessage> responses);
|
||||
|
||||
private:
|
||||
|
||||
bool processGetArtists(const AudioCollectionRequest::GetArtistList& request, std::vector<ServerMessage> responses);
|
||||
|
||||
DatabaseHandler& _db;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Remote
|
||||
} // namespace Server
|
||||
|
||||
#endif
|
||||
|
||||
+121
-17
@@ -1,7 +1,11 @@
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "messages/messages.pb.h"
|
||||
|
||||
#include "RequestHandler.hpp"
|
||||
|
||||
@@ -18,6 +22,7 @@ Connection::Connection(boost::asio::ip::tcp::socket socket,
|
||||
_connectionManager(manager),
|
||||
_requestHandler(handler)
|
||||
{
|
||||
std::cout << "Server::Connection::Connection, Creating connection" << std::endl;
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::socket&
|
||||
@@ -29,29 +34,59 @@ Connection::socket()
|
||||
void
|
||||
Connection::start()
|
||||
{
|
||||
_socket.async_read_some(boost::asio::buffer(_headerBuffer),
|
||||
boost::bind(&Connection::handleRead, shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(Remote::Header::size);
|
||||
|
||||
boost::asio::async_read(_socket,
|
||||
bufs,
|
||||
boost::asio::transfer_exactly(Remote::Header::size),
|
||||
boost::bind(&Connection::handleReadHeader, shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void
|
||||
Connection::stop()
|
||||
{
|
||||
_socket.close();
|
||||
std::cout << "Server::Connection::stop, Stopping connection" << std::endl;
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
void
|
||||
Connection::handleRead(const boost::system::error_code& error, std::size_t bytes_transferred)
|
||||
Connection::handleReadHeader(const boost::system::error_code& error, std::size_t bytes_transferred)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
/* boost::asio::async_write(_socket, reply_.to_buffers(),
|
||||
boost::bind(&Connection::handleWrite, shared_from_this(),
|
||||
boost::asio::placeholders::error));*/
|
||||
if (bytes_transferred != Remote::Header::size)
|
||||
{
|
||||
std::cerr << "bytes_transferred (" << bytes_transferred << ") != Remote::Header::size!" << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
||||
_inputStreamBuf.commit(bytes_transferred);
|
||||
|
||||
std::istream is(&_inputStreamBuf);
|
||||
|
||||
Remote::Header header;
|
||||
if (!header.from_istream(is))
|
||||
{
|
||||
std::cerr << "Cannot read header from buffer!" << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Header received. Size = " << header.getSize() << std::endl;
|
||||
|
||||
// Now read the real message
|
||||
boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(header.getSize());
|
||||
|
||||
boost::asio::async_read(_socket,
|
||||
bufs,
|
||||
boost::asio::transfer_exactly(header.getSize()),
|
||||
boost::bind(&Connection::handleReadMsg, shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
|
||||
start();
|
||||
}
|
||||
else if (error != boost::asio::error::operation_aborted)
|
||||
{
|
||||
@@ -60,21 +95,90 @@ Connection::handleRead(const boost::system::error_code& error, std::size_t bytes
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::handleWrite(const boost::system::error_code& error)
|
||||
void
|
||||
Connection::handleReadMsg(const boost::system::error_code& error, std::size_t bytes_transferred)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
// Initiate graceful Connection closure.
|
||||
boost::system::error_code ignored_ec;
|
||||
_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
||||
}
|
||||
_inputStreamBuf.commit(bytes_transferred);
|
||||
|
||||
if (error != boost::asio::error::operation_aborted)
|
||||
std::istream is(&_inputStreamBuf);
|
||||
std::ostream os(&_outputStreamBuf);
|
||||
|
||||
std::vector<Remote::ServerMessage> responses;
|
||||
Remote::ClientMessage request;
|
||||
|
||||
if (!request.ParseFromIstream(&is))
|
||||
{
|
||||
std::cerr << "Cannot parse request!" << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_requestHandler.process(request, responses))
|
||||
{
|
||||
std::cerr << "Cannot process request!" << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const Remote::ServerMessage& response, responses)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
if (!response.SerializeToOstream(&os))
|
||||
{
|
||||
std::cerr << "Cannot serialize to ostream!" << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<unsigned char, Remote::Header::size> headerBuffer;
|
||||
{
|
||||
Remote::Header header;
|
||||
header.setSize(_outputStreamBuf.size());
|
||||
header.to_buffer(headerBuffer);
|
||||
}
|
||||
|
||||
std::size_t n = boost::asio::write(_socket,
|
||||
boost::asio::buffer(headerBuffer),
|
||||
boost::asio::transfer_exactly(Remote::Header::size),
|
||||
ec);
|
||||
if (ec)
|
||||
{
|
||||
std::cerr << "cannot write header: " << error.message() << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
}
|
||||
|
||||
// Now send serialized payload
|
||||
n = boost::asio::write(_socket,
|
||||
_outputStreamBuf.data(),
|
||||
boost::asio::transfer_exactly(_outputStreamBuf.size()),
|
||||
ec);
|
||||
|
||||
_outputStreamBuf.consume(n);
|
||||
assert(n == _outputStreamBuf.size());
|
||||
|
||||
if (ec)
|
||||
{
|
||||
std::cerr << "cannot write msg: " << error.message() << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
}
|
||||
}
|
||||
start();
|
||||
|
||||
// Initiate graceful Connection closure.
|
||||
// boost::system::error_code ignored_ec;
|
||||
// _socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
||||
|
||||
}
|
||||
else if (error != boost::asio::error::operation_aborted)
|
||||
{
|
||||
std::cerr << "Connection::handleWrite: " << error.message() << std::endl;
|
||||
std::cerr << "Connection::handleRead: " << error.message() << std::endl;
|
||||
_connectionManager.stop(shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Server
|
||||
} // namespace Remote
|
||||
|
||||
@@ -39,11 +39,11 @@ class Connection : public std::enable_shared_from_this<Connection>
|
||||
|
||||
private:
|
||||
/// Handle completion of a read operation.
|
||||
void handleRead(const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred);
|
||||
void handleReadHeader(const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handleWrite(const boost::system::error_code& e);
|
||||
void handleReadMsg(const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
/// Socket for the connection.
|
||||
boost::asio::ip::tcp::socket _socket;
|
||||
@@ -54,18 +54,8 @@ class Connection : public std::enable_shared_from_this<Connection>
|
||||
/// The handler used to process the incoming requests.
|
||||
RequestHandler& _requestHandler;
|
||||
|
||||
// TODO use streambuffers
|
||||
|
||||
/// The incoming request.
|
||||
// request request_;
|
||||
|
||||
/// The parser for the incoming request.
|
||||
// request_parser request_parser_;
|
||||
|
||||
/// The reply to be sent back to the client.
|
||||
// reply reply_;
|
||||
|
||||
std::array<unsigned char, Header::size> _headerBuffer;
|
||||
boost::asio::streambuf _inputStreamBuf;
|
||||
boost::asio::streambuf _outputStreamBuf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,10 +5,39 @@ namespace Remote {
|
||||
namespace Server {
|
||||
|
||||
RequestHandler::RequestHandler(boost::filesystem::path dbPath)
|
||||
: _db( dbPath )
|
||||
: _db( dbPath ),
|
||||
_audioCollectionRequestHandler(_db)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
RequestHandler::process(const ClientMessage& request, std::vector<ServerMessage> responses)
|
||||
{
|
||||
std::cout << "TODO: process request!" << std::endl;
|
||||
|
||||
switch(request.type())
|
||||
{
|
||||
|
||||
case ClientMessage_Type_AuthRequest:
|
||||
|
||||
break;
|
||||
case ClientMessage_Type_AudioCollectionRequest:
|
||||
if (request.has_audio_collection_request())
|
||||
return _audioCollectionRequestHandler.process(request.audio_collection_request(), responses);
|
||||
else
|
||||
std::cerr << "Malformed AudioCollectionRequest message!" << std::endl;
|
||||
break;
|
||||
|
||||
case ClientMessage_Type_MediaRequest:
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "Unhandled message type = " << request.type() << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Server
|
||||
} // namespace Remote
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "messages/messages.pb.h"
|
||||
|
||||
#include "database/DatabaseHandler.hpp"
|
||||
|
||||
// #include "remote/messages/
|
||||
#include "AudioCollectionRequestHandler.hpp"
|
||||
|
||||
namespace Remote {
|
||||
namespace Server {
|
||||
@@ -16,11 +18,16 @@ class RequestHandler
|
||||
|
||||
RequestHandler(boost::filesystem::path dbPath);
|
||||
|
||||
bool process(const ClientMessage& request, std::vector<ServerMessage> responses);
|
||||
|
||||
bool processAudioCollectionRequest(const AudioCollectionRequest& request, std::vector<ServerMessage> responses);
|
||||
|
||||
private:
|
||||
|
||||
DatabaseHandler _db;
|
||||
|
||||
AudioCollectionRequestHandler _audioCollectionRequestHandler;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Server
|
||||
|
||||
Reference in New Issue
Block a user