diff --git a/.gitmodules b/.gitmodules index ef67b3d..03bbf44 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,9 @@ [submodule "deps/libjuice"] path = deps/libjuice url = https://github.com/paullouisageneau/libjuice +[submodule "deps/httplib"] + path = deps/httplib + url = https://github.com/yhirose/cpp-httplib.git +[submodule "deps/json"] + path = deps/json + url = https://github.com/nlohmann/json.git diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9cf226e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "__functional_03": "cpp", + "iosfwd": "cpp", + "ostream": "cpp", + "memory": "cpp", + "functional": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index bbebf7e..f3fe2a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,9 @@ set(TESTS_ANSWERER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test/p2p/answerer.cpp ) +set(JSON_BuildTests OFF CACHE INTERNAL "") +add_subdirectory(deps/json) + set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) @@ -130,7 +133,7 @@ set_target_properties(datachannel-tests PROPERTIES CXX_STANDARD 17) set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests) target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) -target_link_libraries(datachannel-tests datachannel) +target_link_libraries(datachannel-tests datachannel nlohmann_json::nlohmann_json) # P2P Test: offerer add_executable(datachannel-offerer ${TESTS_OFFERER_SOURCES}) @@ -139,6 +142,8 @@ set_target_properties(datachannel-offerer PROPERTIES CXX_STANDARD 17) set_target_properties(datachannel-offerer PROPERTIES OUTPUT_NAME offerer) target_link_libraries(datachannel-offerer datachannel) +target_include_directories(datachannel-offerer PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/deps/httplib) +target_include_directories(datachannel-offerer PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/deps/json/include) # P2P Test: answerer add_executable(datachannel-answerer ${TESTS_ANSWERER_SOURCES}) diff --git a/deps/httplib b/deps/httplib new file mode 160000 index 0000000..26deffe --- /dev/null +++ b/deps/httplib @@ -0,0 +1 @@ +Subproject commit 26deffe0c6a1e177e393416b94cdc0f340ca79bd diff --git a/deps/json b/deps/json new file mode 160000 index 0000000..973c52d --- /dev/null +++ b/deps/json @@ -0,0 +1 @@ +Subproject commit 973c52dd4a9e92ede5ca4afe8b3d01ef677dc57f diff --git a/include/rtc/peerconnection.hpp b/include/rtc/peerconnection.hpp index 02985a4..585e60b 100644 --- a/include/rtc/peerconnection.hpp +++ b/include/rtc/peerconnection.hpp @@ -87,6 +87,8 @@ public: void onStateChange(std::function callback); void onGatheringStateChange(std::function callback); + std::string connectionInfo; + private: std::shared_ptr initIceTransport(Description::Role role); std::shared_ptr initDtlsTransport(); diff --git a/test/p2p/offerer.cpp b/test/p2p/offerer.cpp index ff2b101..145018b 100644 --- a/test/p2p/offerer.cpp +++ b/test/p2p/offerer.cpp @@ -18,6 +18,9 @@ #include "rtc/rtc.hpp" +#include +#include + #include #include #include @@ -28,27 +31,76 @@ using namespace std; template weak_ptr make_weak_ptr(shared_ptr ptr) { return ptr; } +const char base64_url_alphabet[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' +}; + +std::string base64_encode(const std::string & in) { + std::string out; + int val =0, valb=-6; + size_t len = in.length(); + unsigned int i = 0; + for (i = 0; i < len; i++) { + unsigned char c = in[i]; + val = (val<<8) + c; + valb += 8; + while (valb >= 0) { + out.push_back(base64_url_alphabet[(val>>valb)&0x3F]); + valb -= 6; + } + } + if (valb > -6) { + out.push_back(base64_url_alphabet[((val<<8)>>(valb+8))&0x3F]); + } + return out; +} + int main(int argc, char **argv) { InitLogger(LogLevel::Warning); Configuration config; // config.iceServers.emplace_back("stun.l.google.com:19302"); + std::string payload; + auto pc = std::make_shared(config); - pc->onLocalDescription([](const Description &description) { - cout << "Local Description (Paste this to the other peer):" << endl; - cout << string(description) << endl; + pc->onLocalDescription([wpc = make_weak_ptr(pc)](const Description &description){ + auto pc = wpc.lock(); + if (!pc) + return; + + pc->connectionInfo = "{\"description\":\""; + pc->connectionInfo += description; + pc->connectionInfo += "\","; }); - pc->onLocalCandidate([](const Candidate &candidate) { - cout << "Local Candidate (Paste this to the other peer after the local description):" - << endl; - cout << string(candidate) << endl << endl; + pc->onLocalCandidate([wpc = make_weak_ptr(pc)](const Candidate &candidate) { + auto pc = wpc.lock(); + if (!pc) + return; + + pc->connectionInfo += "\"candidate\":\""; + pc->connectionInfo += candidate; + pc->connectionInfo += "\"}"; + + cout << pc->connectionInfo << endl << endl; + + auto encoded = base64_encode(pc->connectionInfo); + cout << "http://localhost:8080/answerer.html?connection=" << encoded << endl; }); - pc->onStateChange( - [](PeerConnection::State state) { cout << "[State: " << state << "]" << endl; }); + pc->onStateChange([](PeerConnection::State state){ + if (state == PeerConnection::State::Connecting) { + // httplib::Client cli("localhost", 8000); + // cli.Post("/state/json", "json", payload); + } + cout << "[State: " << state << "]" << endl; + }); pc->onGatheringStateChange([](PeerConnection::GatheringState state) { cout << "[Gathering State: " << state << "]" << endl;