Delete OptionsFile class. Refactored only user, TurnFileAuth.

Bug: webrtc:6424
Change-Id: I4b74cd6197f2cb060d1aff70e3adadbdf7f7a580
Reviewed-on: https://webrtc-review.googlesource.com/c/108122
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Patrik Höglund <phoglund@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25426}
This commit is contained in:
Niels Möller
2018-10-30 12:20:03 +01:00
committed by Commit Bot
parent 3df6e715ec
commit 9862c2eb13
10 changed files with 154 additions and 425 deletions

View File

@ -47,6 +47,7 @@ if (!build_with_chromium) {
"call:fake_network_unittests",
"common_audio:common_audio_unittests",
"common_video:common_video_unittests",
"examples:examples_unittests",
"media:rtc_media_unittests",
"modules:modules_tests",
"modules:modules_unittests",

View File

@ -60,6 +60,32 @@ group("examples") {
}
}
rtc_source_set("read_auth_file") {
testonly = true
sources = [
"turnserver/read_auth_file.cc",
"turnserver/read_auth_file.h",
]
deps = [
"../rtc_base:rtc_base",
]
}
if (rtc_include_tests) {
rtc_test("examples_unittests") {
testonly = true
sources = [
"turnserver/read_auth_file_unittest.cc",
]
deps = [
":read_auth_file",
"../test:test_main",
"//test:test_support",
"//testing/gtest",
]
}
}
if (is_android) {
rtc_android_apk("AppRTCMobile") {
testonly = true
@ -747,6 +773,7 @@ if (is_linux || is_win) {
"turnserver/turnserver_main.cc",
]
deps = [
":read_auth_file",
"../p2p:rtc_p2p",
"../pc:rtc_pc",
"../rtc_base:rtc_base",

View File

@ -0,0 +1,33 @@
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "examples/turnserver/read_auth_file.h"
#include "rtc_base/stringencode.h"
namespace webrtc_examples {
std::map<std::string, std::string> ReadAuthFile(
std::istream* s) { // no-presubmit-check TODO(webrtc:8982)
std::map<std::string, std::string> name_to_key;
for (std::string line; std::getline(*s, line);) {
const size_t sep = line.find('=');
if (sep == std::string::npos)
continue;
char buf[32];
size_t len = rtc::hex_decode(buf, sizeof(buf), line.data() + sep + 1,
line.size() - sep - 1);
if (len > 0) {
name_to_key.emplace(line.substr(0, sep), std::string(buf, len));
}
}
return name_to_key;
}
} // namespace webrtc_examples

View File

@ -0,0 +1,25 @@
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef EXAMPLES_TURNSERVER_READ_AUTH_FILE_H_
#define EXAMPLES_TURNSERVER_READ_AUTH_FILE_H_
#include <istream> // no-presubmit-check TODO(webrtc:8982)
#include <map>
#include <string>
namespace webrtc_examples {
std::map<std::string, std::string> ReadAuthFile(
std::istream* s); // no-presubmit-check TODO(webrtc:8982)
} // namespace webrtc_examples
#endif // EXAMPLES_TURNSERVER_READ_AUTH_FILE_H_

View File

@ -0,0 +1,45 @@
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <sstream> // no-presubmit-check TODO(webrtc:8982)
#include "examples/turnserver/read_auth_file.h"
#include "test/gtest.h"
namespace webrtc_examples {
TEST(ReadAuthFile, HandlesEmptyFile) {
std::istringstream empty; // no-presubmit-check TODO(webrtc:8982)
auto map = ReadAuthFile(&empty);
EXPECT_TRUE(map.empty());
}
TEST(ReadAuthFile, RecognizesValidUser) {
std::istringstream // no-presubmit-check TODO(webrtc:8982)
file("foo=deadbeaf\n");
auto map = ReadAuthFile(&file);
ASSERT_NE(map.find("foo"), map.end());
EXPECT_EQ(map["foo"], "\xde\xad\xbe\xaf");
}
TEST(ReadAuthFile, EmptyValueForInvalidHex) {
std::istringstream file( // no-presubmit-check TODO(webrtc:8982)
"foo=deadbeaf\n"
"bar=xxxxinvalidhex\n"
"baz=cafe\n");
auto map = ReadAuthFile(&file);
ASSERT_NE(map.find("foo"), map.end());
EXPECT_EQ(map["foo"], "\xde\xad\xbe\xaf");
EXPECT_EQ(map.find("bar"), map.end());
ASSERT_NE(map.find("baz"), map.end());
EXPECT_EQ(map["baz"], "\xca\xfe");
}
} // namespace webrtc_examples

View File

@ -8,39 +8,44 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <iostream> // NOLINT
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include "examples/turnserver/read_auth_file.h"
#include "p2p/base/basicpacketsocketfactory.h"
#include "p2p/base/turnserver.h"
#include "rtc_base/asyncudpsocket.h"
#include "rtc_base/optionsfile.h"
#include "rtc_base/stringencode.h"
#include "rtc_base/thread.h"
static const char kSoftware[] = "libjingle TurnServer";
namespace {
const char kSoftware[] = "libjingle TurnServer";
class TurnFileAuth : public cricket::TurnAuthInterface {
public:
explicit TurnFileAuth(const std::string& path) : file_(path) { file_.Load(); }
explicit TurnFileAuth(std::map<std::string, std::string> name_to_key)
: name_to_key_(std::move(name_to_key)) {}
virtual bool GetKey(const std::string& username,
const std::string& realm,
std::string* key) {
// File is stored as lines of <username>=<HA1>.
// Generate HA1 via "echo -n "<username>:<realm>:<password>" | md5sum"
std::string hex;
bool ret = file_.GetStringValue(username, &hex);
if (ret) {
char buf[32];
size_t len = rtc::hex_decode(buf, sizeof(buf), hex);
*key = std::string(buf, len);
}
return ret;
auto it = name_to_key_.find(username);
if (it == name_to_key_.end())
return false;
*key = it->second;
return true;
}
private:
rtc::OptionsFile file_;
const std::map<std::string, std::string> name_to_key_;
};
} // namespace
int main(int argc, char* argv[]) {
if (argc != 5) {
std::cerr << "usage: turnserver int-addr ext-ip realm auth-file"
@ -70,7 +75,11 @@ int main(int argc, char* argv[]) {
}
cricket::TurnServer server(main);
TurnFileAuth auth(argv[4]);
std::fstream auth_file(argv[4], std::fstream::in);
TurnFileAuth auth(auth_file.is_open()
? webrtc_examples::ReadAuthFile(&auth_file)
: std::map<std::string, std::string>());
server.set_realm(argv[3]);
server.set_software(kSoftware);
server.set_auth_hook(&auth);

View File

@ -829,8 +829,6 @@ rtc_static_library("rtc_base") {
"logsinks.cc",
"logsinks.h",
"numerics/mathutils.h",
"optionsfile.cc",
"optionsfile.h",
"rollingaccumulator.h",
"sslroots.h",
]
@ -1245,7 +1243,6 @@ if (rtc_include_tests) {
"messagequeue_unittest.cc",
"nat_unittest.cc",
"network_unittest.cc",
"optionsfile_unittest.cc",
"proxy_unittest.cc",
"rollingaccumulator_unittest.cc",
"rtccertificate_unittest.cc",

View File

@ -1,180 +0,0 @@
/*
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/optionsfile.h"
#include <ctype.h>
#include "rtc_base/logging.h"
#include "rtc_base/stream.h"
namespace rtc {
OptionsFile::OptionsFile(const std::string& path) : path_(path) {}
OptionsFile::~OptionsFile() = default;
bool OptionsFile::Load() {
options_.clear();
// Open file.
FileStream stream;
int err;
if (!stream.Open(path_, "r", &err)) {
RTC_LOG_F(LS_WARNING) << "Could not open file, err=" << err;
// We do not consider this an error because we expect there to be no file
// until the user saves a setting.
return true;
}
// Read in all its data.
std::string line;
StreamResult res;
for (;;) {
res = stream.ReadLine(&line);
if (res != SR_SUCCESS) {
break;
}
size_t equals_pos = line.find('=');
if (equals_pos == std::string::npos) {
// We do not consider this an error. Instead we ignore the line and
// keep going.
RTC_LOG_F(LS_WARNING) << "Ignoring malformed line in " << path_;
continue;
}
std::string key(line, 0, equals_pos);
std::string value(line, equals_pos + 1, line.length() - (equals_pos + 1));
options_[key] = value;
}
if (res != SR_EOS) {
RTC_LOG_F(LS_ERROR) << "Error when reading from file";
return false;
} else {
return true;
}
}
bool OptionsFile::Save() {
// Open file.
FileStream stream;
int err;
if (!stream.Open(path_, "w", &err)) {
RTC_LOG_F(LS_ERROR) << "Could not open file, err=" << err;
return false;
}
// Write out all the data.
StreamResult res = SR_SUCCESS;
size_t written;
int error;
for (OptionsMap::const_iterator i = options_.begin(); i != options_.end();
++i) {
res =
stream.WriteAll(i->first.c_str(), i->first.length(), &written, &error);
if (res != SR_SUCCESS) {
break;
}
res = stream.WriteAll("=", 1, &written, &error);
if (res != SR_SUCCESS) {
break;
}
res = stream.WriteAll(i->second.c_str(), i->second.length(), &written,
&error);
if (res != SR_SUCCESS) {
break;
}
res = stream.WriteAll("\n", 1, &written, &error);
if (res != SR_SUCCESS) {
break;
}
}
if (res != SR_SUCCESS) {
RTC_LOG_F(LS_ERROR) << "Unable to write to file";
return false;
} else {
return true;
}
}
bool OptionsFile::IsLegalName(const std::string& name) {
for (size_t pos = 0; pos < name.length(); ++pos) {
if (name[pos] == '\n' || name[pos] == '\\' || name[pos] == '=') {
// Illegal character.
RTC_LOG(LS_WARNING) << "Ignoring operation for illegal option " << name;
return false;
}
}
return true;
}
bool OptionsFile::IsLegalValue(const std::string& value) {
for (size_t pos = 0; pos < value.length(); ++pos) {
if (value[pos] == '\n' || value[pos] == '\\') {
// Illegal character.
RTC_LOG(LS_WARNING) << "Ignoring operation for illegal value " << value;
return false;
}
}
return true;
}
bool OptionsFile::GetStringValue(const std::string& option,
std::string* out_val) const {
RTC_LOG(LS_VERBOSE) << "OptionsFile::GetStringValue " << option;
if (!IsLegalName(option)) {
return false;
}
OptionsMap::const_iterator i = options_.find(option);
if (i == options_.end()) {
return false;
}
*out_val = i->second;
return true;
}
bool OptionsFile::GetIntValue(const std::string& option, int* out_val) const {
RTC_LOG(LS_VERBOSE) << "OptionsFile::GetIntValue " << option;
if (!IsLegalName(option)) {
return false;
}
OptionsMap::const_iterator i = options_.find(option);
if (i == options_.end()) {
return false;
}
return FromString(i->second, out_val);
}
bool OptionsFile::SetStringValue(const std::string& option,
const std::string& value) {
RTC_LOG(LS_VERBOSE) << "OptionsFile::SetStringValue " << option << ":"
<< value;
if (!IsLegalName(option) || !IsLegalValue(value)) {
return false;
}
options_[option] = value;
return true;
}
bool OptionsFile::SetIntValue(const std::string& option, int value) {
RTC_LOG(LS_VERBOSE) << "OptionsFile::SetIntValue " << option << ":" << value;
if (!IsLegalName(option)) {
return false;
}
options_[option] = ToString(value);
return true;
}
bool OptionsFile::RemoveValue(const std::string& option) {
RTC_LOG(LS_VERBOSE) << "OptionsFile::RemoveValue " << option;
if (!IsLegalName(option)) {
return false;
}
options_.erase(option);
return true;
}
} // namespace rtc

View File

@ -1,50 +0,0 @@
/*
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_OPTIONSFILE_H_
#define RTC_BASE_OPTIONSFILE_H_
#include <map>
#include <string>
namespace rtc {
// Implements storage of simple options in a text file on disk. This is
// cross-platform, but it is intended mostly for Linux where there is no
// first-class options storage system.
class OptionsFile {
public:
OptionsFile(const std::string& path);
~OptionsFile();
// Loads the file from disk, overwriting the in-memory values.
bool Load();
// Saves the contents in memory, overwriting the on-disk values.
bool Save();
bool GetStringValue(const std::string& option, std::string* out_val) const;
bool GetIntValue(const std::string& option, int* out_val) const;
bool SetStringValue(const std::string& option, const std::string& val);
bool SetIntValue(const std::string& option, int val);
bool RemoveValue(const std::string& option);
private:
typedef std::map<std::string, std::string> OptionsMap;
static bool IsLegalName(const std::string& name);
static bool IsLegalValue(const std::string& value);
std::string path_;
OptionsMap options_;
};
} // namespace rtc
#endif // RTC_BASE_OPTIONSFILE_H_

View File

@ -1,178 +0,0 @@
/*
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <memory>
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"
#include "rtc_base/optionsfile.h"
#include "test/testsupport/fileutils.h"
namespace rtc {
static const std::string kTestOptionA = "test-option-a";
static const std::string kTestOptionB = "test-option-b";
static const std::string kTestString1 = "a string";
static const std::string kTestString2 = "different string";
static const std::string kOptionWithEquals = "foo=bar";
static const std::string kOptionWithNewline = "foo\nbar";
static const std::string kValueWithEquals = "baz=quux";
static const std::string kValueWithNewline = "baz\nquux";
static const std::string kEmptyString = "";
static const char kOptionWithUtf8[] = {'O', 'p', 't', '\302', '\256',
'i', 'o', 'n', '\342', '\204',
'\242', '\0'}; // Opt(R)io(TM).
static const char kValueWithUtf8[] = {
'V', 'a', 'l', '\302', '\256', 'v',
'e', '\342', '\204', '\242', '\0'}; // Val(R)ue(TM).
static int kTestInt1 = 12345;
static int kTestInt2 = 67890;
static int kNegInt = -634;
static int kZero = 0;
#if defined(WEBRTC_ANDROID)
// Fails on Android: https://bugs.chromium.org/p/webrtc/issues/detail?id=4364.
#define MAYBE_OptionsFileTest DISABLED_OptionsFileTest
#else
#define MAYBE_OptionsFileTest OptionsFileTest
#endif
class MAYBE_OptionsFileTest : public testing::Test {
public:
MAYBE_OptionsFileTest() {
test_file_ =
webrtc::test::TempFilename(webrtc::test::OutputPath(), ".testfile");
OpenStore();
}
~MAYBE_OptionsFileTest() override { webrtc::test::RemoveFile(test_file_); }
protected:
void OpenStore() { store_.reset(new OptionsFile(test_file_)); }
std::unique_ptr<OptionsFile> store_;
private:
std::string test_file_;
};
TEST_F(MAYBE_OptionsFileTest, GetSetString) {
// Clear contents of the file on disk.
EXPECT_TRUE(store_->Save());
std::string out1, out2;
EXPECT_FALSE(store_->GetStringValue(kTestOptionA, &out1));
EXPECT_FALSE(store_->GetStringValue(kTestOptionB, &out2));
EXPECT_TRUE(store_->SetStringValue(kTestOptionA, kTestString1));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->SetStringValue(kTestOptionB, kTestString2));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetStringValue(kTestOptionA, &out1));
EXPECT_TRUE(store_->GetStringValue(kTestOptionB, &out2));
EXPECT_EQ(kTestString1, out1);
EXPECT_EQ(kTestString2, out2);
EXPECT_TRUE(store_->RemoveValue(kTestOptionA));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->RemoveValue(kTestOptionB));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_FALSE(store_->GetStringValue(kTestOptionA, &out1));
EXPECT_FALSE(store_->GetStringValue(kTestOptionB, &out2));
}
TEST_F(MAYBE_OptionsFileTest, GetSetInt) {
// Clear contents of the file on disk.
EXPECT_TRUE(store_->Save());
int out1, out2;
EXPECT_FALSE(store_->GetIntValue(kTestOptionA, &out1));
EXPECT_FALSE(store_->GetIntValue(kTestOptionB, &out2));
EXPECT_TRUE(store_->SetIntValue(kTestOptionA, kTestInt1));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->SetIntValue(kTestOptionB, kTestInt2));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetIntValue(kTestOptionA, &out1));
EXPECT_TRUE(store_->GetIntValue(kTestOptionB, &out2));
EXPECT_EQ(kTestInt1, out1);
EXPECT_EQ(kTestInt2, out2);
EXPECT_TRUE(store_->RemoveValue(kTestOptionA));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->RemoveValue(kTestOptionB));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_FALSE(store_->GetIntValue(kTestOptionA, &out1));
EXPECT_FALSE(store_->GetIntValue(kTestOptionB, &out2));
EXPECT_TRUE(store_->SetIntValue(kTestOptionA, kNegInt));
EXPECT_TRUE(store_->GetIntValue(kTestOptionA, &out1));
EXPECT_EQ(kNegInt, out1);
EXPECT_TRUE(store_->SetIntValue(kTestOptionA, kZero));
EXPECT_TRUE(store_->GetIntValue(kTestOptionA, &out1));
EXPECT_EQ(kZero, out1);
}
TEST_F(MAYBE_OptionsFileTest, Persist) {
// Clear contents of the file on disk.
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->SetStringValue(kTestOptionA, kTestString1));
EXPECT_TRUE(store_->SetIntValue(kTestOptionB, kNegInt));
EXPECT_TRUE(store_->Save());
// Load the saved contents from above.
OpenStore();
EXPECT_TRUE(store_->Load());
std::string out1;
int out2;
EXPECT_TRUE(store_->GetStringValue(kTestOptionA, &out1));
EXPECT_TRUE(store_->GetIntValue(kTestOptionB, &out2));
EXPECT_EQ(kTestString1, out1);
EXPECT_EQ(kNegInt, out2);
}
TEST_F(MAYBE_OptionsFileTest, SpecialCharacters) {
// Clear contents of the file on disk.
EXPECT_TRUE(store_->Save());
std::string out;
EXPECT_FALSE(store_->SetStringValue(kOptionWithEquals, kTestString1));
EXPECT_FALSE(store_->GetStringValue(kOptionWithEquals, &out));
EXPECT_FALSE(store_->SetStringValue(kOptionWithNewline, kTestString1));
EXPECT_FALSE(store_->GetStringValue(kOptionWithNewline, &out));
EXPECT_TRUE(store_->SetStringValue(kOptionWithUtf8, kValueWithUtf8));
EXPECT_TRUE(store_->SetStringValue(kTestOptionA, kTestString1));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetStringValue(kTestOptionA, &out));
EXPECT_EQ(kTestString1, out);
EXPECT_TRUE(store_->GetStringValue(kOptionWithUtf8, &out));
EXPECT_EQ(kValueWithUtf8, out);
EXPECT_FALSE(store_->SetStringValue(kTestOptionA, kValueWithNewline));
EXPECT_TRUE(store_->GetStringValue(kTestOptionA, &out));
EXPECT_EQ(kTestString1, out);
EXPECT_TRUE(store_->SetStringValue(kTestOptionA, kValueWithEquals));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetStringValue(kTestOptionA, &out));
EXPECT_EQ(kValueWithEquals, out);
EXPECT_TRUE(store_->SetStringValue(kEmptyString, kTestString2));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetStringValue(kEmptyString, &out));
EXPECT_EQ(kTestString2, out);
EXPECT_TRUE(store_->SetStringValue(kTestOptionB, kEmptyString));
EXPECT_TRUE(store_->Save());
EXPECT_TRUE(store_->Load());
EXPECT_TRUE(store_->GetStringValue(kTestOptionB, &out));
EXPECT_EQ(kEmptyString, out);
}
} // namespace rtc