<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/sync_policy_test.h"

#include "base/win/scoped_handle.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/nt_internals.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sandbox {

SBOX_TESTS_COMMAND int Event_Open(int argc, wchar_t **argv) {
  if (argc != 2)
    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;

  DWORD desired_access = SYNCHRONIZE;
  if (L'f' == argv[0][0])
    desired_access = EVENT_ALL_ACCESS;

  base::win::ScopedHandle event_open(::OpenEvent(
      desired_access, FALSE, argv[1]));
  DWORD error_open = ::GetLastError();

  if (event_open.IsValid())
    return SBOX_TEST_SUCCEEDED;

  if (ERROR_ACCESS_DENIED == error_open ||
      ERROR_BAD_PATHNAME == error_open ||
      ERROR_FILE_NOT_FOUND == error_open)
    return SBOX_TEST_DENIED;

  return SBOX_TEST_FAILED;
}

SBOX_TESTS_COMMAND int Event_CreateOpen(int argc, wchar_t **argv) {
  if (argc < 2 || argc > 3)
    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;

  wchar_t *event_name = NULL;
  if (3 == argc)
    event_name = argv[2];

  BOOL manual_reset = FALSE;
  BOOL initial_state = FALSE;
  if (L't' == argv[0][0])
    manual_reset = TRUE;
  if (L't' == argv[1][0])
    initial_state = TRUE;

  base::win::ScopedHandle event_create(::CreateEvent(
      NULL, manual_reset, initial_state, event_name));
  DWORD error_create = ::GetLastError();
  base::win::ScopedHandle event_open;
  if (event_name)
    event_open.Set(::OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name));

  if (event_create.IsValid()) {
    DWORD wait = ::WaitForSingleObject(event_create.Get(), 0);
    if (initial_state && WAIT_OBJECT_0 != wait)
      return SBOX_TEST_FAILED;

    if (!initial_state && WAIT_TIMEOUT != wait)
      return SBOX_TEST_FAILED;
  }

  if (event_name) {
    // Both event_open and event_create have to be valid.
    if (event_open.IsValid() && event_create.IsValid())
      return SBOX_TEST_SUCCEEDED;

    if ((event_open.IsValid() && !event_create.IsValid()) ||
        (!event_open.IsValid() && event_create.IsValid())) {
      return SBOX_TEST_FAILED;
    }
  } else {
    // Only event_create has to be valid.
    if (event_create.Get())
      return SBOX_TEST_SUCCEEDED;
  }

  if (ERROR_ACCESS_DENIED == error_create ||
      ERROR_BAD_PATHNAME == error_create)
    return SBOX_TEST_DENIED;

  return SBOX_TEST_FAILED;
}

// Tests the creation of events using all the possible combinations.
TEST(SyncPolicyTest, DISABLED_TestEvent) {
  TestRunner runner;
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_ANY,
                             L"test1"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_ANY,
                             L"test2"));

  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f test2"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t test2"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test4"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test4"));
}

// Tests opening events with read only access.
TEST(SyncPolicyTest, DISABLED_TestEventReadOnly) {
  TestRunner runner;
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test1"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test2"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test5"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test6"));

  base::win::ScopedHandle handle1(::CreateEvent(NULL, FALSE, FALSE, L"test1"));
  base::win::ScopedHandle handle2(::CreateEvent(NULL, FALSE, FALSE, L"test2"));
  base::win::ScopedHandle handle3(::CreateEvent(NULL, FALSE, FALSE, L"test3"));
  base::win::ScopedHandle handle4(::CreateEvent(NULL, FALSE, FALSE, L"test4"));

  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_Open s test2"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open s test4"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test5"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test6"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test5"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test6"));
}

}  // namespace sandbox
<commit_msg>Sandbox: Reenable tests that were disabled "temporarily" 2 years ago.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/sync_policy_test.h"

#include "base/win/scoped_handle.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/nt_internals.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sandbox {

SBOX_TESTS_COMMAND int Event_Open(int argc, wchar_t **argv) {
  if (argc != 2)
    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;

  DWORD desired_access = SYNCHRONIZE;
  if (L'f' == argv[0][0])
    desired_access = EVENT_ALL_ACCESS;

  base::win::ScopedHandle event_open(::OpenEvent(
      desired_access, FALSE, argv[1]));
  DWORD error_open = ::GetLastError();

  if (event_open.IsValid())
    return SBOX_TEST_SUCCEEDED;

  if (ERROR_ACCESS_DENIED == error_open ||
      ERROR_BAD_PATHNAME == error_open ||
      ERROR_FILE_NOT_FOUND == error_open)
    return SBOX_TEST_DENIED;

  return SBOX_TEST_FAILED;
}

SBOX_TESTS_COMMAND int Event_CreateOpen(int argc, wchar_t **argv) {
  if (argc < 2 || argc > 3)
    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;

  wchar_t *event_name = NULL;
  if (3 == argc)
    event_name = argv[2];

  BOOL manual_reset = FALSE;
  BOOL initial_state = FALSE;
  if (L't' == argv[0][0])
    manual_reset = TRUE;
  if (L't' == argv[1][0])
    initial_state = TRUE;

  base::win::ScopedHandle event_create(::CreateEvent(
      NULL, manual_reset, initial_state, event_name));
  DWORD error_create = ::GetLastError();
  base::win::ScopedHandle event_open;
  if (event_name)
    event_open.Set(::OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name));

  if (event_create.IsValid()) {
    DWORD wait = ::WaitForSingleObject(event_create.Get(), 0);
    if (initial_state && WAIT_OBJECT_0 != wait)
      return SBOX_TEST_FAILED;

    if (!initial_state && WAIT_TIMEOUT != wait)
      return SBOX_TEST_FAILED;
  }

  if (event_name) {
    // Both event_open and event_create have to be valid.
    if (event_open.IsValid() && event_create.IsValid())
      return SBOX_TEST_SUCCEEDED;

    if ((event_open.IsValid() && !event_create.IsValid()) ||
        (!event_open.IsValid() && event_create.IsValid())) {
      return SBOX_TEST_FAILED;
    }
  } else {
    // Only event_create has to be valid.
    if (event_create.Get())
      return SBOX_TEST_SUCCEEDED;
  }

  if (ERROR_ACCESS_DENIED == error_create ||
      ERROR_BAD_PATHNAME == error_create)
    return SBOX_TEST_DENIED;

  return SBOX_TEST_FAILED;
}

// Tests the creation of events using all the possible combinations.
TEST(SyncPolicyTest, TestEvent) {
  TestRunner runner;
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_ANY,
                             L"test1"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_ANY,
                             L"test2"));

  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f test2"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t test2"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test4"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test4"));
}

// Tests opening events with read only access.
TEST(SyncPolicyTest, TestEventReadOnly) {
  TestRunner runner;
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test1"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test2"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test5"));
  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC,
                             TargetPolicy::EVENTS_ALLOW_READONLY,
                             L"test6"));

  base::win::ScopedHandle handle1(::CreateEvent(NULL, FALSE, FALSE, L"test1"));
  base::win::ScopedHandle handle2(::CreateEvent(NULL, FALSE, FALSE, L"test2"));
  base::win::ScopedHandle handle3(::CreateEvent(NULL, FALSE, FALSE, L"test3"));
  base::win::ScopedHandle handle4(::CreateEvent(NULL, FALSE, FALSE, L"test4"));

  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test1"));
  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_Open s test2"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test3"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open s test4"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test5"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test6"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test5"));
  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test6"));
}

}  // namespace sandbox
<|endoftext|>


<commit_before>/*
 *  Copyright 2004 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.
 */

#if HAVE_OPENSSL_SSL_H

#include "webrtc/base/opensslidentity.h"

// Must be included first before openssl headers.
#include "webrtc/base/win32.h"  // NOLINT

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>

#include "webrtc/base/checks.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/openssl.h"
#include "webrtc/base/openssldigest.h"

