| 359 | } |
| 360 | |
| 361 | void client(const char* destination_hexhash, const char* path) { |
| 362 | requested_path = path; |
| 363 | |
| 364 | // Generate a fresh client identity for this run. Used inside |
| 365 | // on_link_established() to call link.identify() so the server can |
| 366 | // authenticate us against an allow-list policy. |
| 367 | client_identity = RNS::Identity(); |
| 368 | |
| 369 | // Decode the hex destination hash from argv. |
| 370 | RNS::Bytes destination_hash; |
| 371 | try { |
| 372 | int dest_len = (RNS::Type::Reticulum::TRUNCATED_HASHLENGTH/8)*2; |
| 373 | if (strlen(destination_hexhash) != (size_t)dest_len) { |
| 374 | throw std::invalid_argument("Destination length is invalid, must be "+std::to_string(dest_len)+" hexadecimal characters ("+std::to_string(dest_len/2)+" bytes)."); |
| 375 | } |
| 376 | destination_hash.assignHex(destination_hexhash); |
| 377 | } |
| 378 | catch (const std::exception& e) { |
| 379 | RNS::log("Invalid destination entered. Check your input!", RNS::LOG_ERROR); |
| 380 | return; |
| 381 | } |
| 382 | |
| 383 | // Path discovery: ask the network for a path to the destination if |
| 384 | // we don't already know one, then spin until an announce arrives. |
| 385 | if (!RNS::Transport::has_path(destination_hash)) { |
| 386 | RNS::log("Destination is not yet known. Requesting path and waiting for announce to arrive..."); |
| 387 | RNS::Transport::request_path(destination_hash); |
| 388 | while (!RNS::Transport::has_path(destination_hash)) { |
| 389 | reticulum.loop(); |
| 390 | RNS::Utilities::OS::sleep(0.1); |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | // Recall the server's identity from the path table. |
| 395 | RNS::Identity server_identity = RNS::Identity::recall(destination_hash); |
| 396 | |
| 397 | RNS::log("Establishing link with NomadNet node..."); |
| 398 | |
| 399 | RNS::Destination server_destination = RNS::Destination( |
| 400 | server_identity, |
| 401 | RNS::Type::Destination::OUT, |
| 402 | RNS::Type::Destination::SINGLE, |
| 403 | APP_NAME, |
| 404 | APP_ASPECT |
| 405 | ); |
| 406 | |
| 407 | RNS::Link link = RNS::Link(server_destination); |
| 408 | link.set_link_established_callback(on_link_established); |
| 409 | link.set_link_closed_callback(on_link_closed); |
| 410 | |
| 411 | // Pump the stack until the response (or failure) callback fires. |
| 412 | while (!request_done) { |
| 413 | reticulum.loop(); |
| 414 | RNS::Utilities::OS::sleep(0.05); |
| 415 | } |
| 416 | |
| 417 | // Tear the Link down so the server sees a clean close, then drain |
| 418 | // a few hundred ms of events so the teardown packet actually leaves |
no test coverage detected