<commit_before>/*************************************************************************
    > File Name: fileloader.cpp
    > Author: anryyang
    > Mail: anryyang@gmail.com
    > Created Time: Tue 06 Dec 2016 05:13:05 PM
 ************************************************************************/

#include "fileloader.h"
// #include "timer.h"

void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}

BigFileLoader::BigFileLoader(std::string file_path):
    m_file_path(file_path){
    load();
}

BigFileLoader::~BigFileLoader(){
    free();
}

void BigFileLoader::load(){
    auto f = map_file();
    auto l = f + m_length;

    m_line_num = 0;
    while (f && f!=l){
        auto e = f;
        if ((f = static_cast<const char*>(memchr(f, '\n', l-f)))){
            Line line = std::make_pair(e, f-e);
            m_lines.push_back(line);
            m_line_num++;
            f++;
        }
    }
 }

const char* BigFileLoader::map_file(){
    m_fd = open(m_file_path.c_str(), O_RDONLY);
    if (-1 == m_fd)
        handle_error("open");

    posix_fadvise(m_fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

    // obtain file size
    struct stat sb;
    if (-1 == fstat(m_fd, &sb))
        handle_error("fstat");

    m_length = sb.st_size;

    // const char* addr = static_cast<const char*>(mmap(NULL, m_length, PROT_READ, MAP_PRIVATE, m_fd, 0u));
    m_file_ptr = static_cast<char*>(mmap(NULL, m_length, PROT_READ, MAP_PRIVATE, m_fd, 0u));
    const char* addr = m_file_ptr;
    if (addr == MAP_FAILED)
        handle_error("mmap");

    // TODO close fd at some point in time, call munmap(...)
    // close(m_fd);
    // munmap(m_file_ptr, m_length);

    return addr;
}

uintmax_t BigFileLoader::line_num(){
    return m_line_num;
}

std::size_t BigFileLoader::size(){
    return m_length;
}

std::string BigFileLoader::get_line(uintmax_t line_num){
    if(line_num >= m_line_num) return "";
    std::string str(m_lines[line_num].first, m_lines[line_num].second);
    return str;
}

void BigFileLoader::free(){
    m_lines.clear();
    if(m_file_ptr!=NULL){
        if( -1 == munmap( m_file_ptr, m_length ) ){
            handle_error("munmap");
        }
    }
    if(m_fd>0) close(m_fd);
    m_file_ptr = NULL;
    m_length = 0;
    m_line_num = 0;
}

// int main(){
//     Timer timer;
//     timer.start();
//     BigFileLoader loader("graph.txt");
//     timer.stop();
//     std::cout << " line number:" << loader.line_num()
//               << " file size:" << loader.size()
//               << " time:" << timer.elapsed()
//               << std::endl;
//     for(int i=0;i<10;i++){
//         std::cout << "line" << i << " :" << loader.get_line(i) << std::endl;
//     }

//     loader.free();
// }<commit_msg>add free memory func<commit_after>/*************************************************************************
    > File Name: fileloader.cpp
    > Author: anryyang
    > Mail: anryyang@gmail.com
    > Created Time: Tue 06 Dec 2016 05:13:05 PM
 ************************************************************************/

#include "fileloader.h"
// #include "timer.h"

void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}

BigFileLoader::BigFileLoader(std::string file_path):
    m_file_path(file_path){
    load();
}

BigFileLoader::~BigFileLoader(){
    free();
}

void BigFileLoader::load(){
    auto f = map_file();
    auto l = f + m_length;

    m_line_num = 0;
    while (f && f!=l){
        auto e = f;
        if ((f = static_cast<const char*>(memchr(f, '\n', l-f)))){
            Line line = std::make_pair(e, f-e);
            m_lines.push_back(line);
            m_line_num++;
            f++;
        }
    }
 }

