diff --git a/src/ipc/daemon_ipc_handlers.cpp b/src/ipc/daemon_ipc_handlers.cpp index 4aba57adb..21e7e22ad 100644 --- a/src/ipc/daemon_ipc_handlers.cpp +++ b/src/ipc/daemon_ipc_handlers.cpp @@ -28,6 +28,8 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +//TODO: Recheck memory leaks + #include "daemon_ipc_handlers.h" #include @@ -362,5 +364,57 @@ namespace IPC wap_proto_set_grey_peerlist_size(message, p2p->get_peerlist_manager().get_gray_peers_count()); wap_proto_set_status(message, STATUS_OK); } + + void get_peer_list(wap_proto_t *message) { + std::list white_list; + std::list gray_list; + p2p->get_peerlist_manager().get_peerlist_full(white_list, gray_list); + + rapidjson::Document white_list_json; + white_list_json.SetObject(); + rapidjson::Document::AllocatorType &white_list_allocator = white_list_json.GetAllocator(); + rapidjson::Value white_peers(rapidjson::kArrayType); + + for (auto & entry : white_list) { + rapidjson::Value output(rapidjson::kObjectType); + output.AddMember("id", entry.id, white_list_allocator); + output.AddMember("ip", entry.adr.ip, white_list_allocator); + output.AddMember("port", entry.adr.port, white_list_allocator); + output.AddMember("last_seen", entry.last_seen, white_list_allocator); + white_peers.PushBack(output, white_list_allocator); + } + white_list_json.AddMember("peers", white_peers, white_list_allocator); + + rapidjson::Document gray_list_json; + gray_list_json.SetObject(); + rapidjson::Document::AllocatorType &gray_list_allocator = gray_list_json.GetAllocator(); + rapidjson::Value gray_peers(rapidjson::kArrayType); + + for (auto & entry : gray_list) { + rapidjson::Value output(rapidjson::kObjectType); + output.AddMember("id", entry.id, gray_list_allocator); + output.AddMember("ip", entry.adr.ip, gray_list_allocator); + output.AddMember("port", entry.adr.port, gray_list_allocator); + output.AddMember("last_seen", entry.last_seen, gray_list_allocator); + gray_peers.PushBack(output, gray_list_allocator); + } + gray_list_json.AddMember("peers", gray_peers, gray_list_allocator); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + white_list_json.Accept(writer); + std::string white_list_string = buffer.GetString(); + + zframe_t *white_list_frame = zframe_new(white_list_string.c_str(), white_list_string.length()); + + buffer.Clear(); + gray_list_json.Accept(writer); + std::string gray_list_string = buffer.GetString(); + zframe_t *gray_list_frame = zframe_new(gray_list_string.c_str(), gray_list_string.length()); + + wap_proto_set_white_list(message, &white_list_frame); + wap_proto_set_gray_list(message, &gray_list_frame); + wap_proto_set_status(message, STATUS_OK); + } } } diff --git a/src/ipc/include/daemon_ipc_handlers.h b/src/ipc/include/daemon_ipc_handlers.h index eba8b2e03..6dc32bac5 100644 --- a/src/ipc/include/daemon_ipc_handlers.h +++ b/src/ipc/include/daemon_ipc_handlers.h @@ -77,6 +77,7 @@ namespace IPC void get_height(wap_proto_t *message); void save_bc(wap_proto_t *message); void get_info(wap_proto_t *message); + void get_peer_list(wap_proto_t *message); void init(cryptonote::core &p_core, nodetool::node_server > &p_p2p, bool p_testnet); diff --git a/src/ipc/include/wap_client.h b/src/ipc/include/wap_client.h index c4f2a1a76..fa67e945b 100644 --- a/src/ipc/include/wap_client.h +++ b/src/ipc/include/wap_client.h @@ -117,6 +117,11 @@ WAP_EXPORT int WAP_EXPORT int wap_client_stop (wap_client_t *self); +// Get peer list +// Returns >= 0 if successful, -1 if interrupted. +WAP_EXPORT int + wap_client_get_peer_list (wap_client_t *self); + // Return last received status WAP_EXPORT int wap_client_status (wap_client_t *self); @@ -189,6 +194,14 @@ WAP_EXPORT uint64_t WAP_EXPORT uint64_t wap_client_grey_peerlist_size (wap_client_t *self); +// Return last received white_list +WAP_EXPORT zframe_t * + wap_client_white_list (wap_client_t *self); + +// Return last received gray_list +WAP_EXPORT zframe_t * + wap_client_gray_list (wap_client_t *self); + // Self test of this class WAP_EXPORT void wap_client_test (bool verbose); diff --git a/src/ipc/include/wap_client_engine.inc b/src/ipc/include/wap_client_engine.inc index d1fad0938..17d2c4b9a 100644 --- a/src/ipc/include/wap_client_engine.inc +++ b/src/ipc/include/wap_client_engine.inc @@ -34,10 +34,11 @@ typedef enum { expect_random_outs_ok_state = 11, expect_get_height_ok_state = 12, expect_get_info_ok_state = 13, - expect_close_ok_state = 14, - defaults_state = 15, - have_error_state = 16, - reexpect_open_ok_state = 17 + expect_get_peer_list_ok_state = 14, + expect_close_ok_state = 15, + defaults_state = 16, + have_error_state = 17, + reexpect_open_ok_state = 18 } state_t; typedef enum { @@ -56,23 +57,25 @@ typedef enum { random_outs_event = 12, get_height_event = 13, get_info_event = 14, - destructor_event = 15, - blocks_ok_event = 16, - get_ok_event = 17, - put_ok_event = 18, - save_bc_ok_event = 19, - start_ok_event = 20, - stop_ok_event = 21, - output_indexes_ok_event = 22, - random_outs_ok_event = 23, - get_height_ok_event = 24, - get_info_ok_event = 25, - close_ok_event = 26, - ping_ok_event = 27, - error_event = 28, - exception_event = 29, - command_invalid_event = 30, - other_event = 31 + get_peer_list_event = 15, + destructor_event = 16, + blocks_ok_event = 17, + get_ok_event = 18, + put_ok_event = 19, + save_bc_ok_event = 20, + start_ok_event = 21, + stop_ok_event = 22, + output_indexes_ok_event = 23, + random_outs_ok_event = 24, + get_height_ok_event = 25, + get_info_ok_event = 26, + get_peer_list_ok_event = 27, + close_ok_event = 28, + ping_ok_event = 29, + error_event = 30, + exception_event = 31, + command_invalid_event = 32, + other_event = 33 } event_t; // Names for state machine logging and error reporting @@ -92,6 +95,7 @@ s_state_name [] = { "expect random outs ok", "expect get height ok", "expect get info ok", + "expect get peer list ok", "expect close ok", "defaults", "have error", @@ -115,6 +119,7 @@ s_event_name [] = { "RANDOM_OUTS", "GET_HEIGHT", "GET_INFO", + "GET_PEER_LIST", "destructor", "BLOCKS_OK", "GET_OK", @@ -126,6 +131,7 @@ s_event_name [] = { "RANDOM_OUTS_OK", "GET_HEIGHT_OK", "GET_INFO_OK", + "GET_PEER_LIST_OK", "CLOSE_OK", "PING_OK", "ERROR", @@ -238,6 +244,8 @@ static void signal_have_get_height_ok (client_t *self); static void signal_have_get_info_ok (client_t *self); +static void + signal_have_get_peer_list_ok (client_t *self); static void signal_failure (client_t *self); static void @@ -487,6 +495,12 @@ s_protocol_event (s_client_t *self, wap_proto_t *message) case WAP_PROTO_GET_INFO_OK: return get_info_ok_event; break; + case WAP_PROTO_GET_PEER_LIST: + return get_peer_list_event; + break; + case WAP_PROTO_GET_PEER_LIST_OK: + return get_peer_list_ok_event; + break; case WAP_PROTO_STOP: return stop_event; break; @@ -809,6 +823,18 @@ s_client_execute (s_client_t *self, event_t event) self->state = expect_get_info_ok_state; } else + if (self->event == get_peer_list_event) { + if (!self->exception) { + // send GET_PEER_LIST + if (wap_client_verbose) + zsys_debug ("wap_client: $ send GET_PEER_LIST"); + wap_proto_set_id (self->message, WAP_PROTO_GET_PEER_LIST); + wap_proto_send (self->message, self->dealer); + } + if (!self->exception) + self->state = expect_get_peer_list_ok_state; + } + else if (self->event == destructor_event) { if (!self->exception) { // send CLOSE @@ -1320,6 +1346,51 @@ s_client_execute (s_client_t *self, event_t event) } break; + case expect_get_peer_list_ok_state: + if (self->event == get_peer_list_ok_event) { + if (!self->exception) { + // signal have get peer list ok + if (wap_client_verbose) + zsys_debug ("wap_client: $ signal have get peer list ok"); + signal_have_get_peer_list_ok (&self->client); + } + if (!self->exception) + self->state = connected_state; + } + else + if (self->event == ping_ok_event) { + if (!self->exception) { + // client is connected + if (wap_client_verbose) + zsys_debug ("wap_client: $ client is connected"); + client_is_connected (&self->client); + } + } + else + if (self->event == error_event) { + if (!self->exception) { + // check status code + if (wap_client_verbose) + zsys_debug ("wap_client: $ check status code"); + check_status_code (&self->client); + } + if (!self->exception) + self->state = have_error_state; + } + else + if (self->event == exception_event) { + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ exception"); + } + else { + // Handle unexpected protocol events + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ *"); + } + break; + case expect_close_ok_state: if (self->event == close_ok_event) { if (!self->exception) { @@ -1623,6 +1694,10 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument) if (streq (method, "STOP")) { s_client_execute (self, stop_event); } + else + if (streq (method, "GET PEER LIST")) { + s_client_execute (self, get_peer_list_event); + } // Cleanup pipe if any argument frames are still waiting to be eaten if (zsock_rcvmore (self->cmdpipe)) { zsys_error ("wap_client: trailing API command frames (%s)", method); @@ -1753,6 +1828,8 @@ struct _wap_client_t { uint64_t incoming_connections_count; // Returned by actor reply uint64_t white_peerlist_size; // Returned by actor reply uint64_t grey_peerlist_size; // Returned by actor reply + zframe_t *white_list; // Returned by actor reply + zframe_t *gray_list; // Returned by actor reply }; @@ -1805,6 +1882,8 @@ wap_client_destroy (wap_client_t **self_p) zchunk_destroy (&self->tx_data); zframe_destroy (&self->o_indexes); zframe_destroy (&self->random_outputs); + zframe_destroy (&self->white_list); + zframe_destroy (&self->gray_list); free (self); *self_p = NULL; } @@ -1924,7 +2003,13 @@ s_accept_reply (wap_client_t *self, ...) } else if (streq (reply, "STOP OK")) { - zsock_recv (self->actor, "i", &self->status); + zsock_recv (self->actor, "8", &self->status); + } + else + if (streq (reply, "GET PEER LIST OK")) { + zframe_destroy (&self->white_list); + zframe_destroy (&self->gray_list); + zsock_recv (self->actor, "8pp", &self->status, &self->white_list, &self->gray_list); } break; } @@ -2143,6 +2228,22 @@ wap_client_stop (wap_client_t *self) } +// --------------------------------------------------------------------------- +// Get peer list +// Returns >= 0 if successful, -1 if interrupted. + +int +wap_client_get_peer_list (wap_client_t *self) +{ + assert (self); + + zsock_send (self->actor, "s", "GET PEER LIST"); + if (s_accept_reply (self, "GET PEER LIST OK", "FAILURE", NULL)) + return -1; // Interrupted or timed-out + return self->status; +} + + // --------------------------------------------------------------------------- // Return last received status @@ -2339,3 +2440,25 @@ wap_client_grey_peerlist_size (wap_client_t *self) assert (self); return self->grey_peerlist_size; } + + +// --------------------------------------------------------------------------- +// Return last received white_list + +zframe_t * +wap_client_white_list (wap_client_t *self) +{ + assert (self); + return self->white_list; +} + + +// --------------------------------------------------------------------------- +// Return last received gray_list + +zframe_t * +wap_client_gray_list (wap_client_t *self) +{ + assert (self); + return self->gray_list; +} diff --git a/src/ipc/include/wap_proto.h b/src/ipc/include/wap_proto.h index 7b7ad0ae1..a7ebab735 100644 --- a/src/ipc/include/wap_proto.h +++ b/src/ipc/include/wap_proto.h @@ -104,6 +104,13 @@ ERROR. white_peerlist_size number 8 White Peerlist Size grey_peerlist_size number 8 Grey Peerlist Size + GET_PEER_LIST - get_peer_list IPC + + GET_PEER_LIST_OK - This is a codec for a Bitcoin Wallet Access Protocol (RFC tbd) + status number 8 Status + white_list frame White list + gray_list frame Gray list + STOP - Wallet asks daemon to start mining. Daemon replies with STOP-OK, or ERROR. @@ -155,13 +162,15 @@ Daemon will reply with CLOSE-OK or ERROR. #define WAP_PROTO_START_OK 18 #define WAP_PROTO_GET_INFO 19 #define WAP_PROTO_GET_INFO_OK 20 -#define WAP_PROTO_STOP 21 -#define WAP_PROTO_STOP_OK 22 -#define WAP_PROTO_CLOSE 23 -#define WAP_PROTO_CLOSE_OK 24 -#define WAP_PROTO_PING 25 -#define WAP_PROTO_PING_OK 26 -#define WAP_PROTO_ERROR 27 +#define WAP_PROTO_GET_PEER_LIST 21 +#define WAP_PROTO_GET_PEER_LIST_OK 22 +#define WAP_PROTO_STOP 23 +#define WAP_PROTO_STOP_OK 24 +#define WAP_PROTO_CLOSE 25 +#define WAP_PROTO_CLOSE_OK 26 +#define WAP_PROTO_PING 27 +#define WAP_PROTO_PING_OK 28 +#define WAP_PROTO_ERROR 29 #include @@ -397,6 +406,26 @@ uint64_t void wap_proto_set_grey_peerlist_size (wap_proto_t *self, uint64_t grey_peerlist_size); +// Get a copy of the white_list field +zframe_t * + wap_proto_white_list (wap_proto_t *self); +// Get the white_list field and transfer ownership to caller +zframe_t * + wap_proto_get_white_list (wap_proto_t *self); +// Set the white_list field, transferring ownership from caller +void + wap_proto_set_white_list (wap_proto_t *self, zframe_t **frame_p); + +// Get a copy of the gray_list field +zframe_t * + wap_proto_gray_list (wap_proto_t *self); +// Get the gray_list field and transfer ownership to caller +zframe_t * + wap_proto_get_gray_list (wap_proto_t *self); +// Set the gray_list field, transferring ownership from caller +void + wap_proto_set_gray_list (wap_proto_t *self, zframe_t **frame_p); + // Get/set the reason field const char * wap_proto_reason (wap_proto_t *self); diff --git a/src/ipc/include/wap_server_engine.inc b/src/ipc/include/wap_server_engine.inc index cc4a6a1e4..8442f3422 100644 --- a/src/ipc/include/wap_server_engine.inc +++ b/src/ipc/include/wap_server_engine.inc @@ -41,11 +41,12 @@ typedef enum { random_outs_event = 10, get_height_event = 11, get_info_event = 12, - close_event = 13, - ping_event = 14, - expired_event = 15, - exception_event = 16, - settled_event = 17 + get_peer_list_event = 13, + close_event = 14, + ping_event = 15, + expired_event = 16, + exception_event = 17, + settled_event = 18 } event_t; // Names for state machine logging and error reporting @@ -73,6 +74,7 @@ s_event_name [] = { "RANDOM_OUTS", "GET_HEIGHT", "GET_INFO", + "GET_PEER_LIST", "CLOSE", "PING", "expired", @@ -162,6 +164,8 @@ static void height (client_t *self); static void getinfo (client_t *self); +static void + get_peer_list (client_t *self); static void deregister_wallet (client_t *self); static void @@ -376,6 +380,9 @@ s_protocol_event (wap_proto_t *message) case WAP_PROTO_GET_INFO: return get_info_event; break; + case WAP_PROTO_GET_PEER_LIST: + return get_peer_list_event; + break; case WAP_PROTO_STOP: return stop_event; break; @@ -774,6 +781,24 @@ s_client_execute (s_client_t *self, event_t event) } } else + if (self->event == get_peer_list_event) { + if (!self->exception) { + // get peer list + if (self->server->verbose) + zsys_debug ("%s: $ get peer list", self->log_prefix); + get_peer_list (&self->client); + } + if (!self->exception) { + // send GET_PEER_LIST_OK + if (self->server->verbose) + zsys_debug ("%s: $ send GET_PEER_LIST_OK", + self->log_prefix); + wap_proto_set_id (self->server->message, WAP_PROTO_GET_PEER_LIST_OK); + wap_proto_set_routing_id (self->server->message, self->routing_id); + wap_proto_send (self->server->message, self->server->router); + } + } + else if (self->event == close_event) { if (!self->exception) { // send CLOSE_OK diff --git a/src/ipc/wap_client/wap_client.c b/src/ipc/wap_client/wap_client.c index cb4be741e..00b717fe7 100644 --- a/src/ipc/wap_client/wap_client.c +++ b/src/ipc/wap_client/wap_client.c @@ -396,3 +396,16 @@ signal_have_get_info_ok (client_t *self) wap_proto_white_peerlist_size (self->message), wap_proto_grey_peerlist_size (self->message)); } + +// --------------------------------------------------------------------------- +// signal_have_get_get_peer_list_ok +// + +static void +signal_have_get_peer_list_ok (client_t *self) +{ + zsock_send (self->cmdpipe, "s8pp", "GET PEER LIST OK", + wap_proto_status (self->message), + wap_proto_get_white_list (self->message), + wap_proto_get_gray_list (self->message)); +} diff --git a/src/ipc/wap_proto.c b/src/ipc/wap_proto.c index 0d4c9c16a..49b77c7d5 100644 --- a/src/ipc/wap_proto.c +++ b/src/ipc/wap_proto.c @@ -59,6 +59,8 @@ struct _wap_proto_t { uint64_t incoming_connections_count; // Incoming Connections Count uint64_t white_peerlist_size; // White Peerlist Size uint64_t grey_peerlist_size; // Grey Peerlist Size + zframe_t *white_list; // White list + zframe_t *gray_list; // Gray list char reason [256]; // Printable explanation }; @@ -245,6 +247,8 @@ wap_proto_destroy (wap_proto_t **self_p) zframe_destroy (&self->random_outputs); zchunk_destroy (&self->tx_data); zchunk_destroy (&self->address); + zframe_destroy (&self->white_list); + zframe_destroy (&self->gray_list); // Free object itself free (self); @@ -488,6 +492,27 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input) GET_NUMBER8 (self->grey_peerlist_size); break; + case WAP_PROTO_GET_PEER_LIST: + break; + + case WAP_PROTO_GET_PEER_LIST_OK: + GET_NUMBER8 (self->status); + // Get next frame off socket + if (!zsock_rcvmore (input)) { + zsys_warning ("wap_proto: white_list is missing"); + goto malformed; + } + zframe_destroy (&self->white_list); + self->white_list = zframe_recv (input); + // Get next frame off socket + if (!zsock_rcvmore (input)) { + zsys_warning ("wap_proto: gray_list is missing"); + goto malformed; + } + zframe_destroy (&self->gray_list); + self->gray_list = zframe_recv (input); + break; + case WAP_PROTO_STOP: break; @@ -624,6 +649,9 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) frame_size += 8; // white_peerlist_size frame_size += 8; // grey_peerlist_size break; + case WAP_PROTO_GET_PEER_LIST_OK: + frame_size += 8; // status + break; case WAP_PROTO_ERROR: frame_size += 2; // status frame_size += 1 + strlen (self->reason); @@ -774,6 +802,12 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) PUT_NUMBER8 (self->grey_peerlist_size); break; + case WAP_PROTO_GET_PEER_LIST_OK: + PUT_NUMBER8 (self->status); + nbr_frames++; + nbr_frames++; + break; + case WAP_PROTO_ERROR: PUT_NUMBER2 (self->status); PUT_STRING (self->reason); @@ -807,6 +841,19 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) else zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0)); } + // Now send any frame fields, in order + if (self->id == WAP_PROTO_GET_PEER_LIST_OK) { + // If white_list isn't set, send an empty frame + if (self->white_list) + zframe_send (&self->white_list, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0)); + else + zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0)); + // If gray_list isn't set, send an empty frame + if (self->gray_list) + zframe_send (&self->gray_list, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0)); + else + zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0)); + } // Now send the block_data if necessary if (have_block_data) { if (self->block_data) { @@ -971,6 +1018,25 @@ wap_proto_print (wap_proto_t *self) zsys_debug (" grey_peerlist_size=%ld", (long) self->grey_peerlist_size); break; + case WAP_PROTO_GET_PEER_LIST: + zsys_debug ("WAP_PROTO_GET_PEER_LIST:"); + break; + + case WAP_PROTO_GET_PEER_LIST_OK: + zsys_debug ("WAP_PROTO_GET_PEER_LIST_OK:"); + zsys_debug (" status=%ld", (long) self->status); + zsys_debug (" white_list="); + if (self->white_list) + zframe_print (self->white_list, NULL); + else + zsys_debug ("(NULL)"); + zsys_debug (" gray_list="); + if (self->gray_list) + zframe_print (self->gray_list, NULL); + else + zsys_debug ("(NULL)"); + break; + case WAP_PROTO_STOP: zsys_debug ("WAP_PROTO_STOP:"); break; @@ -1108,6 +1174,12 @@ wap_proto_command (wap_proto_t *self) case WAP_PROTO_GET_INFO_OK: return ("GET_INFO_OK"); break; + case WAP_PROTO_GET_PEER_LIST: + return ("GET_PEER_LIST"); + break; + case WAP_PROTO_GET_PEER_LIST_OK: + return ("GET_PEER_LIST_OK"); + break; case WAP_PROTO_STOP: return ("STOP"); break; @@ -1724,6 +1796,72 @@ wap_proto_set_grey_peerlist_size (wap_proto_t *self, uint64_t grey_peerlist_size } +// -------------------------------------------------------------------------- +// Get the white_list field without transferring ownership + +zframe_t * +wap_proto_white_list (wap_proto_t *self) +{ + assert (self); + return self->white_list; +} + +// Get the white_list field and transfer ownership to caller + +zframe_t * +wap_proto_get_white_list (wap_proto_t *self) +{ + zframe_t *white_list = self->white_list; + self->white_list = NULL; + return white_list; +} + +// Set the white_list field, transferring ownership from caller + +void +wap_proto_set_white_list (wap_proto_t *self, zframe_t **frame_p) +{ + assert (self); + assert (frame_p); + zframe_destroy (&self->white_list); + self->white_list = *frame_p; + *frame_p = NULL; +} + + +// -------------------------------------------------------------------------- +// Get the gray_list field without transferring ownership + +zframe_t * +wap_proto_gray_list (wap_proto_t *self) +{ + assert (self); + return self->gray_list; +} + +// Get the gray_list field and transfer ownership to caller + +zframe_t * +wap_proto_get_gray_list (wap_proto_t *self) +{ + zframe_t *gray_list = self->gray_list; + self->gray_list = NULL; + return gray_list; +} + +// Set the gray_list field, transferring ownership from caller + +void +wap_proto_set_gray_list (wap_proto_t *self, zframe_t **frame_p) +{ + assert (self); + assert (frame_p); + zframe_destroy (&self->gray_list); + self->gray_list = *frame_p; + *frame_p = NULL; +} + + // -------------------------------------------------------------------------- // Get/set the reason field @@ -2079,6 +2217,36 @@ wap_proto_test (bool verbose) assert (wap_proto_white_peerlist_size (self) == 123); assert (wap_proto_grey_peerlist_size (self) == 123); } + wap_proto_set_id (self, WAP_PROTO_GET_PEER_LIST); + + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + } + wap_proto_set_id (self, WAP_PROTO_GET_PEER_LIST_OK); + + wap_proto_set_status (self, 123); + zframe_t *get_peer_list_ok_white_list = zframe_new ("Captcha Diem", 12); + wap_proto_set_white_list (self, &get_peer_list_ok_white_list); + zframe_t *get_peer_list_ok_gray_list = zframe_new ("Captcha Diem", 12); + wap_proto_set_gray_list (self, &get_peer_list_ok_gray_list); + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + assert (wap_proto_status (self) == 123); + assert (zframe_streq (wap_proto_white_list (self), "Captcha Diem")); + zframe_destroy (&get_peer_list_ok_white_list); + assert (zframe_streq (wap_proto_gray_list (self), "Captcha Diem")); + zframe_destroy (&get_peer_list_ok_gray_list); + } wap_proto_set_id (self, WAP_PROTO_STOP); // Send twice diff --git a/src/ipc/wap_server/wap_server.c b/src/ipc/wap_server/wap_server.c index 9f108763f..cba82210d 100644 --- a/src/ipc/wap_server/wap_server.c +++ b/src/ipc/wap_server/wap_server.c @@ -300,3 +300,13 @@ getinfo (client_t *self) { IPC::Daemon::get_info(self->message); } + +// --------------------------------------------------------------------------- +// get_peer_list +// + +static void +get_peer_list (client_t *self) +{ + IPC::Daemon::get_peer_list(self->message); +} diff --git a/src/rpc/daemon_deprecated_rpc.cpp b/src/rpc/daemon_deprecated_rpc.cpp index a6154c8ac..465898b70 100644 --- a/src/rpc/daemon_deprecated_rpc.cpp +++ b/src/rpc/daemon_deprecated_rpc.cpp @@ -18,7 +18,7 @@ #include "daemon_deprecated_rpc.h" #include -#define MAX_RESPONSE_SIZE 2000 +#define MAX_RESPONSE_SIZE 100000 /*! * \namespace @@ -56,7 +56,7 @@ namespace * It also adds boilerplate properties like id, method. * \param req net_skeleton request object * \param result_json rapidjson result object - * \param response_json Root rapidjson document that will eventually have the whole response + * \param response_json "Root" rapidjson document that will eventually have the whole response * \param response Response as a string gets written here. */ void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json, @@ -246,12 +246,64 @@ namespace return response.length(); } + /*! + * \brief Implementation of 'getpeerlist' method. + * \param buf Buffer to fill in response. + * \param len Max length of response. + * \param req net_skeleton RPC request + * \return Actual response length. + */ + int getpeerlist(char *buf, int len, struct ns_rpc_request *req) + { + connect_to_daemon(); + int rc = wap_client_get_peer_list(ipc_client); + if (rc < 0) { + return ns_rpc_create_error(buf, len, req, daemon_connection_error, + "Couldn't connect to daemon.", "{}"); + } + + rapidjson::Document response_json; + rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator(); + rapidjson::Value result_json; + result_json.SetObject(); + + zframe_t *white_list_frame = wap_client_white_list(ipc_client); + rapidjson::Document white_list_json; + char *data = reinterpret_cast(zframe_data(white_list_frame)); + size_t size = zframe_size(white_list_frame); + + if (white_list_json.Parse(data, size).HasParseError()) { + return ns_rpc_create_error(buf, len, req, internal_error, + "Couldn't parse JSON sent by daemon.", "{}"); + } + + result_json.AddMember("white_list", white_list_json["peers"], allocator); + + zframe_t *gray_list_frame = wap_client_gray_list(ipc_client); + rapidjson::Document gray_list_json; + data = reinterpret_cast(zframe_data(gray_list_frame)); + size = zframe_size(gray_list_frame); + + if (gray_list_json.Parse(data, size).HasParseError()) { + return ns_rpc_create_error(buf, len, req, internal_error, + "Couldn't parse JSON sent by daemon.", "{}"); + } + result_json.AddMember("gray_list", gray_list_json["peers"], allocator); + + std::string response; + construct_response_string(req, result_json, response_json, response); + size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; + strncpy(buf, response.c_str(), copy_length); + return response.length(); + } + // Contains a list of method names. const char *method_names[] = { "getheight", "startmining", "stopmining", "getinfo", + "getpeerlist", NULL }; @@ -261,6 +313,7 @@ namespace startmining, stopmining, getinfo, + getpeerlist, NULL };