namespace rtc {

// We could have exposed a myriad of parameters for the crypto stuff,
// but keeping it simple seems best.

// Strength of generated keys. Those are RSA.
static const int KEY_LENGTH = 1024;

// Random bits for certificate serial number
static const int SERIAL_RAND_BITS = 64;

// Certificate validity lifetime
static const int CERTIFICATE_LIFETIME = 60*60*24*30;  // 30 days, arbitrarily
// Certificate validity window.
// This is to compensate for slightly incorrect system clocks.
static const int CERTIFICATE_WINDOW = -60*60*24;

// Generate a key pair. Caller is responsible for freeing the returned object.
static EVP_PKEY* MakeKey() {
  LOG(LS_INFO) << "Making key pair";
  EVP_PKEY* pkey = EVP_PKEY_new();
  // RSA_generate_key is deprecated. Use _ex version.
  BIGNUM* exponent = BN_new();
  RSA* rsa = RSA_new();
  if (!pkey || !exponent || !rsa ||
      !BN_set_word(exponent, 0x10001) ||  // 65537 RSA exponent
      !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
      !EVP_PKEY_assign_RSA(pkey, rsa)) {
    EVP_PKEY_free(pkey);
    BN_free(exponent);
    RSA_free(rsa);
    return NULL;
  }
  // ownership of rsa struct was assigned, don't free it.
  BN_free(exponent);
  LOG(LS_INFO) << "Returning key pair";
  return pkey;
}

// Generate a self-signed certificate, with the public key from the
// given key pair. Caller is responsible for freeing the returned object.
static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) {
  LOG(LS_INFO) << "Making certificate for " << params.common_name;
  X509* x509 = NULL;
  BIGNUM* serial_number = NULL;
  X509_NAME* name = NULL;

  if ((x509=X509_new()) == NULL)
    goto error;

  if (!X509_set_pubkey(x509, pkey))
    goto error;

  // serial number
  // temporary reference to serial number inside x509 struct
  ASN1_INTEGER* asn1_serial_number;
  if ((serial_number = BN_new()) == NULL ||
      !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) ||
      (asn1_serial_number = X509_get_serialNumber(x509)) == NULL ||
      !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
    goto error;

  if (!X509_set_version(x509, 0L))  // version 1
    goto error;

  // There are a lot of possible components for the name entries. In
  // our P2P SSL mode however, the certificates are pre-exchanged
  // (through the secure XMPP channel), and so the certificate
  // identification is arbitrary. It can't be empty, so we set some
  // arbitrary common_name. Note that this certificate goes out in
  // clear during SSL negotiation, so there may be a privacy issue in
  // putting anything recognizable here.
  if ((name = X509_NAME_new()) == NULL ||
      !X509_NAME_add_entry_by_NID(
          name, NID_commonName, MBSTRING_UTF8,
          (unsigned char*)params.common_name.c_str(), -1, -1, 0) ||
      !X509_set_subject_name(x509, name) ||
      !X509_set_issuer_name(x509, name))
    goto error;

  if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) ||
      !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after))
    goto error;

  if (!X509_sign(x509, pkey, EVP_sha1()))
    goto error;

  BN_free(serial_number);
  X509_NAME_free(name);
  LOG(LS_INFO) << "Returning certificate";
  return x509;

 error:
  BN_free(serial_number);
  X509_NAME_free(name);
  X509_free(x509);
  return NULL;
}

// This dumps the SSL error stack to the log.
static void LogSSLErrors(const std::string& prefix) {
  char error_buf[200];
  unsigned long err;

  while ((err = ERR_get_error()) != 0) {
    ERR_error_string_n(err, error_buf, sizeof(error_buf));
    LOG(LS_ERROR) << prefix << ": " << error_buf << "\n";
  }
}

OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
  EVP_PKEY* pkey = MakeKey();
  if (!pkey) {
    LogSSLErrors("Generating key pair");
    return NULL;
  }
  return new OpenSSLKeyPair(pkey);
}

OpenSSLKeyPair::~OpenSSLKeyPair() {
  EVP_PKEY_free(pkey_);
}

OpenSSLKeyPair* OpenSSLKeyPair::GetReference() {
  AddReference();
  return new OpenSSLKeyPair(pkey_);
}

void OpenSSLKeyPair::AddReference() {
  CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
}

#ifdef _DEBUG
// Print a certificate to the log, for debugging.
static void PrintCert(X509* x509) {
  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
  if (!temp_memory_bio) {
    LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
    return;
  }
  X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
  BIO_write(temp_memory_bio, "\0", 1);
  char* buffer;
  BIO_get_mem_data(temp_memory_bio, &buffer);
  LOG(LS_VERBOSE) << buffer;
  BIO_free(temp_memory_bio);
}
#endif

OpenSSLCertificate* OpenSSLCertificate::Generate(
    OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
  SSLIdentityParams actual_params(params);
  if (actual_params.common_name.empty()) {
    // Use a random string, arbitrarily 8chars long.
    actual_params.common_name = CreateRandomString(8);
  }
  X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
  if (!x509) {
    LogSSLErrors("Generating certificate");
    return NULL;
  }
#ifdef _DEBUG
  PrintCert(x509);
#endif
  OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
  X509_free(x509);
  return ret;
}

OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
    const std::string& pem_string) {
  BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
  if (!bio)
    return NULL;
  BIO_set_mem_eof_return(bio, 0);
  X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
                                 const_cast<char*>("\0"));
  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.

  if (!x509)
    return NULL;

  OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
  X509_free(x509);
  return ret;
}

// NOTE: This implementation only functions correctly after InitializeSSL
// and before CleanupSSL.
bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
    std::string* algorithm) const {
  return OpenSSLDigest::GetDigestName(
      EVP_get_digestbyobj(x509_->sig_alg->algorithm), algorithm);
}

bool OpenSSLCertificate::GetChain(SSLCertChain** chain) const {
  // Chains are not yet supported when using OpenSSL.
  // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote
  // certificate to be self-signed.
  return false;
}

bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
                                       unsigned char* digest,
                                       size_t size,
                                       size_t* length) const {
  return ComputeDigest(x509_, algorithm, digest, size, length);
}

bool OpenSSLCertificate::ComputeDigest(const X509* x509,
                                       const std::string& algorithm,
                                       unsigned char* digest,
                                       size_t size,
                                       size_t* length) {
  const EVP_MD *md;
  unsigned int n;

  if (!OpenSSLDigest::GetDigestEVP(algorithm, &md))
    return false;

  if (size < static_cast<size_t>(EVP_MD_size(md)))
    return false;

  X509_digest(x509, md, digest, &n);

  *length = n;

  return true;
}

OpenSSLCertificate::~OpenSSLCertificate() {
  X509_free(x509_);
}

OpenSSLCertificate* OpenSSLCertificate::GetReference() const {
  return new OpenSSLCertificate(x509_);
}

std::string OpenSSLCertificate::ToPEMString() const {
  BIO* bio = BIO_new(BIO_s_mem());
  if (!bio) {
    FATAL() << "unreachable code";
  }
  if (!PEM_write_bio_X509(bio, x509_)) {
    BIO_free(bio);
    FATAL() << "unreachable code";
  }
  BIO_write(bio, "\0", 1);
  char* buffer;
  BIO_get_mem_data(bio, &buffer);
  std::string ret(buffer);
  BIO_free(bio);
  return ret;
}

void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
  // In case of failure, make sure to leave the buffer empty.
  der_buffer->SetSize(0);

  // Calculates the DER representation of the certificate, from scratch.
  BIO* bio = BIO_new(BIO_s_mem());
  if (!bio) {
    FATAL() << "unreachable code";
  }
  if (!i2d_X509_bio(bio, x509_)) {
    BIO_free(bio);
    FATAL() << "unreachable code";
  }
  char* data;
  size_t length = BIO_get_mem_data(bio, &data);
  der_buffer->SetData(data, length);
  BIO_free(bio);
}

void OpenSSLCertificate::AddReference() const {
  ASSERT(x509_ != NULL);
  CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
}

OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair,
                                 OpenSSLCertificate* certificate)
    : key_pair_(key_pair), certificate_(certificate) {
  ASSERT(key_pair != NULL);
  ASSERT(certificate != NULL);
}

OpenSSLIdentity::~OpenSSLIdentity() = default;

OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
    const SSLIdentityParams& params) {
  OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
  if (key_pair) {
    OpenSSLCertificate *certificate = OpenSSLCertificate::Generate(
        key_pair, params);
    if (certificate)
      return new OpenSSLIdentity(key_pair, certificate);
    delete key_pair;
  }
  LOG(LS_INFO) << "Identity generation failed";
  return NULL;
}

OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
  SSLIdentityParams params;
  params.common_name = common_name;
  params.not_before = CERTIFICATE_WINDOW;
  params.not_after = CERTIFICATE_LIFETIME;
  return GenerateInternal(params);
}

OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
    const SSLIdentityParams& params) {
  return GenerateInternal(params);
}

SSLIdentity* OpenSSLIdentity::FromPEMStrings(
    const std::string& private_key,
    const std::string& certificate) {
  scoped_ptr<OpenSSLCertificate> cert(
      OpenSSLCertificate::FromPEMString(certificate));
  if (!cert) {
    LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
    return NULL;
  }

  BIO* bio = BIO_new_mem_buf(const_cast<char*>(private_key.c_str()), -1);
  if (!bio) {
    LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
    return NULL;
  }
  BIO_set_mem_eof_return(bio, 0);
  EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL,
                                           const_cast<char*>("\0"));
  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.

  if (!pkey) {
    LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
    return NULL;
  }

  return new OpenSSLIdentity(new OpenSSLKeyPair(pkey),
                             cert.release());
}

const OpenSSLCertificate& OpenSSLIdentity::certificate() const {
  return *certificate_;
}

OpenSSLIdentity* OpenSSLIdentity::GetReference() const {
  return new OpenSSLIdentity(key_pair_->GetReference(),
                             certificate_->GetReference());
}

bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
  // 1 is the documented success return code.
  if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
     SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
    LogSSLErrors("Configuring key and certificate");
    return false;
  }
  return true;
}

}  // namespace rtc

#endif  // HAVE_OPENSSL_SSL_H
<commit_msg>Fix GetSignatureDigestAlgorithm for openssl to prepare for EC key switch.<commit_after>/*
 *  Copyright 2004 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.
 */

#if HAVE_OPENSSL_SSL_H

#include "webrtc/base/opensslidentity.h"

// Must be included first before openssl headers.
#include "webrtc/base/win32.h"  // NOLINT

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>

#include "webrtc/base/checks.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/openssl.h"
#include "webrtc/base/openssldigest.h"