const char* BigFileLoader::map_file(){
    m_fd = open(m_file_path.c_str(), O_RDONLY);
    if (-1 == m_fd)
        handle_error("open");

    posix_fadvise(m_fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

    // obtain file size
    struct stat sb;
    if (-1 == fstat(m_fd, &sb))
        handle_error("fstat");

    m_length = sb.st_size;

    // const char* addr = static_cast<const char*>(mmap(NULL, m_length, PROT_READ, MAP_PRIVATE, m_fd, 0u));
    m_file_ptr = static_cast<char*>(mmap(NULL, m_length, PROT_READ, MAP_PRIVATE, m_fd, 0u));
    const char* addr = m_file_ptr;
    if (addr == MAP_FAILED)
        handle_error("mmap");

    // TODO close fd at some point in time, call munmap(...)
    // close(m_fd);
    // munmap(m_file_ptr, m_length);

    return addr;
}

uintmax_t BigFileLoader::line_num(){
    return m_line_num;
}

std::size_t BigFileLoader::size(){
    return m_length;
}

std::string BigFileLoader::get_line(uintmax_t line_num){
    if(line_num >= m_line_num) return "";
    std::string str(m_lines[line_num].first, m_lines[line_num].second);
    return str;
}

void BigFileLoader::free(){
    m_lines.clear();
    if(m_file_ptr!=NULL){
        if( -1 == munmap( m_file_ptr, m_length ) ){
            handle_error("munmap");
        }
    }
    if(m_fd>0)
        close(m_fd);
    m_file_ptr = NULL;
    m_length = 0;
    m_line_num = 0;
}

// int main(){
//     Timer timer;
//     timer.start();
//     BigFileLoader loader("graph.txt");
//     timer.stop();
//     std::cout << " line number:" << loader.line_num()
//               << " file size:" << loader.size()
//               << " time:" << timer.elapsed()
//               << std::endl;
//     for(int i=0;i<10;i++){
//         std::cout << "line" << i << " :" << loader.get_line(i) << std::endl;
//     }

//     loader.free();
// }<|endoftext|>


<commit_before>#include "core/mesh.h"
#include "core/memory.h"
#include <vector>
NARUKAMI_BEGIN

  MeshData::MeshData(const Transform& object2wrold,int triangle_num,const uint32_t *indices,int vertex_num,const Point3f *vertices,const Normal3f *normals,const Point2f *uvs){
            assert(vertices!=nullptr);
            assert(indices!=nullptr);

            this->indices =  std::unique_ptr<uint32_t[]>(new uint32_t[triangle_num*3]);
            memcpy(this->indices.get(),indices,sizeof(uint32_t)*triangle_num*3);
            this->vertices=std::unique_ptr<Point3f[]>(new Point3f[vertex_num]);
            for(int i=0;i<vertex_num;++i){
                 this->vertices[i]=object2wrold(vertices[i]);
            }

            if(normals){
               this->normals=std::unique_ptr<Normal3f[]>(new Normal3f[vertex_num]);
               for(int i=0;i<vertex_num;++i){
                    this->normals[i]=object2wrold(normals[i]);
               }
            }

            if(uvs){
               this->uvs=std::unique_ptr<Point2f[]>(new Point2f[vertex_num]);
               for(int i=0;i<vertex_num;++i){
                    this->uvs[i]=uvs[i];
               }
            }

  }

  std::vector<SoATriangle> cast2SoA(const std::vector<std::shared_ptr<MeshTriangle>>& triangles,uint32_t start,uint32_t count){
        assert(count>0);
        assert((start+count)<=triangles.size());

        size_t soa_count = (uint32_t)count/SSE_FLOAT_COUNT + 1;

        std::vector<Point3f> v0_array;
        std::vector<Vector3f> e1_array;
        std::vector<Vector3f> e2_array;

        for(size_t i=0;i<soa_count*SSE_FLOAT_COUNT;++i){
            if(i<count){
                auto v0 = (*triangles[start+i])[0];
                auto e1 = (*triangles[start+i])[1]-v0;
                auto e2 = (*triangles[start+i])[2]-v0;

                v0_array.push_back(v0);
                e1_array.push_back(e1);
                e2_array.push_back(e2);
            }else{
                v0_array.push_back(Point3f());
                e1_array.push_back(Vector3f());
                e2_array.push_back(Vector3f());
            }

        }
        std::vector<SoATriangle> soa_triangles;

        for(size_t i=0;i<soa_count;++i){
            SoATriangle triangle;
            triangle.v0=load(&v0_array[i*SSE_FLOAT_COUNT]);
            triangle.e1=load(&e1_array[i*SSE_FLOAT_COUNT]);
            triangle.e2=load(&e2_array[i*SSE_FLOAT_COUNT]);
            soa_triangles.push_back(triangle);
        }

        return soa_triangles;

    }

std::vector<std::shared_ptr<MeshTriangle>> create_mesh_triangles(const Transform* object2wrold,const Transform* world2object,int triangle_num,const uint32_t *indices,int vertex_num,const Point3f *vertices,const Normal3f *normals,const Point2f *uvs){
     std::shared_ptr<MeshData> mesh_data=std::make_shared<MeshData>(*object2wrold,triangle_num,indices,vertex_num,vertices,normals,uvs);
     std::vector<std::shared_ptr<MeshTriangle>> triangles;
     for(int i=0;i<triangle_num;++i){
          triangles.push_back(std::make_shared<MeshTriangle>(object2wrold,world2object,mesh_data,&indices[3*i]));
     }
     return triangles;
}

NARUKAMI_END<commit_msg>add a TODO<commit_after>#include "core/mesh.h"
#include "core/memory.h"
#include <vector>
NARUKAMI_BEGIN

  MeshData::MeshData(const Transform& object2wrold,int triangle_num,const uint32_t *indices,int vertex_num,const Point3f *vertices,const Normal3f *normals,const Point2f *uvs){
            assert(vertices!=nullptr);
            assert(indices!=nullptr);

            this->indices =  std::unique_ptr<uint32_t[]>(new uint32_t[triangle_num*3]);
            memcpy(this->indices.get(),indices,sizeof(uint32_t)*triangle_num*3);
            this->vertices=std::unique_ptr<Point3f[]>(new Point3f[vertex_num]);
            for(int i=0;i<vertex_num;++i){
                 this->vertices[i]=object2wrold(vertices[i]);
            }

            if(normals){
               this->normals=std::unique_ptr<Normal3f[]>(new Normal3f[vertex_num]);
               for(int i=0;i<vertex_num;++i){
                    this->normals[i]=object2wrold(normals[i]);
               }
            }

            if(uvs){
               this->uvs=std::unique_ptr<Point2f[]>(new Point2f[vertex_num]);
               for(int i=0;i<vertex_num;++i){
                    this->uvs[i]=uvs[i];
               }
            }

  }

  //TODO SSE alignas
  std::vector<SoATriangle> cast2SoA(const std::vector<std::shared_ptr<MeshTriangle>>& triangles,uint32_t start,uint32_t count){
        assert(count>0);
        assert((start+count)<=triangles.size());

        size_t soa_count = (uint32_t)count/SSE_FLOAT_COUNT + 1;

        std::vector<Point3f> v0_array;
        std::vector<Vector3f> e1_array;
        std::vector<Vector3f> e2_array;

        for(size_t i=0;i<soa_count*SSE_FLOAT_COUNT;++i){
            if(i<count){
                auto v0 = (*triangles[start+i])[0];
                auto e1 = (*triangles[start+i])[1]-v0;
                auto e2 = (*triangles[start+i])[2]-v0;

                v0_array.push_back(v0);
                e1_array.push_back(e1);
                e2_array.push_back(e2);
            }else{
                v0_array.push_back(Point3f());
                e1_array.push_back(Vector3f());
                e2_array.push_back(Vector3f());
            }

        }
        std::vector<SoATriangle> soa_triangles;

        for(size_t i=0;i<soa_count;++i){
            SoATriangle triangle;
            triangle.v0=load(&v0_array[i*SSE_FLOAT_COUNT]);
            triangle.e1=load(&e1_array[i*SSE_FLOAT_COUNT]);
            triangle.e2=load(&e2_array[i*SSE_FLOAT_COUNT]);
            soa_triangles.push_back(triangle);
        }

        return soa_triangles;

    }

std::vector<std::shared_ptr<MeshTriangle>> create_mesh_triangles(const Transform* object2wrold,const Transform* world2object,int triangle_num,const uint32_t *indices,int vertex_num,const Point3f *vertices,const Normal3f *normals,const Point2f *uvs){
     std::shared_ptr<MeshData> mesh_data=std::make_shared<MeshData>(*object2wrold,triangle_num,indices,vertex_num,vertices,normals,uvs);
     std::vector<std::shared_ptr<MeshTriangle>> triangles;
     for(int i=0;i<triangle_num;++i){
          triangles.push_back(std::make_shared<MeshTriangle>(object2wrold,world2object,mesh_data,&indices[3*i]));
     }
     return triangles;
}

NARUKAMI_END<|endoftext|>


<commit_before>#include "regex.h"
#include <stdlib.h>
#include "pcre2.h"

using std::u16string;
using MatchResult = Regex::MatchResult;

const char16_t EMPTY_PATTERN[] = u".{0}";

Regex::Regex() : code{nullptr} {}

static u16string preprocess_pattern(const char16_t *pattern, uint32_t length) {
  u16string result;
  for (unsigned i = 0; i < length;) {
    char16_t c = pattern[i];

    // Replace escape sequences like '\u00cf' with their literal UTF16 value
    if (c == '\\' && i + 1 < length && pattern[i + 1] == 'u') {
      if (i + 6 <= length) {
        std::string char_code_string(&pattern[i + 2], &pattern[i + 6]);
        char16_t char_code_value = strtol(char_code_string.data(), nullptr, 16);
        if (char_code_value != 0) {
          result += char_code_value;
          i += 6;
          continue;
        }
      }

      // Replace invalid '\u' escape sequences with the literal characters '\' and 'u'
      result += u"\\\\u";
      i += 2;
      continue;
    }

    result += c;
    i++;
  }

  return result;
}

Regex::Regex(const char16_t *pattern, uint32_t pattern_length, u16string *error_message, bool ignore_case) {
  if (pattern_length == 0) {
    pattern = EMPTY_PATTERN;
    pattern_length = 4;
  }

  u16string final_pattern = preprocess_pattern(pattern, pattern_length);

  int error_number = 0;
  size_t error_offset = 0;
  uint32_t options = PCRE2_MULTILINE;
  if (ignore_case) options |= PCRE2_CASELESS;
  code = pcre2_compile(
    reinterpret_cast<const uint16_t *>(final_pattern.data()),
    final_pattern.size(),
    options,
    &error_number,
    &error_offset,
    nullptr
  );

  if (!code) {
    uint16_t message_buffer[256];
    size_t length = pcre2_get_error_message(error_number, message_buffer, 256);
    error_message->assign(message_buffer, message_buffer + length);
    return;
  }

  pcre2_jit_compile(
    code,
    PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_PARTIAL_SOFT
  );
}

Regex::Regex(const u16string &pattern, u16string *error_message, bool ignore_case)
  : Regex(pattern.data(), pattern.size(), error_message, ignore_case) {}

Regex::Regex(Regex &&other) : code{other.code} {
  other.code = nullptr;
}

Regex::~Regex() {
  if (code) pcre2_code_free(code);
}

Regex::MatchData::MatchData(const Regex &regex)
  : data{pcre2_match_data_create_from_pattern(regex.code, nullptr)} {}

Regex::MatchData::~MatchData() {
  pcre2_match_data_free(data);
}

MatchResult Regex::match(const char16_t *string, size_t length,
                         MatchData &match_data, unsigned options) const {
  MatchResult result{MatchResult::None, 0, 0};

  unsigned int pcre_options = 0;
  if (!(options & MatchOptions::IsEndSearch)) pcre_options |= PCRE2_PARTIAL_HARD;
  if (!(options & MatchOptions::IsBeginningOfLine)) pcre_options |= PCRE2_NOTBOL;
  if (!(options & MatchOptions::IsEndOfLine)) pcre_options |= PCRE2_NOTEOL;

  int status = pcre2_match(
    code,
    reinterpret_cast<const uint16_t *>(string),
    length,
    0,
    pcre_options,
    match_data.data,
    nullptr
  );

  if (status < 0) {
    switch (status) {
      case PCRE2_ERROR_PARTIAL:
        result.type = MatchResult::Partial;
        result.start_offset = pcre2_get_ovector_pointer(match_data.data)[0];
        result.end_offset = pcre2_get_ovector_pointer(match_data.data)[1];
        break;
      case PCRE2_ERROR_NOMATCH:
        result.type = MatchResult::None;
        break;
      default:
        result.type = MatchResult::Error;
        break;
    }
  } else {
    result.type = MatchResult::Full;
    result.start_offset = pcre2_get_ovector_pointer(match_data.data)[0];
    result.end_offset = pcre2_get_ovector_pointer(match_data.data)[1];
  }

  return result;
}
<commit_msg>Configure pcre2 to always treat \r and \n as newlines<commit_after>#include "regex.h"
#include <stdlib.h>
#include "pcre2.h"

using std::u16string;
using MatchResult = Regex::MatchResult;

const char16_t EMPTY_PATTERN[] = u".{0}";

Regex::Regex() : code{nullptr} {}

static u16string preprocess_pattern(const char16_t *pattern, uint32_t length) {
  u16string result;
  for (unsigned i = 0; i < length;) {
    char16_t c = pattern[i];

    // Replace escape sequences like '\u00cf' with their literal UTF16 value
    if (c == '\\' && i + 1 < length && pattern[i + 1] == 'u') {
      if (i + 6 <= length) {
        std::string char_code_string(&pattern[i + 2], &pattern[i + 6]);
        char16_t char_code_value = strtol(char_code_string.data(), nullptr, 16);
        if (char_code_value != 0) {
          result += char_code_value;
          i += 6;
          continue;
        }
      }

      // Replace invalid '\u' escape sequences with the literal characters '\' and 'u'
      result += u"\\\\u";
      i += 2;
      continue;
    }

    result += c;
    i++;
  }

  return result;
}

Regex::Regex(const char16_t *pattern, uint32_t pattern_length, u16string *error_message, bool ignore_case) {
  if (pattern_length == 0) {
    pattern = EMPTY_PATTERN;
    pattern_length = 4;
  }

  u16string final_pattern = preprocess_pattern(pattern, pattern_length);

  pcre2_compile_context *context = pcre2_compile_context_create(nullptr);
  pcre2_set_newline(context, PCRE2_NEWLINE_ANY);

  int error_number = 0;
  size_t error_offset = 0;
  uint32_t options = PCRE2_MULTILINE;
  if (ignore_case) options |= PCRE2_CASELESS;
  code = pcre2_compile(
    reinterpret_cast<const uint16_t *>(final_pattern.data()),
    final_pattern.size(),
    options,
    &error_number,
    &error_offset,
    context
  );
  pcre2_compile_context_free(context);

  if (!code) {
    uint16_t message_buffer[256];
    size_t length = pcre2_get_error_message(error_number, message_buffer, 256);
    error_message->assign(message_buffer, message_buffer + length);
    return;
  }

  pcre2_jit_compile(
    code,
    PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_PARTIAL_SOFT
  );
}

Regex::Regex(const u16string &pattern, u16string *error_message, bool ignore_case)
  : Regex(pattern.data(), pattern.size(), error_message, ignore_case) {}

Regex::Regex(Regex &&other) : code{other.code} {
  other.code = nullptr;
}

Regex::~Regex() {
  if (code) pcre2_code_free(code);
}

Regex::MatchData::MatchData(const Regex &regex)
  : data{pcre2_match_data_create_from_pattern(regex.code, nullptr)} {}

Regex::MatchData::~MatchData() {
  pcre2_match_data_free(data);
}

MatchResult Regex::match(const char16_t *string, size_t length,
                         MatchData &match_data, unsigned options) const {
  MatchResult result{MatchResult::None, 0, 0};

  unsigned int pcre_options = 0;
  if (!(options & MatchOptions::IsEndSearch)) pcre_options |= PCRE2_PARTIAL_HARD;
  if (!(options & MatchOptions::IsBeginningOfLine)) pcre_options |= PCRE2_NOTBOL;
  if (!(options & MatchOptions::IsEndOfLine)) pcre_options |= PCRE2_NOTEOL;

  int status = pcre2_match(
    code,
    reinterpret_cast<const uint16_t *>(string),
    length,
    0,
    pcre_options,
    match_data.data,
    nullptr
  );

  if (status < 0) {
    switch (status) {
      case PCRE2_ERROR_PARTIAL:
        result.type = MatchResult::Partial;
        result.start_offset = pcre2_get_ovector_pointer(match_data.data)[0];
        result.end_offset = pcre2_get_ovector_pointer(match_data.data)[1];
        break;
      case PCRE2_ERROR_NOMATCH:
        result.type = MatchResult::None;
        break;
      default:
        result.type = MatchResult::Error;
        break;
    }
  } else {
    result.type = MatchResult::Full;
    result.start_offset = pcre2_get_ovector_pointer(match_data.data)[0];
    result.end_offset = pcre2_get_ovector_pointer(match_data.data)[1];
  }

  return result;
}
<|endoftext|>


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

#include "csvhandle.h"

#include <QTextStream>
#include <QtCore/QtMath>

CSVHandle::CSVHandle(QObject *parent) : QObject(parent)
{
}

QStringList CSVHandle::loadCSV(QString path, CSVHandle::seperator sep, bool has_header, int column_word, int column_translation, int column_priority, bool import_priority)
{
    QStringList errors;

    if(column_priority < 0 || column_translation < 0 || column_word < 0)
    {
        errors << tr("All column indices must be positive or zero");
        return errors;
    }

    QFile file(path);

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QString error = QString(tr("Can not open file \"%1\": %2")).arg(path).arg(file.errorString());
        WARNING(error);
        errors << error;
        return errors;
    }

    QTextStream stream(&file);

    database.transaction();
    QSqlQuery q(database);
    QString s = "INSERT OR ABORT INTO vocabulary VALUES (?,?,100)";

    int need_num_columns = qMax(column_word, column_translation);
    QChar sep_char = getSeperator(sep);

    if(import_priority)
    {
        need_num_columns = qMax(need_num_columns, column_priority);
        s = "INSERT OR ABORT INTO vocabulary VALUES (?,?,?)";
    }

    if(has_header)
    {
        // Ignore header
        stream.readLine();
    }

    while(!stream.atEnd())
    {
        QString line = stream.readLine();
        QStringList columns = line.split(sep_char, QString::KeepEmptyParts);
        if(columns.size() < need_num_columns+1)
        {
            QString error = QString(tr("Error at \"%1\": Column to small")).arg(line);
            WARNING(error);
            errors << error;
            continue;
        }
        q.prepare(s);
        q.addBindValue(columns[column_word]);
        q.addBindValue(columns[column_translation]);
        if(import_priority)
        {
            bool ok = true;
            int priority = qBound(1, columns[column_priority].toInt(&ok), 100);
            if(!ok)
            {
                priority = 100;
                QString error = QString(tr("Can not convert \"%1\" to priority")).arg(columns[column_priority]);
                WARNING(error);
                errors << error;
            }
            q.addBindValue(priority);
        }

        if(!q.exec())
        {
            QString error = s.append(": ").append(q.lastError().text());
            WARNING(error);
            errors << error;
        }
    }

    if(!database.commit())
    {
        errors << database.lastError().text();
    }
    return errors;
}

QStringList CSVHandle::saveCSV(QString path, CSVHandle::seperator sep, bool write_header)
{
    QStringList errors;

    QFile file(path);

    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QString error = QString(tr("Can not open file \"%1\": %2")).arg(path).arg(file.errorString());
        WARNING(error);
        errors << error;
        return errors;
    }

    QTextStream stream(&file);

    QSqlQuery q(database);
    QString s = "SELECT word,translation,priority FROM vocabulary";

    if(!q.exec(s))
    {
        QString error = s.append(": ").append(q.lastError().text());
        WARNING(error);
        errors << error;
        file.close();
        return errors;
    }
    if(!q.isSelect())
    {
        QString error = s.append(": No select");
        WARNING(error);
        errors << error;
        file.close();
        return errors;
    }

    QChar sep_char = getSeperator(sep);

    if(write_header)
    {
        stream << QString(tr("word%1translation%1priority\n")).arg(sep_char);
    }

    while(q.next())
    {
        QString line;
        line.append(q.value(0).toString());
        line.append(sep_char);
        line.append(q.value(1).toString());
        line.append(sep_char);
        line.append(q.value(2).toString());
        line.append('\n');
        stream << line;
    }

    file.close();
    return errors;
}

QChar CSVHandle::getSeperator(CSVHandle::seperator sep)
{
    switch(sep)
    {
    case TAB:
        return QChar('\t');
        break;
    case SPACE:
        return QChar(' ');
        break;
    case COMMA:
        return QChar(',');
        break;
    case SEMICOLON:
        return QChar(';');
        break;
    }
    Q_UNREACHABLE();
}

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

#include "csvhandle.h"

#include <QTextStream>
#include <QtCore/QtMath>
#include <QTextCodec>

CSVHandle::CSVHandle(QObject *parent) : QObject(parent)
{
}

