1 /* 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <iostream> // NOLINT 12 13 #include "webrtc/p2p/base/basicpacketsocketfactory.h" 14 #include "webrtc/p2p/base/turnserver.h" 15 #include "webrtc/base/asyncudpsocket.h" 16 #include "webrtc/base/optionsfile.h" 17 #include "webrtc/base/stringencode.h" 18 #include "webrtc/base/thread.h" 19 20 static const char kSoftware[] = "libjingle TurnServer"; 21 22 class TurnFileAuth : public cricket::TurnAuthInterface { 23 public: 24 explicit TurnFileAuth(const std::string& path) : file_(path) { 25 file_.Load(); 26 } 27 virtual bool GetKey(const std::string& username, const std::string& realm, 28 std::string* key) { 29 // File is stored as lines of <username>=<HA1>. 30 // Generate HA1 via "echo -n "<username>:<realm>:<password>" | md5sum" 31 std::string hex; 32 bool ret = file_.GetStringValue(username, &hex); 33 if (ret) { 34 char buf[32]; 35 size_t len = rtc::hex_decode(buf, sizeof(buf), hex); 36 *key = std::string(buf, len); 37 } 38 return ret; 39 } 40 private: 41 rtc::OptionsFile file_; 42 }; 43 44 int main(int argc, char **argv) { 45 if (argc != 5) { 46 std::cerr << "usage: turnserver int-addr ext-ip realm auth-file" 47 << std::endl; 48 return 1; 49 } 50 51 rtc::SocketAddress int_addr; 52 if (!int_addr.FromString(argv[1])) { 53 std::cerr << "Unable to parse IP address: " << argv[1] << std::endl; 54 return 1; 55 } 56 57 rtc::IPAddress ext_addr; 58 if (!IPFromString(argv[2], &ext_addr)) { 59 std::cerr << "Unable to parse IP address: " << argv[2] << std::endl; 60 return 1; 61 } 62 63 rtc::Thread* main = rtc::Thread::Current(); 64 rtc::AsyncUDPSocket* int_socket = 65 rtc::AsyncUDPSocket::Create(main->socketserver(), int_addr); 66 if (!int_socket) { 67 std::cerr << "Failed to create a UDP socket bound at" 68 << int_addr.ToString() << std::endl; 69 return 1; 70 } 71 72 cricket::TurnServer server(main); 73 TurnFileAuth auth(argv[4]); 74 server.set_realm(argv[3]); 75 server.set_software(kSoftware); 76 server.set_auth_hook(&auth); 77 server.AddInternalSocket(int_socket, cricket::PROTO_UDP); 78 server.SetExternalSocketFactory(new rtc::BasicPacketSocketFactory(), 79 rtc::SocketAddress(ext_addr, 0)); 80 81 std::cout << "Listening internally at " << int_addr.ToString() << std::endl; 82 83 main->Run(); 84 return 0; 85 } 86