diff options
author | David Robillard <d@drobilla.net> | 2008-11-16 02:49:22 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-11-16 02:49:22 +0000 |
commit | 24d998447070dbfef3eaf7762dce7e97c3903801 (patch) | |
tree | 0feffd6ca3c4459e0a7ff6fad9cf48b7816f2cd7 /src/shared | |
parent | fb6471ac9d5daefd3655bc19532a6028b5f0ead4 (diff) | |
download | ingen-24d998447070dbfef3eaf7762dce7e97c3903801.tar.gz ingen-24d998447070dbfef3eaf7762dce7e97c3903801.tar.bz2 ingen-24d998447070dbfef3eaf7762dce7e97c3903801.zip |
TCP notification stream support (not fully implemented yet, but transport stuff is working).
Support multiple event sources in the engine.
Clean up HTTP/TCP stuff.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@1721 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/HTTPSender.cpp | 111 | ||||
-rw-r--r-- | src/shared/HTTPSender.hpp | 21 |
2 files changed, 110 insertions, 22 deletions
diff --git a/src/shared/HTTPSender.cpp b/src/shared/HTTPSender.cpp index 20135b2a..7f760786 100644 --- a/src/shared/HTTPSender.cpp +++ b/src/shared/HTTPSender.cpp @@ -20,6 +20,12 @@ #include <iostream> #include <unistd.h> #include <stdarg.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <errno.h> + +#include <cstring> using namespace std; @@ -27,53 +33,126 @@ namespace Ingen { namespace Shared { -HTTPSender::HTTPSender(SoupServer* server, SoupMessage* msg) - : _server(server) - , _msg(msg) +HTTPSender::HTTPSender() + : _listen_port(-1) + , _listen_sock(-1) + , _client_sock(-1) + , _send_state(Immediate) { - soup_message_headers_set_encoding(msg->response_headers, SOUP_ENCODING_CHUNKED); - cout << "Hello?" << endl; - send_chunk("hello"); + Thread::set_name("HTTP Sender"); + + 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 ) { + fprintf(stderr, "Error creating listening socket (%s)\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + // Bind our socket addresss to the listening socket + if (bind(_listen_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + fprintf(stderr, "Error calling bind (%s)\n", strerror(errno)); + _listen_sock = -1; + } + + // Find port number + socklen_t length = sizeof(addr); + if (getsockname(_listen_sock, (struct sockaddr*)&addr, &length) == -1) { + fprintf(stderr, "Error calling getsockname (%s)\n", strerror(errno)); + _listen_sock = -1; + return; + } + + if (listen(_listen_sock, 1) < 0 ) { + cerr << "Error calling listen: %s" << strerror(errno) << endl; + _listen_sock = -1; + return; + } + + _listen_port = ntohs(addr.sin_port); + cout << "Opening event stream on TCP port " << _listen_port << endl; + start(); } HTTPSender::~HTTPSender() { - cout << "HTTP SENDER EXIT" << endl; - soup_message_body_complete(_msg->response_body); - soup_server_unpause_message(_server, _msg); + stop(); + if (_listen_sock != -1) + close(_listen_sock); + if (_client_sock != -1) + close(_client_sock); +} + +void +HTTPSender::_run() +{ + if (_listen_sock == -1) { + cerr << "Unable to open socket, exiting sender thread" << endl; + return; + } + + // Accept connection + if ((_client_sock = accept(_listen_sock, NULL, NULL) ) < 0) { + cerr << "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", 2); + + _mutex.unlock(); + } + + close(_listen_sock); + _listen_sock = -1; } void HTTPSender::bundle_begin() { + _mutex.lock(); _send_state = SendingBundle; + _transfer = ""; + _mutex.unlock(); } void HTTPSender::bundle_end() { + _mutex.lock(); assert(_send_state == SendingBundle); - soup_message_body_append(_msg->response_body, - SOUP_MEMORY_TEMPORARY, _transfer.c_str(), _transfer.length()); - soup_server_unpause_message(_server, _msg); - _transfer = ""; + _signal.broadcast(); _send_state = Immediate; + _mutex.unlock(); } void HTTPSender::send_chunk(const std::string& buf) { + _mutex.lock(); + if (_send_state == Immediate) { - soup_message_body_append(_msg->response_body, - SOUP_MEMORY_TEMPORARY, buf.c_str(), buf.length()); - soup_server_unpause_message(_server, _msg); + _transfer = ""; + _signal.broadcast(); } else { _transfer.append(buf); } + + _mutex.unlock(); } diff --git a/src/shared/HTTPSender.hpp b/src/shared/HTTPSender.hpp index 1025c071..1077b76d 100644 --- a/src/shared/HTTPSender.hpp +++ b/src/shared/HTTPSender.hpp @@ -20,14 +20,15 @@ #include <stdint.h> #include <string> -#include <libsoup/soup.h> +#include <glibmm/thread.h> +#include "raul/Thread.hpp" namespace Ingen { namespace Shared { -class HTTPSender { +class HTTPSender : public Raul::Thread { public: - HTTPSender(SoupServer* server, SoupMessage* msg); + HTTPSender(); virtual ~HTTPSender(); // Message bundling @@ -38,13 +39,21 @@ public: void transfer_begin() { bundle_begin(); } void transfer_end() { bundle_end(); } + int listen_port() const { return _listen_port; } + protected: - void send_chunk(const std::string& buf); + void _run(); + void send_chunk(const std::string& buf); + enum SendState { Immediate, SendingBundle }; - SoupServer* _server; - SoupMessage* _msg; + Glib::Mutex _mutex; + Glib::Cond _signal; + + int _listen_port; + int _listen_sock; + int _client_sock; SendState _send_state; std::string _transfer; }; |