namespace rtc {

// We could have exposed a myriad of parameters for the crypto stuff,
// but keeping it simple seems best.

// Strength of generated keys. Those are RSA.
static const int KEY_LENGTH = 1024;

// Random bits for certificate serial number
static const int SERIAL_RAND_BITS = 64;

// Certificate validity lifetime
static const int CERTIFICATE_LIFETIME = 60*60*24*30;  // 30 days, arbitrarily
// Certificate validity window.
// This is to compensate for slightly incorrect system clocks.
static const int CERTIFICATE_WINDOW = -60*60*24;

// Generate a key pair. Caller is responsible for freeing the returned object.
static EVP_PKEY* MakeKey() {
  LOG(LS_INFO) << "Making key pair";
  EVP_PKEY* pkey = EVP_PKEY_new();
  // RSA_generate_key is deprecated. Use _ex version.
  BIGNUM* exponent = BN_new();
  RSA* rsa = RSA_new();
  if (!pkey || !exponent || !rsa ||
      !BN_set_word(exponent, 0x10001) ||  // 65537 RSA exponent
      !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
      !EVP_PKEY_assign_RSA(pkey, rsa)) {
    EVP_PKEY_free(pkey);
    BN_free(exponent);
    RSA_free(rsa);
    return NULL;
  }
  // ownership of rsa struct was assigned, don't free it.
  BN_free(exponent);
  LOG(LS_INFO) << "Returning key pair";
  return pkey;
}

// Generate a self-signed certificate, with the public key from the
// given key pair. Caller is responsible for freeing the returned object.
static X509* MakeCertificate(EVP_PKEY* pkey, const SSLIdentityParams& params) {
  LOG(LS_INFO) << "Making certificate for " << params.common_name;
  X509* x509 = NULL;
  BIGNUM* serial_number = NULL;
  X509_NAME* name = NULL;

  if ((x509=X509_new()) == NULL)
    goto error;

  if (!X509_set_pubkey(x509, pkey))
    goto error;

  // serial number
  // temporary reference to serial number inside x509 struct
  ASN1_INTEGER* asn1_serial_number;
  if ((serial_number = BN_new()) == NULL ||
      !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) ||
      (asn1_serial_number = X509_get_serialNumber(x509)) == NULL ||
      !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
    goto error;

  if (!X509_set_version(x509, 0L))  // version 1
    goto error;

  // There are a lot of possible components for the name entries. In
  // our P2P SSL mode however, the certificates are pre-exchanged
  // (through the secure XMPP channel), and so the certificate
  // identification is arbitrary. It can't be empty, so we set some
  // arbitrary common_name. Note that this certificate goes out in
  // clear during SSL negotiation, so there may be a privacy issue in
  // putting anything recognizable here.
  if ((name = X509_NAME_new()) == NULL ||
      !X509_NAME_add_entry_by_NID(
          name, NID_commonName, MBSTRING_UTF8,
          (unsigned char*)params.common_name.c_str(), -1, -1, 0) ||
      !X509_set_subject_name(x509, name) ||
      !X509_set_issuer_name(x509, name))
    goto error;

  if (!X509_gmtime_adj(X509_get_notBefore(x509), params.not_before) ||
      !X509_gmtime_adj(X509_get_notAfter(x509), params.not_after))
    goto error;

  if (!X509_sign(x509, pkey, EVP_sha1()))
    goto error;

  BN_free(serial_number);
  X509_NAME_free(name);
  LOG(LS_INFO) << "Returning certificate";
  return x509;

 error:
  BN_free(serial_number);
  X509_NAME_free(name);
  X509_free(x509);
  return NULL;
}

// This dumps the SSL error stack to the log.
static void LogSSLErrors(const std::string& prefix) {
  char error_buf[200];
  unsigned long err;

  while ((err = ERR_get_error()) != 0) {
    ERR_error_string_n(err, error_buf, sizeof(error_buf));
    LOG(LS_ERROR) << prefix << ": " << error_buf << "\n";
  }
}

OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
  EVP_PKEY* pkey = MakeKey();
  if (!pkey) {
    LogSSLErrors("Generating key pair");
    return NULL;
  }
  return new OpenSSLKeyPair(pkey);
}

OpenSSLKeyPair::~OpenSSLKeyPair() {
  EVP_PKEY_free(pkey_);
}

OpenSSLKeyPair* OpenSSLKeyPair::GetReference() {
  AddReference();
  return new OpenSSLKeyPair(pkey_);
}

void OpenSSLKeyPair::AddReference() {
  CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
}

#ifdef _DEBUG
// Print a certificate to the log, for debugging.
static void PrintCert(X509* x509) {
  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
  if (!temp_memory_bio) {
    LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
    return;
  }
  X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
  BIO_write(temp_memory_bio, "\0", 1);
  char* buffer;
  BIO_get_mem_data(temp_memory_bio, &buffer);
  LOG(LS_VERBOSE) << buffer;
  BIO_free(temp_memory_bio);
}
#endif

OpenSSLCertificate* OpenSSLCertificate::Generate(
    OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
  SSLIdentityParams actual_params(params);
  if (actual_params.common_name.empty()) {
    // Use a random string, arbitrarily 8chars long.
    actual_params.common_name = CreateRandomString(8);
  }
  X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
  if (!x509) {
    LogSSLErrors("Generating certificate");
    return NULL;
  }
#ifdef _DEBUG
  PrintCert(x509);
#endif
  OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
  X509_free(x509);
  return ret;
}

OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
    const std::string& pem_string) {
  BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
  if (!bio)
    return NULL;
  BIO_set_mem_eof_return(bio, 0);
  X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
                                 const_cast<char*>("\0"));
  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.

  if (!x509)
    return NULL;

  OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
  X509_free(x509);
  return ret;
}

// NOTE: This implementation only functions correctly after InitializeSSL
// and before CleanupSSL.
bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
    std::string* algorithm) const {
  int nid = OBJ_obj2nid(x509_->sig_alg->algorithm);
  switch (nid) {
    case NID_md5WithRSA:
    case NID_md5WithRSAEncryption:
      *algorithm = DIGEST_MD5;
      break;
    case NID_ecdsa_with_SHA1:
    case NID_dsaWithSHA1:
    case NID_dsaWithSHA1_2:
    case NID_sha1WithRSA:
    case NID_sha1WithRSAEncryption:
      *algorithm = DIGEST_SHA_1;
      break;
    case NID_ecdsa_with_SHA224:
    case NID_sha224WithRSAEncryption:
    case NID_dsa_with_SHA224:
      *algorithm = DIGEST_SHA_224;
      break;
    case NID_ecdsa_with_SHA256:
    case NID_sha256WithRSAEncryption:
    case NID_dsa_with_SHA256:
      *algorithm = DIGEST_SHA_256;
      break;
    case NID_ecdsa_with_SHA384:
    case NID_sha384WithRSAEncryption:
      *algorithm = DIGEST_SHA_384;
      break;
    case NID_ecdsa_with_SHA512:
    case NID_sha512WithRSAEncryption:
      *algorithm = DIGEST_SHA_512;
      break;
    default:
      // Unknown algorithm.  There are several unhandled options that are less
      // common and more complex.
      LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid;
      algorithm->clear();
      return false;
  }
  return true;
}

bool OpenSSLCertificate::GetChain(SSLCertChain** chain) const {
  // Chains are not yet supported when using OpenSSL.
  // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote
  // certificate to be self-signed.
  return false;
}

bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
                                       unsigned char* digest,
                                       size_t size,
                                       size_t* length) const {
  return ComputeDigest(x509_, algorithm, digest, size, length);
}

bool OpenSSLCertificate::ComputeDigest(const X509* x509,
                                       const std::string& algorithm,
                                       unsigned char* digest,
                                       size_t size,
                                       size_t* length) {
  const EVP_MD *md;
  unsigned int n;

  if (!OpenSSLDigest::GetDigestEVP(algorithm, &md))
    return false;

  if (size < static_cast<size_t>(EVP_MD_size(md)))
    return false;

  X509_digest(x509, md, digest, &n);

  *length = n;

  return true;
}

OpenSSLCertificate::~OpenSSLCertificate() {
  X509_free(x509_);
}

OpenSSLCertificate* OpenSSLCertificate::GetReference() const {
  return new OpenSSLCertificate(x509_);
}

std::string OpenSSLCertificate::ToPEMString() const {
  BIO* bio = BIO_new(BIO_s_mem());
  if (!bio) {
    FATAL() << "unreachable code";
  }
  if (!PEM_write_bio_X509(bio, x509_)) {
    BIO_free(bio);
    FATAL() << "unreachable code";
  }
  BIO_write(bio, "\0", 1);
  char* buffer;
  BIO_get_mem_data(bio, &buffer);
  std::string ret(buffer);
  BIO_free(bio);
  return ret;
}

void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
  // In case of failure, make sure to leave the buffer empty.
  der_buffer->SetSize(0);

  // Calculates the DER representation of the certificate, from scratch.
  BIO* bio = BIO_new(BIO_s_mem());
  if (!bio) {
    FATAL() << "unreachable code";
  }
  if (!i2d_X509_bio(bio, x509_)) {
    BIO_free(bio);
    FATAL() << "unreachable code";
  }
  char* data;
  size_t length = BIO_get_mem_data(bio, &data);
  der_buffer->SetData(data, length);
  BIO_free(bio);
}

