<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// class interface header
#include "cURLManager.h"

// common implementation headers
#include "bzfio.h"

bool                    cURLManager::inited      = false;
CURLM                  *cURLManager::multiHandle = NULL;
std::map<CURL*,
	 cURLManager*>  cURLManager::cURLMap;

cURLManager::cURLManager()
{
  CURLcode result;

  theData   = NULL;
  theLen    = 0;
  errorCode = CURLE_OK;
  added     = false;

  if (!inited)
    setup();

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }
#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt(easyHandle, CURLOPT_NOSIGNAL, true);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOSIGNAL error: %d\n", result);
  }
#endif

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEFUNCTION,
			    cURLManager::writeFunction);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEFUNCTION error: %d\n", result);

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEDATA, this);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEDATA error: %d\n", result);

}

cURLManager::~cURLManager()
{
  if (added)
    removeHandle();
  curl_easy_cleanup(easyHandle);
  free(theData);
}

void cURLManager::setup()
{
  CURLcode result;

  DEBUG1("LIBCURL: %s\n", curl_version());
#if LIBCURL_VERSION_NUM >= 0x070a00
  if ((result = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("cURL Global init Error: %d\n", result);
#endif
  multiHandle = curl_multi_init();
  if (!multiHandle)
    DEBUG1("Unexpected error creating multi handle from libcurl \n");
  inited = true;
}

size_t cURLManager::writeFunction(void *ptr, size_t size, size_t nmemb,
				  void *stream)
{
  int len = size * nmemb;
  ((cURLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

void cURLManager::setTimeout(long timeout)
{
  CURLcode result;

  result = curl_easy_setopt(easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_TIMEOUT error: %d\n", result);
  }
}

void cURLManager::setNoBody()
{
  CURLcode result;
  long     nobody = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_NOBODY, nobody);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOBODY error: %d\n", result);
  }
}

void cURLManager::setGetMode()
{
  CURLcode result;
  long     get = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_HTTPGET, get);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_GET error: %d\n", result);
  }
}

void cURLManager::setURL(std::string url)
{
  CURLcode result;

  if (url == "")
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, NULL);
  else
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, url.c_str());
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_URL error: %d\n", result);
  }
}

void cURLManager::setProgressFunction(curl_progress_callback func, void* data)
{
  CURLcode result;
  if (func != NULL) {
    result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSFUNCTION, func);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSDATA, data);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 0);
  } else {
   result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 1);
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_SET_PROGRESS error: %d\n", result);
  }
}

void cURLManager::setRequestFileTime(bool request)
{
  CURLcode result;
  long     requestFileTime = request ? 1 : 0;
  result = curl_easy_setopt(easyHandle, CURLOPT_FILETIME, requestFileTime);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_FILETIME error: %d\n", result);
  }
}

void cURLManager::addHandle()
{
  CURLMcode result = curl_multi_add_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while adding easy handle from libcurl; Error: %d\n", result);
  cURLMap[easyHandle] = this;
  added = true;
}

void cURLManager::removeHandle()
{
  if (!added)
    return;
  cURLMap.erase(easyHandle);
  CURLMcode result = curl_multi_remove_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while removing easy handle from libcurl; Error: %d\n", result);
  added = false;
}

void cURLManager::finalization(char *, unsigned int, bool)
{
}

void cURLManager::collectData(char* ptr, int len)
{
  unsigned char *newData = (unsigned char *)realloc(theData, theLen + len);
  if (!newData) {
    DEBUG1("memory exhausted\n");
  } else {
    memcpy(newData + theLen, ptr, len);
    theLen += len;
    theData = newData;
  }
}

int cURLManager::perform()
{
  if (!inited)
    setup();

  int activeTransfers = 0;
  CURLMcode result;
  while (true) {
    result = curl_multi_perform(multiHandle, &activeTransfers);
    if (result != CURLM_CALL_MULTI_PERFORM)
      break;
  }
  if (result != CURLM_OK)
    DEBUG1("Error while doing multi_perform from libcurl; Error: %d\n", result);

  int      msgs_in_queue;
  CURLMsg *pendingMsg;
  CURL    *easy;

  while (true) {
    pendingMsg = curl_multi_info_read(multiHandle, &msgs_in_queue);
    if (!pendingMsg)
      break;

    easy        = pendingMsg->easy_handle;

    cURLMap[easy]->infoComplete(pendingMsg->data.result);

    if (msgs_in_queue <= 0)
      break;
  }

  return activeTransfers;
}

void cURLManager::infoComplete(CURLcode result)
{
  if (result != CURLE_OK)
    DEBUG1("File transfer terminated with error from libcurl; Error: %d\n", result);
  finalization((char *)theData, theLen, result == CURLE_OK);
  free(theData);
  removeHandle();
  theData = NULL;
  theLen  = 0;
}

bool cURLManager::getFileTime(time_t &t)
{
  long filetime;
  CURLcode result;
  result = curl_easy_getinfo(easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("CURLINFO_FILETIME error: %d\n", result);
    return false;
  }
  t = (time_t)filetime;
  return true;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Stay in the notify table until destroyed. Avoid some SEGV<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// class interface header
#include "cURLManager.h"

// common implementation headers
#include "bzfio.h"

bool                    cURLManager::inited      = false;
CURLM                  *cURLManager::multiHandle = NULL;
std::map<CURL*,
	 cURLManager*>  cURLManager::cURLMap;

cURLManager::cURLManager()
{
  CURLcode result;

  theData   = NULL;
  theLen    = 0;
  errorCode = CURLE_OK;
  added     = false;

  if (!inited)
    setup();

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }
#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt(easyHandle, CURLOPT_NOSIGNAL, true);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOSIGNAL error: %d\n", result);
  }
#endif

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEFUNCTION,
			    cURLManager::writeFunction);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEFUNCTION error: %d\n", result);

  result = curl_easy_setopt(easyHandle, CURLOPT_WRITEDATA, this);
  if (result != CURLE_OK)
    DEBUG1("CURLOPT_WRITEDATA error: %d\n", result);

  cURLMap[easyHandle] = this;
}

cURLManager::~cURLManager()
{
  if (added)
    removeHandle();
  cURLMap.erase(easyHandle);
  curl_easy_cleanup(easyHandle);
  free(theData);
}

void cURLManager::setup()
{
  CURLcode result;

  DEBUG1("LIBCURL: %s\n", curl_version());
#if LIBCURL_VERSION_NUM >= 0x070a00
  if ((result = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("cURL Global init Error: %d\n", result);
#endif
  multiHandle = curl_multi_init();
  if (!multiHandle)
    DEBUG1("Unexpected error creating multi handle from libcurl \n");
  inited = true;
}

size_t cURLManager::writeFunction(void *ptr, size_t size, size_t nmemb,
				  void *stream)
{
  int len = size * nmemb;
  ((cURLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

void cURLManager::setTimeout(long timeout)
{
  CURLcode result;

  result = curl_easy_setopt(easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_TIMEOUT error: %d\n", result);
  }
}

void cURLManager::setNoBody()
{
  CURLcode result;
  long     nobody = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_NOBODY, nobody);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_NOBODY error: %d\n", result);
  }
}

void cURLManager::setGetMode()
{
  CURLcode result;
  long     get = 1;

  result = curl_easy_setopt(easyHandle, CURLOPT_HTTPGET, get);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_GET error: %d\n", result);
  }
}

void cURLManager::setURL(std::string url)
{
  CURLcode result;

  if (url == "")
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, NULL);
  else
    result = curl_easy_setopt(easyHandle, CURLOPT_URL, url.c_str());
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_URL error: %d\n", result);
  }
}

void cURLManager::setProgressFunction(curl_progress_callback func, void* data)
{
  CURLcode result;
  if (func != NULL) {
    result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSFUNCTION, func);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_PROGRESSDATA, data);
    if (result == CURLE_OK)
      result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 0);
  } else {
   result = curl_easy_setopt(easyHandle, CURLOPT_NOPROGRESS, 1);
  }
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_SET_PROGRESS error: %d\n", result);
  }
}

void cURLManager::setRequestFileTime(bool request)
{
  CURLcode result;
  long     requestFileTime = request ? 1 : 0;
  result = curl_easy_setopt(easyHandle, CURLOPT_FILETIME, requestFileTime);
  if (result != CURLE_OK) {
    errorCode = result;
    DEBUG1("CURLOPT_FILETIME error: %d\n", result);
  }
}

void cURLManager::addHandle()
{
  CURLMcode result = curl_multi_add_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while adding easy handle from libcurl; Error: %d\n", result);
  added = true;
}

