offerer.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. std::vector<string> split(const string& str, const string& delim)
  55. {
  56. vector<string> tokens;
  57. size_t prev = 0, pos = 0;
  58. do
  59. {
  60. pos = str.find(delim, prev);
  61. if (pos == string::npos) pos = str.length();
  62. string token = str.substr(prev, pos-prev);
  63. if (!token.empty()) tokens.push_back(token);
  64. prev = pos + delim.length();
  65. }
  66. while (pos < str.length() && prev < str.length());
  67. return tokens;
  68. }
  69. int main(int argc, char **argv) {
  70. InitLogger(LogLevel::Warning);
  71. Configuration config;
  72. // config.iceServers.emplace_back("stun.l.google.com:19302");
  73. std::string payload;
  74. auto pc = std::make_shared<PeerConnection>(config);
  75. pc->onLocalDescription([wpc = make_weak_ptr(pc)](const Description &description){
  76. auto pc = wpc.lock();
  77. if (!pc)
  78. return;
  79. pc->connectionInfo += description;
  80. pc->connectionInfo += "xxxxx";
  81. });
  82. pc->onLocalCandidate([wpc = make_weak_ptr(pc)](const Candidate &candidate) {
  83. auto pc = wpc.lock();
  84. if (!pc)
  85. return;
  86. pc->connectionInfo += candidate;
  87. cout << pc->connectionInfo << endl << endl;
  88. auto encoded = base64_encode(pc->connectionInfo);
  89. cout << "http://localhost:8080/answerer.html?connection=" << encoded << endl << endl;
  90. httplib::Client cli("localhost", 8000);
  91. auto res = cli.Get("/state/json");
  92. if (!res)
  93. return;
  94. while (res->status == -1) {
  95. res = cli.Get("/state/json");
  96. }
  97. std::string description;
  98. auto parts = split(res->body, "xxxxx");
  99. pc->setRemoteDescription(parts[0]);
  100. });
  101. pc->onStateChange([wpc = make_weak_ptr(pc)](PeerConnection::State state){
  102. cout << "[State: " << state << "]" << endl;
  103. });
  104. pc->onGatheringStateChange([](PeerConnection::GatheringState state) {
  105. cout << "[Gathering State: " << state << "]" << endl;
  106. });
  107. auto dc = pc->createDataChannel("test"); // this is the offerer, so create a data channel
  108. dc->onOpen([&]() { cout << "[DataChannel open: " << dc->label() << "]" << endl; });
  109. dc->onClosed([&]() { cout << "[DataChannel closed: " << dc->label() << "]" << endl; });
  110. dc->onMessage([](const variant<binary, string> &message) {
  111. if (holds_alternative<string>(message)) {
  112. cout << "[Received: " << get<string>(message) << "]" << endl;
  113. }
  114. });
  115. this_thread::sleep_for(1s);
  116. bool exit = false;
  117. while (!exit) {
  118. cout << endl
  119. << "**********************************************************************************"
  120. "*****"
  121. << endl
  122. << "* 0: Exit /"
  123. << " 1: Enter remote description /"
  124. << " 2: Enter remote candidate /"
  125. << " 3: Send message *" << endl
  126. << "[Command]: ";
  127. int command = -1;
  128. cin >> command;
  129. cin.ignore();
  130. switch (command) {
  131. case 0: {
  132. exit = true;
  133. break;
  134. }
  135. case 1: {
  136. // Parse Description
  137. cout << "[Description]: ";
  138. string sdp, line;
  139. while (getline(cin, line) && !line.empty()) {
  140. sdp += line;
  141. sdp += "\r\n";
  142. }
  143. pc->setRemoteDescription(sdp);
  144. break;
  145. }
  146. case 2: {
  147. // Parse Candidate
  148. cout << "[Candidate]: ";
  149. string candidate;
  150. getline(cin, candidate);
  151. pc->addRemoteCandidate(candidate);
  152. break;
  153. }
  154. case 3: {
  155. // Send Message
  156. if (!dc->isOpen()) {
  157. cout << "** Channel is not Open ** ";
  158. break;
  159. }
  160. cout << "[Message]: ";
  161. string message;
  162. getline(cin, message);
  163. dc->send(message);
  164. break;
  165. }
  166. default: {
  167. cout << "** Invalid Command ** ";
  168. break;
  169. }
  170. }
  171. }
  172. if (dc)
  173. dc->close();
  174. if (pc)
  175. pc->close();
  176. }