From 5965dd85c2dbf4b95793f9e87a25e67d33046cd0 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Tue, 25 Jan 2022 12:44:55 +1300 Subject: [PATCH 01/44] fix: overwrote doc --- doc/happy path.drawio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/happy path.drawio b/doc/happy path.drawio index 84ea1c5..f8eb914 100644 --- a/doc/happy path.drawio +++ b/doc/happy path.drawio @@ -1 +1 @@ -1ZdNc5swEIZ/Dcd2+IiJc0wcNzm0J3fS5pRRYANKBcsIYaC/vgIWYxV/tdPU5IT0akHadx/tDJa3SKo7ybL4C4YgLNcOK8u7tVzXcWxXPxql7pS5P+uESPKQggZhxX8CiTapBQ8hNwIVolA8M8UA0xQCZWhMSizNsBcU5q4Zi2AkrAImxuo3HqqYsnAvB/0eeBT3Ozv+VbeSsD6YMsljFmK5JXlLy1tIRNWNkmoBojGv96V779Oe1c3BJKTqlBfkGuJHl72G4dd7Uav84YGrD45Hh1N1nzGE2gCaolQxRpgysRzUG4lFGkLzWVvPhpjPiJkWHS2+glI1VZMVCrUUq0TQqj6xrL8373+c9dNH+lw7ua2MWU2zccrkQo6FDOBQnoQOkxGoQ3FUrMaErR3I0TvABPSBdIAEwRRfm5Qwgi3axA310AMqyZ+Up/vumomCdgoE18knjKejwpllKWOuYJWx1pZSX06zBHutXINUUB3MnVYverPoajsezcvhojg9/fHWJfHtN7LrcmTXOej+e0rdEyn1JwWpO3K9bbLXLQmp7nn5U47BD52R6wud1s2z1KOoGaWgG+J1H5Xp076gTEZFO8KyWbF/QbZtku05O8i++J9kO/47R9s/Ee35pNAeu74T7X1g77gB5yb7t569If1sPXu+32LIeHCkdTR+KMwma+/Vue11Zu+8cfSOHu0c7qQ6R3/sXVwfRboLeGqAzUBOjurNL80bUK2nwy9Ru7b1Y+ktfwE= \ No newline at end of file +5Vtdd6M2EP01Ptt92D2AANuPjuPttt1N3Din2+yLjwKKUYMRRwh/5NdXAgEGJQ6NY4PpQ2JpJBlpdO9oZoR7YLzc/Eph6H0nLvJ7huZueuCyZxi6PRzyDyHZppKBZqaCBcWu7FQIZvgJSaEmpTF2UVTqyAjxGQ7LQocEAXJYSQYpJetytwfil58awgVSBDMH+qr0B3aZJ1dhaYX8K8ILL3uyrsmWJcw6S0HkQZesd0Rg0gNjSghLS8vNGPlCeZle0nFfXmjNJ0ZRwOoMePrpbLSIOkj/68/Q+/23P2b2wye5GSvox3LBcrJsm2kAuVwhskoo88iCBNCfFNILSuLAReIxGq8Vfb4REnKhzoX/IMa2cndhzAgXeWzpy9b0meJBL65NiiIS8xXsWVCGEUgXiO3pB/Id4NBFZIkY3fJxFPmQ4VV5HlBiaJH3K9TMC1LT/0HruqL1GZ8wU1RfVuzawwzNQpisf83p9pwSV4gytNmvRnXZ2QBTYlWS1chgvi6gr2d49nZgb2tH0tSwa/gENfE5aBKfQNH6WJpXYX35vxvEFfq0InHEKzNEOep6hu3zBV3ci9JClBwfc/XMcYDZ/BGzXz7yvp+EqU7kn50wbBzwoHWA11XbcOaIH9REvK49v1WngfxANckc4wLqk9Hl3fzL9c18akx5fXTFG7Xvd/PL0e1InPMoirgTEL0L/l9BfHlb3wH/VhX/oCb+czfn/QmgGp8zJ0Dmyr7OAKNRp0RTFP8DYpY4zVQ8kP+Nr6+uJuPb+XQyuSmwL7pQshRL9EQleuFACClx+Ih52j53IYNtJEW/haSwOkcKoy4pzEZJ0f//Kt5uVPHt8PzRBrO/xfDPlqzd7bRcbuQ3J5VtyQSdeLMOjReSoSNK4XanQ0hwwKKdb54KQWEpB1rZUprVFESlv90/rL9laxVgpTMuYJYv/QDkGQryRoyhZZhHP1+JL465aRw43ptPOTAamq076sCw6fjH6J77Z9bksNGs+6emApOklIjwv+GIoQAHi9wZvOaenvicIkQ/iC4yQYBJcLZ+nzmokMGsSYbB0chgd44Mdl0yWI2SQVV85QyoJMRyHkzjex87vDAJ3DA9zTpCB7NuGHQ8OrTDJ3xPOtRNjhmN5oN1NTtWlw4UryBDXeSDZTTNB9A5X8momyoDh/pKb4p3dLtiEvsniEcynbxMvlHMvbGAYSdl2ow4j2gPz/gOem0kmF49cOr6X8cLRtQI7RQ5h4DPfSfpIKp38uuSSpF2SGpHyDtkhuT1c+nQS5s38dCohq0n4aGaFyjlx0VEhDJK3osS3CGjBlcQ+/BeZA7O9AAEoKL1xi9Lgd0oP/USOwuynoCf1qn4eZj9VK8tSpTB+REWxY6D+KZ0hRvNn13ZhNpxdukn5EbtmKpZbqgx1Wvc0M6UDFbdzMHxyNC5+1NQ10MDjd6fZtPcRTn6sBLekXxjNwF2gvP05YEQ7Xt1QLS2Fvd65TrMbh73qpE5d9zXvU0B/UZxr96m3FIYRMvErIvA4AH76DnkJ6CuB3ft9mLcOOirxr4FoFff2bhBDsKJ1ZFqd7w4eBQJSvni0nnqvpqSPKbuebX4rUIaUxe/+ACTfwE= \ No newline at end of file From 3abbda12e4e663dd6f457f24983cd5801dc70edf Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Tue, 25 Jan 2022 12:47:00 +1300 Subject: [PATCH 02/44] chore: rm noise --- doc/happy path.drawio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/happy path.drawio b/doc/happy path.drawio index f8eb914..09e734b 100644 --- a/doc/happy path.drawio +++ b/doc/happy path.drawio @@ -1 +1 @@ -5Vtdd6M2EP01Ptt92D2AANuPjuPttt1N3Din2+yLjwKKUYMRRwh/5NdXAgEGJQ6NY4PpQ2JpJBlpdO9oZoR7YLzc/Eph6H0nLvJ7huZueuCyZxi6PRzyDyHZppKBZqaCBcWu7FQIZvgJSaEmpTF2UVTqyAjxGQ7LQocEAXJYSQYpJetytwfil58awgVSBDMH+qr0B3aZJ1dhaYX8K8ILL3uyrsmWJcw6S0HkQZesd0Rg0gNjSghLS8vNGPlCeZle0nFfXmjNJ0ZRwOoMePrpbLSIOkj/68/Q+/23P2b2wye5GSvox3LBcrJsm2kAuVwhskoo88iCBNCfFNILSuLAReIxGq8Vfb4REnKhzoX/IMa2cndhzAgXeWzpy9b0meJBL65NiiIS8xXsWVCGEUgXiO3pB/Id4NBFZIkY3fJxFPmQ4VV5HlBiaJH3K9TMC1LT/0HruqL1GZ8wU1RfVuzawwzNQpisf83p9pwSV4gytNmvRnXZ2QBTYlWS1chgvi6gr2d49nZgb2tH0tSwa/gENfE5aBKfQNH6WJpXYX35vxvEFfq0InHEKzNEOep6hu3zBV3ci9JClBwfc/XMcYDZ/BGzXz7yvp+EqU7kn50wbBzwoHWA11XbcOaIH9REvK49v1WngfxANckc4wLqk9Hl3fzL9c18akx5fXTFG7Xvd/PL0e1InPMoirgTEL0L/l9BfHlb3wH/VhX/oCb+czfn/QmgGp8zJ0Dmyr7OAKNRp0RTFP8DYpY4zVQ8kP+Nr6+uJuPb+XQyuSmwL7pQshRL9EQleuFACClx+Ih52j53IYNtJEW/haSwOkcKoy4pzEZJ0f//Kt5uVPHt8PzRBrO/xfDPlqzd7bRcbuQ3J5VtyQSdeLMOjReSoSNK4XanQ0hwwKKdb54KQWEpB1rZUprVFESlv90/rL9laxVgpTMuYJYv/QDkGQryRoyhZZhHP1+JL465aRw43ptPOTAamq076sCw6fjH6J77Z9bksNGs+6emApOklIjwv+GIoQAHi9wZvOaenvicIkQ/iC4yQYBJcLZ+nzmokMGsSYbB0chgd44Mdl0yWI2SQVV85QyoJMRyHkzjex87vDAJ3DA9zTpCB7NuGHQ8OrTDJ3xPOtRNjhmN5oN1NTtWlw4UryBDXeSDZTTNB9A5X8momyoDh/pKb4p3dLtiEvsniEcynbxMvlHMvbGAYSdl2ow4j2gPz/gOem0kmF49cOr6X8cLRtQI7RQ5h4DPfSfpIKp38uuSSpF2SGpHyDtkhuT1c+nQS5s38dCohq0n4aGaFyjlx0VEhDJK3osS3CGjBlcQ+/BeZA7O9AAEoKL1xi9Lgd0oP/USOwuynoCf1qn4eZj9VK8tSpTB+REWxY6D+KZ0hRvNn13ZhNpxdukn5EbtmKpZbqgx1Wvc0M6UDFbdzMHxyNC5+1NQ10MDjd6fZtPcRTn6sBLekXxjNwF2gvP05YEQ7Xt1QLS2Fvd65TrMbh73qpE5d9zXvU0B/UZxr96m3FIYRMvErIvA4AH76DnkJ6CuB3ft9mLcOOirxr4FoFff2bhBDsKJ1ZFqd7w4eBQJSvni0nnqvpqSPKbuebX4rUIaUxe/+ACTfwE= \ No newline at end of file +5Zpbd5s4EIB/jU+fdg93u49ex213t028cU7b7EuOAhOjLUYcIXzJr18JhLloN6a1HcTpQ2I0DCAN34xmJEb2bL17T1ESfiIBRCPLCHYj+2pkWaZpWPxHSPaFZOK5hWBFcSCVKsESP4MUGlKa4QDShiIjJGI4aQp9Esfgs4YMUUq2TbUnEjWfmqAVKIKljyJV+gUHLJSjcI1K/gHwKmSHAcsza1QqS0EaooBsayJ7PrJnlBBWHK13M4iE8Uq7FNe9+5+zh45RiFmXC57/9ndGSn0wP/+VhH/8/ufSe/rFKe6yQVEmByw7y/alBSDgBpFNQllIViRG0byS/kZJFgcgHmPwVqXzkZCEC00u/AcY28u3izJGuChk60ieVYciR5eSjHf4hf6XSCC6AvaCnl3oibHUHiAN9R7IGhjdcwUKEWJ403z5SDK0OuhVZuYH0tLfYXVTsfqSj4Appm8adhtiBssE5QbZcnfraMQNUAa7F4ddnnUkq9JZrRLzbYW+WfIc1rD3jAtZ6u3A+bQ78jnRik9bsfpMhlcRffm/W+AGfd6QLOWNJVCOWO/w2trBa6p+Pix6Jx3pLSdrTfCdqOGV8yqwnU+v7h/e3dw+LKwFb0+v+Unj0/3D1fRuKuZsSFM+oafKWzpCb/MVnYFlt82y3ZHlQ/pxfpjVoDAsmEtIj9NsaUVz2e+a4b8gzPJklooH8r/ZzfX1fHb3sJjPbyuOhQolazHmUDTS/w7Urw33WEO43aHDbXWF29EL7vFPY3hPL8PrkVnDDrOv4vJfXdm6r5252sk75439sRB0xpd19nw8v3RKKdrXFBKCY5bW7rwQgipSToxmpHTaJX5L3xufpu96RgusoscVZoehn0CepZA3ZQzWyaG6+EAiMV0tstgPtZut7Ld9lxXW4DMxp6MblgPTJWaqq2X5uo0ogj/ilEGM49UhL7vhSZf4XQDQN0JF1tCYxL1D7UxaUDsdoZ5cDGpv6FB7XaF29YJaNXwrHLfWfg48L7LHCPv8YB4HSTGxaIa107WyuBzWeqRZJ2DddQ3I0msJ01QXgbpiTfEGMdCZa9fqm2t76DmI1XU1yD57DvJDpYDptULb+BVSdUtdemo50TTjWU7MsF94zJL436B/fzHb80DX9OZyObvTh3twC9J9rbwWzXt5u7xRFdh56/QKuwwDx6eLs28Z/JBbWe3q7lXcSq2AGyu6onCA0sMexRGq+ZaBNghH6FHUyD37mW23rNf7lpvt9epnZsPLKqc7v5+5vfnZaXFQXWhvoI8PM0ua+T7wl6Ib4/3PJWWH9JhLzMsx3rn00IxxtfQYGONu17r5cowPfUOuLBuO1xd6bciV/a7DC282IgmRn1gKXgt8i13lBDTYUzZbOyVe/wSrUWBgBHddpbfHehGsrtLfURSn6zzuikz6CUegIcPtKKwBw+ru/C34gPNwIK3oh1n8TaybyU9NtDBle8Hskqbkzeoj7qJErD6Ft+f/Ag== \ No newline at end of file From 50aa010f12350c8e37ea0da7d2428e516b457306 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Tue, 25 Jan 2022 14:31:48 +1300 Subject: [PATCH 03/44] chore: debug client on linux --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9b55058..a45623f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "(Linux) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/build/ptop_rendezvous", + "program": "${workspaceFolder}/build/ptop", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", From 809edfea7882527e58827fca0da56e6e49e166bb Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 13:29:54 +1300 Subject: [PATCH 04/44] refactor: clearer name --- src/client.cpp | 84 ++++++++++++++++++++++----------------------- src/client.h | 6 ++-- src/ptop_socket.cpp | 2 +- 3 files changed, 45 insertions(+), 47 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index a16397f..e469b2f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -13,22 +13,22 @@ using namespace std::chrono; client_init_kit::client_init_kit(std::string server_address_pair, ::protocol chosen_protocol) : protocol(chosen_protocol) { - _conn_socket = std::make_unique(server_address_pair, ServerListenPort, protocol); + _server_socket = std::make_unique(server_address_pair, ServerListenPort, protocol); // Indicate to server we're ready for p2p last_send = std::chrono::system_clock::now(); - _conn_socket->send_data(create_message(MESSAGE_TYPE::MY_DATA, _conn_socket->get_myname_readable().to_bytes())); - _conn_socket->send_data(create_message(MESSAGE_TYPE::READY_FOR_P2P)); + _server_socket->send_data(create_message(MESSAGE_TYPE::MY_DATA, _server_socket->get_myname_readable().to_bytes())); + _server_socket->send_data(create_message(MESSAGE_TYPE::READY_FOR_P2P)); status = EXECUTION_STATUS::CONTINUE; //int value types will update themselves protocol = chosen_protocol; } -std::unique_ptr& client_init_kit::get_conn_socket() { - return _conn_socket; //yay bug +std::unique_ptr& client_init_kit::get_server_socket() { + return _server_socket; //yay bug } -void client_init_kit::set_conn_socket(std::unique_ptr&& input) { - _conn_socket = std::move(input); +void client_init_kit::set_server_socket(std::unique_ptr&& input) { + _server_socket = std::move(input); if(input == nullptr) std::cout << "client_init_kit: connection socket set to nullptr mmk?" << std::endl; @@ -40,7 +40,7 @@ client_auth_kit::client_auth_kit(client_init_kit& init_kit, const char* data, in std::cout << "Target is: " << peer_private.ip_address << ":" << peer_private.port << "/" << peer_public.ip_address << ":" << peer_public.port << " priv/pub" << std::endl; auth_key_out = read_data(data, i, data_len); - old_privatename = init_kit.get_conn_socket()->get_myname_raw(); + old_privatename = init_kit.get_server_socket()->get_myname_raw(); init_kit.set_conn_socket(nullptr); listen_sock = std::make_unique(old_privatename, init_kit.protocol); @@ -90,6 +90,32 @@ EXECUTION_STATUS process_auth(const Message& mess, std::unique_ptr 0; ) + { + auto& sock = auth_kit.unauthed_sockets[i]; + + if (sock && sock->has_message()) + { + auto status = process_auth(sock->receive_message(), sock, auth_kit.auth_key_out); + + if (status == EXECUTION_STATUS::FAILED) + { + std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has failed to authenticate" << std::endl; + auth_kit.unauthed_sockets.pop_back(); + } + + else if (status == EXECUTION_STATUS::CONNECTED) + { + std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has successfully authenticated" << std::endl; + init_kit.set_server_socket(std::move(sock)); //caused a bug if we dont return immediately after + return EXECUTION_STATUS::CONNECTED; //we only care if either private or public sockets got punched, not both + } + } + } + return EXECUTION_STATUS::CONTINUE; +} + bool check_for_auth_connection(client_init_kit& init_kit, client_auth_kit& auth_kit) { if (auth_kit.unauthed_sockets.size()) return true; @@ -151,59 +177,31 @@ bool check_for_auth_connection(client_init_kit& init_kit, client_auth_kit& auth_ } } -EXECUTION_STATUS respond_to_auth(client_init_kit& init_kit, client_auth_kit& auth_kit) { - for (size_t i = auth_kit.unauthed_sockets.size(); i-- > 0; ) - { - auto& sock = auth_kit.unauthed_sockets[i]; - - if (sock && sock->has_message()) - { - auto status = process_auth(sock->receive_message(), sock, auth_kit.auth_key_out); - - if (status == EXECUTION_STATUS::FAILED) - { - std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has failed to authenticate" << std::endl; - auth_kit.unauthed_sockets.pop_back(); - } - - else if (status == EXECUTION_STATUS::CONNECTED) - { - std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has successfully authenticated" << std::endl; - init_kit.set_conn_socket(std::move(sock)); //caused a bug if we dont return immediately after - return EXECUTION_STATUS::CONNECTED; //we only care if either private or public sockets got punched, not both - } - } - } - return EXECUTION_STATUS::CONTINUE; -} - /// Server giving us a peer to connect to /// Attempt to connect to peer by connecting to it and listening for a connection /// The connect socket must have same local address binding as the socket that connected to the server /// And we must disconnect the connection to the server -EXECUTION_STATUS hole_punch(client_init_kit& kit, const char* data, int& auth_key_out, int i, MESSAGE_LENGTH_T data_len) { +EXECUTION_STATUS hole_punch(client_init_kit& init_kit, const char* data, int& auth_key_out, int i, MESSAGE_LENGTH_T data_len) { try { std::cout << "Attempting to Hole Punch" << std::endl; - client_auth_kit auth_kit{kit, data, i, data_len}; + client_auth_kit auth_kit{init_kit, data, i, data_len}; auto start_time = std::chrono::system_clock::now(); auto current_time = start_time; - bool connection_made = false; do { if(connection_made == false) - connection_made = check_for_auth_connection(kit, auth_kit); + connection_made = check_for_auth_connection(init_kit, auth_kit); else { - auto auth_status = respond_to_auth(kit, auth_kit); + auto auth_status = respond_to_auth(init_kit, auth_kit); if (auth_status == EXECUTION_STATUS::CONNECTED) return auth_status; - } - + } std::this_thread::sleep_for(100ms); } @@ -249,7 +247,7 @@ EXECUTION_STATUS process_server_data(client_init_kit& kit, const Message& messag return EXECUTION_STATUS::CONTINUE; } case MESSAGE_TYPE::CONNECT_PEER: - { + { return hole_punch(kit, data, kit.auth_key, i, data_len); } @@ -327,7 +325,7 @@ void client_loop(std::string server_address_pair, protocol input_protocol) std::cout << "Starting ptop!" << std::endl; std::cout << "Connecting to rendezvous server: " << server_address_pair << std::endl; client_init_kit kit{ server_address_pair, input_protocol }; - auto& connection_socket = kit.get_conn_socket(); + auto& connection_socket = kit.get_server_socket(); while (kit.status == EXECUTION_STATUS::CONTINUE) //listen at the start of protocol { diff --git a/src/client.h b/src/client.h index 0bd1064..95d6717 100644 --- a/src/client.h +++ b/src/client.h @@ -21,11 +21,11 @@ class client_init_kit { ::protocol protocol; bool is_leader; - std::unique_ptr& get_conn_socket(); - void set_conn_socket(std::unique_ptr&& input); + std::unique_ptr& get_server_socket(); + void set_server_socket(std::unique_ptr&& input); protected: - std::unique_ptr _conn_socket; + std::unique_ptr _server_socket; }; class client_auth_kit { diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 04757e6..c73f623 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -186,7 +186,7 @@ bool PtopSocket::has_message() const int n = select((int)_handle + 1, &poll_read_set, 0, 0, &timeout); throw_if_socket_error(n, "Failed to poll linux socket readability " + get_last_error(), LINE_CONTEXT); - return n > 0; + return n > 0; //returns number of sockets ready, 0 if timed out, -1 if socket error } bool PtopSocket::has_died() const From 16e099f5de2b9795f6a801a3d6c0dc77b6922fc1 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 13:30:09 +1300 Subject: [PATCH 05/44] rm: pointless line --- src/client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index e469b2f..3ff1271 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -41,7 +41,6 @@ client_auth_kit::client_auth_kit(client_init_kit& init_kit, const char* data, in auth_key_out = read_data(data, i, data_len); old_privatename = init_kit.get_server_socket()->get_myname_raw(); - init_kit.set_conn_socket(nullptr); listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); From c73950994b8f6707b259781c3ecf1bf5916c14db Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 13:30:09 +1300 Subject: [PATCH 06/44] Revert "rm: pointless line" This reverts commit 16e099f5de2b9795f6a801a3d6c0dc77b6922fc1. --- src/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client.cpp b/src/client.cpp index 3ff1271..e469b2f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -41,6 +41,7 @@ client_auth_kit::client_auth_kit(client_init_kit& init_kit, const char* data, in auth_key_out = read_data(data, i, data_len); old_privatename = init_kit.get_server_socket()->get_myname_raw(); + init_kit.set_conn_socket(nullptr); listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); From 8da522bde8550334bd706a80d4021e1ca8d87955 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:18:13 +1300 Subject: [PATCH 07/44] feat: simplified peer protocol --- src/client.cpp | 426 +++++++++++++++++---------------------- src/client.h | 22 +- src/loop.h | 8 +- src/message.h | 24 +-- src/server.cpp | 4 +- src/server.h | 2 + src/windows_platform.cpp | 3 +- 7 files changed, 210 insertions(+), 279 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index e469b2f..a0fdc23 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -9,16 +9,14 @@ #include - using namespace std::chrono; client_init_kit::client_init_kit(std::string server_address_pair, ::protocol chosen_protocol) : protocol(chosen_protocol) { _server_socket = std::make_unique(server_address_pair, ServerListenPort, protocol); // Indicate to server we're ready for p2p - last_send = std::chrono::system_clock::now(); + server_last_send = std::chrono::system_clock::now(); _server_socket->send_data(create_message(MESSAGE_TYPE::MY_DATA, _server_socket->get_myname_readable().to_bytes())); _server_socket->send_data(create_message(MESSAGE_TYPE::READY_FOR_P2P)); - status = EXECUTION_STATUS::CONTINUE; //int value types will update themselves protocol = chosen_protocol; } @@ -34,181 +32,100 @@ void client_init_kit::set_server_socket(std::unique_ptr&& in std::cout << "client_init_kit: connection socket set to nullptr mmk?" << std::endl; } -client_auth_kit::client_auth_kit(client_init_kit& init_kit, const char* data, int i, MESSAGE_LENGTH_T data_len) { - peer_public = read_peer_data(data, i, data_len); - peer_private = read_peer_data(data, i, data_len); - std::cout << "Target is: " << peer_private.ip_address << ":" << peer_private.port << "/" << peer_public.ip_address << ":" << peer_public.port << " priv/pub" << std::endl; +client_peer_kit::client_peer_kit() { + +} + +void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, int next_data_index, MESSAGE_LENGTH_T data_len) { + public_info = read_peer_data(data, next_data_index, data_len); + private_info = read_peer_data(data, next_data_index, data_len); + std::cout << "Target is: " << private_info.ip_address << ":" << private_info.port << "/" << public_info.ip_address << ":" << public_info.port << " priv/pub" << std::endl; - auth_key_out = read_data(data, i, data_len); - old_privatename = init_kit.get_server_socket()->get_myname_raw(); - init_kit.set_conn_socket(nullptr); + old_privatename = init_kit.get_server_socket()->get_myname_raw(); + public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); + private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); - public_connector = std::make_unique(old_privatename, peer_public.ip_address, peer_public.port, init_kit.protocol); - private_connector = std::make_unique(old_privatename, peer_private.ip_address, peer_private.port, init_kit.protocol); std::vector> unauthed_sockets{}; -} - -EXECUTION_STATUS process_auth(const Message& mess, std::unique_ptr& socket, int my_auth) -{ - if (mess == Message::null_message) - return EXECUTION_STATUS::FAILED; - - const char* data = mess.Data.data(); - size_t data_len = mess.Length; - int i = 0; - int auth_key = 0; - MESSAGE_TYPE type = mess.Type; + peer_connect_start_time = std::chrono::system_clock::now(); +} - switch (type) +EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer_kit) { + if (peer_kit.public_connector->has_connected() == ConnectionStatus::SUCCESS) { - case MESSAGE_TYPE::AUTH_PLS: - std::cout << "Peer (" << socket->get_endpoint_ip() << ":" << socket->get_endpoint_port() << ") requesting Auth, responding with key" << std::endl; - socket->send_data(create_message(MESSAGE_TYPE::HERES_YOUR_AUTH, my_auth)); - return EXECUTION_STATUS::CONTINUE; - case MESSAGE_TYPE::HERES_YOUR_AUTH: - std::cout << "Peer (" << socket->get_endpoint_ip() << ":" << socket->get_endpoint_port() << ") has replied with key" << std::endl; - if (!try_read_data(data, i, data_len, auth_key)) - { - std::cout << "Failed to read key from peer" << std::endl; - return EXECUTION_STATUS::FAILED; - } - - if (auth_key == my_auth) - { - std::cout << "Key matches, we should be connected!" << std::endl; - return EXECUTION_STATUS::CONNECTED; - } - std::cout << "Key did not match" << std::endl; - return EXECUTION_STATUS::FAILED; - default: - std::cout << __func__ << "(" << __LINE__ << "): Ignoring Message with Type: " << mt_to_string(type) << std::endl; - return EXECUTION_STATUS::CONTINUE; + std::cout << "Public Connection has connected, now authenticating" << std::endl; + peer_kit.peer_socket = std::make_unique(std::move(peer_kit.public_connector)); + + return EXECUTION_STATUS::PEER_CONNECTED; } + std::cout << "Public Connection Failed, Retrying connection..." << std::endl; + peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); + return EXECUTION_STATUS::HOLE_PUNCH; } -EXECUTION_STATUS respond_to_auth(client_init_kit& init_kit, client_auth_kit& auth_kit) { - for (size_t i = auth_kit.unauthed_sockets.size(); i-- > 0; ) +EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& peer_kit) { + if (peer_kit.private_connector->has_connected() == ConnectionStatus::SUCCESS) { - auto& sock = auth_kit.unauthed_sockets[i]; - - if (sock && sock->has_message()) - { - auto status = process_auth(sock->receive_message(), sock, auth_kit.auth_key_out); + std::cout << "Private Connection has connected, now attempting to authenticate" << std::endl; + auto analyser = std::make_unique(std::move(peer_kit.private_connector)); + peer_kit.peer_socket = std::move(analyser); + peer_kit.private_connector = nullptr; - if (status == EXECUTION_STATUS::FAILED) - { - std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has failed to authenticate" << std::endl; - auth_kit.unauthed_sockets.pop_back(); - } - - else if (status == EXECUTION_STATUS::CONNECTED) - { - std::cout << "Socket '" << sock->get_endpoint_ip() << ":" << sock->get_endpoint_port() << "' has successfully authenticated" << std::endl; - init_kit.set_server_socket(std::move(sock)); //caused a bug if we dont return immediately after - return EXECUTION_STATUS::CONNECTED; //we only care if either private or public sockets got punched, not both - } - } + return EXECUTION_STATUS::PEER_CONNECTED; } - return EXECUTION_STATUS::CONTINUE; + std::cout << "Private Connection attempt failed, retrying..." << std::endl; + peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); + return EXECUTION_STATUS::HOLE_PUNCH; } -bool check_for_auth_connection(client_init_kit& init_kit, client_auth_kit& auth_kit) { - if (auth_kit.unauthed_sockets.size()) - return true; - - if (auth_kit.listen_sock->has_connection()) +EXECUTION_STATUS connect_listener(client_peer_kit& peer_kit) { + if (peer_kit.listen_sock->has_connection()) { std::cout << "Successfully accepted peer connection, now authenticating them" << std::endl; - auth_kit.unauthed_sockets.emplace_back(auth_kit.listen_sock->accept_connection()); - - if (init_kit.is_leader) - auth_kit.unauthed_sockets.back()->send_data(create_message(MESSAGE_TYPE::AUTH_PLS)); + peer_kit.peer_socket = peer_kit.listen_sock->accept_connection(); - std::this_thread::sleep_for(100ms); - return true; + return EXECUTION_STATUS::PEER_CONNECTED; } + std::cout << "Listen Connection attempt failed, retrying..." << std::endl; + return EXECUTION_STATUS::HOLE_PUNCH; +} - if (auth_kit.private_connector != nullptr) - { - auto status = auth_kit.private_connector->has_connected(); - if (status == ConnectionStatus::SUCCESS) - { - std::cout << "Private Connection has connected, now attempting to authenticate" << std::endl; - auto analyser = std::make_unique(std::move(auth_kit.private_connector)); - auth_kit.unauthed_sockets.emplace_back(std::move(analyser)); - auth_kit.private_connector = nullptr; +EXECUTION_STATUS connect_peer(client_init_kit& init_kit, client_peer_kit& peer_kit) { + if(peer_kit.peer_socket) + return EXECUTION_STATUS::PEER_CONNECTED; - if (init_kit.is_leader) - auth_kit.unauthed_sockets.back()->send_data(create_message(MESSAGE_TYPE::AUTH_PLS)); + auto status = connect_public(init_kit, peer_kit); + + if(status == EXECUTION_STATUS::PEER_CONNECTED) + status = connect_private(init_kit, peer_kit); - std::this_thread::sleep_for(100ms); - return true; - } - else if (status == ConnectionStatus::FAILED) - { - std::cout << "Private Connection attempt failed, retrying..." << std::endl; - auth_kit.private_connector = std::make_unique(auth_kit.old_privatename, auth_kit.peer_private.ip_address, auth_kit.peer_private.port, init_kit.protocol); - } - } + if(status == EXECUTION_STATUS::PEER_CONNECTED) + return connect_listener(peer_kit); +} - if (auth_kit.public_connector != nullptr) - { - auto status = auth_kit.public_connector->has_connected(); - if (status == ConnectionStatus::SUCCESS) - { - std::cout << "Public Connection has connected, now authenticating" << std::endl; - auth_kit.unauthed_sockets.emplace_back(std::make_unique(std::move(auth_kit.public_connector))); //add to the list of connected sockets ready to complete authentication +EXECUTION_STATUS hole_punch(client_init_kit& init_kit, client_peer_kit& peer_kit) { + try + { + EXECUTION_STATUS status = EXECUTION_STATUS::HOLE_PUNCH; + std::cout << "Attempting to Hole Punch" << std::endl; - if (init_kit.is_leader) - auth_kit.unauthed_sockets.back()->send_data(create_message(MESSAGE_TYPE::AUTH_PLS)); + if(init_kit.status != EXECUTION_STATUS::PEER_CONNECTED) + status = connect_peer(init_kit, peer_kit); - std::this_thread::sleep_for(100ms); - return true; - } - else if (status == ConnectionStatus::FAILED) - { - std::cout << "Public Connection Failed, Retrying connection..." << std::endl; - auth_kit.public_connector = std::make_unique(auth_kit.old_privatename, auth_kit.peer_public.ip_address, auth_kit.peer_public.port, init_kit.protocol); - } - } -} + auto current_time = std::chrono::system_clock::now(); -/// Server giving us a peer to connect to -/// Attempt to connect to peer by connecting to it and listening for a connection -/// The connect socket must have same local address binding as the socket that connected to the server -/// And we must disconnect the connection to the server -EXECUTION_STATUS hole_punch(client_init_kit& init_kit, const char* data, int& auth_key_out, int i, MESSAGE_LENGTH_T data_len) { - try - { - std::cout << "Attempting to Hole Punch" << std::endl; - client_auth_kit auth_kit{init_kit, data, i, data_len}; - auto start_time = std::chrono::system_clock::now(); - auto current_time = start_time; - bool connection_made = false; - - do - { - if(connection_made == false) - connection_made = check_for_auth_connection(init_kit, auth_kit); + if(current_time - peer_kit.peer_connect_start_time < 15s) { + std::cerr << "Time out trying to hole punch reached" << std::endl; + return EXECUTION_STATUS::FAILED; + } - else - { - auto auth_status = respond_to_auth(init_kit, auth_kit); - - if (auth_status == EXECUTION_STATUS::CONNECTED) - return auth_status; - } + else std::this_thread::sleep_for(100ms); - } - while (current_time - start_time < 15s); - - std::cerr << "Time out trying to hole punch reached" << std::endl; - return EXECUTION_STATUS::FAILED; + return status; } catch (const std::exception& e) { @@ -216,7 +133,7 @@ EXECUTION_STATUS hole_punch(client_init_kit& init_kit, const char* data, int& au } } -EXECUTION_STATUS process_server_data(client_init_kit& kit, const Message& message) +EXECUTION_STATUS process_server_data(client_init_kit& init_kit, client_peer_kit& peer_kit, const Message& message) { try { @@ -229,38 +146,21 @@ EXECUTION_STATUS process_server_data(client_init_kit& kit, const Message& messag return EXECUTION_STATUS::COMPLETE; } - int i = 0; + int message_data_index = 0; auto msg_type = message.Type; switch (msg_type) { - case MESSAGE_TYPE::MSG: - { - std::string msg = read_string(data, i, data_len); - std::cout << "Message received from server: " << msg << std::endl; - return EXECUTION_STATUS::CONTINUE; - } - case MESSAGE_TYPE::FILE: - { - std::cout << "Received file from server" << std::endl; - // TODO: actually read the file - return EXECUTION_STATUS::CONTINUE; - } - case MESSAGE_TYPE::CONNECT_PEER: + case MESSAGE_TYPE::CONNECT_TO_PEER: { - return hole_punch(kit, data, kit.auth_key, i, data_len); - } - - case MESSAGE_TYPE::CONNECT_PEER_AS_LEADER: - { - kit.is_leader = true; - return hole_punch(kit, data, kit.auth_key, i, data_len); + peer_kit.set_peer_data(init_kit, data, message_data_index, data_len); + return EXECUTION_STATUS::HOLE_PUNCH; } case MESSAGE_TYPE::NONE: default: std::cout << __func__ << "(" << __LINE__ << "): Ignoring Message with Type: " << mt_to_string(msg_type) << std::endl; - return EXECUTION_STATUS::CONTINUE; + return EXECUTION_STATUS::RENDEZVOUS; } } catch (const std::exception& e) @@ -269,7 +169,7 @@ EXECUTION_STATUS process_server_data(client_init_kit& kit, const Message& messag } } -EXECUTION_STATUS process_peer_data(const Message& mess, const std::unique_ptr& peer, int auth_key) +EXECUTION_STATUS process_peer_data(const Message& mess, const std::unique_ptr& peer) { const char* data = mess.Data.data(); auto data_len = mess.Length; @@ -284,114 +184,150 @@ EXECUTION_STATUS process_peer_data(const Message& mess, const std::unique_ptrsend_data(create_message(MESSAGE_TYPE::HERES_YOUR_AUTH, auth_key)); - - return EXECUTION_STATUS::CONTINUE; - } - case MESSAGE_TYPE::MSG: + case MESSAGE_TYPE::PEER_MSG: { std::string msg = read_string(data, i, data_len); std::cout << "Message received from peer: " << msg << std::endl; - return EXECUTION_STATUS::CONTINUE; + return EXECUTION_STATUS::PEER_CONNECTED; } - case MESSAGE_TYPE::FILE: + case MESSAGE_TYPE::PEER_FILE: { std::cout << "Received file from peer" << std::endl; // TODO: actually read the file - return EXECUTION_STATUS::CONTINUE; - } - case MESSAGE_TYPE::CONNECT_PEER: - { - std::cout << "Received Connect Peer message when already connected" << std::endl; - - return EXECUTION_STATUS::CONTINUE; + return EXECUTION_STATUS::PEER_CONNECTED; } case MESSAGE_TYPE::NONE: default: std::cout << __func__ << "(" << __LINE__ << "): Ignoring Message with Type: " << mt_to_string(msg_type) << std::endl; - return EXECUTION_STATUS::CONTINUE; + return EXECUTION_STATUS::PEER_CONNECTED; } - return EXECUTION_STATUS::CONTINUE; + return EXECUTION_STATUS::PEER_CONNECTED; } - -void client_loop(std::string server_address_pair, protocol input_protocol) +void get_user_input(thread_queue& msg_queue) { - std::cout << "Starting ptop!" << std::endl; - std::cout << "Connecting to rendezvous server: " << server_address_pair << std::endl; - client_init_kit kit{ server_address_pair, input_protocol }; - auto& connection_socket = kit.get_server_socket(); - - while (kit.status == EXECUTION_STATUS::CONTINUE) //listen at the start of protocol - { - auto now = std::chrono::system_clock::now(); - - if (now - kit.last_send > 3s) - { - connection_socket->send_data(create_message(MESSAGE_TYPE::READY_FOR_P2P)); - kit.last_send = now; - } - if (connection_socket->has_message()) + std::string input; + do + { + std::getline(std::cin, input); //waits until cin input { - auto message = connection_socket->receive_message(); - kit.status = process_server_data(kit, message); + std::unique_lock lock(msg_queue.queue_mutex); + msg_queue.messages.push(input); } + std::this_thread::sleep_for(100ms); - } + } while (true); +} - if (kit.status == EXECUTION_STATUS::CONNECTED) - { - kit.status = EXECUTION_STATUS::CONTINUE; - std::cout << "connected to peer. enter your message!" << std::endl; - thread_queue message_queue{}; +void print_help() +{ + auto space = "\t"; + std::cout << "PTOP Peer v69.42 is running" << std::endl; + std::cout << "Runtime commands:" << std::endl; + std::cout << space << "file: [filename]" << std::endl; + std::cout << space << space << "sends a file to your peer (not currently implemented)" << std::endl; + std::cout << std::endl; + std::cout << space << "msg: [text]" << std::endl; + std::cout << space << space << "sends plain text message of [text] (without braces) to your peer" << std::endl; + std::cout << space << space << "example: \"msg: banana\" will send 'banana' to your peer" << std::endl; + std::cout << std::endl; + std::cout << space << "debug" << std::endl; + std::cout << space << space << "outputs current status and relevant information" << std::endl; +} - std::thread input_thread = std::thread([&message_queue]() +void do_user_input(thread_queue& message_queue, std::unique_lock& take_message_lock, std::unique_ptr& peer_socket) +{ + if (take_message_lock.try_lock()) + { + if (!message_queue.messages.empty()) { - std::string input; - do + std::string input_message = message_queue.messages.front(); + message_queue.messages.pop(); + + if (input_message.substr(0, 5) == "msg: ") { - std::getline(std::cin, input); //waits until cin input + if (peer_socket) { - std::unique_lock lock(message_queue.queue_mutex); - message_queue.messages.push(input); + std::string send_message = input_message.substr(5); + std::cout << "Sending string of: " << send_message << std::endl; + peer_socket->send_data(create_message(MESSAGE_TYPE::PEER_MSG, send_message)); } + else + std::cout << "Can not send to peer, we have no peer connection" << std::endl; + } + else if (input_message.substr(0, 6) == "file: ") + { + std::cout << "file sending not implemented" << std::endl; + } + if (input_message.substr(0, 4) == "help") + { + print_help(); + } + + } + take_message_lock.unlock(); + } +} - std::this_thread::sleep_for(100ms); - } while (true); - }); - input_thread.detach(); +void client_loop(std::string server_address_pair, protocol input_protocol) +{ + std::cout << "Starting ptop!" << std::endl; + std::cout << "Connecting to rendezvous server: " << server_address_pair << std::endl; + client_init_kit init_kit{ server_address_pair, input_protocol }; + client_peer_kit peer_kit{}; + auto& connection_socket = init_kit.get_server_socket(); + + thread_queue message_queue{}; + + std::thread input_thread = std::thread(get_user_input, std::ref(message_queue)); + input_thread.detach(); + std::unique_lock take_message_lock(message_queue.queue_mutex, std::defer_lock); + + init_kit.status = EXECUTION_STATUS::RENDEZVOUS; + + while (init_kit.status != EXECUTION_STATUS::COMPLETE && init_kit.status != EXECUTION_STATUS::FAILED) //listen at the start of protocol + { + switch (init_kit.status) + { + case EXECUTION_STATUS::RENDEZVOUS: + { + auto now = std::chrono::system_clock::now(); - std::unique_lock take_message_lock(message_queue.queue_mutex, std::defer_lock); + if (now - init_kit.server_last_send > 3s) + { + connection_socket->send_data(create_message(MESSAGE_TYPE::READY_FOR_P2P)); + init_kit.server_last_send = now; + } + if (connection_socket->has_message()) + { + auto message = connection_socket->receive_message(); + init_kit.status = process_server_data(init_kit, peer_kit, message); + } + } + break; - do { - if (connection_socket->has_message()) + case EXECUTION_STATUS::HOLE_PUNCH: { - auto message = connection_socket->receive_message(); - kit.status = process_peer_data(message, connection_socket, kit.auth_key); + init_kit.status = hole_punch(init_kit, peer_kit); } - + break; + + case EXECUTION_STATUS::PEER_CONNECTED: { - if (take_message_lock.try_lock()) + if (peer_kit.peer_socket->has_message()) { - if (!message_queue.messages.empty()) - { - std::string input_message = message_queue.messages.front(); - message_queue.messages.pop(); - connection_socket->send_data(create_message(MESSAGE_TYPE::MSG, input_message)); - } - take_message_lock.unlock(); + auto message = peer_kit.peer_socket->receive_message(); + auto process_status = process_peer_data(message, peer_kit.peer_socket); } } - std::this_thread::sleep_for(100ms); - - } while (kit.status == EXECUTION_STATUS::CONTINUE); - - std::cout << "finished sending to peer" << std::endl; + break; + } + + do_user_input(message_queue, take_message_lock, peer_kit.peer_socket); + + std::this_thread::sleep_for(100ms); } } + diff --git a/src/client.h b/src/client.h index 95d6717..05757fb 100644 --- a/src/client.h +++ b/src/client.h @@ -9,17 +9,14 @@ #include "interfaces.h" #include "platform.h" - void client_loop(std::string server_address_pair, protocol input_protocol); class client_init_kit { public: client_init_kit(std::string server_address_pair, ::protocol input_protocol); - std::chrono::system_clock::time_point last_send; - int auth_key; + std::chrono::system_clock::time_point server_last_send; EXECUTION_STATUS status; ::protocol protocol; - bool is_leader; std::unique_ptr& get_server_socket(); void set_server_socket(std::unique_ptr&& input); @@ -28,15 +25,18 @@ class client_init_kit { std::unique_ptr _server_socket; }; -class client_auth_kit { +class client_peer_kit { public: - client_auth_kit(client_init_kit& init_kit, const char* data, int i, MESSAGE_LENGTH_T data_len); - std::vector> unauthed_sockets; - std::unique_ptr listen_sock; - int auth_key_out; + client_peer_kit(); + void set_peer_data(client_init_kit& init_kit, const char* data, int message_data_index, MESSAGE_LENGTH_T data_len); + std::unique_ptr public_connector; std::unique_ptr private_connector; - readable_ip_info peer_public; - readable_ip_info peer_private; + std::unique_ptr listen_sock; + readable_ip_info public_info; + readable_ip_info private_info; raw_name_data old_privatename; + + std::chrono::system_clock::time_point peer_connect_start_time; + std::unique_ptr peer_socket; }; diff --git a/src/loop.h b/src/loop.h index 5b6c34b..6eee9a6 100644 --- a/src/loop.h +++ b/src/loop.h @@ -9,10 +9,14 @@ enum class EXECUTION_STATUS { - CONTINUE = 0, - CONNECTED, + NONE = 0, + CONTINUE, + SERVER_CONNECTED, COMPLETE, FAILED, + RENDEZVOUS, + HOLE_PUNCH, + PEER_CONNECTED, }; template::value>> // Only allow Plain-old-data to use this method diff --git a/src/message.h b/src/message.h index 2ceca70..14c1457 100644 --- a/src/message.h +++ b/src/message.h @@ -23,12 +23,9 @@ enum class MESSAGE_TYPE NONE = 0, MY_DATA, READY_FOR_P2P, - CONNECT_PEER, - CONNECT_PEER_AS_LEADER, - AUTH_PLS, - HERES_YOUR_AUTH, - MSG, - FILE, + CONNECT_TO_PEER, + PEER_MSG, + PEER_FILE, }; typedef uint32_t MESSAGE_LENGTH_T; @@ -56,24 +53,15 @@ inline std::string mt_to_string(const MESSAGE_TYPE& t) case MESSAGE_TYPE::READY_FOR_P2P: return "READY_FOR_P2P: Connection is ready for P2P"; - case MESSAGE_TYPE::MSG: + case MESSAGE_TYPE::PEER_MSG: return "MSG: Plain Text Msg"; - case MESSAGE_TYPE::FILE: + case MESSAGE_TYPE::PEER_FILE: return "FILE: Incoming File"; - case MESSAGE_TYPE::CONNECT_PEER: + case MESSAGE_TYPE::CONNECT_TO_PEER: return "CONNECT_PEER: Data required to connect to a peer"; - case MESSAGE_TYPE::CONNECT_PEER_AS_LEADER: - return "CONNECT_PEER_AS_LEADER: your client was marked as first in the pair grouping"; - - case MESSAGE_TYPE::AUTH_PLS: - return "AUTH_PLS: Request for Auth"; - - case MESSAGE_TYPE::HERES_YOUR_AUTH: - return "HERES_YOUR_AUTH: Auth Request Response"; - case MESSAGE_TYPE::NONE: default: return "NONE: None"; diff --git a/src/server.cpp b/src/server.cpp index 0667816..d9ec0a6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -36,8 +36,8 @@ void hole_punch_clients(IDataSocketWrapper*& clientA, IDataSocketWrapper*& clien std::cout << "Hole punching clients: A(" << dataA.ip_address << ":" << dataA.port << "), B(" << dataB.ip_address << ":" << dataB.port << ")" << std::endl; - clientA->send_data(create_message(MESSAGE_TYPE::CONNECT_PEER_AS_LEADER, dataB.to_bytes(), privB.to_bytes(), 69)); - clientB->send_data(create_message(MESSAGE_TYPE::CONNECT_PEER, dataA.to_bytes(), privA.to_bytes(), 69)); + clientA->send_data(create_message(MESSAGE_TYPE::CONNECT_TO_PEER, dataB.to_bytes(), privB.to_bytes())); + clientB->send_data(create_message(MESSAGE_TYPE::CONNECT_TO_PEER, dataA.to_bytes(), privA.to_bytes())); clientA = nullptr; clientB = nullptr; diff --git a/src/server.h b/src/server.h index 81d6b48..b95c695 100644 --- a/src/server.h +++ b/src/server.h @@ -12,6 +12,8 @@ #include #include + + class server_init_kit; void server_loop(); diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index 0b2d484..204806d 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -378,7 +378,7 @@ PlatformAnalyser::PlatformAnalyser(PtopSocket&& socket) } Message PlatformAnalyser::receive_message() { - process_socket_data(); + process_socket_data(); // Will block until it receives data if (_stored_messages.size() > 0) { @@ -387,6 +387,7 @@ Message PlatformAnalyser::receive_message() { return tmp; } + // Only way we have no messages is if connection closed return Message::null_message; } From 857d437f8b8af6e26db8e7e90298e34e8f6b7235 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:21:36 +1300 Subject: [PATCH 08/44] refactor: remove word reusable from types --- src/client.cpp | 12 ++++++------ src/client.h | 6 +++--- src/platform.h | 8 ++++---- src/windows_platform.cpp | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index a0fdc23..bdc07d3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -22,7 +22,7 @@ client_init_kit::client_init_kit(std::string server_address_pair, ::protocol cho } std::unique_ptr& client_init_kit::get_server_socket() { - return _server_socket; //yay bug + return _server_socket; } void client_init_kit::set_server_socket(std::unique_ptr&& input) { @@ -42,10 +42,10 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, std::cout << "Target is: " << private_info.ip_address << ":" << private_info.port << "/" << public_info.ip_address << ":" << public_info.port << " priv/pub" << std::endl; old_privatename = init_kit.get_server_socket()->get_myname_raw(); - public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); - private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); + public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); + private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); - listen_sock = std::make_unique(old_privatename, init_kit.protocol); + listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); std::vector> unauthed_sockets{}; @@ -62,7 +62,7 @@ EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer return EXECUTION_STATUS::PEER_CONNECTED; } std::cout << "Public Connection Failed, Retrying connection..." << std::endl; - peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); + peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); return EXECUTION_STATUS::HOLE_PUNCH; } @@ -77,7 +77,7 @@ EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& pee return EXECUTION_STATUS::PEER_CONNECTED; } std::cout << "Private Connection attempt failed, retrying..." << std::endl; - peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); + peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); return EXECUTION_STATUS::HOLE_PUNCH; } diff --git a/src/client.h b/src/client.h index 05757fb..2a5ae0d 100644 --- a/src/client.h +++ b/src/client.h @@ -30,9 +30,9 @@ class client_peer_kit { client_peer_kit(); void set_peer_data(client_init_kit& init_kit, const char* data, int message_data_index, MESSAGE_LENGTH_T data_len); - std::unique_ptr public_connector; - std::unique_ptr private_connector; - std::unique_ptr listen_sock; + std::unique_ptr public_connector; + std::unique_ptr private_connector; + std::unique_ptr listen_sock; readable_ip_info public_info; readable_ip_info private_info; raw_name_data old_privatename; diff --git a/src/platform.h b/src/platform.h index 0504fc6..dd7ff71 100644 --- a/src/platform.h +++ b/src/platform.h @@ -74,18 +74,18 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { bool send_data(const Message& message) override; }; -class ReusableListener : public Platform, public virtual INonBlockingListener { +class NonBlockListener : public Platform, public virtual INonBlockingListener { public: - ReusableListener(raw_name_data data, protocol input_protocol); + NonBlockListener(raw_name_data data, protocol input_protocol); void listen() override; bool has_connection() override; std::unique_ptr accept_connection() override; }; -class ReusableConnector : public Platform, public virtual INonBlockingConnector { +class NonBlockingConnector : public Platform, public virtual INonBlockingConnector { public: - ReusableConnector(raw_name_data private_binding, std::string ip_address, std::string port, protocol input_protocol); + NonBlockingConnector(raw_name_data private_binding, std::string ip_address, std::string port, protocol input_protocol); void connect(std::string ip_address, std::string port) override; // Called in constructor, can be called again if it fails ConnectionStatus has_connected() override; diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index 204806d..f75d0d1 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -292,7 +292,7 @@ bool PlatformAnalyser::send_data(const Message& message) PtopSocket windows_data_socket_steal_construct(std::unique_ptr&& old) { std::cout << "[Data] Moving linux_reusable_nonblocking_connection_socket " << old->get_identifier_str() << " to a data_socket" << std::endl; - ReusableConnector& real_old = *dynamic_cast(old.get()); + NonBlockingConnector& real_old = *dynamic_cast(old.get()); PtopSocket epic = real_old.release_socket(); epic.set_non_blocking(false); return epic; @@ -420,22 +420,22 @@ PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto) } } -ReusableListener::ReusableListener(raw_name_data data, protocol input_protocol) : Platform( +NonBlockListener::NonBlockListener(raw_name_data data, protocol input_protocol) : Platform( windows_reuse_nb_listen_construct(data, input_protocol)) {} -void ReusableListener::listen() +void NonBlockListener::listen() { std::cout << "[ListenReuseNoB] Now Listening on: " << Platform::get_my_ip() << ":" << Platform::get_my_port() << std::endl; _socket.listen(4); } -bool ReusableListener::has_connection() +bool NonBlockListener::has_connection() { return _socket.has_connection(); } -std::unique_ptr ReusableListener::accept_connection() +std::unique_ptr NonBlockListener::accept_connection() { std::cout << "[ListenReuseNoB] Accepting Connection..." << std::endl; @@ -466,14 +466,14 @@ PtopSocket windows_reuse_nb_construct(raw_name_data name, protocol proto) } } -ReusableConnector::ReusableConnector( +NonBlockingConnector::NonBlockingConnector( raw_name_data name, std::string ip_address, std::string port, protocol input_protocol) : Platform( windows_reuse_nb_construct(name, input_protocol)) { connect(ip_address, port); } -void ReusableConnector::connect(std::string ip_address, std::string port) +void NonBlockingConnector::connect(std::string ip_address, std::string port) { try { @@ -502,7 +502,7 @@ void ReusableConnector::connect(std::string ip_address, std::string port) } } -ConnectionStatus ReusableConnector::has_connected() +ConnectionStatus NonBlockingConnector::has_connected() { try { From a88b0d6ef90293cefffc322634ed6f347cb3b6fc Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:25:25 +1300 Subject: [PATCH 09/44] fix: linux build --- src/linux_platform.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 3de25fa..880ed60 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -176,7 +176,7 @@ PtopSocket steal_construct(std::unique_ptr&& old) try { std::cout << "[Data] Moving linux_reusable_nonblocking_connection_socket " << old->get_identifier_str() << " to a data_socket" << std::endl; - ReusableConnector& real_old = *dynamic_cast(old.get()); + NonBlockingConnector& real_old = *dynamic_cast(old.get()); PtopSocket sup = real_old.release_socket(); sup.set_non_blocking(false); return sup; @@ -337,24 +337,24 @@ PtopSocket reuse_listen_construct(raw_name_data data, protocol proto) return listen_socket; } -ReusableListener::ReusableListener(raw_name_data data, protocol proto) +NonBlockingListener::NonBlockingListener(raw_name_data data, protocol proto) : Platform(reuse_listen_construct(data, proto)) { } -void ReusableListener::listen() +void NonBlockingListener::listen() { std::cout << "[ListenReuseNoB] Now Listening on: " << get_my_ip() << ":" << get_my_port() << std::endl; _socket.listen(4); } -bool ReusableListener::has_connection() +bool NonBlockingListener::has_connection() { return _socket.has_connection(); } -std::unique_ptr ReusableListener::accept_connection() +std::unique_ptr NonBlockingListener::accept_connection() { std::cout << "[ListenReuseNoB] Accepting Connection..." << std::endl; @@ -380,7 +380,7 @@ PtopSocket reuse_connection_construct(raw_name_data data, protocol proto) return conn_socket; } -ReusableConnector::ReusableConnector(raw_name_data data, std::string ip_address, std::string port, protocol proto) +NonBlockingConnector::NonBlockingConnector(raw_name_data data, std::string ip_address, std::string port, protocol proto) : Platform(reuse_connection_construct(data, proto)) { // if tcp? @@ -394,7 +394,7 @@ ReusableConnector::ReusableConnector(raw_name_data data, std::string ip_address, } } -void ReusableConnector::connect(std::string ip_address, std::string port) +void NonBlockingConnector::connect(std::string ip_address, std::string port) { try { @@ -423,7 +423,7 @@ void ReusableConnector::connect(std::string ip_address, std::string port) } } -ConnectionStatus ReusableConnector::has_connected() +ConnectionStatus NonBlockingConnector::has_connected() { try { From 0a215bb3898fbb0d31de0f81125dd1394f65fda2 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:34:59 +1300 Subject: [PATCH 10/44] refactor: conform to word usage --- src/client.cpp | 4 ++-- src/client.h | 2 +- src/platform.h | 4 ++-- src/windows_platform.cpp | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index bdc07d3..273ad1d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -33,7 +33,7 @@ void client_init_kit::set_server_socket(std::unique_ptr&& in } client_peer_kit::client_peer_kit() { - + } void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, int next_data_index, MESSAGE_LENGTH_T data_len) { @@ -45,7 +45,7 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); - listen_sock = std::make_unique(old_privatename, init_kit.protocol); + listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); std::vector> unauthed_sockets{}; diff --git a/src/client.h b/src/client.h index 2a5ae0d..32499db 100644 --- a/src/client.h +++ b/src/client.h @@ -32,7 +32,7 @@ class client_peer_kit { std::unique_ptr public_connector; std::unique_ptr private_connector; - std::unique_ptr listen_sock; + std::unique_ptr listen_sock; readable_ip_info public_info; readable_ip_info private_info; raw_name_data old_privatename; diff --git a/src/platform.h b/src/platform.h index dd7ff71..c177342 100644 --- a/src/platform.h +++ b/src/platform.h @@ -74,9 +74,9 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { bool send_data(const Message& message) override; }; -class NonBlockListener : public Platform, public virtual INonBlockingListener { +class NonBlockingListener : public Platform, public virtual INonBlockingListener { public: - NonBlockListener(raw_name_data data, protocol input_protocol); + NonBlockingListener(raw_name_data data, protocol input_protocol); void listen() override; bool has_connection() override; diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index f75d0d1..98079a0 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -420,22 +420,22 @@ PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto) } } -NonBlockListener::NonBlockListener(raw_name_data data, protocol input_protocol) : Platform( +NonBlockingListener::NonBlockingListener(raw_name_data data, protocol input_protocol) : Platform( windows_reuse_nb_listen_construct(data, input_protocol)) {} -void NonBlockListener::listen() +void NonBlockingListener::listen() { std::cout << "[ListenReuseNoB] Now Listening on: " << Platform::get_my_ip() << ":" << Platform::get_my_port() << std::endl; _socket.listen(4); } -bool NonBlockListener::has_connection() +bool NonBlockingListener::has_connection() { return _socket.has_connection(); } -std::unique_ptr NonBlockListener::accept_connection() +std::unique_ptr NonBlockingListener::accept_connection() { std::cout << "[ListenReuseNoB] Accepting Connection..." << std::endl; From cec14caf8f18b904a229f939aeb25f262b03f2b0 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:41:41 +1300 Subject: [PATCH 11/44] fix: need to close server connection before hole punching --- src/client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 273ad1d..bd59c86 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -152,7 +152,8 @@ EXECUTION_STATUS process_server_data(client_init_kit& init_kit, client_peer_kit& switch (msg_type) { case MESSAGE_TYPE::CONNECT_TO_PEER: - { + { + init_kit.set_server_socket(nullptr); peer_kit.set_peer_data(init_kit, data, message_data_index, data_len); return EXECUTION_STATUS::HOLE_PUNCH; } From aaa9a212fdc2367a3f3f29fdc8c32dba2aea419f Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:45:46 +1300 Subject: [PATCH 12/44] fix: close in right spot --- src/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index bd59c86..de44123 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -41,7 +41,8 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, private_info = read_peer_data(data, next_data_index, data_len); std::cout << "Target is: " << private_info.ip_address << ":" << private_info.port << "/" << public_info.ip_address << ":" << public_info.port << " priv/pub" << std::endl; - old_privatename = init_kit.get_server_socket()->get_myname_raw(); + old_privatename = init_kit.get_server_socket()->get_myname_raw(); + init_kit.set_server_socket(nullptr); //need to close the server socket HERE to maintain the same session in the peer sockets public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); @@ -153,7 +154,6 @@ EXECUTION_STATUS process_server_data(client_init_kit& init_kit, client_peer_kit& { case MESSAGE_TYPE::CONNECT_TO_PEER: { - init_kit.set_server_socket(nullptr); peer_kit.set_peer_data(init_kit, data, message_data_index, data_len); return EXECUTION_STATUS::HOLE_PUNCH; } From a49b57de59a519af6dd519bbe2c40b9f1e4534be Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 16:56:39 +1300 Subject: [PATCH 13/44] fix: times out instantly --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index de44123..dcfcd1d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -118,7 +118,7 @@ EXECUTION_STATUS hole_punch(client_init_kit& init_kit, client_peer_kit& peer_kit auto current_time = std::chrono::system_clock::now(); - if(current_time - peer_kit.peer_connect_start_time < 15s) { + if(current_time - peer_kit.peer_connect_start_time > 15s) { std::cerr << "Time out trying to hole punch reached" << std::endl; return EXECUTION_STATUS::FAILED; } From cf84ce7a1d510a4f04a467dbe3b3c5afd1aeb958 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 17:02:03 +1300 Subject: [PATCH 14/44] fix: logic brain boom --- src/client.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index dcfcd1d..54a6016 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -100,11 +100,13 @@ EXECUTION_STATUS connect_peer(client_init_kit& init_kit, client_peer_kit& peer_k auto status = connect_public(init_kit, peer_kit); - if(status == EXECUTION_STATUS::PEER_CONNECTED) + if(status != EXECUTION_STATUS::PEER_CONNECTED) status = connect_private(init_kit, peer_kit); - if(status == EXECUTION_STATUS::PEER_CONNECTED) - return connect_listener(peer_kit); + if(status != EXECUTION_STATUS::PEER_CONNECTED) + status = connect_listener(peer_kit); + + return status; } EXECUTION_STATUS hole_punch(client_init_kit& init_kit, client_peer_kit& peer_kit) { From bd4fc88ea90f514a7ed5210eefda7539ac500c6a Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Thu, 27 Jan 2022 17:16:13 +1300 Subject: [PATCH 15/44] chore: remove unused --- src/client.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 54a6016..1dedad0 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -49,15 +49,13 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock->listen(); - std::vector> unauthed_sockets{}; - peer_connect_start_time = std::chrono::system_clock::now(); } EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer_kit) { if (peer_kit.public_connector->has_connected() == ConnectionStatus::SUCCESS) { - std::cout << "Public Connection has connected, now authenticating" << std::endl; + std::cout << "Public Connection has connected" << std::endl; peer_kit.peer_socket = std::make_unique(std::move(peer_kit.public_connector)); return EXECUTION_STATUS::PEER_CONNECTED; @@ -70,7 +68,7 @@ EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& peer_kit) { if (peer_kit.private_connector->has_connected() == ConnectionStatus::SUCCESS) { - std::cout << "Private Connection has connected, now attempting to authenticate" << std::endl; + std::cout << "Private Connection has connected" << std::endl; auto analyser = std::make_unique(std::move(peer_kit.private_connector)); peer_kit.peer_socket = std::move(analyser); peer_kit.private_connector = nullptr; @@ -85,7 +83,7 @@ EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& pee EXECUTION_STATUS connect_listener(client_peer_kit& peer_kit) { if (peer_kit.listen_sock->has_connection()) { - std::cout << "Successfully accepted peer connection, now authenticating them" << std::endl; + std::cout << "Successfully accepted peer connection" << std::endl; peer_kit.peer_socket = peer_kit.listen_sock->accept_connection(); return EXECUTION_STATUS::PEER_CONNECTED; From 0c0084311d9c83cc185065ed91f5aa08d98f59e8 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:12:12 +1300 Subject: [PATCH 16/44] add: to string for execution status --- src/loop.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/loop.h b/src/loop.h index 6eee9a6..a8213b7 100644 --- a/src/loop.h +++ b/src/loop.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -19,6 +20,30 @@ enum class EXECUTION_STATUS PEER_CONNECTED, }; +inline std::string es_to_string(EXECUTION_STATUS status) +{ + switch (status) + { + default: + case EXECUTION_STATUS::NONE: + return "EXECUTION_STATUS::NONE: No Execution Status"; + case EXECUTION_STATUS::CONTINUE: + return "EXECUTION_STATUS::CONTINUE: Continue Current Operation"; + case EXECUTION_STATUS::SERVER_CONNECTED: + return "EXECUTION_STATUS::SERVER_CONNECTED: Connected to Server"; + case EXECUTION_STATUS::COMPLETE: + return "EXECUTION_STATUS::COMPLETE: Program has completed"; + case EXECUTION_STATUS::FAILED: + return "EXECUTION_STATUS::FAILED: Program has encountered an error"; + case EXECUTION_STATUS::RENDEZVOUS: + return "EXECUTION_STATUS::RENDEZVOUS: Program is communicating with rendezvous server"; + case EXECUTION_STATUS::HOLE_PUNCH: + return "EXECUTION_STATUS::HOLE_PUNCH: Program is attempting to hole punch to a peer"; + case EXECUTION_STATUS::PEER_CONNECTED: + return "EXECUTION_STATUS::PEER_CONNECTED: Program has connected to the peer and is communicating with them"; + } +} + template::value>> // Only allow Plain-old-data to use this method T read_data(const char* data, int& index, size_t data_len) { From c7f5c11c616f06b24f6188499435fda3185fdff3 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:13:22 +1300 Subject: [PATCH 17/44] chore: cleanup ptop_socket --- src/ptop_socket.cpp | 13 +------------ src/ptop_socket.h | 5 +++-- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index c73f623..0f50384 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -175,18 +175,7 @@ bool PtopSocket::select_for(::select_for epic_for) const bool PtopSocket::has_message() const { - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - fd_set poll_read_set; - FD_ZERO(&poll_read_set); - FD_SET(_handle, &poll_read_set); - - int n = select((int)_handle + 1, &poll_read_set, 0, 0, &timeout); - throw_if_socket_error(n, "Failed to poll linux socket readability " + get_last_error(), LINE_CONTEXT); - - return n > 0; //returns number of sockets ready, 0 if timed out, -1 if socket error + return select_for(select_for::READ); } bool PtopSocket::has_died() const diff --git a/src/ptop_socket.h b/src/ptop_socket.h index 155a9aa..a77e73c 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -20,7 +20,7 @@ void throw_if_socket_error(int n, std::string message, std::string line_context) std::string socket_error_to_string(int err); std::string get_last_error(); -enum select_for +enum class select_for { READ, WRITE, @@ -60,7 +60,7 @@ class PtopSocket } template - OptT get_socket_option(int option_name) + OptT get_socket_option(int option_name) const { OptT opt; socklen_t optSize = sizeof(OptT); @@ -104,6 +104,7 @@ class PtopSocket inline bool is_valid() const { return _handle != REALLY_INVALID_SOCKET; } inline bool is_tcp() const { return _protocol.is_tcp(); } inline bool is_udp() const { return _protocol.is_udp(); } + inline bool is_listen() const { return get_socket_option(SO_ACCEPTCONN); } inline SOCKET get_handle() const { return _handle; } inline const protocol& get_protocol() const { return _protocol; } From 4385e72ec82157a934ddab0bc06775efa57da804 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:18:59 +1300 Subject: [PATCH 18/44] chore: make macro more flexible --- src/ptop_socket.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ptop_socket.h b/src/ptop_socket.h index a77e73c..9b0e5d8 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -69,10 +69,10 @@ class PtopSocket return opt; } -#ifdef __linux__ +#ifdef SO_REUSEPORT inline PtopSocket& set_socket_reuse() { set_socket_option(SO_REUSEPORT, (int)1, "Failed to set socket (port) reusability"); return set_socket_option(SO_REUSEADDR, (int)1, "Failed to set socket reusability"); } inline PtopSocket& set_socket_no_reuse() { set_socket_option(SO_REUSEPORT, (int)0, "Failed to set socket (port) un-reusability"); return set_socket_option(SO_REUSEADDR, (int)0, "Failed to set socket un-reusability"); } -#elif defined(WIN32) +#else inline PtopSocket& set_socket_reuse() { return set_socket_option(SO_REUSEADDR, (int)1, "Failed to set socket reusability"); } inline PtopSocket& set_socket_no_reuse() { return set_socket_option(SO_REUSEADDR, (int)0, "Failed to set socket un-reusability"); } #endif From 7476e0436fe0e9d893dc422cdcb644dc27e346ce Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:19:41 +1300 Subject: [PATCH 19/44] add: get_identifier_str now more descriptive --- src/interfaces.h | 2 +- src/platform.cpp | 10 ++++++++-- src/platform.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/interfaces.h b/src/interfaces.h index 6da9f35..e32f049 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -20,7 +20,7 @@ class ISocketWrapper virtual std::string get_my_port() const = 0; virtual std::string get_endpoint_ip() const = 0; virtual std::string get_endpoint_port() const = 0; - virtual std::string get_identifier_str() const = 0; + virtual std::string get_identifier_str() = 0; }; class IDataSocketWrapper : virtual public ISocketWrapper diff --git a/src/platform.cpp b/src/platform.cpp index 2b1d01f..c34c170 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -7,8 +7,14 @@ #include -std::string Platform::get_identifier_str() const { - if (_endpoint_assigned == false) +std::string Platform::get_identifier_str() { + if (_socket.is_listen()) + return std::string("(listen on: ") + _address + ":" + _port + ")"; + + if (_endpoint_assigned == false) + try_update_endpoint_info(); + + if (_endpoint_assigned == false) return std::string("(priv: ") + _address + ":" + _port + ", pub: N/A)"; return std::string("(pub: ") + _address + ":" + _port + ")"; diff --git a/src/platform.h b/src/platform.h index c177342..cb98008 100644 --- a/src/platform.h +++ b/src/platform.h @@ -45,7 +45,7 @@ class Platform : public virtual ISocketWrapper { inline std::string get_my_port() const override { return _port; } inline std::string get_endpoint_ip() const override { return _endpoint_address; } inline std::string get_endpoint_port() const override { return _endpoint_port; } - std::string get_identifier_str() const override; + std::string get_identifier_str() override; inline PtopSocket&& release_socket() { return std::move(_socket); } virtual ~Platform(); From b6b7d9efbc94de10594ebfaec910c3c023939fb8 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:20:53 +1300 Subject: [PATCH 20/44] add: platform sockets now update endpoints better --- src/linux_platform.cpp | 15 +++++++++++---- src/windows_platform.cpp | 12 +++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 880ed60..f0133c4 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -39,7 +39,7 @@ std::string linux_error(int err_code) Platform::Platform(PtopSocket&& socket) : _socket(std::move(socket)) { - update_name_info(); + try_update_name_info(); if (_address == "Unassigned" || _address.empty() || _port == "Unassigned" || _port.empty()) { @@ -58,6 +58,11 @@ void Platform::update_endpoint_info() { try { + if (_socket.is_listen()) + { + std::cout << "[Socket] Not updating endpoint as this socket " << get_identifier_str() << " is a listen socket" << std::endl; + return; + } auto name = get_peername_readable(); _endpoint_address = name.ip_address; _endpoint_port = name.port; @@ -175,10 +180,11 @@ PtopSocket steal_construct(std::unique_ptr&& old) { try { - std::cout << "[Data] Moving linux_reusable_nonblocking_connection_socket " << old->get_identifier_str() << " to a data_socket" << std::endl; + std::cout << "[Data] Moving INonBlockingConnector " << old->get_identifier_str() << " to a data_socket" << std::endl; NonBlockingConnector& real_old = *dynamic_cast(old.get()); PtopSocket sup = real_old.release_socket(); sup.set_non_blocking(false); + sup.set_socket_no_reuse(); return sup; } catch (const std::exception& e) @@ -241,7 +247,7 @@ PlatformAnalyser::PlatformAnalyser(std::unique_ptr&& old) { try { - //update_endpoint_info(); + try_update_endpoint_info(); } catch (const std::exception& e) { @@ -285,7 +291,7 @@ PtopSocket data_connect_construct(std::string peer_address, std::string peer_por PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol proto) : Platform(data_connect_construct(peer_address, peer_port, proto)) { - update_endpoint_info(); + try_update_endpoint_info(); } Message PlatformAnalyser::receive_message() @@ -416,6 +422,7 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) _socket.connect(results->ai_addr, results->ai_addrlen); std::cout << "[DataReuseNoB] Successfully BEGUN Connection to: " << ip_address << ":" << port << std::endl; + try_update_endpoint_info(); } catch (const std::exception& e) { diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index 98079a0..b8ab656 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -16,7 +16,6 @@ Platform::Platform(PtopSocket&& socket) : _socket(std::move(socket)) { try_update_name_info(); - try_update_endpoint_info(); // big chungus if (_address == "Unassigned" || _address.empty() || @@ -102,6 +101,11 @@ void Platform::update_endpoint_info() { try { + if (_socket.is_listen()) + { + std::cout << "[Socket] Not updating endpoint as this socket " << get_identifier_str() << " is a listen socket" << std::endl; + return; + } auto name = get_peername_readable(); _endpoint_address = name.ip_address; _endpoint_port = name.port; @@ -269,7 +273,7 @@ PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_po { try { - update_endpoint_info(); + try_update_endpoint_info(); } catch (const std::exception& e) { @@ -291,10 +295,11 @@ bool PlatformAnalyser::send_data(const Message& message) PtopSocket windows_data_socket_steal_construct(std::unique_ptr&& old) { - std::cout << "[Data] Moving linux_reusable_nonblocking_connection_socket " << old->get_identifier_str() << " to a data_socket" << std::endl; + std::cout << "[Data] Moving INonBlockingConnector " << old->get_identifier_str() << " to a PlatformAnalyzer" << std::endl; NonBlockingConnector& real_old = *dynamic_cast(old.get()); PtopSocket epic = real_old.release_socket(); epic.set_non_blocking(false); + epic.set_socket_no_reuse(); return epic; } @@ -495,6 +500,7 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) _socket.connect(results->ai_addr, (socklen_t)results->ai_addrlen); std::cout << "[DataReuseNoB] Successfully BEGUN Connection to: " << ip_address << ":" << port << std::endl; + try_update_endpoint_info(); } catch (const std::exception& e) { From 906614d92a6a5ddce7c756c55c943d18c909fbe3 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:21:53 +1300 Subject: [PATCH 21/44] add: better user input and a few fixes --- src/client.cpp | 99 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 17 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 1dedad0..0837c13 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -53,30 +53,36 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, } EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer_kit) { - if (peer_kit.public_connector->has_connected() == ConnectionStatus::SUCCESS) + auto status = peer_kit.public_connector->has_connected(); + if (status == ConnectionStatus::SUCCESS) { std::cout << "Public Connection has connected" << std::endl; peer_kit.peer_socket = std::make_unique(std::move(peer_kit.public_connector)); return EXECUTION_STATUS::PEER_CONNECTED; } - std::cout << "Public Connection Failed, Retrying connection..." << std::endl; - peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); + else if (status == ConnectionStatus::FAILED) + { + std::cout << "Public Connection Failed, Retrying connection..." << std::endl; + peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); + } return EXECUTION_STATUS::HOLE_PUNCH; } EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& peer_kit) { - if (peer_kit.private_connector->has_connected() == ConnectionStatus::SUCCESS) + auto status = peer_kit.private_connector->has_connected(); + if (status == ConnectionStatus::SUCCESS) { std::cout << "Private Connection has connected" << std::endl; - auto analyser = std::make_unique(std::move(peer_kit.private_connector)); - peer_kit.peer_socket = std::move(analyser); - peer_kit.private_connector = nullptr; + peer_kit.peer_socket = std::make_unique(std::move(peer_kit.private_connector)); return EXECUTION_STATUS::PEER_CONNECTED; } - std::cout << "Private Connection attempt failed, retrying..." << std::endl; - peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); + else if (status == ConnectionStatus::FAILED) + { + std::cout << "Private Connection attempt failed, retrying..." << std::endl; + peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); + } return EXECUTION_STATUS::HOLE_PUNCH; } @@ -111,7 +117,6 @@ EXECUTION_STATUS hole_punch(client_init_kit& init_kit, client_peer_kit& peer_kit try { EXECUTION_STATUS status = EXECUTION_STATUS::HOLE_PUNCH; - std::cout << "Attempting to Hole Punch" << std::endl; if(init_kit.status != EXECUTION_STATUS::PEER_CONNECTED) status = connect_peer(init_kit, peer_kit); @@ -122,9 +127,6 @@ EXECUTION_STATUS hole_punch(client_init_kit& init_kit, client_peer_kit& peer_kit std::cerr << "Time out trying to hole punch reached" << std::endl; return EXECUTION_STATUS::FAILED; } - - else - std::this_thread::sleep_for(100ms); return status; } @@ -234,11 +236,14 @@ void print_help() std::cout << space << space << "sends plain text message of [text] (without braces) to your peer" << std::endl; std::cout << space << space << "example: \"msg: banana\" will send 'banana' to your peer" << std::endl; std::cout << std::endl; + std::cout << space << "quit" << std::endl; + std::cout << space << space << "closes the program" << std::endl; + std::cout << std::endl; std::cout << space << "debug" << std::endl; std::cout << space << space << "outputs current status and relevant information" << std::endl; } -void do_user_input(thread_queue& message_queue, std::unique_lock& take_message_lock, std::unique_ptr& peer_socket) +bool do_user_input(thread_queue& message_queue, std::unique_lock& take_message_lock, std::unique_ptr& peer_socket, client_init_kit& i_kit, client_peer_kit& peer_kit) { if (take_message_lock.try_lock()) { @@ -262,14 +267,73 @@ void do_user_input(thread_queue& message_queue, std::unique_lockget_identifier_str() << std::endl; + } + } + break; + case EXECUTION_STATUS::HOLE_PUNCH: + std::cout << "Hole punching to peer" << std::endl; + if (!peer_kit.public_connector) + std::cout << "Public connector is null" << std::endl; + else + std::cout << "Public connector: " << peer_kit.public_connector->get_identifier_str() << std::endl; + if (!peer_kit.private_connector) + std::cout << "Private connector is null" << std::endl; + else + std::cout << "Private connector: " << peer_kit.private_connector->get_identifier_str() << std::endl; + if (!peer_kit.listen_sock) + std::cout << "Listen socket is null" << std::endl; + else + std::cout << "Listen socket: " << peer_kit.listen_sock->get_identifier_str() << std::endl; + + break; + case EXECUTION_STATUS::PEER_CONNECTED: + std::cout << "Connected to peer" << std::endl; + if (!peer_kit.peer_socket) + std::cout << "Peer socket is null (a bug)" << std::endl; + else + std::cout << "Peer socket is: " << peer_kit.peer_socket->get_identifier_str() << std::endl; + break; + } + } + else if (input_message.substr(0, 4) == "help") { print_help(); } + else + { + std::cout << "Unknown command: " << input_message << std::endl; + std::cout << "Type 'help' to see available commands" << std::endl; + } } take_message_lock.unlock(); } + return false; } void client_loop(std::string server_address_pair, protocol input_protocol) @@ -320,13 +384,14 @@ void client_loop(std::string server_address_pair, protocol input_protocol) if (peer_kit.peer_socket->has_message()) { auto message = peer_kit.peer_socket->receive_message(); - auto process_status = process_peer_data(message, peer_kit.peer_socket); + init_kit.status = process_peer_data(message, peer_kit.peer_socket); } } break; } - do_user_input(message_queue, take_message_lock, peer_kit.peer_socket); + if (do_user_input(message_queue, take_message_lock, peer_kit.peer_socket, init_kit, peer_kit)) + init_kit.status = EXECUTION_STATUS::COMPLETE; std::this_thread::sleep_for(100ms); } From 1db1b95d7460f0c0b7c15c63254955470b1705ea Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 14:23:27 +1300 Subject: [PATCH 22/44] fix: linux build :alien: --- src/linux_platform.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index f0133c4..2141b23 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -47,6 +47,28 @@ Platform::Platform(PtopSocket&& socket) } } +void Platform::try_update_name_info() +{ + try + { + update_name_info(); + } + catch (const std::exception& e) + { + } +} + +void Platform::try_update_endpoint_info() +{ + try + { + update_endpoint_info(); + } + catch (const std::exception& e) + { + } +} + void Platform::update_name_info() { auto name = get_myname_readable(); From 43f5263418f719a27c405c8a7144be782b38ac6d Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 18:05:18 +1300 Subject: [PATCH 23/44] add: delay command to delay a peer --- src/client.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 0837c13..ea08be3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -47,6 +47,7 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); listen_sock = std::make_unique(old_privatename, init_kit.protocol); + listen_sock = std::make_unique(old_privatename, init_kit.protocol, "HolePunch-Listen"); listen_sock->listen(); peer_connect_start_time = std::chrono::system_clock::now(); @@ -156,6 +157,11 @@ EXECUTION_STATUS process_server_data(client_init_kit& init_kit, client_peer_kit& { case MESSAGE_TYPE::CONNECT_TO_PEER: { + if (init_kit.do_delay) + { + std::cout << "Delaying hole punching by 5s..." << std::endl; + std::this_thread::sleep_for(5s); + } peer_kit.set_peer_data(init_kit, data, message_data_index, data_len); return EXECUTION_STATUS::HOLE_PUNCH; } @@ -236,6 +242,10 @@ void print_help() std::cout << space << space << "sends plain text message of [text] (without braces) to your peer" << std::endl; std::cout << space << space << "example: \"msg: banana\" will send 'banana' to your peer" << std::endl; std::cout << std::endl; + std::cout << space << "delay" << std::endl; + std::cout << space << space << "delays this peer's hole punch call by a set amount (changes and cbf updating this every time)" << std::endl; + std::cout << space << space << "this must be called before this peer tries to hole punch" << std::endl; + std::cout << std::endl; std::cout << space << "quit" << std::endl; std::cout << space << space << "closes the program" << std::endl; std::cout << std::endl; @@ -243,6 +253,7 @@ void print_help() std::cout << space << space << "outputs current status and relevant information" << std::endl; } +// Returns whether to quit or not bool do_user_input(thread_queue& message_queue, std::unique_lock& take_message_lock, std::unique_ptr& peer_socket, client_init_kit& i_kit, client_peer_kit& peer_kit) { if (take_message_lock.try_lock()) @@ -273,6 +284,18 @@ bool do_user_input(thread_queue& message_queue, std::unique_lock Date: Fri, 28 Jan 2022 18:06:50 +1300 Subject: [PATCH 24/44] add + fix: named sockets and working linux --- src/client.cpp | 22 +++---- src/client.h | 1 + src/interfaces.h | 3 + src/linux_platform.cpp | 75 ++++++++++++------------ src/platform.cpp | 9 ++- src/platform.h | 11 ++-- src/ptop_socket.cpp | 4 +- src/ptop_socket.h | 19 ++++-- src/server.cpp | 2 +- src/windows_platform.cpp | 122 +++++++++++++++++++++------------------ 10 files changed, 152 insertions(+), 116 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index ea08be3..75b348d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -12,7 +12,7 @@ using namespace std::chrono; client_init_kit::client_init_kit(std::string server_address_pair, ::protocol chosen_protocol) : protocol(chosen_protocol) { - _server_socket = std::make_unique(server_address_pair, ServerListenPort, protocol); + _server_socket = std::make_unique(server_address_pair, ServerListenPort, protocol, "Server-Conn"); // Indicate to server we're ready for p2p server_last_send = std::chrono::system_clock::now(); _server_socket->send_data(create_message(MESSAGE_TYPE::MY_DATA, _server_socket->get_myname_readable().to_bytes())); @@ -43,10 +43,9 @@ void client_peer_kit::set_peer_data(client_init_kit& init_kit, const char* data, old_privatename = init_kit.get_server_socket()->get_myname_raw(); init_kit.set_server_socket(nullptr); //need to close the server socket HERE to maintain the same session in the peer sockets - public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol); - private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol); + public_connector = std::make_unique(old_privatename, public_info.ip_address, public_info.port, init_kit.protocol, "HolePunch-Public"); + private_connector = std::make_unique(old_privatename, private_info.ip_address, private_info.port, init_kit.protocol, "HolePunch-Private"); - listen_sock = std::make_unique(old_privatename, init_kit.protocol); listen_sock = std::make_unique(old_privatename, init_kit.protocol, "HolePunch-Listen"); listen_sock->listen(); @@ -59,13 +58,15 @@ EXECUTION_STATUS connect_public(client_init_kit& init_kit, client_peer_kit& peer { std::cout << "Public Connection has connected" << std::endl; peer_kit.peer_socket = std::make_unique(std::move(peer_kit.public_connector)); + peer_kit.peer_socket->set_name("Public-Peer"); return EXECUTION_STATUS::PEER_CONNECTED; } else if (status == ConnectionStatus::FAILED) { std::cout << "Public Connection Failed, Retrying connection..." << std::endl; - peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol); + peer_kit.public_connector = nullptr; + peer_kit.public_connector = std::make_unique(peer_kit.old_privatename, peer_kit.public_info.ip_address, peer_kit.public_info.port, init_kit.protocol, "HolePunch-Public"); } return EXECUTION_STATUS::HOLE_PUNCH; } @@ -76,13 +77,15 @@ EXECUTION_STATUS connect_private(client_init_kit& init_kit, client_peer_kit& pee { std::cout << "Private Connection has connected" << std::endl; peer_kit.peer_socket = std::make_unique(std::move(peer_kit.private_connector)); + peer_kit.peer_socket->set_name("Private-Peer"); return EXECUTION_STATUS::PEER_CONNECTED; } else if (status == ConnectionStatus::FAILED) { std::cout << "Private Connection attempt failed, retrying..." << std::endl; - peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol); + peer_kit.private_connector = nullptr; + peer_kit.private_connector = std::make_unique(peer_kit.old_privatename, peer_kit.private_info.ip_address, peer_kit.private_info.port, init_kit.protocol, "HolePunch-Private"); } return EXECUTION_STATUS::HOLE_PUNCH; } @@ -95,7 +98,6 @@ EXECUTION_STATUS connect_listener(client_peer_kit& peer_kit) { return EXECUTION_STATUS::PEER_CONNECTED; } - std::cout << "Listen Connection attempt failed, retrying..." << std::endl; return EXECUTION_STATUS::HOLE_PUNCH; } @@ -103,13 +105,13 @@ EXECUTION_STATUS connect_peer(client_init_kit& init_kit, client_peer_kit& peer_k if(peer_kit.peer_socket) return EXECUTION_STATUS::PEER_CONNECTED; - auto status = connect_public(init_kit, peer_kit); + auto status = connect_listener(peer_kit); if(status != EXECUTION_STATUS::PEER_CONNECTED) - status = connect_private(init_kit, peer_kit); + status = connect_public(init_kit, peer_kit); if(status != EXECUTION_STATUS::PEER_CONNECTED) - status = connect_listener(peer_kit); + status = connect_private(init_kit, peer_kit); return status; } diff --git a/src/client.h b/src/client.h index 32499db..66c4f1c 100644 --- a/src/client.h +++ b/src/client.h @@ -17,6 +17,7 @@ class client_init_kit { std::chrono::system_clock::time_point server_last_send; EXECUTION_STATUS status; ::protocol protocol; + bool do_delay = false; std::unique_ptr& get_server_socket(); void set_server_socket(std::unique_ptr&& input); diff --git a/src/interfaces.h b/src/interfaces.h index e32f049..e820360 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -21,6 +21,9 @@ class ISocketWrapper virtual std::string get_endpoint_ip() const = 0; virtual std::string get_endpoint_port() const = 0; virtual std::string get_identifier_str() = 0; + + virtual const std::string& get_name() const = 0; + virtual void set_name(std::string name) = 0; }; class IDataSocketWrapper : virtual public ISocketWrapper diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 2141b23..79a666a 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -38,7 +38,7 @@ std::string linux_error(int err_code) Platform::Platform(PtopSocket&& socket) : _socket(std::move(socket)) -{ +{ try_update_name_info(); if (_address == "Unassigned" || _address.empty() || @@ -143,14 +143,14 @@ raw_name_data Platform::get_myname_raw() const return _socket.get_name_raw(); } -PtopSocket listen_construct(std::string port, protocol input_proto) +PtopSocket listen_construct(std::string port, protocol input_proto, std::string name) { - std::cout << "[Listen] Create new Socket on port (with localhost): " << port << std::endl; - auto listen_socket = PtopSocket(input_proto); + std::cout << "[Listen] Creating new Socket on port (with localhost, named: " << name << "): " << port << std::endl; + auto listen_socket = PtopSocket(input_proto, name); socklen_t cli_len; if (listen_socket.is_invalid()) - throw std::runtime_error(std::string("[Listen] Failed to create linux socket: ") + linux_error()); + throw std::runtime_error(std::string("[Listen] ") + name + " Failed to create linux socket : " + linux_error()); listen_socket.set_socket_reuse(); @@ -162,19 +162,19 @@ PtopSocket listen_construct(std::string port, protocol input_proto) serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); - std::cout << "Binding..." << std::endl; + std::cout << name << " Binding..." << std::endl; listen_socket.bind_socket(raw_name_data{ *(sockaddr*)&serv_addr, sizeof(serv_addr) }); return listen_socket; } -PlatformListener::PlatformListener(std::string port, protocol input_proto) : Platform(listen_construct(port, input_proto)) +PlatformListener::PlatformListener(std::string port, protocol input_proto, std::string name) : Platform(listen_construct(port, input_proto, name)) { } void PlatformListener::listen() { - std::cout << "[Listen] Socket now Listening (" << get_my_ip() << ":" << get_my_port() << ")" << std::endl; + std::cout << "[Listen] Socket " << get_name() << " now Listening(" << get_my_ip() << ":" << get_my_port() << ")" << std::endl; _socket.start_listening(); } @@ -185,7 +185,7 @@ bool PlatformListener::has_connection() std::unique_ptr PlatformListener::accept_connection() { - std::cout << "[Listen] Socket Attempting to accept a connection" << std::endl; + std::cout << "[Listen] " << get_identifier_str() << " Attempting to accept a connection" << std::endl; try { auto tmp = _socket.accept_data_socket(); @@ -286,9 +286,9 @@ PlatformAnalyser::PlatformAnalyser(PtopSocket&& socket) : Platform(std::move(soc throw std::runtime_error("[Data] Invalid socket in Copy Constructor"); } -PtopSocket data_connect_construct(std::string peer_address, std::string peer_port, protocol ip_proto) +PtopSocket data_connect_construct(std::string peer_address, std::string peer_port, protocol ip_proto, std::string name) { - std::cout << "[Data] Creating a Linux Data Socket connecting to: " << peer_address << ":" << peer_port << std::endl; + std::cout << "[Data] Creating a Linux Data Socket (named " << name << ") connecting to : " << peer_address << ":" << peer_port << std::endl; struct addrinfo* result = NULL, * ptr = NULL, @@ -302,16 +302,17 @@ PtopSocket data_connect_construct(std::string peer_address, std::string peer_por int n = getaddrinfo(peer_address.c_str(), peer_port.c_str(), &hints, &result); if (n == SOCKET_ERROR) - throw_new_exception("Failed to get address info for: " + peer_address + ":" + peer_port + " with: " + linux_error(), LINE_CONTEXT); + throw_new_exception("Failed to get address info for: (" + name + ") " + peer_address + ":" + peer_port + " with: " + linux_error(), LINE_CONTEXT); - auto conn_socket = PtopSocket(ip_proto); + auto conn_socket = PtopSocket(ip_proto, name); + conn_socket.set_socket_reuse(); conn_socket.connect(result->ai_addr, result->ai_addrlen); return conn_socket; } -PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol proto) -: Platform(data_connect_construct(peer_address, peer_port, proto)) +PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol proto, std::string name) +: Platform(data_connect_construct(peer_address, peer_port, proto, name)) { try_update_endpoint_info(); } @@ -327,7 +328,7 @@ Message PlatformAnalyser::receive_message() return tmp; } - throw_new_exception("Failed to parse incoming data", LINE_CONTEXT); + return Message::null_message; } bool PlatformAnalyser::has_message() @@ -347,15 +348,15 @@ bool PlatformAnalyser::send_data(const Message& message) return false; } -PtopSocket reuse_listen_construct(raw_name_data data, protocol proto) +PtopSocket reuse_listen_construct(raw_name_data data, protocol proto, std::string name) { auto readable = convert_to_readable(data); - std::cout << "[ListenReuseNoB] Creating Reusable Listen Socket on: " << readable.ip_address << ":" << readable.port << std::endl; + std::cout << "[ListenReuseNoB] Creating Reusable Listen Socket '" << name << "' on: " << readable.ip_address << ":" << readable.port << std::endl; - auto listen_socket = PtopSocket(proto); + auto listen_socket = PtopSocket(proto, name); if (listen_socket.is_invalid()) - throw std::runtime_error("[ListenReuseNoB] " + readable.ip_address + ":" + readable.port + " Failed to create reusable nonblocking listen socket: " + linux_error()); + throw_new_exception("[ListenReuseNoB] (" + name + ") " + readable.ip_address + ":" + readable.port + " Failed to create reusable nonblocking listen socket: " + linux_error(), LINE_CONTEXT); listen_socket.set_non_blocking(true); listen_socket.set_socket_reuse(); @@ -365,15 +366,15 @@ PtopSocket reuse_listen_construct(raw_name_data data, protocol proto) return listen_socket; } -NonBlockingListener::NonBlockingListener(raw_name_data data, protocol proto) -: Platform(reuse_listen_construct(data, proto)) +NonBlockingListener::NonBlockingListener(raw_name_data data, protocol proto, std::string name) +: Platform(reuse_listen_construct(data, proto, name)) { } void NonBlockingListener::listen() { - std::cout << "[ListenReuseNoB] Now Listening on: " << get_my_ip() << ":" << get_my_port() << std::endl; + std::cout << "[ListenReuseNoB] " + get_identifier_str() + " Now Listening on port: " << get_my_port() << std::endl; _socket.listen(4); } @@ -384,17 +385,17 @@ bool NonBlockingListener::has_connection() std::unique_ptr NonBlockingListener::accept_connection() { - std::cout << "[ListenReuseNoB] Accepting Connection..." << std::endl; + std::cout << "[ListenReuseNoB] " + get_identifier_str() + " Accepting Connection..." << std::endl; auto new_sock = _socket.accept_data_socket(); return std::make_unique(std::move(new_sock)); } -PtopSocket reuse_connection_construct(raw_name_data data, protocol proto) +PtopSocket reuse_connection_construct(raw_name_data data, protocol proto, std::string name) { auto readable = convert_to_readable(data); - std::cout << "[DataReuseNoB] Creating Connection socket bound to: " << readable.ip_address << ":" << readable.port << std::endl; - auto conn_socket = PtopSocket(proto); + std::cout << "[DataReuseNoB] Creating Connection socket '" << name << "' bound to : " << readable.ip_address << ":" << readable.port << std::endl; + auto conn_socket = PtopSocket(proto, name); if (conn_socket.is_invalid()) throw_new_exception("[DataReuseNoB] Failed to create nonblocking socket: " + linux_error(), LINE_CONTEXT); @@ -402,14 +403,14 @@ PtopSocket reuse_connection_construct(raw_name_data data, protocol proto) conn_socket.set_non_blocking(true); conn_socket.set_socket_reuse(); - conn_socket.bind_socket(data, "[DataReuseNoB] Failed to bind"); - std::cout << "[DataReuseNoB] Successfully bound Data socket to: " << readable.ip_address << ":" << readable.port << std::endl; + conn_socket.bind_socket(data, std::string("[DataReuseNoB] (") + name + ") Failed to bind"); + std::cout << "[DataReuseNoB] Successfully bound Data socket (" << name << ") to: " << readable.ip_address << ":" << readable.port << std::endl; return conn_socket; } -NonBlockingConnector::NonBlockingConnector(raw_name_data data, std::string ip_address, std::string port, protocol proto) -: Platform(reuse_connection_construct(data, proto)) +NonBlockingConnector::NonBlockingConnector(raw_name_data data, std::string ip_address, std::string port, protocol proto, std::string name) +: Platform(reuse_connection_construct(data, proto, name)) { // if tcp? try @@ -426,7 +427,7 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) { try { - std::cout << "[DataReuseNoB] Trying to connect to: " << ip_address << ":" << port << std::endl; + std::cout << "[DataReuseNoB] (" << get_name() << ") Trying to connect to : " << ip_address << ":" << port << std::endl; struct addrinfo* results, hints; bzero(&hints, sizeof(hints)); hints.ai_family = AF_INET; @@ -437,13 +438,13 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) iResult = getaddrinfo(ip_address.c_str(), port.c_str(), &hints, &results); if (iResult != 0) - throw_new_exception("Failed to getaddrinfo, error: " + std::to_string(iResult), LINE_CONTEXT); + throw_new_exception("Socket '" + get_name() + "' Failed to getaddrinfo, error: " + std::to_string(iResult), LINE_CONTEXT); if (results == nullptr) - throw_new_exception(("No possible sockets found for '") + ip_address + ":" + port + "'", LINE_CONTEXT); + throw_new_exception(("No possible sockets found for '") + ip_address + ":" + port + "' (socket '" + get_name() + "')", LINE_CONTEXT); _socket.connect(results->ai_addr, results->ai_addrlen); - std::cout << "[DataReuseNoB] Successfully BEGUN Connection to: " << ip_address << ":" << port << std::endl; + std::cout << "[DataReuseNoB] (" << get_name() << ") Successfully BEGUN Connection to : " << ip_address << ":" << port << std::endl; try_update_endpoint_info(); } catch (const std::exception& e) @@ -464,7 +465,7 @@ ConnectionStatus NonBlockingConnector::has_connected() auto sock_error = _socket.get_socket_option(SO_ERROR); if (sock_error != 0 && sock_error != EAGAIN && sock_error != EINPROGRESS) { - std::cerr << LINE_CONTEXT << " [DataReuseNoB] Socket failed to connect with: " << linux_error(sock_error) << std::endl; + std::cerr << "[DataReuseNoB] " << LINE_CONTEXT << " Socket '" << get_name() << "' failed to connect with: " << linux_error(sock_error) << std::endl; return ConnectionStatus::FAILED; } @@ -478,7 +479,7 @@ ConnectionStatus NonBlockingConnector::has_connected() auto sock_error = _socket.get_socket_option(SO_ERROR); - std::cerr << LINE_CONTEXT << " [DataReuseNoB] Socket failed to connect with: " << linux_error(sock_error) << std::endl; + std::cerr << "[DataReuseNoB] " << LINE_CONTEXT << " Socket '" << get_name() << "' failed to connect with: " << linux_error(sock_error) << std::endl; return ConnectionStatus::FAILED; } diff --git a/src/platform.cpp b/src/platform.cpp index c34c170..a7803dd 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -8,16 +8,19 @@ #include std::string Platform::get_identifier_str() { + std::string name_str = "Unnamed"; + if (_socket.get_name().size()) + name_str = _socket.get_name(); if (_socket.is_listen()) - return std::string("(listen on: ") + _address + ":" + _port + ")"; + return std::string("(") + name_str + " is a listen on: " + _address + ":" + _port + ")"; if (_endpoint_assigned == false) try_update_endpoint_info(); if (_endpoint_assigned == false) - return std::string("(priv: ") + _address + ":" + _port + ", pub: N/A)"; + return std::string("(") + name_str + " priv: " + _address + ":" + _port + ", pub : N / A)"; - return std::string("(pub: ") + _address + ":" + _port + ")"; + return std::string("(") + name_str + " pub: " + _address + ":" + _port + ")"; } readable_ip_info convert_to_readable(raw_name_data data) diff --git a/src/platform.h b/src/platform.h index cb98008..64ccba1 100644 --- a/src/platform.h +++ b/src/platform.h @@ -47,13 +47,16 @@ class Platform : public virtual ISocketWrapper { inline std::string get_endpoint_port() const override { return _endpoint_port; } std::string get_identifier_str() override; + inline const std::string& get_name() const override { return _socket.get_name(); } + inline void set_name(std::string name) override { return _socket.set_name(name); } + inline PtopSocket&& release_socket() { return std::move(_socket); } virtual ~Platform(); }; class PlatformListener : public Platform, public virtual IListenSocketWrapper { public: - PlatformListener(std::string port, protocol input_protocol); + PlatformListener(std::string port, protocol input_protocol, std::string name); void listen() override; bool has_connection() override; std::unique_ptr accept_connection() override; @@ -66,7 +69,7 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { public: PlatformAnalyser(std::unique_ptr&& old); PlatformAnalyser(PtopSocket&& socket); - PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol); + PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name); Message receive_message() override; bool has_message() override; @@ -76,7 +79,7 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { class NonBlockingListener : public Platform, public virtual INonBlockingListener { public: - NonBlockingListener(raw_name_data data, protocol input_protocol); + NonBlockingListener(raw_name_data data, protocol input_protocol, std::string name); void listen() override; bool has_connection() override; @@ -85,7 +88,7 @@ class NonBlockingListener : public Platform, public virtual INonBlockingListener class NonBlockingConnector : public Platform, public virtual INonBlockingConnector { public: - NonBlockingConnector(raw_name_data private_binding, std::string ip_address, std::string port, protocol input_protocol); + NonBlockingConnector(raw_name_data private_binding, std::string ip_address, std::string port, protocol input_protocol, std::string); void connect(std::string ip_address, std::string port) override; // Called in constructor, can be called again if it fails ConnectionStatus has_connected() override; diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 0f50384..3d0da47 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -25,7 +25,7 @@ #include -PtopSocket::PtopSocket(protocol proto) : _protocol(proto) +PtopSocket::PtopSocket(protocol proto, std::string name) : _protocol(proto), _name(std::move(name)) { int domain = _protocol.get_ai_family(); int type = _protocol.get_ai_socktype(); @@ -36,7 +36,7 @@ PtopSocket::PtopSocket(protocol proto) : _protocol(proto) PtopSocket& PtopSocket::bind_socket(const raw_name_data& name, std::string error_message) { int result = bind(_handle, &name.name, name.name_len); - throw_if_socket_error(result, error_message, LINE_CONTEXT); + throw_if_socket_error(result, error_message + " " + get_last_error(), LINE_CONTEXT); return *this; } diff --git a/src/ptop_socket.h b/src/ptop_socket.h index 9b0e5d8..337dc0a 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -33,18 +33,29 @@ class PtopSocket SOCKET _handle; protocol _protocol; raw_name_data _endpoint; - PtopSocket(SOCKET handle, protocol proto) : _handle(handle), _protocol(proto), _endpoint() {} - PtopSocket(SOCKET handle, protocol proto, raw_name_data endpoint) : _handle(handle), _protocol(proto), _endpoint(endpoint) {} + std::string _name; + PtopSocket(SOCKET handle, protocol proto, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(), _name(name) {} + PtopSocket(SOCKET handle, protocol proto, raw_name_data endpoint, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(endpoint), _name(name) {} public: - explicit PtopSocket(protocol proto); + explicit PtopSocket(protocol proto, std::string name = ""); - PtopSocket(PtopSocket&& other) : _handle(other._handle), _protocol(other._protocol) { + PtopSocket(PtopSocket&& other) : _handle(other._handle), _protocol(other._protocol), _name(std::move(other._name)) { other._handle = REALLY_INVALID_SOCKET; }; ~PtopSocket(); + inline void set_name(std::string name) + { + _name = std::move(name); + } + + inline const std::string& get_name() const + { + return _name; + } + template PtopSocket& set_socket_option(int option_name, OptT optionVal, std::string error_message) { diff --git a/src/server.cpp b/src/server.cpp index d9ec0a6..ffb77f6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -18,7 +18,7 @@ server_init_kit::server_init_kit(protocol ip_proto) : proto(ip_proto) { clientB = nullptr; cA = nullptr; cB = nullptr; - server_socket = std::make_unique(ServerListenPort, ip_proto); + server_socket = std::make_unique(ServerListenPort, ip_proto, "Server-Listener"); server_socket->listen(); recv_data = std::vector(); //dont need to initialize structs. it will default its params by itself diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index b8ab656..88ae680 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -141,7 +141,7 @@ readable_ip_info Platform::get_peer_data() const std::vector buf{ 50, '0', std::allocator() }; const char* str = inet_ntop(AF_INET, &peer_name.sin_addr, buf.data(), buf.size()); if (!str) - throw std::runtime_error(std::string("Failed to convert sockaddr to string: ") + get_last_error()); + throw std::runtime_error(std::string("Socket '") + get_name() + "' Failed to convert sockaddr to string : " + get_last_error()); std::string address = str; @@ -158,7 +158,7 @@ raw_name_data Platform::get_peername_raw() const socklen_t peer_size = sizeof(peer_name); int n = getpeername(_socket.get_handle(), (sockaddr*)&peer_name, &peer_size); if (n != 0) { - auto error = std::string("[Socket] Failed to getpeername: ") + get_last_error(); + auto error = std::string("[Socket] (" + get_name() + ") Failed to getpeername : ") + get_last_error(); throw_new_exception(error, LINE_CONTEXT); } @@ -175,7 +175,7 @@ raw_name_data Platform::get_myname_raw() const int n = getsockname(_socket.get_handle(), (sockaddr*)&peer_name, &peer_size); if (n != 0) { - auto error = std::string("[Socket] Failed to getsockname: ") + get_last_error(); + auto error = std::string("[Socket] (" + get_name() + ") Failed to getsockname : ") + get_last_error(); throw_new_exception(error, LINE_CONTEXT); } @@ -185,10 +185,10 @@ raw_name_data Platform::get_myname_raw() const return raw_data; } -PtopSocket construct_windowslistensocket(std::string port, protocol input_protocol) { +PtopSocket construct_windowslistensocket(std::string port, protocol input_protocol, std::string name) { try { - std::cout << "[Listen] Create new Socket on port (with localhost): " << port << std::endl; + std::cout << "[Listen] Creating new Socket on port (with localhost, named: " << name << "): " << port << std::endl; int iResult; struct addrinfo* result = NULL, * ptr = NULL, hints; @@ -201,17 +201,17 @@ PtopSocket construct_windowslistensocket(std::string port, protocol input_protoc iResult = getaddrinfo(NULL, port.c_str(), &hints, &result); if (iResult != 0) { - throw std::exception((std::string("[Listen] Failed to create windows socket: getaddrinfo failed with") + std::to_string(iResult)).c_str()); + throw std::exception((std::string("[Listen] (" + name + ") Failed to create windows socket : getaddrinfo failed with") + std::to_string(iResult)).c_str()); } - PtopSocket conn_socket = PtopSocket(input_protocol); + PtopSocket conn_socket = PtopSocket(input_protocol, name); if (conn_socket.is_invalid()) { - throw std::exception((std::string("[Listen] Failed to create socket with WSA error: ") + get_last_error()).c_str()); + throw std::exception((std::string("[Listen] (" + name + ") Failed to create socket with WSA error : ") + get_last_error()).c_str()); } - std::cout << "Binding..." << std::endl; + std::cout << name << " is Binding..." << std::endl; conn_socket.bind_socket(raw_name_data{ *result->ai_addr, (socklen_t)result->ai_addrlen }); return conn_socket; @@ -222,13 +222,13 @@ PtopSocket construct_windowslistensocket(std::string port, protocol input_protoc } } -PlatformListener::PlatformListener(std::string port, protocol input_protocol) : Platform(construct_windowslistensocket(port, input_protocol)) +PlatformListener::PlatformListener(std::string port, protocol input_protocol, std::string name) : Platform(construct_windowslistensocket(port, input_protocol, name)) { - std::cout << "[Listen] Post Bind Check: Bound to: " << get_my_ip() << ":" << get_my_port() << std::endl; } void PlatformListener::listen() { + std::cout << "[Listen] Socket " << get_name() << " now Listening(" << get_my_ip() << ":" << get_my_port() << ")" << std::endl; _socket.listen(4); } @@ -243,8 +243,8 @@ std::unique_ptr PlatformListener::accept_connection() { return std::make_unique(std::move(tmp)); } -PtopSocket construct_windows_data_socket(std::string peer_address, std::string peer_port, protocol input_protocol) { - std::cout << "[Data] Creating a Windows Data Socket connecting to: " << peer_address << ":" << peer_port << std::endl; +PtopSocket construct_windows_data_socket(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name) { + std::cout << "[Data] Creating a Windows Data Socket (" << name << ") connecting to : " << peer_address << " : " << peer_port << std::endl; struct addrinfo* result = NULL, *ptr = NULL, hints; @@ -259,17 +259,17 @@ PtopSocket construct_windows_data_socket(std::string peer_address, std::string p if (iResult != 0) { std::cerr << "Failed to resolve server: " << iResult << std::endl; - throw std::exception((std::string("Failed to resolve peer address, error: ") + std::to_string(iResult)).c_str()); + throw std::exception((std::string("Socket " + name + " Failed to resolve peer address, error: ") + std::to_string(iResult)).c_str()); } - PtopSocket conn_socket = PtopSocket(input_protocol); + PtopSocket conn_socket = PtopSocket(input_protocol, name); conn_socket.connect(result->ai_addr, (socklen_t)result->ai_addrlen); return conn_socket; } -PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol) : Platform(construct_windows_data_socket(peer_address, peer_port, input_protocol)) +PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name) : Platform(construct_windows_data_socket(peer_address, peer_port, input_protocol, name)) { try { @@ -401,16 +401,16 @@ bool PlatformAnalyser::has_message() return _socket.has_message(); } -PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto) +PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto, std::string name) { try { auto readable = convert_to_readable(data); - std::cout << "[ListenReuseNoB] Creating Reusable Listen Socket on: " << readable.ip_address << ":" << readable.port << std::endl; + std::cout << "[ListenReuseNoB] Creating Reusable Listen Socket '" << name << "' on: " << readable.ip_address << ":" << readable.port << std::endl; - PtopSocket listen_socket = PtopSocket(proto); + PtopSocket listen_socket = PtopSocket(proto, name); if (listen_socket.is_invalid()) - throw_new_exception("[ListenReuseNoB] " + readable.ip_address + ":" + readable.port + " Failed to create reusable nonblocking listen socket: " + get_last_error(), LINE_CONTEXT); + throw_new_exception("[ListenReuseNoB] (" + name + ") " + readable.ip_address + ":" + readable.port + " Failed to create reusable nonblocking listen socket: " + get_last_error(), LINE_CONTEXT); listen_socket.set_non_blocking(true); listen_socket.set_socket_reuse(); @@ -425,13 +425,15 @@ PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto) } } -NonBlockingListener::NonBlockingListener(raw_name_data data, protocol input_protocol) : Platform( - windows_reuse_nb_listen_construct(data, input_protocol)) +NonBlockingListener::NonBlockingListener(raw_name_data data, protocol input_protocol, std::string name) + : Platform( + windows_reuse_nb_listen_construct(data, input_protocol, name) + ) {} void NonBlockingListener::listen() { - std::cout << "[ListenReuseNoB] Now Listening on: " << Platform::get_my_ip() << ":" << Platform::get_my_port() << std::endl; + std::cout << "[ListenReuseNoB] " + get_identifier_str() + " Now Listening on port: " << get_my_port() << std::endl; _socket.listen(4); } @@ -442,26 +444,26 @@ bool NonBlockingListener::has_connection() std::unique_ptr NonBlockingListener::accept_connection() { - std::cout << "[ListenReuseNoB] Accepting Connection..." << std::endl; + std::cout << "[ListenReuseNoB] " + get_identifier_str() + " Accepting Connection..." << std::endl; auto new_sock = _socket.accept_data_socket(); return std::make_unique(std::move(new_sock)); } -PtopSocket windows_reuse_nb_construct(raw_name_data name, protocol proto) +PtopSocket windows_reuse_nb_construct(raw_name_data data, protocol proto, std::string name) { try { - auto readable = convert_to_readable(name); - std::cout << "[DataReuseNoB] Creating Connection socket bound to: " << readable.ip_address << ":" << readable.port << std::endl; - auto conn_socket = PtopSocket(proto); + auto readable = convert_to_readable(data); + std::cout << "[DataReuseNoB] Creating Connection socket '" << name << "' bound to : " << readable.ip_address << ":" << readable.port << std::endl; + auto conn_socket = PtopSocket(proto, name); if (conn_socket.is_invalid()) - throw std::runtime_error(std::string("[DataReuseNoB] Failed to create nonblocking socket: ") + get_last_error()); + throw_new_exception(std::string("[DataReuseNoB] Failed to create nonblocking socket (" + name + "): ") + get_last_error(), LINE_CONTEXT); conn_socket.set_non_blocking(true); conn_socket.set_socket_reuse(); - conn_socket.bind_socket(name, "[DataReuseNoB] Failed to bind"); - std::cout << "[DataReuseNoB] Successfully bound Data socket to: " << readable.ip_address << ":" << readable.port << std::endl; + conn_socket.bind_socket(data, "[DataReuseNoB] '" + name + "' Failed to bind"); + std::cout << "[DataReuseNoB] Successfully bound Data socket (" << name << ") to: " << readable.ip_address << " : " << readable.port << std::endl; return conn_socket; } @@ -472,8 +474,10 @@ PtopSocket windows_reuse_nb_construct(raw_name_data name, protocol proto) } NonBlockingConnector::NonBlockingConnector( - raw_name_data name, std::string ip_address, std::string port, protocol input_protocol) : Platform( - windows_reuse_nb_construct(name, input_protocol)) + raw_name_data data, std::string ip_address, std::string port, protocol input_protocol, std::string name) + : Platform( + windows_reuse_nb_construct(data, input_protocol, name) + ) { connect(ip_address, port); } @@ -482,7 +486,7 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) { try { - std::cout << "[DataReuseNoB] Trying to connect to: " << ip_address << ":" << port << std::endl; + std::cout << "[DataReuseNoB] (" << get_name() << ") Trying to connect to : " << ip_address << ":" << port << std::endl; struct addrinfo* results, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; @@ -493,13 +497,13 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) iResult = getaddrinfo(ip_address.c_str(), port.c_str(), &hints, &results); if (iResult != 0) - throw std::exception((std::string("Failed to resolve peer address, error: ") + std::to_string(iResult)).c_str()); + throw_new_exception("Socket '" + get_name() + "' Failed to getaddrinfo, error: " + std::to_string(iResult), LINE_CONTEXT); if (results == nullptr) - throw std::exception((std::string("Could not resolve '") + ip_address + ":" + port + "'").c_str()); + throw_new_exception(("No possible sockets found for '") + ip_address + ":" + port + "' (socket '" + get_name() + "')", LINE_CONTEXT); _socket.connect(results->ai_addr, (socklen_t)results->ai_addrlen); - std::cout << "[DataReuseNoB] Successfully BEGUN Connection to: " << ip_address << ":" << port << std::endl; + std::cout << "[DataReuseNoB] (" << get_name() << ") Successfully BEGUN Connection to : " << ip_address << ":" << port << std::endl; try_update_endpoint_info(); } catch (const std::exception& e) @@ -510,30 +514,38 @@ void NonBlockingConnector::connect(std::string ip_address, std::string port) ConnectionStatus NonBlockingConnector::has_connected() { - try - { - if (_socket.is_invalid()) - return ConnectionStatus::FAILED; + try + { + if (_socket.is_invalid()) + return ConnectionStatus::FAILED; - if (_socket.poll_for(POLLWRNORM)) - { - return ConnectionStatus::SUCCESS; - } + if (_socket.select_for(select_for::WRITE)) + { + auto sock_error = _socket.get_socket_option(SO_ERROR); + if (sock_error != 0 && sock_error != EAGAIN && sock_error != EINPROGRESS) + { + std::cerr << "[DataReuseNoB] " << LINE_CONTEXT << " Socket '" << get_name() << "' failed to connect with: " << get_win_error(sock_error) << std::endl; + return ConnectionStatus::FAILED; + } + + update_endpoint_if_needed(); + return ConnectionStatus::SUCCESS; + } - if (!_socket.select_for(select_for::EXCEPT)) - return ConnectionStatus::PENDING; + if (!_socket.select_for(select_for::EXCEPT)) + return ConnectionStatus::PENDING; - auto sock_error = _socket.get_socket_option(SO_ERROR); + auto sock_error = _socket.get_socket_option(SO_ERROR); - std::cerr << "Socket has error code: " << sock_error << std::endl; + std::cerr << "[DataReuseNoB] " << LINE_CONTEXT << " Socket '" << get_name() << "' failed to connect with: " << get_win_error(sock_error) << std::endl; - return ConnectionStatus::FAILED; - } - catch (const std::exception& e) - { - throw_with_context(e, LINE_CONTEXT); - } + return ConnectionStatus::FAILED; + } + catch (const std::exception& e) + { + throw_with_context(e, LINE_CONTEXT); + } } #endif \ No newline at end of file From 1f17f667fdf1fb6dacdb121b1dc013d27b3d75f5 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 18:49:01 +1300 Subject: [PATCH 25/44] add: connect sockets use SO_KEEPALIVE --- src/ptop_socket.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 3d0da47..47f7483 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -44,6 +44,8 @@ PtopSocket& PtopSocket::connect(sockaddr* addr, socklen_t len) { if (_protocol.is_tcp()) { + // cheeky little hack + set_socket_option(SO_KEEPALIVE, (int)1); int n = ::connect(_handle, addr, len); throw_if_socket_error(n, "Failed to connect " + get_last_error(), LINE_CONTEXT); } @@ -76,7 +78,9 @@ PtopSocket PtopSocket::accept_data_socket() { throw_new_exception("Failed to accept incoming connection: " + get_last_error(), LINE_CONTEXT); } - return PtopSocket(new_socket, _protocol, raw_name_data(client_addr)); + auto new_sock = PtopSocket(new_socket, _protocol, raw_name_data(client_addr)); + new_sock.set_socket_option(SO_KEEPALIVE, (int)1); + return new_sock; } catch(std::exception& e) { From af4dc54c718673bae5e5d178c6b57ceb50038993 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Fri, 28 Jan 2022 18:50:13 +1300 Subject: [PATCH 26/44] add: no longer responds to empty input --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 75b348d..00788bf 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -349,7 +349,7 @@ bool do_user_input(thread_queue& message_queue, std::unique_lock Date: Sun, 30 Jan 2022 16:38:40 +1300 Subject: [PATCH 27/44] refactor: socket type in common spot --- src/protocol.cpp | 2 ++ src/protocol.h | 2 ++ src/ptop_socket.h | 9 +-------- src/socket.h | 9 +++++++++ src/windows_platform.cpp | 5 +++++ 5 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/socket.h diff --git a/src/protocol.cpp b/src/protocol.cpp index 346849a..7a8b232 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,5 +1,7 @@ #include "protocol.h" #include "error.h" +#include "ptop_socket.h" +#include "socket.h" #if defined(WIN32) | defined(_WIN64) #include diff --git a/src/protocol.h b/src/protocol.h index f61169b..e2d7c70 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,6 +1,8 @@ #pragma once +#include "socket.h" #include +#include "name_data.h" class protocol { public: diff --git a/src/ptop_socket.h b/src/ptop_socket.h index 337dc0a..0a7c930 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -1,17 +1,10 @@ #pragma once +#include "socket.h" #include "name_data.h" #include "protocol.h" #include "error.h" -#ifdef WIN32 -#include - -#elif defined(__linux__) -#include -using SOCKET = int; -#endif - #include constexpr SOCKET REALLY_INVALID_SOCKET = -1; diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..c60f3a1 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef WIN32 +#include + +#elif defined(__linux__) +#include +using SOCKET = int; +#endif diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index 88ae680..9908bda 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -18,6 +18,11 @@ Platform::Platform(PtopSocket&& socket) try_update_name_info(); // big chungus + if(_socket.is_udp()) { + std::cout << "Platform constructed for UDP" << std::endl; + return; + } + if (_address == "Unassigned" || _address.empty() || _port == "Unassigned" || _port.empty()) { auto message = "failed to update name info"; From dfc2a3629a95e959415b273486e59f1da76f362b Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Sun, 30 Jan 2022 16:49:39 +1300 Subject: [PATCH 28/44] refactor: move protocol specific messaging to protocol class --- src/platform.h | 3 --- src/protocol.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++ src/protocol.h | 5 +++- src/ptop_socket.cpp | 58 ++++----------------------------------------- src/socket.h | 2 ++ 5 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/platform.h b/src/platform.h index 64ccba1..358e5e3 100644 --- a/src/platform.h +++ b/src/platform.h @@ -6,9 +6,6 @@ #include "ptop_socket.h" #include "interfaces.h" -#if defined(__linux__) -const int SOCKET_ERROR = -1; -#endif #ifdef WIN32 #pragma warning(push) diff --git a/src/protocol.cpp b/src/protocol.cpp index 7a8b232..2d89c11 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -2,6 +2,7 @@ #include "error.h" #include "ptop_socket.h" #include "socket.h" +#include "platform.h" #if defined(WIN32) | defined(_WIN64) #include @@ -43,4 +44,61 @@ bool protocol::is_tcp() const { bool protocol::is_udp() const { return ai_protocol == IPPROTO_UDP; +} + +bool protocol::send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes) { + if (is_tcp()) + { + int result = send(handle, bytes.data(), (int)bytes.size(), 0); + if (result == SOCKET_ERROR) + return false; + return true; + } + else if (is_udp()) + { + int result = sendto(handle, bytes.data(), (int)bytes.size(), 0, &endpoint.name, endpoint.name_len); + if (result == SOCKET_ERROR) + return false; + return true; + } + return false; +} + +std::vector protocol::receive_bytes(SOCKET handle, raw_name_data expected_endpoint) +{ + if (is_tcp()) + { + std::vector data(500, (char)0, std::allocator()); + int result = ::recv(handle, data.data(), (int)data.size(), 0); + if (result == SOCKET_ERROR) + { + std::cout << "Receiving data failed" << std::endl; + return std::vector(); + } + data.resize(result); + return data; + } + if (is_udp()) + { + sockaddr addr; + socklen_t addr_len; + std::vector data(500, (char)0, std::allocator()); + int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &addr, &addr_len); + raw_name_data incoming{ addr, addr_len }; + + if (incoming != expected_endpoint) + { + auto readable = convert_to_readable(incoming); + auto message = "Receiving UDP data from an undesired endpoint (" + readable.ip_address + ":" + readable.port + ")"; + throw_new_exception(message, LINE_CONTEXT); + } + if (result == SOCKET_ERROR) + { + auto message = "Receiving (UDP) data failed: " + socket_error_to_string(result); + throw_new_exception(message, LINE_CONTEXT); + } + data.resize(result); + return data; + } + throw_new_exception("Invalid protocol", LINE_CONTEXT); } \ No newline at end of file diff --git a/src/protocol.h b/src/protocol.h index e2d7c70..b8ade7b 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -19,7 +19,10 @@ class protocol { inline int get_ai_socktype() const { return ai_socktype; } inline int get_ai_protocol() const { return ai_protocol; } inline int get_ai_flags() const { return ai_flags; } - + bool is_tcp() const; bool is_udp() const; + + bool send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes); + std::vector receive_bytes(SOCKET handle, raw_name_data expected_endpoint); }; \ No newline at end of file diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 47f7483..0695e1e 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -23,7 +23,9 @@ #endif #include +#include +using namespace std::chrono; PtopSocket::PtopSocket(protocol proto, std::string name) : _protocol(proto), _name(std::move(name)) { @@ -233,62 +235,10 @@ raw_name_data PtopSocket::get_name_raw() const bool PtopSocket::send_bytes(std::vector bytes) { - if (is_tcp()) - { - int result = send(_handle, bytes.data(), (int)bytes.size(), 0); - if (result == SOCKET_ERROR) - return false; - return true; - } - else if (is_udp()) - { - int result = sendto(_handle, bytes.data(), (int)bytes.size(), 0, &_endpoint.name, _endpoint.name_len); - if (result == SOCKET_ERROR) - return false; - return true; - } - else - { - throw_new_exception("Can not send data with an invalid protocol", LINE_CONTEXT); - } + return _protocol.send_bytes(_handle, _endpoint, bytes); } std::vector PtopSocket::recv_bytes() { - if (is_tcp()) - { - std::vector data(500, (char)0, std::allocator()); - int result = ::recv(_handle, data.data(), (int)data.size(), 0); - if (result == SOCKET_ERROR) - { - std::cout << "Receiving data failed" << std::endl; - return std::vector(); - } - data.resize(result); - return data; - } - if (is_udp()) - { - while (true) - { - sockaddr addr; - socklen_t addr_len; - std::vector data(500, (char)0, std::allocator()); - int result = ::recvfrom(_handle, data.data(), (int)data.size(), 0, &addr, &addr_len); - raw_name_data incoming{ addr, addr_len }; - - if (incoming != _endpoint) - { - auto readable = convert_to_readable(incoming); - std::cout << "Receiving UDP data from an undesired endpoint (" << readable << ")" << std::endl; - continue; - } - if (result == SOCKET_ERROR) - { - std::cerr << "Receiving (UDP) data failed: " << socket_error_to_string(result) << std::endl; - return std::vector(); - } - } - } - throw_new_exception("Invalid protocol", LINE_CONTEXT); + return _protocol.receive_bytes(_handle, _endpoint); } diff --git a/src/socket.h b/src/socket.h index c60f3a1..44d4ce2 100644 --- a/src/socket.h +++ b/src/socket.h @@ -6,4 +6,6 @@ #elif defined(__linux__) #include using SOCKET = int; +const int SOCKET_ERROR = -1; #endif + From f6c78d9e117971c97285e6fe306d21e5ef17c1f1 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Sun, 30 Jan 2022 17:00:42 +1300 Subject: [PATCH 29/44] fix: throw on udp listen --- src/linux_platform.cpp | 2 +- src/platform.cpp | 2 +- src/windows_platform.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 79a666a..9394f20 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -80,7 +80,7 @@ void Platform::update_endpoint_info() { try { - if (_socket.is_listen()) + if (_socket.is_tcp() && _socket.is_listen()) { std::cout << "[Socket] Not updating endpoint as this socket " << get_identifier_str() << " is a listen socket" << std::endl; return; diff --git a/src/platform.cpp b/src/platform.cpp index a7803dd..7374457 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -11,7 +11,7 @@ std::string Platform::get_identifier_str() { std::string name_str = "Unnamed"; if (_socket.get_name().size()) name_str = _socket.get_name(); - if (_socket.is_listen()) + if (_socket.is_tcp() && _socket.is_listen()) return std::string("(") + name_str + " is a listen on: " + _address + ":" + _port + ")"; if (_endpoint_assigned == false) diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index 9908bda..d35e585 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -106,7 +106,7 @@ void Platform::update_endpoint_info() { try { - if (_socket.is_listen()) + if (_socket.is_tcp() && _socket.is_listen()) { std::cout << "[Socket] Not updating endpoint as this socket " << get_identifier_str() << " is a listen socket" << std::endl; return; From 20eeca524b20e40f555699a30cdd2f29fc62a16b Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 17:27:48 +1300 Subject: [PATCH 30/44] fix: have udp socket set endpoint with connect --- src/ptop_socket.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 0695e1e..e0b149a 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -53,6 +53,8 @@ PtopSocket& PtopSocket::connect(sockaddr* addr, socklen_t len) } else if (_protocol.is_udp()) { + int n = ::connect(_handle, addr, len); + throw_if_socket_error(n, "Failed to connect " + get_last_error(), LINE_CONTEXT); _endpoint = raw_name_data(*addr, len); } return *this; From 5d161fed1433cb702ca455742a3ede2814778b16 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 19:41:15 +1300 Subject: [PATCH 31/44] chore: cleanup warnings with throw_new_exception --- src/error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.h b/src/error.h index 098ca22..b144343 100644 --- a/src/error.h +++ b/src/error.h @@ -6,7 +6,7 @@ #define LINE_CONTEXT (std::string("(") + __func__ + ", " + std::to_string(__LINE__) + ")") #endif -void throw_new_exception(std::string input, std::string line_context); +[[noreturn]] void throw_new_exception(std::string input, std::string line_context); void throw_with_context(const std::exception& e, std::string context); void print_exception(const std::exception& e, int level = 0); \ No newline at end of file From 81c04ab46c587ce529cfc8ddcf1365c9029a0a3e Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 19:41:48 +1300 Subject: [PATCH 32/44] chore: convenience to_string for readable_ip_info --- src/ip.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ip.h b/src/ip.h index 4253857..13bdd88 100644 --- a/src/ip.h +++ b/src/ip.h @@ -12,6 +12,7 @@ struct readable_ip_info std::string port; std::vector to_bytes() const; + inline std::string to_string() const { return "(" + ip_address + ":" + port + ")"; } }; inline std::ostream& operator<<(std::ostream& os, const readable_ip_info& ip_info) From 22f138831135a2629074fa10e6fea790923afecf Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 19:42:16 +1300 Subject: [PATCH 33/44] wip: udp using interface crap --- src/interfaces.h | 10 ++ src/platform.cpp | 251 ++++++++++++++++++++++++++++++++++++++++++++ src/platform.h | 67 ++++++++++++ src/ptop_socket.cpp | 33 +++++- src/ptop_socket.h | 16 +++ 5 files changed, 375 insertions(+), 2 deletions(-) diff --git a/src/interfaces.h b/src/interfaces.h index e820360..36732d2 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -5,6 +5,16 @@ #include "name_data.h" #include "message.h" +// BEGIN UDP CRAP + +struct udp_Message +{ + Message message; + raw_name_data from; +}; + +// END UDP CRAP + class ISocketWrapper { public: diff --git a/src/platform.cpp b/src/platform.cpp index 7374457..975af8c 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -1,5 +1,6 @@ #include "platform.h" #include "error.h" +#include "loop.h" #if defined(__linux__) #include @@ -48,3 +49,253 @@ Platform::~Platform() else std::cout << "Closing Dead socket" << std::endl; } + +void UDPAcceptedConnector::throw_if_no_listener() const +{ + if (!_listen) + throw_new_exception("Accepted UDP Connector has no valid listener", LINE_CONTEXT); +} + +UDPAcceptedConnector::~UDPAcceptedConnector() +{ + if (_listen) + _listen->remove_connector(_my_endpoint, this); +} + +Message UDPAcceptedConnector::receive_message() +{ + throw_if_no_listener(); + + return _listen->receive_message(_my_endpoint); +} + +bool UDPAcceptedConnector::has_message() +{ + throw_if_no_listener(); + + return _listen->has_message(_my_endpoint); +} + +bool UDPAcceptedConnector::send_data(const Message& message) +{ + throw_if_no_listener(); + + return _listen->send_data(message, _my_endpoint); +} + +readable_ip_info UDPAcceptedConnector::get_peer_data() const +{ + return convert_to_readable(_my_endpoint); +} + +raw_name_data UDPAcceptedConnector::get_peername_raw() const +{ + return _my_endpoint; +} + +raw_name_data UDPAcceptedConnector::get_myname_raw() const +{ + throw_if_no_listener(); + + return _listen->my_data(); +} + +readable_ip_info UDPAcceptedConnector::get_peername_readable() const +{ + return convert_to_readable(get_peername_raw()); +} + +readable_ip_info UDPAcceptedConnector::get_myname_readable() const +{ + return convert_to_readable(get_myname_raw()); +} + +std::string UDPAcceptedConnector::get_my_ip() const +{ + auto readable = get_myname_readable(); + + return readable.ip_address; +} + +std::string UDPAcceptedConnector::get_my_port() const +{ + auto readable = get_myname_readable(); + + return readable.port; +} + +std::string UDPAcceptedConnector::get_endpoint_ip() const +{ + auto readable = get_peername_readable(); + + return readable.ip_address; +} + +std::string UDPAcceptedConnector::get_endpoint_port() const +{ + auto readable = get_peername_readable(); + + return readable.port; +} + +std::string UDPAcceptedConnector::get_identifier_str() +{ + return "(UDPAcceptedConnector on pub: " + get_peername_readable().to_string() + ")"; +} + +const std::string& UDPAcceptedConnector::get_name() const +{ + throw_if_no_listener(); + + return "UDPAccepterConnector of: " + _listen->get_name(); +} + +void UDPAcceptedConnector::set_name(std::string name) +{ +} + +void process_into_messages(std::queue& message_queue, const std::vector& data) +{ + auto& recv_data = data; + if (recv_data.size() > 0) + { + std::cout << "Received (UDP) " << recv_data.size() << " bytes" << std::endl; + + int data_read = 0; + + while ((recv_data.size() - data_read) > 0) + { + MESSAGE_TYPE type; + MESSAGE_LENGTH_T length; + std::vector data; + + if (!try_read_data(recv_data.data(), data_read, recv_data.size(), type)) + { + return; + } + if (!try_read_data(recv_data.data(), data_read, recv_data.size(), length)) + { + return; + } + if (data_read + length > recv_data.size()) + { + return; + } + data = std::vector(recv_data.data() + data_read, recv_data.data() + data_read + length); + data_read += length; + auto new_message = Message{ type, length, std::move(data) }; + message_queue.push(new_message); + } + } +} + +void UDPListener::process_data() +{ + while (_socket.has_message()) + { + auto received = _socket.recv_udp_bytes(); + + if (_messages.find(received.endpoint) == _messages.end()) + { + _messages[received.endpoint] = std::queue(); + process_into_messages(_messages[received.endpoint], received.bytes); + } + + if (_connectors.find(received.endpoint) == _connectors.end()) + { + _new_connections.push_back(received.endpoint); + } + } +} + +void UDPListener::remove_connector(raw_name_data endpoint, UDPAcceptedConnector* conn) +{ + if (_connectors.find(endpoint) != _connectors.end()) + { + if (_connectors[endpoint] != conn) + { + std::cerr << "Incorrect value for key given from destroying UDPAcceptedConnector" << std::endl; + return; + } + _connectors.erase(endpoint); + } +} + +bool UDPListener::send_data(const Message& message, raw_name_data to) +{ + return _socket.send_udp_bytes(udp_bytes{ message.to_bytes(), to }); +} + +bool UDPListener::has_message(raw_name_data from) +{ + process_data(); + + if (_messages.find(from) == _messages.end()) + return false; + return _messages[from].size(); +} + +Message UDPListener::receive_message(raw_name_data from) +{ + process_data(); + + if (_messages.find(from) == _messages.end()) + throw_new_exception("Failure receiving message for specific UDP endpoint: " + convert_to_readable(from).to_string() + " could not find any messages for endpoint", LINE_CONTEXT); + + auto& q = _messages[from]; + auto tmp = q.front(); + q.pop(); + return tmp; +} + +raw_name_data UDPListener::my_data() +{ + return _socket.get_name_raw(); +} + +PtopSocket construct_udp_listener(std::string port, protocol proto, std::string name) +{ + if (!proto.is_udp()) + throw_new_exception("UDP Listener must only be used with UDP", LINE_CONTEXT); + + auto listen_socket = PtopSocket(proto, name); + + struct sockaddr_in serv_addr, cli_addr; + + int portno = atoi(port.c_str()); +#ifdef WIN32 + ZeroMemory(&serv_addr, sizeof(serv_addr)); +#elif __linux__ + bzero((char*)&serv_addr, sizeof(serv_addr)); +#endif + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(portno); + + std::cout << "[UDPListen] Binding UDP Listener (" << name << ") to port " << port << std::endl; + listen_socket.bind_socket(raw_name_data{ *(sockaddr*)&serv_addr, sizeof(serv_addr) }); + + return listen_socket; +} + +UDPListener::UDPListener(std::string port, protocol proto, std::string name) : Platform(construct_udp_listener(port, proto, name)) +{ +} + +bool UDPListener::has_connection() +{ + return _new_connections.size(); +} + +std::unique_ptr UDPListener::accept_connection() +{ + if (!has_connection()) + return nullptr; + + auto new_conn_endpoint = _new_connections.back(); + _new_connections.pop_back(); + + auto new_conn = std::unique_ptr(new UDPAcceptedConnector(this, new_conn_endpoint)); + + return new_conn; +} diff --git a/src/platform.h b/src/platform.h index 358e5e3..f53ae41 100644 --- a/src/platform.h +++ b/src/platform.h @@ -2,6 +2,7 @@ #include #include +#include #include "ptop_socket.h" #include "interfaces.h" @@ -91,6 +92,72 @@ class NonBlockingConnector : public Platform, public virtual INonBlockingConnect ConnectionStatus has_connected() override; }; +class UDPConnector : public virtual IDataSocketWrapper +{ + +}; + +class UDPListener; + +class UDPAcceptedConnector : public virtual IDataSocketWrapper +{ + void throw_if_no_listener() const; + + UDPListener* _listen; + raw_name_data _my_endpoint; + + friend class UDPListener; + + UDPAcceptedConnector(UDPListener* listen, raw_name_data endpoint); + +public: + ~UDPAcceptedConnector(); + + Message receive_message() override; + bool has_message() override; + + bool send_data(const Message& message) override; + + // Inherited via IDataSocketWrapper + virtual readable_ip_info get_peer_data() const override; + virtual raw_name_data get_peername_raw() const override; + virtual raw_name_data get_myname_raw() const override; + virtual readable_ip_info get_peername_readable() const override; + virtual readable_ip_info get_myname_readable() const override; + virtual std::string get_my_ip() const override; + virtual std::string get_my_port() const override; + virtual std::string get_endpoint_ip() const override; + virtual std::string get_endpoint_port() const override; + virtual std::string get_identifier_str() override; + virtual const std::string& get_name() const override; + virtual void set_name(std::string name) override; +}; + +class UDPListener : public Platform, public virtual IListenSocketWrapper +{ + std::unordered_map> _messages; + std::unordered_map _connectors; + std::vector _new_connections; + + friend class UDPAcceptedConnector; + + void process_data(); + + void remove_connector(raw_name_data endpoint, UDPAcceptedConnector* conn); + + bool send_data(const Message& message, raw_name_data to); + bool has_message(raw_name_data from); + Message receive_message(raw_name_data from); + + raw_name_data my_data(); +public: + UDPListener(std::string port, protocol proto, std::string name); + + inline void listen() override {} + bool has_connection() override; + std::unique_ptr accept_connection() override; +}; + #ifdef WIN32 #pragma warning(pop) #endif \ No newline at end of file diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index e0b149a..1352b71 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -100,14 +100,19 @@ bool PtopSocket::try_connect(sockaddr* addr, socklen_t len) void PtopSocket::listen(int max_conns) { - auto n = ::listen(_handle, max_conns); - throw_if_socket_error(n, "Failed to listen on socket. " + get_last_error(), LINE_CONTEXT); + if (is_tcp()) + { + auto n = ::listen(_handle, max_conns); + throw_if_socket_error(n, "Failed to listen on socket. " + get_last_error(), LINE_CONTEXT); + } } bool PtopSocket::has_connection() const { try { + if (is_udp()) + return false; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; @@ -244,3 +249,27 @@ std::vector PtopSocket::recv_bytes() { return _protocol.receive_bytes(_handle, _endpoint); } + + +bool PtopSocket::send_udp_bytes(udp_bytes bytes) +{ + int n = sendto(_handle, bytes.bytes.data(), bytes.bytes.size(), 0, &bytes.endpoint.name, bytes.endpoint.name_len); + throw_if_socket_error(n, "Failed to send UDP Bytes to " + convert_to_readable(bytes.endpoint).to_string() + " with: " + get_last_error(), LINE_CONTEXT); + + return true; +} + +// BEGIN UDP CRAP +udp_bytes PtopSocket::recv_udp_bytes() +{ + udp_bytes bytes; + bytes.bytes = std::vector(500, (char)0, std::allocator()); + + int n = recvfrom(_handle, bytes.bytes.data(), (int)bytes.bytes.size(), 0, &bytes.endpoint.name, &bytes.endpoint.name_len); + + throw_if_socket_error(n, "Failed to receive UDP bytes (" + _name + ") with: " + get_last_error(), LINE_CONTEXT); + + bytes.bytes.resize(n); + return bytes; +} +// END UDP CRAP \ No newline at end of file diff --git a/src/ptop_socket.h b/src/ptop_socket.h index 0a7c930..0068a85 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -4,6 +4,7 @@ #include "name_data.h" #include "protocol.h" #include "error.h" +#include "message.h" #include @@ -20,6 +21,16 @@ enum class select_for EXCEPT }; +// UDP CRAP + +struct udp_bytes +{ + std::vector bytes; + raw_name_data endpoint; +}; + +// END UDP CRAP + class PtopSocket { private: @@ -115,4 +126,9 @@ class PtopSocket bool send_bytes(std::vector bytes); std::vector recv_bytes(); + + // BEGIN UDP CRAP + bool send_udp_bytes(udp_bytes bytes); + udp_bytes recv_udp_bytes(); + // END UDP CRAP }; \ No newline at end of file From b561cfcae6e39cf12f7671072325bb1ef83884aa Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 21:55:15 +1300 Subject: [PATCH 34/44] fix: udp data socket falsely rejecting data --- src/name_data.h | 1 + src/platform.cpp | 19 ++++++++++++++----- src/platform.h | 30 +++++++++++++++++++++++++++--- src/protocol.cpp | 2 +- src/ptop_socket.cpp | 1 + src/ptop_socket.h | 2 +- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/name_data.h b/src/name_data.h index 4294566..8a6696c 100644 --- a/src/name_data.h +++ b/src/name_data.h @@ -23,6 +23,7 @@ struct raw_name_data socklen_t name_len; sockaddr_in& ipv4_addr() { return *(sockaddr_in*)&name; } + const sockaddr_in& ipv4_addr() const { return *(sockaddr_in*)&name; } inline bool operator==(const raw_name_data& other) const { diff --git a/src/platform.cpp b/src/platform.cpp index 975af8c..bbe5ff2 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -24,7 +24,7 @@ std::string Platform::get_identifier_str() { return std::string("(") + name_str + " pub: " + _address + ":" + _port + ")"; } -readable_ip_info convert_to_readable(raw_name_data data) +readable_ip_info convert_to_readable(const raw_name_data& data) { std::vector buf{ 50, '0', std::allocator() }; const char* str = inet_ntop(AF_INET, &data.ipv4_addr().sin_addr, buf.data(), buf.size()); @@ -56,6 +56,10 @@ void UDPAcceptedConnector::throw_if_no_listener() const throw_new_exception("Accepted UDP Connector has no valid listener", LINE_CONTEXT); } +UDPAcceptedConnector::UDPAcceptedConnector(UDPListener* listen, raw_name_data endpoint) : _listen(listen), _my_endpoint(endpoint) +{ +} + UDPAcceptedConnector::~UDPAcceptedConnector() { if (_listen) @@ -203,7 +207,8 @@ void UDPListener::process_data() if (_connectors.find(received.endpoint) == _connectors.end()) { - _new_connections.push_back(received.endpoint); + if (std::find(_new_connections.begin(), _new_connections.end(), received.endpoint) == _new_connections.end()) + _new_connections.push_back(received.endpoint); } } } @@ -260,7 +265,7 @@ PtopSocket construct_udp_listener(std::string port, protocol proto, std::string auto listen_socket = PtopSocket(proto, name); - struct sockaddr_in serv_addr, cli_addr; + struct sockaddr_in serv_addr; int portno = atoi(port.c_str()); #ifdef WIN32 @@ -284,6 +289,8 @@ UDPListener::UDPListener(std::string port, protocol proto, std::string name) : P bool UDPListener::has_connection() { + process_data(); + return _new_connections.size(); } @@ -292,10 +299,12 @@ std::unique_ptr UDPListener::accept_connection() if (!has_connection()) return nullptr; - auto new_conn_endpoint = _new_connections.back(); - _new_connections.pop_back(); + const auto& new_conn_endpoint = _new_connections.back(); auto new_conn = std::unique_ptr(new UDPAcceptedConnector(this, new_conn_endpoint)); + _connectors[new_conn_endpoint] = new_conn.get(); + _new_connections.pop_back(); + return new_conn; } diff --git a/src/platform.h b/src/platform.h index f53ae41..222df37 100644 --- a/src/platform.h +++ b/src/platform.h @@ -13,7 +13,7 @@ #pragma warning(disable : 4250) #endif -readable_ip_info convert_to_readable(raw_name_data); +readable_ip_info convert_to_readable(const raw_name_data&); class Platform : public virtual ISocketWrapper { protected: @@ -92,10 +92,34 @@ class NonBlockingConnector : public Platform, public virtual INonBlockingConnect ConnectionStatus has_connected() override; }; -class UDPConnector : public virtual IDataSocketWrapper +// Taken from https://stackoverflow.com/a/19195373 +template +inline void hash_combine(std::size_t& s, const T& v) { + std::hash h; + s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); +} + +namespace std +{ + template<> + struct hash + { + std::size_t operator()(const raw_name_data& name_data) const + { + using std::size_t; + using std::hash; + using std::string; + + auto readable = convert_to_readable(name_data); + + size_t h = hash()(readable.ip_address); + hash_combine(h, readable.port); + return h; + } + }; +} -}; class UDPListener; diff --git a/src/protocol.cpp b/src/protocol.cpp index 2d89c11..50b8688 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -81,7 +81,7 @@ std::vector protocol::receive_bytes(SOCKET handle, raw_name_data expected_ if (is_udp()) { sockaddr addr; - socklen_t addr_len; + socklen_t addr_len = sizeof(sockaddr_in); std::vector data(500, (char)0, std::allocator()); int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &addr, &addr_len); raw_name_data incoming{ addr, addr_len }; diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 1352b71..1dabab6 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -263,6 +263,7 @@ bool PtopSocket::send_udp_bytes(udp_bytes bytes) udp_bytes PtopSocket::recv_udp_bytes() { udp_bytes bytes; + bytes.endpoint.name_len = sizeof(bytes.endpoint); bytes.bytes = std::vector(500, (char)0, std::allocator()); int n = recvfrom(_handle, bytes.bytes.data(), (int)bytes.bytes.size(), 0, &bytes.endpoint.name, &bytes.endpoint.name_len); diff --git a/src/ptop_socket.h b/src/ptop_socket.h index 0068a85..fb72c82 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -45,7 +45,7 @@ class PtopSocket explicit PtopSocket(protocol proto, std::string name = ""); - PtopSocket(PtopSocket&& other) : _handle(other._handle), _protocol(other._protocol), _name(std::move(other._name)) { + PtopSocket(PtopSocket&& other) : _handle(other._handle), _protocol(other._protocol), _endpoint(other._endpoint), _name(std::move(other._name)) { other._handle = REALLY_INVALID_SOCKET; }; ~PtopSocket(); From 11b19e504895eb0d889cebba75bba4b2e0c03a0b Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 21:55:33 +1300 Subject: [PATCH 35/44] fix: udp server --- src/server.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index ffb77f6..ab80ea4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -18,7 +18,10 @@ server_init_kit::server_init_kit(protocol ip_proto) : proto(ip_proto) { clientB = nullptr; cA = nullptr; cB = nullptr; - server_socket = std::make_unique(ServerListenPort, ip_proto, "Server-Listener"); + if (ip_proto.is_udp()) + server_socket = std::make_unique(ServerListenPort, ip_proto, "Server-Listener"); + else + server_socket = std::make_unique(ServerListenPort, ip_proto, "Server-Listener"); server_socket->listen(); recv_data = std::vector(); //dont need to initialize structs. it will default its params by itself From 971d1ed8a1a74e3205b2720bcfb12761a9c06e5b Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 21:59:48 +1300 Subject: [PATCH 36/44] fix: yeah.... fixed the linux build --- src/platform.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform.cpp b/src/platform.cpp index bbe5ff2..d56f428 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -7,6 +7,7 @@ #endif #include +#include std::string Platform::get_identifier_str() { std::string name_str = "Unnamed"; From a10f0efb6dedc664d485eb626c16756f2f5949e9 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Sun, 30 Jan 2022 22:29:35 +1300 Subject: [PATCH 37/44] fix: 2 minor bugs --- src/platform.cpp | 2 +- src/protocol.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform.cpp b/src/platform.cpp index d56f428..5a9358b 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -22,7 +22,7 @@ std::string Platform::get_identifier_str() { if (_endpoint_assigned == false) return std::string("(") + name_str + " priv: " + _address + ":" + _port + ", pub : N / A)"; - return std::string("(") + name_str + " pub: " + _address + ":" + _port + ")"; + return std::string("(") + name_str + " pub: " + _endpoint_address + ":" + _endpoint_port + ")"; } readable_ip_info convert_to_readable(const raw_name_data& data) diff --git a/src/protocol.cpp b/src/protocol.cpp index 50b8688..24319fa 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -94,7 +94,7 @@ std::vector protocol::receive_bytes(SOCKET handle, raw_name_data expected_ } if (result == SOCKET_ERROR) { - auto message = "Receiving (UDP) data failed: " + socket_error_to_string(result); + auto message = "Receiving (UDP) data failed: " + get_last_error(); throw_new_exception(message, LINE_CONTEXT); } data.resize(result); From fb681316c7d3fcf0ba08ead8b5fc034b2e60b7a8 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Mon, 31 Jan 2022 12:46:44 +1300 Subject: [PATCH 38/44] refactor: capitalize type name --- src/client.cpp | 4 ++-- src/client.h | 6 +++--- src/clientmain.cpp | 2 +- src/linux_platform.cpp | 16 ++++++++-------- src/platform.cpp | 4 ++-- src/platform.h | 10 +++++----- src/protocol.cpp | 10 +++++----- src/protocol.h | 4 ++-- src/ptop_socket.cpp | 2 +- src/ptop_socket.h | 10 +++++----- src/server.cpp | 6 +++--- src/server.h | 4 ++-- src/windows_platform.cpp | 16 ++++++++-------- 13 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 00788bf..ef1f22d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -11,7 +11,7 @@ using namespace std::chrono; -client_init_kit::client_init_kit(std::string server_address_pair, ::protocol chosen_protocol) : protocol(chosen_protocol) { +client_init_kit::client_init_kit(std::string server_address_pair, ::Protocol chosen_protocol) : protocol(chosen_protocol) { _server_socket = std::make_unique(server_address_pair, ServerListenPort, protocol, "Server-Conn"); // Indicate to server we're ready for p2p server_last_send = std::chrono::system_clock::now(); @@ -361,7 +361,7 @@ bool do_user_input(thread_queue& message_queue, std::unique_lock& get_server_socket(); diff --git a/src/clientmain.cpp b/src/clientmain.cpp index 1400436..e96468d 100644 --- a/src/clientmain.cpp +++ b/src/clientmain.cpp @@ -60,7 +60,7 @@ int main(int argc, char** argv) { std::string possible_protocol{}; std::cin >> possible_protocol; - protocol validated{ possible_protocol }; + Protocol validated{ possible_protocol }; client_loop(raw_ip, validated); } diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 9394f20..46333a7 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -143,7 +143,7 @@ raw_name_data Platform::get_myname_raw() const return _socket.get_name_raw(); } -PtopSocket listen_construct(std::string port, protocol input_proto, std::string name) +PtopSocket listen_construct(std::string port, Protocol input_proto, std::string name) { std::cout << "[Listen] Creating new Socket on port (with localhost, named: " << name << "): " << port << std::endl; auto listen_socket = PtopSocket(input_proto, name); @@ -168,7 +168,7 @@ PtopSocket listen_construct(std::string port, protocol input_proto, std::string return listen_socket; } -PlatformListener::PlatformListener(std::string port, protocol input_proto, std::string name) : Platform(listen_construct(port, input_proto, name)) +PlatformListener::PlatformListener(std::string port, Protocol input_proto, std::string name) : Platform(listen_construct(port, input_proto, name)) { } @@ -286,7 +286,7 @@ PlatformAnalyser::PlatformAnalyser(PtopSocket&& socket) : Platform(std::move(soc throw std::runtime_error("[Data] Invalid socket in Copy Constructor"); } -PtopSocket data_connect_construct(std::string peer_address, std::string peer_port, protocol ip_proto, std::string name) +PtopSocket data_connect_construct(std::string peer_address, std::string peer_port, Protocol ip_proto, std::string name) { std::cout << "[Data] Creating a Linux Data Socket (named " << name << ") connecting to : " << peer_address << ":" << peer_port << std::endl; @@ -311,7 +311,7 @@ PtopSocket data_connect_construct(std::string peer_address, std::string peer_por return conn_socket; } -PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol proto, std::string name) +PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, Protocol proto, std::string name) : Platform(data_connect_construct(peer_address, peer_port, proto, name)) { try_update_endpoint_info(); @@ -348,7 +348,7 @@ bool PlatformAnalyser::send_data(const Message& message) return false; } -PtopSocket reuse_listen_construct(raw_name_data data, protocol proto, std::string name) +PtopSocket reuse_listen_construct(raw_name_data data, Protocol proto, std::string name) { auto readable = convert_to_readable(data); std::cout << "[ListenReuseNoB] Creating Reusable Listen Socket '" << name << "' on: " << readable.ip_address << ":" << readable.port << std::endl; @@ -366,7 +366,7 @@ PtopSocket reuse_listen_construct(raw_name_data data, protocol proto, std::strin return listen_socket; } -NonBlockingListener::NonBlockingListener(raw_name_data data, protocol proto, std::string name) +NonBlockingListener::NonBlockingListener(raw_name_data data, Protocol proto, std::string name) : Platform(reuse_listen_construct(data, proto, name)) { @@ -391,7 +391,7 @@ std::unique_ptr NonBlockingListener::accept_connection() return std::make_unique(std::move(new_sock)); } -PtopSocket reuse_connection_construct(raw_name_data data, protocol proto, std::string name) +PtopSocket reuse_connection_construct(raw_name_data data, Protocol proto, std::string name) { auto readable = convert_to_readable(data); std::cout << "[DataReuseNoB] Creating Connection socket '" << name << "' bound to : " << readable.ip_address << ":" << readable.port << std::endl; @@ -409,7 +409,7 @@ PtopSocket reuse_connection_construct(raw_name_data data, protocol proto, std::s return conn_socket; } -NonBlockingConnector::NonBlockingConnector(raw_name_data data, std::string ip_address, std::string port, protocol proto, std::string name) +NonBlockingConnector::NonBlockingConnector(raw_name_data data, std::string ip_address, std::string port, Protocol proto, std::string name) : Platform(reuse_connection_construct(data, proto, name)) { // if tcp? diff --git a/src/platform.cpp b/src/platform.cpp index 5a9358b..aacdc7f 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -259,7 +259,7 @@ raw_name_data UDPListener::my_data() return _socket.get_name_raw(); } -PtopSocket construct_udp_listener(std::string port, protocol proto, std::string name) +PtopSocket construct_udp_listener(std::string port, Protocol proto, std::string name) { if (!proto.is_udp()) throw_new_exception("UDP Listener must only be used with UDP", LINE_CONTEXT); @@ -284,7 +284,7 @@ PtopSocket construct_udp_listener(std::string port, protocol proto, std::string return listen_socket; } -UDPListener::UDPListener(std::string port, protocol proto, std::string name) : Platform(construct_udp_listener(port, proto, name)) +UDPListener::UDPListener(std::string port, Protocol proto, std::string name) : Platform(construct_udp_listener(port, proto, name)) { } diff --git a/src/platform.h b/src/platform.h index 222df37..23ceb29 100644 --- a/src/platform.h +++ b/src/platform.h @@ -54,7 +54,7 @@ class Platform : public virtual ISocketWrapper { class PlatformListener : public Platform, public virtual IListenSocketWrapper { public: - PlatformListener(std::string port, protocol input_protocol, std::string name); + PlatformListener(std::string port, Protocol input_protocol, std::string name); void listen() override; bool has_connection() override; std::unique_ptr accept_connection() override; @@ -67,7 +67,7 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { public: PlatformAnalyser(std::unique_ptr&& old); PlatformAnalyser(PtopSocket&& socket); - PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name); + PlatformAnalyser(std::string peer_address, std::string peer_port, Protocol input_protocol, std::string name); Message receive_message() override; bool has_message() override; @@ -77,7 +77,7 @@ class PlatformAnalyser : public Platform, public virtual IDataSocketWrapper { class NonBlockingListener : public Platform, public virtual INonBlockingListener { public: - NonBlockingListener(raw_name_data data, protocol input_protocol, std::string name); + NonBlockingListener(raw_name_data data, Protocol input_protocol, std::string name); void listen() override; bool has_connection() override; @@ -86,7 +86,7 @@ class NonBlockingListener : public Platform, public virtual INonBlockingListener class NonBlockingConnector : public Platform, public virtual INonBlockingConnector { public: - NonBlockingConnector(raw_name_data private_binding, std::string ip_address, std::string port, protocol input_protocol, std::string); + NonBlockingConnector(raw_name_data private_binding, std::string ip_address, std::string port, Protocol input_protocol, std::string); void connect(std::string ip_address, std::string port) override; // Called in constructor, can be called again if it fails ConnectionStatus has_connected() override; @@ -175,7 +175,7 @@ class UDPListener : public Platform, public virtual IListenSocketWrapper raw_name_data my_data(); public: - UDPListener(std::string port, protocol proto, std::string name); + UDPListener(std::string port, Protocol proto, std::string name); inline void listen() override {} bool has_connection() override; diff --git a/src/protocol.cpp b/src/protocol.cpp index 24319fa..5ae2086 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -18,7 +18,7 @@ using namespace std; -protocol::protocol(string possible_protocol) { +Protocol::Protocol(string possible_protocol) { transform(possible_protocol.begin(), possible_protocol.end(), possible_protocol.begin(), ::tolower); if (possible_protocol == "tcp") { @@ -38,15 +38,15 @@ protocol::protocol(string possible_protocol) { } } -bool protocol::is_tcp() const { +bool Protocol::is_tcp() const { return ai_protocol == IPPROTO_TCP; } -bool protocol::is_udp() const { +bool Protocol::is_udp() const { return ai_protocol == IPPROTO_UDP; } -bool protocol::send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes) { +bool Protocol::send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes) { if (is_tcp()) { int result = send(handle, bytes.data(), (int)bytes.size(), 0); @@ -64,7 +64,7 @@ bool protocol::send_bytes(SOCKET handle, raw_name_data endpoint, std::vector protocol::receive_bytes(SOCKET handle, raw_name_data expected_endpoint) +std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data expected_endpoint) { if (is_tcp()) { diff --git a/src/protocol.h b/src/protocol.h index b8ade7b..57731c1 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -4,9 +4,9 @@ #include #include "name_data.h" -class protocol { +class Protocol { public: - protocol(std::string possible_protocol); + Protocol(std::string possible_protocol); private: int ai_family; diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 1dabab6..ecefbc9 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -27,7 +27,7 @@ using namespace std::chrono; -PtopSocket::PtopSocket(protocol proto, std::string name) : _protocol(proto), _name(std::move(name)) +PtopSocket::PtopSocket(Protocol proto, std::string name) : _protocol(proto), _name(std::move(name)) { int domain = _protocol.get_ai_family(); int type = _protocol.get_ai_socktype(); diff --git a/src/ptop_socket.h b/src/ptop_socket.h index fb72c82..dbfb7c1 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -35,15 +35,15 @@ class PtopSocket { private: SOCKET _handle; - protocol _protocol; + Protocol _protocol; raw_name_data _endpoint; std::string _name; - PtopSocket(SOCKET handle, protocol proto, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(), _name(name) {} - PtopSocket(SOCKET handle, protocol proto, raw_name_data endpoint, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(endpoint), _name(name) {} + PtopSocket(SOCKET handle, Protocol proto, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(), _name(name) {} + PtopSocket(SOCKET handle, Protocol proto, raw_name_data endpoint, std::string name = "") : _handle(handle), _protocol(proto), _endpoint(endpoint), _name(name) {} public: - explicit PtopSocket(protocol proto, std::string name = ""); + explicit PtopSocket(Protocol proto, std::string name = ""); PtopSocket(PtopSocket&& other) : _handle(other._handle), _protocol(other._protocol), _endpoint(other._endpoint), _name(std::move(other._name)) { other._handle = REALLY_INVALID_SOCKET; @@ -122,7 +122,7 @@ class PtopSocket inline bool is_listen() const { return get_socket_option(SO_ACCEPTCONN); } inline SOCKET get_handle() const { return _handle; } - inline const protocol& get_protocol() const { return _protocol; } + inline const Protocol& get_protocol() const { return _protocol; } bool send_bytes(std::vector bytes); std::vector recv_bytes(); diff --git a/src/server.cpp b/src/server.cpp index ab80ea4..b5d12f9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -13,7 +13,7 @@ using namespace std::chrono; -server_init_kit::server_init_kit(protocol ip_proto) : proto(ip_proto) { +server_init_kit::server_init_kit(Protocol ip_proto) : proto(ip_proto) { clientA = nullptr; clientB = nullptr; cA = nullptr; @@ -224,8 +224,8 @@ void server_loop() std::thread user_input_thread{ input_thread_func, std::ref(user_input_queue) }; user_input_thread.detach(); - server_init_kit init_tcp{ protocol{"tcp"} }; - server_init_kit init_udp{ protocol{"udp"} }; + server_init_kit init_tcp{ Protocol{"tcp"} }; + server_init_kit init_udp{ Protocol{"udp"} }; std::cout << "Server is ready..." << std::endl; while (true) diff --git a/src/server.h b/src/server.h index b95c695..2ad80d5 100644 --- a/src/server.h +++ b/src/server.h @@ -35,9 +35,9 @@ class server_init_kit { std::vector recv_data; EXECUTION_STATUS status; - protocol proto; + Protocol proto; - server_init_kit(protocol proto); + server_init_kit(Protocol proto); server_init_kit(server_init_kit&& other); server_init_kit& operator=(server_init_kit&& other); diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index d35e585..b87825c 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -190,7 +190,7 @@ raw_name_data Platform::get_myname_raw() const return raw_data; } -PtopSocket construct_windowslistensocket(std::string port, protocol input_protocol, std::string name) { +PtopSocket construct_windowslistensocket(std::string port, Protocol input_protocol, std::string name) { try { std::cout << "[Listen] Creating new Socket on port (with localhost, named: " << name << "): " << port << std::endl; @@ -227,7 +227,7 @@ PtopSocket construct_windowslistensocket(std::string port, protocol input_protoc } } -PlatformListener::PlatformListener(std::string port, protocol input_protocol, std::string name) : Platform(construct_windowslistensocket(port, input_protocol, name)) +PlatformListener::PlatformListener(std::string port, Protocol input_protocol, std::string name) : Platform(construct_windowslistensocket(port, input_protocol, name)) { } @@ -248,7 +248,7 @@ std::unique_ptr PlatformListener::accept_connection() { return std::make_unique(std::move(tmp)); } -PtopSocket construct_windows_data_socket(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name) { +PtopSocket construct_windows_data_socket(std::string peer_address, std::string peer_port, Protocol input_protocol, std::string name) { std::cout << "[Data] Creating a Windows Data Socket (" << name << ") connecting to : " << peer_address << " : " << peer_port << std::endl; struct addrinfo* result = NULL, *ptr = NULL, @@ -274,7 +274,7 @@ PtopSocket construct_windows_data_socket(std::string peer_address, std::string p return conn_socket; } -PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, protocol input_protocol, std::string name) : Platform(construct_windows_data_socket(peer_address, peer_port, input_protocol, name)) +PlatformAnalyser::PlatformAnalyser(std::string peer_address, std::string peer_port, Protocol input_protocol, std::string name) : Platform(construct_windows_data_socket(peer_address, peer_port, input_protocol, name)) { try { @@ -406,7 +406,7 @@ bool PlatformAnalyser::has_message() return _socket.has_message(); } -PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto, std::string name) +PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, Protocol proto, std::string name) { try { @@ -430,7 +430,7 @@ PtopSocket windows_reuse_nb_listen_construct(raw_name_data data, protocol proto, } } -NonBlockingListener::NonBlockingListener(raw_name_data data, protocol input_protocol, std::string name) +NonBlockingListener::NonBlockingListener(raw_name_data data, Protocol input_protocol, std::string name) : Platform( windows_reuse_nb_listen_construct(data, input_protocol, name) ) @@ -455,7 +455,7 @@ std::unique_ptr NonBlockingListener::accept_connection() return std::make_unique(std::move(new_sock)); } -PtopSocket windows_reuse_nb_construct(raw_name_data data, protocol proto, std::string name) +PtopSocket windows_reuse_nb_construct(raw_name_data data, Protocol proto, std::string name) { try { auto readable = convert_to_readable(data); @@ -479,7 +479,7 @@ PtopSocket windows_reuse_nb_construct(raw_name_data data, protocol proto, std::s } NonBlockingConnector::NonBlockingConnector( - raw_name_data data, std::string ip_address, std::string port, protocol input_protocol, std::string name) + raw_name_data data, std::string ip_address, std::string port, Protocol input_protocol, std::string name) : Platform( windows_reuse_nb_construct(data, input_protocol, name) ) From d2fd8e56a3f5c0725d4a7a072093e67188d8709f Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Mon, 31 Jan 2022 13:49:37 +1300 Subject: [PATCH 39/44] refactor: move send receive to protocol class --- src/linux_platform.cpp | 2 +- src/platform.cpp | 2 +- src/protocol.cpp | 24 +++++++++++++++++++++++- src/protocol.h | 1 + src/ptop_socket.cpp | 37 ++++++++----------------------------- src/ptop_socket.h | 8 +++----- src/windows_platform.cpp | 2 +- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index 46333a7..2c762a4 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -218,7 +218,7 @@ PtopSocket steal_construct(std::unique_ptr&& old) void PlatformAnalyser::process_socket_data() { std::cout << "[Data] Trying to receive new data from Socket: " << get_identifier_str() << std::endl; - std::vector recv_data = _socket.recv_bytes(); + std::vector recv_data = _socket.receive_bytes(); if (recv_data.size() > 0) { std::cout << "Received " << recv_data.size() << " bytes" << std::endl; diff --git a/src/platform.cpp b/src/platform.cpp index aacdc7f..3141247 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -198,7 +198,7 @@ void UDPListener::process_data() { while (_socket.has_message()) { - auto received = _socket.recv_udp_bytes(); + auto received = _socket.receive_udp_bytes(); if (_messages.find(received.endpoint) == _messages.end()) { diff --git a/src/protocol.cpp b/src/protocol.cpp index 5ae2086..7c63436 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -101,4 +101,26 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data expected_ return data; } throw_new_exception("Invalid protocol", LINE_CONTEXT); -} \ No newline at end of file +} + +bool Protocol::has_died(SOCKET handle, bool has_message) { + if (is_tcp()) + { + if (has_message) + { + std::vector recv_data{ 100, '0', std::allocator() }; + int n = recv(handle, recv_data.data(), (int)recv_data.size(), MSG_PEEK); + if (n == SOCKET_ERROR) + { + std::cerr << "[Data] Failed to peek data from linux socket (trying to determine if closed): " << get_last_error() << std::endl; + return true; + } + return n == 0; + } + return false; + } + if (is_udp()) + return false; + throw_new_exception("Invalid protocol", LINE_CONTEXT); + return true; +} diff --git a/src/protocol.h b/src/protocol.h index 57731c1..677e6cd 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -25,4 +25,5 @@ class Protocol { bool send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes); std::vector receive_bytes(SOCKET handle, raw_name_data expected_endpoint); + bool has_died(SOCKET handle, bool has_message); }; \ No newline at end of file diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index ecefbc9..e2ae239 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -191,27 +191,9 @@ bool PtopSocket::has_message() const return select_for(select_for::READ); } -bool PtopSocket::has_died() const +bool PtopSocket::has_died() { - if (is_tcp()) - { - if (has_message()) - { - std::vector recv_data{ 100, '0', std::allocator() }; - int n = recv(_handle, recv_data.data(), (int)recv_data.size(), MSG_PEEK); - if (n == SOCKET_ERROR) - { - std::cerr << "[Data] Failed to peek data from linux socket (trying to determine if closed): " << get_last_error() << std::endl; - return true; - } - return n == 0; - } - return false; - } - if (is_udp()) - return false; - throw_new_exception("Invalid protocol", LINE_CONTEXT); - return true; + return _protocol.has_died(_handle, has_message()); } raw_name_data PtopSocket::get_peer_raw() const @@ -245,22 +227,20 @@ bool PtopSocket::send_bytes(std::vector bytes) return _protocol.send_bytes(_handle, _endpoint, bytes); } -std::vector PtopSocket::recv_bytes() +std::vector PtopSocket::receive_bytes() { return _protocol.receive_bytes(_handle, _endpoint); } bool PtopSocket::send_udp_bytes(udp_bytes bytes) -{ - int n = sendto(_handle, bytes.bytes.data(), bytes.bytes.size(), 0, &bytes.endpoint.name, bytes.endpoint.name_len); - throw_if_socket_error(n, "Failed to send UDP Bytes to " + convert_to_readable(bytes.endpoint).to_string() + " with: " + get_last_error(), LINE_CONTEXT); - - return true; +{ + bool output = _protocol.send_bytes(_handle, bytes.endpoint, bytes.bytes); + throw_if_socket_error(-1, "Failed to send UDP Bytes to " + convert_to_readable(bytes.endpoint).to_string() + " with: " + get_last_error(), LINE_CONTEXT); + return output; } -// BEGIN UDP CRAP -udp_bytes PtopSocket::recv_udp_bytes() +udp_bytes PtopSocket::receive_udp_bytes() { udp_bytes bytes; bytes.endpoint.name_len = sizeof(bytes.endpoint); @@ -273,4 +253,3 @@ udp_bytes PtopSocket::recv_udp_bytes() bytes.bytes.resize(n); return bytes; } -// END UDP CRAP \ No newline at end of file diff --git a/src/ptop_socket.h b/src/ptop_socket.h index dbfb7c1..9a8f0fb 100644 --- a/src/ptop_socket.h +++ b/src/ptop_socket.h @@ -110,7 +110,7 @@ class PtopSocket bool select_for(select_for s_for) const; bool has_message() const; - bool has_died() const; + bool has_died(); raw_name_data get_peer_raw() const; raw_name_data get_name_raw() const; @@ -125,10 +125,8 @@ class PtopSocket inline const Protocol& get_protocol() const { return _protocol; } bool send_bytes(std::vector bytes); - std::vector recv_bytes(); + std::vector receive_bytes(); - // BEGIN UDP CRAP bool send_udp_bytes(udp_bytes bytes); - udp_bytes recv_udp_bytes(); - // END UDP CRAP + udp_bytes receive_udp_bytes(); }; \ No newline at end of file diff --git a/src/windows_platform.cpp b/src/windows_platform.cpp index b87825c..4460a55 100644 --- a/src/windows_platform.cpp +++ b/src/windows_platform.cpp @@ -311,7 +311,7 @@ PtopSocket windows_data_socket_steal_construct(std::unique_ptr recv_data = _socket.recv_bytes(); + std::vector recv_data = _socket.receive_bytes(); if (recv_data.size() > 0) { std::cout << "Received " << recv_data.size() << " bytes" << std::endl; From 9da08cab56bb6e5c0d55da5d06e18f9b17a09615 Mon Sep 17 00:00:00 2001 From: Bobstuna Date: Mon, 31 Jan 2022 14:02:51 +1300 Subject: [PATCH 40/44] fix: quick dirty udp send fix --- src/ptop_socket.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index e2ae239..913933f 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -235,9 +235,7 @@ std::vector PtopSocket::receive_bytes() bool PtopSocket::send_udp_bytes(udp_bytes bytes) { - bool output = _protocol.send_bytes(_handle, bytes.endpoint, bytes.bytes); - throw_if_socket_error(-1, "Failed to send UDP Bytes to " + convert_to_readable(bytes.endpoint).to_string() + " with: " + get_last_error(), LINE_CONTEXT); - return output; + return _protocol.send_bytes(_handle, bytes.endpoint, bytes.bytes); } udp_bytes PtopSocket::receive_udp_bytes() From ce3f263bc3a756bb4fe67ba6ff078a99f095dfcf Mon Sep 17 00:00:00 2001 From: coletdjnz Date: Tue, 1 Feb 2022 18:32:01 +1300 Subject: [PATCH 41/44] refactor: receive bytes merged methods (totally wrote this) --- src/name_data.h | 3 ++- src/protocol.cpp | 13 +++++++++---- src/protocol.h | 2 +- src/ptop_socket.cpp | 21 ++++++++------------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/name_data.h b/src/name_data.h index 8a6696c..22cb68d 100644 --- a/src/name_data.h +++ b/src/name_data.h @@ -21,7 +21,8 @@ struct raw_name_data sockaddr name; socklen_t name_len; - + + bool initialized = false; sockaddr_in& ipv4_addr() { return *(sockaddr_in*)&name; } const sockaddr_in& ipv4_addr() const { return *(sockaddr_in*)&name; } diff --git a/src/protocol.cpp b/src/protocol.cpp index 7c63436..4d29ca5 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -64,7 +64,7 @@ bool Protocol::send_bytes(SOCKET handle, raw_name_data endpoint, std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data expected_endpoint) +std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data& expected_endpoint) { if (is_tcp()) { @@ -80,13 +80,17 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data expected_ } if (is_udp()) { + if (expected_endpoint.initialized == false){ + expected_endpoint.name_len = sizeof(raw_name_data); + } sockaddr addr; socklen_t addr_len = sizeof(sockaddr_in); std::vector data(500, (char)0, std::allocator()); - int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &addr, &addr_len); + int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &expected_endpoint.name, &expected_endpoint.name_len); + throw_if_socket_error(result, "Failed to receive UDP bytes with: " + get_last_error(), LINE_CONTEXT); + raw_name_data incoming{ addr, addr_len }; - - if (incoming != expected_endpoint) + if (incoming != expected_endpoint && expected_endpoint.initialized == false) { auto readable = convert_to_readable(incoming); auto message = "Receiving UDP data from an undesired endpoint (" + readable.ip_address + ":" + readable.port + ")"; @@ -97,6 +101,7 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data expected_ auto message = "Receiving (UDP) data failed: " + get_last_error(); throw_new_exception(message, LINE_CONTEXT); } + expected_endpoint.initialized = true; data.resize(result); return data; } diff --git a/src/protocol.h b/src/protocol.h index 677e6cd..c606d11 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -24,6 +24,6 @@ class Protocol { bool is_udp() const; bool send_bytes(SOCKET handle, raw_name_data endpoint, std::vector bytes); - std::vector receive_bytes(SOCKET handle, raw_name_data expected_endpoint); + std::vector receive_bytes(SOCKET handle, raw_name_data& expected_endpoint); bool has_died(SOCKET handle, bool has_message); }; \ No newline at end of file diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 913933f..2b311c0 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -238,16 +238,11 @@ bool PtopSocket::send_udp_bytes(udp_bytes bytes) return _protocol.send_bytes(_handle, bytes.endpoint, bytes.bytes); } -udp_bytes PtopSocket::receive_udp_bytes() -{ - udp_bytes bytes; - bytes.endpoint.name_len = sizeof(bytes.endpoint); - bytes.bytes = std::vector(500, (char)0, std::allocator()); - - int n = recvfrom(_handle, bytes.bytes.data(), (int)bytes.bytes.size(), 0, &bytes.endpoint.name, &bytes.endpoint.name_len); - - throw_if_socket_error(n, "Failed to receive UDP bytes (" + _name + ") with: " + get_last_error(), LINE_CONTEXT); - - bytes.bytes.resize(n); - return bytes; -} +udp_bytes PtopSocket::receive_udp_bytes(){ + raw_name_data new_name; + auto result = _protocol.receive_bytes(_handle, new_name); + udp_bytes output = udp_bytes{ + result, new_name + }; + return output; +} \ No newline at end of file From ef6f923cad709e9ffb97a7b773a4919339d80c43 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Wed, 2 Feb 2022 06:51:59 +1300 Subject: [PATCH 42/44] fix: not sending bytes --- src/name_data.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/name_data.h b/src/name_data.h index 22cb68d..d4e22f8 100644 --- a/src/name_data.h +++ b/src/name_data.h @@ -15,9 +15,9 @@ struct raw_name_data { raw_name_data() = default; - raw_name_data(sockaddr addr) : name(addr), name_len(sizeof(addr)) {} - raw_name_data(sockaddr addr, socklen_t len) : name(addr), name_len(len) {} - raw_name_data(sockaddr_in addr) : name(*(sockaddr*)&addr), name_len(sizeof(addr)) {} + raw_name_data(sockaddr addr) : name(addr), name_len(sizeof(addr)), initialized(true) {}; + raw_name_data(sockaddr addr, socklen_t len) : name(addr), name_len(len), initialized(true) {}; + raw_name_data(sockaddr_in addr) : name(*(sockaddr*)&addr), name_len(sizeof(addr)), initialized(true) {}; sockaddr name; socklen_t name_len; From 11e3a88f7fa339813beb68c698ed7521dfe77653 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Sun, 6 Feb 2022 13:23:20 +1300 Subject: [PATCH 43/44] fix: raw_name_data not being used properly --- src/protocol.cpp | 6 ++++-- src/ptop_socket.cpp | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index 4d29ca5..784ad2d 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -86,11 +86,11 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data& expected sockaddr addr; socklen_t addr_len = sizeof(sockaddr_in); std::vector data(500, (char)0, std::allocator()); - int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &expected_endpoint.name, &expected_endpoint.name_len); + int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &addr, &addr_len); throw_if_socket_error(result, "Failed to receive UDP bytes with: " + get_last_error(), LINE_CONTEXT); raw_name_data incoming{ addr, addr_len }; - if (incoming != expected_endpoint && expected_endpoint.initialized == false) + if (incoming != expected_endpoint && expected_endpoint.initialized == true) { auto readable = convert_to_readable(incoming); auto message = "Receiving UDP data from an undesired endpoint (" + readable.ip_address + ":" + readable.port + ")"; @@ -101,6 +101,8 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data& expected auto message = "Receiving (UDP) data failed: " + get_last_error(); throw_new_exception(message, LINE_CONTEXT); } + if (expected_endpoint.initialized == false) + std::memcpy(&expected_endpoint, &incoming, sizeof(raw_name_data)); expected_endpoint.initialized = true; data.resize(result); return data; diff --git a/src/ptop_socket.cpp b/src/ptop_socket.cpp index 2b311c0..70e3421 100644 --- a/src/ptop_socket.cpp +++ b/src/ptop_socket.cpp @@ -232,7 +232,6 @@ std::vector PtopSocket::receive_bytes() return _protocol.receive_bytes(_handle, _endpoint); } - bool PtopSocket::send_udp_bytes(udp_bytes bytes) { return _protocol.send_bytes(_handle, bytes.endpoint, bytes.bytes); From 30153abcb3e7a95382dbdb6b396bf81a9032b424 Mon Sep 17 00:00:00 2001 From: doublecouponday Date: Sun, 6 Feb 2022 13:34:57 +1300 Subject: [PATCH 44/44] fix: uninitialized memory --- src/protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index 784ad2d..cfa31e2 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -83,7 +83,7 @@ std::vector Protocol::receive_bytes(SOCKET handle, raw_name_data& expected if (expected_endpoint.initialized == false){ expected_endpoint.name_len = sizeof(raw_name_data); } - sockaddr addr; + auto addr = sockaddr{}; socklen_t addr_len = sizeof(sockaddr_in); std::vector data(500, (char)0, std::allocator()); int result = ::recvfrom(handle, data.data(), (int)data.size(), 0, &addr, &addr_len);