Skip to content

Commit 8a7a58a

Browse files
author
Lars Gierth
committed
Merge pull request #80 from tigusoft/pr-long-reference-clean
Fix long outgoing references blocking cjdroute
2 parents d482e89 + a26136a commit 8a7a58a

3 files changed

Lines changed: 77 additions & 1 deletion

File tree

benc/serialization/standard/BencMessageWriter.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "benc/Dict.h"
1919
#include "benc/List.h"
2020
#include "exception/Except.h"
21+
#include "exception/Jmp.h"
2122
#include "wire/Message.h"
2223
#include "util/Base10.h"
2324

@@ -66,6 +67,25 @@ static void writeDict(Dict* d, struct Message* msg, struct Except* eh)
6667
Message_push8(msg, 'd', eh);
6768
}
6869

70+
/**
71+
* Tries to send a message same as in writeDic() but in case of some problems
72+
* where it would throw, it instead returns non-zero value to indicate error:
73+
* return 1 - there was an error
74+
* return 0 - no error was detected, but still no guarantee if message was sent,
75+
* some errors like message not fitting UDP-admin-packet size are NOT detected
76+
* (therefore you should detect them in caller function)
77+
*/
78+
int BencMessageWriter_writeDictTry(Dict* d, struct Message* msg, struct Except* eh)
79+
{
80+
struct Jmp jmp;
81+
Jmp_try(jmp) {
82+
writeDict(d, msg, &jmp.handler);
83+
return 0;
84+
} Jmp_catch {
85+
return 1;
86+
}
87+
}
88+
6989
static void writeGeneric(Object* obj, struct Message* msg, struct Except* eh)
7090
{
7191
switch (obj->type) {

benc/serialization/standard/BencMessageWriter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,11 @@ Linker_require("benc/serialization/standard/BencMessageWriter.c")
2323

2424
void BencMessageWriter_write(Dict* toWrite, struct Message* msg, struct Except* eh);
2525

26+
/**
27+
* this function is a non-static wrapper for same function,
28+
* so that we can use it from other places to estimate if reference
29+
* will fit in admin UDP packet
30+
*/
31+
int BencMessageWriter_writeDictTry(Dict* d, struct Message* msg, struct Except* eh);
32+
2633
#endif

client/Configurator.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "client/Configurator.h"
1717
#include "benc/String.h"
1818
#include "benc/Dict.h"
19+
#include "benc/serialization/standard/BencMessageWriter.h"
1920
#include "benc/Int.h"
2021
#include "benc/List.h"
2122
#include "memory/Allocator.h"
@@ -42,6 +43,8 @@ struct Context
4243
struct EventBase* base;
4344
};
4445

46+
const int abort_if_invalid_ref = 1;
47+
4548
static void rpcCallback(struct AdminClient_Promise* p, struct AdminClient_Result* res)
4649
{
4750
struct Context* ctx = p->userData;
@@ -211,7 +214,37 @@ static void udpInterface(Dict* config, struct Context* ctx)
211214
"is not a dictionary type.", key->bytes);
212215
exit(-1);
213216
}
214-
Dict* value = entry->val->as.dictionary;
217+
Dict* all = entry->val->as.dictionary;
218+
Dict* value = Dict_new(perCallAlloc);
219+
String* pub_d = Dict_getString(all, String_CONST("publicKey"));
220+
String* pss_d = Dict_getString(all, String_CONST("password"));
221+
String* peerName_d = Dict_getString(all, String_CONST("peerName"));
222+
String* login_d = Dict_getString(all, String_CONST("login"));
223+
224+
if ( !pub_d || !pss_d ) {
225+
const char * error_name = "(unknown)";
226+
if ( !pub_d ) {
227+
error_name = "publicKey";
228+
}
229+
if ( !pss_d ) {
230+
error_name = "password";
231+
}
232+
Log_warn(ctx->logger,
233+
"Skipping peer: missing %s for peer [%s]", error_name, key->bytes);
234+
if (abort_if_invalid_ref) {
235+
Assert_failure("Invalid peer reference");
236+
}
237+
else {
238+
entry = entry->next;
239+
continue;
240+
}
241+
}
242+
243+
Dict_putString(value, String_CONST("publicKey"), pub_d, perCallAlloc);
244+
Dict_putString(value, String_CONST("password"), pss_d, perCallAlloc);
245+
Dict_putString(value, String_CONST("peerName"), peerName_d, perCallAlloc);
246+
Dict_putString(value, String_CONST("login"), login_d, perCallAlloc);
247+
215248
Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
216249
key = String_clone(key, perCallAlloc);
217250
char* lastColon = CString_strrchr(key->bytes, ':');
@@ -236,6 +269,22 @@ static void udpInterface(Dict* config, struct Context* ctx)
236269
continue;
237270
}
238271
}
272+
struct Allocator* child = Allocator_child(ctx->alloc);
273+
struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE + 256, child);
274+
int r = BencMessageWriter_writeDictTry(value, msg, NULL);
275+
276+
const int max_reference_size = 298;
277+
if (r != 0 || msg->length > max_reference_size) {
278+
Log_warn(ctx->logger, "Peer skipped:");
279+
Log_warn(ctx->logger, "Too long peer reference for [%s]", key->bytes);
280+
if (abort_if_invalid_ref) {
281+
Assert_failure("Invalid peer reference");
282+
}
283+
else {
284+
entry = entry->next;
285+
continue;
286+
}
287+
}
239288
Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
240289
Dict_putString(value, String_CONST("address"), key, perCallAlloc);
241290
rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);

0 commit comments

Comments
 (0)