Added http::Server to musik::core::Server. Fixed some issues in the Remote Library.

This commit is contained in:
Daniel Önnerby 2008-08-26 15:10:31 +00:00
parent 7b72e40a4c
commit 22a2f0caaf
16 changed files with 85 additions and 60 deletions

View File

@ -628,3 +628,7 @@ void Library::Base::CreateDatabase(db::Connection &db){
db.Execute("ANALYZE");
}
utfstring Library::Base::BasePath(){
return UTF("");
}

View File

@ -130,6 +130,8 @@ class Base : boost::noncopyable{
virtual musik::core::Indexer *Indexer();
virtual utfstring BasePath();
bool Exited();
const utfstring& Identifier();

View File

@ -188,6 +188,9 @@ void Library::Remote::ReadThread(){
boost::mutex::scoped_lock lock(this->libraryMutex);
currentQuery->status |= Query::Base::Status::Canceled | Query::Base::Status::Ended;
}
this->waitCondition.notify_all();
}
}
}
@ -293,3 +296,13 @@ void Library::Remote::Exit(){
}
this->waitCondition.notify_all();
}
utfstring Library::Remote::BasePath(){
utfstring path(UTF("http://"));
boost::asio::ip::tcp::endpoint endPoint = this->socket.remote_endpoint();
boost::asio::ip::address address = endPoint.address();
path += musik::core::ConvertUTF16(address.to_string());
path += UTF(":") + musik::core::ConvertUTF16(this->port) + UTF("/");
return path;
}

View File