QStringList CSVHandle::loadCSV(QString path, CSVHandle::seperator sep, bool has_header, int column_word, int column_translation, int column_priority, bool import_priority)
{
    QStringList errors;

    if(column_priority < 0 || column_translation < 0 || column_word < 0)
    {
        errors << tr("All column indices must be positive or zero");
        return errors;
    }

    QFile file(path);

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QString error = QString(tr("Can not open file \"%1\": %2")).arg(path).arg(file.errorString());
        WARNING(error);
        errors << error;
        return errors;
    }

    QTextStream stream(&file);
    stream.setCodec(QTextCodec::codecForName("UTF-8"));

    database.transaction();
    QSqlQuery q(database);
    QString s = "INSERT OR ABORT INTO vocabulary VALUES (?,?,100)";

    int need_num_columns = qMax(column_word, column_translation);
    QChar sep_char = getSeperator(sep);

    if(import_priority)
    {
        need_num_columns = qMax(need_num_columns, column_priority);
        s = "INSERT OR ABORT INTO vocabulary VALUES (?,?,?)";
    }

    if(has_header)
    {
        // Ignore header
        stream.readLine();
    }

    while(!stream.atEnd())
    {
        QString line = stream.readLine();
        QStringList columns = line.split(sep_char, QString::KeepEmptyParts);
        if(columns.size() < need_num_columns+1)
        {
            QString error = QString(tr("Error at \"%1\": Column to small")).arg(line);
            WARNING(error);
            errors << error;
            continue;
        }
        q.prepare(s);
        q.addBindValue(columns[column_word]);
        q.addBindValue(columns[column_translation]);
        if(import_priority)
        {
            bool ok = true;
            int priority = qBound(1, columns[column_priority].toInt(&ok), 100);
            if(!ok)
            {
                priority = 100;
                QString error = QString(tr("Can not convert \"%1\" to priority")).arg(columns[column_priority]);
                WARNING(error);
                errors << error;
            }
            q.addBindValue(priority);
        }

        if(!q.exec())
        {
            QString error = s.append(": ").append(q.lastError().text());
            WARNING(error);
            errors << error;
        }
    }

    if(!database.commit())
    {
        errors << database.lastError().text();
    }
    return errors;
}

QStringList CSVHandle::saveCSV(QString path, CSVHandle::seperator sep, bool write_header)
{
    QStringList errors;

    QFile file(path);

    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QString error = QString(tr("Can not open file \"%1\": %2")).arg(path).arg(file.errorString());
        WARNING(error);
        errors << error;
        return errors;
    }

    QTextStream stream(&file);
    stream.setCodec(QTextCodec::codecForName("UTF-8"));

    QSqlQuery q(database);
    QString s = "SELECT word,translation,priority FROM vocabulary";

    if(!q.exec(s))
    {
        QString error = s.append(": ").append(q.lastError().text());
        WARNING(error);
        errors << error;
        file.close();
        return errors;
    }
    if(!q.isSelect())
    {
        QString error = s.append(": No select");
        WARNING(error);
        errors << error;
        file.close();
        return errors;
    }

    QChar sep_char = getSeperator(sep);

    if(write_header)
    {
        stream << QString(tr("word%1translation%1priority\n")).arg(sep_char);
    }

    while(q.next())
    {
        QString line;
        line.append(q.value(0).toString());
        line.append(sep_char);
        line.append(q.value(1).toString());
        line.append(sep_char);
        line.append(q.value(2).toString());
        line.append('\n');
        stream << line;
    }

    file.close();
    return errors;
}

QChar CSVHandle::getSeperator(CSVHandle::seperator sep)
{
    switch(sep)
    {
    case TAB:
        return QChar('\t');
        break;
    case SPACE:
        return QChar(' ');
        break;
    case COMMA:
        return QChar(',');
        break;
    case SEMICOLON:
        return QChar(';');
        break;
    }
    Q_UNREACHABLE();
}

<|endoftext|>


<commit_before>#include "cvm.h"
#include "../cshared/disasm.h"

void DabVM_debug::print_registers()
{
    fprintf(stderr, "IP = %p (%d)\n", (void *)vm.ip(), (int)vm.ip());
}

void DabVM_debug::print_ssa_registers()
{
    auto err_stream = $VM->options.output;
    fprintf(err_stream, "Registers:\n");
    size_t index = 0;
    for (const auto &reg : vm._registers)
    {
        fprintf(err_stream, "R%zu: ", index);
        reg.dump(err_stream);
        fprintf(err_stream, "\n");
    }
}

void DabVM_debug::print_classes()
{
    for (const auto &it : vm.classes)
    {
        fprintf(stderr, " - 0x%04x %s (super = 0x%04x)\n", it.first, it.second.name.c_str(),
                it.second.superclass_index);
        for (const auto &fin : it.second.static_functions)
        {
            fprintf(stderr, "   ::%s [%s]\n", $VM->get_symbol(fin.first).c_str(),
                    fin.second.regular ? "Dab" : "C");
        }
        for (const auto &fin : it.second.functions)
        {
            fprintf(stderr, "    .%s [%s]\n", $VM->get_symbol(fin.first).c_str(),
                    fin.second.regular ? "Dab" : "C");
        }
    }
}

void DabVM_debug::print_functions()
{
    for (auto it : vm.functions)
    {
        auto &fun = it.second;
        fprintf(stderr, " - %s: %s at %p\n", fun.name.c_str(), fun.regular ? "Dab" : "C",
                (void *)fun.address);
    }
}

void DabVM_debug::print_constants()
{
    auto output = $VM->options.output;
    fprintf(output, "symbols:\n");
    size_t i = 0;
    for (const auto &symbol : $VM->symbols)
    {
        fprintf(output, "%d: %s\n", (int)i, symbol.c_str());
        i++;
    }
}

void DabVM_debug::print_stack()
{
}

void DabVM_debug::print_code(bool current_only)
{
    prepare_disasm();

    auto err_stream = $VM->options.output;

    auto ip = vm.ip();

    fprintf(err_stream, "IP = %d\n", (int)ip);

    auto it = find_if(disasm.begin(), disasm.end(),
                      [ip](const std::pair<size_t, std::string> &obj) { return obj.first == ip; });

    if (it == disasm.end())
        return;

    auto index = std::distance(disasm.begin(), it);

    long start = current_only ? (index - 2) : 0;
    long end   = current_only ? (index + 3) : disasm.size();

    for (long i = start; i < end; i++)
    {
        if (i < 0 || i >= (int)disasm.size())
            continue;

        const auto &line = disasm[i];
        fprintf(err_stream, "%c %8ld: %s\n", line.first == ip ? '>' : ' ', line.first,
                line.second.c_str());
    }
}

struct InstructionsReader : public BaseReader
{
    DabVM &vm;

    const byte *_data;
    size_t      _length;

    size_t start_position = 0;

    InstructionsReader(DabVM &vm, size_t &position) : BaseReader(position), vm(vm)
    {
        _data   = vm.instructions.raw_base_data();
        _length = vm.instructions.raw_base_length();

        BinSection code_section;
        bool       has_code = false;

        for (auto &section : vm.sections)
        {
            if (std::string(section.name) == "code")
            {
                code_section = section;
                has_code     = true;
                break;
            }
        }

        if (!has_code)
            throw "no code?";

        start_position = code_section.pos;

        _data += start_position;
        _length = code_section.length;
    }

    virtual size_t raw_read(void *buffer, size_t size) override
    {
        auto data       = _data;
        auto length     = _length;
        auto offset     = position();
        auto max_length = std::min(size, length - offset);

        memcpy(buffer, data + offset, max_length);

        return max_length;
    }

    bool feof()
    {
        return false;
    }
};

void DabVM_debug::prepare_disasm()
{
    if (has_disasm)
        return;

    has_disasm = true;

    size_t                              position = 0;
    InstructionsReader                  reader(vm, position);
    DisasmProcessor<InstructionsReader> processor(reader);

    processor.go([this, reader](size_t pos, std::string info) {
        disasm.push_back(std::make_pair(pos + reader.start_position, info));
    });
}

void DabVM::execute_debug(Stream &input)
{
    auto err_stream = options.output;

    DabVM_debug debug(*this);
    while (!input.eof())
    {
        char rawcmd[2048];
        fprintf(stderr, "> ");
        fgets(rawcmd, sizeof(rawcmd), stdin);
        std::string cmd = rawcmd;

        cmd = cmd.substr(0, cmd.length() - 1);

        if (cmd == "help")
        {
            fprintf(err_stream, "Help:\n");
            fprintf(err_stream, "help - print this\n");
            fprintf(err_stream, "[s]tep - run single instruction\n");
            fprintf(err_stream, "[r]egisters - show registers\n");
            fprintf(err_stream, "classes - print classes\n");
            fprintf(err_stream, "functions - print functions\n");
            fprintf(err_stream, "constants - dump constants\n");
            fprintf(err_stream, "stack - dump stack\n");
            fprintf(err_stream, "code - show current code\n");
            fprintf(err_stream, "allcode - show all code\n");
            fprintf(err_stream, "run - run remaining instructions\n");
            fprintf(err_stream, "break [ip] - break at defined IP\n");
            fprintf(err_stream, "quit - quit\n");
        }
        else if (cmd == "step" || cmd == "s")
        {
            execute_single(input);
        }
        else if (cmd == "registers" || cmd == "r")
        {
            debug.print_registers();
        }
        else if (cmd == "classes")
        {
            debug.print_classes();
        }
        else if (cmd == "functions")
        {
            debug.print_functions();
        }
        else if (cmd == "constants")
        {
            debug.print_constants();
        }
        else if (cmd == "stack")
        {
            debug.print_stack();
        }
        else if (cmd == "ip")
        {
            fprintf(err_stream, "IP = %zu\n", ip());
        }
        else if (cmd == "code")
        {
            debug.print_code(true);
        }
        else if (cmd == "allcode")
        {
            debug.print_code(false);
        }
        else if (cmd == "quit")
        {
            exit(0);
        }
        else if (cmd == "run")
        {
            execute(input);
        }
        else if (cmd.substr(0, 6) == "break ")
        {
            int ip  = 0;
            int ret = sscanf(cmd.c_str(), "break %d", &ip);
            assert(ret == 1);
            fprintf(err_stream, "debug: break at %d.\n", ip);
            breakpoints.insert(ip);
        }
        else if (cmd == "ssaregs")
        {
            debug.print_ssa_registers();
        }
        else
        {
            fprintf(stderr, "Unknown command, type <help> to get available commands.\n");
        }
    }
}
<commit_msg>vm: fix debug type specifier on windows<commit_after>#include "cvm.h"
#include "../cshared/disasm.h"

void DabVM_debug::print_registers()
{
    fprintf(stderr, "IP = %p (%d)\n", (void *)vm.ip(), (int)vm.ip());
}

void DabVM_debug::print_ssa_registers()
{
    auto err_stream = $VM->options.output;
    fprintf(err_stream, "Registers:\n");
    size_t index = 0;
    for (const auto &reg : vm._registers)
    {
        fprintf(err_stream, "R%zu: ", index);
        reg.dump(err_stream);
        fprintf(err_stream, "\n");
    }
}

void DabVM_debug::print_classes()
{
    for (const auto &it : vm.classes)
    {
        fprintf(stderr, " - 0x%04x %s (super = 0x%04x)\n", it.first, it.second.name.c_str(),
                it.second.superclass_index);
        for (const auto &fin : it.second.static_functions)
        {
            fprintf(stderr, "   ::%s [%s]\n", $VM->get_symbol(fin.first).c_str(),
                    fin.second.regular ? "Dab" : "C");
        }
        for (const auto &fin : it.second.functions)
        {
            fprintf(stderr, "    .%s [%s]\n", $VM->get_symbol(fin.first).c_str(),
                    fin.second.regular ? "Dab" : "C");
        }
    }
}

void DabVM_debug::print_functions()
{
    for (auto it : vm.functions)
    {
        auto &fun = it.second;
        fprintf(stderr, " - %s: %s at %p\n", fun.name.c_str(), fun.regular ? "Dab" : "C",
                (void *)fun.address);
    }
}

void DabVM_debug::print_constants()
{
    auto output = $VM->options.output;
    fprintf(output, "symbols:\n");
    size_t i = 0;
    for (const auto &symbol : $VM->symbols)
    {
        fprintf(output, "%d: %s\n", (int)i, symbol.c_str());
        i++;
    }
}

void DabVM_debug::print_stack()
{
}

