Skip to content

Commit

Permalink
Fix tunfd as discussion at pull 913
Browse files Browse the repository at this point in the history
  • Loading branch information
madafoo committed Mar 14, 2016
1 parent 83d1a43 commit 80688c2
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 101 deletions.
70 changes: 38 additions & 32 deletions admin/angel/Core.c
Expand Up @@ -44,10 +44,7 @@
#include "tunnel/IpTunnel_admin.h"
#include "tunnel/RouteGen_admin.h"
#include "util/events/EventBase.h"
#ifndef win32
#include "util/events/libuv/FileNo_admin.h"
#include "util/events/FileNo.h"
#endif
#include "util/events/Pipe.h"
#include "util/events/Timeout.h"
#include "util/Hex.h"
Expand Down Expand Up @@ -110,33 +107,10 @@ struct Context
struct EventBase* base;
struct NetCore* nc;
struct IpTunnel* ipTunnel;
#ifndef win32
struct FileNo_admin* fileno;
#endif
Identity
};

#ifndef win32
static void onFileNoReceived(void* vcontext, enum FileNo_Type type, int fileno)
{
struct Context* ctx = Identity_check((struct Context*) vcontext);
struct Jmp jmp;
Jmp_try(jmp) {
struct Pipe* p = Pipe_forFiles(fileno, fileno, ctx->base, &jmp.handler, ctx->alloc);
p->logger = ctx->logger;
if (type == FileNo_Type_ANDROID) {
struct AndroidWrapper* aw = AndroidWrapper_new(ctx->alloc, ctx->logger);
Iface_plumb(&aw->externalIf, &p->iface);
Iface_plumb(&aw->internalIf, &ctx->nc->tunAdapt->tunIf);
} else {
Iface_plumb(&p->iface, &ctx->nc->tunAdapt->tunIf);
}
} Jmp_catch {
Log_warn(ctx->logger, "Failed to configure fileno [%s]", jmp.message);
}
}
#endif

static void shutdown(void* vcontext)
{
struct Context* context = Identity_check((struct Context*) vcontext);
Expand Down Expand Up @@ -188,6 +162,37 @@ static void initTunnel2(String* desiredDeviceName,
NetDev_setMTU(assignedTunName, DEFAULT_MTU, ctx->logger, eh);
}

static void initTunfd(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
struct Context* ctx = Identity_check((struct Context*) vcontext);
struct Jmp jmp;
Jmp_try(jmp) {
int64_t* tunfd = Dict_getInt(args, String_CONST("tunfd"));
int64_t* tuntype = Dict_getInt(args, String_CONST("type"));
if (!tunfd || *tunfd < 0) {
String* error = String_printf(requestAlloc, "Invalid tunfd");
sendResponse(error, ctx->admin, txid, requestAlloc);
return;
}
int fileno = *tunfd;
int type = (*tuntype) ? *tuntype : FileNo_Type_NORMAL;
struct Pipe* p = Pipe_forFiles(fileno, fileno, ctx->base, &jmp.handler, ctx->alloc);
p->logger = ctx->logger;
if (type == FileNo_Type_ANDROID) {
struct AndroidWrapper* aw = AndroidWrapper_new(ctx->alloc, ctx->logger);
Iface_plumb(&aw->externalIf, &p->iface);
Iface_plumb(&aw->internalIf, &ctx->nc->tunAdapt->tunIf);
} else {
Iface_plumb(&p->iface, &ctx->nc->tunAdapt->tunIf);
}
sendResponse(String_CONST("none"), ctx->admin, txid, requestAlloc);
} Jmp_catch {
String* error = String_printf(requestAlloc, "Failed to configure tunnel [%s]", jmp.message);
sendResponse(error, ctx->admin, txid, requestAlloc);
return;
}
}

static void initTunnel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
struct Context* const ctx = Identity_check((struct Context*) vcontext);
Expand Down Expand Up @@ -227,10 +232,8 @@ void Core_init(struct Allocator* alloc,
Iface_plumb(&nc->tunAdapt->ipTunnelIf, &ipTunnel->tunInterface);
Iface_plumb(&nc->upper->ipTunnelIf, &ipTunnel->nodeInterface);

#ifndef win32
struct FileNo_admin* fileno = FileNo_admin_new(admin, alloc, eventBase,
logger, eh, onFileNoReceived);
#endif
logger, eh);

// The link between the Pathfinder and the core needs to be asynchronous.
struct Pathfinder* pf = Pathfinder_register(alloc, logger, eventBase, rand, admin);
Expand Down Expand Up @@ -264,10 +267,7 @@ void Core_init(struct Allocator* alloc,
ctx->base = eventBase;
ctx->ipTunnel = ipTunnel;
ctx->nc = nc;
#ifndef win32
ctx->fileno = fileno;
ctx->fileno->userData = ctx;
#endif

Admin_registerFunction("Core_exit", adminExit, ctx, true, NULL, admin);

Expand All @@ -277,6 +277,12 @@ void Core_init(struct Allocator* alloc,
((struct Admin_FunctionArg[]) {
{ .name = "desiredTunName", .required = 0, .type = "String" }
}), admin);

Admin_registerFunction("Core_initTunfd", initTunfd, ctx, true,
((struct Admin_FunctionArg[]) {
{ .name = "tunfd", .required = 1, .type = "Int" },
{ .name = "type", .required = 0, .type = "Int" }
}), admin);
}

int Core_main(int argc, char** argv)
Expand Down
24 changes: 13 additions & 11 deletions client/Configurator.c
Expand Up @@ -263,22 +263,24 @@ static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Co
}

