diff options
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/HTTPClientReceiver.cpp | 232 | ||||
-rw-r--r-- | src/http/HTTPClientReceiver.hpp | 85 | ||||
-rw-r--r-- | src/http/HTTPClientSender.cpp | 137 | ||||
-rw-r--r-- | src/http/HTTPClientSender.hpp | 105 | ||||
-rw-r--r-- | src/http/HTTPEngineReceiver.cpp | 227 | ||||
-rw-r--r-- | src/http/HTTPEngineReceiver.hpp | 75 | ||||
-rw-r--r-- | src/http/HTTPEngineSender.cpp | 197 | ||||
-rw-r--r-- | src/http/HTTPEngineSender.hpp | 123 | ||||
-rw-r--r-- | src/http/HTTPSender.cpp | 155 | ||||
-rw-r--r-- | src/http/HTTPSender.hpp | 60 | ||||
-rw-r--r-- | src/http/ingen_http_client.cpp | 53 | ||||
-rw-r--r-- | src/http/ingen_http_server.cpp | 53 | ||||
-rw-r--r-- | src/http/wscript | 28 |
13 files changed, 0 insertions, 1530 deletions
diff --git a/src/http/HTTPClientReceiver.cpp b/src/http/HTTPClientReceiver.cpp deleted file mode 100644 index 64554ce4..00000000 --- a/src/http/HTTPClientReceiver.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <assert.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> - -#include <libsoup/soup.h> - -#include "ingen/shared/World.hpp" -#include "raul/log.hpp" - -#include "HTTPClientReceiver.hpp" - -#define LOG(s) s << "[HTTPClientReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Serialisation; - -namespace Client { - -HTTPClientReceiver::HTTPClientReceiver( - Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> target) - : _target(target) - , _world(world) - , _url(url) -{ - _client_session = soup_session_sync_new(); - start(false); - assert(_client_session); -} - -HTTPClientReceiver::~HTTPClientReceiver() -{ - stop(); -} - -HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std::string& uri) - : _uri(uri) - , _receiver(receiver) -{ - const string port_str = uri.substr(uri.find_last_of(":")+1); - int port = atoi(port_str.c_str()); - - LOG(info) << "Client HTTP listen: " << uri << " (port " << port << ")" << endl; - - struct sockaddr_in servaddr; - - // Create listen address - memset(&servaddr, 0, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(port); - - // Create listen socket - if ((_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOG(error) << "Error creating listening socket: %s" << strerror(errno) << endl; - _sock = -1; - return; - } - - // Set remote address (FIXME: always localhost) - if (inet_aton("127.0.0.1", &servaddr.sin_addr) <= 0) { - LOG(error) << "Invalid remote IP address" << endl; - _sock = -1; - return; - } - - // Connect to server - if (connect(_sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { - LOG(error) << "Error calling connect: " << strerror(errno) << endl; - _sock = -1; - return; - } -} - -HTTPClientReceiver::Listener::~Listener() -{ - close(_sock); -} - -void -HTTPClientReceiver::send(SoupMessage* msg) -{ - assert(SOUP_IS_SESSION(_client_session)); - assert(SOUP_IS_MESSAGE(msg)); - soup_session_queue_message(_client_session, msg, message_callback, this); -} - -void -HTTPClientReceiver::close_session() -{ - if (_client_session) { - SoupSession* s = _client_session; - _client_session = NULL; - soup_session_abort(s); - } -} - -void -HTTPClientReceiver::update(const std::string& str) -{ - //LOG(info) << _world->parser()->parse_update(_world, _target.get(), str, _url); -} - -void -HTTPClientReceiver::Listener::_run() -{ - char in = '\0'; - char last = '\0'; - char llast = '\0'; - string recv; - - while (true) { - while (read(_sock, &in, 1) > 0 ) { - recv += in; - if (in == '\n' && last == '\n' && llast == '\n') { - if (!recv.empty()) { - _receiver->update(recv); - recv.clear(); - last = '\0'; - llast = '\0'; - } - break; - } - llast = last; - last = in; - } - } - - LOG(info) << "HTTP listener finished" << endl; -} - -void -HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, void* ptr) -{ - if (ptr == NULL) - return; - - HTTPClientReceiver* me = (HTTPClientReceiver*)ptr; - const string path = soup_message_get_uri(msg)->path; - - if (msg->response_body->data == NULL) { - LOG(error) << "Empty client message" << endl; - return; - } - - if (path == "/") { - me->_target->response(0, SUCCESS); - - } else if (path == "/plugins") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - me->_target->response(0, SUCCESS); - me->_world->parser()->parse_string(me->_world, me->_target.get(), - Glib::ustring(msg->response_body->data), me->_url); - } - - } else if (path.substr(0, 6) == "/patch") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - me->_target->response(0, SUCCESS); - me->_world->parser()->parse_string( - me->_world, - me->_target.get(), - Glib::ustring(msg->response_body->data), - ""); - } - - } else if (path == "/stream") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - string uri = string(soup_uri_to_string(soup_message_get_uri(msg), false)); - uri = uri.substr(0, uri.find_last_of(":")); - uri += string(":") + msg->response_body->data; - LOG(info) << "Stream URI: " << uri << endl; - me->_listener = boost::shared_ptr<Listener>(new Listener(me, uri)); - me->_listener->start(); - } - - } else { - LOG(error) << "Unknown message: " << path << endl; - me->update(msg->response_body->data); - } -} - -void -HTTPClientReceiver::start(bool dump) -{ - if (!_world->parser()) - _world->load_module("serialisation"); - - SoupMessage* msg = soup_message_new("GET", (_url + "/stream").c_str()); - assert(SOUP_IS_MESSAGE(msg)); - soup_session_queue_message(_client_session, msg, message_callback, this); -} - -void -HTTPClientReceiver::stop() -{ - //unregister_client(); - close_session(); -} - -} // namespace Client -} // namespace Ingen - diff --git a/src/http/HTTPClientReceiver.hpp b/src/http/HTTPClientReceiver.hpp deleted file mode 100644 index 795dac5d..00000000 --- a/src/http/HTTPClientReceiver.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP -#define INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP - -#include <cstdlib> - -#include <boost/utility.hpp> -#include <glibmm/thread.h> - -#include "ingen/ClientInterface.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "raul/Deletable.hpp" -#include "raul/SharedPtr.hpp" -#include "raul/Thread.hpp" -#include "sord/sordmm.hpp" - -typedef struct _SoupSession SoupSession; -typedef struct _SoupMessage SoupMessage; - -namespace Ingen { -namespace Client { - -class HTTPClientReceiver : public boost::noncopyable, public Raul::Deletable -{ -public: - HTTPClientReceiver(Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> target); - - ~HTTPClientReceiver(); - - void send(SoupMessage* msg); - void close_session(); - - std::string uri() const { return _url; } - - void start(bool dump); - void stop(); - - static void message_callback(SoupSession* session, SoupMessage* msg, void* ptr); - -private: - void update(const std::string& str); - - class Listener : public Raul::Thread { - public: - Listener(HTTPClientReceiver* receiver, const std::string& uri); - ~Listener(); - void _run(); - private: - std::string _uri; - int _sock; - HTTPClientReceiver* _receiver; - }; - - friend class Listener; - - SharedPtr<Listener> _listener; - Glib::Mutex _mutex; - SharedPtr<ClientInterface> _target; - Shared::World* _world; - const std::string _url; - SoupSession* _client_session; - bool _quit_flag; -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP diff --git a/src/http/HTTPClientSender.cpp b/src/http/HTTPClientSender.cpp deleted file mode 100644 index ed5299dd..00000000 --- a/src/http/HTTPClientSender.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string> - -#include <libsoup/soup.h> - -#include "ingen/serialisation/Serialiser.hpp" -#include "ingen/shared/World.hpp" -#include "raul/Atom.hpp" -#include "raul/AtomRDF.hpp" -#include "raul/log.hpp" - -#include "../server/Engine.hpp" - -#include "HTTPClientSender.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Server { - -void -HTTPClientSender::response(int32_t id, Status status) -{ - if (status) { - warn << "HTTP Error " << id - << " (" << ingen_status_string(status) << ")" << endl; - } -} - -void -HTTPClientSender::error(const std::string& msg) -{ - warn << "HTTP send error " << msg << endl; -} - -void -HTTPClientSender::put(const URI& uri, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - const std::string request_uri = (Raul::Path::is_path(uri)) - ? _url + "/patch" + uri.substr(uri.find("/")) - : uri.str(); - - const Shared::World& world = _engine.world(); - Sord::Model model(world.rdf_world()); - for (Resource::Properties::const_iterator i = properties.begin(); - i != properties.end(); ++i) - model.add_statement( - Sord::URI(world.rdf_world(), request_uri), - Sord::URI(world.rdf_world(), i->first), - AtomRDF::atom_to_node(model, i->second)); - - const string str = model.write_to_string("", SERD_TURTLE); - send_chunk(str); -} - -void -HTTPClientSender::delta(const URI& uri, - const Resource::Properties& remove, - const Resource::Properties& add) -{ -} - -void -HTTPClientSender::del(const URI& uri) -{ - send_chunk(string("<").append(uri.str()).append("> a <http://www.w3.org/2002/07/owl#Nothing> .")); -} - -void -HTTPClientSender::connect(const Path& src_path, const Path& dst_path) -{ - const string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n").append( - "<> ingen:connection [\n" - "\tingen:destination <").append(dst_path.str()).append("> ;\n" - "\tingen:source <").append(src_path.str()).append(">\n] .\n"); - send_chunk(msg); -} - -void -HTTPClientSender::disconnect(const URI& src, - const URI& dst) -{ -} - -void -HTTPClientSender::disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path) -{ -} - -void -HTTPClientSender::set_property(const URI& subject, const URI& key, const Atom& value) -{ -#if 0 - Sord::Node node = AtomRDF::atom_to_node(*_engine.world()->rdf_world(), value); - const string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n").append( - subject.str()).append("> ingen:property [\n" - "rdf:predicate ").append(key.str()).append(" ;\n" - "rdf:value ").append(node.to_string()).append("\n] .\n"); - send_chunk(msg); -#endif -} - -void -HTTPClientSender::move(const Path& old_path, const Path& new_path) -{ - string msg = string( - "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" - "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n\n<").append( - old_path.str()).append("> rdf:subject <").append(new_path.str()).append("> .\n"); - send_chunk(msg); -} - -} // namespace Server -} // namespace Ingen diff --git a/src/http/HTTPClientSender.hpp b/src/http/HTTPClientSender.hpp deleted file mode 100644 index cfe24001..00000000 --- a/src/http/HTTPClientSender.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef INGEN_ENGINE_HTTPCLIENTSENDER_HPP -#define INGEN_ENGINE_HTTPCLIENTSENDER_HPP - -#include <cassert> -#include <string> - -#include "raul/Thread.hpp" - -#include "ingen/ClientInterface.hpp" - -#include "HTTPSender.hpp" - -namespace Ingen { - -class ServerInterface; - -namespace Server { - -class Engine; - -/** Implements ClientInterface for HTTP clients. - * Sends changes as RDF deltas over an HTTP stream - * (a single message with chunked encoding response). - * - * \ingroup engine - */ -class HTTPClientSender - : public ClientInterface - , public Ingen::Shared::HTTPSender -{ -public: - explicit HTTPClientSender(Engine& engine) - : _engine(engine) - , _enabled(true) - {} - - bool enabled() const { return _enabled; } - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() { HTTPSender::bundle_begin(); } - void bundle_end() { HTTPSender::bundle_end(); } - - Raul::URI uri() const { return "http://example.org/"; } - - /* *** ClientInterface Implementation Below *** */ - - void response(int32_t id, Status status); - - void error(const std::string& msg); - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject_path, - const Raul::URI& predicate, - const Raul::Atom& value); - -private: - Engine& _engine; - std::string _url; - bool _enabled; -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_HTTPCLIENTSENDER_HPP - diff --git a/src/http/HTTPEngineReceiver.cpp b/src/http/HTTPEngineReceiver.cpp deleted file mode 100644 index 4831ee4d..00000000 --- a/src/http/HTTPEngineReceiver.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <cstdio> -#include <cstdlib> -#include <string> - -#include <boost/format.hpp> - -#include <libsoup/soup.h> - -#include "raul/SharedPtr.hpp" -#include "raul/log.hpp" - -#include "ingen/ClientInterface.hpp" -#include "ingen/ServerInterface.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "ingen/serialisation/Serialiser.hpp" -#include "ingen/shared/Module.hpp" -#include "ingen/shared/Store.hpp" - -#include "../server/ClientBroadcaster.hpp" -#include "../server/Engine.hpp" - -#include "HTTPClientSender.hpp" -#include "HTTPEngineReceiver.hpp" - -#define LOG(s) s << "[HTTPEngineReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Serialisation; - -namespace Server { - -HTTPEngineReceiver::HTTPEngineReceiver(Engine& engine, - SharedPtr<ServerInterface> interface, - uint16_t port) - : _engine(engine) - , _interface(interface) - , _server(soup_server_new(SOUP_SERVER_PORT, port, NULL)) -{ - _receive_thread = new ReceiveThread(*this); - - soup_server_add_handler(_server, NULL, message_callback, this, NULL); - - LOG(info) << "Started HTTP server on port " << soup_server_get_port(_server) << endl; - - if (!engine.world()->parser() || !engine.world()->serialiser()) - engine.world()->load_module("serialisation"); - - _receive_thread->set_name("HTTPEngineReceiver Listener"); - _receive_thread->start(); -} - -HTTPEngineReceiver::~HTTPEngineReceiver() -{ - _receive_thread->stop(); - delete _receive_thread; - - if (_server) { - soup_server_quit(_server); - _server = NULL; - } -} - -void -HTTPEngineReceiver::message_callback(SoupServer* server, - SoupMessage* msg, - const char* path_str, - GHashTable* query, - SoupClientContext* client, - void* data) -{ - HTTPEngineReceiver* me = (HTTPEngineReceiver*)data; - ServerInterface* interface = me->_interface.get(); - - using namespace Ingen::Shared; - - SharedPtr<Store> store = me->_engine.world()->store(); - if (!store) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - string path = path_str; - if (path[path.length() - 1] == '/') { - path = path.substr(0, path.length()-1); - } - - SharedPtr<Serialiser> serialiser = me->_engine.world()->serialiser(); - - const string base_uri = "path:/"; - const char* mime_type = "text/plain"; - - // Special GET paths - if (msg->method == SOUP_METHOD_GET) { - if (path == Path::root().str() || path.empty()) { - const string r = string("@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n") - .append("\n<> rdfs:seeAlso <plugins> ;") - .append("\n rdfs:seeAlso <stream> ;") - .append("\n rdfs:seeAlso <patch> ."); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, r.c_str(), r.length()); - return; - - } else if (msg->method == SOUP_METHOD_GET && path.substr(0, 8) == "/plugins") { - // FIXME: kludge - #if 0 - interface->get("ingen:plugins"); - me->_receive_thread->whip(); - - serialiser->start_to_string("/", base_uri); - for (NodeFactory::Plugins::const_iterator p = me->_engine.node_factory()->plugins().begin(); - p != me->_engine.node_factory()->plugins().end(); ++p) - serialiser->serialise_plugin(*(Shared::Plugin*)p->second); - const string r = serialiser->finish(); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, r.c_str(), r.length()); - #endif - return; - - } else if (path.substr(0, 6) == "/patch") { - path = '/' + path.substr(6); - if (path.substr(0, 2) == "//") - path = path.substr(1); - - } else if (path.substr(0, 7) == "/stream") { - HTTPClientSender* client = new HTTPClientSender(me->_engine); - interface->register_client(client); - - // Respond with port number of stream for client - const int port = client->listen_port(); - char buf[32]; - snprintf(buf, sizeof(buf), "%d", port); - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, buf, strlen(buf)); - return; - } - } - - if (!Path::is_valid(path)) { - LOG(error) << "Bad HTTP path: " << path << endl; - soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST); - const string& err = (boost::format("Bad path: %1%") % path).str(); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_COPY, - err.c_str(), err.length()); - return; - } - - if (msg->method == SOUP_METHOD_GET) { - Glib::RWLock::ReaderLock lock(store->lock()); - - // Find object - Store::const_iterator start = store->find(path); - if (start == store->end()) { - soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); - const string& err = (boost::format("No such object: %1%") % path).str(); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_COPY, - err.c_str(), err.length()); - return; - } - - // Get serialiser - SharedPtr<Serialiser> serialiser = me->_engine.world()->serialiser(); - if (!serialiser) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - soup_message_set_response(msg, "text/plain", SOUP_MEMORY_STATIC, - "No serialiser available\n", 24); - return; - } - - // Serialise object - const string response = serialiser->to_string(start->second, - "http://localhost:16180/patch", GraphObject::Properties()); - - soup_message_set_status(msg, SOUP_STATUS_OK); - soup_message_set_response(msg, mime_type, SOUP_MEMORY_COPY, - response.c_str(), response.length()); - - } else if (msg->method == SOUP_METHOD_PUT) { - Glib::RWLock::WriterLock lock(store->lock()); - - // Get parser - SharedPtr<Parser> parser = me->_engine.world()->parser(); - if (!parser) { - soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - parser->parse_string(me->_engine.world(), interface, msg->request_body->data, base_uri); - soup_message_set_status(msg, SOUP_STATUS_OK); - - } else if (msg->method == SOUP_METHOD_DELETE) { - interface->del(path); - soup_message_set_status(msg, SOUP_STATUS_OK); - - } else { - soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); - } -} - -void -HTTPEngineReceiver::ReceiveThread::_run() -{ - soup_server_run(_receiver._server); -} - -} // namespace Server -} // namespace Ingen - diff --git a/src/http/HTTPEngineReceiver.hpp b/src/http/HTTPEngineReceiver.hpp deleted file mode 100644 index d560a5f3..00000000 --- a/src/http/HTTPEngineReceiver.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef INGEN_ENGINE_HTTPENGINERECEIVER_HPP -#define INGEN_ENGINE_HTTPENGINERECEIVER_HPP - -#include <stdint.h> - -#include <string> - -#include "raul/Thread.hpp" - -typedef struct _SoupServer SoupServer; -typedef struct _SoupMessage SoupMessage; -typedef struct SoupClientContext SoupClientContext; - -namespace Ingen { - -class ServerInterface; - -namespace Server { - -class Engine; - -class HTTPEngineReceiver -{ -public: - HTTPEngineReceiver(Engine& engine, - SharedPtr<ServerInterface> interface, - uint16_t port); - - ~HTTPEngineReceiver(); - -private: - struct ReceiveThread : public Raul::Thread { - explicit ReceiveThread(HTTPEngineReceiver& receiver) - : _receiver(receiver) - {} - virtual void _run(); - private: - HTTPEngineReceiver& _receiver; - }; - - friend class ReceiveThread; - - static void message_callback(SoupServer* server, - SoupMessage* msg, - const char* path, - GHashTable *query, - SoupClientContext* client, - void* data); - - Engine& _engine; - SharedPtr<ServerInterface> _interface; - ReceiveThread* _receive_thread; - SoupServer* _server; -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_HTTPENGINERECEIVER_HPP diff --git a/src/http/HTTPEngineSender.cpp b/src/http/HTTPEngineSender.cpp deleted file mode 100644 index 39de6f41..00000000 --- a/src/http/HTTPEngineSender.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <libsoup/soup.h> - -#include "raul/AtomRDF.hpp" -#include "raul/log.hpp" -#include "sord/sordmm.hpp" - -#include "ingen/shared/World.hpp" -#include "HTTPEngineSender.hpp" -#include "HTTPClientReceiver.hpp" - -#define LOG(s) s << "[HTTPEngineSender] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Shared; - -namespace Client { - -HTTPEngineSender::HTTPEngineSender(World* world, - const URI& engine_url, - SharedPtr<Raul::Deletable> receiver) - : _receiver(PtrCast<HTTPClientReceiver>(receiver)) - , _world(*world->rdf_world()) - , _engine_url(engine_url) - , _id(0) - , _enabled(true) -{ - assert(_receiver); - _session = soup_session_sync_new(); -} - -HTTPEngineSender::~HTTPEngineSender() -{ - soup_session_abort(_session); -} - -void -HTTPEngineSender::attach(int32_t ping_id, bool block) -{ - LOG(debug) << "Attaching to " << _engine_url << endl; - SoupMessage* msg = soup_message_new("GET", _engine_url.c_str()); - soup_session_queue_message(_session, msg, - HTTPClientReceiver::message_callback, _receiver.get()); -} - -/* *** ServerInterface implementation below here *** */ - -/** Register with the engine via HTTP. - * - * Note that this does not actually use 'key', since the engine creates - * it's own key for HTTP clients (namely the incoming URL), for NAT - * traversal. It is a parameter to remain compatible with ServerInterface. - */ -void -HTTPEngineSender::register_client(ClientInterface* client) -{ - /*SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/stream").c_str()); - HTTPClientReceiver::send(msg);*/ -} - -void -HTTPEngineSender::unregister_client(const URI& uri) -{ -} - -// Object commands - -void -HTTPEngineSender::put(const URI& uri, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); - const string full_uri = _engine_url.str() + "/" + path; - - Sord::Model model(_world); - for (Resource::Properties::const_iterator i = properties.begin(); i != properties.end(); ++i) - model.add_statement(Sord::URI(_world, path), - AtomRDF::atom_to_node(model, i->first), - AtomRDF::atom_to_node(model, i->second)); - - const string str = model.write_to_string(""); - SoupMessage* msg = soup_message_new(SOUP_METHOD_PUT, full_uri.c_str()); - assert(msg); - soup_message_set_request(msg, "application/x-turtle", SOUP_MEMORY_COPY, str.c_str(), str.length()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add) -{ - LOG(warn) << "TODO: HTTP delta" << endl; -} - -void -HTTPEngineSender::move(const Path& old_path, - const Path& new_path) -{ - SoupMessage* msg = soup_message_new(SOUP_METHOD_MOVE, - (_engine_url.str() + old_path.str()).c_str()); - soup_message_headers_append(msg->request_headers, "Destination", - (_engine_url.str() + new_path.str()).c_str()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::del(const URI& uri) -{ - const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); - const string full_uri = _engine_url.str() + "/" + path; - SoupMessage* msg = soup_message_new(SOUP_METHOD_DELETE, full_uri.c_str()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::connect(const Path& src_port_path, - const Path& dst_port_path) -{ - LOG(warn) << "TODO: HTTP connect" << endl; -} - -void -HTTPEngineSender::disconnect(const URI& src, - const URI& dst) -{ - LOG(warn) << "TODO: HTTP disconnect" << endl; -} - -void -HTTPEngineSender::disconnect_all(const Path& parent_patch_path, - const Path& path) -{ - LOG(warn) << "TODO: HTTP disconnect_all" << endl; -} - -void -HTTPEngineSender::set_property(const URI& subject, - const URI& predicate, - const Atom& value) -{ - Resource::Properties prop; - prop.insert(make_pair(predicate, value)); - put(subject, prop); -} - -// Requests // - -void -HTTPEngineSender::ping() -{ - LOG(debug) << "Ping " << _engine_url << endl; - get(_engine_url); -} - -void -HTTPEngineSender::get(const URI& uri) -{ - if (!Raul::Path::is_path(uri) && uri.scheme() != "http" && uri.scheme() != "ingen") { - LOG(warn) << "Ignoring GET of non-HTTP URI " << uri << endl; - return; - } - - const std::string request_uri = (Raul::Path::is_path(uri)) - ?_engine_url.str() + "/patch" + uri.substr(uri.find("/")) - : uri.str(); - cout << "Get " << request_uri << endl; - LOG(debug) << "Get " << request_uri << endl; - SoupMessage* msg = soup_message_new("GET", request_uri.c_str()); - soup_session_queue_message(_session, msg, - HTTPClientReceiver::message_callback, _receiver.get()); - -} - -} // namespace Client -} // namespace Ingen - diff --git a/src/http/HTTPEngineSender.hpp b/src/http/HTTPEngineSender.hpp deleted file mode 100644 index 6f1d9cc5..00000000 --- a/src/http/HTTPEngineSender.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef INGEN_CLIENT_HTTPENGINESENDER_HPP -#define INGEN_CLIENT_HTTPENGINESENDER_HPP - -#include <inttypes.h> - -#include <string> - -#include "raul/Deletable.hpp" -#include "raul/Path.hpp" -#include "sord/sordmm.hpp" - -#include "ingen/ServerInterface.hpp" - -typedef struct _SoupSession SoupSession; - -namespace Ingen { - -namespace Shared { class World; } - -namespace Client { - -class HTTPClientReceiver; - -/* HTTP (via libsoup) interface to the engine. - * - * Clients can use this opaquely as an ServerInterface to control the engine - * over HTTP (whether over a network or not). - * - * \ingroup IngenClient - */ -class HTTPEngineSender : public ServerInterface -{ -public: - HTTPEngineSender(Shared::World* world, - const Raul::URI& engine_url, - SharedPtr<Raul::Deletable> receiver); - - ~HTTPEngineSender(); - - Raul::URI uri() const { return _engine_url; } - - inline int32_t next_id() { return (_id == -1) ? -1 : _id++; } - - void set_response_id(int32_t id) { _id = id; } - - void attach(int32_t ping_id, bool block); - - /* *** ServerInterface implementation below here *** */ - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() {} - void bundle_end() {} - - // Client registration - void register_client(ClientInterface* client); - void unregister_client(const Raul::URI& uri); - - // Object commands - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx=Resource::DEFAULT); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject, - const Raul::URI& predicate, - const Raul::Atom& value); - - // Requests // - void ping(); - void get(const Raul::URI& uri); - -protected: - SharedPtr<HTTPClientReceiver> _receiver; - - SoupSession* _session; - Sord::World& _world; - const Raul::URI _engine_url; - int _client_port; - int32_t _id; - bool _enabled; -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_HTTPENGINESENDER_HPP - diff --git a/src/http/HTTPSender.cpp b/src/http/HTTPSender.cpp deleted file mode 100644 index 8436956f..00000000 --- a/src/http/HTTPSender.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <cassert> -#include <cstdio> -#include <cstring> -#include <unistd.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdlib.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <errno.h> -#include "raul/log.hpp" -#include "HTTPSender.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Shared { - -HTTPSender::HTTPSender() - : _listen_port(-1) - , _listen_sock(-1) - , _client_sock(-1) - , _send_state(Immediate) -{ - Thread::set_name("HTTPSender"); - - struct sockaddr_in addr; - - // Create listen address - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - // Create listen socket - if ((_listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { - error << "Error creating listening socket (" << strerror(errno) << ")" << endl; - exit(EXIT_FAILURE); - } - - // Bind our socket addresss to the listening socket - if (bind(_listen_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - error << "Error calling bind (%s)\n" << strerror(errno) << ")" << endl; - _listen_sock = -1; - } - - // Find port number - socklen_t length = sizeof(addr); - if (getsockname(_listen_sock, (struct sockaddr*)&addr, &length) == -1) { - error << "Error calling getsockname (" << strerror(errno) << ")" << endl; - _listen_sock = -1; - return; - } - - if (listen(_listen_sock, 1) < 0 ) { - error << "Error calling listen (" << strerror(errno) << ")" << endl; - _listen_sock = -1; - return; - } - - _listen_port = ntohs(addr.sin_port); - info << "Opening event stream on TCP port " << _listen_port << endl; - start(); -} - -HTTPSender::~HTTPSender() -{ - stop(); - if (_listen_sock != -1) - close(_listen_sock); - if (_client_sock != -1) - close(_client_sock); -} - -void -HTTPSender::_run() -{ - if (_listen_sock == -1) { - error << "Unable to open socket, exiting sender thread" << endl; - return; - } - - // Accept connection - if ((_client_sock = accept(_listen_sock, NULL, NULL) ) < 0) { - error << "Error calling accept: " << strerror(errno) << endl; - return; - } - - // Hold connection open and write when signalled - while (true) { - _mutex.lock(); - _signal.wait(_mutex); - - write(_client_sock, _transfer.c_str(), _transfer.length()); - write(_client_sock, "\n\n\n", 3); - - _signal.broadcast(); - _mutex.unlock(); - } - - close(_listen_sock); - _listen_sock = -1; -} - -void -HTTPSender::bundle_begin() -{ - _mutex.lock(); - _send_state = SendingBundle; - _transfer = ""; -} - -void -HTTPSender::bundle_end() -{ - assert(_send_state == SendingBundle); - _signal.broadcast(); - _signal.wait(_mutex); - _send_state = Immediate; - _mutex.unlock(); -} - -void -HTTPSender::send_chunk(const std::string& buf) -{ - if (_send_state == Immediate) { - _mutex.lock(); - _transfer = buf; - _signal.broadcast(); - _signal.wait(_mutex); - _mutex.unlock(); - } else { - _transfer.append(buf); - } -} - -} // namespace Shared -} // namespace Ingen diff --git a/src/http/HTTPSender.hpp b/src/http/HTTPSender.hpp deleted file mode 100644 index d0ea32e4..00000000 --- a/src/http/HTTPSender.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef INGEN_SHARED_HTTPSENDER_HPP -#define INGEN_SHARED_HTTPSENDER_HPP - -#include <string> - -#include <glibmm/thread.h> - -#include "raul/Thread.hpp" - -namespace Ingen { -namespace Shared { - -class HTTPSender : public Raul::Thread { -public: - HTTPSender(); - virtual ~HTTPSender(); - - void bundle_begin(); - void bundle_end(); - - int listen_port() const { return _listen_port; } - -protected: - void _run(); - - void send_chunk(const std::string& buf); - - enum SendState { Immediate, SendingBundle }; - - Glib::Mutex _mutex; - Glib::Cond _signal; - - int _listen_port; - int _listen_sock; - int _client_sock; - SendState _send_state; - std::string _transfer; -}; - -} // namespace Shared -} // namespace Ingen - -#endif // INGEN_SHARED_HTTPSENDER_HPP - diff --git a/src/http/ingen_http_client.cpp b/src/http/ingen_http_client.cpp deleted file mode 100644 index e444e2e2..00000000 --- a/src/http/ingen_http_client.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ingen/shared/Module.hpp" -#include "ingen/shared/World.hpp" - -#include "HTTPClientReceiver.hpp" -#include "HTTPEngineSender.hpp" - -using namespace std; -using namespace Ingen; - -SharedPtr<Ingen::ServerInterface> -new_http_interface(Ingen::Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> respond_to) -{ - SharedPtr<Client::HTTPClientReceiver> receiver( - new Client::HTTPClientReceiver(world, url, respond_to)); - Client::HTTPEngineSender* hes = new Client::HTTPEngineSender( - world, url, receiver); - hes->attach(rand(), true); - return SharedPtr<ServerInterface>(hes); -} - -struct IngenHTTPClientModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { - world->add_interface_factory("http", &new_http_interface); - } -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenHTTPClientModule(); -} - -} // extern "C" diff --git a/src/http/ingen_http_server.cpp b/src/http/ingen_http_server.cpp deleted file mode 100644 index 56fff6f5..00000000 --- a/src/http/ingen_http_server.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard <http://drobilla.net/> - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "ingen/shared/Module.hpp" -#include "ingen/shared/World.hpp" - -#include "../server/Engine.hpp" -#include "../server/ServerInterfaceImpl.hpp" - -#include "HTTPEngineReceiver.hpp" - -using namespace std; -using namespace Ingen; - -struct IngenHTTPModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { - Server::Engine* engine = (Server::Engine*)world->local_engine().get(); - SharedPtr<Server::ServerInterfaceImpl> interface( - new Server::ServerInterfaceImpl(*engine)); - - receiver = SharedPtr<Server::HTTPEngineReceiver>( - new Server::HTTPEngineReceiver( - *engine, - interface, - world->conf()->option("engine-port").get_int32())); - engine->add_event_source(interface); - } - - SharedPtr<Server::HTTPEngineReceiver> receiver; -}; - -extern "C" { - -Ingen::Shared::Module* -ingen_module_load() -{ - return new IngenHTTPModule(); -} - -} // extern "C" diff --git a/src/http/wscript b/src/http/wscript deleted file mode 100644 index dec805e3..00000000 --- a/src/http/wscript +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python -from waflib.extras import autowaf as autowaf - -def build(bld): - if bld.is_defined('HAVE_SOUP'): - obj = bld(features = 'cxx cxxshlib', - source = '''HTTPClientSender.cpp - HTTPEngineReceiver.cpp - HTTPSender.cpp - ingen_http_server.cpp''', - includes = ['../..'], - name = 'libingen_http_server', - target = 'ingen_http_server', - install_path = '${LIBDIR}', - use = 'libingen_server') - autowaf.use_lib(bld, obj, 'RAUL SOUP') - - obj = bld(features = 'cxx cxxshlib', - source = '''HTTPClientReceiver.cpp - HTTPEngineSender.cpp - HTTPSender.cpp - ingen_http_client.cpp''', - includes = ['../..'], - name = 'libingen_http_client', - target = 'ingen_http_client', - install_path = '${LIBDIR}', - use = 'libingen_client') - autowaf.use_lib(bld, obj, 'RAUL SOUP') |