void DabVM_debug::print_code(bool current_only)
{
    prepare_disasm();

    auto err_stream = $VM->options.output;

    auto ip = vm.ip();

    fprintf(err_stream, "IP = %d\n", (int)ip);

    auto it = find_if(disasm.begin(), disasm.end(),
                      [ip](const std::pair<size_t, std::string> &obj) { return obj.first == ip; });

    if (it == disasm.end())
        return;

    auto index = std::distance(disasm.begin(), it);

    long start = current_only ? (index - 2) : 0;
    long end   = current_only ? (index + 3) : disasm.size();

    for (long i = start; i < end; i++)
    {
        if (i < 0 || i >= (int)disasm.size())
            continue;

        const auto &line = disasm[i];
        fprintf(err_stream, "%c %8" PRIu64 ": %s\n", line.first == ip ? '>' : ' ', line.first,
                line.second.c_str());
    }
}

struct InstructionsReader : public BaseReader
{
    DabVM &vm;

    const byte *_data;
    size_t      _length;

    size_t start_position = 0;

    InstructionsReader(DabVM &vm, size_t &position) : BaseReader(position), vm(vm)
    {
        _data   = vm.instructions.raw_base_data();
        _length = vm.instructions.raw_base_length();

        BinSection code_section;
        bool       has_code = false;

        for (auto &section : vm.sections)
        {
            if (std::string(section.name) == "code")
            {
                code_section = section;
                has_code     = true;
                break;
            }
        }

        if (!has_code)
            throw "no code?";

        start_position = code_section.pos;

        _data += start_position;
        _length = code_section.length;
    }

    virtual size_t raw_read(void *buffer, size_t size) override
    {
        auto data       = _data;
        auto length     = _length;
        auto offset     = position();
        auto max_length = std::min(size, length - offset);

        memcpy(buffer, data + offset, max_length);

        return max_length;
    }

    bool feof()
    {
        return false;
    }
};

void DabVM_debug::prepare_disasm()
{
    if (has_disasm)
        return;

    has_disasm = true;

    size_t                              position = 0;
    InstructionsReader                  reader(vm, position);
    DisasmProcessor<InstructionsReader> processor(reader);

    processor.go([this, reader](size_t pos, std::string info) {
        disasm.push_back(std::make_pair(pos + reader.start_position, info));
    });
}

void DabVM::execute_debug(Stream &input)
{
    auto err_stream = options.output;

    DabVM_debug debug(*this);
    while (!input.eof())
    {
        char rawcmd[2048];
        fprintf(stderr, "> ");
        fgets(rawcmd, sizeof(rawcmd), stdin);
        std::string cmd = rawcmd;

        cmd = cmd.substr(0, cmd.length() - 1);

        if (cmd == "help")
        {
            fprintf(err_stream, "Help:\n");
            fprintf(err_stream, "help - print this\n");
            fprintf(err_stream, "[s]tep - run single instruction\n");
            fprintf(err_stream, "[r]egisters - show registers\n");
            fprintf(err_stream, "classes - print classes\n");
            fprintf(err_stream, "functions - print functions\n");
            fprintf(err_stream, "constants - dump constants\n");
            fprintf(err_stream, "stack - dump stack\n");
            fprintf(err_stream, "code - show current code\n");
            fprintf(err_stream, "allcode - show all code\n");
            fprintf(err_stream, "run - run remaining instructions\n");
            fprintf(err_stream, "break [ip] - break at defined IP\n");
            fprintf(err_stream, "quit - quit\n");
        }
        else if (cmd == "step" || cmd == "s")
        {
            execute_single(input);
        }
        else if (cmd == "registers" || cmd == "r")
        {
            debug.print_registers();
        }
        else if (cmd == "classes")
        {
            debug.print_classes();
        }
        else if (cmd == "functions")
        {
            debug.print_functions();
        }
        else if (cmd == "constants")
        {
            debug.print_constants();
        }
        else if (cmd == "stack")
        {
            debug.print_stack();
        }
        else if (cmd == "ip")
        {
            fprintf(err_stream, "IP = %zu\n", ip());
        }
        else if (cmd == "code")
        {
            debug.print_code(true);
        }
        else if (cmd == "allcode")
        {
            debug.print_code(false);
        }
        else if (cmd == "quit")
        {
            exit(0);
        }
        else if (cmd == "run")
        {
            execute(input);
        }
        else if (cmd.substr(0, 6) == "break ")
        {
            int ip  = 0;
            int ret = sscanf(cmd.c_str(), "break %d", &ip);
            assert(ret == 1);
            fprintf(err_stream, "debug: break at %d.\n", ip);
            breakpoints.insert(ip);
        }
        else if (cmd == "ssaregs")
        {
            debug.print_ssa_registers();
        }
        else
        {
            fprintf(stderr, "Unknown command, type <help> to get available commands.\n");
        }
    }
}
<|endoftext|>


<commit_before>/*
 * cgreterm.hpp
 *
 *  Created on: 18.08.2014
 *      Author: andreas
 */

#ifndef CGRETERM_HPP_
#define CGRETERM_HPP_

#include <bitset>
#include <vector>
#include <string>
#include <ostream>
#include <exception>

#include <rofl/common/crofdpt.h>
#include <rofl/common/cdptid.h>
#include <rofl/common/openflow/cofmatch.h>
#include <rofl/common/protocols/fipv4frame.h>
#include <rofl/common/protocols/fipv6frame.h>
#include <rofl/common/protocols/fudpframe.h>
#include <rofl/common/openflow/experimental/actions/gre_actions.h>

#include <roflibs/netlink/clogging.hpp>

namespace roflibs {
namespace gre {

class eGreTermBase : public std::runtime_error {
public:
	eGreTermBase(const std::string& __arg) : std::runtime_error(__arg) {};
};
class eGreTermNotFound : public eGreTermBase {
public:
	eGreTermNotFound(const std::string& __arg) : eGreTermBase(__arg) {};
};

/*
 * -ingress- means: send traffic into the tunnel
 * -egress-  means: strip the tunnel and send traffic to the external world
 */
class cgreterm {
public:

	/**
	 *
	 */
	cgreterm() :
		state(STATE_DETACHED), eth_ofp_table_id(0), gre_ofp_table_id(0), ip_fwd_ofp_table_id(0),
		idle_timeout(DEFAULT_IDLE_TIMEOUT),
		gre_portno(0), gre_key(0) {};

	/**
	 *
	 */
	~cgreterm() {};

	/**
	 *
	 */
	cgreterm(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id,
			uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			uint32_t gre_portno, uint32_t gre_key) :
		state(STATE_DETACHED), dpid(dpid), eth_ofp_table_id(eth_ofp_table_id),
		gre_ofp_table_id(gre_ofp_table_id), ip_fwd_ofp_table_id(ip_fwd_ofp_table_id),
		idle_timeout(DEFAULT_IDLE_TIMEOUT),
		gre_portno(gre_portno), gre_key(gre_key) {};

	/**
	 *
	 */
	cgreterm(const cgreterm& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm&
	operator= (const cgreterm& greterm) {
		if (this == &greterm)
			return *this;
		state 				= greterm.state;
		dpid 				= greterm.dpid;
		eth_ofp_table_id 	= greterm.eth_ofp_table_id;
		gre_ofp_table_id 	= greterm.gre_ofp_table_id;
		ip_fwd_ofp_table_id	= greterm.ip_fwd_ofp_table_id;
		idle_timeout 		= greterm.idle_timeout;
		gre_portno 			= greterm.gre_portno;
		gre_key 			= greterm.gre_key;
		return *this;
	};

public:

	/**
	 *
	 */
	const uint32_t&
	get_gre_key() const { return gre_key; };

	/**
	 *
	 */
	const uint32_t&
	get_gre_portno() const { return gre_portno; };

protected:

	/**
	 *
	 */
	void
	execute(
			std::string const& executable,
			std::vector<std::string> argv,
			std::vector<std::string> envp);

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm& greterm) {
		os << rofcore::indent(0) << "<cgreterm key:0x"
				<< std::hex << (unsigned int)greterm.get_gre_key() << std::dec << " >" << std::endl;
		return os;
	};

protected:

	enum ofp_state_t {
		STATE_DETACHED = 1,
		STATE_ATTACHED = 2,
	};
	enum ofp_state_t 		state;

	enum cgreterm_flags_t {
		FLAG_INGRESS_FM_INSTALLED 	= (1 << 0),
		FLAG_EGRESS_FM_INSTALLED 	= (1 << 1),
	};
	std::bitset<32>			flags;

	rofl::cdpid 			dpid;
	uint8_t					eth_ofp_table_id;				// OFP tableid for capturing plain ethernet frames (table 0)
	uint8_t 				gre_ofp_table_id;				// OFP tableid for installing GRE-pop entries
	uint8_t					ip_fwd_ofp_table_id;			// OFP tableid for forwarding IP datagrams
	static const int 		DEFAULT_IDLE_TIMEOUT = 15; 		// seconds
	int 					idle_timeout;

	std::string				gre_portname;
	uint32_t				gre_portno; 					// portno of ethernet port
	uint32_t				gre_key;							// GRE key according to IETF RFC 2890
	static const uint8_t	GRE_IP_PROTO = 47;
	static const uint16_t 	GRE_PROT_TYPE_TRANSPARENT_ETHERNET_BRIDGING = 0x6558;

	static std::string		script_path_init;
	static std::string		script_path_term;
};

class cgreterm_in4 : public cgreterm {
public:

	/**
	 *
	 */
	cgreterm_in4() {};

	/**
	 *
	 */
	~cgreterm_in4() {
		try {
			if (STATE_ATTACHED == state) {
				handle_dpt_close(rofl::crofdpt::get_dpt(dpid));
			}
		} catch (rofl::eRofDptNotFound& e) {};
		hook_term();
	};

	/**
	 *
	 */
	cgreterm_in4(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id, uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			const rofl::caddress_in4& laddr, const rofl::caddress_in4& raddr, uint32_t gre_portno, uint32_t gre_key) :
		cgreterm(dpid, eth_ofp_table_id, gre_ofp_table_id, ip_fwd_ofp_table_id, gre_portno, gre_key),
		laddr(laddr), raddr(raddr) {
		hook_init();
	};

	/**
	 *
	 */
	cgreterm_in4(const cgreterm_in4& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm_in4&
	operator= (const cgreterm_in4& greterm) {
		if (this == &greterm)
			return *this;
		cgreterm::operator= (greterm);
		laddr = greterm.laddr;
		raddr = greterm.raddr;
		return *this;
	};

	/**
	 *
	 */
	bool
	operator< (const cgreterm_in4& greterm) const {
		return (raddr < greterm.raddr);
	};

public:

	/**
	 *
	 */
	const rofl::caddress_in4&
	get_local_addr() const { return laddr; };

	/**
	 *
	 */
	const rofl::caddress_in4&
	get_remote_addr() const { return raddr; };

public:

	/**
	 *
	 */
	void
	handle_dpt_open(rofl::crofdpt& dpt) {
		handle_dpt_open_egress(dpt);
		handle_dpt_open_ingress(dpt);
	};

	/**
	 *
	 */
	void
	handle_dpt_close(rofl::crofdpt& dpt) {
		handle_dpt_close_egress(dpt);
		handle_dpt_close_ingress(dpt);
	};

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm_in4& greterm) {
		os << dynamic_cast<const cgreterm&>( greterm );
		os << rofcore::indent(2) << "<cgreterm_in4 laddr:" << greterm.get_local_addr().str()
				<< " <==> raddr:" << greterm.get_remote_addr().str() << " >" << std::endl;
		return os;
	};

private:

	/**
	 *
	 */
	void
	handle_dpt_open_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_open_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	hook_init();

	/**
	 *
	 */
	void
	hook_term();

private:

	rofl::caddress_in4 laddr;
	rofl::caddress_in4 raddr;
};

class cgreterm_in6 : public cgreterm {
public:

	/**
	 *
	 */
	cgreterm_in6() {};

	/**
	 *
	 */
	~cgreterm_in6() {
		try {
			if (STATE_ATTACHED == state) {
				handle_dpt_close(rofl::crofdpt::get_dpt(dpid));
			}
		} catch (rofl::eRofDptNotFound& e) {};
		hook_term();
	};

	/**
	 *
	 */
	cgreterm_in6(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id, uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			const rofl::caddress_in6& laddr, const rofl::caddress_in6& raddr, uint32_t gre_portno, uint32_t gre_key) :
		cgreterm(dpid, eth_ofp_table_id, gre_ofp_table_id, ip_fwd_ofp_table_id, gre_portno, gre_key),
		laddr(laddr), raddr(raddr) {
		hook_init();
	};