void OpenSSLCertificate::AddReference() const {
  ASSERT(x509_ != NULL);
  CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
}

OpenSSLIdentity::OpenSSLIdentity(OpenSSLKeyPair* key_pair,
                                 OpenSSLCertificate* certificate)
    : key_pair_(key_pair), certificate_(certificate) {
  ASSERT(key_pair != NULL);
  ASSERT(certificate != NULL);
}

OpenSSLIdentity::~OpenSSLIdentity() = default;

OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
    const SSLIdentityParams& params) {
  OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
  if (key_pair) {
    OpenSSLCertificate *certificate = OpenSSLCertificate::Generate(
        key_pair, params);
    if (certificate)
      return new OpenSSLIdentity(key_pair, certificate);
    delete key_pair;
  }
  LOG(LS_INFO) << "Identity generation failed";
  return NULL;
}

OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
  SSLIdentityParams params;
  params.common_name = common_name;
  params.not_before = CERTIFICATE_WINDOW;
  params.not_after = CERTIFICATE_LIFETIME;
  return GenerateInternal(params);
}

OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
    const SSLIdentityParams& params) {
  return GenerateInternal(params);
}

SSLIdentity* OpenSSLIdentity::FromPEMStrings(
    const std::string& private_key,
    const std::string& certificate) {
  scoped_ptr<OpenSSLCertificate> cert(
      OpenSSLCertificate::FromPEMString(certificate));
  if (!cert) {
    LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
    return NULL;
  }

  BIO* bio = BIO_new_mem_buf(const_cast<char*>(private_key.c_str()), -1);
  if (!bio) {
    LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
    return NULL;
  }
  BIO_set_mem_eof_return(bio, 0);
  EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL,
                                           const_cast<char*>("\0"));
  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.

  if (!pkey) {
    LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
    return NULL;
  }

  return new OpenSSLIdentity(new OpenSSLKeyPair(pkey),
                             cert.release());
}

const OpenSSLCertificate& OpenSSLIdentity::certificate() const {
  return *certificate_;
}

OpenSSLIdentity* OpenSSLIdentity::GetReference() const {
  return new OpenSSLIdentity(key_pair_->GetReference(),
                             certificate_->GetReference());
}

bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
  // 1 is the documented success return code.
  if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
     SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
    LogSSLErrors("Configuring key and certificate");
    return false;
  }
  return true;
}

}  // namespace rtc

#endif  // HAVE_OPENSSL_SSL_H
<|endoftext|>


<commit_before>/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/debug/debug_grpc_testlib.h"

#include "tensorflow/core/debug/debug_graph_utils.h"
#include "tensorflow/core/debug/debug_io_utils.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/tracing.h"

namespace tensorflow {

namespace test {

::grpc::Status TestEventListenerImpl::SendEvents(
    ::grpc::ServerContext* context,
    ::grpc::ServerReaderWriter< ::tensorflow::EventReply, ::tensorflow::Event>*
        stream) {
  Event event;

  while (stream->Read(&event)) {
    const Summary::Value& val = event.summary().value(0);

    std::vector<string> name_items =
        tensorflow::str_util::Split(val.node_name(), ':');

    const string node_name = name_items[0];
    int32 output_slot = 0;
    tensorflow::strings::safe_strto32(name_items[1], &output_slot);
    const string debug_op = name_items[2];

    const TensorProto& tensor_proto = val.tensor();
    Tensor tensor(tensor_proto.dtype());
    if (!tensor.FromProto(tensor_proto)) {
      return ::grpc::Status::CANCELLED;
    }

    string dump_path;
    DebugFileIO::DumpTensorToDir(node_name, output_slot, debug_op, tensor,
                                 event.wall_time(), dump_root, &dump_path)
        .IgnoreError();
  }

  return ::grpc::Status::OK;
}

GrpcTestServerClientPair::GrpcTestServerClientPair(const int server_port)
    : server_port(server_port) {
  const int kTensorSize = 2;
  prep_tensor_.reset(
      new Tensor(DT_FLOAT, TensorShape({kTensorSize, kTensorSize})));
  for (int i = 0; i < kTensorSize * kTensorSize; ++i) {
    prep_tensor_->flat<float>()(i) = static_cast<float>(i);
  }

  // Obtain server's gRPC url.
  test_server_url = strings::StrCat("grpc://[::]:", server_port);

  // Obtain dump directory for the stream server.
  string tmp_dir = port::Tracing::LogDir();
  dump_root =
      io::JoinPath(tmp_dir, strings::StrCat("tfdbg_dump_port", server_port, "_",
                                            Env::Default()->NowMicros()));
}

bool GrpcTestServerClientPair::PollTillFirstRequestSucceeds() {
  const std::vector<string> urls({test_server_url});
  int n_attempts = 0;
  bool success = false;

  // Try a number of times to send the Event proto to the server, as it may
  // take the server a few seconds to start up and become responsive.
  while (n_attempts++ < kMaxAttempts) {
    const uint64 wall_time = Env::Default()->NowMicros();

    Status publish_s = DebugIO::PublishDebugTensor(
        "prep_node:0", "DebugIdentity", *prep_tensor_, wall_time, urls);
    Status close_s = DebugIO::CloseDebugURL(test_server_url);

    if (publish_s.ok() && close_s.ok()) {
      success = true;
      break;
    } else {
      Env::Default()->SleepForMicroseconds(kSleepDurationMicros);
    }
  }

  return success;
}

}  // namespace test

}  // namespace tensorflow
<commit_msg>Switch debug_grpc_testlib to bind on localhost<commit_after>/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/debug/debug_grpc_testlib.h"

#include "tensorflow/core/debug/debug_graph_utils.h"
#include "tensorflow/core/debug/debug_io_utils.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/tracing.h"

namespace tensorflow {

namespace test {

::grpc::Status TestEventListenerImpl::SendEvents(
    ::grpc::ServerContext* context,
    ::grpc::ServerReaderWriter< ::tensorflow::EventReply, ::tensorflow::Event>*
        stream) {
  Event event;

  while (stream->Read(&event)) {
    const Summary::Value& val = event.summary().value(0);

    std::vector<string> name_items =
        tensorflow::str_util::Split(val.node_name(), ':');

    const string node_name = name_items[0];
    int32 output_slot = 0;
    tensorflow::strings::safe_strto32(name_items[1], &output_slot);
    const string debug_op = name_items[2];

    const TensorProto& tensor_proto = val.tensor();
    Tensor tensor(tensor_proto.dtype());
    if (!tensor.FromProto(tensor_proto)) {
      return ::grpc::Status::CANCELLED;
    }

    string dump_path;
    DebugFileIO::DumpTensorToDir(node_name, output_slot, debug_op, tensor,
                                 event.wall_time(), dump_root, &dump_path)
        .IgnoreError();
  }

  return ::grpc::Status::OK;
}

GrpcTestServerClientPair::GrpcTestServerClientPair(const int server_port)
    : server_port(server_port) {
  const int kTensorSize = 2;
  prep_tensor_.reset(
      new Tensor(DT_FLOAT, TensorShape({kTensorSize, kTensorSize})));
  for (int i = 0; i < kTensorSize * kTensorSize; ++i) {
    prep_tensor_->flat<float>()(i) = static_cast<float>(i);
  }

  // Obtain server's gRPC url.
  test_server_url = strings::StrCat("grpc://localhost:", server_port);

  // Obtain dump directory for the stream server.
  string tmp_dir = port::Tracing::LogDir();
  dump_root =
      io::JoinPath(tmp_dir, strings::StrCat("tfdbg_dump_port", server_port, "_",
                                            Env::Default()->NowMicros()));
}

bool GrpcTestServerClientPair::PollTillFirstRequestSucceeds() {
  const std::vector<string> urls({test_server_url});
  int n_attempts = 0;
  bool success = false;

  // Try a number of times to send the Event proto to the server, as it may
  // take the server a few seconds to start up and become responsive.
  while (n_attempts++ < kMaxAttempts) {
    const uint64 wall_time = Env::Default()->NowMicros();

    Status publish_s = DebugIO::PublishDebugTensor(
        "prep_node:0", "DebugIdentity", *prep_tensor_, wall_time, urls);
    Status close_s = DebugIO::CloseDebugURL(test_server_url);

    if (publish_s.ok() && close_s.ok()) {
      success = true;
      break;
    } else {
      Env::Default()->SleepForMicroseconds(kSleepDurationMicros);
    }
  }

  return success;
}

}  // namespace test

}  // namespace tensorflow
<|endoftext|>


<commit_before>#include "game.h"

#define LOOKAHEAD 4
#define SACRIFICE_OPTIONS 5
#define OPPONENT_MOVES 5

using namespace std;

// globals
int sacrificeCombinations = factorial(SACRIFICE_OPTIONS) / (factorial(SACRIFICE_OPTIONS - 2) * factorial(2));
stringstream token;
char botId, opponentId;
char gameState[16][18];
int roundNum, timebank, myLiveCells, theirLiveCells;

// this just for logging time TODO: remove
auto t = chrono::steady_clock::now();

