mirror of
https://github.com/cjdelisle/cjdns
synced 2025-10-06 00:32:50 +02:00
Deleted sybilsim and FakeNetwork which are nolonger being meaningfully maintained
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,7 +17,6 @@
|
|||||||
/cleanconfig*
|
/cleanconfig*
|
||||||
/privatetopublic*
|
/privatetopublic*
|
||||||
/publictoip6*
|
/publictoip6*
|
||||||
/sybilsim*
|
|
||||||
/makekeys*
|
/makekeys*
|
||||||
/mkpasswd*
|
/mkpasswd*
|
||||||
/node_build/node_modules/jshint
|
/node_build/node_modules/jshint
|
||||||
|
49
HACKING.md
49
HACKING.md
@@ -143,51 +143,4 @@ You can do this on Linux using the `perf` utility.
|
|||||||
<ctrl+c>
|
<ctrl+c>
|
||||||
sudo perf script | ../FlameGraph/stackcollapse-perf.pl > ./cjdns-stackcollapse.out
|
sudo perf script | ../FlameGraph/stackcollapse-perf.pl > ./cjdns-stackcollapse.out
|
||||||
../FlameGraph/flamegraph.pl < ./cjdns-stackcollapse.out > ./cjdns-stackcollapse.svg
|
../FlameGraph/flamegraph.pl < ./cjdns-stackcollapse.out > ./cjdns-stackcollapse.svg
|
||||||
chromium ./cjdns-stackcollapse.svg
|
chromium ./cjdns-stackcollapse.svg
|
||||||
|
|
||||||
|
|
||||||
Simulating
|
|
||||||
----------
|
|
||||||
|
|
||||||
Cjdns comes with it's own simulator, it will create *n* nodes and link them together
|
|
||||||
however you wish. It's like having many cjdns processes all running together but they're
|
|
||||||
all in the same process so it is much more efficient. You can set admin credentials on
|
|
||||||
one node and then use the admin tools to access it as you would an ordinary router.
|
|
||||||
You will however need private keys whose public keys hash to ip addresses beginning with
|
|
||||||
fc. To make these keys, use the `makekeys` utility.
|
|
||||||
|
|
||||||
./makekeys | head -n 32 > keys.txt
|
|
||||||
|
|
||||||
To convert the list of keys into a simulator configuration, use `makesim.js`, note there
|
|
||||||
are interesting constants inside of `makesim.js` which you might want to alter.
|
|
||||||
|
|
||||||
node ./tools/lib/makesim.js keys.txt > ~/my-cjdns-simulation.json
|
|
||||||
|
|
||||||
Once you have a simulation setup, you may want to add your admin credentials to one of
|
|
||||||
the nodes so you can inspect it, dump the table, etc...
|
|
||||||
|
|
||||||
Example simulation config entry with added admin block:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
"fc5c:0537:606a:3d7e:c9f0:2103:4dcd:6bc8": {
|
|
||||||
"privateKey": "0dc3d33bbffc2d16c175df463110c6d164714a40d23db2f83539664b7365a5b6",
|
|
||||||
"peers": [
|
|
||||||
"fc1c:84bf:9557:1ce4:4862:fd82:5105:9984",
|
|
||||||
"fc1c:90e4:2953:938b:47cc:65c3:6540:dff6",
|
|
||||||
"fc1b:7ea7:911f:f2d5:7685:ac22:6c4f:8b15"
|
|
||||||
],
|
|
||||||
"admin":
|
|
||||||
{
|
|
||||||
"bind": "127.0.0.1:11234",
|
|
||||||
"password": "the_password_you_will_use_to_connect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
And to start it up (in the debugger):
|
|
||||||
|
|
||||||
gdb ./sybilsim -ex 'r < ~/my-cjdns-simulation.json'
|
|
||||||
|
|
||||||
BUG: Sometimes the simulator doesn't really start up correctly! If you could figure out
|
|
||||||
what is going wrong, your help would be most appreciated, if not, you can just quit and
|
|
||||||
then restart it again and it should start up ok.
|
|
@@ -335,7 +335,6 @@ void Core_init(struct Allocator* alloc,
|
|||||||
struct Admin* admin,
|
struct Admin* admin,
|
||||||
struct Random* rand,
|
struct Random* rand,
|
||||||
struct Except* eh,
|
struct Except* eh,
|
||||||
struct FakeNetwork* fakeNet,
|
|
||||||
bool noSec)
|
bool noSec)
|
||||||
{
|
{
|
||||||
struct Security* sec = NULL;
|
struct Security* sec = NULL;
|
||||||
@@ -376,7 +375,7 @@ void Core_init(struct Allocator* alloc,
|
|||||||
InterfaceController_admin_register(nc->ifController, admin, alloc);
|
InterfaceController_admin_register(nc->ifController, admin, alloc);
|
||||||
SwitchPinger_admin_register(nc->sp, admin, alloc);
|
SwitchPinger_admin_register(nc->sp, admin, alloc);
|
||||||
UDPInterface_admin_register(
|
UDPInterface_admin_register(
|
||||||
eventBase, alloc, logger, admin, nc->ifController, fakeNet, globalConf);
|
eventBase, alloc, logger, admin, nc->ifController, globalConf);
|
||||||
#ifdef HAS_ETH_INTERFACE
|
#ifdef HAS_ETH_INTERFACE
|
||||||
ETHInterface_admin_register(eventBase, alloc, logger, admin, nc->ifController);
|
ETHInterface_admin_register(eventBase, alloc, logger, admin, nc->ifController);
|
||||||
#endif
|
#endif
|
||||||
@@ -535,7 +534,7 @@ int Core_main(int argc, char** argv)
|
|||||||
|
|
||||||
Allocator_free(tempAlloc);
|
Allocator_free(tempAlloc);
|
||||||
|
|
||||||
Core_init(alloc, logger, eventBase, privateKey, admin, rand, eh, NULL, false);
|
Core_init(alloc, logger, eventBase, privateKey, admin, rand, eh, false);
|
||||||
EventBase_beginLoop(eventBase);
|
EventBase_beginLoop(eventBase);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include "exception/Except.h"
|
#include "exception/Except.h"
|
||||||
#include "memory/Allocator.h"
|
#include "memory/Allocator.h"
|
||||||
#include "tunnel/IpTunnel.h"
|
#include "tunnel/IpTunnel.h"
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "util/Linker.h"
|
#include "util/Linker.h"
|
||||||
Linker_require("admin/angel/Core.c")
|
Linker_require("admin/angel/Core.c")
|
||||||
|
|
||||||
@@ -40,7 +39,6 @@ void Core_init(struct Allocator* alloc,
|
|||||||
struct Admin* admin,
|
struct Admin* admin,
|
||||||
struct Random* rand,
|
struct Random* rand,
|
||||||
struct Except* eh,
|
struct Except* eh,
|
||||||
struct FakeNetwork* fakeNet,
|
|
||||||
bool noSec);
|
bool noSec);
|
||||||
|
|
||||||
int Core_main(int argc, char** argv);
|
int Core_main(int argc, char** argv);
|
||||||
|
@@ -48,7 +48,6 @@
|
|||||||
#include "util/events/EventBase.h"
|
#include "util/events/EventBase.h"
|
||||||
#include "util/events/Pipe.h"
|
#include "util/events/Pipe.h"
|
||||||
#include "util/events/Process.h"
|
#include "util/events/Process.h"
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "util/events/libuv/Glock.h"
|
#include "util/events/libuv/Glock.h"
|
||||||
#include "util/Hex.h"
|
#include "util/Hex.h"
|
||||||
#include "util/log/Log.h"
|
#include "util/log/Log.h"
|
||||||
|
@@ -1,457 +0,0 @@
|
|||||||
/* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include "benc/serialization/standard/BencMessageReader.h"
|
|
||||||
#include "benc/serialization/standard/BencMessageWriter.h"
|
|
||||||
#include "benc/serialization/json/JsonBencSerializer.h"
|
|
||||||
#include "benc/serialization/BencSerializer.h"
|
|
||||||
#include "benc/List.h"
|
|
||||||
#include "io/ArrayReader.h"
|
|
||||||
#include "admin/angel/Core.h"
|
|
||||||
#include "client/AdminClient.h"
|
|
||||||
#include "interface/ASynchronizer.h"
|
|
||||||
#include "interface/addressable/AddrIfaceAdapter.h"
|
|
||||||
#include "memory/Allocator.h"
|
|
||||||
#include "util/log/FileWriterLog.h"
|
|
||||||
#include "wire/Message.h"
|
|
||||||
#include "util/events/EventBase.h"
|
|
||||||
#include "crypto/random/Random.h"
|
|
||||||
#include "crypto/random/nanotime/NanotimeEntropyProvider.h"
|
|
||||||
#include "exception/Except.h"
|
|
||||||
#include "util/events/Timeout.h"
|
|
||||||
#include "crypto/Key.h"
|
|
||||||
#include "util/log/Log_impl.h"
|
|
||||||
#include "io/FileReader.h"
|
|
||||||
#include "io/ArrayWriter.h"
|
|
||||||
#include "util/Hex.h"
|
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "util/Hash.h"
|
|
||||||
|
|
||||||
#include <sodium/crypto_scalarmult_curve25519.h>
|
|
||||||
|
|
||||||
#include <unistd.h> // isatty()
|
|
||||||
|
|
||||||
struct NodeContext {
|
|
||||||
struct Sockaddr* boundAddr;
|
|
||||||
struct Allocator* alloc;
|
|
||||||
struct EventBase* base;
|
|
||||||
uint8_t privateKey[32];
|
|
||||||
String* publicKey;
|
|
||||||
struct AdminClient* adminClient;
|
|
||||||
struct Admin* admin;
|
|
||||||
|
|
||||||
char* nodeName;
|
|
||||||
|
|
||||||
/** Admin socket to bind */
|
|
||||||
String* bind;
|
|
||||||
|
|
||||||
/** Admin password */
|
|
||||||
String* pass;
|
|
||||||
|
|
||||||
/** UDPInterface */
|
|
||||||
int ifNum;
|
|
||||||
struct Sockaddr* udpAddr;
|
|
||||||
|
|
||||||
struct Log nodeLog;
|
|
||||||
struct Log* parentLogger;
|
|
||||||
|
|
||||||
List* peers;
|
|
||||||
|
|
||||||
Identity
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RPCCall;
|
|
||||||
|
|
||||||
typedef void (* RPCCallback)(struct RPCCall* call, struct AdminClient_Result* res);
|
|
||||||
|
|
||||||
struct RPCCall
|
|
||||||
{
|
|
||||||
String* func;
|
|
||||||
Dict* args;
|
|
||||||
struct NodeContext* node;
|
|
||||||
RPCCallback callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Map_KEY_TYPE String*
|
|
||||||
#define Map_VALUE_TYPE struct NodeContext*
|
|
||||||
#define Map_NAME OfNodes
|
|
||||||
#define Map_USE_COMPARATOR
|
|
||||||
#define Map_USE_HASH
|
|
||||||
#include "util/Map.h"
|
|
||||||
static inline int Map_OfNodes_compare(String** a, String** b)
|
|
||||||
{
|
|
||||||
return String_compare(*a, *b);
|
|
||||||
}
|
|
||||||
static inline uint32_t Map_OfNodes_hash(String** a)
|
|
||||||
{
|
|
||||||
return Hash_compute(a[0]->bytes, a[0]->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Context
|
|
||||||
{
|
|
||||||
struct RPCCall* rpcCalls;
|
|
||||||
int rpcCallCount;
|
|
||||||
int nextCall;
|
|
||||||
struct Allocator* rpcAlloc;
|
|
||||||
|
|
||||||
struct Random* rand;
|
|
||||||
struct EventBase* base;
|
|
||||||
struct Log* logger;
|
|
||||||
struct Allocator* alloc;
|
|
||||||
|
|
||||||
struct Map_OfNodes nodeMap;
|
|
||||||
Dict* confNodes;
|
|
||||||
|
|
||||||
Identity
|
|
||||||
};
|
|
||||||
|
|
||||||
static String* pubKeyForPriv(uint8_t* privateKey, struct Allocator* alloc)
|
|
||||||
{
|
|
||||||
uint8_t publicKey[32];
|
|
||||||
crypto_scalarmult_curve25519_base(publicKey, privateKey);
|
|
||||||
return Key_stringify(publicKey, alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void printLog(struct Log* log,
|
|
||||||
enum Log_Level logLevel,
|
|
||||||
const char* file,
|
|
||||||
int line,
|
|
||||||
const char* format,
|
|
||||||
va_list args)
|
|
||||||
{
|
|
||||||
struct NodeContext* ctx = Identity_check(
|
|
||||||
(struct NodeContext*) (((char*)log) - offsetof(struct NodeContext, nodeLog))
|
|
||||||
);
|
|
||||||
struct Allocator* alloc = Allocator_child(ctx->alloc);
|
|
||||||
String* str = String_printf(alloc, "[%s] %s", ctx->nodeName, file);
|
|
||||||
ctx->parentLogger->print(ctx->parentLogger, logLevel, str->bytes, line, format, args);
|
|
||||||
Allocator_free(alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct RPCCall* pushCall(struct Context* ctx)
|
|
||||||
{
|
|
||||||
ctx->rpcCalls = Allocator_realloc(ctx->rpcAlloc,
|
|
||||||
ctx->rpcCalls,
|
|
||||||
sizeof(struct RPCCall) * (ctx->rpcCallCount+1));
|
|
||||||
Bits_memset(&ctx->rpcCalls[ctx->rpcCallCount], 0, sizeof(struct RPCCall));
|
|
||||||
return &ctx->rpcCalls[ctx->rpcCallCount++];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bindUDPCallback(struct RPCCall* call, struct AdminClient_Result* res)
|
|
||||||
{
|
|
||||||
Assert_true(!res->err);
|
|
||||||
// Indirection to shutup clang warning
|
|
||||||
struct Log* logger = &call->node->nodeLog;
|
|
||||||
Log_debug(logger, "UDPInterface_new() -> [%s]", res->messageBytes);
|
|
||||||
String* addr = Dict_getStringC(res->responseDict, "bindAddress");
|
|
||||||
int64_t* ifNum = Dict_getIntC(res->responseDict, "interfaceNumber");
|
|
||||||
struct Sockaddr_storage ss;
|
|
||||||
Assert_true(!Sockaddr_parse(addr->bytes, &ss));
|
|
||||||
call->node->ifNum = *ifNum;
|
|
||||||
call->node->udpAddr = Sockaddr_clone(&ss.addr, call->node->alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bindUDP(struct Context* ctx, struct NodeContext* node)
|
|
||||||
{
|
|
||||||
struct RPCCall* call = pushCall(ctx);
|
|
||||||
call->func = String_new("UDPInterface_new", ctx->rpcAlloc);
|
|
||||||
call->args = Dict_new(ctx->rpcAlloc);
|
|
||||||
call->node = node;
|
|
||||||
call->callback = bindUDPCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void securitySetupComplete(struct Context* ctx, struct NodeContext* node)
|
|
||||||
{
|
|
||||||
struct RPCCall* call = pushCall(ctx);
|
|
||||||
call->func = String_new("Security_setupComplete", ctx->rpcAlloc);
|
|
||||||
call->args = Dict_new(ctx->rpcAlloc);
|
|
||||||
call->node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct NodeContext* startNode(char* nodeName,
|
|
||||||
char* privateKeyHex,
|
|
||||||
Dict* admin,
|
|
||||||
struct Context* ctx,
|
|
||||||
struct Except* eh,
|
|
||||||
struct FakeNetwork* fakeNet)
|
|
||||||
{
|
|
||||||
struct Allocator* alloc = Allocator_child(ctx->alloc);
|
|
||||||
struct NodeContext* node = Allocator_clone(alloc, (&(struct NodeContext) {
|
|
||||||
.alloc = alloc,
|
|
||||||
.base = ctx->base,
|
|
||||||
.nodeLog = {
|
|
||||||
.print = printLog
|
|
||||||
},
|
|
||||||
.parentLogger = ctx->logger,
|
|
||||||
.nodeName = nodeName
|
|
||||||
}));
|
|
||||||
Identity_set(node);
|
|
||||||
|
|
||||||
node->bind = Dict_getStringC(admin, "bind");
|
|
||||||
if (!node->bind) {
|
|
||||||
node->bind = String_new("127.0.0.1:0", alloc);
|
|
||||||
}
|
|
||||||
node->pass = Dict_getStringC(admin, "password");
|
|
||||||
if (!node->pass) {
|
|
||||||
node->pass = String_new("x", alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert_true(Hex_decode(node->privateKey, 32, privateKeyHex, 64) == 32);
|
|
||||||
|
|
||||||
struct AddrIfaceAdapter* adminClientIface = AddrIfaceAdapter_new(node->alloc);
|
|
||||||
struct AddrIfaceAdapter* adminIface = AddrIfaceAdapter_new(node->alloc);
|
|
||||||
struct ASynchronizer* asyncer = ASynchronizer_new(node->alloc, ctx->base, ctx->logger);
|
|
||||||
Iface_plumb(&asyncer->ifA, &adminClientIface->inputIf);
|
|
||||||
Iface_plumb(&asyncer->ifB, &adminIface->inputIf);
|
|
||||||
|
|
||||||
String* pass = String_new("12345", node->alloc);
|
|
||||||
node->adminClient = AdminClient_new(&adminClientIface->generic,
|
|
||||||
Sockaddr_clone(Sockaddr_LOOPBACK, node->alloc),
|
|
||||||
pass,
|
|
||||||
ctx->base,
|
|
||||||
&node->nodeLog,
|
|
||||||
node->alloc);
|
|
||||||
|
|
||||||
node->admin = Admin_new(&adminIface->generic, &node->nodeLog, ctx->base, pass);
|
|
||||||
|
|
||||||
Core_init(node->alloc,
|
|
||||||
&node->nodeLog,
|
|
||||||
ctx->base,
|
|
||||||
node->privateKey,
|
|
||||||
node->admin,
|
|
||||||
ctx->rand,
|
|
||||||
eh,
|
|
||||||
fakeNet,
|
|
||||||
true);
|
|
||||||
|
|
||||||
securitySetupComplete(ctx, node);
|
|
||||||
bindUDP(ctx, node);
|
|
||||||
node->publicKey = pubKeyForPriv(node->privateKey, node->alloc);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void beginConnectionCallback(struct RPCCall* call, struct AdminClient_Result* res)
|
|
||||||
{
|
|
||||||
Assert_true(!res->err);
|
|
||||||
// Indirection to shutup clang warning
|
|
||||||
struct Log* logger = &call->node->nodeLog;
|
|
||||||
Log_debug(logger, "UDPInterface_beginConnection() -> [%s]", res->messageBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void linkNodes(struct Context* ctx, struct NodeContext* client, struct NodeContext* server)
|
|
||||||
{
|
|
||||||
Dict* addPasswordArgs = Dict_new(ctx->rpcAlloc);
|
|
||||||
String* clientStr = String_printf(ctx->rpcAlloc, "%ld", (long) (uintptr_t) client);
|
|
||||||
Dict_putString(addPasswordArgs,
|
|
||||||
String_new("password", ctx->rpcAlloc),
|
|
||||||
clientStr,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
Dict_putString(addPasswordArgs,
|
|
||||||
String_new("user", ctx->rpcAlloc),
|
|
||||||
clientStr,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
struct RPCCall* addPasswordCall = pushCall(ctx);
|
|
||||||
addPasswordCall->func = String_new("AuthorizedPasswords_add", ctx->rpcAlloc);
|
|
||||||
addPasswordCall->args = addPasswordArgs;
|
|
||||||
addPasswordCall->node = server;
|
|
||||||
|
|
||||||
// client
|
|
||||||
Dict* beginConnectionArgs = Dict_new(ctx->rpcAlloc);
|
|
||||||
Dict_putInt(beginConnectionArgs,
|
|
||||||
String_new("interfaceNumber", ctx->rpcAlloc),
|
|
||||||
client->ifNum,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
Dict_putString(beginConnectionArgs,
|
|
||||||
String_new("password", ctx->rpcAlloc),
|
|
||||||
clientStr,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
Dict_putString(beginConnectionArgs,
|
|
||||||
String_new("publicKey", ctx->rpcAlloc),
|
|
||||||
server->publicKey,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
char* udpAddr = Sockaddr_print(server->udpAddr, ctx->rpcAlloc);
|
|
||||||
Dict_putString(beginConnectionArgs,
|
|
||||||
String_new("address", ctx->rpcAlloc),
|
|
||||||
String_new(udpAddr, ctx->rpcAlloc),
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
|
|
||||||
Log_info(ctx->logger, "Linking [%s] with [%s/%s]",
|
|
||||||
client->nodeName, server->nodeName, udpAddr);
|
|
||||||
|
|
||||||
struct RPCCall* connectCall = pushCall(ctx);
|
|
||||||
connectCall->func = String_new("UDPInterface_beginConnection", ctx->rpcAlloc);
|
|
||||||
connectCall->args = beginConnectionArgs;
|
|
||||||
connectCall->node = client;
|
|
||||||
connectCall->callback = beginConnectionCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void linkAllNodes(struct Context* ctx)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
String* key = NULL;
|
|
||||||
Dict_forEach(ctx->confNodes, key) {
|
|
||||||
int nodeIdx = Map_OfNodes_indexForKey(&key, &ctx->nodeMap);
|
|
||||||
Assert_true(nodeIdx >= 0);
|
|
||||||
struct NodeContext* nc = ctx->nodeMap.values[nodeIdx];
|
|
||||||
List* connectTo = nc->peers;
|
|
||||||
for (int j = 0; j < List_size(connectTo); j++) {
|
|
||||||
String* server = List_getString(connectTo, j);
|
|
||||||
Assert_true(server);
|
|
||||||
int nodeIdxB = Map_OfNodes_indexForKey(&server, &ctx->nodeMap);
|
|
||||||
Assert_true(nodeIdxB >= 0);
|
|
||||||
struct NodeContext* ncB = ctx->nodeMap.values[nodeIdxB];
|
|
||||||
linkNodes(ctx, nc, ncB);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
ctx->confNodes = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void startRpc(void* vcontext);
|
|
||||||
|
|
||||||
static void rpcCallback(struct AdminClient_Promise* promise, struct AdminClient_Result* res)
|
|
||||||
{
|
|
||||||
struct Context* ctx = promise->userData;
|
|
||||||
Identity_check(ctx);
|
|
||||||
|
|
||||||
struct RPCCall* thisCall = &ctx->rpcCalls[ctx->nextCall];
|
|
||||||
if (thisCall->callback) {
|
|
||||||
thisCall->callback(thisCall, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->nextCall++;
|
|
||||||
startRpc(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void startRpc(void* vcontext)
|
|
||||||
{
|
|
||||||
struct Context* ctx = vcontext;
|
|
||||||
Identity_check(ctx);
|
|
||||||
|
|
||||||
if (ctx->nextCall >= ctx->rpcCallCount) {
|
|
||||||
if (ctx->confNodes) {
|
|
||||||
linkAllNodes(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ctx->nextCall >= ctx->rpcCallCount) {
|
|
||||||
Log_info(ctx->logger, "\n\nCompleted setting up simulation\n\n");
|
|
||||||
Allocator_free(ctx->rpcAlloc);
|
|
||||||
ctx->rpcAlloc = NULL;
|
|
||||||
ctx->rpcCalls = NULL;
|
|
||||||
ctx->rpcCallCount = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RPCCall* nextCall = &ctx->rpcCalls[ctx->nextCall];
|
|
||||||
struct AdminClient_Promise* promise = AdminClient_rpcCall(nextCall->func,
|
|
||||||
nextCall->args,
|
|
||||||
nextCall->node->adminClient,
|
|
||||||
ctx->rpcAlloc);
|
|
||||||
promise->callback = rpcCallback;
|
|
||||||
promise->userData = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void letErRip(Dict* config, struct Allocator* alloc)
|
|
||||||
{
|
|
||||||
struct Except* eh = NULL;
|
|
||||||
struct Log* logger = FileWriterLog_new(stdout, alloc);
|
|
||||||
struct EventBase* base = EventBase_new(alloc);
|
|
||||||
struct Random* rand = NanotimeEntropyProvider_newDefaultRandom(base, logger, eh, alloc);
|
|
||||||
Allocator_setCanary(alloc, (uintptr_t)Random_uint64(rand));
|
|
||||||
|
|
||||||
struct Context sctx = {
|
|
||||||
.rpcAlloc = Allocator_child(alloc),
|
|
||||||
|
|
||||||
.logger = logger,
|
|
||||||
.base = base,
|
|
||||||
.rand = rand,
|
|
||||||
.alloc = alloc,
|
|
||||||
.nodeMap = {
|
|
||||||
.allocator = alloc
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct Context* ctx = &sctx;
|
|
||||||
Identity_set(ctx);
|
|
||||||
|
|
||||||
ctx->confNodes = Dict_getDictC(config, "nodes");
|
|
||||||
|
|
||||||
struct FakeNetwork* fakeNet = FakeNetwork_new(base, alloc, logger);
|
|
||||||
|
|
||||||
String* key = NULL;
|
|
||||||
Dict_forEach(ctx->confNodes, key) {
|
|
||||||
Dict* val = Dict_getDict(ctx->confNodes, key);
|
|
||||||
String* privateKeyHex = Dict_getStringC(val, "privateKey");
|
|
||||||
Dict* admin = Dict_getDictC(val, "admin");
|
|
||||||
struct NodeContext* nc =
|
|
||||||
startNode(key->bytes, privateKeyHex->bytes, admin, ctx, eh, fakeNet);
|
|
||||||
nc->peers = Dict_getListC(val, "peers");
|
|
||||||
Map_OfNodes_put(&key, &nc, &ctx->nodeMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log_info(ctx->logger, "\n\nAll nodes initialized\n\n");
|
|
||||||
|
|
||||||
// begin the chain of RPC calls which sets up the net
|
|
||||||
Timeout_setTimeout(startRpc, ctx, 0, base, ctx->rpcAlloc);
|
|
||||||
|
|
||||||
EventBase_beginLoop(base);
|
|
||||||
|
|
||||||
Allocator_free(alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage(char* appName)
|
|
||||||
{
|
|
||||||
printf("Example usage: %s < config.json\n"
|
|
||||||
"Example config:\n"
|
|
||||||
"{\n"
|
|
||||||
" \"nodes\": {\n"
|
|
||||||
" \"alice\": {\n"
|
|
||||||
" \"privateKey\": "
|
|
||||||
"\"5e2295679394e5e1db67c238abbc10292ad9b127904394c52cc5fff39383e920\",\n"
|
|
||||||
" \"peers\": []\n"
|
|
||||||
" },\n"
|
|
||||||
" \"bob\": {\n"
|
|
||||||
" \"privateKey\": "
|
|
||||||
"\"6569bf3f0d168faa6dfb2912f8ee5ee9b938319e97618fdf06caed73b1aad1cc\",\n"
|
|
||||||
" \"peers\": [\n"
|
|
||||||
" \"alice\"\n"
|
|
||||||
" ]\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n", appName);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is invoked from sybilsim.rs
|
|
||||||
int sybilsim_main(int argc, char** argv);
|
|
||||||
int sybilsim_main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
Assert_true(argc > 0);
|
|
||||||
if (isatty(STDIN_FILENO)) {
|
|
||||||
return usage(argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Allocator* alloc = Allocator_new(1LL<<31);
|
|
||||||
|
|
||||||
struct Reader* stdinReader = FileReader_new(stdin, alloc);
|
|
||||||
Dict config;
|
|
||||||
if (JsonBencSerializer_get()->parseDictionary(stdinReader, alloc, &config)) {
|
|
||||||
fprintf(stderr, "Failed to parse configuration.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
letErRip(&config, alloc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,43 +0,0 @@
|
|||||||
sybilsim(8) -- Cjdns packet switch
|
|
||||||
=============================================
|
|
||||||
|
|
||||||
## SYNOPSIS
|
|
||||||
|
|
||||||
`/usr/libexec/cjdns/sybilsim < config.json`
|
|
||||||
|
|
||||||
## DESCRIPTION
|
|
||||||
|
|
||||||
Sybilsim reads a list of nodes and peers from stdin and simulates the
|
|
||||||
corresponding mesh without any actual networking using the same code
|
|
||||||
as cjdroute. This is useful for testing and optimizing cjdroute.
|
|
||||||
Every node must have a valid cjdns private key. The makekeys(1) utility can be
|
|
||||||
useful for scripts that generate the config.
|
|
||||||
|
|
||||||
## USAGE
|
|
||||||
|
|
||||||
Example config:
|
|
||||||
|
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"alice": {
|
|
||||||
"privateKey":
|
|
||||||
"5e2295679394e5e1db67c238abbc10292ad9b127904394c52cc5fff39383e920",
|
|
||||||
"peers": []
|
|
||||||
},
|
|
||||||
"bob": {
|
|
||||||
"privateKey":
|
|
||||||
"6569bf3f0d168faa6dfb2912f8ee5ee9b938319e97618fdf06caed73b1aad1cc",
|
|
||||||
"peers": [ "alice" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Example use:
|
|
||||||
|
|
||||||
makekeys | head -20 >keys.txt
|
|
||||||
node /usr/libexec/cjdns/tools/lib/makesim.js keys.txt |
|
|
||||||
/usr/libexec/cjdns/sybilsim
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
makekeys(1), cjdroute(1)
|
|
@@ -11,12 +11,6 @@ RUN adduser -D -h /etc/cjdns -u 1000 cjdns \
|
|||||||
&& rm -rf build_* && ./do \
|
&& rm -rf build_* && ./do \
|
||||||
&& cp cjdroute /usr/bin \
|
&& cp cjdroute /usr/bin \
|
||||||
&& cp -r tools/* /usr/bin \
|
&& cp -r tools/* /usr/bin \
|
||||||
&& cp makekeys \
|
|
||||||
mkpasswd \
|
|
||||||
privatetopublic \
|
|
||||||
publictoip6 \
|
|
||||||
randombytes \
|
|
||||||
sybilsim /usr/bin \
|
|
||||||
&& cp contrib/docker/entrypoint.sh / \
|
&& cp contrib/docker/entrypoint.sh / \
|
||||||
&& rm -rf /src /var/cache/apk/* \
|
&& rm -rf /src /var/cache/apk/* \
|
||||||
&& apk del --purge python build-base linux-headers
|
&& apk del --purge python build-base linux-headers
|
||||||
|
@@ -121,8 +121,6 @@ ln contrib/selinux/cjdns.{te,fc} . # for doc dir
|
|||||||
|
|
||||||
# install c and nodejs tools
|
# install c and nodejs tools
|
||||||
mkdir -p %{buildroot}%{_prefix}/lib/cjdns/{node_build,contrib}
|
mkdir -p %{buildroot}%{_prefix}/lib/cjdns/{node_build,contrib}
|
||||||
cp -p publictoip6 privatetopublic makekeys randombytes sybilsim \
|
|
||||||
$RPM_BUILD_ROOT%{_prefix}/lib/cjdns
|
|
||||||
cp -pr tools $RPM_BUILD_ROOT%{_prefix}/lib/cjdns
|
cp -pr tools $RPM_BUILD_ROOT%{_prefix}/lib/cjdns
|
||||||
cp -p node_build/Semaphore.js $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/node_build
|
cp -p node_build/Semaphore.js $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/node_build
|
||||||
cp -pr contrib/nodejs $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/contrib
|
cp -pr contrib/nodejs $RPM_BUILD_ROOT%{_prefix}/lib/cjdns/contrib
|
||||||
|
@@ -5,7 +5,6 @@ cp mkpasswd /usr/bin/
|
|||||||
cp privatetopublic /usr/bin/
|
cp privatetopublic /usr/bin/
|
||||||
cp publictoip6 /usr/bin/
|
cp publictoip6 /usr/bin/
|
||||||
cp randombytes /usr/bin/
|
cp randombytes /usr/bin/
|
||||||
cp sybilsim /usr/bin/
|
|
||||||
cp contrib/systemd/cjdns.service /etc/systemd/system/
|
cp contrib/systemd/cjdns.service /etc/systemd/system/
|
||||||
cp contrib/systemd/cjdns-resume.service /etc/systemd/system
|
cp contrib/systemd/cjdns-resume.service /etc/systemd/system
|
||||||
systemctl enable --now cjdns.service
|
systemctl enable --now cjdns.service
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#include "memory/Allocator.h"
|
#include "memory/Allocator.h"
|
||||||
#include "net/InterfaceController.h"
|
#include "net/InterfaceController.h"
|
||||||
#include "util/events/EventBase.h"
|
#include "util/events/EventBase.h"
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "util/platform/Sockaddr.h"
|
#include "util/platform/Sockaddr.h"
|
||||||
#include "crypto/Key.h"
|
#include "crypto/Key.h"
|
||||||
#include "interface/UDPInterface_admin.h"
|
#include "interface/UDPInterface_admin.h"
|
||||||
@@ -36,7 +35,6 @@ struct Context
|
|||||||
struct Admin* admin;
|
struct Admin* admin;
|
||||||
struct ArrayList_UDPInterface* ifaces;
|
struct ArrayList_UDPInterface* ifaces;
|
||||||
struct InterfaceController* ic;
|
struct InterfaceController* ic;
|
||||||
struct FakeNetwork* fakeNet;
|
|
||||||
struct GlobalConfig* globalConf;
|
struct GlobalConfig* globalConf;
|
||||||
Identity
|
Identity
|
||||||
};
|
};
|
||||||
@@ -333,7 +331,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
|||||||
struct Log* logger,
|
struct Log* logger,
|
||||||
struct Admin* admin,
|
struct Admin* admin,
|
||||||
struct InterfaceController* ic,
|
struct InterfaceController* ic,
|
||||||
struct FakeNetwork* fakeNet,
|
|
||||||
struct GlobalConfig* globalConf)
|
struct GlobalConfig* globalConf)
|
||||||
{
|
{
|
||||||
struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
|
struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
|
||||||
@@ -342,7 +339,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
|||||||
.logger = logger,
|
.logger = logger,
|
||||||
.admin = admin,
|
.admin = admin,
|
||||||
.ic = ic,
|
.ic = ic,
|
||||||
.fakeNet = fakeNet,
|
|
||||||
.globalConf = globalConf
|
.globalConf = globalConf
|
||||||
}));
|
}));
|
||||||
Identity_set(ctx);
|
Identity_set(ctx);
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include "net/InterfaceController.h"
|
#include "net/InterfaceController.h"
|
||||||
#include "util/log/Log.h"
|
#include "util/log/Log.h"
|
||||||
#include "util/events/EventBase.h"
|
#include "util/events/EventBase.h"
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "util/GlobalConfig.h"
|
#include "util/GlobalConfig.h"
|
||||||
#include "util/Linker.h"
|
#include "util/Linker.h"
|
||||||
Linker_require("interface/UDPInterface_admin.c")
|
Linker_require("interface/UDPInterface_admin.c")
|
||||||
@@ -30,7 +29,6 @@ void UDPInterface_admin_register(struct EventBase* base,
|
|||||||
struct Log* logger,
|
struct Log* logger,
|
||||||
struct Admin* admin,
|
struct Admin* admin,
|
||||||
struct InterfaceController* ic,
|
struct InterfaceController* ic,
|
||||||
struct FakeNetwork* fakeNet,
|
|
||||||
struct GlobalConfig* globalConf);
|
struct GlobalConfig* globalConf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -294,7 +294,6 @@ Builder.configure({
|
|||||||
|
|
||||||
builder.buildLibrary('contrib/c/publictoip6.c');
|
builder.buildLibrary('contrib/c/publictoip6.c');
|
||||||
builder.buildLibrary('contrib/c/privatetopublic.c');
|
builder.buildLibrary('contrib/c/privatetopublic.c');
|
||||||
builder.buildLibrary('contrib/c/sybilsim.c');
|
|
||||||
builder.buildLibrary('contrib/c/makekeys.c');
|
builder.buildLibrary('contrib/c/makekeys.c');
|
||||||
builder.buildLibrary('contrib/c/mkpasswd.c');
|
builder.buildLibrary('contrib/c/mkpasswd.c');
|
||||||
builder.buildLibrary('crypto/random/randombytes.c');
|
builder.buildLibrary('crypto/random/randombytes.c');
|
||||||
|
@@ -1,44 +0,0 @@
|
|||||||
/* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef FakeNetwork_H
|
|
||||||
#define FakeNetwork_H
|
|
||||||
|
|
||||||
#include "exception/Except.h"
|
|
||||||
#include "interface/Iface.h"
|
|
||||||
#include "interface/addressable/AddrIface.h"
|
|
||||||
#include "memory/Allocator.h"
|
|
||||||
#include "util/events/EventBase.h"
|
|
||||||
#include "util/log/Log.h"
|
|
||||||
#include "util/Linker.h"
|
|
||||||
Linker_require("util/events/libuv/FakeNetwork.c")
|
|
||||||
|
|
||||||
struct FakeNetwork
|
|
||||||
{
|
|
||||||
int unused;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FakeNetwork_UDPIface
|
|
||||||
{
|
|
||||||
struct AddrIface generic;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FakeNetwork* FakeNetwork_new(struct EventBase* base,
|
|
||||||
struct Allocator* allocator,
|
|
||||||
struct Log* logger);
|
|
||||||
|
|
||||||
struct FakeNetwork_UDPIface* FakeNetwork_iface(struct FakeNetwork* net,
|
|
||||||
struct Sockaddr* bindAddress,
|
|
||||||
struct Allocator* alloc);
|
|
||||||
#endif
|
|
@@ -1,166 +0,0 @@
|
|||||||
/* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include "util/events/FakeNetwork.h"
|
|
||||||
#include "exception/Except.h"
|
|
||||||
#include "interface/Iface.h"
|
|
||||||
#include "interface/addressable/AddrIface.h"
|
|
||||||
#include "memory/Allocator.h"
|
|
||||||
#include "util/events/EventBase.h"
|
|
||||||
#include "util/log/Log.h"
|
|
||||||
#include "interface/ASynchronizer.h"
|
|
||||||
#include "wire/Error.h"
|
|
||||||
|
|
||||||
#define Map_USE_HASH
|
|
||||||
#define Map_USE_COMPARATOR
|
|
||||||
#define Map_NAME OfIfaces
|
|
||||||
#define Map_KEY_TYPE struct Sockaddr*
|
|
||||||
#define Map_VALUE_TYPE struct FakeNetwork_UDPIface_pvt*
|
|
||||||
#include "util/Map.h"
|
|
||||||
static inline uint32_t Map_OfIfaces_hash(struct Sockaddr** key)
|
|
||||||
{
|
|
||||||
return Sockaddr_hash(*key);
|
|
||||||
}
|
|
||||||
static inline int Map_OfIfaces_compare(struct Sockaddr** keyA, struct Sockaddr** keyB)
|
|
||||||
{
|
|
||||||
return Sockaddr_compare(*keyA, *keyB);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FakeNetwork_pvt
|
|
||||||
{
|
|
||||||
struct FakeNetwork pub;
|
|
||||||
struct Allocator* alloc;
|
|
||||||
struct Log* log;
|
|
||||||
struct EventBase* base;
|
|
||||||
struct ASynchronizer* async;
|
|
||||||
struct Iface fromAsync;
|
|
||||||
struct Iface toAsync;
|
|
||||||
uint16_t lastPort;
|
|
||||||
|
|
||||||
struct Map_OfIfaces map;
|
|
||||||
Identity
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FakeNetwork_UDPIface_pvt
|
|
||||||
{
|
|
||||||
struct FakeNetwork_UDPIface pub;
|
|
||||||
struct FakeNetwork_pvt* fnp;
|
|
||||||
Identity
|
|
||||||
};
|
|
||||||
|
|
||||||
static void popSockaddr(struct Message* msg, struct Sockaddr_storage* ss)
|
|
||||||
{
|
|
||||||
uint64_t length = 0;
|
|
||||||
Er_assert(Message_epop(msg, &length, 8));
|
|
||||||
Er_assert(Message_eshift(msg, 8));
|
|
||||||
Assert_true(length >= Sockaddr_OVERHEAD);
|
|
||||||
Assert_true(length <= sizeof(struct Sockaddr_storage));
|
|
||||||
Er_assert(Message_epop(msg, ss, length));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pushSockaddr(struct Message* msg, struct Sockaddr* sa)
|
|
||||||
{
|
|
||||||
Er_assert(Message_epush(msg, sa, sa->addrLen));
|
|
||||||
}
|
|
||||||
|
|
||||||
static Iface_DEFUN fromAsync(struct Message* msg, struct Iface* fnpFromAsync)
|
|
||||||
{
|
|
||||||
struct FakeNetwork_pvt* fnp =
|
|
||||||
Identity_containerOf(fnpFromAsync, struct FakeNetwork_pvt, fromAsync);
|
|
||||||
|
|
||||||
struct Sockaddr_storage dest;
|
|
||||||
struct Sockaddr* dp = &dest.addr;
|
|
||||||
popSockaddr(msg, &dest);
|
|
||||||
int idx = Map_OfIfaces_indexForKey(&dp, &fnp->map);
|
|
||||||
if (idx == -1) {
|
|
||||||
char* destAddr = Sockaddr_print(dp, Message_getAlloc(msg));
|
|
||||||
|
|
||||||
// hack, the 'dest' becomes the source.
|
|
||||||
popSockaddr(msg, &dest);
|
|
||||||
char* srcAddr = Sockaddr_print(dp, Message_getAlloc(msg));
|
|
||||||
|
|
||||||
Log_debug(fnp->log, "Message with unknown dest address [%s] from [%s]", destAddr, srcAddr);
|
|
||||||
return Error(msg, "INVALID");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FakeNetwork_UDPIface_pvt* fnip = Identity_check(fnp->map.values[idx]);
|
|
||||||
return Iface_next(&fnip->pub.generic.iface, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Iface_DEFUN incoming(struct Message* msg, struct Iface* iface)
|
|
||||||
{
|
|
||||||
struct FakeNetwork_UDPIface_pvt* fnip =
|
|
||||||
Identity_check((struct FakeNetwork_UDPIface_pvt*) iface);
|
|
||||||
struct FakeNetwork_pvt* fnp = Identity_check(fnip->fnp);
|
|
||||||
|
|
||||||
// Swap so that the message contains [dest][src][content]
|
|
||||||
struct Sockaddr_storage dest;
|
|
||||||
popSockaddr(msg, &dest);
|
|
||||||
pushSockaddr(msg, fnip->pub.generic.addr);
|
|
||||||
pushSockaddr(msg, &dest.addr);
|
|
||||||
|
|
||||||
return Iface_next(&fnp->toAsync, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FakeNetwork_UDPIface* FakeNetwork_iface(struct FakeNetwork* net,
|
|
||||||
struct Sockaddr* bindAddress,
|
|
||||||
struct Allocator* allocator)
|
|
||||||
{
|
|
||||||
struct FakeNetwork_pvt* fnp = Identity_check((struct FakeNetwork_pvt*) net);
|
|
||||||
struct Allocator* alloc = Allocator_child(allocator);
|
|
||||||
struct Sockaddr* addr = Sockaddr_clone(bindAddress, alloc);
|
|
||||||
|
|
||||||
uint8_t* addrBytes;
|
|
||||||
int addrLen = Sockaddr_getAddress(addr, &addrBytes);
|
|
||||||
if (Sockaddr_getPort(addr) == 0) {
|
|
||||||
Sockaddr_setPort(addr, ++fnp->lastPort);
|
|
||||||
// Check for wrapping.
|
|
||||||
Assert_true(fnp->lastPort != 0);
|
|
||||||
Assert_true(addrLen == 4);
|
|
||||||
Bits_memcpy(addrBytes, ((uint8_t[]){127, 0, 0, 1}), 4);
|
|
||||||
} else if (addrLen == 4 && !Bits_memcmp(addrBytes, "\0\0\0\0", 4)) {
|
|
||||||
Assert_failure("Address 0 with port specified is not allowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Map_OfIfaces_indexForKey(&addr, &fnp->map) != -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct FakeNetwork_UDPIface_pvt* fnip =
|
|
||||||
Allocator_calloc(alloc, sizeof(struct FakeNetwork_UDPIface_pvt), 1);
|
|
||||||
Map_OfIfaces_put(&addr, &fnip, &fnp->map);
|
|
||||||
fnip->fnp = fnp;
|
|
||||||
fnip->pub.generic.alloc = alloc;
|
|
||||||
fnip->pub.generic.addr = addr;
|
|
||||||
fnip->pub.generic.iface.send = incoming;
|
|
||||||
Identity_set(fnip);
|
|
||||||
return &fnip->pub;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FakeNetwork* FakeNetwork_new(struct EventBase* base,
|
|
||||||
struct Allocator* allocator,
|
|
||||||
struct Log* logger)
|
|
||||||
{
|
|
||||||
struct Allocator* alloc = Allocator_child(allocator);
|
|
||||||
struct FakeNetwork_pvt* fnp = Allocator_calloc(alloc, sizeof(struct FakeNetwork_pvt), 1);
|
|
||||||
fnp->alloc = alloc;
|
|
||||||
fnp->log = logger;
|
|
||||||
fnp->base = base;
|
|
||||||
fnp->map.allocator = alloc;
|
|
||||||
fnp->async = ASynchronizer_new(alloc, base, logger);
|
|
||||||
fnp->fromAsync.send = fromAsync;
|
|
||||||
Iface_plumb(&fnp->fromAsync, &fnp->async->ifB);
|
|
||||||
Iface_plumb(&fnp->toAsync, &fnp->async->ifA);
|
|
||||||
Identity_set(fnp);
|
|
||||||
return &fnp->pub;
|
|
||||||
}
|
|
Reference in New Issue
Block a user