	/**
	 *
	 */
	cgreterm_in6(const cgreterm_in6& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm_in6&
	operator= (const cgreterm_in6& greterm) {
		if (this == &greterm)
			return *this;
		cgreterm::operator= (greterm);
		laddr = greterm.laddr;
		raddr = greterm.raddr;
		return *this;
	};

	/**
	 *
	 */
	bool
	operator< (const cgreterm_in6& greterm) const {
		return (raddr < greterm.raddr);
	};

public:

	/**
	 *
	 */
	const rofl::caddress_in6&
	get_local_addr() const { return laddr; };

	/**
	 *
	 */
	const rofl::caddress_in6&
	get_remote_addr() const { return raddr; };

public:

	/**
	 *
	 */
	void
	handle_dpt_open(rofl::crofdpt& dpt) {
		handle_dpt_open_egress(dpt);
		handle_dpt_open_ingress(dpt);
	};

	/**
	 *
	 */
	void
	handle_dpt_close(rofl::crofdpt& dpt) {
		handle_dpt_close_egress(dpt);
		handle_dpt_close_ingress(dpt);
	};

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm_in6& greterm) {
		os << dynamic_cast<const cgreterm&>( greterm );
		os << rofcore::indent(2) << "<cgreterm_in6 laddr:" << greterm.get_local_addr().str()
				<< " <==> raddr:" << greterm.get_remote_addr().str() << " >" << std::endl;
		return os;
	};

private:

	/**
	 *
	 */
	void
	handle_dpt_open_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_open_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	hook_init();

	/**
	 *
	 */
	void
	hook_term();

private:

	rofl::caddress_in6 laddr;
	rofl::caddress_in6 raddr;
};

}; // end of namespace gre
}; // end of namespace roflibs

#endif /* CGRETERM_HPP_ */
<commit_msg>cgreterm => moving init and term hook methods to handle_dpt_open()/close()<commit_after>/*
 * cgreterm.hpp
 *
 *  Created on: 18.08.2014
 *      Author: andreas
 */

#ifndef CGRETERM_HPP_
#define CGRETERM_HPP_

#include <bitset>
#include <vector>
#include <string>
#include <ostream>
#include <exception>

#include <rofl/common/crofdpt.h>
#include <rofl/common/cdptid.h>
#include <rofl/common/openflow/cofmatch.h>
#include <rofl/common/protocols/fipv4frame.h>
#include <rofl/common/protocols/fipv6frame.h>
#include <rofl/common/protocols/fudpframe.h>
#include <rofl/common/openflow/experimental/actions/gre_actions.h>

#include <roflibs/netlink/clogging.hpp>

namespace roflibs {
namespace gre {

class eGreTermBase : public std::runtime_error {
public:
	eGreTermBase(const std::string& __arg) : std::runtime_error(__arg) {};
};
class eGreTermNotFound : public eGreTermBase {
public:
	eGreTermNotFound(const std::string& __arg) : eGreTermBase(__arg) {};
};

/*
 * -ingress- means: send traffic into the tunnel
 * -egress-  means: strip the tunnel and send traffic to the external world
 */
class cgreterm {
public:

	/**
	 *
	 */
	cgreterm() :
		state(STATE_DETACHED), eth_ofp_table_id(0), gre_ofp_table_id(0), ip_fwd_ofp_table_id(0),
		idle_timeout(DEFAULT_IDLE_TIMEOUT),
		gre_portno(0), gre_key(0) {};

	/**
	 *
	 */
	~cgreterm() {};

	/**
	 *
	 */
	cgreterm(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id,
			uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			uint32_t gre_portno, uint32_t gre_key) :
		state(STATE_DETACHED), dpid(dpid), eth_ofp_table_id(eth_ofp_table_id),
		gre_ofp_table_id(gre_ofp_table_id), ip_fwd_ofp_table_id(ip_fwd_ofp_table_id),
		idle_timeout(DEFAULT_IDLE_TIMEOUT),
		gre_portno(gre_portno), gre_key(gre_key) {};

	/**
	 *
	 */
	cgreterm(const cgreterm& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm&
	operator= (const cgreterm& greterm) {
		if (this == &greterm)
			return *this;
		state 				= greterm.state;
		dpid 				= greterm.dpid;
		eth_ofp_table_id 	= greterm.eth_ofp_table_id;
		gre_ofp_table_id 	= greterm.gre_ofp_table_id;
		ip_fwd_ofp_table_id	= greterm.ip_fwd_ofp_table_id;
		idle_timeout 		= greterm.idle_timeout;
		gre_portno 			= greterm.gre_portno;
		gre_key 			= greterm.gre_key;
		return *this;
	};

public:

	/**
	 *
	 */
	const uint32_t&
	get_gre_key() const { return gre_key; };

	/**
	 *
	 */
	const uint32_t&
	get_gre_portno() const { return gre_portno; };

protected:

	/**
	 *
	 */
	void
	execute(
			std::string const& executable,
			std::vector<std::string> argv,
			std::vector<std::string> envp);

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm& greterm) {
		os << rofcore::indent(0) << "<cgreterm key:0x"
				<< std::hex << (unsigned int)greterm.get_gre_key() << std::dec << " >" << std::endl;
		return os;
	};

protected:

	enum ofp_state_t {
		STATE_DETACHED = 1,
		STATE_ATTACHED = 2,
	};
	enum ofp_state_t 		state;

	enum cgreterm_flags_t {
		FLAG_INGRESS_FM_INSTALLED 	= (1 << 0),
		FLAG_EGRESS_FM_INSTALLED 	= (1 << 1),
	};
	std::bitset<32>			flags;

	rofl::cdpid 			dpid;
	uint8_t					eth_ofp_table_id;				// OFP tableid for capturing plain ethernet frames (table 0)
	uint8_t 				gre_ofp_table_id;				// OFP tableid for installing GRE-pop entries
	uint8_t					ip_fwd_ofp_table_id;			// OFP tableid for forwarding IP datagrams
	static const int 		DEFAULT_IDLE_TIMEOUT = 15; 		// seconds
	int 					idle_timeout;

	std::string				gre_portname;
	uint32_t				gre_portno; 					// portno of ethernet port
	uint32_t				gre_key;							// GRE key according to IETF RFC 2890
	static const uint8_t	GRE_IP_PROTO = 47;
	static const uint16_t 	GRE_PROT_TYPE_TRANSPARENT_ETHERNET_BRIDGING = 0x6558;

	static std::string		script_path_init;
	static std::string		script_path_term;
};

class cgreterm_in4 : public cgreterm {
public:

	/**
	 *
	 */
	cgreterm_in4() {};

	/**
	 *
	 */
	~cgreterm_in4() {
		try {
			if (STATE_ATTACHED == state) {
				handle_dpt_close(rofl::crofdpt::get_dpt(dpid));
			}
		} catch (rofl::eRofDptNotFound& e) {};
	};

	/**
	 *
	 */
	cgreterm_in4(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id, uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			const rofl::caddress_in4& laddr, const rofl::caddress_in4& raddr, uint32_t gre_portno, uint32_t gre_key) :
		cgreterm(dpid, eth_ofp_table_id, gre_ofp_table_id, ip_fwd_ofp_table_id, gre_portno, gre_key),
		laddr(laddr), raddr(raddr) {
	};

	/**
	 *
	 */
	cgreterm_in4(const cgreterm_in4& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm_in4&
	operator= (const cgreterm_in4& greterm) {
		if (this == &greterm)
			return *this;
		cgreterm::operator= (greterm);
		laddr = greterm.laddr;
		raddr = greterm.raddr;
		return *this;
	};

	/**
	 *
	 */
	bool
	operator< (const cgreterm_in4& greterm) const {
		return (raddr < greterm.raddr);
	};

public:

	/**
	 *
	 */
	const rofl::caddress_in4&
	get_local_addr() const { return laddr; };

	/**
	 *
	 */
	const rofl::caddress_in4&
	get_remote_addr() const { return raddr; };

public:

	/**
	 *
	 */
	void
	handle_dpt_open(rofl::crofdpt& dpt) {
		handle_dpt_open_egress(dpt);
		handle_dpt_open_ingress(dpt);
		hook_init();
	};

	/**
	 *
	 */
	void
	handle_dpt_close(rofl::crofdpt& dpt) {
		hook_term();
		handle_dpt_close_egress(dpt);
		handle_dpt_close_ingress(dpt);
	};

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm_in4& greterm) {
		os << dynamic_cast<const cgreterm&>( greterm );
		os << rofcore::indent(2) << "<cgreterm_in4 laddr:" << greterm.get_local_addr().str()
				<< " <==> raddr:" << greterm.get_remote_addr().str() << " >" << std::endl;
		return os;
	};

private:

	/**
	 *
	 */
	void
	handle_dpt_open_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_open_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	hook_init();

	/**
	 *
	 */
	void
	hook_term();

private:

	rofl::caddress_in4 laddr;
	rofl::caddress_in4 raddr;
};

class cgreterm_in6 : public cgreterm {
public:

	/**
	 *
	 */
	cgreterm_in6() {};

	/**
	 *
	 */
	~cgreterm_in6() {
		try {
			if (STATE_ATTACHED == state) {
				handle_dpt_close(rofl::crofdpt::get_dpt(dpid));
			}
		} catch (rofl::eRofDptNotFound& e) {};
	};

	/**
	 *
	 */
	cgreterm_in6(const rofl::cdpid& dpid, uint8_t eth_ofp_table_id, uint8_t gre_ofp_table_id, uint8_t ip_fwd_ofp_table_id,
			const rofl::caddress_in6& laddr, const rofl::caddress_in6& raddr, uint32_t gre_portno, uint32_t gre_key) :
		cgreterm(dpid, eth_ofp_table_id, gre_ofp_table_id, ip_fwd_ofp_table_id, gre_portno, gre_key),
		laddr(laddr), raddr(raddr) {
	};

	/**
	 *
	 */
	cgreterm_in6(const cgreterm_in6& greterm) { *this = greterm; };

	/**
	 *
	 */
	cgreterm_in6&
	operator= (const cgreterm_in6& greterm) {
		if (this == &greterm)
			return *this;
		cgreterm::operator= (greterm);
		laddr = greterm.laddr;
		raddr = greterm.raddr;
		return *this;
	};

	/**
	 *
	 */
	bool
	operator< (const cgreterm_in6& greterm) const {
		return (raddr < greterm.raddr);
	};

public:

	/**
	 *
	 */
	const rofl::caddress_in6&
	get_local_addr() const { return laddr; };

	/**
	 *
	 */
	const rofl::caddress_in6&
	get_remote_addr() const { return raddr; };

public:

	/**
	 *
	 */
	void
	handle_dpt_open(rofl::crofdpt& dpt) {
		handle_dpt_open_egress(dpt);
		handle_dpt_open_ingress(dpt);
		hook_init();
	};

	/**
	 *
	 */
	void
	handle_dpt_close(rofl::crofdpt& dpt) {
		hook_term();
		handle_dpt_close_egress(dpt);
		handle_dpt_close_ingress(dpt);
	};

public:

	friend std::ostream&
	operator<< (std::ostream& os, const cgreterm_in6& greterm) {
		os << dynamic_cast<const cgreterm&>( greterm );
		os << rofcore::indent(2) << "<cgreterm_in6 laddr:" << greterm.get_local_addr().str()
				<< " <==> raddr:" << greterm.get_remote_addr().str() << " >" << std::endl;
		return os;
	};

private:

	/**
	 *
	 */
	void
	handle_dpt_open_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_egress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_open_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	handle_dpt_close_ingress(rofl::crofdpt& dpt);

	/**
	 *
	 */
	void
	hook_init();

	/**
	 *
	 */
	void
	hook_term();

private:

	rofl::caddress_in6 laddr;
	rofl::caddress_in6 raddr;
};

}; // end of namespace gre
}; // end of namespace roflibs

#endif /* CGRETERM_HPP_ */
<|endoftext|>