void game()
{
  string line, command;

  while (getline(cin, line))
  {
    token.clear();
    token.str(line);
    token >> command;

    if (command == "action")
      processAction();
    if (command == "update")
      processUpdate();
    if (command == "settings")
      processSettings();
  }
}

void processAction()
{
  string type, time;
  token >> type;
  token >> time;

  if (type == "move") {
    t = chrono::steady_clock::now(); // TODO: remove
    timebank = stoi(time);
    makeMove();
    chrono::duration<double> diff = chrono::steady_clock::now() - t; // TODO: remove
    cerr << diff.count() * 1000 << "ms used\n"; // TODO: remove
  } else
    cerr << "action type: " << type << " not expected\n";
}

void processUpdate()
{
  string target, field, value;
  token >> target;
  token >> field;
  token >> value;

  if (target == "game") {
    if (field == "round") {
      roundNum = stoi(value);
    }
    if (field == "field") {
      parseState(value);
    }
  } else if (target == "player0" or target == "player1") {
    if (field == "living_cells") {
      if (target[6] == botId)
        myLiveCells = stoi(value);
      else
        theirLiveCells = stoi(value);
    } else if (field != "move")
      cerr << "update playerX field: " << field << " not expected\n";
  } else
    cerr << "update target: " << target << " not expected\n";
}

void processSettings()
{
  string field, value;
  token >> field;
  token >> value;

  if (field == "player_names") {
    if (value != "player0,player1")
      cerr << "settings player_names value: " << value << " not expected\n";
  } else if (field == "your_bot") {
    if (value != "player0" and value != "player1")
      cerr << "settings your_bot value: " << value << " not expected\n";
  } else if (field == "timebank") {
    if (value == "10000")
      timebank = stoi(value);
    else
      cerr << "settings timebank value: " << value << " not expected\n";
  } else if (field == "time_per_move") {
    if (value != "100")
      cerr << "settings time_per_move value: " << value << " not expected\n";
  } else if (field == "field_width") {
    if (value != "18")
      cerr << "settings field_width value: " << value << " not expected\n";
  } else if (field == "field_height") {
    if (value != "16")
      cerr << "settings field_height value: " << value << " not expected\n";
  } else if (field == "max_rounds") {
    if (value != "100")
      cerr << "settings max_rounds value: " << value << " not expected\n";
  } else if (field == "your_botid") {
    if (value == "0") {
      botId = '0';
      opponentId = '1';
    } else if (value == "1") {
      botId = '1';
      opponentId = '0';
    }
    else
      cerr << "settings your_botid value: " << value << " not expected\n";
  } else
    cerr << "settings field: " << field << " not expected\n";
}

void parseState(const string &value)
{
  int row = 0;
  int col = 0;
  for (const char& c : value) {
    if (c != ',') {
      gameState[row][col] = c;
      if (col == 17) {
        col = 0;
        row++;
      } else {
        col++;
      }
    }
  }
}

void makeMove()
{
  int numMoves = 1 + (myLiveCells + theirLiveCells) + (sacrificeCombinations * (288 - myLiveCells - theirLiveCells));

  // TODO: handle less then n of my cells alive for birthing calcs
  node nodes[numMoves];

  addKillNodes(nodes);

  node bestKillNodes[SACRIFICE_OPTIONS];
  findBestKillNodes(nodes, bestKillNodes);

  addPassNode(nodes);

  addBirthNodes(nodes, bestKillNodes);

  // TODO: for the best n nodes, calculate opponent moves and recalculate heuristic, then pick the best of those
  // sort then slice, then 2nd round heuristic, then sort then first
  sort(nodes, nodes + numMoves, nodeCompare);

  // node bestNode = findBestNode(nodes, numMoves);
  node bestNode = nodes[0];

  sendMove(bestNode);
}

void addKillNodes(node nodes[], const char state[][18])
{
  int i = 0;
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (state[r][c] != '.') {
        node n;
        n.value = state[r][c];
        n.type = 'k';
        n.target = r * 18 + c;
        copyState(n.state);
        n.state[r][c] = '.';
        calculateNextState(n);
        calculateHeuristic(n);
        nodes[i++] = n;
      }
    }
  }
}

void findBestKillNodes(node nodes[], node bestKillNodes[])
{
  sort(nodes, nodes + myLiveCells + theirLiveCells, nodeCompare);

  int killNodeCount = 0;
  for (int i = 0; i < myLiveCells + theirLiveCells; i++) {
    node n = nodes[i];

    if (n.value == botId) {
      bestKillNodes[killNodeCount] = n;
      killNodeCount++;

      if (killNodeCount == SACRIFICE_OPTIONS) {
        break;
      }
    }
  }
}

void addPassNode(node nodes[], char state[][18], int idx)
{
  node n;
  n.type = 'p';
  copyState(n.state);
  calculateNextState(n);
  calculateHeuristic(n);
  nodes[idx] = n;
}

void addBirthNodes(node nodes[], char state[][18], const node bestKillNodes[], int idx)
{
  for (int x = 0; x < SACRIFICE_OPTIONS - 1; x++) {
    for (int y = x + 1; y < SACRIFICE_OPTIONS; y++) {
      for (int c = 0; c < 18; c++) {
        for (int r = 0; r < 16; r++) {
          if (state[r][c] == '.') {
            node n;
            n.type = 'b';
            n.target = r * 18 + c;
            n.sacrifice1 = bestKillNodes[x].target;
            n.sacrifice2 = bestKillNodes[y].target;
            copyState(n.state);
            n.state[r][c] = botId;
            n.state[n.sacrifice1 / 18][n.sacrifice1 % 18] = '.';
            n.state[n.sacrifice2 / 18][n.sacrifice2 % 18] = '.';
            calculateNextState(n);
            calculateHeuristic(n);
            nodes[idx++] = n;
          }
        }
      }
    }
  }
}

node findBestNode(const node nodes[], int nodeCount)
{
  int topHeuristic = -288;
  int topHeuristicIdx = 0;
  for (int i = 0; i < nodeCount; i++) {
    if (nodes[i].heuristicValue > topHeuristic) {
      topHeuristic = nodes[topHeuristicIdx].heuristicValue;
      topHeuristicIdx = i;
    }
  }

  return nodes[topHeuristicIdx];
}

void sendMove(const node &n)
{
  if (n.type == 'p') {
    cout << "pass\n";
  } else if (n.type == 'k') {
    cout << "kill " << coords(n.target) << "\n";
  } else if (n.type == 'b') {
    cout << "birth " << coords(n.target) << " " << coords(n.sacrifice1) << " " << coords(n.sacrifice2) << "\n";
  }
}

void calculateNextState(node &n, int lookahead)
{
  for (int l = 0; l < lookahead; l++) {
    int neighbours0[16][18];
    int neighbours1[16][18];

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours0[r][c] = 0;
        neighbours1[r][c] = 0;
      }
    }

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        if (n.state[r][c] == '0') {
          if (c > 0) {
            neighbours0[r][c - 1]++;
            if (r > 0) neighbours0[r - 1][c - 1]++;
            if (r < 15) neighbours0[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours0[r][c + 1]++;
            if (r > 0) neighbours0[r - 1][c + 1]++;
            if (r < 15) neighbours0[r + 1][c + 1]++;
          }
          if (r > 0) neighbours0[r - 1][c]++;
          if (r < 15) neighbours0[r + 1][c]++;
        }
        if (n.state[r][c] == '1') {
          if (c > 0) {
            neighbours1[r][c - 1]++;
            if (r > 0) neighbours1[r - 1][c - 1]++;
            if (r < 15) neighbours1[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours1[r][c + 1]++;
            if (r > 0) neighbours1[r - 1][c + 1]++;
            if (r < 15) neighbours1[r + 1][c + 1]++;
          }
          if (r > 0) neighbours1[r - 1][c]++;
          if (r < 15) neighbours1[r + 1][c]++;
        }
      }
    }

    int neighbours;
    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours = neighbours0[r][c] + neighbours1[r][c];
        if (n.state[r][c] == '.' and neighbours == 3) {
          n.state[r][c] = (neighbours0[r][c] > neighbours1[r][c]) ?  '0' : '1';
        } else if (n.state[r][c] != '.' and (neighbours < 2 or neighbours > 3)) {
          n.state[r][c] = '.';
        }
      }
    }
  }
}

void calculateHeuristic(node &n)
{
  int cellCount0 = 0;
  int cellCount1 = 0;

  // TODO: consider the number of opponent cells alive to increase aggression when they are low
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (n.state[r][c] == '0') {
        cellCount0++;
      } else if (n.state[r][c] == '1') {
        cellCount1++;
      }
    }
  }

  if (botId == '0') {
    if (cellCount0 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount1 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount0 - cellCount1;
    }
  } else if (botId == '1') {
    if (cellCount1 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount0 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount1 - cellCount0;
    }
  }
}

// utility functions
int factorial(int x, int result) {
  return (x == 1) ? result : factorial(x - 1, x * result);
}

string coords(int cellIdx)
{
  stringstream ss;
  ss << (cellIdx % 18) << "," << cellIdx / 18;
  return ss.str();
}

void copyState(const char source[][18], char target[][18])
{
  for (int r = 0; r < 16; r++) {
    for (int c = 0; c < 18; c++) {
      target[r][c] = source[r][c];
    }
  }
}

