Max Lv
9 years ago
3 changed files with 299 additions and 13 deletions
Unified View
Diff Options
-
203src/android.c
-
45src/android.h
-
64src/local.c
@ -0,0 +1,203 @@ |
|||||
|
/* |
||||
|
* android.c - Setup IPC for shadowsocks-android |
||||
|
* |
||||
|
* Copyright (C) 2013 - 2015, Max Lv <max.c.lv@gmail.com> |
||||
|
* |
||||
|
* 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 |
||||
|
* <http://www.gnu.org/licenses/>. |
||||
|
*/ |
||||
|
|
||||
|
#include <sys/stat.h> |
||||
|
#include <sys/types.h> |
||||
|
#include <fcntl.h> |
||||
|
#include <locale.h> |
||||
|
#include <signal.h> |
||||
|
#include <string.h> |
||||
|
#include <strings.h> |
||||
|
#include <unistd.h> |
||||
|
|
||||
|
#ifdef HAVE_CONFIG_H |
||||
|
#include "config.h" |
||||
|
#endif |
||||
|
|
||||
|
#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); |
||||
|
|
||||
|
int verbose = 0; |
||||
|
|
||||
|
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(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; |
||||
|
|
||||
|
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; |
||||
|
struct sockaddr_un addr; |
||||
|
|
||||
|
// Setup |
||||
|
setnonblocking(remotefd); |
||||
|
|
||||
|
if ( (remotefd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { |
||||
|
LOGE("[android] socket() failed: %s (socket fd = %d)\n", strerror(errno), remotefd); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
memset(&addr, 0, sizeof(addr)); |
||||
|
addr.sun_family = AF_UNIX; |
||||
|
strncpy(addr.sun_path, "/data/data/com.github.shadowsocks/protect_path", sizeof(addr.sun_path)-1); |
||||
|
|
||||
|
struct remote *remote = new_remote(remotefd, 100); |
||||
|
|
||||
|
remote->protect_fd = fd; |
||||
|
remote->protect_cb = protect_cb; |
||||
|
remote->data = data; |
||||
|
|
||||
|
if (connect(remotefd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { |
||||
|
LOGE("[android] connect() failed: %s (fd = %d)\n", strerror(errno), remotefd); |
||||
|
close(remotefd); |
||||
|
return -1 |
||||
|
} |
||||
|
|
||||
|
// listen to remote connected event |
||||
|
ev_io_start(EV_A_ & remote->send_ctx->io); |
||||
|
ev_timer_start(EV_A_ & remote->send_ctx->watcher); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
@ -0,0 +1,45 @@ |
|||||
|
/* |
||||
|
* android.h - Define Android IPC's buffers and callbacks |
||||
|
* |
||||
|
* Copyright (C) 2013 - 2015, Max Lv <max.c.lv@gmail.com> |
||||
|
* |
||||
|
* 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 |
||||
|
* <http://www.gnu.org/licenses/>. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef _ANDROID_H |
||||
|
#define _ANDROID_H |
||||
|
|
||||
|
#include <ev.h> |
||||
|
|
||||
|
#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 |
Write
Preview
Loading…
Cancel
Save