$ git clone https://socialnetwork.ion.nu/socialnetwork.git
commit 46b15944079ec9bc0a000f4e2d84dfbaa13f8c01
Author: Alicia <...>
Date: Sun Jan 8 16:10:44 2017 +0100
Added a 'findpeer' command to find a peer by ID, and peer_findpeer(ID) for convenience.
diff --git a/peer.c b/peer.c
index 851cc57..09d416c 100644
--- a/peer.c
+++ b/peer.c
@@ -124,6 +124,85 @@ static void getpeers(struct peer* peer, void* data, unsigned int len)
printf("We now have %u peers\n", peercount);
}
+struct findpeer_request
+{
+ unsigned char id[20];
+ struct sockaddr addr;
+ uint16_t addrlen;
+ time_t timestamp;
+};
+static void findpeer(struct peer* peer, void* data, unsigned int len)
+{
+ // <target ID, 20><ttl, 2>[<addrlen, 2><source addr>]
+ // Sender can't know their own address, so the first recipient will need to add the address of whoever they got it from
+ uint16_t ttl;
+ if(len<20+sizeof(ttl)){return;}
+ unsigned char id[20];
+ memcpy(id, data, 20);
+printf("Got findpeer request for '"PEERFMT"'\n", PEERARG(id));
+ memcpy(&ttl, data+20, sizeof(ttl));
+ if(!ttl){return;}
+ --ttl;
+ struct sockaddr addr;
+ uint16_t addrlen;
+ if(len>20+sizeof(ttl)+sizeof(addrlen))
+ { // Has address already
+ memcpy(&addrlen, data+20+sizeof(ttl), sizeof(addrlen));
+ if(len<20+sizeof(ttl)+sizeof(addrlen)+addrlen){return;}
+ memcpy(&addr, data+20+sizeof(ttl)+sizeof(addrlen), addrlen);
+ }
+ else if(len==20+sizeof(ttl))
+ { // Get address from sender
+ addrlen=peer->addrlen;
+ memcpy(&addr, &peer->addr, addrlen);
+ }else{return;}
+ // Avoid floody loops by keeping track of what we've already handled recently
+ static struct findpeer_request* reqs=0;
+ static unsigned int reqcount=0;
+ time_t now=time(0);
+ struct findpeer_request* newentry=0;
+ unsigned int i;
+ for(i=0; i<reqcount; ++i)
+ {
+ if(reqs[i].timestamp+30<now) // Old entry (30 seconds)
+ {
+ newentry=&reqs[i]; // Mark as replacable
+ }
+ else if(!memcmp(reqs[i].id, id, 20) && reqs[i].addrlen==addrlen && !memcmp(&reqs[i].addr, &addr, addrlen))
+ { // Already handled, update the timestamp too in case it keeps coming for a while
+ reqs[i].timestamp=now;
+ return;
+ }
+ }
+ if(!newentry) // Make room for new entry if there were no old ones to replace
+ {
+ ++reqcount;
+ reqs=realloc(reqs, sizeof(struct findpeer_request)*reqcount);
+ newentry=&reqs[reqcount-1];
+ }
+ memcpy(newentry->id, id, 20);
+ memcpy(&newentry->addr, &addr, addrlen);
+ newentry->addrlen=addrlen;
+ newentry->timestamp=now;
+ // Check if it's us
+ if(!memcmp(id, peer_id, 20))
+ {
+ peer_new_unique(udpstream_getsocket(peer->stream), &addr, addrlen);
+ return;
+ }
+ // Propagate (unless it was us, !ttl, or already handled)
+ if(ttl)
+ {
+ len=20+sizeof(ttl)+sizeof(addrlen)+addrlen;
+ unsigned char data[len];
+ memcpy(data, id, 20);
+ memcpy(data+20, &ttl, sizeof(ttl));
+ memcpy(data+20+sizeof(ttl), &addrlen, sizeof(addrlen));
+ memcpy(data+20+sizeof(ttl)+sizeof(addrlen), &addr, addrlen);
+ peer_sendcmd(0, "findpeer", data, len);
+ }
+}
+
void peer_init(const char* keypath)
{
gnutls_global_init();
@@ -165,6 +244,7 @@ void peer_init(const char* keypath)
// Register core commands
peer_registercmd("getpeers", sendpeers);
peer_registercmd("peers", getpeers);
+ peer_registercmd("findpeer", findpeer);
}
static int checkcert(gnutls_session_t tls)
@@ -400,3 +480,13 @@ void peer_disconnect(struct peer* peer, char cleanly)
}
}
}
+
+void peer_findpeer(const unsigned char id[20])
+{
+ uint16_t ttl=8; // 8 is probably a good level to start at, might need to be higher in the future
+ unsigned int len=20+sizeof(ttl);
+ unsigned char data[len];
+ memcpy(data, id, 20);
+ memcpy(data+20, &ttl, sizeof(ttl));
+ peer_sendcmd(0, "findpeer", data, len);
+}
diff --git a/peer.h b/peer.h
index b4f619c..987452d 100644
--- a/peer.h
+++ b/peer.h
@@ -45,3 +45,4 @@ extern void peer_bootstrap(int sock, const char* peerlist);
extern void peer_handlesocket(int sock); // Incoming data
extern void peer_sendcmd(struct peer* peer, const char* cmd, void* data, uint32_t len);
extern void peer_disconnect(struct peer* peer, char cleanly);
+extern void peer_findpeer(const unsigned char id[20]); // Find and ask a peer to connect to us