bool nodeCompare(node lhs, node rhs)
{
  // sort descending
  return lhs.heuristicValue > rhs.heuristicValue;
}

// debug functions
void setBotId(const char id)
{
  botId = id;
}
<commit_msg>findBestKillNodes takes an id<commit_after>#include "game.h"

#define LOOKAHEAD 4
#define SACRIFICE_OPTIONS 5
#define OPPONENT_MOVES 5

using namespace std;

// globals
int sacrificeCombinations = factorial(SACRIFICE_OPTIONS) / (factorial(SACRIFICE_OPTIONS - 2) * factorial(2));
stringstream token;
char botId, opponentId;
char gameState[16][18];
int roundNum, timebank, myLiveCells, theirLiveCells;

// this just for logging time TODO: remove
auto t = chrono::steady_clock::now();

void game()
{
  string line, command;

  while (getline(cin, line))
  {
    token.clear();
    token.str(line);
    token >> command;

    if (command == "action")
      processAction();
    if (command == "update")
      processUpdate();
    if (command == "settings")
      processSettings();
  }
}

void processAction()
{
  string type, time;
  token >> type;
  token >> time;

  if (type == "move") {
    t = chrono::steady_clock::now(); // TODO: remove
    timebank = stoi(time);
    makeMove();
    chrono::duration<double> diff = chrono::steady_clock::now() - t; // TODO: remove
    cerr << diff.count() * 1000 << "ms used\n"; // TODO: remove
  } else
    cerr << "action type: " << type << " not expected\n";
}

void processUpdate()
{
  string target, field, value;
  token >> target;
  token >> field;
  token >> value;

  if (target == "game") {
    if (field == "round") {
      roundNum = stoi(value);
    }
    if (field == "field") {
      parseState(value);
    }
  } else if (target == "player0" or target == "player1") {
    if (field == "living_cells") {
      if (target[6] == botId)
        myLiveCells = stoi(value);
      else
        theirLiveCells = stoi(value);
    } else if (field != "move")
      cerr << "update playerX field: " << field << " not expected\n";
  } else
    cerr << "update target: " << target << " not expected\n";
}

void processSettings()
{
  string field, value;
  token >> field;
  token >> value;

  if (field == "player_names") {
    if (value != "player0,player1")
      cerr << "settings player_names value: " << value << " not expected\n";
  } else if (field == "your_bot") {
    if (value != "player0" and value != "player1")
      cerr << "settings your_bot value: " << value << " not expected\n";
  } else if (field == "timebank") {
    if (value == "10000")
      timebank = stoi(value);
    else
      cerr << "settings timebank value: " << value << " not expected\n";
  } else if (field == "time_per_move") {
    if (value != "100")
      cerr << "settings time_per_move value: " << value << " not expected\n";
  } else if (field == "field_width") {
    if (value != "18")
      cerr << "settings field_width value: " << value << " not expected\n";
  } else if (field == "field_height") {
    if (value != "16")
      cerr << "settings field_height value: " << value << " not expected\n";
  } else if (field == "max_rounds") {
    if (value != "100")
      cerr << "settings max_rounds value: " << value << " not expected\n";
  } else if (field == "your_botid") {
    if (value == "0") {
      botId = '0';
      opponentId = '1';
    } else if (value == "1") {
      botId = '1';
      opponentId = '0';
    }
    else
      cerr << "settings your_botid value: " << value << " not expected\n";
  } else
    cerr << "settings field: " << field << " not expected\n";
}

void parseState(const string &value)
{
  int row = 0;
  int col = 0;
  for (const char& c : value) {
    if (c != ',') {
      gameState[row][col] = c;
      if (col == 17) {
        col = 0;
        row++;
      } else {
        col++;
      }
    }
  }
}

void makeMove()
{
  int numMoves = 1 + (myLiveCells + theirLiveCells) + (sacrificeCombinations * (288 - myLiveCells - theirLiveCells));

  // TODO: handle less then n of my cells alive for birthing calcs
  node nodes[numMoves];

  addKillNodes(nodes);

  node bestKillNodes[SACRIFICE_OPTIONS];
  findBestKillNodes(nodes, bestKillNodes);

  addPassNode(nodes);

  addBirthNodes(nodes, bestKillNodes);

  // TODO: for the best n nodes, calculate opponent moves and recalculate heuristic, then pick the best of those
  // sort then slice, then 2nd round heuristic, then sort then first
  sort(nodes, nodes + numMoves, nodeCompare);

  // node bestNode = findBestNode(nodes, numMoves);
  node bestNode = nodes[0];

  sendMove(bestNode);
}

void addKillNodes(node nodes[], const char state[][18])
{
  int i = 0;
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (state[r][c] != '.') {
        node n;
        n.value = state[r][c];
        n.type = 'k';
        n.target = r * 18 + c;
        copyState(n.state);
        n.state[r][c] = '.';
        calculateNextState(n);
        calculateHeuristic(n);
        nodes[i++] = n;
      }
    }
  }
}

void findBestKillNodes(node nodes[], char id, node bestKillNodes[])
{
  int killNodeCount = 0;
  for (int i = 0; i < myLiveCells + theirLiveCells; i++) {
    node n = nodes[i];

    if (n.value == id) {
      bestKillNodes[killNodeCount] = n;
      killNodeCount++;

      if (killNodeCount == SACRIFICE_OPTIONS) {
        break;
      }
    }
  }
}

void addPassNode(node nodes[], char state[][18], int idx)
{
  node n;
  n.type = 'p';
  copyState(n.state);
  calculateNextState(n);
  calculateHeuristic(n);
  nodes[idx] = n;
}

void addBirthNodes(node nodes[], char state[][18], const node bestKillNodes[], int idx)
{
  for (int x = 0; x < SACRIFICE_OPTIONS - 1; x++) {
    for (int y = x + 1; y < SACRIFICE_OPTIONS; y++) {
      for (int c = 0; c < 18; c++) {
        for (int r = 0; r < 16; r++) {
          if (state[r][c] == '.') {
            node n;
            n.type = 'b';
            n.target = r * 18 + c;
            n.sacrifice1 = bestKillNodes[x].target;
            n.sacrifice2 = bestKillNodes[y].target;
            copyState(n.state);
            n.state[r][c] = botId;
            n.state[n.sacrifice1 / 18][n.sacrifice1 % 18] = '.';
            n.state[n.sacrifice2 / 18][n.sacrifice2 % 18] = '.';
            calculateNextState(n);
            calculateHeuristic(n);
            nodes[idx++] = n;
          }
        }
      }
    }
  }
}

node findBestNode(const node nodes[], int nodeCount)
{
  int topHeuristic = -288;
  int topHeuristicIdx = 0;
  for (int i = 0; i < nodeCount; i++) {
    if (nodes[i].heuristicValue > topHeuristic) {
      topHeuristic = nodes[topHeuristicIdx].heuristicValue;
      topHeuristicIdx = i;
    }
  }

  return nodes[topHeuristicIdx];
}

void sendMove(const node &n)
{
  if (n.type == 'p') {
    cout << "pass\n";
  } else if (n.type == 'k') {
    cout << "kill " << coords(n.target) << "\n";
  } else if (n.type == 'b') {
    cout << "birth " << coords(n.target) << " " << coords(n.sacrifice1) << " " << coords(n.sacrifice2) << "\n";
  }
}

void calculateNextState(node &n, int lookahead)
{
  for (int l = 0; l < lookahead; l++) {
    int neighbours0[16][18];
    int neighbours1[16][18];

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours0[r][c] = 0;
        neighbours1[r][c] = 0;
      }
    }

    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        if (n.state[r][c] == '0') {
          if (c > 0) {
            neighbours0[r][c - 1]++;
            if (r > 0) neighbours0[r - 1][c - 1]++;
            if (r < 15) neighbours0[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours0[r][c + 1]++;
            if (r > 0) neighbours0[r - 1][c + 1]++;
            if (r < 15) neighbours0[r + 1][c + 1]++;
          }
          if (r > 0) neighbours0[r - 1][c]++;
          if (r < 15) neighbours0[r + 1][c]++;
        }
        if (n.state[r][c] == '1') {
          if (c > 0) {
            neighbours1[r][c - 1]++;
            if (r > 0) neighbours1[r - 1][c - 1]++;
            if (r < 15) neighbours1[r + 1][c - 1]++;
          }
          if (c < 17) {
            neighbours1[r][c + 1]++;
            if (r > 0) neighbours1[r - 1][c + 1]++;
            if (r < 15) neighbours1[r + 1][c + 1]++;
          }
          if (r > 0) neighbours1[r - 1][c]++;
          if (r < 15) neighbours1[r + 1][c]++;
        }
      }
    }

    int neighbours;
    for (int c = 0; c < 18; c++) {
      for (int r = 0; r < 16; r++) {
        neighbours = neighbours0[r][c] + neighbours1[r][c];
        if (n.state[r][c] == '.' and neighbours == 3) {
          n.state[r][c] = (neighbours0[r][c] > neighbours1[r][c]) ?  '0' : '1';
        } else if (n.state[r][c] != '.' and (neighbours < 2 or neighbours > 3)) {
          n.state[r][c] = '.';
        }
      }
    }
  }
}

