<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2011 New Dream Network
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#define LARGE_SIZE 8192

#include "assert.h"
#include "Formatter.h"
#include "common/escape.h"

#include <inttypes.h>
#include <iostream>
#include <sstream>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

// -----------------------
namespace ceph {

Formatter::Formatter()
{
}

Formatter::~Formatter()
{
}

// -----------------------
JSONFormatter::JSONFormatter(bool p)
  : m_pretty(p), m_is_pending_string(false)
{
  reset();
}

void JSONFormatter::flush(std::ostream& os)
{
  finish_pending_string();
  os << m_ss.str();
  m_ss.clear();
  m_ss.str("");
}

void JSONFormatter::reset()
{
  m_stack.clear();
  m_ss.clear();
  m_ss.str("");
  m_pending_string.clear();
  m_pending_string.str("");
}

void JSONFormatter::print_comma(json_formatter_stack_entry_d& entry)
{
  if (entry.size) {
    if (m_pretty) {
      m_ss << ",\n";
      for (unsigned i=1; i < m_stack.size(); i++)
	m_ss << "    ";
    } else {
      m_ss << ",";
    }
  } else if (entry.is_array && m_pretty) {
    m_ss << "\n";
    for (unsigned i=1; i < m_stack.size(); i++)
      m_ss << "    ";
  }
  if (m_pretty && entry.is_array)
    m_ss << "    ";
}

void JSONFormatter::print_quoted_string(const char *s)
{
  int len = escape_json_attr_len(s);
  char *escaped = (char*)malloc(len);
  escape_json_attr(s, escaped);
  m_ss << '\"' << escaped << '\"';
  free(escaped);
}

void JSONFormatter::print_name(const char *name)
{
  finish_pending_string();
  if (m_stack.empty())
    return;
  struct json_formatter_stack_entry_d& entry = m_stack.back();
  print_comma(entry);
  if (!entry.is_array) {
    if (m_pretty) {
      if (entry.size)
	m_ss << "  ";
      else
	m_ss << " ";
    }
    m_ss << "\"" << name << "\"";
    if (m_pretty)
      m_ss << ": ";
    else
      m_ss << ':';
  }
  ++entry.size;
}

void JSONFormatter::open_section(const char *name, bool is_array)
{
  print_name(name);
  if (is_array)
    m_ss << '[';
  else
    m_ss << '{';

  json_formatter_stack_entry_d n;
  n.is_array = is_array;
  m_stack.push_back(n);
}

void JSONFormatter::open_array_section(const char *name)
{
  open_section(name, true);
}

void JSONFormatter::open_array_section_in_ns(const char *name, const char *ns)
{
  std::ostringstream oss;
  oss << name << " " << ns;
  open_section(oss.str().c_str(), true);
}

void JSONFormatter::open_object_section(const char *name)
{
  open_section(name, false);
}

void JSONFormatter::open_object_section_in_ns(const char *name, const char *ns)
{
  std::ostringstream oss;
  oss << name << " " << ns;
  open_section(oss.str().c_str(), false);
}

void JSONFormatter::close_section()
{
  assert(!m_stack.empty());
  finish_pending_string();

  struct json_formatter_stack_entry_d& entry = m_stack.back();
  m_ss << (entry.is_array ? ']' : '}');
  m_stack.pop_back();
}

void JSONFormatter::finish_pending_string()
{
  if (m_is_pending_string) {
    print_quoted_string(m_pending_string.str().c_str());
    m_pending_string.str(std::string());
    m_is_pending_string = false;
  }
}

void JSONFormatter::dump_unsigned(const char *name, uint64_t u)
{
  print_name(name);
  m_ss << u;
}

void JSONFormatter::dump_int(const char *name, int64_t s)
{
  print_name(name);
  m_ss << s;
}

void JSONFormatter::dump_float(const char *name, double d)
{
  char foo[30];
  snprintf(foo, sizeof(foo), "%lf", d);
  dump_string(name, foo);
}

void JSONFormatter::dump_string(const char *name, std::string s)
{
  print_name(name);
  print_quoted_string(s.c_str());
}

std::ostream& JSONFormatter::dump_stream(const char *name)
{
  print_name(name);
  m_is_pending_string = true;
  return m_pending_string;
}

void JSONFormatter::dump_format(const char *name, const char *fmt, ...)
{
  char buf[LARGE_SIZE];
  va_list ap;
  va_start(ap, fmt);
  vsnprintf(buf, LARGE_SIZE, fmt, ap);
  va_end(ap);

  print_name(name);
  print_quoted_string(buf);
}

int JSONFormatter::get_len() const
{
  return m_ss.str().size();
}

void JSONFormatter::write_raw_data(const char *data)
{
  m_ss << data;
}

const char *XMLFormatter::XML_1_DTD =
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

XMLFormatter::XMLFormatter(bool pretty)
  : m_pretty(pretty)
{
  reset();
}

void XMLFormatter::flush(std::ostream& os)
{
  finish_pending_string();
  os << m_ss.str();
  m_ss.clear();
  m_ss.str("");
}

void XMLFormatter::reset()
{
  m_ss.clear();
  m_ss.str("");
  m_pending_string.clear();
  m_pending_string.str("");
  m_sections.clear();
  m_pending_string_name.clear();
}

void XMLFormatter::open_object_section(const char *name)
{
  open_section_in_ns(name, NULL);
}

void XMLFormatter::open_object_section_in_ns(const char *name, const char *ns)
{
  open_section_in_ns(name, ns);
}

void XMLFormatter::open_array_section(const char *name)
{
  open_section_in_ns(name, NULL);
}

void XMLFormatter::open_array_section_in_ns(const char *name, const char *ns)
{
  open_section_in_ns(name, ns);
}

void XMLFormatter::close_section()
{
  assert(!m_sections.empty());

  print_spaces(false);
  m_ss << "</" << m_sections.back() << ">";
  m_sections.pop_back();
}

void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << u << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_int(const char *name, int64_t u)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << u << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_float(const char *name, double d)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << d << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_string(const char *name, std::string s)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << escape_xml_str(s.c_str()) << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

std::ostream& XMLFormatter::dump_stream(const char *name)
{
  assert(m_pending_string_name.empty());
  m_pending_string_name = name;
  m_ss << "<" << m_pending_string_name << ">";
  return m_pending_string;
}

void XMLFormatter::dump_format(const char *name, const char *fmt, ...)
{
  char buf[LARGE_SIZE];
  va_list ap;
  va_start(ap, fmt);
  vsnprintf(buf, LARGE_SIZE, fmt, ap);
  va_end(ap);

  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << escape_xml_str(buf) << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

int XMLFormatter::get_len() const
{
  return m_ss.str().size();
}

void XMLFormatter::write_raw_data(const char *data)
{
  m_ss << data;
}

void XMLFormatter::open_section_in_ns(const char *name, const char *ns)
{
  print_spaces(false);
  if (ns) {
    m_ss << "<" << name << " xmlns=\"" << ns << "\">";
  }
  else {
    m_ss << "<" << name << ">";
  }
  m_sections.push_back(name);
}

void XMLFormatter::finish_pending_string()
{
  if (!m_pending_string_name.empty()) {
    m_ss << escape_xml_str(m_pending_string.str().c_str())
         << "</" << m_pending_string_name << ">";
    m_pending_string_name.clear();
    if (m_pretty) {
      m_ss << "\n";
    }
  }
}

void XMLFormatter::print_spaces(bool extra_space)
{
  finish_pending_string();
  if (m_pretty) {
    std::vector<char> spaces(m_sections.size(), ' ');
    if (extra_space)
      spaces.push_back(' ');
    spaces.push_back('\0');
    m_ss << &spaces[0];
  }
}

std::string XMLFormatter::escape_xml_str(const char *str)
{
  int len = escape_xml_attr_len(str);
  std::vector<char> escaped(len, '\0');
  escape_xml_attr(str, &escaped[0]);
  return std::string(&escaped[0]);
}

}
<commit_msg>formatter: less big buffer for dump format string<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2011 New Dream Network
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#define LARGE_SIZE 1024

#include "assert.h"
#include "Formatter.h"
#include "common/escape.h"

#include <inttypes.h>
#include <iostream>
#include <sstream>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

// -----------------------
namespace ceph {

Formatter::Formatter()
{
}

Formatter::~Formatter()
{
}

// -----------------------
JSONFormatter::JSONFormatter(bool p)
  : m_pretty(p), m_is_pending_string(false)
{
  reset();
}

void JSONFormatter::flush(std::ostream& os)
{
  finish_pending_string();
  os << m_ss.str();
  m_ss.clear();
  m_ss.str("");
}

void JSONFormatter::reset()
{
  m_stack.clear();
  m_ss.clear();
  m_ss.str("");
  m_pending_string.clear();
  m_pending_string.str("");
}

void JSONFormatter::print_comma(json_formatter_stack_entry_d& entry)
{
  if (entry.size) {
    if (m_pretty) {
      m_ss << ",\n";
      for (unsigned i=1; i < m_stack.size(); i++)
	m_ss << "    ";
    } else {
      m_ss << ",";
    }
  } else if (entry.is_array && m_pretty) {
    m_ss << "\n";
    for (unsigned i=1; i < m_stack.size(); i++)
      m_ss << "    ";
  }
  if (m_pretty && entry.is_array)
    m_ss << "    ";
}

void JSONFormatter::print_quoted_string(const char *s)
{
  int len = escape_json_attr_len(s);
  char *escaped = (char*)malloc(len);
  escape_json_attr(s, escaped);
  m_ss << '\"' << escaped << '\"';
  free(escaped);
}

void JSONFormatter::print_name(const char *name)
{
  finish_pending_string();
  if (m_stack.empty())
    return;
  struct json_formatter_stack_entry_d& entry = m_stack.back();
  print_comma(entry);
  if (!entry.is_array) {
    if (m_pretty) {
      if (entry.size)
	m_ss << "  ";
      else
	m_ss << " ";
    }
    m_ss << "\"" << name << "\"";
    if (m_pretty)
      m_ss << ": ";
    else
      m_ss << ':';
  }
  ++entry.size;
}

void JSONFormatter::open_section(const char *name, bool is_array)
{
  print_name(name);
  if (is_array)
    m_ss << '[';
  else
    m_ss << '{';

  json_formatter_stack_entry_d n;
  n.is_array = is_array;
  m_stack.push_back(n);
}

void JSONFormatter::open_array_section(const char *name)
{
  open_section(name, true);
}

void JSONFormatter::open_array_section_in_ns(const char *name, const char *ns)
{
  std::ostringstream oss;
  oss << name << " " << ns;
  open_section(oss.str().c_str(), true);
}

void JSONFormatter::open_object_section(const char *name)
{
  open_section(name, false);
}

void JSONFormatter::open_object_section_in_ns(const char *name, const char *ns)
{
  std::ostringstream oss;
  oss << name << " " << ns;
  open_section(oss.str().c_str(), false);
}

void JSONFormatter::close_section()
{
  assert(!m_stack.empty());
  finish_pending_string();

  struct json_formatter_stack_entry_d& entry = m_stack.back();
  m_ss << (entry.is_array ? ']' : '}');
  m_stack.pop_back();
}

void JSONFormatter::finish_pending_string()
{
  if (m_is_pending_string) {
    print_quoted_string(m_pending_string.str().c_str());
    m_pending_string.str(std::string());
    m_is_pending_string = false;
  }
}

void JSONFormatter::dump_unsigned(const char *name, uint64_t u)
{
  print_name(name);
  m_ss << u;
}

void JSONFormatter::dump_int(const char *name, int64_t s)
{
  print_name(name);
  m_ss << s;
}

void JSONFormatter::dump_float(const char *name, double d)
{
  char foo[30];
  snprintf(foo, sizeof(foo), "%lf", d);
  dump_string(name, foo);
}

void JSONFormatter::dump_string(const char *name, std::string s)
{
  print_name(name);
  print_quoted_string(s.c_str());
}

std::ostream& JSONFormatter::dump_stream(const char *name)
{
  print_name(name);
  m_is_pending_string = true;
  return m_pending_string;
}

void JSONFormatter::dump_format(const char *name, const char *fmt, ...)
{
  char buf[LARGE_SIZE];
  va_list ap;
  va_start(ap, fmt);
  vsnprintf(buf, LARGE_SIZE, fmt, ap);
  va_end(ap);

  print_name(name);
  print_quoted_string(buf);
}

int JSONFormatter::get_len() const
{
  return m_ss.str().size();
}

void JSONFormatter::write_raw_data(const char *data)
{
  m_ss << data;
}

const char *XMLFormatter::XML_1_DTD =
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

XMLFormatter::XMLFormatter(bool pretty)
  : m_pretty(pretty)
{
  reset();
}

void XMLFormatter::flush(std::ostream& os)
{
  finish_pending_string();
  os << m_ss.str();
  m_ss.clear();
  m_ss.str("");
}

void XMLFormatter::reset()
{
  m_ss.clear();
  m_ss.str("");
  m_pending_string.clear();
  m_pending_string.str("");
  m_sections.clear();
  m_pending_string_name.clear();
}

void XMLFormatter::open_object_section(const char *name)
{
  open_section_in_ns(name, NULL);
}

void XMLFormatter::open_object_section_in_ns(const char *name, const char *ns)
{
  open_section_in_ns(name, ns);
}

void XMLFormatter::open_array_section(const char *name)
{
  open_section_in_ns(name, NULL);
}

void XMLFormatter::open_array_section_in_ns(const char *name, const char *ns)
{
  open_section_in_ns(name, ns);
}

void XMLFormatter::close_section()
{
  assert(!m_sections.empty());

  print_spaces(false);
  m_ss << "</" << m_sections.back() << ">";
  m_sections.pop_back();
}

void XMLFormatter::dump_unsigned(const char *name, uint64_t u)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << u << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_int(const char *name, int64_t u)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << u << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_float(const char *name, double d)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << d << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

void XMLFormatter::dump_string(const char *name, std::string s)
{
  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << escape_xml_str(s.c_str()) << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

std::ostream& XMLFormatter::dump_stream(const char *name)
{
  assert(m_pending_string_name.empty());
  m_pending_string_name = name;
  m_ss << "<" << m_pending_string_name << ">";
  return m_pending_string;
}

void XMLFormatter::dump_format(const char *name, const char *fmt, ...)
{
  char buf[LARGE_SIZE];
  va_list ap;
  va_start(ap, fmt);
  vsnprintf(buf, LARGE_SIZE, fmt, ap);
  va_end(ap);

  std::string e(name);
  print_spaces(true);
  m_ss << "<" << e << ">" << escape_xml_str(buf) << "</" << e << ">";
  if (m_pretty)
    m_ss << "\n";
}

int XMLFormatter::get_len() const
{
  return m_ss.str().size();
}

void XMLFormatter::write_raw_data(const char *data)
{
  m_ss << data;
}

void XMLFormatter::open_section_in_ns(const char *name, const char *ns)
{
  print_spaces(false);
  if (ns) {
    m_ss << "<" << name << " xmlns=\"" << ns << "\">";
  }
  else {
    m_ss << "<" << name << ">";
  }
  m_sections.push_back(name);
}

void XMLFormatter::finish_pending_string()
{
  if (!m_pending_string_name.empty()) {
    m_ss << escape_xml_str(m_pending_string.str().c_str())
         << "</" << m_pending_string_name << ">";
    m_pending_string_name.clear();
    if (m_pretty) {
      m_ss << "\n";
    }
  }
}

void XMLFormatter::print_spaces(bool extra_space)
{
  finish_pending_string();
  if (m_pretty) {
    std::vector<char> spaces(m_sections.size(), ' ');
    if (extra_space)
      spaces.push_back(' ');
    spaces.push_back('\0');
    m_ss << &spaces[0];
  }
}

std::string XMLFormatter::escape_xml_str(const char *str)
{
  int len = escape_xml_attr_len(str);
  std::vector<char> escaped(len, '\0');
  escape_xml_attr(str, &escaped[0]);
  return std::string(&escaped[0]);
}

}
<|endoftext|>


<commit_before>#include <stdio.h>

#include "NetworkManager.h"
#include "third_party/raknet/PluginInterface.h"
#include "third_party/raknet/RakNetworkFactory.h"
#include "third_party/raknet/RakPeerInterface.h"
#include "third_party/raknet/MessageIdentifiers.h"
#include "third_party/raknet/BitStream.h"

#include <string>
using namespace std;

enum GlopPacketIDs {
  ID_BASIC_DATA = ID_USER_PACKET_ENUM,
};

// Raknet System Address to Glop Network Address
GlopNetworkAddress RSA2GNA(SystemAddress rsa) {
  GlopNetworkAddress gna;
  gna.first = rsa.binaryAddress;
  gna.second = rsa.port;
  return gna;
}

SystemAddress GNA2RSA(GlopNetworkAddress gna) {
  SystemAddress rsa;
  rsa.binaryAddress = gna.first;
  rsa.port = gna.second;
  return rsa;
}

class GlopPlugin : public PluginInterface {
 public:
  virtual void Update(RakPeerInterface* peer, Packet* packet) {
//    printf("Update\n");
  }
  virtual PluginReceiveResult OnReceive(RakPeerInterface* peer, Packet* packet) {
//    printf("Received a packet\n");
    return (PluginReceiveResult)true;
  }
 private:
};

NetworkManager::NetworkManager()
  : rakpeer_(NULL),
    host_search_port_(0) {
}

bool NetworkManager::Startup(int port) {
//  printf("Starting on port %d\n", port);
  rakpeer_ = RakNetworkFactory::GetRakPeerInterface();
	SocketDescriptor server_socket(port, 0);
	if (!rakpeer_->Startup(32, 5, &server_socket, 1)) {
    return false;
	}
  rakpeer_->AttachPlugin(new GlopPlugin);
  rakpeer_->SetMaximumIncomingConnections(16);
  return true;
}

NetworkManager::~NetworkManager() {
  rakpeer_->Shutdown(0);
  RakNetworkFactory::DestroyRakPeerInterface(rakpeer_);
}

void NetworkManager::StartHosting(const string& data) {
  rakpeer_->SetOfflinePingResponse(data.c_str(), data.size() + 1);
}

void NetworkManager::StopHosting() {
  rakpeer_->SetOfflinePingResponse(NULL, 0);
}

// TODO: this should probably just clear out old host entries
void NetworkManager::FindHosts(int port) {
//  printf("This: %x\n", this);
  host_search_port_ = port;
  map<GlopNetworkAddress, string>::iterator it;
  vector<map<GlopNetworkAddress, string>::iterator> trash;
  for (it = hosts_.begin(); it != hosts_.end(); it++) {
    if (it->first.second != port) {
      trash.push_back(it);
    }
  }
  for (int i = 0; i < trash.size(); i++) {
    hosts_.erase(trash[i]);
  }
	rakpeer_->Ping("255.255.255.255", port, true);
}

void NetworkManager::ClearHosts() {
  hosts_.clear();
}

vector<pair<GlopNetworkAddress, string> > NetworkManager::AvailableHosts() const {
  vector<pair<GlopNetworkAddress, string> > ret;
  map<GlopNetworkAddress, string>::const_iterator it;
  for (it = hosts_.begin(); it != hosts_.end(); it++) {
    ret.push_back(*it);
  }
  return ret;
}

void NetworkManager::Connect(GlopNetworkAddress gna) {
  int ip = gna.first;
  char buf[16];
  sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
  if (rakpeer_->Connect(buf, gna.second, 0, 0, 0)) {
//    printf("Connection successfully initiated\n");
  } else {
//    printf("Couldn't initiate connection.\n");
  }
}

void NetworkManager::Disconnect(GlopNetworkAddress gna) {
  //TODO: fill me in! :'(
/*  int ip = gna.first;
  char buf[16];
  sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
//  printf("Connceting to %s:%d\n", buf, gna.second);
  if (rakpeer_->Connect(buf, gna.second, 0, 0, 0)) {
//    printf("Connection successfully initiated\n");
  } else {
//    printf("Couldn't initiate connection.\n");
  }
*/
}

vector<GlopNetworkAddress> NetworkManager::GetConnections() const {
  SystemAddress connections[256];
  unsigned short num_connections = 256;
  rakpeer_->GetConnectionList(connections, &num_connections);
  vector<GlopNetworkAddress> ret;
  for (int i = 0; i < num_connections; i++) {
    GlopNetworkAddress g = RSA2GNA(connections[i]);
    ret.push_back(RSA2GNA(connections[i]));
  }
/*
  for (int i = 0; i < ret.size(); i++) {
        char buf[25];
        int ip = ret[i].first;
        sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
        printf("Connected to %s\n", buf);
        if (!rakpeer_->IsConnected(connections[i], true, false)) { continue; }

  }
*/
  return ret;
}

void NetworkManager::SendData(GlopNetworkAddress gna, const string& data) {
  RakNet::BitStream bs;
  char basic_data = ID_BASIC_DATA;
  bs.WriteAlignedBytes((unsigned char*)&basic_data, 1);
  bs.WriteAlignedBytes((unsigned char*)data.c_str(), data.size());
  rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE, 0, GNA2RSA(gna), false);
}

bool NetworkManager::ReceiveData(GlopNetworkAddress* gna, string* data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    *gna = it->first;
    *data = it->second;
    incoming_data_.erase(it);
    return true;
  }
  return false;
}

