summaryrefslogtreecommitdiffstats
path: root/src/socket/Socket.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-05-10 02:14:55 +0000
committerDavid Robillard <d@drobilla.net>2012-05-10 02:14:55 +0000
commit281bbcc6a7208c28283bc9bdd521c5d6cc48a60f (patch)
tree6cfc2bf6c3c0d92b3cb5a79a4d019d5952d41989 /src/socket/Socket.cpp
parentcd2ac251d7e076e3bf25f2640d1684447efa83d3 (diff)
downloadingen-281bbcc6a7208c28283bc9bdd521c5d6cc48a60f.tar.gz
ingen-281bbcc6a7208c28283bc9bdd521c5d6cc48a60f.tar.bz2
ingen-281bbcc6a7208c28283bc9bdd521c5d6cc48a60f.zip
Bidirectional socket communication (GUI once again works remotely).
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4335 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/socket/Socket.cpp')
-rw-r--r--src/socket/Socket.cpp132
1 files changed, 97 insertions, 35 deletions
diff --git a/src/socket/Socket.cpp b/src/socket/Socket.cpp
index 7fb4d89b..daeb6fa2 100644
--- a/src/socket/Socket.cpp
+++ b/src/socket/Socket.cpp
@@ -15,11 +15,12 @@
*/
#include <errno.h>
+#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
+#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <stdlib.h>
#include <string>
#include <sstream>
@@ -33,51 +34,104 @@
namespace Ingen {
namespace Socket {
-bool
-Socket::open_unix(const std::string& uri, const std::string& path)
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif
+
+Socket::Socket(Type t)
+ : _type(t)
+ , _addr(NULL)
+ , _addr_len(0)
+ , _sock(-1)
{
- if ((_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- return false;
+ switch (t) {
+ case UNIX:
+ _sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ break;
+ case TCP:
+ _sock = socket(AF_INET, SOCK_STREAM, 0);
+ break;
}
+}
- 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();
+Socket::Socket(Type t,
+ const std::string& uri,
+ struct sockaddr* addr,
+ socklen_t addr_len,
+ int fd)
+ : _type(t)
+ , _uri(uri)
+ , _addr(addr)
+ , _addr_len(addr_len)
+ , _sock(fd)
+{
}
bool
-Socket::open_tcp(const std::string& uri, uint16_t port)
+Socket::set_addr(const std::string& uri)
{
- if ((_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- return false;
+ if (_type == UNIX && uri.substr(0, strlen("unix://")) == "unix://") {
+ const std::string path = uri.substr(strlen("unix://"));
+ 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 true;
+ } else if (_type == TCP && uri.find("://") != std::string::npos) {
+ const std::string no_scheme = uri.substr(uri.find("://") + 4);
+ const size_t port_sep = no_scheme.find(':');
+ if (port_sep == std::string::npos) {
+ return false;
+ }
+
+ const std::string host = no_scheme.substr(0, port_sep);
+ const std::string port = no_scheme.substr(port_sep + 1).c_str();
+
+ struct addrinfo* ainfo;
+ int st = 0;
+ if ((st = getaddrinfo(host.c_str(), port.c_str(), NULL, &ainfo))) {
+ LOG(Raul::error) << "Error in getaddrinfo: "
+ << gai_strerror(st) << std::endl;
+ return false;
+ }
+
+ _uri = uri;
+ _addr = (struct sockaddr*)malloc(ainfo->ai_addrlen);
+ _addr_len = ainfo->ai_addrlen;
+ memcpy(_addr, ainfo->ai_addr, ainfo->ai_addrlen);
+ return true;
}
+ 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(const std::string& uri)
+{
+ if (set_addr(uri) && ::bind(_sock, _addr, _addr_len) != -1) {
+ return true;
+ }
+
+ LOG(Raul::error) << "Failed to bind " << _uri
+ << ": " << strerror(errno) << std::endl;
+ return false;
}
bool
-Socket::bind()
+Socket::connect(const std::string& uri)
{
- if (::bind(_sock, _addr, _addr_len) == -1) {
- LOG(Raul::error) << "Failed to bind " << _uri
- << ": " << strerror(errno) << std::endl;
- return false;
+ if (set_addr(uri) && ::connect(_sock, _addr, _addr_len) != -1) {
+ return true;
}
- return true;
+
+ LOG(Raul::error) << "Failed to connect " << _uri
+ << ": " << strerror(errno) << std::endl;
+ return false;
}
bool
@@ -92,10 +146,9 @@ Socket::listen()
}
}
-int
+SharedPtr<Socket>
Socket::accept()
{
- // Accept connection from client
socklen_t client_addr_len = _addr_len;
struct sockaddr* client_addr = (struct sockaddr*)calloc(
1, client_addr_len);
@@ -104,9 +157,18 @@ Socket::accept()
if (conn == -1) {
LOG(Raul::error) << "Error accepting connection: "
<< strerror(errno) << std::endl;
+ return SharedPtr<Socket>();
}
- return conn;
+ std::string client_uri = _uri;
+ char host[NI_MAXHOST];
+ if (getnameinfo(client_addr, client_addr_len,
+ host, sizeof(host), NULL, 0, 0)) {
+ client_uri = _uri.substr(0, _uri.find(":") + 1) + host;
+ }
+
+ return SharedPtr<Socket>(
+ new Socket(_type, client_uri, client_addr, client_addr_len, conn));
}
void