<commit_before>/*
    kopetepasswordedaccount.cpp - Kopete Account with a password

    Copyright (c) 2004      by Richard Smith         <kde@metafoo.co.uk>
    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "kopetepasswordedaccount.h"
#include "kopetepassword.h"
#include "kopeteprotocol.h"
#include "kopeteonlinestatus.h"

#include <klocale.h>

#include <qpixmap.h>

struct Kopete::PasswordedAccount::Private
{
	Private( const QString &group, bool allowBlankPassword ) :
		password( group, allowBlankPassword ) {}
	Kopete::Password password;
	Kopete::OnlineStatus initialStatus;
};

Kopete::PasswordedAccount::PasswordedAccount( Kopete::Protocol *parent, const QString &acctId, bool allowBlankPassword )
 : Kopete::Account( parent, acctId ), d( new Private( QString::fromLatin1("Account_")+ parent->pluginId() + QString::fromLatin1("_") + acctId , allowBlankPassword  ) )
{
}

Kopete::PasswordedAccount::~PasswordedAccount()
{
	delete d;
}

Kopete::Password &Kopete::PasswordedAccount::password()
{
	return d->password;
}

void Kopete::PasswordedAccount::connect( )
{
	Kopete::OnlineStatus s(Kopete::OnlineStatus::Online);
	connect( s );
}

void Kopete::PasswordedAccount::connect( const Kopete::OnlineStatus& initialStatus )
{
	// check that the networkstatus is up

	// warn user somewhere
	d->initialStatus = initialStatus;
	QString cached = password().cachedValue();
	if( !cached.isNull() || d->password.allowBlankPassword() )
	{
		connectWithPassword( cached );
		return;
	}

	QString prompt = passwordPrompt();
	Kopete::Password::PasswordSource src = password().isWrong() ? Kopete::Password::FromUser : Kopete::Password::FromConfigOrUser;

	password().request( this, SLOT( connectWithPassword( const QString & ) ), accountIcon( Kopete::Password::preferredImageSize() ), prompt, src );
}

QString Kopete::PasswordedAccount::passwordPrompt()
{
	if ( password().isWrong() )
		return i18n( "<qt>The password was wrong. Please re-enter your password for %1 account %2</qt>", protocol()->displayName(), accountId() );
	else
		return i18n( "<qt>Please enter your password for %1 account %2</qt>", protocol()->displayName(), accountId() );
}

Kopete::OnlineStatus Kopete::PasswordedAccount::initialStatus()
{
	return d->initialStatus;
}

bool Kopete::PasswordedAccount::removeAccount()
{
	password().set(QString::null);	//krazy:exclude=nullstrassign for old broken gcc
	return Kopete::Account::removeAccount();
}

void Kopete::PasswordedAccount::disconnected( Kopete::Account::DisconnectReason reason )
{
	if(reason==Kopete::Account::BadPassword || reason==Kopete::Account::BadUserName)
	{
		password().setWrong(true);
	}
	Kopete::Account::disconnected(reason);
}

#include "kopetepasswordedaccount.moc"

// vim: set noet ts=4 sts=4 sw=4:
<commit_msg>done elsewhere, redundant comment<commit_after>/*
    kopetepasswordedaccount.cpp - Kopete Account with a password

    Copyright (c) 2004      by Richard Smith         <kde@metafoo.co.uk>
    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "kopetepasswordedaccount.h"
#include "kopetepassword.h"
#include "kopeteprotocol.h"
#include "kopeteonlinestatus.h"

#include <klocale.h>

#include <qpixmap.h>

struct Kopete::PasswordedAccount::Private
{
	Private( const QString &group, bool allowBlankPassword ) :
		password( group, allowBlankPassword ) {}
	Kopete::Password password;
	Kopete::OnlineStatus initialStatus;
};

Kopete::PasswordedAccount::PasswordedAccount( Kopete::Protocol *parent, const QString &acctId, bool allowBlankPassword )
 : Kopete::Account( parent, acctId ), d( new Private( QString::fromLatin1("Account_")+ parent->pluginId() + QString::fromLatin1("_") + acctId , allowBlankPassword  ) )
{
}

Kopete::PasswordedAccount::~PasswordedAccount()
{
	delete d;
}

Kopete::Password &Kopete::PasswordedAccount::password()
{
	return d->password;
}

void Kopete::PasswordedAccount::connect( )
{
	Kopete::OnlineStatus s(Kopete::OnlineStatus::Online);
	connect( s );
}

void Kopete::PasswordedAccount::connect( const Kopete::OnlineStatus& initialStatus )
{
	// warn user somewhere
	d->initialStatus = initialStatus;
	QString cached = password().cachedValue();
	if( !cached.isNull() || d->password.allowBlankPassword() )
	{
		connectWithPassword( cached );
		return;
	}

	QString prompt = passwordPrompt();
	Kopete::Password::PasswordSource src = password().isWrong() ? Kopete::Password::FromUser : Kopete::Password::FromConfigOrUser;

	password().request( this, SLOT( connectWithPassword( const QString & ) ), accountIcon( Kopete::Password::preferredImageSize() ), prompt, src );
}

QString Kopete::PasswordedAccount::passwordPrompt()
{
	if ( password().isWrong() )
		return i18n( "<qt>The password was wrong. Please re-enter your password for %1 account %2</qt>", protocol()->displayName(), accountId() );
	else
		return i18n( "<qt>Please enter your password for %1 account %2</qt>", protocol()->displayName(), accountId() );
}

Kopete::OnlineStatus Kopete::PasswordedAccount::initialStatus()
{
	return d->initialStatus;
}

bool Kopete::PasswordedAccount::removeAccount()
{
	password().set(QString::null);	//krazy:exclude=nullstrassign for old broken gcc
	return Kopete::Account::removeAccount();
}

void Kopete::PasswordedAccount::disconnected( Kopete::Account::DisconnectReason reason )
{
	if(reason==Kopete::Account::BadPassword || reason==Kopete::Account::BadUserName)
	{
		password().setWrong(true);
	}
	Kopete::Account::disconnected(reason);
}

#include "kopetepasswordedaccount.moc"

// vim: set noet ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>#include "DNSServer.h"
#include <lwip/def.h>
#include <Arduino.h>

DNSServer::DNSServer()
{
  _ttl = htonl(60);
  _errorReplyCode = DNSReplyCode::NonExistentDomain;
}

bool DNSServer::start(const uint16_t &port, const String &domainName,
                     const IPAddress &resolvedIP)
{
  _port = port;

  _domainName = domainName;
  _resolvedIP[0] = resolvedIP[0];
  _resolvedIP[1] = resolvedIP[1];
  _resolvedIP[2] = resolvedIP[2];
  _resolvedIP[3] = resolvedIP[3];
  downcaseAndRemoveWwwPrefix(_domainName);
  return _udp.begin(_port) == 1;
}

void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
{
  _errorReplyCode = replyCode;
}

void DNSServer::setTTL(const uint32_t &ttl)
{
  _ttl = htonl(ttl);
}

void DNSServer::stop()
{
  _udp.stop();
}

void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
{
  domainName.toLowerCase();
  domainName.replace("www.", "");
}

void DNSServer::processNextRequest()
{
  size_t packetSize = _udp.parsePacket();

  if (packetSize >= sizeof(DNSHeader))
  {
    uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(packetSize));
    if (buffer == NULL) return;

    _udp.read(buffer, packetSize);

    DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

    if (dnsHeader->QR == DNS_QR_QUERY &&
        dnsHeader->OPCode == DNS_OPCODE_QUERY &&
        requestIncludesOnlyOneQuestion(dnsHeader) &&
        (_domainName == "*" || getDomainNameWithoutWwwPrefix(buffer, packetSize) == _domainName)
       )
    {
      replyWithIP(buffer, packetSize);
    }
    else if (dnsHeader->QR == DNS_QR_QUERY)
    {
      replyWithCustomCode(buffer, packetSize);
    }

    free(buffer);
  }
}

bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
{
  return ntohs(dnsHeader->QDCount) == 1 &&
         dnsHeader->ANCount == 0 &&
         dnsHeader->NSCount == 0 &&
         dnsHeader->ARCount == 0;
}

String DNSServer::getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize)
{
  String parsedDomainName;

  const uint8_t* pos = buffer + sizeof(DNSHeader);
  const uint8_t* end = buffer + packetSize;

  // to minimize reallocations due to concats below
  // we reserve enough space that a median or average domain
  // name size cold be easily contained without a reallocation
  // - max size would be 253, in 2013, average is 11 and max was 42
  //
  parsedDomainName.reserve(32);

  uint8_t labelLength = *pos;

  while (true)
  {
    if (labelLength == 0)
    {
        // no more labels
        downcaseAndRemoveWwwPrefix(parsedDomainName);
        return parsedDomainName;
    }

    // append next label
    for (int i = 0; i < labelLength && pos < end; i++)
    {
      pos++;
      parsedDomainName += static_cast<char>(*pos);
    }

    if (pos >= end)
    {
        // malformed packet, return an empty domain name
        parsedDomainName = "";
        return parsedDomainName;
    }
    else
    {
        // next label
        pos++;
        labelLength = *pos;

        // if there is another label, add delimiter
        if (labelLength != 0)
        {
            parsedDomainName += ".";
        }
    }
  }
}

void DNSServer::replyWithIP(uint8_t* buffer, size_t packetSize)
{
  DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

  dnsHeader->QR = DNS_QR_RESPONSE;
  dnsHeader->ANCount = dnsHeader->QDCount;
  dnsHeader->QDCount = dnsHeader->QDCount;
  //dnsHeader->RA = 1;

  _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
  _udp.write(buffer, packetSize);

  _udp.write((uint8_t)192); //  answer name is a pointer
  _udp.write((uint8_t)12);  // pointer to offset at 0x00c

  _udp.write((uint8_t)0);   // 0x0001  answer is type A query (host address)
  _udp.write((uint8_t)1);

  _udp.write((uint8_t)0);   //0x0001 answer is class IN (internet address)
  _udp.write((uint8_t)1);

  _udp.write((unsigned char*)&_ttl, 4);

  // Length of RData is 4 bytes (because, in this case, RData is IPv4)
  _udp.write((uint8_t)0);
  _udp.write((uint8_t)4);
  _udp.write(_resolvedIP, sizeof(_resolvedIP));
  _udp.endPacket();

  #ifdef DEBUG_ESP_DNS
    DEBUG_ESP_PORT.printf("DNS responds: %s for %s\n",
            IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix(buffer, packetSize).c_str() );
  #endif
}

void DNSServer::replyWithCustomCode(uint8_t* buffer, size_t packetSize)
{
  if (packetSize < sizeof(DNSHeader))
  {
    return;
  }

  DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

  dnsHeader->QR = DNS_QR_RESPONSE;
  dnsHeader->RCode = (unsigned char)_errorReplyCode;
  dnsHeader->QDCount = 0;

  _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
  _udp.write(buffer, sizeof(DNSHeader));
  _udp.endPacket();
}
<commit_msg>Fix debug provision for DNSServer (#5329)<commit_after>#include "DNSServer.h"
#include <lwip/def.h>
#include <Arduino.h>

#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serial
#endif

DNSServer::DNSServer()
{
  _ttl = htonl(60);
  _errorReplyCode = DNSReplyCode::NonExistentDomain;
}

bool DNSServer::start(const uint16_t &port, const String &domainName,
                     const IPAddress &resolvedIP)
{
  _port = port;

  _domainName = domainName;
  _resolvedIP[0] = resolvedIP[0];
  _resolvedIP[1] = resolvedIP[1];
  _resolvedIP[2] = resolvedIP[2];
  _resolvedIP[3] = resolvedIP[3];
  downcaseAndRemoveWwwPrefix(_domainName);
  return _udp.begin(_port) == 1;
}

void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
{
  _errorReplyCode = replyCode;
}

void DNSServer::setTTL(const uint32_t &ttl)
{
  _ttl = htonl(ttl);
}

void DNSServer::stop()
{
  _udp.stop();
}

void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
{
  domainName.toLowerCase();
  domainName.replace("www.", "");
}

void DNSServer::processNextRequest()
{
  size_t packetSize = _udp.parsePacket();

  if (packetSize >= sizeof(DNSHeader))
  {
    uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(packetSize));
    if (buffer == NULL) return;

    _udp.read(buffer, packetSize);

    DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

    if (dnsHeader->QR == DNS_QR_QUERY &&
        dnsHeader->OPCode == DNS_OPCODE_QUERY &&
        requestIncludesOnlyOneQuestion(dnsHeader) &&
        (_domainName == "*" || getDomainNameWithoutWwwPrefix(buffer, packetSize) == _domainName)
       )
    {
      replyWithIP(buffer, packetSize);
    }
    else if (dnsHeader->QR == DNS_QR_QUERY)
    {
      replyWithCustomCode(buffer, packetSize);
    }

    free(buffer);
  }
}

bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
{
  return ntohs(dnsHeader->QDCount) == 1 &&
         dnsHeader->ANCount == 0 &&
         dnsHeader->NSCount == 0 &&
         dnsHeader->ARCount == 0;
}

String DNSServer::getDomainNameWithoutWwwPrefix(const uint8_t* buffer, size_t packetSize)
{
  String parsedDomainName;

  const uint8_t* pos = buffer + sizeof(DNSHeader);
  const uint8_t* end = buffer + packetSize;

  // to minimize reallocations due to concats below
  // we reserve enough space that a median or average domain
  // name size cold be easily contained without a reallocation
  // - max size would be 253, in 2013, average is 11 and max was 42
  //
  parsedDomainName.reserve(32);

  uint8_t labelLength = *pos;

  while (true)
  {
    if (labelLength == 0)
    {
        // no more labels
        downcaseAndRemoveWwwPrefix(parsedDomainName);
        return parsedDomainName;
    }

    // append next label
    for (int i = 0; i < labelLength && pos < end; i++)
    {
      pos++;
      parsedDomainName += static_cast<char>(*pos);
    }

    if (pos >= end)
    {
        // malformed packet, return an empty domain name
        parsedDomainName = "";
        return parsedDomainName;
    }
    else
    {
        // next label
        pos++;
        labelLength = *pos;

        // if there is another label, add delimiter
        if (labelLength != 0)
        {
            parsedDomainName += ".";
        }
    }
  }
}

void DNSServer::replyWithIP(uint8_t* buffer, size_t packetSize)
{
  DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

  dnsHeader->QR = DNS_QR_RESPONSE;
  dnsHeader->ANCount = dnsHeader->QDCount;
  dnsHeader->QDCount = dnsHeader->QDCount;
  //dnsHeader->RA = 1;

  _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
  _udp.write(buffer, packetSize);

  _udp.write((uint8_t)192); //  answer name is a pointer
  _udp.write((uint8_t)12);  // pointer to offset at 0x00c

  _udp.write((uint8_t)0);   // 0x0001  answer is type A query (host address)
  _udp.write((uint8_t)1);

  _udp.write((uint8_t)0);   //0x0001 answer is class IN (internet address)
  _udp.write((uint8_t)1);

  _udp.write((unsigned char*)&_ttl, 4);

  // Length of RData is 4 bytes (because, in this case, RData is IPv4)
  _udp.write((uint8_t)0);
  _udp.write((uint8_t)4);
  _udp.write(_resolvedIP, sizeof(_resolvedIP));
  _udp.endPacket();

  #ifdef DEBUG_ESP_DNS
    DEBUG_OUTPUT.printf("DNS responds: %s for %s\n",
            IPAddress(_resolvedIP).toString().c_str(), getDomainNameWithoutWwwPrefix(buffer, packetSize).c_str() );
  #endif
}

void DNSServer::replyWithCustomCode(uint8_t* buffer, size_t packetSize)
{
  if (packetSize < sizeof(DNSHeader))
  {
    return;
  }

  DNSHeader* dnsHeader = reinterpret_cast<DNSHeader*>(buffer);

  dnsHeader->QR = DNS_QR_RESPONSE;
  dnsHeader->RCode = (unsigned char)_errorReplyCode;
  dnsHeader->QDCount = 0;

  _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
  _udp.write(buffer, sizeof(DNSHeader));
  _udp.endPacket();
}
<|endoftext|>


<commit_before>#pragma once

namespace supermarx
{

namespace detail
{
	template<typename T, size_t LENGTH>
	inline size_t numlength(const T x)
	{
		return std::log10(x)+1;
	}

	template<>
	inline size_t numlength<long, 2>(const long x)
	{
		if(x > 9)
			return 2;
		else
			return 1;
	}

	template<typename T, size_t LENGTH>
	inline void write_int_to_cstr(char* str, T x)
	{
		size_t x_length(numlength<T, LENGTH>(x));
		int64_t pad_length(LENGTH - x_length);

		for(size_t i = 0; i < pad_length; ++i)
			str[i] = '0';

		for(int64_t i = LENGTH-1; i >= pad_length; --i)
		{
			str[i] = '0' + x % 10;
			x /= 10;
		}
	}

	inline void write_time(char* str, time const& rhs)
	{
		write_int_to_cstr<long, 2>(str, rhs.hours());
		write_int_to_cstr<long, 2>(str+3, rhs.minutes());
		write_int_to_cstr<long, 2>(str+6, rhs.seconds());
	}

	inline void write_date(char* str, date const& rhs)
	{
		auto ymd(rhs.year_month_day());
		write_int_to_cstr<long, 4>(str, ymd.year);
		write_int_to_cstr<long, 2>(str+5, ymd.month);
		write_int_to_cstr<long, 2>(str+8, ymd.day);
	}
}

inline std::string to_string(time const& rhs)
{
	char result[] = "xx:xx:xx";
	detail::write_time(result, rhs);
	return std::string(result);
}

inline std::string to_string(date const& rhs)
{
	char result[] = "xxxx-xx-xx";
	detail::write_date(result, rhs);
	return std::string(result);
}

inline std::string to_string(datetime const& rhs)
{
	char result[] = "xxxx-xx-xxTxx:xx:xx";
	detail::write_date(result, rhs.date());
	detail::write_time(result+11, rhs.time_of_day());
	return std::string(result);
}

inline std::ostream& operator<<(std::ostream& os, time const& rhs)
{
	char result[] = "xx:xx:xx";
	detail::write_time(result, rhs);
	os << result;
	return os;
}

inline std::ostream& operator<<(std::ostream& os, date const& rhs)
{
	char result[] = "xxxx-xx-xx";
	detail::write_date(result, rhs);
	os << result;
	return os;
}

inline std::ostream& operator<<(std::ostream& os, datetime const& rhs)
{
	char result[] = "xxxx-xx-xxTxx:xx:xx";
	detail::write_date(result, rhs.date());
	detail::write_time(result+11, rhs.time_of_day());
	os << result;
	return os;
}

}
<commit_msg>Improved performance a slight bit for writing dates<commit_after>#pragma once

namespace supermarx
{

namespace detail
{
	template<typename T, size_t LENGTH>
	inline size_t numlength(const T x)
	{
		return std::log10(x)+1;
	}

	template<>
	inline size_t numlength<long, 2>(const long x)
	{
		if(x > 9)
			return 2;
		else
			return 1;
	}

	template<>
	inline size_t numlength<long, 4>(const long x)
	{
		if(x > 999)
			return 4;
		else if(x > 99)
			return 3;
		else if(x > 9)
			return 2;
		else
			return 1;
	}

	template<typename T, size_t LENGTH>
	inline void write_int_to_cstr(char* str, T x)
	{
		size_t x_length(numlength<T, LENGTH>(x));
		int64_t pad_length(LENGTH - x_length);

		for(size_t i = 0; i < pad_length; ++i)
			str[i] = '0';

		for(int64_t i = LENGTH-1; i >= pad_length; --i)
		{
			str[i] = '0' + x % 10;
			x /= 10;
		}
	}

	inline void write_time(char* str, time const& rhs)
	{
		write_int_to_cstr<long, 2>(str, rhs.hours());
		write_int_to_cstr<long, 2>(str+3, rhs.minutes());
		write_int_to_cstr<long, 2>(str+6, rhs.seconds());
	}

	inline void write_date(char* str, date const& rhs)
	{
		auto ymd(rhs.year_month_day());
		write_int_to_cstr<long, 4>(str, ymd.year);
		write_int_to_cstr<long, 2>(str+5, ymd.month);
		write_int_to_cstr<long, 2>(str+8, ymd.day);
	}
}

inline std::string to_string(time const& rhs)
{
	char result[] = "xx:xx:xx";
	detail::write_time(result, rhs);
	return std::string(result);
}

inline std::string to_string(date const& rhs)
{
	char result[] = "xxxx-xx-xx";
	detail::write_date(result, rhs);
	return std::string(result);
}

inline std::string to_string(datetime const& rhs)
{
	char result[] = "xxxx-xx-xxTxx:xx:xx";
	detail::write_date(result, rhs.date());
	detail::write_time(result+11, rhs.time_of_day());
	return std::string(result);
}

inline std::ostream& operator<<(std::ostream& os, time const& rhs)
{
	char result[] = "xx:xx:xx";
	detail::write_time(result, rhs);
	os << result;
	return os;
}

inline std::ostream& operator<<(std::ostream& os, date const& rhs)
{
	char result[] = "xxxx-xx-xx";
	detail::write_date(result, rhs);
	os << result;
	return os;
}

inline std::ostream& operator<<(std::ostream& os, datetime const& rhs)
{
	char result[] = "xxxx-xx-xxTxx:xx:xx";
	detail::write_date(result, rhs.date());
	detail::write_time(result+11, rhs.time_of_day());
	os << result;
	return os;
}

}
<|endoftext|>


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

#include "tests/NXTTest.h"

#include "utils/NXTHelpers.h"

class BasicTests : public NXTTest {
};

// Test Buffer::SetSubData changes the content of the buffer, but really this is the most
// basic test possible, and tests the test harness
TEST_P(BasicTests, BufferSetSubData) {
    nxt::Buffer buffer = device.CreateBufferBuilder()
        .SetSize(4)
        .SetAllowedUsage(nxt::BufferUsageBit::TransferSrc | nxt::BufferUsageBit::TransferDst)
        .SetInitialUsage(nxt::BufferUsageBit::TransferDst)
        .GetResult();

    uint32_t value = 3094587;
    buffer.SetSubData(0, 1, &value);

    EXPECT_BUFFER_U32_EQ(value, buffer, 0);
}

NXT_INSTANTIATE_TEST(BasicTests, D3D12Backend, MetalBackend, OpenGLBackend)
<commit_msg>Enable BasicTests on the Vulkan backend<commit_after>// Copyright 2017 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tests/NXTTest.h"

#include "utils/NXTHelpers.h"

class BasicTests : public NXTTest {
};

// Test Buffer::SetSubData changes the content of the buffer, but really this is the most
// basic test possible, and tests the test harness
TEST_P(BasicTests, BufferSetSubData) {
    nxt::Buffer buffer = device.CreateBufferBuilder()
        .SetSize(4)
        .SetAllowedUsage(nxt::BufferUsageBit::TransferSrc | nxt::BufferUsageBit::TransferDst)
        .SetInitialUsage(nxt::BufferUsageBit::TransferDst)
        .GetResult();

    uint32_t value = 3094587;
    buffer.SetSubData(0, 1, &value);

    EXPECT_BUFFER_U32_EQ(value, buffer, 0);
}

NXT_INSTANTIATE_TEST(BasicTests, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)
<|endoftext|>


<commit_before>/** @file
 *
 *  A brief file description
 *
 *  @section license License
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "tscore/ink_string.h"
#include "tscore/ink_args.h"
#include "tscore/I_Layout.h"
#include "tscore/I_Version.h"

#include "RecordsConfig.h"
#include "URL.h"
#include "MIME.h"
#include "HTTP.h"
#include "HuffmanCodec.h"
#include "Http3Config.h"

#include "diags.h"
#include "quic_client.h"

#define THREADS 1

constexpr size_t stacksize = 1048576;

// TODO: Support QUIC version, cipher suite ...etc
// TODO: Support qdrive tests
//   https://github.com/ekr/qdrive
//   https://github.com/mcmanus/mozquic/tree/master/tests/qdrive
int
main(int argc, const char **argv)
{
  // Before accessing file system initialize Layout engine
  Layout::create();

  // Set up the application version info
  AppVersionInfo appVersionInfo;
  appVersionInfo.setup(PACKAGE_NAME, "traffic_quic", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, "");

  QUICClientConfig config;

  const ArgumentDescription argument_descriptions[] = {
    {"addr", 'a', "Address", "S1023", config.addr, nullptr, nullptr},
    {"output", 'o', "Write to FILE instead of stdout", "S1023", config.output, nullptr, nullptr},
    {"port", 'p', "Port", "S15", config.port, nullptr, nullptr},
    {"path", 'P', "Path", "S1017", config.path, nullptr, nullptr},
    {"debug", 'T', "Vertical-bar-separated Debug Tags", "S1023", config.debug_tags, nullptr, nullptr},
    {"close", 'c', "Enable connection close excercise", "F", &config.close, nullptr, nullptr},
    {"http0_9", '-', "Enable HTTP/0.9", "T", &config.http0_9, nullptr, nullptr},
    {"http3", '-', "Enable HTTP/3", "F", &config.http3, nullptr, nullptr},

    HELP_ARGUMENT_DESCRIPTION(),
    VERSION_ARGUMENT_DESCRIPTION(),
    RUNROOT_ARGUMENT_DESCRIPTION(),
  };

  // Process command line arguments and dump into variables
  process_args(&appVersionInfo, argument_descriptions, countof(argument_descriptions), argv);

  if (config.http3) {
    config.http0_9 = false;
  }

  init_diags(config.debug_tags, nullptr);
  RecProcessInit(RECM_STAND_ALONE);
  LibRecordsConfigInit();

  Debug("quic_client", "Load configs from %s", RecConfigReadConfigDir().c_str());

  Thread *main_thread = new EThread;
  main_thread->set_specific();
  net_config_poll_timeout = 10;
  ink_net_init(ts::ModuleVersion(1, 0, ts::ModuleVersion::PRIVATE));

  SSLInitializeLibrary();
  SSLConfig::startup();

  netProcessor.init();
  quic_NetProcessor.init();

  ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
  eventProcessor.start(THREADS);
  udpNet.start(1, stacksize);
  quic_NetProcessor.start(-1, stacksize);

  // Same to init_http_header(); in traffic_server.cc
  url_init();
  mime_init();
  http_init();
  hpack_huffman_init();

  Http3Config::startup();

  QUICClient client(&config);
  eventProcessor.schedule_in(&client, 1, ET_NET);

  this_thread()->execute();
}

// FIXME: remove stub
//
// stub
//
void
initialize_thread_for_http_sessions(EThread *, int)
{
  ink_assert(false);
}

#include "P_UnixNet.h"
#include "P_DNSConnection.h"
int
DNSConnection::close()
{
  ink_assert(false);
  return 0;
}

void
DNSConnection::trigger()
{
  ink_assert(false);
}

#include "StatPages.h"
void
StatPagesManager::register_http(char const *, Action *(*)(Continuation *, HTTPHdr *))
{
  //  ink_assert(false);
}

#include "ParentSelection.h"
void
SocksServerConfig::startup()
{
  ink_assert(false);
}

int SocksServerConfig::m_id = 0;

void
ParentConfigParams::findParent(HttpRequestData *, ParentResult *, unsigned int, unsigned int)
{
  ink_assert(false);
}

void
ParentConfigParams::nextParent(HttpRequestData *, ParentResult *, unsigned int, unsigned int)
{
  ink_assert(false);
}

#include "Log.h"
void
Log::trace_in(sockaddr const *, unsigned short, char const *, ...)
{
  ink_assert(false);
}

void
Log::trace_out(sockaddr const *, unsigned short, char const *, ...)
{
  ink_assert(false);
}

#include "InkAPIInternal.h"

int
APIHook::invoke(int, void *)
{
  ink_assert(false);
  return 0;
}

APIHook *
APIHook::next() const
{
  ink_assert(false);
  return nullptr;
}

APIHook *
APIHooks::get() const
{
  ink_assert(false);
  return nullptr;
}

void
APIHooks::clear()
{
  ink_abort("do not call stub");
}

void
APIHooks::append(INKContInternal *)
{
  ink_abort("do not call stub");
}

void
APIHooks::prepend(INKContInternal *)
{
  ink_abort("do not call stub");
}

void
ConfigUpdateCbTable::invoke(const char * /* name ATS_UNUSED */)
{
  ink_release_assert(false);
}