bool NetworkManager::ReceiveData(GlopNetworkAddress gna, string* data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    if (it->first == gna) {
      *data = it->second;
      incoming_data_.erase(it);
      return true;
    }
  }
  return false;
}

bool NetworkManager::ReceiveData(GlopNetworkAddress* gna, const string& data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    if (it->second == data) {
      *gna = it->first;
      incoming_data_.erase(it);
      return true;
    }
  }
  return false;
}

int NetworkManager::PendingData() const {
  return incoming_data_.size();
}

void NetworkManager::Think() {
  Packet* p = rakpeer_->Receive();
  while (p != NULL) {
    if (p->data[0] == ID_PONG) {
      if (p->systemAddress.port == host_search_port_) {
        string pong((const char*)(p->data + 5));
        char buf[16];
        int ip = p->systemAddress.binaryAddress;
        sprintf(buf, "%d.%d.%d.%d",
            ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
        if (pong.size() > 0) {
          hosts_[RSA2GNA(p->systemAddress)] = pong;
        }
      }
    }
    if (p->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
    }
    if (p->data[0] == ID_CONNECTION_ATTEMPT_FAILED) {
    }
    if (p->data[0] == ID_BASIC_DATA) {
      incoming_data_.push_back(
          pair<GlopNetworkAddress, string>(
              RSA2GNA(p->systemAddress),
              string((const char*)(p->data + 1), (p->bitSize - 8) / 8)));
    }
    p = rakpeer_->Receive();
  }
}
<commit_msg>Fixed crash that happened on destruction if you never called Startup()<commit_after>#include <stdio.h>

#include "NetworkManager.h"
#include "third_party/raknet/PluginInterface.h"
#include "third_party/raknet/RakNetworkFactory.h"
#include "third_party/raknet/RakPeerInterface.h"
#include "third_party/raknet/MessageIdentifiers.h"
#include "third_party/raknet/BitStream.h"

#include <string>
using namespace std;

enum GlopPacketIDs {
  ID_BASIC_DATA = ID_USER_PACKET_ENUM,
};

// Raknet System Address to Glop Network Address
GlopNetworkAddress RSA2GNA(SystemAddress rsa) {
  GlopNetworkAddress gna;
  gna.first = rsa.binaryAddress;
  gna.second = rsa.port;
  return gna;
}

SystemAddress GNA2RSA(GlopNetworkAddress gna) {
  SystemAddress rsa;
  rsa.binaryAddress = gna.first;
  rsa.port = gna.second;
  return rsa;
}

class GlopPlugin : public PluginInterface {
 public:
  virtual void Update(RakPeerInterface* peer, Packet* packet) {
//    printf("Update\n");
  }
  virtual PluginReceiveResult OnReceive(RakPeerInterface* peer, Packet* packet) {
//    printf("Received a packet\n");
    return (PluginReceiveResult)true;
  }
 private:
};

NetworkManager::NetworkManager()
  : rakpeer_(NULL),
    host_search_port_(0) {
}

bool NetworkManager::Startup(int port) {
//  printf("Starting on port %d\n", port);
  rakpeer_ = RakNetworkFactory::GetRakPeerInterface();
	SocketDescriptor server_socket(port, 0);
	if (!rakpeer_->Startup(32, 5, &server_socket, 1)) {
    return false;
	}
  rakpeer_->AttachPlugin(new GlopPlugin);
  rakpeer_->SetMaximumIncomingConnections(16);
  return true;
}

NetworkManager::~NetworkManager() {
  if (rakpeer_ != NULL) {
    rakpeer_->Shutdown(0);
    RakNetworkFactory::DestroyRakPeerInterface(rakpeer_);
  }
}

void NetworkManager::StartHosting(const string& data) {
  rakpeer_->SetOfflinePingResponse(data.c_str(), data.size() + 1);
}

void NetworkManager::StopHosting() {
  rakpeer_->SetOfflinePingResponse(NULL, 0);
}

// TODO: this should probably just clear out old host entries
void NetworkManager::FindHosts(int port) {
//  printf("This: %x\n", this);
  host_search_port_ = port;
  map<GlopNetworkAddress, string>::iterator it;
  vector<map<GlopNetworkAddress, string>::iterator> trash;
  for (it = hosts_.begin(); it != hosts_.end(); it++) {
    if (it->first.second != port) {
      trash.push_back(it);
    }
  }
  for (int i = 0; i < trash.size(); i++) {
    hosts_.erase(trash[i]);
  }
	rakpeer_->Ping("255.255.255.255", port, true);
}

void NetworkManager::ClearHosts() {
  hosts_.clear();
}

vector<pair<GlopNetworkAddress, string> > NetworkManager::AvailableHosts() const {
  vector<pair<GlopNetworkAddress, string> > ret;
  map<GlopNetworkAddress, string>::const_iterator it;
  for (it = hosts_.begin(); it != hosts_.end(); it++) {
    ret.push_back(*it);
  }
  return ret;
}

void NetworkManager::Connect(GlopNetworkAddress gna) {
  int ip = gna.first;
  char buf[16];
  sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
  if (rakpeer_->Connect(buf, gna.second, 0, 0, 0)) {
//    printf("Connection successfully initiated\n");
  } else {
//    printf("Couldn't initiate connection.\n");
  }
}

void NetworkManager::Disconnect(GlopNetworkAddress gna) {
  //TODO: fill me in! :'(
/*  int ip = gna.first;
  char buf[16];
  sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
//  printf("Connceting to %s:%d\n", buf, gna.second);
  if (rakpeer_->Connect(buf, gna.second, 0, 0, 0)) {
//    printf("Connection successfully initiated\n");
  } else {
//    printf("Couldn't initiate connection.\n");
  }
*/
}

vector<GlopNetworkAddress> NetworkManager::GetConnections() const {
  SystemAddress connections[256];
  unsigned short num_connections = 256;
  rakpeer_->GetConnectionList(connections, &num_connections);
  vector<GlopNetworkAddress> ret;
  for (int i = 0; i < num_connections; i++) {
    GlopNetworkAddress g = RSA2GNA(connections[i]);
    ret.push_back(RSA2GNA(connections[i]));
  }
/*
  for (int i = 0; i < ret.size(); i++) {
        char buf[25];
        int ip = ret[i].first;
        sprintf(buf, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
        printf("Connected to %s\n", buf);
        if (!rakpeer_->IsConnected(connections[i], true, false)) { continue; }

  }
*/
  return ret;
}

void NetworkManager::SendData(GlopNetworkAddress gna, const string& data) {
  RakNet::BitStream bs;
  char basic_data = ID_BASIC_DATA;
  bs.WriteAlignedBytes((unsigned char*)&basic_data, 1);
  bs.WriteAlignedBytes((unsigned char*)data.c_str(), data.size());
  rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE, 0, GNA2RSA(gna), false);
}