void cURLManager::removeHandle()
{
  if (!added)
    return;
  CURLMcode result = curl_multi_remove_handle(multiHandle, easyHandle);
  if (result != CURLM_OK)
    DEBUG1("Error while removing easy handle from libcurl; Error: %d\n", result);
  added = false;
}

void cURLManager::finalization(char *, unsigned int, bool)
{
}

void cURLManager::collectData(char* ptr, int len)
{
  unsigned char *newData = (unsigned char *)realloc(theData, theLen + len);
  if (!newData) {
    DEBUG1("memory exhausted\n");
  } else {
    memcpy(newData + theLen, ptr, len);
    theLen += len;
    theData = newData;
  }
}

int cURLManager::perform()
{
  if (!inited)
    setup();

  int activeTransfers = 0;
  CURLMcode result;
  while (true) {
    result = curl_multi_perform(multiHandle, &activeTransfers);
    if (result != CURLM_CALL_MULTI_PERFORM)
      break;
  }
  if (result != CURLM_OK)
    DEBUG1("Error while doing multi_perform from libcurl; Error: %d\n", result);

  int      msgs_in_queue;
  CURLMsg *pendingMsg;
  CURL    *easy;

  while (true) {
    pendingMsg = curl_multi_info_read(multiHandle, &msgs_in_queue);
    if (!pendingMsg)
      break;

    easy        = pendingMsg->easy_handle;

    cURLMap[easy]->infoComplete(pendingMsg->data.result);

    if (msgs_in_queue <= 0)
      break;
  }

  return activeTransfers;
}

void cURLManager::infoComplete(CURLcode result)
{
  if (result != CURLE_OK)
    DEBUG1("File transfer terminated with error from libcurl; Error: %d\n", result);
  finalization((char *)theData, theLen, result == CURLE_OK);
  free(theData);
  removeHandle();
  theData = NULL;
  theLen  = 0;
}

bool cURLManager::getFileTime(time_t &t)
{
  long filetime;
  CURLcode result;
  result = curl_easy_getinfo(easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("CURLINFO_FILETIME error: %d\n", result);
    return false;
  }
  t = (time_t)filetime;
  return true;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>
#include "Block.h"

namespace common {
namespace entity {

Block::Block(QPoint position) :
  Entity(position, true, true, "res/block.png") {

}

void Block::Update(std::weak_ptr<GameEngine> game_engine, int t) {
  (void) game_engine;
  (void) t;
}

void Block::HitByFire(std::weak_ptr<GameEngine> game_engine) {
  /* Called when entity is hit by fire. */
  // TODO : add bonus creation
  (void) game_engine;
  should_be_removed_ = true;
}

void Block::Serialize(QDataStream& stream) const {
  SerializeBaseEntity(stream, EntityId::kBlockId); //othing else to do
}

bool Block::operator==(const Block& other) const {
  return Entity::operator==(other);
}

}
}
<commit_msg>Typo.<commit_after>
#include "Block.h"

namespace common {
namespace entity {

Block::Block(QPoint position) :
  Entity(position, true, true, "res/block.png") {

}

void Block::Update(std::weak_ptr<GameEngine> game_engine, int t) {
  (void) game_engine;
  (void) t;
}

void Block::HitByFire(std::weak_ptr<GameEngine> game_engine) {
  /* Called when entity is hit by fire. */
  // TODO : add bonus creation
  (void) game_engine;
  should_be_removed_ = true;
}

void Block::Serialize(QDataStream& stream) const {
  SerializeBaseEntity(stream, EntityId::kBlockId); //nothing else to do
}

bool Block::operator==(const Block& other) const {
  return Entity::operator==(other);
}

}
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string HTML_RESPONSE() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
  ...and can improvise http. With limitations of course, but it's been easier than expected so far
"
         << "
 © 2015, Oslo and Akershus University College of Applied Sciences "
         << "\n";

  std::string html = stream.str();

  std::string header="HTTP/1.1 200 OK \n "        \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"      \
    "Server: IncludeOS prototype 4.0 \n"                \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"   \
    "Content-Type: text/html; charset=UTF-8 \n"     \
    "Content-Length: "+std::to_string(html.size())+"\n"   \
    "Accept-Ranges: bytes\n"          \
    "Connection: close\n\n";
  return header + html;
}

const std::string NOT_FOUND = "HTTP/1.1 404 Not Found \n Connection: close\n\n";

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server on port 80
  auto& server = inet->tcp().bind(80);

  hw::PIT::instance().onRepeatedTimeout(30s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([] (auto conn) -> bool {
      printf("<Service> @onAccept - Connection attempt from: %s \n",
             conn->to_string().c_str());
      return true; // allow all connections

    }).onConnect([] (auto conn) {
        printf("<Service> @onConnect - Connection successfully established.\n");
        // read async with a buffer size of 1024 bytes
        // define what to do when data is read
        conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
            // create string from buffer
            std::string data { (char*)buf.get(), n };
            printf("<Service> @read:\n%s\n", data.c_str());

            if (data.find("GET / ") != std::string::npos) {

              // create response
              std::string response = HTML_RESPONSE();
              // write the data from the string with the strings size
              conn->write(response.data(), response.size(), [](size_t n) {
                  printf("<Service> @write: %u bytes written\n", n);
                });
            }
            else {
              conn->write(NOT_FOUND.data(), NOT_FOUND.size());
            }
          });

      }).onDisconnect([](auto conn, auto reason) {
          printf("<Service> @onDisconnect - Reason: %s \n", reason.to_string().c_str());
          conn->close();
        }).onPacketReceived([](auto, auto packet) {
            printf("@Packet: %s\n", packet->to_string().c_str());
          });

  printf("*** TEST SERVICE STARTED *** \n");
}
<commit_msg>examples: added more debug on demo<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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 <os>
#include <net/inet4>
#include <net/dhcp/dh4client.hpp>
#include <math.h> // rand()
#include <sstream>

// An IP-stack object
std::unique_ptr<net::Inet4<VirtioNet> > inet;

using namespace std::chrono;

std::string HTML_RESPONSE() {
  int color = rand();
  std::stringstream stream;

  /* HTML Fonts */
  std::string ubuntu_medium  = "font-family: \'Ubuntu\', sans-serif; font-weight: 500; ";
  std::string ubuntu_normal  = "font-family: \'Ubuntu\', sans-serif; font-weight: 400; ";
  std::string ubuntu_light  = "font-family: \'Ubuntu\', sans-serif; font-weight: 300; ";

  /* HTML */
  stream << ""
         << "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300' rel='stylesheet' type='text/css'>"
         << ""
         << "<h1 style= \"color: " << "#" << std::hex << (color >> 8) << "\">"
         <<  "IncludeOS
"
         <<  "
Now speaks TCP!
"
    // .... generate more dynamic content
         << "
  ...and can improvise http. With limitations of course, but it's been easier than expected so far
"
         << "
 © 2015, Oslo and Akershus University College of Applied Sciences "
         << "\n";

  std::string html = stream.str();

  std::string header="HTTP/1.1 200 OK \n "        \
    "Date: Mon, 01 Jan 1970 00:00:01 GMT \n"      \
    "Server: IncludeOS prototype 4.0 \n"                \
    "Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT \n"   \
    "Content-Type: text/html; charset=UTF-8 \n"     \
    "Content-Length: "+std::to_string(html.size())+"\n"   \
    "Accept-Ranges: bytes\n"          \
    "Connection: close\n\n";
  return header + html;
}

const std::string NOT_FOUND = "HTTP/1.1 404 Not Found \nConnection: close\n\n";