#include "ControlMatcher.h"
char *
HttpRequestData::get_string()
{
  ink_assert(false);
  return nullptr;
}

const char *
HttpRequestData::get_host()
{
  ink_assert(false);
  return nullptr;
}

sockaddr const *
HttpRequestData::get_ip()
{
  ink_assert(false);
  return nullptr;
}

sockaddr const *
HttpRequestData::get_client_ip()
{
  ink_assert(false);
  return nullptr;
}

SslAPIHooks *ssl_hooks = nullptr;
StatPagesManager statPagesManager;

#include "HttpDebugNames.h"
const char *
HttpDebugNames::get_api_hook_name(TSHttpHookID t)
{
  return "dummy";
}

#include "HttpSM.h"
HttpSM::HttpSM() : Continuation(nullptr), vc_table(this) {}

void
HttpSM::cleanup()
{
  ink_abort("do not call stub");
}

void
HttpSM::destroy()
{
  ink_abort("do not call stub");
}

void
HttpSM::set_next_state()
{
  ink_abort("do not call stub");
}

void
HttpSM::handle_api_return()
{
  ink_abort("do not call stub");
}

int
HttpSM::kill_this_async_hook(int /* event ATS_UNUSED */, void * /* data ATS_UNUSED */)
{
  return EVENT_DONE;
}