// Setup the interface.
int64_t* tunfd = Dict_getInt(ifaceConf, String_CONST("tunfd"));
String* type = Dict_getString(ifaceConf, String_CONST("tunfdType"));
String* tunfd = Dict_getString(ifaceConf, String_CONST("tunfd"));
String* device = Dict_getString(ifaceConf, String_CONST("tunDevice"));

if (tunfd && *tunfd && !device) {
return;
}

Dict* args = Dict_new(tempAlloc);
if (tunfd && *tunfd) {
if (tunfd && device) {
Dict_putString(args, String_CONST("path"), device, tempAlloc);
if (type) {
Dict_putString(args, String_CONST("type"),
String_new(type->bytes, tempAlloc), tempAlloc);
Dict_putString(args, String_CONST("type"),
String_new(tunfd->bytes, tempAlloc), tempAlloc);
Dict* res = NULL;
rpcCall0(String_CONST("FileNo_import"), args, ctx, tempAlloc, &res, false);
if (res) {
Dict* args = Dict_new(tempAlloc);
int64_t* tunfd = Dict_getInt(res, String_CONST("tunfd"));
int64_t* type = Dict_getInt(res, String_CONST("type"));
Dict_putInt(args, String_CONST("tunfd"), *tunfd, tempAlloc);
Dict_putInt(args, String_CONST("type"), *type, tempAlloc);
rpcCall0(String_CONST("Core_initTunfd"), args, ctx, tempAlloc, NULL, false);
}
rpcCall0(String_CONST("FileNo_import"), args, ctx, tempAlloc, NULL, false);
} else {
if (device) {
Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc);
Expand Down
10 changes: 4 additions & 6 deletions client/cjdroute2.c
Expand Up @@ -260,12 +260,10 @@ static int genconf(struct Random* rand, bool eth)
" {\n"
" // The type of interface (only TUNInterface is supported for now)\n"
" \"type\": \"TUNInterface\"\n"
" // The tun device is a file description or not.\n"
" // \"tunfd\" : 0,\n"
" // If tunfd value is not 0, the tunDevice should be used as the pipe path\n"
" // used to transfer the tun file description.\n"
" // The type of tunfd (only \"android\" is supported for now)\n"
" // \"tunfdType\" : \"\"\n"
" // The type of tunfd (only \"android\" for now)\n"
" // If \"android\" here, the tunDevice should be used as the pipe path\n"
" // to transfer the tun file description.\n"
" // \"tunfd\" : \"android\"\n"
#ifndef __APPLE__
"\n"
" // The name of a persistent TUN device to use.\n"
Expand Down
22 changes: 14 additions & 8 deletions util/events/FileNo.h
Expand Up @@ -32,7 +32,14 @@ enum FileNo_Type {
FileNo_Type_ANDROID
};

typedef void (* FileNo_callback)(void* context, enum FileNo_Type type, int fileno);
struct FileNo_Promise;
struct FileNo_Promise
{
void (* callback)(struct FileNo_Promise* promise,
int fileno);
void* userData;
struct Allocator* alloc;
};

struct FileNo
{
Expand All @@ -45,19 +52,18 @@ struct FileNo

struct EventBase* const base;

FileNo_callback onFileNoReceived;
struct Allocator* alloc;

struct Log* logger;
};

#define FileNo_PADDING_AMOUNT 512
#define FileNo_BUFFER_CAP 4000

struct FileNo* FileNo_new(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* userAlloc,
FileNo_callback recv_cb);
struct FileNo_Promise* FileNo_import(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* alloc);

#endif
73 changes: 55 additions & 18 deletions util/events/libuv/FileNo.c
Expand Up @@ -23,6 +23,14 @@
#include <inttypes.h>
#include <stdio.h>

struct FileNoContext
{
struct FileNo_Promise pub;
struct FileNo* fileno;

Identity
};

struct FileNo_pvt
{
struct FileNo pub;
Expand All @@ -35,8 +43,6 @@ struct FileNo_pvt

int isActive;

struct Allocator* alloc;

Identity
};

Expand All @@ -59,20 +65,23 @@ static void incoming(uv_pipe_t* stream,
const uv_buf_t* buf,
uv_handle_type pending)
{
struct FileNo_pvt* fileno = Identity_check((struct FileNo_pvt*) stream->data);

// Grab out the allocator which was placed there by allocate()
struct Allocator* alloc = buf->base ? ALLOC(buf->base) : NULL;

Assert_true(pending == UV_UNKNOWN_HANDLE);

if (nread < 0) {
uv_close((uv_handle_t*) stream, onClose);
} else if (fileno->peer.accepted_fd != -1) {
if (fileno->pub.onFileNoReceived) {
fileno->pub.onFileNoReceived(fileno->pub.userData, fileno->pub.type,
fileno->peer.accepted_fd);
#ifndef win32
} else {
struct FileNo_pvt* fileno = Identity_check((struct FileNo_pvt*) stream->data);
if (fileno->peer.accepted_fd != -1) {
struct FileNoContext* fctx = (struct FileNoContext*) fileno->pub.userData;
if (fctx->pub.callback) {
fctx->pub.callback(&fctx->pub, fileno->peer.accepted_fd);
}
}
#endif
}

if (alloc) {
Expand All @@ -86,7 +95,7 @@ static void allocate(uv_handle_t* handle, size_t size, uv_buf_t* buf)
size = FileNo_BUFFER_CAP;
size_t fullSize = size + FileNo_PADDING_AMOUNT;

struct Allocator* child = Allocator_child(pipe->alloc);
struct Allocator* child = Allocator_child(pipe->pub.alloc);
char* buff = Allocator_malloc(child, fullSize);
buff += FileNo_PADDING_AMOUNT;

Expand Down Expand Up @@ -164,12 +173,11 @@ static int closeHandlesOnFree(struct Allocator_OnFreeJob* job)
return Allocator_ONFREE_ASYNC;
}

struct FileNo* FileNo_new(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* userAlloc,
FileNo_callback recv_cb)
static struct FileNo* FileNo_new(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* userAlloc)
{
struct EventBase_pvt* ctx = EventBase_privatize(eb);
struct Allocator* alloc = Allocator_child(userAlloc);
Expand All @@ -180,9 +188,8 @@ struct FileNo* FileNo_new(const char* path,
.pipePath = pathStr->bytes,
.base = eb,
.logger = logger,
.onFileNoReceived = recv_cb
},
.alloc = alloc
.alloc = alloc
}
}));

int ret = uv_pipe_init(ctx->loop, &out->peer, 1);
Expand Down Expand Up @@ -211,6 +218,7 @@ struct FileNo* FileNo_new(const char* path,
Except_throw(eh, "uv_listen() failed [%s] for pipe [%s]",
uv_strerror(ret), out->pub.pipePath);
}

return &out->pub;
}

Expand All @@ -219,3 +227,32 @@ struct FileNo* FileNo_new(const char* path,

return &out->pub;
}

static struct FileNo_Promise* FileNo_newFile(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* alloc)
{
struct FileNo* fn = FileNo_new(path, eb, eh, logger, alloc);
struct FileNoContext* fctx = Allocator_clone(fn->alloc, (&(struct FileNoContext) {
.pub = {
.alloc = fn->alloc
},
.fileno = fn
}));
Identity_set(fctx);

fn->userData = fctx;

return &fctx->pub;
}

struct FileNo_Promise* FileNo_import(const char* path,
struct EventBase* eb,
struct Except* eh,
struct Log* logger,
struct Allocator* alloc)
{
return FileNo_newFile(path, eb, eh, logger, alloc);
}

0 comments on commit 80688c2

Please sign in to comment.