void Service::start() {
  // Assign a driver (VirtioNet) to a network interface (eth0)
  // @note: We could determine the appropirate driver dynamically, but then we'd
  // have to include all the drivers into the image, which  we want to avoid.
  hw::Nic<VirtioNet>& eth0 = hw::Dev::eth<0,VirtioNet>();

  // Bring up a network stack, attached to the nic
  // @note : No parameters after 'nic' means we'll use DHCP for IP config.
  inet = std::make_unique<net::Inet4<VirtioNet> >(eth0);

  // Static IP configuration, until we (possibly) get DHCP
  // @note : Mostly to get a robust demo service that it works with and without DHCP
  inet->network_config( { 10,0,0,42 },      // IP
                        { 255,255,255,0 },  // Netmask
                        { 10,0,0,1 },       // Gateway
                        { 8,8,8,8 } );      // DNS

  srand(OS::cycles_since_boot());

  // Set up a TCP server on port 80
  auto& server = inet->tcp().bind(80);

  hw::PIT::instance().on_repeated_timeout(30s, []{
      printf("<Service> TCP STATUS:\n%s \n", inet->tcp().status().c_str());
    });

  // Add a TCP connection handler - here a hardcoded HTTP-service
  server.onAccept([] (auto conn) -> bool {
      printf("<Service> @onAccept - Connection attempt from: %s \n",
             conn->to_string().c_str());
      return true; // allow all connections

    })
    .onConnect([] (auto conn) {
      printf("<Service> @onConnect - Connection successfully established.\n");
      // read async with a buffer size of 1024 bytes
      // define what to do when data is read
      conn->read(1024, [conn](net::TCP::buffer_t buf, size_t n) {
          // create string from buffer
          std::string data { (char*)buf.get(), n };
          printf("<Service> @read:\n%s\n", data.c_str());

          if (data.find("GET / ") != std::string::npos) {

            // create response
            std::string response = HTML_RESPONSE();
            // write the data from the string with the strings size
            conn->write(response.data(), response.size(), [](size_t n) {
                printf("<Service> @write: %u bytes written\n", n);
              });
          }
          else {
            conn->write(NOT_FOUND.data(), NOT_FOUND.size());
          }
        });

    })
    .onDisconnect([](auto conn, auto reason) {
        printf("<Service> @onDisconnect - Reason: %s \n", reason.to_string().c_str());
        conn->close();
    })
    .onPacketReceived([](auto, auto packet) {
        printf("@Packet: %s\n", packet->to_string().c_str());
    })
    .onError([](auto, auto err) {
      printf("<Service> @onError - %s\n", err.what());
    });

  printf("*** TEST SERVICE STARTED *** \n");
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "bytes.hh"

#include <optional>
#include <variant>

#include <seastar/util/variant_utils.hh>

#include "utils/fragmented_temporary_buffer.hh"

namespace cql3 {

struct null_value {
};

struct unset_value {
};

class raw_value;
/// \brief View to a raw CQL protocol value.
///
/// \see raw_value
struct raw_value_view {
    std::variant<fragmented_temporary_buffer::view, null_value, unset_value> _data;
    // Temporary storage is only useful if a raw_value_view needs to be instantiated
    // with a value which lifetime is bounded only to the view itself.
    // This hack is introduced in order to avoid storing temporary storage
    // in an external container, which may cause memory leaking problems.
    // This pointer is disengaged for regular raw_value_view instances.
    // Data is stored in a shared pointer for two reasons:
    // - pointers are cheap to copy
    // - it makes the view keep its semantics - it's safe to copy a view multiple times
    //   and all copies still refer to the same underlying data.
    lw_shared_ptr<bytes> _temporary_storage = nullptr;

    raw_value_view(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(fragmented_temporary_buffer::view data)
        : _data{data}
    {}
    // This constructor is only used by make_temporary() and it acquires ownership
    // of the given buffer. The view created that way refers to its own temporary storage.
    explicit raw_value_view(bytes&& temporary_storage);
public:
    static raw_value_view make_null() {
        return raw_value_view{std::move(null_value{})};
    }
    static raw_value_view make_unset_value() {
        return raw_value_view{std::move(unset_value{})};
    }
    static raw_value_view make_value(fragmented_temporary_buffer::view view) {
        return raw_value_view{view};
    }
    static raw_value_view make_temporary(raw_value&& value);
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<fragmented_temporary_buffer::view>(_data);
    }
    std::optional<fragmented_temporary_buffer::view> data() const {
        if (auto pdata = std::get_if<fragmented_temporary_buffer::view>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const fragmented_temporary_buffer::view* operator->() const {
        return &std::get<fragmented_temporary_buffer::view>(_data);
    }
    const fragmented_temporary_buffer::view& operator*() const {
        return std::get<fragmented_temporary_buffer::view>(_data);
    }

    bool operator==(const raw_value_view& other) const {
        if (_data.index() != other._data.index()) {
            return false;
        }
        if (is_value() && **this != *other) {
            return false;
        }
        return true;
    }
    bool operator!=(const raw_value_view& other) const {
        return !(*this == other);
    }

    friend std::ostream& operator<<(std::ostream& os, const raw_value_view& value);
};

/// \brief Raw CQL protocol value.
///
/// The `raw_value` type represents an uninterpreted value from the CQL wire
/// protocol. A raw value can hold either a null value, an unset value, or a byte
/// blob that represents the value.
class raw_value {
    std::variant<bytes, null_value, unset_value> _data;

    raw_value(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(bytes&& data)
        : _data{std::move(data)}
    {}
    raw_value(const bytes& data)
        : _data{data}
    {}
public:
    static raw_value make_null() {
        return raw_value{std::move(null_value{})};
    }
    static raw_value make_unset_value() {
        return raw_value{std::move(unset_value{})};
    }
    static raw_value make_value(const raw_value_view& view);
    static raw_value make_value(bytes&& bytes) {
        return raw_value{std::move(bytes)};
    }
    static raw_value make_value(const bytes& bytes) {
        return raw_value{bytes};
    }
    static raw_value make_value(const bytes_opt& bytes) {
        if (bytes) {
            return make_value(*bytes);
        }
        return make_null();
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<bytes>(_data);
    }
    bytes_opt data() const {
        if (auto pdata = std::get_if<bytes>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const bytes* operator->() const {
        return &std::get<bytes>(_data);
    }
    const bytes& operator*() const {
        return std::get<bytes>(_data);
    }
    bytes&& extract_value() && {
        auto b = std::get_if<bytes>(&_data);
        assert(b);
        return std::move(*b);
    }
    raw_value_view to_view() const;
};

}

inline bytes to_bytes(const cql3::raw_value_view& view)
{
    return linearized(*view);
}

inline bytes_opt to_bytes_opt(const cql3::raw_value_view& view) {
    auto buffer_view = view.data();
    if (buffer_view) {
        return bytes_opt(linearized(*buffer_view));
    }
    return bytes_opt();
}

inline bytes_opt to_bytes_opt(const cql3::raw_value& value) {
    return to_bytes_opt(value.to_view());
}
<commit_msg>cql3: values: add an internals-independent API to raw_value_view<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "types.hh"
#include "types/collection.hh"
#include "bytes.hh"

#include <optional>
#include <variant>

#include <seastar/util/variant_utils.hh>

#include "utils/fragmented_temporary_buffer.hh"

namespace cql3 {

struct null_value {
};

struct unset_value {
};

class raw_value;
/// \brief View to a raw CQL protocol value.
///
/// \see raw_value
struct raw_value_view {
    std::variant<fragmented_temporary_buffer::view, null_value, unset_value> _data;
    // Temporary storage is only useful if a raw_value_view needs to be instantiated
    // with a value which lifetime is bounded only to the view itself.
    // This hack is introduced in order to avoid storing temporary storage
    // in an external container, which may cause memory leaking problems.
    // This pointer is disengaged for regular raw_value_view instances.
    // Data is stored in a shared pointer for two reasons:
    // - pointers are cheap to copy
    // - it makes the view keep its semantics - it's safe to copy a view multiple times
    //   and all copies still refer to the same underlying data.
    lw_shared_ptr<bytes> _temporary_storage = nullptr;

    raw_value_view(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value_view(fragmented_temporary_buffer::view data)
        : _data{data}
    {}
    // This constructor is only used by make_temporary() and it acquires ownership
    // of the given buffer. The view created that way refers to its own temporary storage.
    explicit raw_value_view(bytes&& temporary_storage);
public:
    static raw_value_view make_null() {
        return raw_value_view{std::move(null_value{})};
    }
    static raw_value_view make_unset_value() {
        return raw_value_view{std::move(unset_value{})};
    }
    static raw_value_view make_value(fragmented_temporary_buffer::view view) {
        return raw_value_view{view};
    }
    static raw_value_view make_value(bytes_view view) {
        return raw_value_view{fragmented_temporary_buffer::view(view)};
    }
    static raw_value_view make_temporary(raw_value&& value);
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<fragmented_temporary_buffer::view>(_data);
    }
    std::optional<fragmented_temporary_buffer::view> data() const {
        if (auto pdata = std::get_if<fragmented_temporary_buffer::view>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const fragmented_temporary_buffer::view* operator->() const {
        return &std::get<fragmented_temporary_buffer::view>(_data);
    }
    const fragmented_temporary_buffer::view& operator*() const {
        return std::get<fragmented_temporary_buffer::view>(_data);
    }

    bool operator==(const raw_value_view& other) const {
        if (_data.index() != other._data.index()) {
            return false;
        }
        if (is_value() && **this != *other) {
            return false;
        }
        return true;
    }
    bool operator!=(const raw_value_view& other) const {
        return !(*this == other);
    }

    template <typename Func>
    requires std::invocable<Func, const managed_bytes_view&> && std::invocable<Func, const fragmented_temporary_buffer::view&>
    decltype(auto) with_value(Func f) const {
        return f(std::get<fragmented_temporary_buffer::view>(_data));
    }

    template <typename Func>
    requires std::invocable<Func, bytes_view>
    decltype(auto) with_linearized(Func f) const {
        return with_value([&] (const FragmentedView auto& v) {
            return ::with_linearized(v, std::forward<Func>(f));
        });
    }

    size_t size_bytes() const {
        return with_value([&] (const FragmentedView auto& v) {
            return v.size_bytes();
        });
    }

    template <typename ValueType>
    ValueType deserialize(const abstract_type& t) const {
        return value_cast<ValueType>(with_value([&] (const FragmentedView auto& v) { return t.deserialize(v); }));
    }

    template <typename ValueType>
    ValueType deserialize(const collection_type_impl& t, cql_serialization_format sf) const {
        return value_cast<ValueType>(with_value([&] (const FragmentedView auto& v) { return t.deserialize(v, sf); }));
    }

    void validate(const abstract_type& t, cql_serialization_format sf) const {
        return with_value([&] (const FragmentedView auto& v) { return t.validate(v, sf); });
    }

    template <typename ValueType>
    ValueType validate_and_deserialize(const collection_type_impl& t, cql_serialization_format sf) const {
        return with_value([&] (const FragmentedView auto& v) {
            t.validate(v, sf);
            return value_cast<ValueType>(t.deserialize(v, sf));
        });
    }

    template <typename ValueType>
    ValueType validate_and_deserialize(const abstract_type& t, cql_serialization_format sf) const {
        return with_value([&] (const FragmentedView auto& v) {
            t.validate(v, sf);
            return value_cast<ValueType>(t.deserialize(v));
        });
    }

    friend std::ostream& operator<<(std::ostream& os, const raw_value_view& value);
};

/// \brief Raw CQL protocol value.
///
/// The `raw_value` type represents an uninterpreted value from the CQL wire
/// protocol. A raw value can hold either a null value, an unset value, or a byte
/// blob that represents the value.
class raw_value {
    std::variant<bytes, null_value, unset_value> _data;

    raw_value(null_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(unset_value&& data)
        : _data{std::move(data)}
    {}
    raw_value(bytes&& data)
        : _data{std::move(data)}
    {}
    raw_value(const bytes& data)
        : _data{data}
    {}
public:
    static raw_value make_null() {
        return raw_value{std::move(null_value{})};
    }
    static raw_value make_unset_value() {
        return raw_value{std::move(unset_value{})};
    }
    static raw_value make_value(const raw_value_view& view);
    static raw_value make_value(bytes&& bytes) {
        return raw_value{std::move(bytes)};
    }
    static raw_value make_value(const bytes& bytes) {
        return raw_value{bytes};
    }
    static raw_value make_value(const bytes_opt& bytes) {
        if (bytes) {
            return make_value(*bytes);
        }
        return make_null();
    }
    bool is_null() const {
        return std::holds_alternative<null_value>(_data);
    }
    bool is_unset_value() const {
        return std::holds_alternative<unset_value>(_data);
    }
    bool is_value() const {
        return std::holds_alternative<bytes>(_data);
    }
    bytes_opt data() const {
        if (auto pdata = std::get_if<bytes>(&_data)) {
            return *pdata;
        }
        return {};
    }
    explicit operator bool() const {
        return is_value();
    }
    const bytes* operator->() const {
        return &std::get<bytes>(_data);
    }
    const bytes& operator*() const {
        return std::get<bytes>(_data);
    }
    bytes&& extract_value() && {
        auto b = std::get_if<bytes>(&_data);
        assert(b);
        return std::move(*b);
    }
    bytes to_bytes() && {
        return std::move(std::get<bytes>(_data));
    }
    raw_value_view to_view() const;
};

}

inline bytes to_bytes(const cql3::raw_value_view& view)
{
    return linearized(*view);
}

inline bytes_opt to_bytes_opt(const cql3::raw_value_view& view) {
    auto buffer_view = view.data();
    if (buffer_view) {
        return bytes_opt(linearized(*buffer_view));
    }
    return bytes_opt();
}

inline bytes_opt to_bytes_opt(const cql3::raw_value& value) {
    return to_bytes_opt(value.to_view());
}
<|endoftext|>


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

#include "compiler/PoolAlloc.h"

#ifndef _MSC_VER
#include <stdint.h>
#endif
#include <stdio.h>

#include "compiler/InitializeGlobals.h"
#include "compiler/osinclude.h"

OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;

void InitializeGlobalPools()
{
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (globalPools)
        return;

    TThreadGlobalPools* threadData = new TThreadGlobalPools();
    threadData->globalPoolAllocator = 0;

    OS_SetTLSValue(PoolIndex, threadData);
}

void FreeGlobalPools()
{
    // Release the allocated memory for this thread.
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (!globalPools)
        return;

    delete globalPools;
}

bool InitializePoolIndex()
{
    // Allocate a TLS index.
    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
        return false;

    return true;
}

void FreePoolIndex()
{
    // Release the TLS index.
    OS_FreeTLSIndex(PoolIndex);
}

TPoolAllocator& GetGlobalPoolAllocator()
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    return *threadData->globalPoolAllocator;
}

void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    threadData->globalPoolAllocator = poolAllocator;
}

//
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
    pageSize(growthIncrement),
    alignment(allocationAlignment),
    freeList(0),
    inUseList(0),
    numCalls(0),
    totalBytes(0)
{
    //
    // Don't allow page sizes we know are smaller than all common
    // OS page sizes.
    //
    if (pageSize < 4*1024)
        pageSize = 4*1024;

    //
    // A large currentPageOffset indicates a new page needs to
    // be obtained to allocate memory.
    //
    currentPageOffset = pageSize;

    //
    // Adjust alignment to be at least pointer aligned and
    // power of 2.
    //
    size_t minAlign = sizeof(void*);
    alignment &= ~(minAlign - 1);
    if (alignment < minAlign)
        alignment = minAlign;
    size_t a = 1;
    while (a < alignment)
        a <<= 1;
    alignment = a;
    alignmentMask = a - 1;

    //
    // Align header skip
    //
    headerSkip = minAlign;
    if (headerSkip < sizeof(tHeader)) {
        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
    }
}

TPoolAllocator::~TPoolAllocator()
{
    while (inUseList) {
        tHeader* next = inUseList->nextPage;
        inUseList->~tHeader();
        delete [] reinterpret_cast<char*>(inUseList);
        inUseList = next;
    }

    // We should not check the guard blocks
    // here, because we did it already when the block was
    // placed into the free list.
    //
    while (freeList) {
        tHeader* next = freeList->nextPage;
        delete [] reinterpret_cast<char*>(freeList);
        freeList = next;
    }
}

// Support MSVC++ 6.0
const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
const unsigned char TAllocation::userDataFill       = 0xcd;

#ifdef GUARD_BLOCKS
    const size_t TAllocation::guardBlockSize = 16;
#else
    const size_t TAllocation::guardBlockSize = 0;
#endif

//
// Check a single guard block for damage
//
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
{
#ifdef GUARD_BLOCKS
    for (size_t x = 0; x < guardBlockSize; x++) {
        if (blockMem[x] != val) {
            char assertMsg[80];

            // We don't print the assert message.  It's here just to be helpful.
            sprintf(assertMsg, "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
                    locText, size, data());
            assert(0 && "PoolAlloc: Damage in guard block");
        }
    }
#endif
}

void TPoolAllocator::push()
{
    tAllocState state = { currentPageOffset, inUseList };

    stack.push_back(state);

    //
    // Indicate there is no current page to allocate from.
    //
    currentPageOffset = pageSize;
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred since the last push(), or since the
// last pop(), or since the object's creation.
//
// The deallocated pages are saved for future allocations.
//
void TPoolAllocator::pop()
{
    if (stack.size() < 1)
        return;

    tHeader* page = stack.back().page;
    currentPageOffset = stack.back().offset;

    while (inUseList != page) {
        // invoke destructor to free allocation list
        inUseList->~tHeader();

        tHeader* nextInUse = inUseList->nextPage;
        if (inUseList->pageCount > 1)
            delete [] reinterpret_cast<char*>(inUseList);
        else {
            inUseList->nextPage = freeList;
            freeList = inUseList;
        }
        inUseList = nextInUse;
    }

    stack.pop_back();
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred.
//
void TPoolAllocator::popAll()
{
    while (stack.size() > 0)
        pop();
}

void* TPoolAllocator::allocate(size_t numBytes)
{
    // If we are using guard blocks, all allocations are bracketed by
    // them: [guardblock][allocation][guardblock].  numBytes is how
    // much memory the caller asked for.  allocationSize is the total
    // size including guard blocks.  In release build,
    // guardBlockSize=0 and this all gets optimized away.
    size_t allocationSize = TAllocation::allocationSize(numBytes);

    //
    // Just keep some interesting statistics.
    //
    ++numCalls;
    totalBytes += numBytes;

    //
    // Do the allocation, most likely case first, for efficiency.
    // This step could be moved to be inline sometime.
    //
    if (currentPageOffset + allocationSize <= pageSize) {
        //
        // Safe to allocate from currentPageOffset.
        //
        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
        currentPageOffset += allocationSize;
        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;

        return initializeAllocation(inUseList, memory, numBytes);
    }

    if (allocationSize + headerSkip > pageSize) {
        //
        // Do a multi-page allocation.  Don't mix these with the others.
        // The OS is efficient and allocating and free-ing multiple pages.
        //
        size_t numBytesToAlloc = allocationSize + headerSkip;
        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
        if (memory == 0)
            return 0;

        // Use placement-new to initialize header
        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
        inUseList = memory;

        currentPageOffset = pageSize;  // make next allocation come from a new page

        // No guard blocks for multi-page allocations (yet)
        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
    }

    //
    // Need a simple page to allocate from.
    //
    tHeader* memory;
    if (freeList) {
        memory = freeList;
        freeList = freeList->nextPage;
    } else {
        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
        if (memory == 0)
            return 0;
    }

    // Use placement-new to initialize header
    new(memory) tHeader(inUseList, 1);
    inUseList = memory;

    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;

    return initializeAllocation(inUseList, ret, numBytes);
}

//
// Check all allocations in a list for damage by calling check on each.
//
void TAllocation::checkAllocList() const
{
    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
        alloc->check();
}
<commit_msg>Fix printf format specifier in PoolAlloc.cpp.<commit_after>//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/PoolAlloc.h"

#ifndef _MSC_VER
#include <stdint.h>
#endif
#include <stdio.h>

#include "compiler/InitializeGlobals.h"
#include "compiler/osinclude.h"

OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;

void InitializeGlobalPools()
{
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (globalPools)
        return;

    TThreadGlobalPools* threadData = new TThreadGlobalPools();
    threadData->globalPoolAllocator = 0;

    OS_SetTLSValue(PoolIndex, threadData);
}

void FreeGlobalPools()
{
    // Release the allocated memory for this thread.
    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
    if (!globalPools)
        return;

    delete globalPools;
}

bool InitializePoolIndex()
{
    // Allocate a TLS index.
    if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
        return false;

    return true;
}

void FreePoolIndex()
{
    // Release the TLS index.
    OS_FreeTLSIndex(PoolIndex);
}

TPoolAllocator& GetGlobalPoolAllocator()
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    return *threadData->globalPoolAllocator;
}

void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{
    TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));

    threadData->globalPoolAllocator = poolAllocator;
}

//
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
    pageSize(growthIncrement),
    alignment(allocationAlignment),
    freeList(0),
    inUseList(0),
    numCalls(0),
    totalBytes(0)
{
    //
    // Don't allow page sizes we know are smaller than all common
    // OS page sizes.
    //
    if (pageSize < 4*1024)
        pageSize = 4*1024;

    //
    // A large currentPageOffset indicates a new page needs to
    // be obtained to allocate memory.
    //
    currentPageOffset = pageSize;

    //
    // Adjust alignment to be at least pointer aligned and
    // power of 2.
    //
    size_t minAlign = sizeof(void*);
    alignment &= ~(minAlign - 1);
    if (alignment < minAlign)
        alignment = minAlign;
    size_t a = 1;
    while (a < alignment)
        a <<= 1;
    alignment = a;
    alignmentMask = a - 1;

    //
    // Align header skip
    //
    headerSkip = minAlign;
    if (headerSkip < sizeof(tHeader)) {
        headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
    }
}

TPoolAllocator::~TPoolAllocator()
{
    while (inUseList) {
        tHeader* next = inUseList->nextPage;
        inUseList->~tHeader();
        delete [] reinterpret_cast<char*>(inUseList);
        inUseList = next;
    }

    // We should not check the guard blocks
    // here, because we did it already when the block was
    // placed into the free list.
    //
    while (freeList) {
        tHeader* next = freeList->nextPage;
        delete [] reinterpret_cast<char*>(freeList);
        freeList = next;
    }
}

// Support MSVC++ 6.0
const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
const unsigned char TAllocation::userDataFill       = 0xcd;

#ifdef GUARD_BLOCKS
    const size_t TAllocation::guardBlockSize = 16;
#else
    const size_t TAllocation::guardBlockSize = 0;
#endif

//
// Check a single guard block for damage
//
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
{
#ifdef GUARD_BLOCKS
    for (size_t x = 0; x < guardBlockSize; x++) {
        if (blockMem[x] != val) {
            char assertMsg[80];

            // We don't print the assert message.  It's here just to be helpful.
#if defined(_MSC_VER)
            sprintf(assertMsg, "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
                    locText, size, data());
#else
            sprintf(assertMsg, "PoolAlloc: Damage %s %z byte allocation at 0x%p\n",
                    locText, size, data());
#endif
            assert(0 && "PoolAlloc: Damage in guard block");
        }
    }
#endif
}

void TPoolAllocator::push()
{
    tAllocState state = { currentPageOffset, inUseList };

    stack.push_back(state);

    //
    // Indicate there is no current page to allocate from.
    //
    currentPageOffset = pageSize;
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred since the last push(), or since the
// last pop(), or since the object's creation.
//
// The deallocated pages are saved for future allocations.
//
void TPoolAllocator::pop()
{
    if (stack.size() < 1)
        return;

    tHeader* page = stack.back().page;
    currentPageOffset = stack.back().offset;

    while (inUseList != page) {
        // invoke destructor to free allocation list
        inUseList->~tHeader();

        tHeader* nextInUse = inUseList->nextPage;
        if (inUseList->pageCount > 1)
            delete [] reinterpret_cast<char*>(inUseList);
        else {
            inUseList->nextPage = freeList;
            freeList = inUseList;
        }
        inUseList = nextInUse;
    }

    stack.pop_back();
}

//
// Do a mass-deallocation of all the individual allocations
// that have occurred.
//
void TPoolAllocator::popAll()
{
    while (stack.size() > 0)
        pop();
}

void* TPoolAllocator::allocate(size_t numBytes)
{
    // If we are using guard blocks, all allocations are bracketed by
    // them: [guardblock][allocation][guardblock].  numBytes is how
    // much memory the caller asked for.  allocationSize is the total
    // size including guard blocks.  In release build,
    // guardBlockSize=0 and this all gets optimized away.
    size_t allocationSize = TAllocation::allocationSize(numBytes);

    //
    // Just keep some interesting statistics.
    //
    ++numCalls;
    totalBytes += numBytes;

    //
    // Do the allocation, most likely case first, for efficiency.
    // This step could be moved to be inline sometime.
    //
    if (currentPageOffset + allocationSize <= pageSize) {
        //
        // Safe to allocate from currentPageOffset.
        //
        unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
        currentPageOffset += allocationSize;
        currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;

        return initializeAllocation(inUseList, memory, numBytes);
    }

    if (allocationSize + headerSkip > pageSize) {
        //
        // Do a multi-page allocation.  Don't mix these with the others.
        // The OS is efficient and allocating and free-ing multiple pages.
        //
        size_t numBytesToAlloc = allocationSize + headerSkip;
        tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
        if (memory == 0)
            return 0;

        // Use placement-new to initialize header
        new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
        inUseList = memory;

        currentPageOffset = pageSize;  // make next allocation come from a new page

        // No guard blocks for multi-page allocations (yet)
        return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
    }

    //
    // Need a simple page to allocate from.
    //
    tHeader* memory;
    if (freeList) {
        memory = freeList;
        freeList = freeList->nextPage;
    } else {
        memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
        if (memory == 0)
            return 0;
    }

    // Use placement-new to initialize header
    new(memory) tHeader(inUseList, 1);
    inUseList = memory;

    unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
    currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;

    return initializeAllocation(inUseList, ret, numBytes);
}

//
// Check all allocations in a list for damage by calling check on each.
//
void TAllocation::checkAllocList() const
{
    for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
        alloc->check();
}
<|endoftext|>


<commit_before>#include <openlane/component_provider.h>
#include <openlane/module.h>
#include <iostream>
#include <string>

typedef uint32_t (*ComponentFn)(void *ctx);
ComponentFn LCT;

namespace openlane {

std::string MakeModuleName(const char* name) {
    std::string module("lib");
    module.append(name);
    module.append(".so");
    return module;
}

std::string MakeConfigName(const char* name) {
    std::string config(name);
    config.append(".xml");
    return config;
}

ComponentProvider::ComponentProvider() :
    xml_parser(this)
{
}

ComponentProvider::~ComponentProvider() {
    ComponentReverseIterator b = modules.rbegin();
    ComponentReverseIterator e = modules.rend();

    for(;b != e; ++b) {
        ErrorCode res = (*b)->GetSymbol("UnloadComponent", LCT);
        if (Ok == res)
            LCT(this); // FIXME
    }
}

ErrorCode ComponentProvider::LoadComponent(const char* filename) {

    ErrorCode res = Ok;
    try
    {
        DynamicLibraryPtr module(new DynamicLibrary);
        res = module->Load(filename);
        std::cout << "LoadComponent\tLoad(" << filename << ")=" << res << std::endl;

        if (Ok == res)
            res = module->GetSymbol("LoadComponent", LCT);

        if (Ok == res)
            if (LCT(this) == 0) res = Ok; // FIXME

        if (Ok == res)
            modules.push_back(module);
    }
    catch(const std::bad_alloc&)
    {
        res = NoMemory;
    }

    return res;
}

ErrorCode ComponentProvider::Initialize(const char* filename) {
    configs.push_back(std::string(filename));
        std::cout << "ComponentProvider::Initialize\tname1=" << *configs.begin() << std::endl;

    while(!configs.empty()) {
        std::cout << "ComponentProvider::Initialize\tname=" << *configs.begin() << std::endl;
        LoadConfig(configs.begin()->c_str());
        configs.erase(configs.begin());
    }
    return Ok;
}

ErrorCode ComponentProvider::LoadConfig(const char* filename) {
    if (!filename)
        return InvalidArgument;

    ErrorCode result = xml_parser.Parse(filename);
    if (result != Ok)
        return result;

    return Ok;
}

ErrorCode ComponentProvider::RegisterComponent(uint32_t id, CreateComponentFn fun) {
    std::cout << "ComponentProvider::RegisterComponent\tid=" << id << std::endl;
    dic[id] = fun;
    return Ok;
}

ErrorCode ComponentProvider::UnregisterComponent(uint32_t id) {
    std::cout << "ComponentProvider::UnregisterComponent\tid=" << id << std::endl;
    return Ok;
}

void ComponentProvider::OnLoadComponent(const char* name) {
    std::string module_name = MakeModuleName(name);
    std::cout << "ComponentProvider::OnLoadComponent\tname=" << module_name << std::endl;
    LoadComponent(module_name.c_str());
}

void ComponentProvider::OnLoadConfig(const char* name) {
    std::string config_name = MakeConfigName(name);
    std::cout << "ComponentProvider::OnLoadConfig\tname=" << config_name << std::endl;
    //LoadConfig(config_name.c_str());
    configs.push_back(config_name);
}

} /* openlane */
<commit_msg>Fix logging<commit_after>#include <openlane/component_provider.h>
#include <openlane/module.h>
#include <iostream>
#include <string>

namespace {
typedef uint32_t (*ComponentFn)(void *ctx);
ComponentFn LCT;
}

namespace openlane {

std::string MakeModuleName(const char* name) {
    std::string module("lib");
    module.append(name);
    module.append(".so");
    return module;
}

std::string MakeConfigName(const char* name) {
    std::string config(name);
    config.append(".xml");
    return config;
}

ComponentProvider::ComponentProvider() :
    xml_parser(this)
{
}

ComponentProvider::~ComponentProvider() {
    ComponentReverseIterator b = modules.rbegin();
    ComponentReverseIterator e = modules.rend();

    for(;b != e; ++b) {
        ErrorCode res = (*b)->GetSymbol("UnloadComponent", LCT);
        if (Ok == res)
            LCT(this); // FIXME
    }
}

ErrorCode ComponentProvider::LoadComponent(const char* filename) {

    ErrorCode res = Ok;
    try
    {
        DynamicLibraryPtr module(new DynamicLibrary);
        res = module->Load(filename);
        std::cout << "component_provider\tLoad component " << filename << ", result=" << res << std::endl;

        if (Ok == res)
            res = module->GetSymbol("LoadComponent", LCT);

        if (Ok == res)
            if (LCT(this) == 0) res = Ok; // FIXME

        if (Ok == res)
            modules.push_back(module);
    }
    catch(const std::bad_alloc&)
    {
        res = NoMemory;
    }

    return res;
}

ErrorCode ComponentProvider::Initialize(const char* filename) {
    std::cout << "component_provider\tInitialize" << std::endl;
    configs.push_back(std::string(filename));

    while(!configs.empty()) {
        LoadConfig(configs.begin()->c_str());
        configs.erase(configs.begin());
    }
    return Ok;
}

ErrorCode ComponentProvider::LoadConfig(const char* filename) {
    if (!filename)
        return InvalidArgument;

    std::cout << "component_provider\tParse config, name=" << filename << std::endl;
    ErrorCode result = xml_parser.Parse(filename);
    if (result != Ok)
        return result;

    return Ok;
}

ErrorCode ComponentProvider::RegisterComponent(uint32_t id, CreateComponentFn fun) {
    std::cout << "component_provider\tRegisterComponent id=" << id << std::endl;
    dic[id] = fun;
    return Ok;
}

ErrorCode ComponentProvider::UnregisterComponent(uint32_t id) {
    std::cout << "component_provider\tUnregisterComponent id=" << id << std::endl;
    return Ok;
}

void ComponentProvider::OnLoadComponent(const char* name) {
    std::string module_name = MakeModuleName(name);
    LoadComponent(module_name.c_str());
}

void ComponentProvider::OnLoadConfig(const char* name) {
    std::string config_name = MakeConfigName(name);
    configs.push_back(config_name);
}

} /* openlane */
<|endoftext|>


<commit_before>// This file is part of the "x0" project, http://github.com/christianparpart/x0>
//   (c) 2009-2017 Christian Parpart <christian@parpart.family>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/client/HttpClient.h>
#include <xzero/http/HttpRequest.h>
#include <xzero/http/HeaderFieldList.h>
#include <xzero/net/TcpEndPoint.h>
#include <xzero/executor/PosixScheduler.h>
#include <xzero/net/DnsClient.h>
#include <xzero/io/FileUtil.h>
#include <xzero/Application.h>
#include <xzero/RuntimeError.h>
#include <xzero/Uri.h>
#include <xzero/Flags.h>
#include <xzero/logging.h>
#include <unordered_map>
#include "sysconfig.h"
#include <iostream>
#include <unistd.h>

// #define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

#define VERBOSE(msg...) logInfo("xurl", msg)
#define DEBUG(msg...) logDebug("xurl", msg)
#define TRACE(msg...) logTrace("xurl", msg)

using namespace xzero;
using namespace xzero::http;
using namespace xzero::http::client;

using xzero::http::HttpRequestInfo;
using xzero::http::HttpVersion;
using xzero::http::HeaderField;

class ServicePortMapping { // {{{
 public:
  ServicePortMapping();

  void loadFile(const std::string& path = "/etc/services");
  void loadContent(const std::string& content);

  int tcp(const std::string& name);
  int udp(const std::string& name);

 private:
  std::unordered_map<std::string, int> tcp_;
  std::unordered_map<std::string, int> udp_;
};

ServicePortMapping::ServicePortMapping()
    : tcp_() {
  tcp_["http"] = 80;
  tcp_["https"] = 443;
}

int ServicePortMapping::tcp(const std::string& name) {
  auto i = tcp_.find(name);
  if (i != tcp_.end())
    return i->second;

  RAISE(RuntimeError, "Unknown service '%s'", name.c_str());
}
// }}}

class TerminalLogTarget : public ::xzero::LogTarget { // {{{
 public:
  void log(LogLevel level,
           const std::string& component,
           const std::string& message) override;
};

void TerminalLogTarget::log(LogLevel level,
                            const std::string& component,
                            const std::string& message) {
  if (component == "xurl") {
    printf("%s\n", message.c_str());
  } else {
    printf("[%s] %s\n", component.c_str(), message.c_str());
  }
}
// }}}

class XUrl {
 public:
  XUrl();

  int run(int argc, const char* argv[]);

 private:
  void addRequestHeader(const std::string& value);
  Uri makeUri(const std::string& url);
  IPAddress getIPAddress(const std::string& host);
  int getPort(const Uri& uri);
  void query(const Uri& uri);

 private:
  PosixScheduler scheduler_;
  Flags flags_;
  DnsClient dns_;
  Duration connectTimeout_;
  Duration readTimeout_;
  Duration writeTimeout_;
  TerminalLogTarget logTarget_;
  http::HeaderFieldList requestHeaders_;
};

XUrl::XUrl()
    : scheduler_(CatchAndLogExceptionHandler("xurl")),
      flags_(),
      dns_(),
      connectTimeout_(4_seconds),
      readTimeout_(60_seconds),
      writeTimeout_(10_seconds),
      logTarget_(),
      requestHeaders_()
{
  Application::init();
  //Application::logToStderr(LogLevel::Info);
  Logger::get()->addTarget(&logTarget_);

  requestHeaders_.push_back("User-Agent", "xurl/" PACKAGE_VERSION);

  flags_.defineBool("help", 'h', "Prints this help.");
  flags_.defineBool("head", 'I', "Performs a HEAD request.");
  flags_.defineBool("verbose", 'v', "Be verbose (log level: info)");
  flags_.defineString("output", 'o', "PATH", "Write response body to given file.");
  flags_.defineString("log-level", 'L', "STRING", "Log level.", "warning");
  flags_.defineString("method", 'X', "METHOD", "HTTP method", "GET");
  flags_.defineNumber("connect-timeout", 0, "MS", "TCP connect() timeout", 10_seconds .milliseconds());
  flags_.defineString("upload-file", 'T', "PATH", "Uploads given file.", "");
  flags_.defineString("header", 'H', "HEADER", "Adds a custom request header",
      None(),
      std::bind(&XUrl::addRequestHeader, this, std::placeholders::_1));
  flags_.defineBool("ipv4", '4', "Favor IPv4 for TCP/IP communication.");
  flags_.defineBool("ipv6", '6', "Favor IPv6 for TCP/IP communication.");
  flags_.enableParameters("URL", "URL to query");
}

void XUrl::addRequestHeader(const std::string& field) {
  requestHeaders_.push_back(HeaderField::parse(field));
}

int XUrl::run(int argc, const char* argv[]) {
  std::error_code ec = flags_.parse(argc, argv);
  if (ec) {
    fprintf(stderr, "Failed to parse flags. %s\n", ec.message().c_str());
    return 1;
  }

  if (flags_.isSet("log-level"))
    Logger::get()->setMinimumLogLevel(make_loglevel(flags_.getString("log-level")));

  if (flags_.getBool("verbose"))
    Logger::get()->setMinimumLogLevel(make_loglevel("info"));

  if (flags_.getBool("help")) {
    std::cerr
      << "xurl: Xzero HTTP Client " PACKAGE_VERSION
          << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
      << "Copyright (c) 2009-2017 by Christian Parpart <christian@parpart.family>" << std::endl
      << std::endl
      << "Usage: xurl [options ...]" << std::endl
      << std::endl
      << "Options:" << std::endl
      << flags_.helpText() << std::endl;
    return 0;
  }

  if (flags_.parameters().empty()) {
    logError("xurl", "No URL given.");
    return 1;
  }

  if (flags_.parameters().size() != 1) {
    logError("xurl", "Too many URLs given.");
    return 1;
  }

  Uri uri = makeUri(flags_.parameters()[0]);
  query(uri);

  return 0;
}

Uri XUrl::makeUri(const std::string& url) {
  Uri uri(url);

  if (uri.path() == "")
    uri.setPath("/");

  return uri;
}

IPAddress XUrl::getIPAddress(const std::string& host) {
  std::vector<IPAddress> ipaddresses = dns_.ipv4(host);
  if (ipaddresses.empty())
    RAISE(RuntimeError, "Could not resolve %s.", host.c_str());

  return ipaddresses.front();
}

int XUrl::getPort(const Uri& uri) {
  if (uri.port())
    return uri.port();

  return ServicePortMapping().tcp(uri.scheme());
}

void XUrl::query(const Uri& uri) {
  IPAddress ipaddr = getIPAddress(uri.host());
  int port = getPort(uri);
  InetAddress inetAddr(ipaddr, port);
  Duration keepAlive = 8_seconds;

  logDebug("xurl", "inet addr: $0, uri: $1", inetAddr, uri.toString());

  std::string method = flags_.getString("method");

  if (flags_.getBool("head")) {
    method = "HEAD";
  }

  HugeBuffer body;
  if (!flags_.getString("upload-file").empty()) {
    method = "PUT";
    body = FileUtil::read(flags_.getString("upload-file"));
  }

  requestHeaders_.overwrite("Host", uri.hostAndPort());

  HttpRequest req(HttpVersion::VERSION_1_1,
                  method,
                  uri.pathAndQuery(),
                  requestHeaders_,
                  uri.scheme() == "https",
                  std::move(body));
  req.setScheme(uri.scheme());

  VERBOSE("> $0 $1 HTTP/$2", req.unparsedMethod(),
                             req.unparsedUri(),
                             req.version());

  for (const HeaderField& field: req.headers())
    if (field.name()[0] != ':')
      VERBOSE("> $0: $1", field.name(), field.value());

  VERBOSE(">");

  HttpClient httpClient(&scheduler_, inetAddr,
                        connectTimeout_, readTimeout_, writeTimeout_,
                        keepAlive);

  Future<HttpClient::Response> f = httpClient.send(req);

  f.onSuccess([](HttpClient::Response& response) {
    VERBOSE("< HTTP/$0 $1 $2", response.version(),
                               (int) response.status(),
                               response.reason());

    for (const HeaderField& field: response.headers())
      VERBOSE("< $0: $1", field.name(), field.value());

    VERBOSE("<");

    const BufferRef& content = response.content().getBuffer();
    write(STDOUT_FILENO, content.data(), content.size());
  });

  f.onFailure([](std::error_code ec) {
    logError("xurl", "connect() failed. $0", ec.message());
  });

  scheduler_.runLoop();
}

int main(int argc, const char* argv[]) {
  XUrl app;
  return app.run(argc, argv);
}
<commit_msg>[xurl] small refactors<commit_after>// This file is part of the "x0" project, http://github.com/christianparpart/x0>
//   (c) 2009-2017 Christian Parpart <christian@parpart.family>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/client/HttpClient.h>
#include <xzero/http/HttpRequest.h>
#include <xzero/http/HeaderFieldList.h>
#include <xzero/net/TcpEndPoint.h>
#include <xzero/executor/PosixScheduler.h>
#include <xzero/net/DnsClient.h>
#include <xzero/io/FileUtil.h>
#include <xzero/Application.h>
#include <xzero/RuntimeError.h>
#include <xzero/Uri.h>
#include <xzero/Flags.h>
#include <xzero/logging.h>
#include <unordered_map>
#include "sysconfig.h"
#include <iostream>
#include <unistd.h>

// #define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

#define VERBOSE(msg...) logInfo("xurl", msg)
#define DEBUG(msg...) logDebug("xurl", msg)
#define TRACE(msg...) logTrace("xurl", msg)

using namespace xzero;
using namespace xzero::http;
using namespace xzero::http::client;

using xzero::http::HttpRequestInfo;
using xzero::http::HttpVersion;
using xzero::http::HeaderField;

class ServicePortMapping { // {{{
 public:
  ServicePortMapping();

  void loadFile(const std::string& path = "/etc/services");
  void loadContent(const std::string& content);

  int tcp(const std::string& name);
  int udp(const std::string& name);

 private:
  std::unordered_map<std::string, int> tcp_;
  std::unordered_map<std::string, int> udp_;
};

ServicePortMapping::ServicePortMapping()
    : tcp_() {
  tcp_["http"] = 80;
  tcp_["https"] = 443;
}

int ServicePortMapping::tcp(const std::string& name) {
  auto i = tcp_.find(name);
  if (i != tcp_.end())
    return i->second;

  RAISE(RuntimeError, "Unknown service '%s'", name.c_str());
}
// }}}

class XurlLogTarget : public ::xzero::LogTarget { // {{{
 public:
  void log(LogLevel level,
           const std::string& component,
           const std::string& message) override;
};

void XurlLogTarget::log(LogLevel level,
                            const std::string& component,
                            const std::string& message) {
  if (component == "xurl") {
    printf("%s\n", message.c_str());
  } else {
    printf("[%s] %s\n", component.c_str(), message.c_str());
  }
}
// }}}

class XUrl {
 public:
  XUrl();

  int run(int argc, const char* argv[]);

 private:
  void addRequestHeader(const std::string& value);
  Uri makeUri(const std::string& url);
  IPAddress getIPAddress(const std::string& host);
  int getPort(const Uri& uri);
  void query(const Uri& uri);

 private:
  PosixScheduler scheduler_;
  Flags flags_;
  DnsClient dns_;
  Duration connectTimeout_;
  Duration readTimeout_;
  Duration writeTimeout_;
  XurlLogTarget logTarget_;
  http::HeaderFieldList requestHeaders_;
};

XUrl::XUrl()
    : scheduler_(CatchAndLogExceptionHandler("xurl")),
      flags_(),
      dns_(),
      connectTimeout_(4_seconds),
      readTimeout_(60_seconds),
      writeTimeout_(10_seconds),
      logTarget_(),
      requestHeaders_()
{
  Application::init();
  //Application::logToStderr(LogLevel::Info);
  Logger::get()->addTarget(&logTarget_);

  requestHeaders_.push_back("User-Agent", "xurl/" PACKAGE_VERSION);

  flags_.defineBool("help", 'h', "Prints this help.");
  flags_.defineBool("head", 'I', "Performs a HEAD request.");
  flags_.defineBool("verbose", 'v', "Be verbose (log level: info)");
  flags_.defineString("output", 'o', "PATH", "Write response body to given file.");
  flags_.defineString("log-level", 'L', "STRING", "Log level.", "warning");
  flags_.defineString("method", 'X', "METHOD", "HTTP method", "GET");
  flags_.defineNumber("connect-timeout", 0, "MS", "TCP connect() timeout", 10_seconds .milliseconds());
  flags_.defineString("upload-file", 'T', "PATH", "Uploads given file.", "");
  flags_.defineString("header", 'H', "HEADER", "Adds a custom request header",
      None(),
      std::bind(&XUrl::addRequestHeader, this, std::placeholders::_1));
  flags_.defineBool("ipv4", '4', "Favor IPv4 for TCP/IP communication.");
  flags_.defineBool("ipv6", '6', "Favor IPv6 for TCP/IP communication.");
  flags_.enableParameters("URL", "URL to query");
}

void XUrl::addRequestHeader(const std::string& field) {
  requestHeaders_.push_back(HeaderField::parse(field));
}

int XUrl::run(int argc, const char* argv[]) {
  std::error_code ec = flags_.parse(argc, argv);
  if (ec) {
    fprintf(stderr, "Failed to parse flags. %s\n", ec.message().c_str());
    return 1;
  }

  if (flags_.isSet("log-level"))
    Logger::get()->setMinimumLogLevel(make_loglevel(flags_.getString("log-level")));

  if (flags_.getBool("verbose"))
    Logger::get()->setMinimumLogLevel(make_loglevel("info"));

  if (flags_.getBool("help")) {
    std::cerr
      << "xurl: Xzero HTTP Client " PACKAGE_VERSION
          << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
      << "Copyright (c) 2009-2017 by Christian Parpart <christian@parpart.family>" << std::endl
      << std::endl
      << "Usage: xurl [options ...]" << std::endl
      << std::endl
      << "Options:" << std::endl
      << flags_.helpText() << std::endl;
    return 0;
  }

  if (flags_.parameters().empty()) {
    logError("xurl", "No URL given.");
    return 1;
  }

  if (flags_.parameters().size() != 1) {
    logError("xurl", "Too many URLs given.");
    return 1;
  }

  query(makeUri(flags_.parameters()[0]));

  return 0;
}

Uri XUrl::makeUri(const std::string& url) {
  Uri uri(url);

  if (uri.path() == "")
    uri.setPath("/");

  return uri;
}

IPAddress XUrl::getIPAddress(const std::string& host) {
  std::vector<IPAddress> ipaddresses = dns_.ipv4(host);
  if (ipaddresses.empty())
    RAISE(RuntimeError, "Could not resolve %s.", host.c_str());

  return ipaddresses.front();
}

int XUrl::getPort(const Uri& uri) {
  if (uri.port())
    return uri.port();

  return ServicePortMapping().tcp(uri.scheme());
}

void XUrl::query(const Uri& uri) {
  IPAddress ipaddr = getIPAddress(uri.host());
  int port = getPort(uri);
  InetAddress inetAddr(ipaddr, port);
  Duration keepAlive = 8_seconds;

  std::string method = flags_.getString("method");

  if (flags_.getBool("head")) {
    method = "HEAD";
  }

  HugeBuffer body;
  if (!flags_.getString("upload-file").empty()) {
    method = "PUT";
    body = FileUtil::read(flags_.getString("upload-file"));
  }

  requestHeaders_.overwrite("Host", uri.hostAndPort());

  HttpRequest req(HttpVersion::VERSION_1_1,
                  method,
                  uri.pathAndQuery(),
                  requestHeaders_,
                  uri.scheme() == "https",
                  std::move(body));
  req.setScheme(uri.scheme());

  VERBOSE("* connecting to $0", inetAddr);

  VERBOSE("> $0 $1 HTTP/$2", req.unparsedMethod(),
                             req.unparsedUri(),
                             req.version());

  for (const HeaderField& field: req.headers())
    if (field.name()[0] != ':')
      VERBOSE("> $0: $1", field.name(), field.value());

  VERBOSE(">");

  HttpClient httpClient(&scheduler_, inetAddr,
                        connectTimeout_, readTimeout_, writeTimeout_,
                        keepAlive);

  Future<HttpClient::Response> f = httpClient.send(req);

  f.onSuccess([](HttpClient::Response& response) {
    VERBOSE("< HTTP/$0 $1 $2", response.version(),
                               (int) response.status(),
                               response.reason());

    for (const HeaderField& field: response.headers())
      VERBOSE("< $0: $1", field.name(), field.value());

    VERBOSE("<");

    const BufferRef& content = response.content().getBuffer();
    write(STDOUT_FILENO, content.data(), content.size());
  });

  f.onFailure([](std::error_code ec) {
    logError("xurl", "connect() failed. $0", ec.message());
  });

  scheduler_.runLoop();
}

int main(int argc, const char* argv[]) {
  XUrl app;
  return app.run(argc, argv);
}
<|endoftext|>


<commit_before><commit_msg>A triple drift<commit_after><|endoftext|>


<commit_before>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

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

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

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

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "statement.hpp"

#include <cassert>
#include <memory>

#include <compiler/casting.hpp>
#include <compiler/parser.hpp>
#include <compiler/tokens/statements/compound_statement.hpp>
#include <compiler/tokens/token.hpp>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// Statement
//------------------------------------------------------------------------------

Statement::Statement( TokenTy sub_class_id )
    :Token( sub_class_id )
{
}

Statement::~Statement()
{
}

void Statement::Print( int depth ) const
{
}

bool Statement::Parse( Parser& parser, Statement_up& token )
{
    // Try and parse any kind of statement
    std::unique_ptr<Token> t;
    if( !parser.ExpectAnyOf< CompoundStatement >( t ) )
        return false;

    assert( isa<Statement>( t ) && "Statement parsed a non-statement" );
    token.reset( static_cast<Statement*>( t.release() ) );
    return true;
}

bool Statement::classof( const Token* d )
{
    return d->GetSubClassID() >= TokenTy::Statement_Start &&
           d->GetSubClassID() <= TokenTy::Statement_End;
}

bool Statement::classof( const Statement* d )
{
    // A Statement is always a Statement
    return true;
}

} // namespace Compiler
} // namespace JoeLang
<commit_msg>[+] Parsing Return statements<commit_after>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

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

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

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

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "statement.hpp"

#include <cassert>
#include <memory>

#include <compiler/casting.hpp>
#include <compiler/parser.hpp>
#include <compiler/tokens/statements/compound_statement.hpp>
#include <compiler/tokens/statements/return_statement.hpp>
#include <compiler/tokens/token.hpp>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// Statement
//------------------------------------------------------------------------------

Statement::Statement( TokenTy sub_class_id )
    :Token( sub_class_id )
{
}

Statement::~Statement()
{
}

void Statement::Print( int depth ) const
{
}

bool Statement::Parse( Parser& parser, Statement_up& token )
{
    // Try and parse any kind of statement
    std::unique_ptr<Token> t;
    if( !parser.ExpectAnyOf< CompoundStatement,
                             ReturnStatement >( t ) )
        return false;

    assert( isa<Statement>( t ) && "Statement parsed a non-statement" );
    token.reset( static_cast<Statement*>( t.release() ) );
    return true;
}

bool Statement::classof( const Token* d )
{
    return d->GetSubClassID() >= TokenTy::Statement_Start &&
           d->GetSubClassID() <= TokenTy::Statement_End;
}

bool Statement::classof( const Statement* d )
{
    // A Statement is always a Statement
    return true;
}

} // namespace Compiler
} // namespace JoeLang
<|endoftext|>


<commit_before><commit_msg>Kart shouldn't fly through colliders now<commit_after><|endoftext|>