From 6180d6954c41a2412c166e5a9e8a2851cf39c6d1 Mon Sep 17 00:00:00 2001 From: Mikael Hallendal Date: Wed, 19 Feb 2003 08:13:31 +0000 Subject: 2003-02-19 Mikael Hallendal * dbus/dbus-server.c (dbus_server_listen): Support tcp: addresses. * dbus/dbus-transport-unix.c (_dbus_transport_new_for_tcp_socket): Added to create a transport connecting using a tcp/ip socket. * dbus/dbus-sysdeps.c (_dbus_connect_tcp_socket): Added to connect to a tcp socket at given host and port. (_dbus_listen_tcp_socket): added to listen on tcp socket for given hostname and port. * dbus/dbus-server.c (dbus_server_listen): Support tcp: addresses. * dbus/dbus-server-unix.c (_dbus_server_new_for_tcp_socket): Added to create a server listening on a TCP/IP socket. --- dbus/dbus-server-unix.c | 35 ++++++++++ dbus/dbus-server-unix.h | 3 + dbus/dbus-server.c | 26 +++++++- dbus/dbus-sysdeps.c | 157 +++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-sysdeps.h | 6 ++ dbus/dbus-transport-unix.c | 37 +++++++++++ dbus/dbus-transport-unix.h | 5 +- dbus/dbus-transport.c | 29 +++++++++ 8 files changed, 296 insertions(+), 2 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 6da70537..a6635ddc 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -264,5 +264,40 @@ _dbus_server_new_for_domain_socket (const char *path, return server; } +/** + * Creates a new server listening on the given hostname and port + * + * @param host the hostname to listen on. + * @param port the port to listen on. + * @param result location to store reason for failure. + * @returns the new server, or #NULL on failure. + */ +DBusServer* +_dbus_server_new_for_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result) +{ + DBusServer *server; + int listen_fd; + + listen_fd = _dbus_listen_tcp_socket (host, port, result); + _dbus_fd_set_close_on_exec (listen_fd); + + if (listen_fd < 0) + return NULL; + + server = _dbus_server_new_for_fd (listen_fd); + if (server == NULL) + { + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); + close (listen_fd); + return NULL; + } + + return server; + + +} + /** @} */ diff --git a/dbus/dbus-server-unix.h b/dbus/dbus-server-unix.h index 43614cc0..ebd017d0 100644 --- a/dbus/dbus-server-unix.h +++ b/dbus/dbus-server-unix.h @@ -31,6 +31,9 @@ DBUS_BEGIN_DECLS; DBusServer* _dbus_server_new_for_fd (int fd); DBusServer* _dbus_server_new_for_domain_socket (const char *path, DBusResultCode *result); +DBusServer* _dbus_server_new_for_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result); DBUS_END_DECLS; diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 862aead5..fd03423e 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -19,7 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - */ + */ +#include #include "dbus-server.h" #include "dbus-server-unix.h" #ifdef DBUS_BUILD_TESTS @@ -225,6 +226,29 @@ dbus_server_listen (const char *address, server = _dbus_server_new_for_domain_socket (path, result); + if (server) + break; + } + else if (strcmp (method, "tcp") == 0) + { + const char *host = dbus_address_entry_get_value (entries[i], "host"); + const char *port = dbus_address_entry_get_value (entries[i], "port"); + DBusString str; + long lport; + dbus_bool_t sresult; + + if (port == NULL) + goto bad_address; + + _dbus_string_init_const (&str, port); + sresult = _dbus_string_parse_int (&str, 0, &lport, NULL); + _dbus_string_free (&str); + + if (sresult == FALSE || lport <= 0 || lport > 65535) + goto bad_address; + + server = _dbus_server_new_for_tcp_socket (host, lport, result); + if (server) break; } diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 316d278c..bf4793eb 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #ifdef HAVE_WRITEV #include @@ -394,6 +396,161 @@ _dbus_listen_unix_socket (const char *path, return listen_fd; } +/** + * Creates a socket and connects to a socket at the given host + * and port. The connection fd is returned, and is set up as + * nonblocking. + * + * @param host the host name to connect to + * @param port the prot to connect to + * @param result return location for error code + * @returns connection file descriptor or -1 on error + */ +int +_dbus_connect_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result) +{ + int fd; + struct sockaddr_in addr; + struct hostent *he; + struct in_addr *haddr; + + fd = socket (AF_INET, SOCK_STREAM, 0); + + if (fd < 0) + { + dbus_set_result (result, + _dbus_result_from_errno (errno)); + + _dbus_verbose ("Failed to create socket: %s\n", + _dbus_strerror (errno)); + + return -1; + } + + if (host == NULL) + host = "localhost"; + + he = gethostbyname (host); + if (he == NULL) + { + dbus_set_result (result, + _dbus_result_from_errno (errno)); + _dbus_verbose ("Failed to lookup hostname: %s\n", + host); + return -1; + } + + haddr = ((struct in_addr *) (he->h_addr_list)[0]); + + _DBUS_ZERO (addr); + memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons (port); + + if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0) + { + dbus_set_result (result, + _dbus_result_from_errno (errno)); + + _dbus_verbose ("Failed to connect to socket %s: %s:%d\n", + host, port, _dbus_strerror (errno)); + + close (fd); + fd = -1; + + return -1; + } + + if (!_dbus_set_fd_nonblocking (fd, result)) + { + close (fd); + fd = -1; + + return -1; + } + + return fd; +} + +/** + * Creates a socket and binds it to the given path, + * then listens on the socket. The socket is + * set to be nonblocking. + * + * @param host the host name to listen on + * @param port the prot to listen on + * @param result return location for errors + * @returns the listening file descriptor or -1 on error + */ +int +_dbus_listen_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result) +{ + int listen_fd; + struct sockaddr_in addr; + struct hostent *he; + struct in_addr *haddr; + + listen_fd = socket (AF_INET, SOCK_STREAM, 0); + + if (listen_fd < 0) + { + dbus_set_result (result, _dbus_result_from_errno (errno)); + _dbus_verbose ("Failed to create socket \"%s:%d\": %s\n", + host, port, _dbus_strerror (errno)); + return -1; + } + + if (host == NULL) + host = "localhost"; + + he = gethostbyname (host); + if (he == NULL) + { + dbus_set_result (result, + _dbus_result_from_errno (errno)); + _dbus_verbose ("Failed to lookup hostname: %s\n", + host); + return -1; + } + + haddr = ((struct in_addr *) (he->h_addr_list)[0]); + + _DBUS_ZERO (addr); + memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons (port); + + if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr))) + { + dbus_set_result (result, _dbus_result_from_errno (errno)); + _dbus_verbose ("Failed to bind socket \"%s:%d\": %s\n", + host, port, _dbus_strerror (errno)); + close (listen_fd); + return -1; + } + + if (listen (listen_fd, 30 /* backlog */) < 0) + { + dbus_set_result (result, _dbus_result_from_errno (errno)); + _dbus_verbose ("Failed to listen on socket \"%s:%d\": %s\n", + host, port, _dbus_strerror (errno)); + close (listen_fd); + return -1; + } + + if (!_dbus_set_fd_nonblocking (listen_fd, result)) + { + close (listen_fd); + return -1; + } + + return listen_fd; +} + /* try to read a single byte and return #TRUE if we read it * and it's equal to nul. */ diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 50da679c..3c95227d 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -79,6 +79,12 @@ int _dbus_connect_unix_socket (const char *path, DBusResultCode *result); int _dbus_listen_unix_socket (const char *path, DBusResultCode *result); +int _dbus_connect_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result); +int _dbus_listen_tcp_socket (const char *host, + dbus_uint32_t port, + DBusResultCode *result); int _dbus_accept (int listen_fd); dbus_bool_t _dbus_read_credentials_unix_socket (int client_fd, diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 84703345..c5dce8d7 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -1118,6 +1118,43 @@ _dbus_transport_new_for_domain_socket (const char *path, return transport; } +/** + * Creates a new transport for the given hostname and port. + * + * @param host the host to connect to + * @param port the port to connect to + * @param server #TRUE if this transport is on the server side of a connection + * @param result location to store reason for failure. + * @returns a new transport, or #NULL on failure. + */ +DBusTransport* +_dbus_transport_new_for_tcp_socket (const char *host, + dbus_int32_t port, + dbus_bool_t server, + DBusResultCode *result) +{ + int fd; + DBusTransport *transport; + + fd = _dbus_connect_tcp_socket (host, port, result); + if (fd < 0) + return NULL; + + _dbus_fd_set_close_on_exec (fd); + + _dbus_verbose ("Successfully connected to tcp socket %s:%d\n", + host, port); + + transport = _dbus_transport_new_for_fd (fd, server); + if (transport == NULL) + { + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); + close (fd); + fd = -1; + } + + return transport; +} /** @} */ diff --git a/dbus/dbus-transport-unix.h b/dbus/dbus-transport-unix.h index 0c7d04fa..1fd0134d 100644 --- a/dbus/dbus-transport-unix.h +++ b/dbus/dbus-transport-unix.h @@ -32,7 +32,10 @@ DBusTransport* _dbus_transport_new_for_fd (int fd, DBusTransport* _dbus_transport_new_for_domain_socket (const char *path, dbus_bool_t server, DBusResultCode *result); - +DBusTransport* _dbus_transport_new_for_tcp_socket (const char *host, + dbus_int32_t port, + dbus_bool_t server, + DBusResultCode *result); DBUS_END_DECLS; diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 5a25a675..1f34b3bb 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -199,6 +199,35 @@ _dbus_transport_open (const char *address, transport = _dbus_transport_new_for_domain_socket (path, FALSE, result); } + else if (strcmp (method, "tcp") == 0) + { + const char *host = dbus_address_entry_get_value (entries[i], "host"); + const char *port = dbus_address_entry_get_value (entries[i], "port"); + DBusString str; + long lport; + dbus_bool_t sresult; + + if (port == NULL) + goto bad_address; + + _dbus_string_init_const (&str, port); + sresult = _dbus_string_parse_int (&str, 0, &lport, NULL); + _dbus_string_free (&str); + + if (sresult == FALSE || lport <= 0 || lport > 65535) + goto bad_address; + + transport = _dbus_transport_new_for_tcp_socket (host, lport, FALSE, result); + } + else if (strcmp (method, "tcp") == 0) + { + const char *path = dbus_address_entry_get_value (entries[i], "path"); + + if (path == NULL) + goto bad_address; + + transport = _dbus_transport_new_for_domain_socket (path, FALSE, result); + } #ifdef DBUS_BUILD_TESTS else if (strcmp (method, "debug") == 0) { -- cgit