@ -67,6 +67,7 @@ class Remote : public Library::Base{
bool Startup();
utfstring GetInfo();
virtual utfstring BasePath();
protected:
void CancelCurrentQuery( );

View File

@ -396,6 +396,9 @@ bool TrackMetadata::SendResults(musik::core::xml::WriterNode &queryNode,Library:
if( !resultCopy.empty() ){
try{
for(TrackVector::iterator track=resultCopy.begin();track!=resultCopy.end();++track){
// Erase the path.. is translated in the RecieveResults
(*track)->ClearValue("path");
musik::core::xml::WriterNode trackNode(queryNode,"t");
trackNode.Attributes()["id"] = boost::lexical_cast<std::string>( (*track)->id );
@ -426,6 +429,9 @@ bool TrackMetadata::SendResults(musik::core::xml::WriterNode &queryNode,Library:
bool TrackMetadata::RecieveResults(musik::core::xml::ParserNode &queryNode,Library::Base *library){
bool requestPath( this->requestedFields.find("path")!=this->requestedFields.end() );
utfstring pathPrefix(library->BasePath()+UTF("track/?track_id="));
while(musik::core::xml::ParserNode trackNode=queryNode.ChildNode("t") ){
try{
DBINT trackId( boost::lexical_cast<DBINT>(trackNode.Attributes()["id"]) );
@ -453,6 +459,13 @@ bool TrackMetadata::RecieveResults(musik::core::xml::ParserNode &queryNode,Libra
currentTrack->SetValue( metadataNode.Attributes()["k"].c_str(),ConvertUTF16(metadataNode.Content()).c_str());
}
// Special case for the "path" when connecting to a webserver
if(requestPath){
utfstring path(pathPrefix);
path += boost::lexical_cast<utfstring>(currentTrack->id);
currentTrack->SetValue("path",path.c_str());
}
{
boost::mutex::scoped_lock oLock(library->oResultMutex);
this->aResultTracks.push_back(currentTrack);
@ -460,7 +473,7 @@ bool TrackMetadata::RecieveResults(musik::core::xml::ParserNode &queryNode,Libra
}
}
catch(...){
return false;
// return false;
}
}

View File

@ -47,9 +47,10 @@
using namespace musik::core;
Server::Server(unsigned int port)
Server::Server(unsigned int port,unsigned int httpPort)
:exitThread(false)
,acceptor(ioService,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
,httpServer(httpPort)
{
this->acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
}
@ -77,6 +78,7 @@ bool Server::Exited(){
bool Server::Startup(){
// Start the server thread
this->threads.create_thread(boost::bind(&Server::ThreadLoop,this));
return true;
}
@ -88,6 +90,8 @@ void Server::ThreadLoop(){
utfstring directory( musik::core::GetDataDirectory()+UTF("server/") );
utfstring database(directory+UTF("musik.db"));
this->httpServer.Startup(database);
{
// Create database
db::Connection db;

View File

@ -39,6 +39,7 @@
#include <core/server/Connection.h>
#include <core/Indexer.h>
#include <core/http/Server.h>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
@ -53,12 +54,13 @@ namespace musik{ namespace core{
class Server{
public:
// Methods
Server(unsigned int port);
Server(unsigned int port,unsigned int httpPort);
~Server(void);
bool Startup();
public:
Indexer indexer;
http::Server httpServer;
private:
// Methods

View File

@ -125,6 +125,12 @@ void Track::SetValue(const char* metakey,const utfchar* value){
}
}
void Track::ClearValue(const char* metakey){
if(this->meta){
this->meta->ClearValue(metakey);
}
}
void Track::ClearMeta(){
if(this->meta){

View File

@ -113,6 +113,7 @@ class Track : public ITrack {
const utfchar* GetValue(const char* metakey) const;
void SetValue(const char* metakey,const utfchar* value);
void SetThumbnail(const char *data,unsigned int size);
void ClearValue(const char* metakey);
void InitMeta(Library::Base *library);

View File

@ -135,6 +135,11 @@ void TrackMeta::SetValue(const TrackMeta::Key &key,const TrackMeta::Value &value
}
}
void TrackMeta::ClearValue(const TrackMeta::Key &key){
this->tags.erase(key);
}
const TrackMeta::Value& TrackMeta::_GetValue(const TrackMeta::Key &key) const{
TrackMeta::TagMap::const_iterator oKeyValue = this->tags.find(key);

View File

@ -77,6 +77,7 @@ class TrackMeta : boost::noncopyable{
const utfstring& GetValue(const Key &key) const;
TrackMeta::TagMapIteratorPair GetValues(const char* metakey) const;
void SetValue(const Key &key,const Value &value);
void ClearValue(const Key &key);
const utfchar* GetValue(const char* metakey) const;
Library::Base *library;

View File

@ -81,6 +81,14 @@ void RequestParser::SplitPath(){
if(!this->path.empty()){
boost::algorithm::split(this->splitPath,this->path,boost::algorithm::is_any_of("/"));
}
// Remove empty paths
for(StringVector::iterator path=this->splitPath.begin();path!=this->splitPath.end();){
if(path->empty()){
path = this->splitPath.erase(path);
}else{
++path;
}
}
}

View File

@ -56,6 +56,7 @@ Responder::Responder(Server &server,boost::asio::io_service &ioService,utfstring
:socket(ioService)
,thread(NULL)
,server(server)
,exited(false)
{
this->db.Open(dbFilename,0,256);
}
@ -133,47 +134,6 @@ void Responder::ThreadLoop(){
boost::asio::write(this->socket,boost::asio::buffer(send.c_str(),send.size()));
}
/*
utfstring fileName;
int fileSize(0);
if(this->GetFileName(fileName,fileSize,requester)){
char buffer[1024];
int buffersize(0);
FILE *file = _wfopen(fileName.c_str(),UTF("rb"));
// Send header
std::string header( boost::str( boost::format("HTTP/1.1 200 OK\r\nContent-Type: audio/mpeg\r\nContent-Length: %1%\r\n\r\n")%fileSize ));
//send(this->iSocket,sHeader.c_str(),sHeader.size(),0);
try{
boost::asio::write(this->socket,boost::asio::buffer(header.c_str(),header.size()));
}
catch(...){
}
while(!feof(file) && file && !this->Exited()){
buffersize=0;
while(buffersize<1024 && !feof(file)){
buffersize += fread(buffer,sizeof(char),1024-buffersize,file);
}
// send buffer
// send(this->iSocket,buffer,iBuffersize,0);
boost::asio::write(this->socket,boost::asio::buffer(buffer,buffersize));
}
fclose(file);
}else{
std::string send("HTTP/1.1 404 OK\r\nContent-Type: text/html\r\n\r\n<html><body bgcolor=\"#ff0000\">testar: ");
send += musik::core::ConvertUTF8(fileName);
send += "<br><pre>";
send += request;
send += "</pre></body></html>";
boost::asio::write(this->socket,boost::asio::buffer(send.c_str(),send.size()));
}*/
}
}

View File

@ -48,13 +48,12 @@
using namespace musik::core::http;
Server::Server(int port,utfstring dbFilename)
Server::Server(int port)
:acceptor(ioService,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
,thread(NULL)
,timer(ioService)
,exited(false)
,port(port)
,dbFilename(dbFilename)
{
// Check for plugins
typedef IRequestPlugin PluginType;
@ -85,7 +84,9 @@ Server::~Server(){
}
}
bool Server::Startup(){
bool Server::Startup(utfstring dbFilename){
this->dbFilename = dbFilename;
// start the thread
this->thread = new boost::thread(boost::bind(&Server::ThreadLoop,this));
@ -165,10 +166,14 @@ ResponderPtr Server::GetResponder(){
void Server::FreeResponder(Responder *responder){
boost::mutex::scoped_lock lock(this->mutex);
ResponderSet::iterator foundResponder = this->busyResponders.find(ResponderPtr(responder));
if(foundResponder!=this->busyResponders.end()){
this->freeResponders.push(*foundResponder);
this->busyResponders.erase(foundResponder);
ResponderSet::iterator tempResponder=this->busyResponders.begin();
while(tempResponder!=this->busyResponders.end()){
if(tempResponder->get()==responder){
this->freeResponders.push(*tempResponder);
tempResponder = this->busyResponders.erase(tempResponder);
}else{
++tempResponder;
}
}
}

View File

@ -56,10 +56,10 @@ namespace musik{ namespace core{ namespace http {
//////////////////////////////////////////////////////////////////////////////
class Server : private boost::noncopyable{
public:
Server(int port,utfstring dbFilename);
Server(int port);
~Server();
bool Startup();
bool Startup(utfstring dbFilename);
int port;
@ -70,12 +70,6 @@ class Server : private boost::noncopyable{
void Exit();
bool Exited();
typedef std::set<ResponderPtr> ResponderSet;
typedef std::queue<ResponderPtr> ResponderQueue;
ResponderSet busyResponders;
ResponderQueue freeResponders;
ResponderPtr waitingResponder;
ResponderPtr GetResponder();
void initAccept();
@ -99,6 +93,12 @@ class Server : private boost::noncopyable{
typedef std::map<std::string,boost::shared_ptr<IRequestPlugin>> PluginPathMap;
PluginPathMap requestPlugins;
typedef std::set<ResponderPtr> ResponderSet;
typedef std::queue<ResponderPtr> ResponderQueue;
ResponderSet busyResponders;
ResponderQueue freeResponders;
ResponderPtr waitingResponder;
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -43,7 +43,7 @@ using namespace musik::core;
int main(int argc, utfchar* argv[]){
Server server(10543);
Server server(10543,10544);
server.Startup();