diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2007-12-13 19:07:36 +0000 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2007-12-13 19:07:36 +0000 |
commit | 0a377c514a6d0d5eb3b723977007c682748d1baf (patch) | |
tree | 5a1841be16323ae219403f259fc0825c4139465e /serial | |
parent | 2e6b3caf16b973b4bcf71ae1f31d5c8276939f70 (diff) |
Add TCP connection support for serial proxy
Diffstat (limited to 'serial')
-rw-r--r-- | serial/manager.c | 105 |
1 files changed, 94 insertions, 11 deletions
diff --git a/serial/manager.c b/serial/manager.c index b45958b9..9c9827d4 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -105,6 +105,7 @@ static struct { typedef enum { TTY_PROXY, UNIX_SOCKET_PROXY, + TCP_SOCKET_PROXY, UNKNOWN_PROXY_TYPE = 0xFF } proxy_type_t; @@ -113,6 +114,7 @@ struct proxy { bdaddr_t dst; char *uuid128; /* UUID 128 */ char *address; /* TTY or Unix socket name */ + short int port; /* TCP port */ proxy_type_t type; /* TTY or Unix socket */ struct termios sys_ti; /* Default TTY setting */ struct termios proxy_ti; /* Proxy TTY settings */ @@ -586,7 +588,7 @@ static void record_reply(DBusPendingCall *call, void *data) err = rfcomm_connect(pc); if (err < 0) { error("RFCOMM connection failed"); - error_connection_attempt_failed(pc->conn, + error_connection_attempt_failed(pc->conn, pc->msg, -err); goto fail; } @@ -657,7 +659,7 @@ static void handles_reply(DBusPendingCall *call, void *data) /* FIXME : forward error as is */ if (dbus_error_has_name(&derr, "org.bluez.Error.ConnectionAttemptFailed")) - error_connection_attempt_failed(pc->conn, + error_connection_attempt_failed(pc->conn, pc->msg, EIO); else error_not_supported(pc->conn, pc->msg); @@ -667,7 +669,7 @@ static void handles_reply(DBusPendingCall *call, void *data) dbus_error_free(&derr); goto fail; } - + if (!dbus_message_get_args(reply, &derr, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len, DBUS_TYPE_INVALID)) { @@ -1287,6 +1289,45 @@ static inline int unix_socket_connect(const char *address) return sk; } +static int tcp_socket_connect(const char *address) +{ + struct sockaddr_in addr; + int err, sk; + unsigned short int port; + + memset(&addr, 0, sizeof(addr)); + + if (strncmp(address, "localhost", 9) != 0) { + error("Address should have the form localhost:port."); + return -1; + } + port = atoi(strchr(address, ':') + 1); + if (port <= 0) { + error("Invalid port '%d'.", port); + return -1; + } + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(port); + + sk = socket(PF_INET, SOCK_STREAM, 0); + if (sk < 0) { + err = errno; + error("TCP socket(%s) create failed %s(%d)", address, + strerror(err), err); + return -err; + } + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + error("TCP socket(%s) connect failed: %s(%d)", + address, strerror(err), err); + close(sk); + errno = err; + return -err; + } + return sk; +} + static inline int tty_open(const char *tty, struct termios *ti) { int err, sk; @@ -1337,10 +1378,19 @@ static gboolean connect_event(GIOChannel *chan, bacpy(&prx->dst, &raddr.rc_bdaddr); - if (prx->type == UNIX_SOCKET_PROXY) + switch (prx->type) { + case UNIX_SOCKET_PROXY: lsk = unix_socket_connect(prx->address); - else + break; + case TTY_PROXY: lsk = tty_open(prx->address, &prx->proxy_ti); + break; + case TCP_SOCKET_PROXY: + lsk = tcp_socket_connect(prx->address); + break; + default: + lsk = -1; + } if (lsk < 0) { close(rsk); @@ -1753,6 +1803,25 @@ static int proxy_socket_register(bdaddr_t *src, const char *uuid128, return ret; } +static int proxy_tcp_register(bdaddr_t *src, const char *uuid128, + const char *address, char *outpath, size_t size) +{ + struct proxy *prx; + int ret; + + prx = g_new0(struct proxy, 1); + prx->address = g_strdup(address); + prx->uuid128 = g_strdup(uuid128); + prx->type = TCP_SOCKET_PROXY; + bacpy(&prx->src, src); + + ret = register_proxy_object(prx, outpath, size); + if (ret < 0) + proxy_free(prx); + + return ret; +} + static proxy_type_t addr2type(const char *address) { struct stat st; @@ -1763,6 +1832,8 @@ static proxy_type_t addr2type(const char *address) * it refers to abstract namespace. 'x00' will be used * to represent the null byte. */ + if (strncmp("localhost:", address, 10) == 0) + return TCP_SOCKET_PROXY; if (strncmp("x00", address, 3) != 0) return UNKNOWN_PROXY_TYPE; else @@ -1833,13 +1904,22 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (type != TTY_PROXY) + switch (type) { + case UNIX_SOCKET_PROXY: ret = proxy_socket_register(&src, uuid128, - address, path, sizeof(path)); - else + address, path, sizeof(path)); + break; + case TTY_PROXY: ret = proxy_tty_register(&src, uuid128, address, NULL, path, sizeof(path)); - + break; + case TCP_SOCKET_PROXY: + ret = proxy_tcp_register(&src, uuid128, address, + path, sizeof(path)); + break; + default: + ret = -1; + } if (ret < 0) { dbus_message_unref(reply); return error_failed(conn, msg, "Create object path failed"); @@ -2065,7 +2145,7 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, pending = find_pending_connect_by_pattern(bda, pattern); if (!pending) - return error_does_not_exist(conn, msg, + return error_does_not_exist(conn, msg, "No such connection request"); reply = dbus_message_new_method_return(msg); @@ -2087,7 +2167,7 @@ static void proxy_path_free(gpointer data, gpointer udata) if (dbus_connection_get_object_user_data(conn, path, (void *) &prx) && prx) { struct termios *ti; - + ti = (prx->type == TTY_PROXY ? &prx->proxy_ti : NULL); proxy_store(&prx->src, prx->uuid128, prx->address, NULL, prx->channel, 0, ti); @@ -2244,6 +2324,9 @@ static void parse_proxy(char *key, char *value, void *data) case UNIX_SOCKET_PROXY: proxy_socket_register(&src, uuid128, key, NULL, 0); break; + case TCP_SOCKET_PROXY: + proxy_tcp_register(&src, uuid128, key, NULL, 0); + break; default: return; } |