Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

mostly done, need a few tests now

  • Loading branch information...
commit e8fb37a66a5b7c621c343781da16c2b0236bbafe 1 parent 79b6924
Caleb James DeLisle authored
View
50 admin/Configurator.c
@@ -98,26 +98,38 @@ static void authorizedPasswords(List* list, struct Context* ctx)
static void udpInterface(Dict* config, struct Context* ctx)
{
Dict* udp = Dict_getDict(config, String_CONST("UDPInterface"));
- Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
- if (connectTo) {
- struct Dict_Entry* entry = *connectTo;
- while (entry != NULL) {
- String* key = (String*) entry->key;
- if (entry->val->type != Object_DICT) {
- Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
- "is not a dictionary type.", key->bytes);
- exit(-1);
- }
- Dict* value = entry->val->as.dictionary;
-
- Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
-
- struct Allocator* perCallAlloc = ctx->alloc->child(ctx->alloc);
- Dict_putString(value, String_CONST("address"), key, perCallAlloc);
- rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
- perCallAlloc->free(perCallAlloc);
- entry = entry->next;
+ if (udp) {
+ // Setup the interface.
+ String* bindStr = Dict_getString(udp, String_CONST("bind"));
+ Dict* d = Dict_new(ctx->alloc);
+ if (bindStr) {
+ Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
+ }
+ rpcCall(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc);
+
+ // Make the connections.
+ Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
+ if (connectTo) {
+ struct Dict_Entry* entry = *connectTo;
+ while (entry != NULL) {
+ String* key = (String*) entry->key;
+ if (entry->val->type != Object_DICT) {
+ Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
+ "is not a dictionary type.", key->bytes);
+ exit(-1);
+ }
+ Dict* value = entry->val->as.dictionary;
+
+ Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
+
+ struct Allocator* perCallAlloc = ctx->alloc->child(ctx->alloc);
+ Dict_putString(value, String_CONST("address"), key, perCallAlloc);
+ rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
+ perCallAlloc->free(perCallAlloc);
+
+ entry = entry->next;
+ }
}
}
}
View
35 cjdroute.c
@@ -20,7 +20,6 @@
#include "crypto/Crypto.h"
#include "crypto/CryptoAuth.h"
#include "crypto/CryptoAuth_benchmark.h"
-#include "dht/CJDHTConstants.h"
#include "dht/ReplyModule.h"
#include "dht/SerializationModule.h"
#include "dht/dhtcore/RouterModule_admin.h"
@@ -29,7 +28,7 @@
#include "interface/Interface.h"
#include "interface/TUNInterface.h"
#include "interface/TUNConfigurator.h"
-#include "interface/UDPInterface.h"
+#include "interface/UDPInterface_admin.h"
#include "io/Reader.h"
#include "io/FileReader.h"
#include "io/Writer.h"
@@ -38,7 +37,6 @@
#include "benc/serialization/json/JsonBencSerializer.h"
#include "util/Log.h"
#include "memory/MallocAllocator.h"
-#include "memory/BufferAllocator.h"
#include "memory/Allocator.h"
#include "net/Ducttape.h"
#include "net/DefaultInterfaceController.h"
@@ -83,12 +81,6 @@ struct Context
struct Admin* admin;
};
-struct UDPInterfaceContext
-{
- struct Context* context;
- struct UDPInterface* udpContext;
-};
-
struct User
{
uint64_t trust;
@@ -379,7 +371,7 @@ static void security(List* config, struct Log* logger, struct ExceptionHandler*
static void adminPing(Dict* input, void* vadmin, String* txid)
{
- Dict d = Dict_CONST(CJDHTConstants_QUERY, String_OBJ(String_CONST("pong")), NULL);
+ Dict d = Dict_CONST(String_CONST("q"), String_OBJ(String_CONST("pong")), NULL);
Admin_sendMessage(&d, txid, (struct Admin*) vadmin);
}
@@ -568,24 +560,11 @@ int main(int argc, char** argv)
sp,
context.allocator);
- Dict* interfaces = Dict_getDict(&config, String_CONST("interfaces"));
-
- Dict* udpConf = Dict_getDict(interfaces, String_CONST("UDPInterface"));
- if (udpConf) {
- String* bindStr = Dict_getString(udpConf, String_CONST("bind"));
- UDPInterface_new(context.base,
- (bindStr) ? bindStr->bytes : NULL,
- context.allocator,
- context.eHandler,
- context.logger,
- ifController,
- context.admin);
- }
-
- if (udpConf == NULL) {
- fprintf(stderr, "No interfaces configured to connect to.\n");
- return -1;
- }
+ UDPInterface_admin_register(context.base,
+ context.allocator,
+ context.logger,
+ context.admin,
+ ifController);
// pid file
String* pidFile = Dict_getString(&config, String_CONST("pidFile"));
View
67 exception/Jmp.h
@@ -0,0 +1,67 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef Jmp_H
+#define Jmp_H
+
+#include "exception/ExceptionHandler.h"
+#include <setjmp.h>
+
+/**
+ * setjmp based exception handler.
+ *
+ * struct Jmp jmp;
+ * Jmp_try(jmp) {
+ * Do_somethingDangerous(&jmp.handler);
+ * } Jmp_catch {
+ * printf("failed %d %s", jmp.code, jmp.message);
+ * }
+ *
+ * Provides an easy way to implement the most basic try/catch functionality.
+ * the jmp structure must not be used for anything outside of the try block,
+ * calling jmp.handler.exception outside of a try block is undefined behavior.
+ */
+
+struct Jmp {
+ /** The exception handler which will trigger the entry into the catch block. */
+ struct ExceptionHandler handler;
+
+ /** The exception message if in the catch block, otherwise undefined. */
+ char* message;
+
+ /** The code if inside of the catch block, otherwise undefined. */
+ int code;
+
+ /** Internal setjmp buffer. */
+ jmp_buf buf;
+};
+
+/** Internal callback, this should not be called directly. */
+Gcc_NORETURN
+static void Jmp_callback(char* message, int code, struct ExceptionHandler* handler)
+{
+ struct Jmp* jmp = (struct Jmp*) handler;
+ jmp->message = message;
+ jmp->code = code;
+ longjmp(jmp->buf, 1);
+}
+
+#define Jmp_try(jmp) \
+ jmp.handler.exception = Jmp_callback; \
+ if (!setjmp(jmp.buf))
+// CHECKFILES_IGNORE squigly bracket will be added by the caller.
+
+#define Jmp_catch else
+
+#endif
View
1  interface/CMakeLists.txt
@@ -21,6 +21,7 @@ endif()
add_library(interface
UDPInterface.c
+ UDPInterface_admin.c
${tunif}
${tunconf}
InterfaceConnector.c
View
179 interface/UDPInterface.c
@@ -12,22 +12,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "admin/Admin.h"
#include "crypto/Crypto.h"
#include "exception/ExceptionHandler.h"
#include "interface/Interface.h"
#include "interface/UDPInterface.h"
#include "memory/Allocator.h"
-#include "memory/BufferAllocator.h"
#include "net/InterfaceController.h"
-#include "util/Bits.h"
-#include "util/Endian.h"
-#include "util/Base32.h"
#include "wire/Message.h"
#include "wire/Error.h"
-
#include "util/Assert.h"
-#include <event2/event.h>
#ifdef WIN32
#include <winsock.h>
@@ -41,6 +34,7 @@
#include <netinet/in.h>
#endif
+#include <event2/event.h>
#include <sys/types.h>
#include <errno.h>
@@ -50,10 +44,6 @@
#define MAX_INTERFACES 256
-#ifdef Log_DEBUG
- #define SCRAMBLE_KEYS
-#endif
-
struct UDPInterface
{
struct Interface interface;
@@ -74,34 +64,12 @@ struct UDPInterface
struct Log* logger;
struct InterfaceController* ic;
-
- struct Admin* admin;
-
- #ifdef SCRAMBLE_KEYS
- uint8_t xorValue[InterfaceController_KEY_SIZE];
- #endif
};
#define EFFECTIVE_KEY_SIZE \
((InterfaceController_KEY_SIZE > sizeof(struct sockaddr_in)) \
? sizeof(struct sockaddr_in) : InterfaceController_KEY_SIZE)
-/**
- * This exists entirely for testing, it allows a call to be made which will alter all keys,
- * effectively the same as making everyone's ip address change.
- */
-#ifdef SCRAMBLE_KEYS
- static inline void xorkey(uint8_t key[InterfaceController_KEY_SIZE],
- struct UDPInterface* udpif)
- {
- for (int i = 0; i < InterfaceController_KEY_SIZE; i++) {
- key[i] ^= udpif->xorValue[i];
- }
- }
-#else
- #define xorkey(a, b)
-#endif
-
static inline void sockaddrForKey(struct sockaddr_in* sockaddr,
uint8_t key[InterfaceController_KEY_SIZE],
struct UDPInterface* udpif)
@@ -110,7 +78,6 @@ static inline void sockaddrForKey(struct sockaddr_in* sockaddr,
memset(sockaddr, 0, sizeof(struct sockaddr_in));
}
Bits_memcpyConst(sockaddr, key, EFFECTIVE_KEY_SIZE);
- xorkey(key, udpif);
}
static inline void keyForSockaddr(uint8_t key[InterfaceController_KEY_SIZE],
@@ -121,7 +88,6 @@ static inline void keyForSockaddr(uint8_t key[InterfaceController_KEY_SIZE],
memset(key, 0, InterfaceController_KEY_SIZE);
}
Bits_memcpyConst(key, sockaddr, EFFECTIVE_KEY_SIZE);
- xorkey(key, udpif);
}
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
@@ -190,11 +156,7 @@ static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
0,
(struct sockaddr*) &addrStore,
&addrLen);
- /*
- Log_debug(context->logger,
- "Got message from peer on port %u\n",
- Endian_bigEndianToHost16(((struct sockaddr_in*) &addrStore)->sin_port));
- */
+
if (addrLen != context->addrLen) {
return;
}
@@ -242,82 +204,12 @@ int UDPInterface_beginConnection(const char* address,
}
}
-static void beginConnectionAdmin(Dict* args, void* vcontext, String* txid)
-{
- struct UDPInterface* udpif = (struct UDPInterface*) vcontext;
-
- String* password = Dict_getString(args, String_CONST("password"));
- String* publicKey = Dict_getString(args, String_CONST("publicKey"));
- String* address = Dict_getString(args, String_CONST("address"));
- String* error = NULL;
-
- uint8_t pkBytes[32];
-
- if (!publicKey || publicKey->len < 52) {
- error = String_CONST("publicKey is too short, must be 52 characters long.");
-
- } else if (Base32_decode(pkBytes, 32, (uint8_t*)publicKey->bytes, 52) != 32) {
- error = String_CONST("failed to parse publicKey.");
-
- } else {
- switch (UDPInterface_beginConnection(address->bytes, pkBytes, password, udpif)) {
- case UDPInterface_beginConnection_OUT_OF_SPACE:
- error = String_CONST("no more space to register with the switch.");
- break;
- case UDPInterface_beginConnection_BAD_KEY:
- error = String_CONST("invalid cjdns public key.");
- break;
- case UDPInterface_beginConnection_BAD_ADDRESS:
- error = String_CONST("unable to parse ip address and port.");
- break;
- case UDPInterface_beginConnection_ADDRESS_MISMATCH:
- error = String_CONST("different address type than this socket is bound to.");
- break;
- case 0:
- error = String_CONST("none");
- break;
- default:
- error = String_CONST("unknown error");
- }
- }
-
- Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
- Admin_sendMessage(&out, txid, udpif->admin);
-}
-
-#ifdef SCRAMBLE_KEYS
-static void scrambleKeys(Dict* args, void* vcontext, String* txid)
-{
- struct UDPInterface* udpif = (struct UDPInterface*) vcontext;
-
- uint8_t key[InterfaceController_KEY_SIZE];
- String* xorVal = Dict_getString(args, String_CONST("xorValue"));
- String* error = String_CONST("none");
- #define WRONG_LENGTH(x) String_CONST("xorValue length needs to be " #x " characters long")
- if (!xorVal || xorVal->len != InterfaceController_KEY_SIZE * 2) {
- error = WRONG_LENGTH((InterfaceController_KEY_SIZE * 2));
-
- } else {
- int ret =
- Hex_decode(key, InterfaceController_KEY_SIZE, (uint8_t*) xorVal->bytes, xorVal->len);
- if (ret < 0) {
- error = String_CONST("Failed to parse hex");
- } else {
- Bits_memcpyConst(udpif->xorValue, key, InterfaceController_KEY_SIZE);
- }
- }
- Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
- Admin_sendMessage(&out, txid, udpif->admin);
-}
-#endif
-
struct UDPInterface* UDPInterface_new(struct event_base* base,
const char* bindAddr,
struct Allocator* allocator,
struct ExceptionHandler* exHandler,
struct Log* logger,
- struct InterfaceController* ic,
- struct Admin* admin)
+ struct InterfaceController* ic)
{
struct UDPInterface* context = allocator->malloc(sizeof(struct UDPInterface), allocator);
Bits_memcpyConst(context, (&(struct UDPInterface) {
@@ -327,8 +219,7 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
.allocator = allocator
},
.logger = logger,
- .ic = ic,
- .admin = admin
+ .ic = ic
}), sizeof(struct UDPInterface));
int addrFam;
@@ -339,26 +230,17 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
(struct sockaddr*) &addr,
(int*) &context->addrLen))
{
- exHandler->exception(__FILE__ " UDPInterface_new() Failed to parse address.",
- -1, exHandler);
- return NULL;
+ exHandler->exception("failed to parse address",
+ UDPInterface_new_PARSE_ADDRESS_FAILED, exHandler);
}
addrFam = addr.ss_family;
// This is because the key size is only 8 bytes.
// Expanding the key size just for IPv6 doesn't make a lot of sense
// when ethernet, 802.11 and ipv4 are ok with a shorter key size
- if (addr.ss_family == AF_INET6) {
- exHandler->exception(__FILE__ " UDPInterface_new() IPv6 transport not supported.",
- -4,
- exHandler);
- }
-
- // This could easily be ported to non-IPv4 but I'm not willing to claim support until
- // there's some actual testing.
- if (context->addrLen != sizeof(struct sockaddr_in)) {
- exHandler->exception(__FILE__ " UDPInterface_new() Unexpected address length.",
- -5,
+ if (addr.ss_family != AF_INET || context->addrLen != sizeof(struct sockaddr_in)) {
+ exHandler->exception("only IPv4 is supported",
+ UDPInterface_new_PROTOCOL_NOT_SUPPORTED,
exHandler);
}
@@ -369,16 +251,14 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
context->socket = socket(addrFam, SOCK_DGRAM, 0);
if (context->socket == -1) {
- exHandler->exception(__FILE__ " UDPInterface_new() call to socket() failed.",
- -3, exHandler);
- return NULL;
+ exHandler->exception("call to socket() failed.",
+ UDPInterface_new_SOCKET_FAILED, exHandler);
}
if (bindAddr != NULL) {
if (bind(context->socket, (struct sockaddr*) &addr, context->addrLen)) {
- exHandler->exception(__FILE__ " UDPInterface_new() Failed to bind socket.",
- EVUTIL_SOCKET_ERROR(), exHandler);
- return NULL;
+ exHandler->exception("call to bind() failed.",
+ UDPInterface_new_BIND_FAILED, exHandler);
}
}
@@ -387,41 +267,14 @@ struct UDPInterface* UDPInterface_new(struct event_base* base,
context->incomingMessageEvent =
event_new(base, context->socket, EV_READ | EV_PERSIST, handleEvent, context);
- if (context->incomingMessageEvent == NULL) {
- exHandler->exception(__FILE__ " UDPInterface_new() failed to create UDPInterface event.",
- -4, exHandler);
- return NULL;
+ if (!context->incomingMessageEvent || event_add(context->incomingMessageEvent, NULL)) {
+ exHandler->exception("failed to create UDPInterface event",
+ UDPInterface_new_FAILED_CREATING_EVENT, exHandler);
}
- event_add(context->incomingMessageEvent, NULL);
-
allocator->onFree(freeEvent, context->incomingMessageEvent, allocator);
InterfaceController_registerInterface(&context->interface, ic);
- struct Admin_FunctionArg adma[3] = {
- { .name = "password", .required = 0, .type = "String" },
- { .name = "publicKey", .required = 1, .type = "String" },
- { .name = "address", .required = 1, .type = "String" },
- };
- Admin_registerFunction("UDPInterface_beginConnection",
- beginConnectionAdmin,
- context,
- true,
- adma,
- admin);
-
- #ifdef SCRAMBLE_KEYS
- struct Admin_FunctionArg scrambleArgs[1] = {
- { .name = "xorValue", .required = 1, .type = "String" }
- };
- Admin_registerFunction("UDPInterface_scrambleKeys",
- scrambleKeys,
- context,
- true,
- scrambleArgs,
- admin);
- #endif
-
return context;
}
View
18 interface/UDPInterface.h
@@ -29,20 +29,30 @@ struct UDPInterface;
* @param bindAddr a string representation of the address to bind to such as "0.0.0.0:12345".
* @param allocator the memory allocator for this message.
* @param exHandler the handler to deal with whatever exception arises.
+ * Exceptions:
+ * UDPInterface_new_PARSE_ADDRESS_FAILED Couldn't parse bindAddr as an ip address and port
+ * UDPInterface_new_FAILED_CREATING_EVENT Failed creating the event or registering it with
+ * the libevent event base (shouldn't happen)
+ * UDPInterface_new_SOCKET_FAILED Failed calling socket(), check EVUTIL_SOCKET_ERROR()
+ * UDPInterface_new_PROTOCOL_NOT_SUPPORTED Only IPv4 is supported as an underlying protocol
+ * UDPInterface_new_BIND_FAILED Failed calling bind(), check EVUTIL_SOCKET_ERROR()
+ *
* @param logger
- * @param admin the administration module which will have UDPInterface_beginConnection()
- * registered with it.
* @param ic the controller which this interface should register with
* and use when starting connections.
* @return a new UDPInterface.
*/
+#define UDPInterface_new_PARSE_ADDRESS_FAILED -1
+#define UDPInterface_new_FAILED_CREATING_EVENT -2
+#define UDPInterface_new_SOCKET_FAILED -3
+#define UDPInterface_new_PROTOCOL_NOT_SUPPORTED -4
+#define UDPInterface_new_BIND_FAILED -5
struct UDPInterface* UDPInterface_new(struct event_base* base,
const char* bindAddr,
struct Allocator* allocator,
struct ExceptionHandler* exHandler,
struct Log* logger,
- struct InterfaceController* ic,
- struct Admin* admin);
+ struct InterfaceController* ic);
/**
* Begin an outgoing connection.
View
321 interface/UDPInterface_admin.c
@@ -12,254 +12,56 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "benc/Int.h"
#include "admin/Admin.h"
-#include "crypto/Crypto.h"
-#include "exception/ExceptionHandler.h"
-#include "interface/Interface.h"
+#include "exception/Jmp.h"
#include "interface/UDPInterface.h"
#include "memory/Allocator.h"
-#include "memory/BufferAllocator.h"
#include "net/InterfaceController.h"
-#include "util/Bits.h"
-#include "util/Endian.h"
#include "util/Base32.h"
-#include "wire/Message.h"
-#include "wire/Error.h"
-#include "util/Assert.h"
-#include <event2/event.h>
-
-#ifdef WIN32
- #include <winsock.h>
- #undef interface
- #define EMSGSIZE WSAEMSGSIZE
- #define ENOBUFS WSAENOBUFS
- #define EWOULDBLOCK WSAEWOULDBLOCK
-#else
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-#endif
-
-#include <sys/types.h>
#include <errno.h>
+#include <event2/event.h>
-#define MAX_PACKET_SIZE 8192
-
-#define PADDING 512
-
-#define MAX_INTERFACES 256
-
-#ifdef Log_DEBUG
- #define SCRAMBLE_KEYS
-#endif
-
-struct UDPInterface
+struct Context
{
- struct Interface interface;
-
- evutil_socket_t socket;
-
- /**
- * The event registered with libevent.
- * Needed only so it can be freed.
- */
- struct event* incomingMessageEvent;
-
- /** Used to tell what address type is being used. */
- ev_socklen_t addrLen;
-
- uint8_t messageBuff[PADDING + MAX_PACKET_SIZE];
-
+ struct event_base* eventBase;
+ struct Allocator* allocator;
struct Log* logger;
-
- struct InterfaceController* ic;
-
struct Admin* admin;
+ struct InterfaceController* ic;
- #ifdef SCRAMBLE_KEYS
- uint8_t xorValue[InterfaceController_KEY_SIZE];
- #endif
+ uint32_t ifCount;
+ struct UDPInterface** ifaces;
};
-#define EFFECTIVE_KEY_SIZE \
- ((InterfaceController_KEY_SIZE > sizeof(struct sockaddr_in)) \
- ? sizeof(struct sockaddr_in) : InterfaceController_KEY_SIZE)
-
-/**
- * This exists entirely for testing, it allows a call to be made which will alter all keys,
- * effectively the same as making everyone's ip address change.
- */
-#ifdef SCRAMBLE_KEYS
- static inline void xorkey(uint8_t key[InterfaceController_KEY_SIZE],
- struct UDPInterface* udpif)
- {
- for (int i = 0; i < InterfaceController_KEY_SIZE; i++) {
- key[i] ^= udpif->xorValue[i];
- }
- }
-#else
- #define xorkey(a, b)
-#endif
-
-static inline void sockaddrForKey(struct sockaddr_in* sockaddr,
- uint8_t key[InterfaceController_KEY_SIZE],
- struct UDPInterface* udpif)
-{
- if (EFFECTIVE_KEY_SIZE < sizeof(struct sockaddr_in)) {
- memset(sockaddr, 0, sizeof(struct sockaddr_in));
- }
- Bits_memcpyConst(sockaddr, key, EFFECTIVE_KEY_SIZE);
- xorkey(key, udpif);
-}
-
-static inline void keyForSockaddr(uint8_t key[InterfaceController_KEY_SIZE],
- struct sockaddr_in* sockaddr,
- struct UDPInterface* udpif)
-{
- if (EFFECTIVE_KEY_SIZE < InterfaceController_KEY_SIZE) {
- memset(key, 0, InterfaceController_KEY_SIZE);
- }
- Bits_memcpyConst(key, sockaddr, EFFECTIVE_KEY_SIZE);
- xorkey(key, udpif);
-}
-
-static uint8_t sendMessage(struct Message* message, struct Interface* iface)
-{
- struct UDPInterface* context = iface->senderContext;
- Assert_true(&context->interface == iface);
-
- struct sockaddr_in sin;
- sockaddrForKey(&sin, message->bytes, context);
- Bits_memcpyConst(&sin, message->bytes, InterfaceController_KEY_SIZE);
- Message_shift(message, -InterfaceController_KEY_SIZE);
-
- if (sendto(context->socket,
- message->bytes,
- message->length,
- 0,
- (struct sockaddr*) &sin,
- context->addrLen) < 0)
- {
- switch (EVUTIL_SOCKET_ERROR()) {
- case EMSGSIZE:
- return Error_OVERSIZE_MESSAGE;
-
- case ENOBUFS:
- case EAGAIN:
- #if EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
- #endif
- return Error_LINK_LIMIT_EXCEEDED;
-
- default:;
- Log_info(context->logger, "Got error sending to socket errno=%d",
- EVUTIL_SOCKET_ERROR());
- }
- }
- return 0;
-}
-
-/**
- * Release the event used by this module.
- *
- * @param vevent a void pointer cast of the event structure.
- */
-static void freeEvent(void* vevent)
-{
- event_del((struct event*) vevent);
- event_free((struct event*) vevent);
-}
-
-static void handleEvent(evutil_socket_t socket, short eventType, void* vcontext)
-{
- struct UDPInterface* context = (struct UDPInterface*) vcontext;
-
- struct Message message =
- { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };
-
- struct sockaddr_storage addrStore;
- memset(&addrStore, 0, sizeof(struct sockaddr_storage));
- ev_socklen_t addrLen = sizeof(struct sockaddr_storage);
-
- // Start writing InterfaceController_KEY_SIZE after the beginning,
- // keyForSockaddr() will write the key there.
- int rc = recvfrom(socket,
- message.bytes + InterfaceController_KEY_SIZE,
- message.length - InterfaceController_KEY_SIZE,
- 0,
- (struct sockaddr*) &addrStore,
- &addrLen);
- /*
- Log_debug(context->logger,
- "Got message from peer on port %u\n",
- Endian_bigEndianToHost16(((struct sockaddr_in*) &addrStore)->sin_port));
- */
- if (addrLen != context->addrLen) {
- return;
- }
- if (rc < 0) {
- return;
- }
- message.length = rc + InterfaceController_KEY_SIZE;
-
- keyForSockaddr(message.bytes, (struct sockaddr_in*) &addrStore, context);
-
- context->interface.receiveMessage(&message, &context->interface);
-}
-
-int UDPInterface_admin_beginConnection(const char* address,
- uint8_t cryptoKey[32],
- String* password,
- struct UDPInterface* udpif)
+static void beginConnection(Dict* args, void* vcontext, String* txid)
{
- struct sockaddr_storage addr;
- ev_socklen_t addrLen = sizeof(struct sockaddr_storage);
- memset(&addr, 0, addrLen);
- if (evutil_parse_sockaddr_port(address, (struct sockaddr*) &addr, (int*) &addrLen)) {
- return UDPInterface_beginConnection_BAD_ADDRESS;
- }
- if (addrLen != udpif->addrLen) {
- return UDPInterface_beginConnection_ADDRESS_MISMATCH;
- }
-
- uint8_t key[InterfaceController_KEY_SIZE];
- keyForSockaddr(key, (struct sockaddr_in*) &addr, udpif);
- int ret =
- InterfaceController_insertEndpoint(key, cryptoKey, password, &udpif->interface, udpif->ic);
- switch(ret) {
- case 0:
- return 0;
-
- case InterfaceController_registerInterface_BAD_KEY:
- return UDPInterface_beginConnection_BAD_KEY;
-
- case InterfaceController_registerInterface_OUT_OF_SPACE:
- return UDPInterface_beginConnection_OUT_OF_SPACE;
-
- default:
- return UDPInterface_beginConnection_UNKNOWN_ERROR;
- }
-}
-
-static void beginConnectionAdmin(Dict* args, void* vcontext, String* txid)
-{
- struct UDPInterface* udpif = (struct UDPInterface*) vcontext;
+ struct Context* ctx = vcontext;
String* password = Dict_getString(args, String_CONST("password"));
String* publicKey = Dict_getString(args, String_CONST("publicKey"));
String* address = Dict_getString(args, String_CONST("address"));
+ int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber"));
+ uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
String* error = NULL;
uint8_t pkBytes[32];
- if (!publicKey || publicKey->len < 52) {
+ if (ctx->ifCount == 0) {
+ error = String_CONST("no interfaces are setup, call UDPInterface_new() first");
+
+ } else if (interfaceNumber && (*interfaceNumber >= ctx->ifCount || *interfaceNumber < 0)) {
+ error = String_CONST("invalid interfaceNumber");
+
+ } else if (!publicKey || publicKey->len < 52) {
error = String_CONST("publicKey is too short, must be 52 characters long.");
} else if (Base32_decode(pkBytes, 32, (uint8_t*)publicKey->bytes, 52) != 32) {
error = String_CONST("failed to parse publicKey.");
} else {
+ struct UDPInterface* udpif = ctx->ifaces[ifNum];
switch (UDPInterface_beginConnection(address->bytes, pkBytes, password, udpif)) {
case UDPInterface_beginConnection_OUT_OF_SPACE:
error = String_CONST("no more space to register with the switch.");
@@ -282,41 +84,76 @@ static void beginConnectionAdmin(Dict* args, void* vcontext, String* txid)
}
Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
- Admin_sendMessage(&out, txid, udpif->admin);
+ Admin_sendMessage(&out, txid, ctx->admin);
}
-struct UDPInterface* UDPInterface_new(struct event_base* base,
- const char* bindAddr,
- struct Allocator* allocator,
- struct ExceptionHandler* exHandler,
- struct Log* logger,
- struct InterfaceController* ic,
- struct Admin* admin)
-
-struct UDPInterface_Manager
+static void newInterface(Dict* args, void* vcontext, String* txid)
{
- struct event_base* eventBase;
- struct Allocator* allocator;
- struct Log* logger;
- struct Admin* admin;
-};
+ struct Context* const ctx = vcontext;
+ String* const bindAddress = Dict_getString(args, String_CONST("bindAddress"));
+ char* const bindBytes = (bindAddress) ? bindAddress->bytes : NULL;
+ struct Allocator* const alloc = ctx->allocator->child(ctx->allocator);
+
+ struct UDPInterface* udpIf = NULL;
+ struct Jmp jmp;
+ Jmp_try(jmp) {
+ udpIf = UDPInterface_new(
+ ctx->eventBase, bindBytes, alloc, &jmp.handler, ctx->logger, ctx->ic);
+ } Jmp_catch {
+ String* errStr = String_CONST(jmp.message);
+ Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL);
+
+ if (jmp.code == UDPInterface_new_SOCKET_FAILED
+ || jmp.code == UDPInterface_new_BIND_FAILED)
+ {
+ char* err = strerror(EVUTIL_SOCKET_ERROR());
+ Dict out = Dict_CONST(String_CONST("cause"), String_OBJ(String_CONST(err)), out);
+ Admin_sendMessage(&out, txid, ctx->admin);
+ } else {
+ Admin_sendMessage(&out, txid, ctx->admin);
+ }
+
+ alloc->free(alloc);
+ return;
+ }
+
+ ctx->ifaces[ctx->ifCount] = udpIf;
+
+ Dict out = Dict_CONST(
+ String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
+ String_CONST("interfaceNumber"), Int_OBJ(ctx->ifCount), NULL
+ ));
+
+ Admin_sendMessage(&out, txid, ctx->admin);
+ ctx->ifCount++;
+}
void UDPInterface_admin_register(struct event_base* base,
struct Allocator* allocator,
struct Log* logger,
- struct Admin* admin)
+ struct Admin* admin,
+ struct InterfaceController* ic)
{
- struct UDPInterface_Manager* udpman = allocator->malloc(
- sizeof(struct UDPInterface_Manager), allocator, &(struct UDPInterface_Manager) {
+ struct Context* ctx = allocator->clone(
+ sizeof(struct Context), allocator, &(struct Context) {
.eventBase = base,
.allocator = allocator,
.logger = logger,
- .admin = admin
+ .admin = admin,
+ .ic = ic
});
- struct Admin_FunctionArg adma[3] = {
- { .name = "bindAddress", .required = 1, .type = "String" },
- { .name = "password", .required = 1, .type = "String" }
+ struct Admin_FunctionArg adma[1] = {
+ { .name = "bindAddress", .required = 0, .type = "String" }
+ };
+ Admin_registerFunction("UDPInterface_new", newInterface, ctx, true, adma, admin);
+
+ struct Admin_FunctionArg adma2[4] = {
+ { .name = "interfaceNumber", .required = 0, .type = "Int" },
+ { .name = "password", .required = 0, .type = "String" },
+ { .name = "publicKey", .required = 1, .type = "String" },
+ { .name = "address", .required = 1, .type = "String" }
};
- Admin_registerFunction("UDPInterface_new", newInterface, udpman, true, adma, admin);
+ Admin_registerFunction("UDPInterface_beginConnection",
+ beginConnection, ctx, true, adma2, admin);
}
View
31 interface/UDPInterface_admin.h
@@ -0,0 +1,31 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef UDPInterface_admin_H
+#define UDPInterface_admin_H
+
+#include "admin/Admin.h"
+#include "memory/Allocator.h"
+#include "net/InterfaceController.h"
+#include "util/Log.h"
+
+#include <event2/event.h>
+
+void UDPInterface_admin_register(struct event_base* base,
+ struct Allocator* allocator,
+ struct Log* logger,
+ struct Admin* admin,
+ struct InterfaceController* ic);
+
+#endif
Please sign in to comment.
Something went wrong with that request. Please try again.