From 94a1c4fa10c6af71600048e43b148f8e8b8ab8b2 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Fri, 24 Jul 2015 20:42:22 +0800 Subject: [PATCH] use blocking IPC --- src/android.c | 176 ++++++++----------------------------------------- src/android.h | 45 ------------- src/common.h | 2 +- src/local.c | 68 +++++++------------ src/tunnel.c | 10 +++ src/udprelay.c | 53 ++------------- 6 files changed, 69 insertions(+), 285 deletions(-) delete mode 100644 src/android.h diff --git a/src/android.c b/src/android.c index 3283711b..793d6e6c 100644 --- a/src/android.c +++ b/src/android.c @@ -44,151 +44,22 @@ #include "netutils.h" #include "utils.h" -#include "android.h" -#ifndef EAGAIN -#define EAGAIN EWOULDBLOCK -#endif - -#ifndef EWOULDBLOCK -#define EWOULDBLOCK EAGAIN -#endif - -static void remote_recv_cb(EV_P_ ev_io *w, int revents); -static void remote_send_cb(EV_P_ ev_io *w, int revents); - -static struct remote * new_remote(int fd, int timeout); - -static void free_remote(struct remote *remote); -static void close_and_free_remote(EV_P_ struct remote *remote); - -extern int verbose; - -static int setnonblocking(int fd) -{ - int flags; - if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { - flags = 0; - } - return fcntl(fd, F_SETFL, flags | O_NONBLOCK); -} - -static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) -{ - struct remote_ctx *remote_ctx = (struct remote_ctx *)(((void *)watcher) - sizeof(ev_io)); - struct remote *remote = remote_ctx->remote; - - if (verbose) { - LOGI("[android] IPC connection timeout"); - } - - remote->protect_cb(-1, remote->data); - close_and_free_remote(EV_A_ remote); -} - -static void remote_recv_cb(EV_P_ ev_io *w, int revents) -{ - struct remote_ctx *remote_recv_ctx = (struct remote_ctx *)w; - struct remote *remote = remote_recv_ctx->remote; - - int fd, ret = 0; - - if (ancil_recv_fd(remote->fd, &fd)) { - ERROR("[android] ancil_recv_fd"); - ret = -1; - } - - if (fd != remote->protect_fd) { - ret = -1; - } - - remote->protect_cb(ret, remote->data); - close_and_free_remote(EV_A_ remote); -} - -static void remote_send_cb(EV_P_ ev_io *w, int revents) -{ - struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w; - struct remote *remote = remote_send_ctx->remote; - - struct sockaddr_storage addr; - socklen_t len = sizeof addr; - - int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len); - - if (r == 0) { - ev_io_stop(EV_A_ & remote_send_ctx->io); - ev_timer_stop(EV_A_ & remote_send_ctx->watcher); - - if (ancil_send_fd(remote->fd, remote->protect_fd)) { - ERROR("[android] ancil_send_fd"); - remote->protect_cb(-1, remote->data); - close_and_free_remote(EV_A_ remote); - return; - } - - ev_io_start(EV_A_ & remote->recv_ctx->io); - ev_timer_start(EV_A_ & remote->recv_ctx->watcher); - } else { - ERROR("[android] getpeername"); - remote->protect_cb(-1, remote->data); - close_and_free_remote(EV_A_ remote); - return; - } -} - - -static struct remote * new_remote(int fd, int timeout) -{ - struct remote *remote; - remote = malloc(sizeof(struct remote)); - remote->recv_ctx = malloc(sizeof(struct remote_ctx)); - remote->send_ctx = malloc(sizeof(struct remote_ctx)); - remote->fd = fd; - ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ); - ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE); - ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, timeout, 0); - ev_timer_init(&remote->recv_ctx->watcher, remote_timeout_cb, timeout, 0); - remote->recv_ctx->remote = remote; - remote->send_ctx->remote = remote; - return remote; -} - -static void free_remote(struct remote *remote) -{ - if (remote != NULL) { - free(remote->recv_ctx); - free(remote->send_ctx); - free(remote); - } -} - -static void close_and_free_remote(EV_P_ struct remote *remote) -{ - if (remote != NULL) { - ev_timer_stop(EV_A_ & remote->send_ctx->watcher); - ev_timer_stop(EV_A_ & remote->recv_ctx->watcher); - ev_io_stop(EV_A_ & remote->send_ctx->io); - ev_io_stop(EV_A_ & remote->recv_ctx->io); - close(remote->fd); - free_remote(remote); - } -} - -int protect_socket(void (*protect_cb)(int ret, void *data), void *data, int fd) { - // Inilitialize ev loop - struct ev_loop *loop = EV_DEFAULT; - - int remotefd; +int protect_socket(int fd) { + int sock, recvfd; struct sockaddr_un addr; - if ( (remotefd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - LOGE("[android] socket() failed: %s (socket fd = %d)\n", strerror(errno), remotefd); + if ( (sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + LOGE("[android] socket() failed: %s (socket fd = %d)\n", strerror(errno), sock); return -1; } - // Setup - setnonblocking(remotefd); + // Set timeout to 100us + struct timeval tv; + tv.tv_sec = 0; /* 30 Secs Timeout */ + tv.tv_usec = 1000; // Not init'ing this can cause strange errors + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); const char path[] = "/data/data/com.github.shadowsocks/protect_path"; @@ -196,18 +67,27 @@ int protect_socket(void (*protect_cb)(int ret, void *data), void *data, int fd) addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1); - struct remote *remote = new_remote(remotefd, 1); + if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + LOGE("[android] connect() failed: %s (socket fd = %d)\n", strerror(errno), sock); + close(sock); + return -1; + } - remote->protect_fd = fd; - remote->protect_cb = protect_cb; - remote->data = data; + if (ancil_send_fd(sock, fd)) { + ERROR("[android] ancil_send_fd"); + close(sock); + return -1; + } - connect(remotefd, (struct sockaddr*)&addr, sizeof(addr)); + char ret = 0; - // listen to remote connected event - ev_io_start(EV_A_ & remote->send_ctx->io); - ev_timer_start(EV_A_ & remote->send_ctx->watcher); + if (recv(sock, &ret, 1, 0) == -1) { + ERROR("[android] recv"); + close(sock); + return -1; + } - return 0; + close(sock); + return ret; } diff --git a/src/android.h b/src/android.h deleted file mode 100644 index d7d430d8..00000000 --- a/src/android.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * android.h - Define Android IPC's buffers and callbacks - * - * Copyright (C) 2013 - 2015, Max Lv - * - * This file is part of the shadowsocks-libev. - * - * shadowsocks-libev is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * shadowsocks-libev 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shadowsocks-libev; see the file COPYING. If not, see - * . - */ - -#ifndef _ANDROID_H -#define _ANDROID_H - -#include - -#include "common.h" - -struct remote_ctx { - ev_io io; - ev_timer watcher; - struct remote *remote; -}; - -struct remote { - int fd; - int protect_fd; - void *data; - void (*protect_cb)(int ret, void *data); - struct remote_ctx *recv_ctx; - struct remote_ctx *send_ctx; -}; - -#endif // _ANDROID_H diff --git a/src/common.h b/src/common.h index 8e8492d3..43a3183d 100644 --- a/src/common.h +++ b/src/common.h @@ -59,7 +59,7 @@ int init_udprelay(const char *server_host, const char *server_port, void free_udprelay(void); #ifdef ANDROID -int protect_socket(void (*protect_cb)(int ret, void *data), void *data, int fd); +int protect_socket(int fd); #endif #endif // _COMMON_H diff --git a/src/local.c b/src/local.c index a784b794..8f7c239b 100644 --- a/src/local.c +++ b/src/local.c @@ -98,8 +98,6 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents); static void accept_cb(EV_P_ ev_io *w, int revents); static void signal_cb(EV_P_ ev_signal *w, int revents); -static void protect_cb(int ret, void *data); - static int create_and_bind(const char *addr, const char *port); static struct remote * create_remote(struct listen_ctx *listener, struct sockaddr *addr); static void free_remote(struct remote *remote); @@ -197,26 +195,6 @@ static void free_connections(struct ev_loop *loop) } } -#ifdef ANDROID -static void protect_cb(int ret, void *data) { - struct remote_ctx *remote_ctx = (struct remote_ctx *)data; - struct remote *remote = remote_ctx->remote; - struct server *server = remote->server; - - if (verbose) { - LOGI("[android] one connection protected"); - } - - if (ret == -1) { - close_and_free_remote(EV_DEFAULT, remote); - close_and_free_server(EV_DEFAULT, server); - return; - } - - server_recv_cb(EV_DEFAULT, &server->recv_ctx->io, EV_CUSTOM); -} -#endif - static void server_recv_cb(EV_P_ ev_io *w, int revents) { struct server_ctx *server_recv_ctx = (struct server_ctx *)w; @@ -232,25 +210,23 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) ssize_t r; - if (revents != EV_CUSTOM) { - r = recv(server->fd, buf, BUF_SIZE, 0); + r = recv(server->fd, buf, BUF_SIZE, 0); - if (r == 0) { - // connection closed + if (r == 0) { + // connection closed + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } else if (r < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // no data + // continue to wait for recv + return; + } else { + ERROR("server_recv_cb_recv"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; - } else if (r < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // no data - // continue to wait for recv - return; - } else { - ERROR("server_recv_cb_recv"); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - return; - } } } @@ -263,14 +239,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) return; } -#ifdef ANDROID - if (revents != EV_CUSTOM) { - ev_io_stop(EV_A_ & server_recv_ctx->io); - protect_socket(protect_cb, (void*)remote, remote->fd); - return; - } -#endif - // insert shadowsocks header if (!remote->direct) { remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, @@ -285,6 +253,16 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) } if (!remote->send_ctx->connected) { + +#ifdef ANDROID + if (protect_socket(remote->fd) == -1) { + ERROR("protect_socket"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } +#endif + remote->buf_idx = 0; remote->buf_len = r; diff --git a/src/tunnel.c b/src/tunnel.c index cd5246d9..f975339c 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -602,6 +602,15 @@ static void accept_cb(EV_P_ ev_io *w, int revents) return; } +#ifdef ANDROID + if (protect_socket(remotefd) == -1) { + ERROR("protect_socket"); + close(remotefd); + return; + } +#endif + + setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); @@ -620,6 +629,7 @@ static void accept_cb(EV_P_ ev_io *w, int revents) server->destaddr = listener->tunnel_addr; server->remote = remote; remote->server = server; + connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); diff --git a/src/udprelay.c b/src/udprelay.c index 7161fd37..6c772b98 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -87,10 +87,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents); static void remote_recv_cb(EV_P_ ev_io *w, int revents); static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents); -#if defined(ANDROID) && !defined(UDPRELAY_TUNNEL) -static void protect_cb(int ret, void *data); -#endif - static char *hash_key(const int af, const struct sockaddr_storage *addr); #ifdef UDPRELAY_REMOTE static void query_resolve_cb(struct sockaddr *addr, void *data); @@ -103,42 +99,6 @@ extern int verbose; static int server_num = 0; static struct server_ctx *server_ctx_list[MAX_REMOTE_NUM] = { NULL }; -#if defined(ANDROID) && !defined(UDPRELAY_TUNNEL) -static struct protect_ctx *new_protect_ctx(char *buf, int buf_len, - const struct sockaddr *addr, int addr_len) { - struct protect_ctx *protect_ctx = (struct protect_ctx *)malloc(sizeof(struct protect_ctx)); - memset(protect_ctx, 0, sizeof(struct protect_ctx)); - - protect_ctx->buf = malloc(buf_len); - memcpy(protect_ctx->buf, buf, buf_len); - protect_ctx->buf_len = buf_len; - - memcpy(&protect_ctx->addr, (const char*)addr, addr_len); - protect_ctx->addr_len = addr_len; - - return protect_ctx; -} - -static void free_protect_ctx(struct protect_ctx *protect_ctx) { - if (protect_ctx != NULL) { - free(protect_ctx->buf); - free(protect_ctx); - } -} - -static void protect_cb(int ret, void *data) { - struct protect_ctx *protect_ctx = (struct protect_ctx*)data; - if (ret != -1) { - int s = sendto(protect_ctx->remote_ctx->fd, protect_ctx->buf, - protect_ctx->buf_len, 0, (const struct sockaddr *)&protect_ctx->addr, protect_ctx->addr_len); - if (s == -1) { - ERROR("[udp] sendto_remote"); - } - } - free_protect_ctx(protect_ctx); -} -#endif - #ifndef __MINGW32__ static int setnonblocking(int fd) { @@ -1099,17 +1059,18 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method); -#if defined(ANDROID) && !defined(UDPRELAY_TUNNEL) - struct protect_ctx *protect_ctx = new_protect_ctx(buf, buf_len, remote_addr, remote_addr_len); - protect_ctx->remote_ctx = remote_ctx; - protect_socket(protect_cb, (void*)protect_ctx, remote_ctx->fd); -#else +#if defined(ANDROID) + if (protect_socket(remote_ctx->fd) == -1) { + ERROR("protect_socket"); + close_and_free_remote(EV_A_ remote_ctx); + goto CLEAN_UP; + } +#endif int s = sendto(remote_ctx->fd, buf, buf_len, 0, remote_addr, remote_addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); } -#endif #else