upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/test_relayproc.cpp
blob: f9d7f0709720801b91be1d20542898e57cbf1b61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Tests the tunnel against a SEPARATE running bitflashd relay process (not an
// in-process relay) -- i.e. exactly the VPS deployment shape, on loopback.
// Usage: test_relayproc.exe <port>   (a bitflashd must already listen there)
//
// Build: g++ -std=gnu++14 -O2 -pthread test_relayproc.cpp btftunnel.cpp btfrv.cpp btfchan.cpp -lsodium -lws2_32 -o test_relayproc.exe

#include "btftunnel.h"
#include "btfrv.h"
#include "btfchan.h"
#include <winsock2.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <thread>
#include <chrono>

using namespace btf;
static int g_fail = 0;
#define CHECK(c,n) do{ if(c){printf("  ok   %s\n",n);} else {printf("  FAIL %s\n",n); g_fail++;} }while(0)

static unsigned short PORT = 18446;
static const char* HOST = "127.0.0.1";
static bool RecvN(SOCKET s, void* b, int n){char*p=(char*)b;int o=0;while(o<n){int r=recv(s,p+o,n-o,0);if(r<=0)return false;o+=r;}return true;}
static bool SendN(SOCKET s, const void* b, int n){const char*p=(const char*)b;int o=0;while(o<n){int r=send(s,p+o,n-o,0);if(r<=0)return false;o+=r;}return true;}

static bool g_ok=false; static std::string g_got;
static void Service(std::vector<unsigned char> id, std::vector<unsigned char> sk, int len)
{
    RvSocket rv = RvServiceRegister(HOST, PORT, id.data());
    if (rv==RV_INVALID) return;
    btf_socket_t app = BtfServiceWrap(rv, sk.data());
    if (app==INVALID_SOCKET) return;
    std::vector<char> buf(len);
    if(!RecvN((SOCKET)app, buf.data(), len)){closesocket((SOCKET)app);return;}
    g_got.assign(buf.data(), len);
    g_ok = SendN((SOCKET)app, buf.data(), len);
    closesocket((SOCKET)app);
}

int main(int argc, char* argv[])
{
    if (argc>=2) HOST=argv[1]; if (argc>=3) PORT=(unsigned short)atoi(argv[2]);
    if(!TunnelInit()){printf("init failed\n");return 2;}
    unsigned char pk[32], sk[32]; ChanKeypair(pk,sk);
    std::vector<unsigned char> id(32); for(int i=0;i<32;i++) id[i]=(unsigned char)(i*11+3);
    std::string msg="anonymous hop through a real bitflashd relay process";
    int len=(int)msg.size();

    printf("tunnel_through_external_relay_process (port %u)\n", PORT);
    std::thread svc(Service, id, std::vector<unsigned char>(sk,sk+32), len);
    std::this_thread::sleep_for(std::chrono::milliseconds(400));

    btf_socket_t app = BtfClientTunnel(HOST, PORT, id.data(), pk);
    CHECK(app!=INVALID_SOCKET, "client tunneled through the running bitflashd");
    if(app!=INVALID_SOCKET){
        CHECK(SendN((SOCKET)app,msg.data(),len), "app writes plaintext");
        std::vector<char> echo(len);
        CHECK(RecvN((SOCKET)app,echo.data(),len), "app reads echo");
        CHECK(std::string(echo.data(),len)==msg, "round-trips end-to-end via the relay process");
        closesocket((SOCKET)app);
    }
    svc.join();
    CHECK(g_ok && g_got==msg, "service saw correct plaintext");
    printf("\n%s (%d failures)\n", g_fail==0?"ALL TESTS PASSED":"TESTS FAILED", g_fail);
    return g_fail==0?0:1;
}