void
HttpSM::attach_client_session(ProxyTransaction *, IOBufferReader *)
{
  ink_abort("do not call stub");
}

void
HttpSM::init()
{
  ink_abort("do not call stub");
}

ClassAllocator<HttpSM> httpSMAllocator("httpSMAllocator");
HttpAPIHooks *http_global_hooks;

HttpVCTable::HttpVCTable(HttpSM *) {}

PostDataBuffers::~PostDataBuffers() {}

#include "HttpTunnel.h"
HttpTunnel::HttpTunnel() : Continuation(nullptr) {}
HttpTunnelConsumer::HttpTunnelConsumer() {}
HttpTunnelProducer::HttpTunnelProducer() {}
ChunkedHandler::ChunkedHandler() {}

#include "HttpCacheSM.h"
HttpCacheSM::HttpCacheSM() {}

HttpCacheAction::HttpCacheAction() : sm(nullptr) {}
void
HttpCacheAction::cancel(Continuation *c)
{
}
<commit_msg>Fix QUIC build<commit_after>/** @file
 *
 *  A brief file description
 *
 *  @section license License
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "tscore/ink_string.h"
#include "tscore/ink_args.h"
#include "tscore/I_Layout.h"
#include "tscore/I_Version.h"

#include "RecordsConfig.h"
#include "URL.h"
#include "MIME.h"
#include "HTTP.h"
#include "HuffmanCodec.h"
#include "Http3Config.h"

#include "diags.h"
#include "quic_client.h"

#define THREADS 1

constexpr size_t stacksize = 1048576;

// TODO: Support QUIC version, cipher suite ...etc
// TODO: Support qdrive tests
//   https://github.com/ekr/qdrive
//   https://github.com/mcmanus/mozquic/tree/master/tests/qdrive
int
main(int argc, const char **argv)
{
  // Before accessing file system initialize Layout engine
  Layout::create();

  // Set up the application version info
  AppVersionInfo appVersionInfo;
  appVersionInfo.setup(PACKAGE_NAME, "traffic_quic", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, "");

  QUICClientConfig config;

  const ArgumentDescription argument_descriptions[] = {
    {"addr", 'a', "Address", "S1023", config.addr, nullptr, nullptr},
    {"output", 'o', "Write to FILE instead of stdout", "S1023", config.output, nullptr, nullptr},
    {"port", 'p', "Port", "S15", config.port, nullptr, nullptr},
    {"path", 'P', "Path", "S1017", config.path, nullptr, nullptr},
    {"debug", 'T', "Vertical-bar-separated Debug Tags", "S1023", config.debug_tags, nullptr, nullptr},
    {"close", 'c', "Enable connection close excercise", "F", &config.close, nullptr, nullptr},
    {"http0_9", '-', "Enable HTTP/0.9", "T", &config.http0_9, nullptr, nullptr},
    {"http3", '-', "Enable HTTP/3", "F", &config.http3, nullptr, nullptr},

    HELP_ARGUMENT_DESCRIPTION(),
    VERSION_ARGUMENT_DESCRIPTION(),
    RUNROOT_ARGUMENT_DESCRIPTION(),
  };

  // Process command line arguments and dump into variables
  process_args(&appVersionInfo, argument_descriptions, countof(argument_descriptions), argv);

  if (config.http3) {
    config.http0_9 = false;
  }

  init_diags(config.debug_tags, nullptr);
  RecProcessInit(RECM_STAND_ALONE);
  LibRecordsConfigInit();

  Debug("quic_client", "Load configs from %s", RecConfigReadConfigDir().c_str());

  Thread *main_thread = new EThread;
  main_thread->set_specific();
  net_config_poll_timeout = 10;
  ink_net_init(ts::ModuleVersion(1, 0, ts::ModuleVersion::PRIVATE));

  SSLInitializeLibrary();
  SSLConfig::startup();

  netProcessor.init();
  quic_NetProcessor.init();

  ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
  eventProcessor.start(THREADS);
  udpNet.start(1, stacksize);
  quic_NetProcessor.start(-1, stacksize);

  // Same to init_http_header(); in traffic_server.cc
  url_init();
  mime_init();
  http_init();
  hpack_huffman_init();

  Http3Config::startup();

  QUICClient client(&config);
  eventProcessor.schedule_in(&client, 1, ET_NET);

  this_thread()->execute();
}

// FIXME: remove stub
//
// stub
//
void
initialize_thread_for_http_sessions(EThread *, int)
{
  ink_assert(false);
}

#include "P_UnixNet.h"
#include "P_DNSConnection.h"
int
DNSConnection::close()
{
  ink_assert(false);
  return 0;
}

void
DNSConnection::trigger()
{
  ink_assert(false);
}

#include "StatPages.h"
void
StatPagesManager::register_http(char const *, Action *(*)(Continuation *, HTTPHdr *))
{
  //  ink_assert(false);
}

#include "ParentSelection.h"
void
SocksServerConfig::startup()
{
  ink_assert(false);
}

int SocksServerConfig::m_id = 0;

void
ParentConfigParams::findParent(HttpRequestData *, ParentResult *, unsigned int, unsigned int)
{
  ink_assert(false);
}

void
ParentConfigParams::nextParent(HttpRequestData *, ParentResult *, unsigned int, unsigned int)
{
  ink_assert(false);
}

#include "Log.h"
void
Log::trace_in(sockaddr const *, unsigned short, char const *, ...)
{
  ink_assert(false);
}

void
Log::trace_out(sockaddr const *, unsigned short, char const *, ...)
{
  ink_assert(false);
}

#include "InkAPIInternal.h"

APIHook *
APIHook::next() const
{
  ink_assert(false);
  return nullptr;
}

void
APIHooks::clear()
{
  ink_abort("do not call stub");
}

void
APIHooks::append(INKContInternal *)
{
  ink_abort("do not call stub");
}

int
APIHook::invoke(int, void *) const
{
  ink_assert(false);
  return 0;
}

APIHook *
APIHooks::head() const
{
  return nullptr;
}

HttpHookState::HttpHookState() {}

void
HttpHookState::init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn, HttpAPIHooks const *txn)
{
}

APIHook const *
HttpHookState::getNext()
{
  return nullptr;
}

void
ConfigUpdateCbTable::invoke(const char * /* name ATS_UNUSED */)
{
  ink_release_assert(false);
}

#include "ControlMatcher.h"
char *
HttpRequestData::get_string()
{
  ink_assert(false);
  return nullptr;
}

const char *
HttpRequestData::get_host()
{
  ink_assert(false);
  return nullptr;
}

sockaddr const *
HttpRequestData::get_ip()
{
  ink_assert(false);
  return nullptr;
}

sockaddr const *
HttpRequestData::get_client_ip()
{
  ink_assert(false);
  return nullptr;
}

SslAPIHooks *ssl_hooks = nullptr;
StatPagesManager statPagesManager;

#include "HttpDebugNames.h"
const char *
HttpDebugNames::get_api_hook_name(TSHttpHookID t)
{
  return "dummy";
}

#include "HttpSM.h"
HttpSM::HttpSM() : Continuation(nullptr), vc_table(this) {}

void
HttpSM::cleanup()
{
  ink_abort("do not call stub");
}

void
HttpSM::destroy()
{
  ink_abort("do not call stub");
}

void
HttpSM::set_next_state()
{
  ink_abort("do not call stub");
}

void
HttpSM::handle_api_return()
{
  ink_abort("do not call stub");
}

int
HttpSM::kill_this_async_hook(int /* event ATS_UNUSED */, void * /* data ATS_UNUSED */)
{
  return EVENT_DONE;
}

void
HttpSM::attach_client_session(ProxyTransaction *, IOBufferReader *)
{
  ink_abort("do not call stub");
}

void
HttpSM::init()
{
  ink_abort("do not call stub");
}

ClassAllocator<HttpSM> httpSMAllocator("httpSMAllocator");
HttpAPIHooks *http_global_hooks;

HttpVCTable::HttpVCTable(HttpSM *) {}

PostDataBuffers::~PostDataBuffers() {}

#include "HttpTunnel.h"
HttpTunnel::HttpTunnel() : Continuation(nullptr) {}
HttpTunnelConsumer::HttpTunnelConsumer() {}
HttpTunnelProducer::HttpTunnelProducer() {}
ChunkedHandler::ChunkedHandler() {}

#include "HttpCacheSM.h"
HttpCacheSM::HttpCacheSM() {}

HttpCacheAction::HttpCacheAction() : sm(nullptr) {}
void
HttpCacheAction::cancel(Continuation *c)
{
}
<|endoftext|>