bool NetworkManager::ReceiveData(GlopNetworkAddress* gna, string* data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    *gna = it->first;
    *data = it->second;
    incoming_data_.erase(it);
    return true;
  }
  return false;
}

bool NetworkManager::ReceiveData(GlopNetworkAddress gna, string* data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    if (it->first == gna) {
      *data = it->second;
      incoming_data_.erase(it);
      return true;
    }
  }
  return false;
}

bool NetworkManager::ReceiveData(GlopNetworkAddress* gna, const string& data) {
  List<pair<GlopNetworkAddress, string> >::iterator it;
  for (it = incoming_data_.begin(); it != incoming_data_.end(); it++) {
    if (it->second == data) {
      *gna = it->first;
      incoming_data_.erase(it);
      return true;
    }
  }
  return false;
}

int NetworkManager::PendingData() const {
  return incoming_data_.size();
}

void NetworkManager::Think() {
  Packet* p = rakpeer_->Receive();
  while (p != NULL) {
    if (p->data[0] == ID_PONG) {
      if (p->systemAddress.port == host_search_port_) {
        string pong((const char*)(p->data + 5));
        char buf[16];
        int ip = p->systemAddress.binaryAddress;
        sprintf(buf, "%d.%d.%d.%d",
            ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
        if (pong.size() > 0) {
          hosts_[RSA2GNA(p->systemAddress)] = pong;
        }
      }
    }
    if (p->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
    }
    if (p->data[0] == ID_CONNECTION_ATTEMPT_FAILED) {
    }
    if (p->data[0] == ID_BASIC_DATA) {
      incoming_data_.push_back(
          pair<GlopNetworkAddress, string>(
              RSA2GNA(p->systemAddress),
              string((const char*)(p->data + 1), (p->bitSize - 8) / 8)));
    }
    p = rakpeer_->Receive();
  }
}
<|endoftext|>


<commit_before><commit_msg>http_loader: fix style<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLPStructuredGridReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLPStructuredGridReader.h"

#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkStructuredGrid.h"
#include "vtkXMLDataElement.h"
#include "vtkXMLStructuredGridReader.h"

vtkCxxRevisionMacro(vtkXMLPStructuredGridReader, "1.5");
vtkStandardNewMacro(vtkXMLPStructuredGridReader);

//----------------------------------------------------------------------------
vtkXMLPStructuredGridReader::vtkXMLPStructuredGridReader()
{
  // Copied from vtkStructuredGridReader constructor:
  this->SetOutput(vtkStructuredGrid::New());
  // Releasing data for pipeline parallism.
  // Filters will know it is empty.
  this->Outputs[0]->ReleaseData();
  this->Outputs[0]->Delete();
}

//----------------------------------------------------------------------------
vtkXMLPStructuredGridReader::~vtkXMLPStructuredGridReader()
{
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetOutput(vtkStructuredGrid *output)
{
  this->Superclass::SetNthOutput(0, output);
}

//----------------------------------------------------------------------------
vtkStructuredGrid* vtkXMLPStructuredGridReader::GetOutput()
{
  if(this->NumberOfOutputs < 1)
    {
    return 0;
    }
  return static_cast<vtkStructuredGrid*>(this->Outputs[0]);
}

//----------------------------------------------------------------------------
vtkStructuredGrid* vtkXMLPStructuredGridReader::GetPieceInput(int index)
{
  vtkXMLStructuredGridReader* reader =
    static_cast<vtkXMLStructuredGridReader*>(this->PieceReaders[index]);
  return reader->GetOutput();
}

//----------------------------------------------------------------------------
const char* vtkXMLPStructuredGridReader::GetDataSetName()
{
  return "PStructuredGrid";
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetOutputExtent(int* extent)
{
  this->GetOutput()->SetExtent(extent);
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::GetPieceInputExtent(int index, int* extent)
{
  this->GetPieceInput(index)->GetExtent(extent);
}

//----------------------------------------------------------------------------
int
vtkXMLPStructuredGridReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
{
  if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; }

  // Find the PPoints element.
  this->PPointsElement = 0;
  int i;
  int numNested = ePrimary->GetNumberOfNestedElements();
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if((strcmp(eNested->GetName(), "PPoints") == 0) &&
       (eNested->GetNumberOfNestedElements() == 1))
      {
      this->PPointsElement = eNested;
      }
    }

  if(!this->PPointsElement)
    {
    int extent[6];
    this->GetOutput()->GetWholeExtent(extent);
    if((extent[0] <= extent[1]) && (extent[2] <= extent[3]) &&
       (extent[4] <= extent[5]))
      {
      vtkErrorMacro("Could not find PPoints element with 1 array.");
      return 0;
      }
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetupOutputInformation()
{
  this->Superclass::SetupOutputInformation();
  vtkStructuredGrid* output = this->GetOutput();

  // Create the points array.
  vtkPoints* points = vtkPoints::New();
  vtkXMLDataElement* ePoints = this->PPointsElement;
  if(ePoints)
    {
    // Non-zero volume.
    vtkDataArray* a = this->CreateDataArray(ePoints->GetNestedElement(0));
    if(a)
      {
      points->SetData(a);
      a->Delete();
      }
    else
      {
      this->InformationError = 1;
      }
    }
  output->SetPoints(points);
  points->Delete();
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetupOutputData()
{
  this->Superclass::SetupOutputData();

  // Allocate the points array.
  vtkDataArray* a = this->GetOutput()->GetPoints()->GetData();
  a->SetNumberOfTuples(this->GetNumberOfPoints());
}

//----------------------------------------------------------------------------
int vtkXMLPStructuredGridReader::ReadPieceData()
{
  if(!this->Superclass::ReadPieceData()) { return 0; }

  // Copy the points.
  vtkStructuredGrid* input = this->GetPieceInput(this->Piece);
  vtkStructuredGrid* output = this->GetOutput();
  this->CopyArrayForPoints(input->GetPoints()->GetData(),
                           output->GetPoints()->GetData());

  return 1;
}

//----------------------------------------------------------------------------
vtkXMLDataReader* vtkXMLPStructuredGridReader::CreatePieceReader()
{
  return vtkXMLStructuredGridReader::New();
}
<commit_msg>Jean noticed this bug (we need a GetOutput(int) method for ParaView)<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLPStructuredGridReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLPStructuredGridReader.h"

#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkStructuredGrid.h"
#include "vtkXMLDataElement.h"
#include "vtkXMLStructuredGridReader.h"

vtkCxxRevisionMacro(vtkXMLPStructuredGridReader, "1.6");
vtkStandardNewMacro(vtkXMLPStructuredGridReader);

//----------------------------------------------------------------------------
vtkXMLPStructuredGridReader::vtkXMLPStructuredGridReader()
{
  // Copied from vtkStructuredGridReader constructor:
  this->SetOutput(vtkStructuredGrid::New());
  // Releasing data for pipeline parallism.
  // Filters will know it is empty.
  this->Outputs[0]->ReleaseData();
  this->Outputs[0]->Delete();
}

//----------------------------------------------------------------------------
vtkXMLPStructuredGridReader::~vtkXMLPStructuredGridReader()
{
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
vtkStructuredGrid* vtkXMLPStructuredGridReader::GetOutput(int idx)
{
  return static_cast<vtkStructuredGrid*>(this->Superclass::GetOutput(idx));
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetOutput(vtkStructuredGrid *output)
{
  this->Superclass::SetNthOutput(0, output);
}

//----------------------------------------------------------------------------
vtkStructuredGrid* vtkXMLPStructuredGridReader::GetOutput()
{
  if(this->NumberOfOutputs < 1)
    {
    return 0;
    }
  return static_cast<vtkStructuredGrid*>(this->Outputs[0]);
}

//----------------------------------------------------------------------------
vtkStructuredGrid* vtkXMLPStructuredGridReader::GetPieceInput(int index)
{
  vtkXMLStructuredGridReader* reader =
    static_cast<vtkXMLStructuredGridReader*>(this->PieceReaders[index]);
  return reader->GetOutput();
}

//----------------------------------------------------------------------------
const char* vtkXMLPStructuredGridReader::GetDataSetName()
{
  return "PStructuredGrid";
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetOutputExtent(int* extent)
{
  this->GetOutput()->SetExtent(extent);
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::GetPieceInputExtent(int index, int* extent)
{
  this->GetPieceInput(index)->GetExtent(extent);
}

//----------------------------------------------------------------------------
int
vtkXMLPStructuredGridReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
{
  if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; }

  // Find the PPoints element.
  this->PPointsElement = 0;
  int i;
  int numNested = ePrimary->GetNumberOfNestedElements();
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if((strcmp(eNested->GetName(), "PPoints") == 0) &&
       (eNested->GetNumberOfNestedElements() == 1))
      {
      this->PPointsElement = eNested;
      }
    }

  if(!this->PPointsElement)
    {
    int extent[6];
    this->GetOutput()->GetWholeExtent(extent);
    if((extent[0] <= extent[1]) && (extent[2] <= extent[3]) &&
       (extent[4] <= extent[5]))
      {
      vtkErrorMacro("Could not find PPoints element with 1 array.");
      return 0;
      }
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetupOutputInformation()
{
  this->Superclass::SetupOutputInformation();
  vtkStructuredGrid* output = this->GetOutput();

  // Create the points array.
  vtkPoints* points = vtkPoints::New();
  vtkXMLDataElement* ePoints = this->PPointsElement;
  if(ePoints)
    {
    // Non-zero volume.
    vtkDataArray* a = this->CreateDataArray(ePoints->GetNestedElement(0));
    if(a)
      {
      points->SetData(a);
      a->Delete();
      }
    else
      {
      this->InformationError = 1;
      }
    }
  output->SetPoints(points);
  points->Delete();
}

//----------------------------------------------------------------------------
void vtkXMLPStructuredGridReader::SetupOutputData()
{
  this->Superclass::SetupOutputData();

  // Allocate the points array.
  vtkDataArray* a = this->GetOutput()->GetPoints()->GetData();
  a->SetNumberOfTuples(this->GetNumberOfPoints());
}

//----------------------------------------------------------------------------
int vtkXMLPStructuredGridReader::ReadPieceData()
{
  if(!this->Superclass::ReadPieceData()) { return 0; }

  // Copy the points.
  vtkStructuredGrid* input = this->GetPieceInput(this->Piece);
  vtkStructuredGrid* output = this->GetOutput();
  this->CopyArrayForPoints(input->GetPoints()->GetData(),
                           output->GetPoints()->GetData());

  return 1;
}

//----------------------------------------------------------------------------
vtkXMLDataReader* vtkXMLPStructuredGridReader::CreatePieceReader()
{
  return vtkXMLStructuredGridReader::New();
}
<|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004 darkbits                              Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "sdltruetypefont.hpp"

#include "guichan/exception.hpp"
#include "guichan/image.hpp"

#include <guichan/sdl/sdlgraphics.hpp>

namespace gcn
{
  SDLTrueTypeFont::SDLTrueTypeFont (const std::string& filename, int size)
  {
		mRowSpacing = 0;
		mGlyphSpacing = 0;
		mAntiAlias = true;
		mFilename = filename;
		mFont = NULL;

		mFont = TTF_OpenFont(filename.c_str(), size);

		if (mFont == NULL)
		{
			throw GCN_EXCEPTION("SDLTrueTypeFont::SDLTrueTypeFont. "+std::string(TTF_GetError()));
		}
	}

  SDLTrueTypeFont::~SDLTrueTypeFont()
  {
    TTF_CloseFont(mFont);
  }

	int SDLTrueTypeFont::getWidth(const std::string& text) const
  {
		int w, h;
	  TTF_SizeText(mFont, text.c_str(), &w, &h);

		return w;
  }

  int SDLTrueTypeFont::getHeight() const
  {
		return TTF_FontHeight(mFont) + mRowSpacing;
  }

	void SDLTrueTypeFont::drawString(Graphics* graphics, const std::string& text, const int x, const int y)
	{
		SDLGraphics *sdlGraphics = dynamic_cast<SDLGraphics *>(graphics);

		if (sdlGraphics == NULL)
		{
			throw GCN_EXCEPTION("SDLTrueTypeFont::drawString. Graphics object not an SDL graphics object!");
			return;
		}

		// This is needed for drawing the Glyph in the middle if we have spacing
		int yoffset = getRowSpacing() / 2;

		Color col = sdlGraphics->getColor();

		SDL_Color sdlCol;
		sdlCol.b = col.b;
		sdlCol.r = col.r;
		sdlCol.g = col.g;

		SDL_Surface *textSurface;
		if (mAntiAlias)
		{
			textSurface = TTF_RenderText_Blended(mFont, text.c_str(), sdlCol);
		}
		else
		{
			textSurface = TTF_RenderText_Solid(mFont, text.c_str(), sdlCol);
		}

		SDL_Rect dst, src;
		dst.x = x;
		dst.y = y + yoffset;
		src.w = textSurface->w;
		src.h = textSurface->h;
		src.x = 0;
		src.y = 0;

		sdlGraphics->drawSDLSurface(textSurface, src, dst);
		SDL_FreeSurface(textSurface);

	} // end drawString

	void SDLTrueTypeFont::setRowSpacing(int spacing)
	{
		mRowSpacing = spacing;
	}

	int SDLTrueTypeFont::getRowSpacing()
	{
		return mRowSpacing;
	}

	void SDLTrueTypeFont::setGlyphSpacing(int spacing)
	{
		mGlyphSpacing = spacing;
	}

	int SDLTrueTypeFont::getGlyphSpacing()
	{
		return mGlyphSpacing;
	}

	void SDLTrueTypeFont::setAntiAlias(bool antiAlias)
	{
		mAntiAlias = antiAlias;
	}

	bool SDLTrueTypeFont::isAntiAlias()
	{
		return mAntiAlias;
	}

} // end gcn

<commit_msg>Fixed a bug when drawing empty strings<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004 darkbits                              Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "sdltruetypefont.hpp"

#include "guichan/exception.hpp"
#include "guichan/image.hpp"

#include <guichan/sdl/sdlgraphics.hpp>

namespace gcn
{
	SDLTrueTypeFont::SDLTrueTypeFont (const std::string& filename, int size)
	{
		mRowSpacing = 0;
		mGlyphSpacing = 0;
		mAntiAlias = true;
		mFilename = filename;
		mFont = NULL;

		mFont = TTF_OpenFont(filename.c_str(), size);

		if (mFont == NULL)
		{
			throw GCN_EXCEPTION("SDLTrueTypeFont::SDLTrueTypeFont. "+std::string(TTF_GetError()));
		}
	}

	SDLTrueTypeFont::~SDLTrueTypeFont()
	{
		TTF_CloseFont(mFont);
	}

	int SDLTrueTypeFont::getWidth(const std::string& text) const
	{
		int w, h;
		TTF_SizeText(mFont, text.c_str(), &w, &h);

		return w;
	}

	int SDLTrueTypeFont::getHeight() const
	{
		return TTF_FontHeight(mFont) + mRowSpacing;
	}

	void SDLTrueTypeFont::drawString(Graphics* graphics, const std::string& text, const int x, const int y)
	{
		if (text == "")
		{
			return;
		}

		SDLGraphics *sdlGraphics = dynamic_cast<SDLGraphics *>(graphics);

		if (sdlGraphics == NULL)
		{
			throw GCN_EXCEPTION("SDLTrueTypeFont::drawString. Graphics object not an SDL graphics object!");
			return;
		}

		// This is needed for drawing the Glyph in the middle if we have spacing
		int yoffset = getRowSpacing() / 2;

		Color col = sdlGraphics->getColor();

		SDL_Color sdlCol;
		sdlCol.b = col.b;
		sdlCol.r = col.r;
		sdlCol.g = col.g;

		SDL_Surface *textSurface;
		if (mAntiAlias)
		{
			textSurface = TTF_RenderText_Blended(mFont, text.c_str(), sdlCol);
		}
		else
		{
			textSurface = TTF_RenderText_Solid(mFont, text.c_str(), sdlCol);
		}

		SDL_Rect dst, src;
		dst.x = x;
		dst.y = y + yoffset;
		src.w = textSurface->w;
		src.h = textSurface->h;
		src.x = 0;
		src.y = 0;

		sdlGraphics->drawSDLSurface(textSurface, src, dst);
		SDL_FreeSurface(textSurface);

	} // end drawString

	void SDLTrueTypeFont::setRowSpacing(int spacing)
	{
		mRowSpacing = spacing;
	}

	int SDLTrueTypeFont::getRowSpacing()
	{
		return mRowSpacing;
	}

	void SDLTrueTypeFont::setGlyphSpacing(int spacing)
	{
		mGlyphSpacing = spacing;
	}

	int SDLTrueTypeFont::getGlyphSpacing()
	{
		return mGlyphSpacing;
	}

	void SDLTrueTypeFont::setAntiAlias(bool antiAlias)
	{
		mAntiAlias = antiAlias;
	}

	bool SDLTrueTypeFont::isAntiAlias()
	{
		return mAntiAlias;
	}

} // end gcn

<|endoftext|>


<commit_before>
#include "EIMTomo/EIMTomoConfiguration.h"

// C Includes
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef CMP_HAVE_SYS_PARAM_H
#include <sys/param.h>  // MAXPATHLEN definition
#else
#error sys/paramh is needed for this code and was not found on your system
#endif
// C++ includes
#include <string>
#include <iostream>

// EIMTomo Includes
#include "EIMTomo/EIMTomo.h"
#include "EIMTomo/common/EIMTime.h"
#include "EIMTomo/common/allocate.h"

#include "EIMTomo/IO/VTKFileWriters.hpp"
#include "EIMTomo/IO/RawGeometryWriter.h"

// MXA Includes
#include "MXA/Utilities/MXADir.h"
#include "ScaleOffsetCorrectionConstants.h"
#include "ScaleOffsetCorrectionParser.h"
#include "ScaleOffsetCorrectionEngine.h"

#define START startm = EIMTOMO_getMilliSeconds();
#define STOP stopm = EIMTOMO_getMilliSeconds();
#define PRINTTIME printf( "%6.3f seconds used by the processor.\n", ((double)stopm-startm)/1000.0);

/*double
 CE => Computation Engine
 CI => Computation Inputs
 N_ => Number of ..

 */
#define MAKE_OUTPUT_FILE(Fp, err, outdir, filename)\
    {\
    std::string filepath(outdir);\
    filepath =+ MXADir::Separator;\
    filepath.append(filename);\
    Fp = fopen(filepath.c_str(),"wb");\
    if (Fp == NULL) { std::cout << "Error Opening Output file " << filepath << std::endl; err = 1; }\
    }

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int main(int argc, char** argv)
{
  int32_t error;
  //FILE* Fp = NULL;
  TomoInputs inputs;
  Sino sinogram;
  Geom geometry;
  uint64_t startm;
  uint64_t stopm;

  START;

  error = -1;
  ScaleOffsetCorrectionParser soci;

  error = soci.parseArguments(argc, argv, &inputs);
  if(error != -1)
  {
    printf("***************\nParameter File: %s\nSinogram File: %s\nInitial Reconstruction File: %s\nOutput Directory: %s\nOutput File: %s\n***************\n",
           inputs.ParamFile.c_str(),
           inputs.SinoFile.c_str(),
           inputs.InitialRecon.c_str(),
           inputs.outputDir.c_str(),
           inputs.OutputFile.c_str());

    char path1[MAXPATHLEN];  // This is a buffer for the text
    ::memset(path1, 0, MAXPATHLEN); // Initialize the string to all zeros.
    getcwd(path1, MAXPATHLEN);
    std::cout << "Current Working Directory: " << path1 << std::endl;

    // Make sure the output directory is created if it does not exist
    if(MXADir::exists(inputs.outputDir) == false)
    {
      std::cout << "Output Directory '" << inputs.outputDir << "' does NOT exist. Attempting to create it." << std::endl;
      if(MXADir::mkdir(inputs.outputDir, true) == false)
      {
        std::cout << "Error creating the output directory '" << inputs.outputDir << "'\n   Exiting Now." << std::endl;
        return EXIT_FAILURE;
      }
      std::cout << "Output Directory Created." << std::endl;
    }
    ::memset(path1, 0, MAXPATHLEN); // Initialize the string to all zeros.
    getcwd(path1, MAXPATHLEN);
    std::cout << "Current Working Directory: " << path1 << std::endl;

    error = soci.readParameterFile(inputs.ParamFile, &inputs, &sinogram, &geometry);
    if (error < 0)
    {
      std::cout << "Error Opening Parameter file and parsing the data within." << std::endl;
      return EXIT_FAILURE;
    }
    //Based on the inputs , calculate the "other" variables in the structure definition
    soci.initializeSinoParameters(&sinogram, &inputs);
    //CI_MaskSinogram(&OriginalSinogram,&MaskedSinogram);
    soci.initializeGeomParameters(&sinogram, &geometry, &inputs);
  }

  // Run the reconstruction
  SOCEngine soce(&sinogram, &geometry, &inputs);
  error = soce.mapicdReconstruct();
  if(error < 0)
  {
    std::cout << "Error (" << error << ") During Reconstruction" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "Final Dimensions of Object: " << std::endl;
  std::cout << "  Nx = " << geometry.N_x << std::endl;
  std::cout << "  Ny = " << geometry.N_y << std::endl;
  std::cout << "  Nz = " << geometry.N_z << std::endl;

  // Write the vtk output file
  VTKRectilinearGridFileWriter vtkWriter;
  vtkWriter.setWriteBinaryFiles(true);
  DimsAndRes dimsAndRes;
  dimsAndRes.xpoints = geometry.N_x;
  dimsAndRes.ypoints = geometry.N_y;
  dimsAndRes.zpoints = geometry.N_z;
  dimsAndRes.resx = 1.0f;
  dimsAndRes.resy = 1.0f;
  dimsAndRes.resz = 1.0f;
  std::string vtkFile(inputs.outputDir);
  vtkFile = vtkFile.append(MXADir::getSeparator()).append("Output.vtk");

  VtkScalarWriter* w0 = static_cast<VtkScalarWriter*>(new TomoOutputScalarWriter(&geometry));
  std::vector<VtkScalarWriter*> scalarsToWrite;
  w0->m_WriteBinaryFiles = true;
  scalarsToWrite.push_back(w0);

  error = vtkWriter.write<DimsAndRes>(vtkFile, &dimsAndRes, scalarsToWrite);
  if (error < 0)
  {
    std::cout << "Error writing vtk file '" << vtkFile << "'" << std::endl;
  }

  // Write a raw binary output file
  RawGeometryWriter binWriter(&geometry);
  error = binWriter.writeFile(inputs.OutputFile);
  if (error < 0)
  {
    std::cout << "Error writing Raw binary file '" << inputs.OutputFile << "'" << std::endl;
  }

  STOP;
  PRINTTIME;
  // if(error < 0)
  // {
  // //TODO:clean up memory here
  // return EXIT_FAILURE;
  // }
  // //TODO:free memory
  //
  // return EXIT_SUCCESS;
  return 0;
}

<commit_msg>Writing out a StructuredPoints VTK file instead of RectilinearGrid<commit_after>
#include "EIMTomo/EIMTomoConfiguration.h"

// C Includes
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef CMP_HAVE_SYS_PARAM_H
#include <sys/param.h>  // MAXPATHLEN definition
#else
#error sys/paramh is needed for this code and was not found on your system
#endif
// C++ includes
#include <string>
#include <iostream>

// EIMTomo Includes
#include "EIMTomo/EIMTomo.h"
#include "EIMTomo/common/EIMTime.h"
#include "EIMTomo/common/allocate.h"

#include "EIMTomo/IO/VTKFileWriters.hpp"
#include "EIMTomo/IO/RawGeometryWriter.h"

// MXA Includes
#include "MXA/Utilities/MXADir.h"
#include "ScaleOffsetCorrectionConstants.h"
#include "ScaleOffsetCorrectionParser.h"
#include "ScaleOffsetCorrectionEngine.h"

#define START startm = EIMTOMO_getMilliSeconds();
#define STOP stopm = EIMTOMO_getMilliSeconds();
#define PRINTTIME printf( "%6.3f seconds used by the processor.\n", ((double)stopm-startm)/1000.0);

/*double
 CE => Computation Engine
 CI => Computation Inputs
 N_ => Number of ..

 */
#define MAKE_OUTPUT_FILE(Fp, err, outdir, filename)\
    {\
    std::string filepath(outdir);\
    filepath =+ MXADir::Separator;\
    filepath.append(filename);\
    Fp = fopen(filepath.c_str(),"wb");\
    if (Fp == NULL) { std::cout << "Error Opening Output file " << filepath << std::endl; err = 1; }\
    }

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int main(int argc, char** argv)
{
  int32_t error;
  //FILE* Fp = NULL;
  TomoInputs inputs;
  Sino sinogram;
  Geom geometry;
  uint64_t startm;
  uint64_t stopm;

  START;

  error = -1;
  ScaleOffsetCorrectionParser soci;

  error = soci.parseArguments(argc, argv, &inputs);
  if(error != -1)
  {
    printf("***************\nParameter File: %s\nSinogram File: %s\nInitial Reconstruction File: %s\nOutput Directory: %s\nOutput File: %s\n***************\n",
           inputs.ParamFile.c_str(),
           inputs.SinoFile.c_str(),
           inputs.InitialRecon.c_str(),
           inputs.outputDir.c_str(),
           inputs.OutputFile.c_str());

    char path1[MAXPATHLEN];  // This is a buffer for the text
    ::memset(path1, 0, MAXPATHLEN); // Initialize the string to all zeros.
    getcwd(path1, MAXPATHLEN);
    std::cout << "Current Working Directory: " << path1 << std::endl;

    // Make sure the output directory is created if it does not exist
    if(MXADir::exists(inputs.outputDir) == false)
    {
      std::cout << "Output Directory '" << inputs.outputDir << "' does NOT exist. Attempting to create it." << std::endl;
      if(MXADir::mkdir(inputs.outputDir, true) == false)
      {
        std::cout << "Error creating the output directory '" << inputs.outputDir << "'\n   Exiting Now." << std::endl;
        return EXIT_FAILURE;
      }
      std::cout << "Output Directory Created." << std::endl;
    }
    ::memset(path1, 0, MAXPATHLEN); // Initialize the string to all zeros.
    getcwd(path1, MAXPATHLEN);
    std::cout << "Current Working Directory: " << path1 << std::endl;

    error = soci.readParameterFile(inputs.ParamFile, &inputs, &sinogram, &geometry);
    if (error < 0)
    {
      std::cout << "Error Opening Parameter file and parsing the data within." << std::endl;
      return EXIT_FAILURE;
    }
    //Based on the inputs , calculate the "other" variables in the structure definition
    soci.initializeSinoParameters(&sinogram, &inputs);
    //CI_MaskSinogram(&OriginalSinogram,&MaskedSinogram);
    soci.initializeGeomParameters(&sinogram, &geometry, &inputs);
  }

  // Run the reconstruction
  SOCEngine soce(&sinogram, &geometry, &inputs);
  error = soce.mapicdReconstruct();
  if(error < 0)
  {
    std::cout << "Error (" << error << ") During Reconstruction" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "Final Dimensions of Object: " << std::endl;
  std::cout << "  Nx = " << geometry.N_x << std::endl;
  std::cout << "  Ny = " << geometry.N_y << std::endl;
  std::cout << "  Nz = " << geometry.N_z << std::endl;

  // Write the vtk output file
//  VTKRectilinearGridFileWriter vtkWriter;
	VTKStructuredPointsFileWriter vtkWriter;
  vtkWriter.setWriteBinaryFiles(true);
  DimsAndRes dimsAndRes;
  dimsAndRes.xpoints = geometry.N_x;
  dimsAndRes.ypoints = geometry.N_y;
  dimsAndRes.zpoints = geometry.N_z;
  dimsAndRes.resx = 1.0f;
  dimsAndRes.resy = 1.0f;
  dimsAndRes.resz = 1.0f;
  std::string vtkFile(inputs.outputDir);
  vtkFile = vtkFile.append(MXADir::getSeparator()).append("Output.vtk");

  VtkScalarWriter* w0 = static_cast<VtkScalarWriter*>(new TomoOutputScalarWriter(&geometry));
  std::vector<VtkScalarWriter*> scalarsToWrite;
  w0->m_WriteBinaryFiles = true;
  scalarsToWrite.push_back(w0);

  error = vtkWriter.write<DimsAndRes>(vtkFile, &dimsAndRes, scalarsToWrite);
  if (error < 0)
  {
    std::cout << "Error writing vtk file '" << vtkFile << "'" << std::endl;
  }

  // Write a raw binary output file
  RawGeometryWriter binWriter(&geometry);
  error = binWriter.writeFile(inputs.OutputFile);
  if (error < 0)
  {
    std::cout << "Error writing Raw binary file '" << inputs.OutputFile << "'" << std::endl;
  }

  STOP;
  PRINTTIME;
  // if(error < 0)
  // {
  // //TODO:clean up memory here
  // return EXIT_FAILURE;
  // }
  // //TODO:free memory
  //
  // return EXIT_SUCCESS;
  return 0;
}

<|endoftext|>


<commit_before>// RUN: %clang_cc1 -emit-llvm %s -o -

struct Pass {} ;
template<typename PassName>
Pass *callDefaultCtor() { return new PassName(); }

void foo(Pass *(*C)());

#include <string>

bool foo(std::string &X) {
  return X.empty();
}
<commit_msg>Remove this file, it's not much of a test and string headers cause problems on windows.<commit_after><|endoftext|>


<commit_before>#include "udsscanwindow.h"
#include "ui_udsscanwindow.h"
#include "mainwindow.h"

UDSScanWindow::UDSScanWindow(const QVector<CANFrame> *frames, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::UDSScanWindow)
{
    ui->setupUi(this);

    modelFrames = frames;

    waitTimer = new QTimer;
    waitTimer->setInterval(300);

    connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
    connect(ui->btnScan, &QPushButton::clicked, this, &UDSScanWindow::scanUDS);
    connect(waitTimer, &QTimer::timeout, this, &UDSScanWindow::timeOut);

    ui->cbBuses->addItem("0");
    ui->cbBuses->addItem("1");
    ui->cbBuses->addItem("Both");

}

UDSScanWindow::~UDSScanWindow()
{
    delete ui;
    waitTimer->stop();
    delete waitTimer;
}

void UDSScanWindow::scanUDS()
{
    ui->listResults->clear();
    sendingFrames.clear();

    CANFrame frame;
    int typ, id;
    int startID, endID;
    startID = Utility::ParseStringToNum(ui->txtStartID->text());
    endID = Utility::ParseStringToNum(ui->txtEndID->text());

    int buses = ui->cbBuses->currentIndex();
    buses++;
    if (buses < 1) buses = 1;

    //start out by sending tester present to every address to see if anyone replies
    for (id = startID; id < endID; id++)
    {
        frame.ID = id;
        frame.len = 8;
        frame.extended = false;
        frame.data[0] = 2;
        frame.data[1] = 0x3E; //tester present
        frame.data[2] = 0;
        frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
        frame.data[6] = 0;frame.data[7] = 0;

        if (buses & 1)
        {
            frame.bus = 0;
            sendingFrames.append(frame);
        }
        if (buses & 2)
        {
            frame.bus = 1;
            sendingFrames.append(frame);
        }
    }

    //then try asking for the various diagnostic session types
    for (typ = 1; typ < 5; typ++)
    {
        for (id = startID; id <= endID; id++)
        {
            frame.ID = id;
            frame.len = 8;
            frame.extended = false;
            frame.data[0] = 2;
            frame.data[1] = 0x10;
            frame.data[2] = typ;
            frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
            frame.data[6] = 0;frame.data[7] = 0;

            if (buses & 1)
            {
                frame.bus = 0;
                sendingFrames.append(frame);
            }
            if (buses & 2)
            {
                frame.bus = 1;
                sendingFrames.append(frame);
            }
        }
    }

    waitTimer->start();
    currIdx = -1;
    sendNextMsg();
}

void UDSScanWindow::updatedFrames(int numFrames)
{
    CANFrame thisFrame;
    QString result;
    int id;
    if (numFrames == -1) //all frames deleted. We don't care
    {
    }
    else if (numFrames == -2) //all new set of frames. Don't care.
    {
    }
    else //just got some new frames. See if they are relevant.
    {
        if (numFrames > modelFrames->count()) return;
        for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
        {
            thisFrame = modelFrames->at(i);
            id = thisFrame.ID;

            id -= ui->spinReplyOffset->value(); //back to original ECU id
            if (id == sendingFrames[currIdx].ID)
            {
                if (thisFrame.data[1] == 0x40 + sendingFrames[currIdx].data[1])
                {
                    result = "ECU at bus " + QString::number(thisFrame.bus) + " ID: " + QString::number(id, 16) + " responds to mode "
                        + QString::number(sendingFrames[currIdx].data[1], 16)
                        + " " + QString::number(sendingFrames[currIdx].data[2], 16) + " with affirmation.";
                }
                else if ( thisFrame.data[1] == 0x7F)
                {
                    result = "ECU at bus " + QString::number(thisFrame.bus) + " ID: " + QString::number(id, 16) + " responds to mode "
                        + QString::number(sendingFrames[currIdx].data[1], 16)
                        + " " + QString::number(sendingFrames[currIdx].data[2], 16) + " with an error.";
                }
                ui->listResults->addItem(result);
                sendNextMsg();
            }
        }
    }
}

void UDSScanWindow::timeOut()
{
    QString result;
    result = "ECU at bus " + QString::number(sendingFrames[currIdx].bus) + " ID: " + QString::number(sendingFrames[currIdx].ID, 16) + " did not respond to mode "
             + QString::number(sendingFrames[currIdx].data[1], 16) + " " + QString::number(sendingFrames[currIdx].data[2], 16);
    ui->listResults->addItem(result);

    sendNextMsg();
}

void UDSScanWindow::sendNextMsg()
{
    currIdx++;
    if (currIdx < sendingFrames.count())
    {
        emit sendCANFrame(&sendingFrames[currIdx], sendingFrames[currIdx].bus);
    }
    else
    {
        waitTimer->stop();
    }
}
<commit_msg>Small fix for potential crash bug in UDS scanner<commit_after>#include "udsscanwindow.h"
#include "ui_udsscanwindow.h"
#include "mainwindow.h"

UDSScanWindow::UDSScanWindow(const QVector<CANFrame> *frames, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::UDSScanWindow)
{
    ui->setupUi(this);

    modelFrames = frames;

    waitTimer = new QTimer;
    waitTimer->setInterval(300);

    connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
    connect(ui->btnScan, &QPushButton::clicked, this, &UDSScanWindow::scanUDS);
    connect(waitTimer, &QTimer::timeout, this, &UDSScanWindow::timeOut);

    ui->cbBuses->addItem("0");
    ui->cbBuses->addItem("1");
    ui->cbBuses->addItem("Both");

}

UDSScanWindow::~UDSScanWindow()
{
    delete ui;
    waitTimer->stop();
    delete waitTimer;
}

void UDSScanWindow::scanUDS()
{
    ui->listResults->clear();
    sendingFrames.clear();

    CANFrame frame;
    int typ, id;
    int startID, endID;
    startID = Utility::ParseStringToNum(ui->txtStartID->text());
    endID = Utility::ParseStringToNum(ui->txtEndID->text());

    int buses = ui->cbBuses->currentIndex();
    buses++;
    if (buses < 1) buses = 1;

    //start out by sending tester present to every address to see if anyone replies
    for (id = startID; id < endID; id++)
    {
        frame.ID = id;
        frame.len = 8;
        frame.extended = false;
        frame.data[0] = 2;
        frame.data[1] = 0x3E; //tester present
        frame.data[2] = 0;
        frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
        frame.data[6] = 0;frame.data[7] = 0;

        if (buses & 1)
        {
            frame.bus = 0;
            sendingFrames.append(frame);
        }
        if (buses & 2)
        {
            frame.bus = 1;
            sendingFrames.append(frame);
        }
    }

    //then try asking for the various diagnostic session types
    for (typ = 1; typ < 5; typ++)
    {
        for (id = startID; id <= endID; id++)
        {
            frame.ID = id;
            frame.len = 8;
            frame.extended = false;
            frame.data[0] = 2;
            frame.data[1] = 0x10;
            frame.data[2] = typ;
            frame.data[3] = 0;frame.data[4] = 0;frame.data[5] = 0;
            frame.data[6] = 0;frame.data[7] = 0;

            if (buses & 1)
            {
                frame.bus = 0;
                sendingFrames.append(frame);
            }
            if (buses & 2)
            {
                frame.bus = 1;
                sendingFrames.append(frame);
            }
        }
    }

    waitTimer->start();
    currIdx = -1;
    sendNextMsg();
}

void UDSScanWindow::updatedFrames(int numFrames)
{
    CANFrame thisFrame;
    QString result;
    int id;
    if (numFrames == -1) //all frames deleted. We don't care
    {
    }
    else if (numFrames == -2) //all new set of frames. Don't care.
    {
    }
    else //just got some new frames. See if they are relevant.
    {
        if (numFrames > modelFrames->count()) return;
        for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
        {
            thisFrame = modelFrames->at(i);
            id = thisFrame.ID;

            id -= ui->spinReplyOffset->value(); //back to original ECU id
            int numFrames = sendingFrames.length();

            if (numFrames > 0 && numFrames > currIdx && id == sendingFrames[currIdx].ID)
            {
                if (thisFrame.data[1] == 0x40 + sendingFrames[currIdx].data[1])
                {
                    result = "ECU at bus " + QString::number(thisFrame.bus) + " ID: " + QString::number(id, 16) + " responds to mode "
                        + QString::number(sendingFrames[currIdx].data[1], 16)
                        + " " + QString::number(sendingFrames[currIdx].data[2], 16) + " with affirmation.";
                }
                else if ( thisFrame.data[1] == 0x7F)
                {
                    result = "ECU at bus " + QString::number(thisFrame.bus) + " ID: " + QString::number(id, 16) + " responds to mode "
                        + QString::number(sendingFrames[currIdx].data[1], 16)
                        + " " + QString::number(sendingFrames[currIdx].data[2], 16) + " with an error.";
                }
                ui->listResults->addItem(result);
                sendNextMsg();
            }
        }
    }
}

void UDSScanWindow::timeOut()
{
    QString result;
    result = "ECU at bus " + QString::number(sendingFrames[currIdx].bus) + " ID: " + QString::number(sendingFrames[currIdx].ID, 16) + " did not respond to mode "
             + QString::number(sendingFrames[currIdx].data[1], 16) + " " + QString::number(sendingFrames[currIdx].data[2], 16);
    ui->listResults->addItem(result);

    sendNextMsg();
}

void UDSScanWindow::sendNextMsg()
{
    currIdx++;
    if (currIdx < sendingFrames.count())
    {
        emit sendCANFrame(&sendingFrames[currIdx], sendingFrames[currIdx].bus);
    }
    else
    {
        waitTimer->stop();
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Arvid Norberg
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 author 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.

*/

#include "test.hpp"
#include "setup_transfer.hpp"
#include "dht_server.hpp"
#include "peer_server.hpp"
#include "udp_tracker.hpp"
#include "test_utils.hpp"

#include "libtorrent/alert.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/alert_types.hpp"

#include <fstream>

using namespace libtorrent;
namespace lt = libtorrent;

char const* proxy_name[] = {
	"none",
	"socks4",
	"socks5",
	"socks5_pw",
	"http",
	"http_pw",
	"i2p_proxy"
};

std::vector<std::string> rejected_trackers;

bool alert_predicate(libtorrent::alert const* a)
{
	anonymous_mode_alert const* am = alert_cast<anonymous_mode_alert>(a);
	if (am == NULL) return false;

	if (am->kind == anonymous_mode_alert::tracker_not_anonymous)
		rejected_trackers.push_back(am->str);

	return false;
}

enum flags_t
{
	force_proxy_mode = 1,
	expect_http_connection = 2,
	expect_udp_connection = 4,
	expect_http_reject = 8,
	expect_udp_reject = 16,
	expect_dht_msg = 32,
	expect_peer_connection = 64,
	expect_possible_udp_connection = 128,
	expect_possible_dht_msg = 256,
};

session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags)
{
#ifdef TORRENT_DISABLE_DHT
	// if DHT is disabled, we won't get any requests to it
	flags &= ~expect_dht_msg;
#endif
	fprintf(stderr, "\n=== TEST == proxy: %s anonymous-mode: %s\n\n", proxy_name[proxy_type], (flags & force_proxy_mode) ? "yes" : "no");
	int http_port = start_web_server();
	int udp_port = start_udp_tracker();
	int dht_port = start_dht();
	int peer_port = start_peer();

	int prev_udp_announces = num_udp_announces();

	int const alert_mask = alert::all_categories
		& ~alert::progress_notification
		& ~alert::stats_notification;

	settings_pack sett;
	sett.set_int(settings_pack::stop_tracker_timeout, 2);
	sett.set_int(settings_pack::tracker_completion_timeout, 2);
	sett.set_int(settings_pack::tracker_receive_timeout, 2);
#ifndef TORRENT_NO_DEPRECATE
	sett.set_int(settings_pack::half_open_limit, 2);
#endif
	sett.set_bool(settings_pack::announce_to_all_trackers, true);
	sett.set_bool(settings_pack::announce_to_all_tiers, true);
	sett.set_bool(settings_pack::force_proxy, flags & force_proxy_mode);
	sett.set_int(settings_pack::alert_mask, alert_mask);
	sett.set_bool(settings_pack::enable_upnp, false);
	sett.set_bool(settings_pack::enable_natpmp, false);

	// since multiple sessions may exist simultaneously (because of the
	// pipelining of the tests) they actually need to use different ports
	static int listen_port = 10000 + libtorrent::random() % 50000;
	char iface[200];
	snprintf(iface, sizeof(iface), "127.0.0.1:%d", listen_port);
	listen_port += (libtorrent::random() % 10) + 1;
	sett.set_str(settings_pack::listen_interfaces, iface);
	sett.set_bool(settings_pack::enable_dht, true);

	// if we don't do this, the peer connection test
	// will be delayed by several seconds, by first
	// trying uTP
	sett.set_bool(settings_pack::enable_outgoing_utp, false);

	// in non-anonymous mode we circumvent/ignore the proxy if it fails
	// wheras in anonymous mode, we just fail
	sett.set_str(settings_pack::proxy_hostname, "non-existing.com");
	sett.set_int(settings_pack::proxy_type, (settings_pack::proxy_type_t)proxy_type);
	sett.set_int(settings_pack::proxy_port, 4444);

	lt::session* s = new lt::session(sett);

	error_code ec;
	remove_all("tmp1_privacy", ec);
	create_directory("tmp1_privacy", ec);
	std::ofstream file(combine_path("tmp1_privacy", "temporary").c_str());
	boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	char http_tracker_url[200];
	snprintf(http_tracker_url, sizeof(http_tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(http_tracker_url, 0);

	char udp_tracker_url[200];
	snprintf(udp_tracker_url, sizeof(udp_tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(udp_tracker_url, 1);

	add_torrent_params addp;
	addp.flags &= ~add_torrent_params::flag_paused;
	addp.flags &= ~add_torrent_params::flag_auto_managed;

	// we don't want to waste time checking the torrent, just go straight into
	// seeding it, announcing to trackers and connecting to peers
	addp.flags |= add_torrent_params::flag_seed_mode;

	addp.ti = t;
	addp.save_path = "tmp1_privacy";
	addp.dht_nodes.push_back(std::pair<std::string, int>("127.0.0.1", dht_port));
	torrent_handle h = s->add_torrent(addp);

	printf("connect_peer: 127.0.0.1:%d\n", peer_port);
	h.connect_peer(tcp::endpoint(address_v4::from_string("127.0.0.1"), peer_port));

	rejected_trackers.clear();

#ifdef TORRENT_USE_VALGRIND
	const int timeout = 100;
#else
	const int timeout = 20;
#endif

	for (int i = 0; i < timeout; ++i)
	{
		print_alerts(*s, "s", false, false, false, &alert_predicate);
		test_sleep(100);

		if (num_udp_announces() >= prev_udp_announces + 1
			&& num_peer_hits() > 0)
			break;
	}

	// we should have announced to the tracker by now
	if (flags & expect_possible_udp_connection)
	{
		// this flag is true if we may fail open, but also might not have had
		// enough time to fail yet
		TEST_CHECK(num_udp_announces() == prev_udp_announces
			|| num_udp_announces() == prev_udp_announces + 1);
	}
	else
	{
		TEST_EQUAL(num_udp_announces(), prev_udp_announces + bool(flags & expect_udp_connection));
	}

	if (flags & expect_possible_udp_connection)
	{
		// this flag is true if we may fail open, but also might not have had
		// enough time to fail yet
		TEST_CHECK(num_dht_hits() == 0 || num_dht_hits() == 1);
	}
	else
	{
		if (flags & expect_dht_msg)
		{
			TEST_CHECK(num_dht_hits() > 0);
		}
		else
		{
			TEST_EQUAL(num_dht_hits(), 0);
		}
	}

	if (flags & expect_peer_connection)
	{
		TEST_CHECK(num_peer_hits() > 0);
	}
	else
	{
		TEST_EQUAL(num_peer_hits(), 0);
	}

	if (flags & expect_udp_reject)
		TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end(), udp_tracker_url) != rejected_trackers.end());

	if (flags & expect_http_reject)
		TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end(), http_tracker_url) != rejected_trackers.end());

	fprintf(stderr, "%s: ~session\n", time_now_string());
	session_proxy pr = s->abort();
	delete s;

	stop_peer();
	stop_dht();
	stop_udp_tracker();
	stop_web_server();
	return pr;
}

// not using anonymous mode
// UDP fails open if we can't connect to the proxy
// or if the proxy doesn't support UDP

TORRENT_TEST(no_proxy)
{
	test_proxy(settings_pack::none, expect_udp_connection | expect_http_connection | expect_dht_msg | expect_peer_connection);
}

TORRENT_TEST(socks4)
{
	test_proxy(settings_pack::socks4, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(socks5)
{
	test_proxy(settings_pack::socks5, expect_possible_udp_connection | expect_possible_dht_msg);
}

TORRENT_TEST(socks5_pw)
{
	prtest_proxy(settings_pack::socks5_pw,expect_possible_udp_connection | expect_possible_dht_msg);
}

TORRENT_TEST(http)
{
	prtest_proxy(settings_pack::http, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(http_pt)
{
	prtest_proxy(settings_pack::http_pw, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(i2p)
{
	prtest_proxy(settings_pack::i2p_proxy, expect_udp_connection | expect_dht_msg);
}

// using anonymous mode

// anonymous mode doesn't require a proxy when one isn't configured. It could be
// used with a VPN for instance. This will all changed in 1.0, where anonymous
// mode is separated from force_proxy

TORRENT_TEST(anon_no_proxy)
{
	prtest_proxy(settings_pack::none, force_proxy_mode | expect_peer_connection);
}

TORRENT_TEST(anon_socks4)
{
	prtest_proxy(settings_pack::socks4, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_socks5)
{
	prtest_proxy(settings_pack::socks5, force_proxy_mode);
}

TORRENT_TEST(anon_socks5_pw)
{
	prtest_proxy(settings_pack::socks5_pw, force_proxy_mode);
}

TORRENT_TEST(anon_http)
{
	prtest_proxy(settings_pack::http, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_http_pw)
{
	prtest_proxy(settings_pack::http_pw, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_i2p)
{
	prtest_proxy(settings_pack::i2p_proxy, force_proxy_mode);
}

<commit_msg>fix silly typo<commit_after>/*

Copyright (c) 2013, Arvid Norberg
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 author 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.

*/

#include "test.hpp"
#include "setup_transfer.hpp"
#include "dht_server.hpp"
#include "peer_server.hpp"
#include "udp_tracker.hpp"
#include "test_utils.hpp"

#include "libtorrent/alert.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/alert_types.hpp"

#include <fstream>

using namespace libtorrent;
namespace lt = libtorrent;

char const* proxy_name[] = {
	"none",
	"socks4",
	"socks5",
	"socks5_pw",
	"http",
	"http_pw",
	"i2p_proxy"
};

std::vector<std::string> rejected_trackers;

bool alert_predicate(libtorrent::alert const* a)
{
	anonymous_mode_alert const* am = alert_cast<anonymous_mode_alert>(a);
	if (am == NULL) return false;

	if (am->kind == anonymous_mode_alert::tracker_not_anonymous)
		rejected_trackers.push_back(am->str);

	return false;
}

enum flags_t
{
	force_proxy_mode = 1,
	expect_http_connection = 2,
	expect_udp_connection = 4,
	expect_http_reject = 8,
	expect_udp_reject = 16,
	expect_dht_msg = 32,
	expect_peer_connection = 64,
	expect_possible_udp_connection = 128,
	expect_possible_dht_msg = 256,
};

session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags)
{
#ifdef TORRENT_DISABLE_DHT
	// if DHT is disabled, we won't get any requests to it
	flags &= ~expect_dht_msg;
#endif
	fprintf(stderr, "\n=== TEST == proxy: %s anonymous-mode: %s\n\n", proxy_name[proxy_type], (flags & force_proxy_mode) ? "yes" : "no");
	int http_port = start_web_server();
	int udp_port = start_udp_tracker();
	int dht_port = start_dht();
	int peer_port = start_peer();

	int prev_udp_announces = num_udp_announces();

	int const alert_mask = alert::all_categories
		& ~alert::progress_notification
		& ~alert::stats_notification;

	settings_pack sett;
	sett.set_int(settings_pack::stop_tracker_timeout, 2);
	sett.set_int(settings_pack::tracker_completion_timeout, 2);
	sett.set_int(settings_pack::tracker_receive_timeout, 2);
#ifndef TORRENT_NO_DEPRECATE
	sett.set_int(settings_pack::half_open_limit, 2);
#endif
	sett.set_bool(settings_pack::announce_to_all_trackers, true);
	sett.set_bool(settings_pack::announce_to_all_tiers, true);
	sett.set_bool(settings_pack::force_proxy, flags & force_proxy_mode);
	sett.set_int(settings_pack::alert_mask, alert_mask);
	sett.set_bool(settings_pack::enable_upnp, false);
	sett.set_bool(settings_pack::enable_natpmp, false);

	// since multiple sessions may exist simultaneously (because of the
	// pipelining of the tests) they actually need to use different ports
	static int listen_port = 10000 + libtorrent::random() % 50000;
	char iface[200];
	snprintf(iface, sizeof(iface), "127.0.0.1:%d", listen_port);
	listen_port += (libtorrent::random() % 10) + 1;
	sett.set_str(settings_pack::listen_interfaces, iface);
	sett.set_bool(settings_pack::enable_dht, true);

	// if we don't do this, the peer connection test
	// will be delayed by several seconds, by first
	// trying uTP
	sett.set_bool(settings_pack::enable_outgoing_utp, false);

	// in non-anonymous mode we circumvent/ignore the proxy if it fails
	// wheras in anonymous mode, we just fail
	sett.set_str(settings_pack::proxy_hostname, "non-existing.com");
	sett.set_int(settings_pack::proxy_type, (settings_pack::proxy_type_t)proxy_type);
	sett.set_int(settings_pack::proxy_port, 4444);

	lt::session* s = new lt::session(sett);

	error_code ec;
	remove_all("tmp1_privacy", ec);
	create_directory("tmp1_privacy", ec);
	std::ofstream file(combine_path("tmp1_privacy", "temporary").c_str());
	boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	char http_tracker_url[200];
	snprintf(http_tracker_url, sizeof(http_tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(http_tracker_url, 0);

	char udp_tracker_url[200];
	snprintf(udp_tracker_url, sizeof(udp_tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(udp_tracker_url, 1);

	add_torrent_params addp;
	addp.flags &= ~add_torrent_params::flag_paused;
	addp.flags &= ~add_torrent_params::flag_auto_managed;

	// we don't want to waste time checking the torrent, just go straight into
	// seeding it, announcing to trackers and connecting to peers
	addp.flags |= add_torrent_params::flag_seed_mode;

	addp.ti = t;
	addp.save_path = "tmp1_privacy";
	addp.dht_nodes.push_back(std::pair<std::string, int>("127.0.0.1", dht_port));
	torrent_handle h = s->add_torrent(addp);

	printf("connect_peer: 127.0.0.1:%d\n", peer_port);
	h.connect_peer(tcp::endpoint(address_v4::from_string("127.0.0.1"), peer_port));

	rejected_trackers.clear();

#ifdef TORRENT_USE_VALGRIND
	const int timeout = 100;
#else
	const int timeout = 20;
#endif

	for (int i = 0; i < timeout; ++i)
	{
		print_alerts(*s, "s", false, false, false, &alert_predicate);
		test_sleep(100);

		if (num_udp_announces() >= prev_udp_announces + 1
			&& num_peer_hits() > 0)
			break;
	}

	// we should have announced to the tracker by now
	if (flags & expect_possible_udp_connection)
	{
		// this flag is true if we may fail open, but also might not have had
		// enough time to fail yet
		TEST_CHECK(num_udp_announces() == prev_udp_announces
			|| num_udp_announces() == prev_udp_announces + 1);
	}
	else
	{
		TEST_EQUAL(num_udp_announces(), prev_udp_announces + bool(flags & expect_udp_connection));
	}

	if (flags & expect_possible_udp_connection)
	{
		// this flag is true if we may fail open, but also might not have had
		// enough time to fail yet
		TEST_CHECK(num_dht_hits() == 0 || num_dht_hits() == 1);
	}
	else
	{
		if (flags & expect_dht_msg)
		{
			TEST_CHECK(num_dht_hits() > 0);
		}
		else
		{
			TEST_EQUAL(num_dht_hits(), 0);
		}
	}

	if (flags & expect_peer_connection)
	{
		TEST_CHECK(num_peer_hits() > 0);
	}
	else
	{
		TEST_EQUAL(num_peer_hits(), 0);
	}

	if (flags & expect_udp_reject)
		TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end(), udp_tracker_url) != rejected_trackers.end());

	if (flags & expect_http_reject)
		TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end(), http_tracker_url) != rejected_trackers.end());

	fprintf(stderr, "%s: ~session\n", time_now_string());
	session_proxy pr = s->abort();
	delete s;

	stop_peer();
	stop_dht();
	stop_udp_tracker();
	stop_web_server();
	return pr;
}

// not using anonymous mode
// UDP fails open if we can't connect to the proxy
// or if the proxy doesn't support UDP

TORRENT_TEST(no_proxy)
{
	test_proxy(settings_pack::none, expect_udp_connection | expect_http_connection | expect_dht_msg | expect_peer_connection);
}

TORRENT_TEST(socks4)
{
	test_proxy(settings_pack::socks4, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(socks5)
{
	test_proxy(settings_pack::socks5, expect_possible_udp_connection | expect_possible_dht_msg);
}

TORRENT_TEST(socks5_pw)
{
	test_proxy(settings_pack::socks5_pw,expect_possible_udp_connection | expect_possible_dht_msg);
}

TORRENT_TEST(http)
{
	test_proxy(settings_pack::http, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(http_pt)
{
	test_proxy(settings_pack::http_pw, expect_udp_connection | expect_dht_msg);
}

TORRENT_TEST(i2p)
{
	test_proxy(settings_pack::i2p_proxy, expect_udp_connection | expect_dht_msg);
}

// using anonymous mode

// anonymous mode doesn't require a proxy when one isn't configured. It could be
// used with a VPN for instance. This will all changed in 1.0, where anonymous
// mode is separated from force_proxy

TORRENT_TEST(anon_no_proxy)
{
	test_proxy(settings_pack::none, force_proxy_mode | expect_peer_connection);
}

TORRENT_TEST(anon_socks4)
{
	test_proxy(settings_pack::socks4, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_socks5)
{
	test_proxy(settings_pack::socks5, force_proxy_mode);
}

TORRENT_TEST(anon_socks5_pw)
{
	test_proxy(settings_pack::socks5_pw, force_proxy_mode);
}

TORRENT_TEST(anon_http)
{
	test_proxy(settings_pack::http, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_http_pw)
{
	test_proxy(settings_pack::http_pw, force_proxy_mode | expect_udp_reject);
}

TORRENT_TEST(anon_i2p)
{
	test_proxy(settings_pack::i2p_proxy, force_proxy_mode);
}

<|endoftext|>