summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-05-09 17:50:15 +0000
committerDavid Robillard <d@drobilla.net>2012-05-09 17:50:15 +0000
commit8c24b153cbef68bf235d00e75b21b1c81766895c (patch)
tree49f8b95fc28e7209ff0b8c7549000584f4b51d26
parentffdf4624323af943a2f3f7241fa87d97afc50460 (diff)
downloadingen-8c24b153cbef68bf235d00e75b21b1c81766895c.tar.gz
ingen-8c24b153cbef68bf235d00e75b21b1c81766895c.tar.bz2
ingen-8c24b153cbef68bf235d00e75b21b1c81766895c.zip
Factor out Socket from SocketListener and make interface more general.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4330 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/socket/Socket.cpp122
-rw-r--r--src/socket/Socket.hpp70
-rw-r--r--src/socket/SocketListener.cpp92
-rw-r--r--src/socket/SocketListener.hpp23
4 files changed, 206 insertions, 101 deletions
diff --git a/src/socket/Socket.cpp b/src/socket/Socket.cpp
new file mode 100644
index 00000000..7fb4d89b
--- /dev/null
+++ b/src/socket/Socket.cpp
@@ -0,0 +1,122 @@
+/*
+ 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 <errno.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+
+#include <string>
+#include <sstream>
+
+#include "raul/log.hpp"
+
+#include "Socket.hpp"
+
+#define LOG(s) s << "[Socket] "
+
+namespace Ingen {
+namespace Socket {
+
+bool
+Socket::open_unix(const std::string& uri, const std::string& path)
+{
+ if ((_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ return false;
+ }
+
+ struct sockaddr_un* uaddr = (struct sockaddr_un*)calloc(
+ 1, sizeof(struct sockaddr_un));
+ uaddr->sun_family = AF_UNIX;
+ strncpy(uaddr->sun_path, path.c_str(), sizeof(uaddr->sun_path) - 1);
+ _uri = uri;
+ _addr = (sockaddr*)uaddr;
+ _addr_len = sizeof(struct sockaddr_un);
+
+ return bind();
+}
+
+bool
+Socket::open_tcp(const std::string& uri, uint16_t port)
+{
+ if ((_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ return false;
+ }
+
+ struct sockaddr_in* naddr = (struct sockaddr_in*)calloc(
+ 1, sizeof(struct sockaddr_in));
+ naddr->sin_family = AF_INET;
+ naddr->sin_port = htons(port);
+ _uri = uri;
+ _addr = (sockaddr*)naddr;
+ _addr_len = sizeof(struct sockaddr_in);
+
+ return bind();
+}
+
+bool
+Socket::bind()
+{
+ if (::bind(_sock, _addr, _addr_len) == -1) {
+ LOG(Raul::error) << "Failed to bind " << _uri
+ << ": " << strerror(errno) << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool
+Socket::listen()
+{
+ if (::listen(_sock, 64) == -1) {
+ LOG(Raul::error) << "Failed to listen on " << _uri << std::endl;
+ return false;
+ } else {
+ LOG(Raul::info) << "Listening on " << _uri << std::endl;
+ return true;
+ }
+}
+
+int
+Socket::accept()
+{
+ // Accept connection from client
+ socklen_t client_addr_len = _addr_len;
+ struct sockaddr* client_addr = (struct sockaddr*)calloc(
+ 1, client_addr_len);
+
+ int conn = ::accept(_sock, client_addr, &client_addr_len);
+ if (conn == -1) {
+ LOG(Raul::error) << "Error accepting connection: "
+ << strerror(errno) << std::endl;
+ }
+
+ return conn;
+}
+
+void
+Socket::close()
+{
+ if (_sock != -1) {
+ ::close(_sock);
+ _sock = -1;
+ }
+}
+
+} // namespace Ingen
+} // namespace Socket
diff --git a/src/socket/Socket.hpp b/src/socket/Socket.hpp
new file mode 100644
index 00000000..fa2b6972
--- /dev/null
+++ b/src/socket/Socket.hpp
@@ -0,0 +1,70 @@
+/*
+ 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 <stdint.h>
+#include <sys/socket.h>
+
+#include <string>
+
+namespace Ingen {
+namespace Socket {
+
+class Socket {
+public:
+ Socket() : _addr(NULL), _addr_len(0), _sock(-1) {}
+ ~Socket() { close(); }
+
+ /** Open UNIX socket and bind to address.
+ * @param uri URI used for identification and log output.
+ * @param path Socket path.
+ * @return True on success
+ */
+ bool open_unix(const std::string& uri, const std::string& path);
+
+ /** Open TCP socket and bind to address.
+ * @param uri URI used for identification and log output.
+ * @param port Port number.
+ * @return True on success
+ */
+ bool open_tcp(const std::string& uri, uint16_t port);
+
+ /** Mark server socket as passive to listen for incoming connections.
+ * @return True on success.
+ */
+ bool listen();
+
+ /** Accept a connection.
+ * @return The socket file descriptor, or -1 on error.
+ */
+ int accept();
+
+ /** Return the file descriptor for the socket. */
+ int fd() { return _sock; }
+
+ /** Close the socket. */
+ void close();
+
+private:
+ bool bind();
+
+ std::string _uri;
+ struct sockaddr* _addr;
+ socklen_t _addr_len;
+ int _sock;
+};
+
+} // namespace Socket
+} // namespace Ingen
diff --git a/src/socket/SocketListener.cpp b/src/socket/SocketListener.cpp
index eadeedd8..6f41383b 100644
--- a/src/socket/SocketListener.cpp
+++ b/src/socket/SocketListener.cpp
@@ -15,14 +15,10 @@
*/
#include <errno.h>
-#include <netinet/in.h>
#include <poll.h>
-#include <sys/fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <string>
#include <sstream>
+#include <string>
#include "ingen/Interface.hpp"
#include "ingen/shared/World.hpp"
@@ -40,91 +36,27 @@
namespace Ingen {
namespace Socket {
-bool
-SocketListener::Socket::open(const std::string& uri,
- int domain,
- struct sockaddr* a,
- socklen_t s)
-{
- addr = a;
- addr_len = s;
- sock = socket(domain, SOCK_STREAM, 0);
- if (sock == -1) {
- return false;
- }
-
- if (bind(sock, addr, addr_len) == -1) {
- LOG(Raul::error) << "Failed to bind " << uri << std::endl;
- return false;
- }
-
- if (listen(sock, 64) == -1) {
- LOG(Raul::error) << "Failed to listen on " << uri << std::endl;
- return false;
- } else {
- LOG(Raul::info) << "Listening on " << uri << std::endl;
- }
-
- return true;
-}
-
-int
-SocketListener::Socket::accept()
-{
- // Accept connection from client
- socklen_t client_addr_len = addr_len;
- struct sockaddr* client_addr = (struct sockaddr*)calloc(
- 1, client_addr_len);
-
- int conn = ::accept(sock, client_addr, &client_addr_len);
- if (conn == -1) {
- LOG(Raul::error) << "Error accepting connection: "
- << strerror(errno) << std::endl;
- }
-
- return conn;
-}
-
-void
-SocketListener::Socket::close()
-{
- if (sock != -1) {
- ::close(sock);
- sock = -1;
- }
-}
-
SocketListener::SocketListener(Ingen::Shared::World& world)
: _world(world)
{
set_name("SocketListener");
// Create UNIX socket
- _unix_path = world.conf()->option("socket").get_string();
- std::string unix_uri = "turtle+unix://" + _unix_path;
- struct sockaddr_un* uaddr = (struct sockaddr_un*)calloc(
- 1, sizeof(struct sockaddr_un));
- uaddr->sun_family = AF_UNIX;
- strncpy(uaddr->sun_path, _unix_path.c_str(), sizeof(uaddr->sun_path) - 1);
- if (!_unix_sock.open(unix_uri, AF_UNIX,
- (struct sockaddr*)uaddr,
- sizeof(struct sockaddr_un))) {
+ _unix_path = world.conf()->option("socket").get_string();
+ const std::string unix_uri = "unix://" + _unix_path;
+ if (!_unix_sock.open_unix(unix_uri, _unix_path) || !_unix_sock.listen()) {
LOG(Raul::error) << "Failed to create UNIX socket" << std::endl;
+ _unix_sock.close();
}
// Create TCP socket
int port = world.conf()->option("engine-port").get_int();
std::ostringstream ss;
- ss << "turtle+tcp:///localhost:";
+ ss << "tcp:///localhost:";
ss << port;
- struct sockaddr_in* naddr = (struct sockaddr_in*)calloc(
- 1, sizeof(struct sockaddr_in));
- naddr->sin_family = AF_INET;
- naddr->sin_port = htons(port);
- if (!_net_sock.open(ss.str(), AF_INET,
- (struct sockaddr*)naddr,
- sizeof(struct sockaddr_in))) {
+ if (!_net_sock.open_tcp(ss.str(), port) || !_net_sock.listen()) {
LOG(Raul::error) << "Failed to create TCP socket" << std::endl;
+ _net_sock.close();
}
start();
@@ -146,14 +78,14 @@ SocketListener::_run()
struct pollfd pfds[2];
int nfds = 0;
- if (_unix_sock.sock != -1) {
- pfds[nfds].fd = _unix_sock.sock;
+ if (_unix_sock.fd() != -1) {
+ pfds[nfds].fd = _unix_sock.fd();
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
++nfds;
}
- if (_net_sock.sock != -1) {
- pfds[nfds].fd = _net_sock.sock;
+ if (_net_sock.fd() != -1) {
+ pfds[nfds].fd = _net_sock.fd();
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
++nfds;
diff --git a/src/socket/SocketListener.hpp b/src/socket/SocketListener.hpp
index 6d70c78a..ca05f325 100644
--- a/src/socket/SocketListener.hpp
+++ b/src/socket/SocketListener.hpp
@@ -14,13 +14,13 @@
along with Ingen. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <sys/socket.h>
-
#include <string>
#include "raul/SharedPtr.hpp"
#include "raul/Thread.hpp"
+#include "Socket.hpp"
+
namespace Ingen {
class Interface;
@@ -35,25 +35,6 @@ public:
SocketListener(Ingen::Shared::World& world);
~SocketListener();
- struct Socket {
- Socket() : addr(NULL), addr_len(0), sock(-1) {}
- ~Socket() { close(); }
-
- bool open(const std::string& uri,
- int domain,
- struct sockaddr* addr,
- socklen_t addr_len);
-
- int accept();
-
- void close();
-
- std::string uri;
- struct sockaddr* addr;
- socklen_t addr_len;
- int sock;
- };
-
private:
virtual void _run();