offerer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /**
  2. * Copyright (c) 2019 Paul-Louis Ageneau, Murat Dogan
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "rtc/rtc.hpp"
  19. #include <httplib.h>
  20. #include <nlohmann/json.hpp>
  21. #include <chrono>
  22. #include <iostream>
  23. #include <memory>
  24. #include <thread>
  25. using namespace rtc;
  26. using namespace std;
  27. template <class T> weak_ptr<T> make_weak_ptr(shared_ptr<T> ptr) { return ptr; }
  28. const char base64_url_alphabet[] = {
  29. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  30. 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  31. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  32. 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  33. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
  34. };
  35. std::string base64_encode(const std::string & in) {
  36. std::string out;
  37. int val =0, valb=-6;
  38. size_t len = in.length();
  39. unsigned int i = 0;
  40. for (i = 0; i < len; i++) {
  41. unsigned char c = in[i];
  42. val = (val<<8) + c;
  43. valb += 8;
  44. while (valb >= 0) {
  45. out.push_back(base64_url_alphabet[(val>>valb)&0x3F]);
  46. valb -= 6;
  47. }
  48. }
  49. if (valb > -6) {
  50. out.push_back(base64_url_alphabet[((val<<8)>>(valb+8))&0x3F]);
  51. }
  52. return out;
  53. }
  54. int main(int argc, char **argv) {
  55. InitLogger(LogLevel::Warning);
  56. Configuration config;
  57. // config.iceServers.emplace_back("stun.l.google.com:19302");
  58. std::string payload;
  59. auto pc = std::make_shared<PeerConnection>(config);
  60. pc->onLocalDescription([wpc = make_weak_ptr(pc)](const Description &description){
  61. auto pc = wpc.lock();
  62. if (!pc)
  63. return;
  64. pc->connectionInfo += description;
  65. pc->connectionInfo += "xxxxx";
  66. });
  67. pc->onLocalCandidate([wpc = make_weak_ptr(pc)](const Candidate &candidate) {
  68. auto pc = wpc.lock();
  69. if (!pc)
  70. return;
  71. pc->connectionInfo += candidate;
  72. cout << pc->connectionInfo << endl << endl;
  73. auto encoded = base64_encode(pc->connectionInfo);
  74. cout << "http://localhost:8080/answerer.html?connection=" << encoded << endl << endl;
  75. httplib::Client cli("localhost", 8000);
  76. auto res = cli.Get("/state/json");
  77. if (!res)
  78. return;
  79. while (res->body.empty()) {
  80. res = cli.Get("/state/json");
  81. }
  82. pc->setRemoteDescription(res->body);
  83. });
  84. pc->onStateChange([wpc = make_weak_ptr(pc)](PeerConnection::State state){
  85. cout << "[State: " << state << "]" << endl;
  86. });
  87. pc->onGatheringStateChange([](PeerConnection::GatheringState state) {
  88. cout << "[Gathering State: " << state << "]" << endl;
  89. });
  90. auto dc = pc->createDataChannel("test"); // this is the offerer, so create a data channel
  91. dc->onOpen([&]() { cout << "[DataChannel open: " << dc->label() << "]" << endl; });
  92. dc->onClosed([&]() { cout << "[DataChannel closed: " << dc->label() << "]" << endl; });
  93. dc->onMessage([](const variant<binary, string> &message) {
  94. if (holds_alternative<string>(message)) {
  95. cout << "[Received: " << get<string>(message) << "]" << endl;
  96. }
  97. });
  98. this_thread::sleep_for(1s);
  99. bool exit = false;
  100. while (!exit) {
  101. cout << endl
  102. << "**********************************************************************************"
  103. "*****"
  104. << endl
  105. << "* 0: Exit /"
  106. << " 1: Enter remote description /"
  107. << " 2: Enter remote candidate /"
  108. << " 3: Send message *" << endl
  109. << "[Command]: ";
  110. int command = -1;
  111. cin >> command;
  112. cin.ignore();
  113. switch (command) {
  114. case 0: {
  115. exit = true;
  116. break;
  117. }
  118. case 1: {
  119. // Parse Description
  120. cout << "[Description]: ";
  121. string sdp, line;
  122. while (getline(cin, line) && !line.empty()) {
  123. sdp += line;
  124. sdp += "\r\n";
  125. }
  126. pc->setRemoteDescription(sdp);
  127. break;
  128. }
  129. case 2: {
  130. // Parse Candidate
  131. cout << "[Candidate]: ";
  132. string candidate;
  133. getline(cin, candidate);
  134. pc->addRemoteCandidate(candidate);
  135. break;
  136. }
  137. case 3: {
  138. // Send Message
  139. if (!dc->isOpen()) {
  140. cout << "** Channel is not Open ** ";
  141. break;
  142. }
  143. cout << "[Message]: ";
  144. string message;
  145. getline(cin, message);
  146. dc->send(message);
  147. break;
  148. }
  149. default: {
  150. cout << "** Invalid Command ** ";
  151. break;
  152. }
  153. }
  154. }
  155. if (dc)
  156. dc->close();
  157. if (pc)
  158. pc->close();
  159. }