void calculateHeuristic(node &n)
{
  int cellCount0 = 0;
  int cellCount1 = 0;

  // TODO: consider the number of opponent cells alive to increase aggression when they are low
  for (int c = 0; c < 18; c++) {
    for (int r = 0; r < 16; r++) {
      if (n.state[r][c] == '0') {
        cellCount0++;
      } else if (n.state[r][c] == '1') {
        cellCount1++;
      }
    }
  }

  if (botId == '0') {
    if (cellCount0 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount1 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount0 - cellCount1;
    }
  } else if (botId == '1') {
    if (cellCount1 == 0) {
      n.heuristicValue = -288;
    } else if (cellCount0 == 0) {
      n.heuristicValue = 288;
    } else {
      n.heuristicValue = cellCount1 - cellCount0;
    }
  }
}

// utility functions
int factorial(int x, int result) {
  return (x == 1) ? result : factorial(x - 1, x * result);
}

string coords(int cellIdx)
{
  stringstream ss;
  ss << (cellIdx % 18) << "," << cellIdx / 18;
  return ss.str();
}

void copyState(const char source[][18], char target[][18])
{
  for (int r = 0; r < 16; r++) {
    for (int c = 0; c < 18; c++) {
      target[r][c] = source[r][c];
    }
  }
}

bool nodeCompare(node lhs, node rhs)
{
  // sort descending
  return lhs.heuristicValue > rhs.heuristicValue;
}

// debug functions
void setBotId(const char id)
{
  botId = id;
}
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"
#include "../control.h"

using namespace std;
using namespace cv;

void detect_lines(Mat &original_frame, double scale_factor);

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list);

#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"

void line_main() {
//  printf("Hello, this is Caleb\n");
//  no this is patric

  VideoCapture cap("../../tests/videos/top_down_1.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

//  Mat edges;
  for (; ;) {
    Mat frame;
    cap >> frame; // get a new frame from camera

    detect_lines(frame, .2);

    if (waitKey(30) >= 0) break;

  }
  // the camera will be deinitialized automatically in VideoCapture destructor

  return;
}

#pragma clang diagnostic pop

void detect_lines(Mat &original_frame, double scale_factor) {

  Mat hsv;
  Mat mask;
  Mat image;

  // resize(original_frame, image, Size(), scale_factor, scale_factor); //Potentially scale down the frame

  cvtColor(original_frame, hsv, CV_BGR2HSV); // Image is now HSV

  double minH = 50;
  double minS = 20;
  double minV = 150;
  double maxH = 125;
  double maxS = 100;
  double maxV = 255;

  Scalar lower(minH, minS, minV);
  Scalar upper(maxH, maxS, maxV);
  inRange(hsv, lower, upper, mask); // Create a mask of only the desired color
  Canny(mask, mask, 50, 200, 3);

  vector<Vec2f> lines, condensed, tmp_list;
  HoughLines(mask, lines, 1, CV_PI / 180, 100, 0, 0);
//  HoughLinesP(mask, lines, 1, CV_PI / 180.0, 10, 50, 10); // Find all lines in the image

  printf("Adding in %d lines\n", (int) lines.size());

  //Flipping any backwards lines
  for (int i = 0; i < lines.size(); i++) {
    if (lines[i][1] > CV_PI / 2) {
      lines[i][1] -= CV_PI;
      lines[i][0] *= -1;
    }
    else if (lines[i][1] < ((CV_PI / 2) * -1)) {
      lines[i][1] += CV_PI;
      lines[i][0] *= -1;
    }

    //put in order of theta, rho
    swap(lines[i][0], lines[i][1]);
  }

  //Order from least to greatest theta
  std::sort(lines.begin(), lines.end(),
            [](const Vec2f &a, const Vec2f &b) {
              return a[0] < b[0];
            });

  while (!lines.empty()) {
    Vec2f to_manipulate = lines.front();
    lines.erase(lines.begin());

    if (tmp_list.empty()) {
      tmp_list.push_back(to_manipulate);
      continue;
    } else {
      if (abs(to_manipulate[0] - tmp_list.front()[0]) < 20 * (CV_PI / 180.0)) {
        //The angles are similar
        if (abs(to_manipulate[1] - tmp_list.front()[1]) < 50) {
          //the distances are similar
          tmp_list.push_back(to_manipulate);
          continue;
        }
      } else {
        //Need to clear out the tmp_list
        compress_lines(condensed, tmp_list);

        tmp_list.clear();
        tmp_list.push_back(to_manipulate);

      }
    }
  }
  if (!tmp_list.empty()) {
    compress_lines(condensed, tmp_list);
  }

  printf("Compressed down to %d lines\n", (int) condensed.size());

  // Undoing work:
  // condensed = lines;

  for (size_t i = 0; i < condensed.size(); i++) {
    float theta = condensed[i][0], rho = condensed[i][1];
    // float rho = lines[i][0], theta = lines[i][1];
    Point pt1, pt2;
    double a = cos(theta), b = sin(theta);
    double x0 = a * rho, y0 = b * rho;
    pt1.x = cvRound(x0 + 1000 * (-b));
    pt1.y = cvRound(y0 + 1000 * (a));
    pt2.x = cvRound(x0 - 1000 * (-b));
    pt2.y = cvRound(y0 - 1000 * (a));
    line(original_frame, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
  }

//  imshow("line_window", image);
  // resize(image, original_frame, Size(), 1 / scale_factor, 1 / scale_factor);
  // original_frame = image;
}

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list) {
  Vec2f new_point;
  float angle_sum = 0;
  float rho_sum = 0;
  for (int j = 0; j < tmp_list.size(); ++j) {
    angle_sum += tmp_list[j][0];
    rho_sum += tmp_list[j][1];
  }
  angle_sum /= tmp_list.size();
  rho_sum /= tmp_list.size();

  new_point[0] = angle_sum;
  new_point[1] = rho_sum;

  condensed.push_back(new_point);
}

LineFollowing::LineFollowing(Control *control) {
  namedWindow("line_window", CV_WINDOW_NORMAL);
  control_ptr = control;
  return;
}

void LineFollowing::close() {
  return;
}

void LineFollowing::fly() {

  control_ptr->velocities.vx = 0;
  control_ptr->velocities.vy = 0;
  control_ptr->velocities.vz = 0;
  control_ptr->velocities.vr = 0;

  detect_lines(control_ptr->image, 1);

  return;
}
<commit_msg>refactoring<commit_after>/*

*/

#include "lineFollowing.h"
#include "../control.h"

using namespace std;
using namespace cv;

void detect_lines(Mat &original_frame, double scale_factor);

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list);

void draw_lines(const Mat &image, const vector<Vec2f> &lines);

vector<Vec2f> condense_lines(vector<Vec2f> &lines);

#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"

void line_main() {
//  printf("Hello, this is Caleb\n");
//  no this is patric

  VideoCapture cap("../../tests/videos/top_down_1.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

//  Mat edges;
  for (; ;) {
    Mat frame;
    cap >> frame; // get a new frame from camera

    detect_lines(frame, .2);

    if (waitKey(30) >= 0) break;

  }
  // the camera will be deinitialized automatically in VideoCapture destructor

  return;
}

#pragma clang diagnostic pop

void detect_lines(Mat &original_frame, double scale_factor) {

  Mat hsv;
  Mat mask;
  Mat image;

  // resize(original_frame, image, Size(), scale_factor, scale_factor); //Potentially scale down the frame

  cvtColor(original_frame, hsv, CV_BGR2HSV); // Image is now HSV

  double minH = 50;
  double minS = 20;
  double minV = 150;
  double maxH = 125;
  double maxS = 100;
  double maxV = 255;

  Scalar lower(minH, minS, minV);
  Scalar upper(maxH, maxS, maxV);
  inRange(hsv, lower, upper, mask); // Create a mask of only the desired color
  Canny(mask, mask, 50, 200, 3);

  vector<Vec2f> lines;
  HoughLines(mask, lines, 1, CV_PI / 180, 100, 0, 0);
//  HoughLinesP(mask, lines, 1, CV_PI / 180.0, 10, 50, 10); // Find all lines in the image

  printf("Adding in %d lines\n", (int) lines.size());

  //Flipping any backwards lines
  vector<Vec2f> condensed = condense_lines(lines);

  //  printf("Compressed down to %d lines\n", (int) condensed.size());

  draw_lines(original_frame, condensed);

}

vector<Vec2f> condense_lines(vector<Vec2f> lines) {
  vector<Vec2f> condensed;
  vector<Vec2f> tmp_list;
  for (int i = 0; i < lines.size(); i++) {
    if (lines[i][1] > CV_PI / 2) {
      lines[i][1] -= CV_PI;
      lines[i][0] *= -1;
    }
    else if (lines[i][1] < ((CV_PI / 2) * -1)) {
      lines[i][1] += CV_PI;
      lines[i][0] *= -1;
    }

    //put in order of theta, rho
    swap(lines[i][0], lines[i][1]);
  }

  //Order from least to greatest theta
  sort(lines.begin(), lines.end(),
       [](const Vec2f &a, const Vec2f &b) {
         return a[0] < b[0];
       });

  while (!lines.empty()) {
    Vec2f to_manipulate = lines.front();
    lines.erase(lines.begin());

    if (tmp_list.empty()) {
      tmp_list.push_back(to_manipulate);
      continue;
    } else {
      if (abs(to_manipulate[0] - tmp_list.front()[0]) < 20 * (CV_PI / 180.0)) {
        //The angles are similar
        if (abs(to_manipulate[1] - tmp_list.front()[1]) < 50) {
          //the distances are similar
          tmp_list.push_back(to_manipulate);
          continue;
        }
      } else {
        //Need to clear out the tmp_list
        compress_lines(condensed, tmp_list);

        tmp_list.clear();
        tmp_list.push_back(to_manipulate);

      }
    }
  }
  if (!tmp_list.empty()) {
    compress_lines(condensed, tmp_list);
  }
  return condensed;
}

void draw_lines(const Mat &image, const vector<Vec2f> &lines) {
  for (size_t i = 0; i < lines.size(); i++) {
    float theta = lines[i][0], rho = lines[i][1];
    // float rho = lines[i][0], theta = lines[i][1];
    Point pt1, pt2;
    double a = cos(theta), b = sin(theta);
    double x0 = a * rho, y0 = b * rho;
    pt1.x = cvRound(x0 + 1000 * (-b));
    pt1.y = cvRound(y0 + 1000 * (a));
    pt2.x = cvRound(x0 - 1000 * (-b));
    pt2.y = cvRound(y0 - 1000 * (a));
    line(image, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
  }
}

void compress_lines(vector<Vec2f> &condensed, const vector<Vec2f> &tmp_list) {
  Vec2f new_point;
  float angle_sum = 0;
  float rho_sum = 0;
  for (int j = 0; j < tmp_list.size(); ++j) {
    angle_sum += tmp_list[j][0];
    rho_sum += tmp_list[j][1];
  }
  angle_sum /= tmp_list.size();
  rho_sum /= tmp_list.size();

  new_point[0] = angle_sum;
  new_point[1] = rho_sum;

  condensed.push_back(new_point);
}

LineFollowing::LineFollowing(Control *control) {
  namedWindow("line_window", CV_WINDOW_NORMAL);
  control_ptr = control;
  return;
}

void LineFollowing::close() {
  return;
}

void LineFollowing::fly() {

  control_ptr->velocities.vx = 0;
  control_ptr->velocities.vy = 0;
  control_ptr->velocities.vz = 0;
  control_ptr->velocities.vr = 0;

  detect_lines(control_ptr->image, 1);

  return;
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospray
#include "Library.h"
// std

#ifdef _WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#else
#  include <dlfcn.h>
#endif

namespace ospray {

  std::vector<Library*> loadedLibs;

  void  loadLibrary(const std::string &_name)
  {
#ifdef OSPRAY_TARGET_MIC
    std::string name = _name+"_mic";
#else
    std::string name = _name;
#endif

    for (int i=0;i<loadedLibs.size();i++)
      if (loadedLibs[i]->name == name)
        // lib already loaded.
        return;

    Library *lib = new Library;
    lib->name = name;
    lib->lib = embree::openLibrary(name);
    if (lib->lib == NULL)
      throw std::runtime_error("could not open module lib "+name);

    loadedLibs.push_back(lib);
  }
  void *getSymbol(const std::string &name)
  {
    for (int i=0;i<loadedLibs.size();i++) {
      void *sym = embree::getSymbol(loadedLibs[i]->lib, name);
      if (sym) return sym;
    }

    // if none found in the loaded libs, try the default lib ...
#ifdef _WIN32
    void *sym = GetProcAddress(GetModuleHandle(0), name.c_str());
#else
    void *sym = dlsym(RTLD_DEFAULT,name.c_str());
#endif
    return sym;
  }

} // ::ospray
<commit_msg>Also search in ospray.dll for symbols<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospray
#include "Library.h"
// std

#ifdef _WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#else
#  include <dlfcn.h>
#endif

namespace ospray {

  std::vector<Library*> loadedLibs;

  void  loadLibrary(const std::string &_name)
  {
#ifdef OSPRAY_TARGET_MIC
    std::string name = _name+"_mic";
#else
    std::string name = _name;
#endif

    for (int i=0;i<loadedLibs.size();i++)
      if (loadedLibs[i]->name == name)
        // lib already loaded.
        return;

    Library *lib = new Library;
    lib->name = name;
    lib->lib = embree::openLibrary(name);
    if (lib->lib == NULL)
      throw std::runtime_error("could not open module lib "+name);

    loadedLibs.push_back(lib);
  }
  void *getSymbol(const std::string &name)
  {
    for (int i=0;i<loadedLibs.size();i++) {
      void *sym = embree::getSymbol(loadedLibs[i]->lib, name);
      if (sym) return sym;
    }

    // if none found in the loaded libs, try the default lib ...
#ifdef _WIN32
    void *sym = GetProcAddress(GetModuleHandle(0), name.c_str()); // look in exe (i.e. when linked statically)
    if (!sym) {
      MEMORY_BASIC_INFORMATION mbi;
      VirtualQuery(getSymbol, &mbi, sizeof(mbi)); // get handle to current dll via a known function
      sym = GetProcAddress((HINSTANCE)(mbi.AllocationBase), name.c_str()); // look in ospray.dll (i.e. when linked dynamically)
    }
#else
    void *sym = dlsym(RTLD_DEFAULT,name.c_str());
#endif
    return sym;
  }

} // ::ospray
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
  Mat edges;
  for (; ;) {
    Mat frame, mask;
    cap >> frame; // get a new frame from camera
    cvtColor(frame, edges, CV_BGR2HSV);

    Scalar low, high;
    low = Scalar(30, 0, 240);
    high = Scalar(80, 70, 255);

    inRange(frame, low, high, mask);

    vector <Vec4i> lines;
    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    for (size_t i = 0; i < lines.size(); i++) {
      cout << "adding a line\n";
      Vec4i l = lines[i];
      line(frame, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", frame);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<commit_msg>first attempt at lines<commit_after>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("../../tests/videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("edges", CV_WINDOW_NORMAL);
  Mat edges;
  for (; ;) {
    Mat frame, mask;
    cap >> frame; // get a new frame from camera
    cvtColor(frame, edges, CV_BGR2HSV);

    Scalar low, high;
    low = Scalar(30, 0, 240);
    high = Scalar(80, 70, 255);

    inRange(frame, low, high, mask);

    vector <Vec4i> lines;
    HoughLinesP(mask, lines, 1, CV_PI / 180, 100, 100, 10);

    for (size_t i = 0; i < lines.size(); i++) {
      cout << "adding a line\n";
      Vec4i l = lines[i];
      line(frame, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
    }

    imshow("edges", mask);
    if (waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<|endoftext|>


<commit_before>// $Id$

/*
Copyright (c) 2007-2009, Trustees of The Leland Stanford Junior University
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the Stanford University nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// ----------------------------------------------------------------------
//
//  SeparableAllocator: Separable Allocator
//
// ----------------------------------------------------------------------

#ifndef _SEPARABLE_HPP_
#define _SEPARABLE_HPP_

#include "allocator.hpp"
#include "arbiter.hpp"
#include <cassert>

#include <vector>

class SeparableAllocator : public Allocator {

protected:

  vector<int> _matched ;

  vector<Arbiter*> _input_arb ;
  vector<Arbiter*> _output_arb ;

  vector<vector<sRequest> > _requests ;

public:

  SeparableAllocator( Module* parent, const string& name, int inputs,
		      int outputs, const string& arb_type ) ;

  virtual ~SeparableAllocator() ;

  //
  // Allocator Interface
  //
  virtual void Clear() ;
  virtual int  ReadRequest( int in, int out ) const ;
  virtual bool ReadRequest( sRequest& req, int in, int out ) const ;
  virtual void AddRequest( int in, int out, int label = 1,
			   int in_pri = 0, int out_pri = 0 ) ;
  virtual void RemoveRequest( int in, int out, int label = 1 ) ;
  virtual void Allocate() = 0 ;
  virtual void PrintRequests( ostream * os = NULL ) const ;

} ;

#endif
<commit_msg>remove unused member variable<commit_after>// $Id$

/*
Copyright (c) 2007-2009, Trustees of The Leland Stanford Junior University
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the Stanford University nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// ----------------------------------------------------------------------
//
//  SeparableAllocator: Separable Allocator
//
// ----------------------------------------------------------------------

#ifndef _SEPARABLE_HPP_
#define _SEPARABLE_HPP_

#include "allocator.hpp"
#include "arbiter.hpp"
#include <cassert>

#include <vector>

class SeparableAllocator : public Allocator {

protected:

  vector<Arbiter*> _input_arb ;
  vector<Arbiter*> _output_arb ;

  vector<vector<sRequest> > _requests ;

public:

  SeparableAllocator( Module* parent, const string& name, int inputs,
		      int outputs, const string& arb_type ) ;

  virtual ~SeparableAllocator() ;

  //
  // Allocator Interface
  //
  virtual void Clear() ;
  virtual int  ReadRequest( int in, int out ) const ;
  virtual bool ReadRequest( sRequest& req, int in, int out ) const ;
  virtual void AddRequest( int in, int out, int label = 1,
			   int in_pri = 0, int out_pri = 0 ) ;
  virtual void RemoveRequest( int in, int out, int label = 1 ) ;
  virtual void Allocate() = 0 ;
  virtual void PrintRequests( ostream * os = NULL ) const ;

} ;

#endif
<|endoftext|>