<commit_before>// Copyright (c) 2013, Maria Teresa Lazaro Grañon
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice, this
//   list of conditions and the following disclaimer in the documentation and/or
//   other materials provided with the distribution.
//
//   Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ros_handler.h"

RosHandler::RosHandler (int idRobot, int nRobots, int typeExperiment){

  _idRobot = idRobot;
  _nRobots = nRobots;
  _typeExperiment = typeExperiment;

  _gtPoses = new SE2[nRobots];
  _subgt = new ros::Subscriber[nRobots];
  _timeLastPing = new ros::Time[nRobots];

  _odomTopic = "odom";
  _scanTopic = "base_scan";

  _useOdom = false;
  _useLaser = false;
}

void RosHandler::pingCallback(const cg_mrslam::Ping::ConstPtr& msg){
  int robot = msg->robotFrom;
  std::cerr << "Received Ping from robot " << robot << std::endl;

  _timeLastPing[robot] = ros::Time::now();
}

void RosHandler::groundTruthCallback(const nav_msgs::Odometry::ConstPtr& msg, SE2 *gtpose)
{
  gtpose->setTranslation(Eigen::Vector2d(-msg->pose.pose.position.y,  msg->pose.pose.position.x));
  gtpose->setRotation(tf::getYaw(msg->pose.pose.orientation)+M_PI_2);
}

void RosHandler::odomCallback(const nav_msgs::Odometry::ConstPtr& msg)
{
  _odom = *msg;
}

void RosHandler::scanCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
  _laserscan = *msg;
}

SE2 RosHandler::getOdom(){
  SE2 odomSE2;
  odomSE2.setTranslation(Eigen::Vector2d(_odom.pose.pose.position.x, _odom.pose.pose.position.y));
  odomSE2.setRotation(tf::getYaw(_odom.pose.pose.orientation));
  return odomSE2;
}

RobotLaser* RosHandler::getLaser(){

  //LaserParameters lparams(0, _laserscan.ranges.size(), _laserscan.angle_min,  _laserscan.angle_increment, _laserscan.range_max, 0.1, 0);
  LaserParameters lparams(0, _laserscan.ranges.size(), _laserscan.angle_min,  _laserscan.angle_increment, 8.0, 0.1, 0);
  SE2 trobotlaser(0, 0, 0); //TODO: get transformation from tf
  lparams.laserPose = trobotlaser;

  RobotLaser* rlaser = new RobotLaser;
  rlaser->setLaserParams(lparams);
  rlaser->setOdomPose(getOdom());
  std::vector<double> ranges(_laserscan.ranges.size());
  for (size_t i =0; i < _laserscan.ranges.size(); i++){
    ranges[i] = _laserscan.ranges[i];
  }
  rlaser->setRanges(ranges);
  rlaser->setTimestamp(_laserscan.header.stamp.sec + _laserscan.header.stamp.nsec * pow(10, -9));
  rlaser->setLoggerTimestamp(rlaser->timestamp());
  rlaser->setHostname("hostname");

  return rlaser;
}

void RosHandler::init(){

  if (_useOdom){
    //Init Odom
    nav_msgs::Odometry::ConstPtr odommsg = ros::topic::waitForMessage<nav_msgs::Odometry>(_odomTopic);
    _odom = *odommsg;
  }

  if (_useLaser){
  //Init scan
    sensor_msgs::LaserScan::ConstPtr lasermsg = ros::topic::waitForMessage<sensor_msgs::LaserScan>(_scanTopic);
    _laserscan = *lasermsg;
  }

  if (_typeExperiment == SIM_EXPERIMENT){
    //Init ground-truth
    for (int r = 0; r < _nRobots; r++){
      std::stringstream nametopic;
      nametopic << "/robot_" << r << "/base_pose_ground_truth";
      nav_msgs::Odometry::ConstPtr gtmsg = ros::topic::waitForMessage<nav_msgs::Odometry>(nametopic.str());
      _gtPoses[r] = SE2(-gtmsg->pose.pose.position.y, gtmsg->pose.pose.position.x, tf::getYaw(gtmsg->pose.pose.orientation)+M_PI_2);
    }
  }

}

void RosHandler::run(){
  if (_useOdom) //Subscribe Odom
    _subOdom = _nh.subscribe<nav_msgs::Odometry>(_odomTopic, 1000, &RosHandler::odomCallback, this);

  if (_useLaser) //Subscribe Laser
    _subScan = _nh.subscribe<sensor_msgs::LaserScan>(_scanTopic, 1000,  &RosHandler::scanCallback, this);

  if (_typeExperiment == BAG_EXPERIMENT){
    //subscribe pings
    _subPing = _nh.subscribe<cg_mrslam::Ping>("ping_msgs", 1000, &RosHandler::pingCallback, this);
  } else if (_typeExperiment == SIM_EXPERIMENT){
    //subscribe ground truth
    for (int r = 0; r < _nRobots; r++){
      std::stringstream nametopic;
      nametopic << "/robot_" << r << "/base_pose_ground_truth";
      _subgt[r] = _nh.subscribe<nav_msgs::Odometry>(nametopic.str(), 1000, boost::bind(&RosHandler::groundTruthCallback, this, _1, &_gtPoses[r]));
    }
  } else if (_typeExperiment == REAL_EXPERIMENT){
    //publish ping, sent and received messages
    _pubRecv = _nh.advertise<cg_mrslam::SLAM>("recv_msgs", 1);
    _pubSent = _nh.advertise<cg_mrslam::SLAM>("sent_msgs", 1);
    _pubPing = _nh.advertise<cg_mrslam::Ping>("ping_msgs", 1);
  }
}

void RosHandler::publishPing(int idRobotFrom){
  cg_mrslam::Ping rosmsg;

  rosmsg.header.stamp = ros::Time::now();

  rosmsg.robotFrom = idRobotFrom;
  rosmsg.robotTo   = _idRobot;

  _pubPing.publish(rosmsg);
}

void RosHandler::createComboMsg(ComboMessage* cmsg, cg_mrslam::SLAM& dslamMsg){
  dslamMsg.header.stamp = ros::Time::now();

  dslamMsg.robotId = cmsg->robotId();
  dslamMsg.type = cmsg->type();

  cg_mrslam::RobotLaser laser;
  laser.nodeId = cmsg->nodeId;
  laser.readings = cmsg->readings;
  laser.minAngle = cmsg->minangle;
  laser.angleInc = cmsg->angleincrement;
  laser.maxRange = cmsg->maxrange;
  laser.accuracy = cmsg->accuracy;
  dslamMsg.laser = laser;

  dslamMsg.vertices.resize(cmsg->vertexVector.size());
  for (size_t i = 0; i < cmsg->vertexVector.size(); i++){
    dslamMsg.vertices[i].id = cmsg->vertexVector[i].id;
    dslamMsg.vertices[i].estimate[0] = cmsg->vertexVector[i].estimate[0];
    dslamMsg.vertices[i].estimate[1] = cmsg->vertexVector[i].estimate[1];
    dslamMsg.vertices[i].estimate[2] = cmsg->vertexVector[i].estimate[2];
  }
}

void RosHandler::createCondensedGraphMsg(CondensedGraphMessage* gmsg,  cg_mrslam::SLAM& dslamMsg){
  dslamMsg.header.stamp = ros::Time::now();

  dslamMsg.robotId = gmsg->robotId();
  dslamMsg.type = gmsg->type();

  dslamMsg.edges.resize(gmsg->edgeVector.size());
  for (size_t i = 0; i < gmsg->edgeVector.size(); i++){
    dslamMsg.edges[i].idFrom = gmsg->edgeVector[i].idfrom;
    dslamMsg.edges[i].idTo = gmsg->edgeVector[i].idto;
    dslamMsg.edges[i].estimate[0] = gmsg->edgeVector[i].estimate[0];
    dslamMsg.edges[i].estimate[1] = gmsg->edgeVector[i].estimate[1];
    dslamMsg.edges[i].estimate[2] = gmsg->edgeVector[i].estimate[2];
    dslamMsg.edges[i].information[0] = gmsg->edgeVector[i].information[0];
    dslamMsg.edges[i].information[1] = gmsg->edgeVector[i].information[1];
    dslamMsg.edges[i].information[2] = gmsg->edgeVector[i].information[2];
    dslamMsg.edges[i].information[3] = gmsg->edgeVector[i].information[3];
    dslamMsg.edges[i].information[4] = gmsg->edgeVector[i].information[4];
    dslamMsg.edges[i].information[5] = gmsg->edgeVector[i].information[5];
  }

  dslamMsg.closures = gmsg->closures;
}

void RosHandler::createDSlamMsg(RobotMessage* msg, cg_mrslam::SLAM& dslamMsg){
  ComboMessage* cmsg = dynamic_cast<ComboMessage*>(msg);
  if (cmsg)
    createComboMsg(cmsg, dslamMsg);
  else{
    CondensedGraphMessage* gmsg = dynamic_cast<CondensedGraphMessage*>(msg);
    if (gmsg)
      createCondensedGraphMsg(gmsg, dslamMsg);
  }
}

void RosHandler::publishSentMsg(RobotMessage* msg){
  cg_mrslam::SLAM dslamMsg;

  createDSlamMsg(msg, dslamMsg);
  _pubSent.publish(dslamMsg);
}

void RosHandler::publishReceivedMsg(RobotMessage* msg){
  cg_mrslam::SLAM dslamMsg;

  createDSlamMsg(msg, dslamMsg);
  _pubRecv.publish(dslamMsg);
}
<commit_msg>ros_handler manages correctly the scan max range if lower than 8. Thanks Leonardo Fermin.<commit_after>// Copyright (c) 2013, Maria Teresa Lazaro Grañon
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice, this
//   list of conditions and the following disclaimer in the documentation and/or
//   other materials provided with the distribution.
//
//   Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ros_handler.h"

RosHandler::RosHandler (int idRobot, int nRobots, int typeExperiment){

  _idRobot = idRobot;
  _nRobots = nRobots;
  _typeExperiment = typeExperiment;

  _gtPoses = new SE2[nRobots];
  _subgt = new ros::Subscriber[nRobots];
  _timeLastPing = new ros::Time[nRobots];

  _odomTopic = "odom";
  _scanTopic = "base_scan";

  _useOdom = false;
  _useLaser = false;
}

void RosHandler::pingCallback(const cg_mrslam::Ping::ConstPtr& msg){
  int robot = msg->robotFrom;
  std::cerr << "Received Ping from robot " << robot << std::endl;

  _timeLastPing[robot] = ros::Time::now();
}

void RosHandler::groundTruthCallback(const nav_msgs::Odometry::ConstPtr& msg, SE2 *gtpose)
{
  gtpose->setTranslation(Eigen::Vector2d(-msg->pose.pose.position.y,  msg->pose.pose.position.x));
  gtpose->setRotation(tf::getYaw(msg->pose.pose.orientation)+M_PI_2);
}

void RosHandler::odomCallback(const nav_msgs::Odometry::ConstPtr& msg)
{
  _odom = *msg;
}

void RosHandler::scanCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
  _laserscan = *msg;
}

SE2 RosHandler::getOdom(){
  SE2 odomSE2;
  odomSE2.setTranslation(Eigen::Vector2d(_odom.pose.pose.position.x, _odom.pose.pose.position.y));
  odomSE2.setRotation(tf::getYaw(_odom.pose.pose.orientation));
  return odomSE2;
}

RobotLaser* RosHandler::getLaser(){

  //LaserParameters lparams(0, _laserscan.ranges.size(), _laserscan.angle_min,  _laserscan.angle_increment, _laserscan.range_max, 0.1, 0);
  LaserParameters lparams(0, _laserscan.ranges.size(), _laserscan.angle_min,  _laserscan.angle_increment, min(8.0f , _laserscan.range_max), 0.1, 0);
  SE2 trobotlaser(0, 0, 0); //TODO: get transformation from tf
  lparams.laserPose = trobotlaser;

  RobotLaser* rlaser = new RobotLaser;
  rlaser->setLaserParams(lparams);
  rlaser->setOdomPose(getOdom());
  std::vector<double> ranges(_laserscan.ranges.size());
  for (size_t i =0; i < _laserscan.ranges.size(); i++){
    ranges[i] = _laserscan.ranges[i];
  }
  rlaser->setRanges(ranges);
  rlaser->setTimestamp(_laserscan.header.stamp.sec + _laserscan.header.stamp.nsec * pow(10, -9));
  rlaser->setLoggerTimestamp(rlaser->timestamp());
  rlaser->setHostname("hostname");

  return rlaser;
}

void RosHandler::init(){

  if (_useOdom){
    //Init Odom
    nav_msgs::Odometry::ConstPtr odommsg = ros::topic::waitForMessage<nav_msgs::Odometry>(_odomTopic);
    _odom = *odommsg;
  }

  if (_useLaser){
  //Init scan
    sensor_msgs::LaserScan::ConstPtr lasermsg = ros::topic::waitForMessage<sensor_msgs::LaserScan>(_scanTopic);
    _laserscan = *lasermsg;
  }

  if (_typeExperiment == SIM_EXPERIMENT){
    //Init ground-truth
    for (int r = 0; r < _nRobots; r++){
      std::stringstream nametopic;
      nametopic << "/robot_" << r << "/base_pose_ground_truth";
      nav_msgs::Odometry::ConstPtr gtmsg = ros::topic::waitForMessage<nav_msgs::Odometry>(nametopic.str());
      _gtPoses[r] = SE2(-gtmsg->pose.pose.position.y, gtmsg->pose.pose.position.x, tf::getYaw(gtmsg->pose.pose.orientation)+M_PI_2);
    }
  }

}

void RosHandler::run(){
  if (_useOdom) //Subscribe Odom
    _subOdom = _nh.subscribe<nav_msgs::Odometry>(_odomTopic, 1000, &RosHandler::odomCallback, this);

  if (_useLaser) //Subscribe Laser
    _subScan = _nh.subscribe<sensor_msgs::LaserScan>(_scanTopic, 1000,  &RosHandler::scanCallback, this);

  if (_typeExperiment == BAG_EXPERIMENT){
    //subscribe pings
    _subPing = _nh.subscribe<cg_mrslam::Ping>("ping_msgs", 1000, &RosHandler::pingCallback, this);
  } else if (_typeExperiment == SIM_EXPERIMENT){
    //subscribe ground truth
    for (int r = 0; r < _nRobots; r++){
      std::stringstream nametopic;
      nametopic << "/robot_" << r << "/base_pose_ground_truth";
      _subgt[r] = _nh.subscribe<nav_msgs::Odometry>(nametopic.str(), 1000, boost::bind(&RosHandler::groundTruthCallback, this, _1, &_gtPoses[r]));
    }
  } else if (_typeExperiment == REAL_EXPERIMENT){
    //publish ping, sent and received messages
    _pubRecv = _nh.advertise<cg_mrslam::SLAM>("recv_msgs", 1);
    _pubSent = _nh.advertise<cg_mrslam::SLAM>("sent_msgs", 1);
    _pubPing = _nh.advertise<cg_mrslam::Ping>("ping_msgs", 1);
  }
}

void RosHandler::publishPing(int idRobotFrom){
  cg_mrslam::Ping rosmsg;

  rosmsg.header.stamp = ros::Time::now();

  rosmsg.robotFrom = idRobotFrom;
  rosmsg.robotTo   = _idRobot;

  _pubPing.publish(rosmsg);
}

void RosHandler::createComboMsg(ComboMessage* cmsg, cg_mrslam::SLAM& dslamMsg){
  dslamMsg.header.stamp = ros::Time::now();

  dslamMsg.robotId = cmsg->robotId();
  dslamMsg.type = cmsg->type();

  cg_mrslam::RobotLaser laser;
  laser.nodeId = cmsg->nodeId;
  laser.readings = cmsg->readings;
  laser.minAngle = cmsg->minangle;
  laser.angleInc = cmsg->angleincrement;
  laser.maxRange = cmsg->maxrange;
  laser.accuracy = cmsg->accuracy;
  dslamMsg.laser = laser;

  dslamMsg.vertices.resize(cmsg->vertexVector.size());
  for (size_t i = 0; i < cmsg->vertexVector.size(); i++){
    dslamMsg.vertices[i].id = cmsg->vertexVector[i].id;
    dslamMsg.vertices[i].estimate[0] = cmsg->vertexVector[i].estimate[0];
    dslamMsg.vertices[i].estimate[1] = cmsg->vertexVector[i].estimate[1];
    dslamMsg.vertices[i].estimate[2] = cmsg->vertexVector[i].estimate[2];
  }
}

void RosHandler::createCondensedGraphMsg(CondensedGraphMessage* gmsg,  cg_mrslam::SLAM& dslamMsg){
  dslamMsg.header.stamp = ros::Time::now();

  dslamMsg.robotId = gmsg->robotId();
  dslamMsg.type = gmsg->type();

  dslamMsg.edges.resize(gmsg->edgeVector.size());
  for (size_t i = 0; i < gmsg->edgeVector.size(); i++){
    dslamMsg.edges[i].idFrom = gmsg->edgeVector[i].idfrom;
    dslamMsg.edges[i].idTo = gmsg->edgeVector[i].idto;
    dslamMsg.edges[i].estimate[0] = gmsg->edgeVector[i].estimate[0];
    dslamMsg.edges[i].estimate[1] = gmsg->edgeVector[i].estimate[1];
    dslamMsg.edges[i].estimate[2] = gmsg->edgeVector[i].estimate[2];
    dslamMsg.edges[i].information[0] = gmsg->edgeVector[i].information[0];
    dslamMsg.edges[i].information[1] = gmsg->edgeVector[i].information[1];
    dslamMsg.edges[i].information[2] = gmsg->edgeVector[i].information[2];
    dslamMsg.edges[i].information[3] = gmsg->edgeVector[i].information[3];
    dslamMsg.edges[i].information[4] = gmsg->edgeVector[i].information[4];
    dslamMsg.edges[i].information[5] = gmsg->edgeVector[i].information[5];
  }

  dslamMsg.closures = gmsg->closures;
}

void RosHandler::createDSlamMsg(RobotMessage* msg, cg_mrslam::SLAM& dslamMsg){
  ComboMessage* cmsg = dynamic_cast<ComboMessage*>(msg);
  if (cmsg)
    createComboMsg(cmsg, dslamMsg);
  else{
    CondensedGraphMessage* gmsg = dynamic_cast<CondensedGraphMessage*>(msg);
    if (gmsg)
      createCondensedGraphMsg(gmsg, dslamMsg);
  }
}

void RosHandler::publishSentMsg(RobotMessage* msg){
  cg_mrslam::SLAM dslamMsg;

  createDSlamMsg(msg, dslamMsg);
  _pubSent.publish(dslamMsg);
}

void RosHandler::publishReceivedMsg(RobotMessage* msg){
  cg_mrslam::SLAM dslamMsg;

  createDSlamMsg(msg, dslamMsg);
  _pubRecv.publish(dslamMsg);
}
<|endoftext|>


<commit_before>/*
 * Functions deal with the regex banning.
 *
 * Copyright (c) eQualit.ie 2013 under GNU AGPL v3.0 or later
 *
 *  Vmon: June 2013, Initial version
 */
#include <string>
#include <list>
#include <vector>
#include <stdio.h>
#include <sys/time.h>
#include <zmq.hpp>
#include <iostream>
#include <re2/re2.h> //google re2

#include <ts/ts.h>

using namespace std;

#include "regex_manager.h"
#include "ip_database.h"

/**
  reads all the regular expressions from the database.
  and compile them
 */
void
RegexManager::load_config(libconfig::Setting& cfg)
{
   try
   {
     const libconfig::Setting &banned_regexes_list = cfg["banned_regexes"];

     unsigned int count = banned_regexes_list.getLength();

     //now we compile all of them and store them for later use
     for(unsigned int i = 0; i < count; i++) {
       string cur_rule = (const char*) banned_regexes_list[i]["rule"];
       TSDebug(BANJAX_PLUGIN_NAME, "initiating rule %s", cur_rule.c_str());

       unsigned int observation_interval = banned_regexes_list[i]["interval"];
       unsigned int threshold  = banned_regexes_list[i]["hits_per_interval"];

       rated_banning_regexes.push_back(new RatedRegex(cur_rule, new RE2((const char*)(banned_regexes_list[i]["regex"])), observation_interval * 1000, threshold /(double)(observation_interval* 1000)));

     }

    }
   catch(const libconfig::SettingNotFoundException &nfex)
     {
       // Ignore.
     }

}

/**
  applies all regex to an ATS record

  @param ats_record: the full request record including time url agent etc
  @return: 1 match 0 not match < 0 error.
*/
pair<RegexManager::RegexResult,RatedRegex*>
RegexManager::parse_request(string ip, string ats_record, string method)
{
  for(list<RatedRegex*>::iterator it=rated_banning_regexes.begin(); it != rated_banning_regexes.end(); it++) {
      int METHOD_TYPE;
      if (method.find("GET") != std::string::npos) {
        METHOD_TYPE = 0;
      } else {
        METHOD_TYPE = 1;
      }
      if (RE2::FullMatch(ats_record, *((*it)->re2_regex))) {

        TSDebug(BANJAX_PLUGIN_NAME, "requests matched %s", (char*)((*it)->re2_regex->pattern()).c_str());
        //if it is a simple regex i.e. with rate 0 we bans immidiately without
        //wasting time and mem
        if ((*it)->rate == 0) {
            TSDebug(BANJAX_PLUGIN_NAME, "simple regex, ban immediately");
            return make_pair(REGEX_MATCHED, (*it));
        }
	//select appropriate rate, dependent on whether GET or POST request

        /* we need to check the rate condition here */
        //getting current time in msec
        timeval cur_time; gettimeofday(&cur_time, NULL);
        long cur_time_msec = cur_time.tv_sec * 1000 + cur_time.tv_usec / 1000.0;

        /* first we check if we already have a state for this ip */
        RegexBannerStateUnion cur_ip_state;
        cur_ip_state.state_allocator =  ip_database->get_ip_state(ip, REGEX_BANNER_FILTER_ID);

        if (cur_ip_state.detail[METHOD_TYPE].begin_msec == 0) {//We don't have a record
          cur_ip_state.detail[METHOD_TYPE].begin_msec = cur_time_msec;
          cur_ip_state.detail[METHOD_TYPE].rate = 0;
          ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);

        } else { //we have a record, update the rate and ban if necessary.
          //we move the interval by the differences of the "begin_in_ms - cur_time_msec - interval*1000"
          //if it is less than zero we don't do anything

          long time_window_movement = cur_time_msec - cur_ip_state.detail[METHOD_TYPE].begin_msec - (*it)->interval;
          if (time_window_movement > 0) { //we need to move
            cur_ip_state.detail[METHOD_TYPE].begin_msec += time_window_movement;
            cur_ip_state.detail[METHOD_TYPE].rate= cur_ip_state.detail[METHOD_TYPE].rate - (cur_ip_state.detail[METHOD_TYPE].rate * time_window_movement - 1)/(double) (*it)->interval;
            cur_ip_state.detail[METHOD_TYPE].rate =  cur_ip_state.detail[METHOD_TYPE].rate < 0 ? 0 : cur_ip_state.detail[METHOD_TYPE].rate; //just to make sure
          }
          else {
            //we are still in the same interval so just increase the hit by 1
            cur_ip_state.detail[METHOD_TYPE].rate += 1/(double) (*it)->interval;
          }
          TSDebug(BANJAX_PLUGIN_NAME, "with rate %f /msec", cur_ip_state.detail[METHOD_TYPE].rate);
          ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);
        }
        if (cur_ip_state.detail[METHOD_TYPE].rate >= (*it)->rate) {
          TSDebug(BANJAX_PLUGIN_NAME, "exceeding excessive rate %f /msec", (*it)->rate);
          //clear the record to avoid multiple reporting to swabber
          //we are not clearing the state cause it is not for sure that
          //swabber ban the ip due to possible failure of acquiring lock
          // cur_ip_state.detail.begin_msec = 0;
          // cur_ip_state.detail.rate = 0;
          // ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);
          return make_pair(REGEX_MATCHED, (*it));
        }
      }
  }

  //no match
  return make_pair(REGEX_MISSED, (RatedRegex*)NULL);

}

FilterResponse RegexManager::execute(const TransactionParts& transaction_parts)
{
  const string sep(" ");
  TransactionParts ats_record_parts = (TransactionParts) transaction_parts;

  string ats_record =  ats_record_parts[TransactionMuncher::METHOD] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::URL] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::HOST] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::UA];

  TSDebug(BANJAX_PLUGIN_NAME, "Examining %s for banned matches", ats_record.c_str());
  pair<RegexResult,RatedRegex*> result = parse_request(
						ats_record_parts[TransactionMuncher::IP],
						ats_record,
						ats_record_parts[TransactionMuncher::METHOD]
						);

  if (result.first == REGEX_MATCHED) {
    TSDebug(BANJAX_PLUGIN_NAME, "asking swabber to ban client ip: %s", ats_record_parts[TransactionMuncher::IP].c_str());

    //here instead we are calling nosmos's banning client
    string banning_reason = "matched regex rule " + result.second->rule_name;
    swabber_interface->ban(ats_record_parts[TransactionMuncher::IP], banning_reason);
    return FilterResponse(static_cast<ResponseGenerator>(&RegexManager::generate_response));

  } else if (result.first != REGEX_MISSED) {
    TSError("Regex failed with error: %d\n", result.first);
  }

  return FilterResponse(FilterResponse::GO_AHEAD_NO_COMMENT);

}

std::string RegexManager::generate_response(const TransactionParts& transaction_parts, const FilterResponse& response_info)
{
  (void)transaction_parts; (void)response_info;
  char* forbidden_response = new char[forbidden_message_length+1];
  memcpy((void*)forbidden_response, (const void*)forbidden_message.c_str(), (forbidden_message_length+1)*sizeof(char));
  return forbidden_response;
}
<commit_msg>functioning version<commit_after>/*
 * Functions deal with the regex banning.
 *
 * Copyright (c) eQualit.ie 2013 under GNU AGPL v3.0 or later
 *
 *  Vmon: June 2013, Initial version
 */
#include <string>
#include <list>
#include <vector>
#include <stdio.h>
#include <sys/time.h>
#include <zmq.hpp>
#include <iostream>
#include <re2/re2.h> //google re2

#include <ts/ts.h>

using namespace std;

#include "regex_manager.h"
#include "ip_database.h"

/**
  reads all the regular expressions from the database.
  and compile them
 */
void
RegexManager::load_config(libconfig::Setting& cfg)
{
   try
   {
     const libconfig::Setting &banned_regexes_list = cfg["banned_regexes"];

     unsigned int count = banned_regexes_list.getLength();

     //now we compile all of them and store them for later use
     for(unsigned int i = 0; i < count; i++) {
       string cur_rule = (const char*) banned_regexes_list[i]["rule"];
       TSDebug(BANJAX_PLUGIN_NAME, "initiating rule %s", cur_rule.c_str());

       unsigned int observation_interval = banned_regexes_list[i]["interval"];
       unsigned int threshold  = banned_regexes_list[i]["hits_per_interval"];

       rated_banning_regexes.push_back(new RatedRegex(cur_rule, new RE2((const char*)(banned_regexes_list[i]["regex"])), observation_interval * 1000, threshold /(double)(observation_interval* 1000)));

     }

    }
   catch(const libconfig::SettingNotFoundException &nfex)
     {
       // Ignore.
     }

}

/**
  applies all regex to an ATS record

  @param ats_record: the full request record including time url agent etc
  @return: 1 match 0 not match < 0 error.
*/
pair<RegexManager::RegexResult,RatedRegex*>
RegexManager::parse_request(string ip, string ats_record, string method)
{
  for(list<RatedRegex*>::iterator it=rated_banning_regexes.begin(); it != rated_banning_regexes.end(); it++) {
      int METHOD_TYPE;
      if (method.find("GET") != std::string::npos) {
        METHOD_TYPE = 0;
      } else {
        METHOD_TYPE = 1;
      }
      if (RE2::FullMatch(ats_record, *((*it)->re2_regex))) {

        TSDebug(BANJAX_PLUGIN_NAME, "requests matched %s", (char*)((*it)->re2_regex->pattern()).c_str());
        //if it is a simple regex i.e. with rate 0 we bans immidiately without
        //wasting time and mem
        if ((*it)->rate == 0) {
            TSDebug(BANJAX_PLUGIN_NAME, "simple regex, ban immediately");
            return make_pair(REGEX_MATCHED, (*it));
        }
	//select appropriate rate, dependent on whether GET or POST request

        /* we need to check the rate condition here */
        //getting current time in msec
        timeval cur_time; gettimeofday(&cur_time, NULL);
        long cur_time_msec = cur_time.tv_sec * 1000 + cur_time.tv_usec / 1000.0;

        /* first we check if we already have a state for this ip */
        RegexBannerStateUnion cur_ip_state;
        cur_ip_state.state_allocator =  ip_database->get_ip_state(ip, REGEX_BANNER_FILTER_ID);
        if (cur_ip_state.detail[METHOD_TYPE].begin_msec == 0) {//We don't have a record
          cur_ip_state.detail[METHOD_TYPE].begin_msec = cur_time_msec;
          cur_ip_state.detail[METHOD_TYPE].rate = 0;
          ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);

        } else { //we have a record, update the rate and ban if necessary.
          //we move the interval by the differences of the "begin_in_ms - cur_time_msec - interval*1000"
          //if it is less than zero we don't do anything

          long time_window_movement = cur_time_msec - cur_ip_state.detail[METHOD_TYPE].begin_msec - (*it)->interval;
          if (time_window_movement > 0) { //we need to move
            cur_ip_state.detail[METHOD_TYPE].begin_msec += time_window_movement;
            cur_ip_state.detail[METHOD_TYPE].rate= cur_ip_state.detail[METHOD_TYPE].rate - (cur_ip_state.detail[METHOD_TYPE].rate * time_window_movement - 1)/(double) (*it)->interval;
            cur_ip_state.detail[METHOD_TYPE].rate =  cur_ip_state.detail[METHOD_TYPE].rate < 0 ? 0 : cur_ip_state.detail[METHOD_TYPE].rate; //just to make sure
          }
          else {
            //we are still in the same interval so just increase the hit by 1
            cur_ip_state.detail[METHOD_TYPE].rate += 1/(double) (*it)->interval;
          }
          TSDebug(BANJAX_PLUGIN_NAME, "with rate %f /msec", cur_ip_state.detail[METHOD_TYPE].rate);
          ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);
        }
        if (cur_ip_state.detail[METHOD_TYPE].rate >= (*it)->rate) {
          TSDebug(BANJAX_PLUGIN_NAME, "exceeding excessive rate %f /msec", (*it)->rate);
          //clear the record to avoid multiple reporting to swabber
          //we are not clearing the state cause it is not for sure that
          //swabber ban the ip due to possible failure of acquiring lock
          // cur_ip_state.detail.begin_msec = 0;
          // cur_ip_state.detail.rate = 0;
          // ip_database->set_ip_state(ip, REGEX_BANNER_FILTER_ID, cur_ip_state.state_allocator);
          return make_pair(REGEX_MATCHED, (*it));
        }
      }
  }

  //no match
  return make_pair(REGEX_MISSED, (RatedRegex*)NULL);

}

FilterResponse RegexManager::execute(const TransactionParts& transaction_parts)
{
  const string sep(" ");
  TransactionParts ats_record_parts = (TransactionParts) transaction_parts;

  string ats_record =  ats_record_parts[TransactionMuncher::METHOD] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::URL] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::HOST] + sep;
  ats_record+= ats_record_parts[TransactionMuncher::UA];

  TSDebug(BANJAX_PLUGIN_NAME, "Examining %s for banned matches", ats_record.c_str());
  pair<RegexResult,RatedRegex*> result = parse_request(
						ats_record_parts[TransactionMuncher::IP],
						ats_record,
						ats_record_parts[TransactionMuncher::METHOD]
						);

  if (result.first == REGEX_MATCHED) {
    TSDebug(BANJAX_PLUGIN_NAME, "asking swabber to ban client ip: %s", ats_record_parts[TransactionMuncher::IP].c_str());

    //here instead we are calling nosmos's banning client
    string banning_reason = "matched regex rule " + result.second->rule_name;
    swabber_interface->ban(ats_record_parts[TransactionMuncher::IP], banning_reason);
    return FilterResponse(static_cast<ResponseGenerator>(&RegexManager::generate_response));

  } else if (result.first != REGEX_MISSED) {
    TSError("Regex failed with error: %d\n", result.first);
  }

  return FilterResponse(FilterResponse::GO_AHEAD_NO_COMMENT);

}

std::string RegexManager::generate_response(const TransactionParts& transaction_parts, const FilterResponse& response_info)
{
  (void)transaction_parts; (void)response_info;
  char* forbidden_response = new char[forbidden_message_length+1];
  memcpy((void*)forbidden_response, (const void*)forbidden_message.c_str(), (forbidden_message_length+1)*sizeof(char));
  return forbidden_response;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "rpcprotocol.h"

#include "util.h"

#include <stdint.h>

#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
#include "json/json_spirit_writer_template.h"

using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace json_spirit;

//
// HTTP protocol
//
// This ain't Apache.  We're just using HTTP header for the length field
// and to be compatible with other JSON-RPC implementations.
//

string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
{
    ostringstream s;
    s << "POST / HTTP/1.1\r\n"
      << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
      << "Host: 127.0.0.1\r\n"
      << "Content-Type: application/json\r\n"
      << "Content-Length: " << strMsg.size() << "\r\n"
      << "Connection: close\r\n"
      << "Accept: application/json\r\n";
    BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
        s << item.first << ": " << item.second << "\r\n";
    s << "\r\n" << strMsg;

    return s.str();
}

static string rfc1123Time()
{
    return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime());
}

static const char *httpStatusDescription(int nStatus)
{
    switch (nStatus) {
        case HTTP_OK: return "OK";
        case HTTP_BAD_REQUEST: return "Bad Request";
        case HTTP_FORBIDDEN: return "Forbidden";
        case HTTP_NOT_FOUND: return "Not Found";
        case HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error";
        default: return "";
    }
}

string HTTPError(int nStatus, bool keepalive, bool headersOnly)
{
    if (nStatus == HTTP_UNAUTHORIZED)
        return strprintf("HTTP/1.0 401 Authorization Required\r\n"
            "Date: %s\r\n"
            "Server: bitcoin-json-rpc/%s\r\n"
            "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
            "Content-Type: text/html\r\n"
            "Content-Length: 296\r\n"
            "\r\n"
            "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
            "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
            "\r\n"
            "\r\n"
            "<TITLE>Error</TITLE>\r\n"
            "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
            "\r\n"
            "
401 Unauthorized.
\r\n"
            "\r\n", rfc1123Time(), FormatFullVersion());

    return HTTPReply(nStatus, httpStatusDescription(nStatus), keepalive,
                     headersOnly, "text/plain");
}

string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
                 bool headersOnly, const char *contentType)
{
    return strprintf(
            "HTTP/1.1 %d %s\r\n"
            "Date: %s\r\n"
            "Connection: %s\r\n"
            "Content-Length: %u\r\n"
            "Content-Type: %s\r\n"
            "Server: bitcoin-json-rpc/%s\r\n"
            "\r\n"
            "%s",
        nStatus,
        httpStatusDescription(nStatus),
        rfc1123Time(),
        keepalive ? "keep-alive" : "close",
        (headersOnly ? 0 : strMsg.size()),
        contentType,
        FormatFullVersion(),
        (headersOnly ? "" : strMsg.c_str())
        );
}

bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
                         string& http_method, string& http_uri)
{
    string str;
    getline(stream, str);

    // HTTP request line is space-delimited
    vector<string> vWords;
    boost::split(vWords, str, boost::is_any_of(" "));
    if (vWords.size() < 2)
        return false;

    // HTTP methods permitted: GET, POST
    http_method = vWords[0];
    if (http_method != "GET" && http_method != "POST")
        return false;

    // HTTP URI must be an absolute path, relative to current host
    http_uri = vWords[1];
    if (http_uri.size() == 0 || http_uri[0] != '/')
        return false;

    // parse proto, if present
    string strProto = "";
    if (vWords.size() > 2)
        strProto = vWords[2];

    proto = 0;
    const char *ver = strstr(strProto.c_str(), "HTTP/1.");
    if (ver != NULL)
        proto = atoi(ver+7);

    return true;
}

int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
{
    string str;
    getline(stream, str);
    vector<string> vWords;
    boost::split(vWords, str, boost::is_any_of(" "));
    if (vWords.size() < 2)
        return HTTP_INTERNAL_SERVER_ERROR;
    proto = 0;
    const char *ver = strstr(str.c_str(), "HTTP/1.");
    if (ver != NULL)
        proto = atoi(ver+7);
    return atoi(vWords[1].c_str());
}

int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
{
    int nLen = 0;
    while (true)
    {
        string str;
        std::getline(stream, str);
        if (str.empty() || str == "\r")
            break;
        string::size_type nColon = str.find(":");
        if (nColon != string::npos)
        {
            string strHeader = str.substr(0, nColon);
            boost::trim(strHeader);
            boost::to_lower(strHeader);
            string strValue = str.substr(nColon+1);
            boost::trim(strValue);
            mapHeadersRet[strHeader] = strValue;
            if (strHeader == "content-length")
                nLen = atoi(strValue.c_str());
        }
    }
    return nLen;
}

int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
                    string>& mapHeadersRet, string& strMessageRet,
                    int nProto)
{
    mapHeadersRet.clear();
    strMessageRet = "";

    // Read header
    int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
    if (nLen < 0 || nLen > (int)MAX_SIZE)
        return HTTP_INTERNAL_SERVER_ERROR;

    // Read message
    if (nLen > 0)
    {
        vector<char> vch(nLen);
        stream.read(&vch[0], nLen);
        strMessageRet = string(vch.begin(), vch.end());
    }

    string sConHdr = mapHeadersRet["connection"];

    if ((sConHdr != "close") && (sConHdr != "keep-alive"))
    {
        if (nProto >= 1)
            mapHeadersRet["connection"] = "keep-alive";
        else
            mapHeadersRet["connection"] = "close";
    }

    return HTTP_OK;
}

//
// JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
// unspecified (HTTP errors and contents of 'error').
//
// 1.0 spec: http://json-rpc.org/wiki/specification
// 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html
// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
//

string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
{
    Object request;
    request.push_back(Pair("method", strMethod));
    request.push_back(Pair("params", params));
    request.push_back(Pair("id", id));
    return write_string(Value(request), false) + "\n";
}

Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
{
    Object reply;
    if (error.type() != null_type)
        reply.push_back(Pair("result", Value::null));
    else
        reply.push_back(Pair("result", result));
    reply.push_back(Pair("error", error));
    reply.push_back(Pair("id", id));
    return reply;
}

string JSONRPCReply(const Value& result, const Value& error, const Value& id)
{
    Object reply = JSONRPCReplyObj(result, error, id);
    return write_string(Value(reply), false) + "\n";
}

Object JSONRPCError(int code, const string& message)
{
    Object error;
    error.push_back(Pair("code", code));
    error.push_back(Pair("message", message));
    return error;
}
<commit_msg>rpc: Prevent easy memory exhaustion attack<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "rpcprotocol.h"

#include "util.h"

#include <stdint.h>

#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
#include "json/json_spirit_writer_template.h"

using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace json_spirit;

// Number of bytes to allocate and read at most at once in post data
const size_t POST_READ_SIZE = 256 * 1024;

//
// HTTP protocol
//
// This ain't Apache.  We're just using HTTP header for the length field
// and to be compatible with other JSON-RPC implementations.
//

string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
{
    ostringstream s;
    s << "POST / HTTP/1.1\r\n"
      << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
      << "Host: 127.0.0.1\r\n"
      << "Content-Type: application/json\r\n"
      << "Content-Length: " << strMsg.size() << "\r\n"
      << "Connection: close\r\n"
      << "Accept: application/json\r\n";
    BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
        s << item.first << ": " << item.second << "\r\n";
    s << "\r\n" << strMsg;

    return s.str();
}

static string rfc1123Time()
{
    return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime());
}

static const char *httpStatusDescription(int nStatus)
{
    switch (nStatus) {
        case HTTP_OK: return "OK";
        case HTTP_BAD_REQUEST: return "Bad Request";
        case HTTP_FORBIDDEN: return "Forbidden";
        case HTTP_NOT_FOUND: return "Not Found";
        case HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error";
        default: return "";
    }
}

string HTTPError(int nStatus, bool keepalive, bool headersOnly)
{
    if (nStatus == HTTP_UNAUTHORIZED)
        return strprintf("HTTP/1.0 401 Authorization Required\r\n"
            "Date: %s\r\n"
            "Server: bitcoin-json-rpc/%s\r\n"
            "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
            "Content-Type: text/html\r\n"
            "Content-Length: 296\r\n"
            "\r\n"
            "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
            "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
            "\r\n"
            "\r\n"
            "<TITLE>Error</TITLE>\r\n"
            "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
            "\r\n"
            "
401 Unauthorized.
\r\n"
            "\r\n", rfc1123Time(), FormatFullVersion());

    return HTTPReply(nStatus, httpStatusDescription(nStatus), keepalive,
                     headersOnly, "text/plain");
}

string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
                 bool headersOnly, const char *contentType)
{
    return strprintf(
            "HTTP/1.1 %d %s\r\n"
            "Date: %s\r\n"
            "Connection: %s\r\n"
            "Content-Length: %u\r\n"
            "Content-Type: %s\r\n"
            "Server: bitcoin-json-rpc/%s\r\n"
            "\r\n"
            "%s",
        nStatus,
        httpStatusDescription(nStatus),
        rfc1123Time(),
        keepalive ? "keep-alive" : "close",
        (headersOnly ? 0 : strMsg.size()),
        contentType,
        FormatFullVersion(),
        (headersOnly ? "" : strMsg.c_str())
        );
}

bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
                         string& http_method, string& http_uri)
{
    string str;
    getline(stream, str);

    // HTTP request line is space-delimited
    vector<string> vWords;
    boost::split(vWords, str, boost::is_any_of(" "));
    if (vWords.size() < 2)
        return false;

    // HTTP methods permitted: GET, POST
    http_method = vWords[0];
    if (http_method != "GET" && http_method != "POST")
        return false;

    // HTTP URI must be an absolute path, relative to current host
    http_uri = vWords[1];
    if (http_uri.size() == 0 || http_uri[0] != '/')
        return false;

    // parse proto, if present
    string strProto = "";
    if (vWords.size() > 2)
        strProto = vWords[2];

    proto = 0;
    const char *ver = strstr(strProto.c_str(), "HTTP/1.");
    if (ver != NULL)
        proto = atoi(ver+7);

    return true;
}

int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
{
    string str;
    getline(stream, str);
    vector<string> vWords;
    boost::split(vWords, str, boost::is_any_of(" "));
    if (vWords.size() < 2)
        return HTTP_INTERNAL_SERVER_ERROR;
    proto = 0;
    const char *ver = strstr(str.c_str(), "HTTP/1.");
    if (ver != NULL)
        proto = atoi(ver+7);
    return atoi(vWords[1].c_str());
}

int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
{
    int nLen = 0;
    while (true)
    {
        string str;
        std::getline(stream, str);
        if (str.empty() || str == "\r")
            break;
        string::size_type nColon = str.find(":");
        if (nColon != string::npos)
        {
            string strHeader = str.substr(0, nColon);
            boost::trim(strHeader);
            boost::to_lower(strHeader);
            string strValue = str.substr(nColon+1);
            boost::trim(strValue);
            mapHeadersRet[strHeader] = strValue;
            if (strHeader == "content-length")
                nLen = atoi(strValue.c_str());
        }
    }
    return nLen;
}

int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
                    string>& mapHeadersRet, string& strMessageRet,
                    int nProto)
{
    mapHeadersRet.clear();
    strMessageRet = "";

    // Read header
    int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
    if (nLen < 0 || nLen > (int)MAX_SIZE)
        return HTTP_INTERNAL_SERVER_ERROR;

    // Read message
    if (nLen > 0)
    {
        vector<char> vch;
        size_t ptr = 0;
        while (ptr < (size_t)nLen)
        {
            size_t bytes_to_read = std::min((size_t)nLen - ptr, POST_READ_SIZE);
            vch.resize(ptr + bytes_to_read);
            stream.read(&vch[ptr], bytes_to_read);
            if (!stream) // Connection lost while reading
                return HTTP_INTERNAL_SERVER_ERROR;
            ptr += bytes_to_read;
        }
        strMessageRet = string(vch.begin(), vch.end());
    }

    string sConHdr = mapHeadersRet["connection"];

    if ((sConHdr != "close") && (sConHdr != "keep-alive"))
    {
        if (nProto >= 1)
            mapHeadersRet["connection"] = "keep-alive";
        else
            mapHeadersRet["connection"] = "close";
    }

    return HTTP_OK;
}

//
// JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
// unspecified (HTTP errors and contents of 'error').
//
// 1.0 spec: http://json-rpc.org/wiki/specification
// 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html
// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
//

string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
{
    Object request;
    request.push_back(Pair("method", strMethod));
    request.push_back(Pair("params", params));
    request.push_back(Pair("id", id));
    return write_string(Value(request), false) + "\n";
}

Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
{
    Object reply;
    if (error.type() != null_type)
        reply.push_back(Pair("result", Value::null));
    else
        reply.push_back(Pair("result", result));
    reply.push_back(Pair("error", error));
    reply.push_back(Pair("id", id));
    return reply;
}

string JSONRPCReply(const Value& result, const Value& error, const Value& id)
{
    Object reply = JSONRPCReplyObj(result, error, id);
    return write_string(Value(reply), false) + "\n";
}

Object JSONRPCError(int code, const string& message)
{
    Object error;
    error.push_back(Pair("code", code));
    error.push_back(Pair("message", message));
    return error;
}
<|endoftext|>


<commit_before>// The runtime wants to pull a number of variables out of the
// environment but calling getenv is not threadsafe, so every value
// that might come from the environment is loaded here, once, during
// init.

#include "rust_internal.h"

// The environment variables that the runtime knows about
#define RUST_THREADS "RUST_THREADS"
#define RUST_MIN_STACK "RUST_MIN_STACK"
#define RUST_LOG "RUST_LOG"
#define CHECK_CLAIMS "CHECK_CLAIMS"
#define DETAILED_LEAKS "DETAILED_LEAKS"
#define RUST_SEED "RUST_SEED"

#if defined(__WIN32__)
static int
get_num_cpus() {
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);

    return (int) sysinfo.dwNumberOfProcessors;
}
#elif defined(__BSD__)
static int
get_num_cpus() {
    /* swiped from http://stackoverflow.com/questions/150355/
       programmatically-find-the-number-of-cores-on-a-machine */

    unsigned int numCPU;
    int mib[4];
    size_t len = sizeof(numCPU);

    /* set the mib for hw.ncpu */
    mib[0] = CTL_HW;
    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;

    /* get the number of CPUs from the system */
    sysctl(mib, 2, &numCPU, &len, NULL, 0);

    if( numCPU < 1 ) {
        mib[1] = HW_NCPU;
        sysctl( mib, 2, &numCPU, &len, NULL, 0 );

        if( numCPU < 1 ) {
            numCPU = 1;
        }
    }
    return numCPU;
}
#elif defined(__GNUC__)
static int
get_num_cpus() {
    return sysconf(_SC_NPROCESSORS_ONLN);
}
#endif

static int
get_num_threads()
{
    char *env = getenv(RUST_THREADS);
    if(env) {
        int num = atoi(env);
        if(num > 0)
            return num;
    }
    return get_num_cpus();
}

static size_t
get_min_stk_size() {
    char *stack_size = getenv(RUST_MIN_STACK);
    if(stack_size) {
        return strtol(stack_size, NULL, 0);
    }
    else {
        return 0x300;
    }
}

static char*
copyenv(const char* name) {
    char *envvar = getenv(name);
    if (!envvar) {
        return NULL;
    } else {
        size_t slen = strlen(envvar);
        size_t buflen = slen + 1;
        char *var = (char*)malloc(buflen);
        memset(var, 0, buflen);
        strncpy(var, envvar, slen);
        return var;
    }
}

rust_env*
load_env() {
    rust_env *env = (rust_env*)malloc(sizeof(rust_env));

    env->num_sched_threads = (size_t)get_num_threads();
    env->min_stack_size = get_min_stk_size();
    env->logspec = copyenv(RUST_LOG);
    env->check_claims = getenv(CHECK_CLAIMS) != NULL;
    env->detailed_leaks = getenv(DETAILED_LEAKS) != NULL;
    env->rust_seed = copyenv(RUST_SEED);

    return env;
}

void
free_env(rust_env *env) {
    free(env->logspec);
    free(env->rust_seed);
    free(env);
}
<commit_msg>rt: Turn on big stacks again. Unwinding still doesn't always succeed on mac<commit_after>// The runtime wants to pull a number of variables out of the
// environment but calling getenv is not threadsafe, so every value
// that might come from the environment is loaded here, once, during
// init.

#include "rust_internal.h"

// The environment variables that the runtime knows about
#define RUST_THREADS "RUST_THREADS"
#define RUST_MIN_STACK "RUST_MIN_STACK"
#define RUST_LOG "RUST_LOG"
#define CHECK_CLAIMS "CHECK_CLAIMS"
#define DETAILED_LEAKS "DETAILED_LEAKS"
#define RUST_SEED "RUST_SEED"

#if defined(__WIN32__)
static int
get_num_cpus() {
    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);

    return (int) sysinfo.dwNumberOfProcessors;
}
#elif defined(__BSD__)
static int
get_num_cpus() {
    /* swiped from http://stackoverflow.com/questions/150355/
       programmatically-find-the-number-of-cores-on-a-machine */

    unsigned int numCPU;
    int mib[4];
    size_t len = sizeof(numCPU);

    /* set the mib for hw.ncpu */
    mib[0] = CTL_HW;
    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;

    /* get the number of CPUs from the system */
    sysctl(mib, 2, &numCPU, &len, NULL, 0);

    if( numCPU < 1 ) {
        mib[1] = HW_NCPU;
        sysctl( mib, 2, &numCPU, &len, NULL, 0 );

        if( numCPU < 1 ) {
            numCPU = 1;
        }
    }
    return numCPU;
}
#elif defined(__GNUC__)
static int
get_num_cpus() {
    return sysconf(_SC_NPROCESSORS_ONLN);
}
#endif

static int
get_num_threads()
{
    char *env = getenv(RUST_THREADS);
    if(env) {
        int num = atoi(env);
        if(num > 0)
            return num;
    }
    return get_num_cpus();
}

static size_t
get_min_stk_size() {
    char *stack_size = getenv(RUST_MIN_STACK);
    if(stack_size) {
        return strtol(stack_size, NULL, 0);
    }
    else {
        return 0x300000;
    }
}

static char*
copyenv(const char* name) {
    char *envvar = getenv(name);
    if (!envvar) {
        return NULL;
    } else {
        size_t slen = strlen(envvar);
        size_t buflen = slen + 1;
        char *var = (char*)malloc(buflen);
        memset(var, 0, buflen);
        strncpy(var, envvar, slen);
        return var;
    }
}

rust_env*
load_env() {
    rust_env *env = (rust_env*)malloc(sizeof(rust_env));

    env->num_sched_threads = (size_t)get_num_threads();
    env->min_stack_size = get_min_stk_size();
    env->logspec = copyenv(RUST_LOG);
    env->check_claims = getenv(CHECK_CLAIMS) != NULL;
    env->detailed_leaks = getenv(DETAILED_LEAKS) != NULL;
    env->rust_seed = copyenv(RUST_SEED);

    return env;
}

void
free_env(rust_env *env) {
    free(env->logspec);
    free(env->rust_seed);
    free(env);
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
//#define DBUG
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "defs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"

extern "C" {
  int ug_intro();
  void *yyparse();
  int profile();
  void rtprofile();
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

int interactive;     /* used in y.tab.c - don't remove this! */
Tree program;

#define CMAX 16    /* allow up to 16 command line args to be passed to subs */
char *aargv[CMAX];
char name[NAMESIZE];
int aargc;

/* <yyin> is yacc's input file. If we leave it alone, stdin will be used. */
extern FILE *yyin;

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   int i;

   RTBUFSAMPS = 8192;           /* default, modifyable with rtsetparams */
   NCHANS = 2;
   audioNCHANS = 0;

#ifdef LINUX
   for (i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   interactive = 1;
   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;
   check_peaks = 1;
   report_clipping = 1;

   output_data_format = -1;
   output_header_type = -1;
   normalize_output_floats = 0;
   is_float_format = 0;
   rtoutsfname = NULL;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   Bus_Configed = NO;
   for (i = 0; i < MAXBUS; i++) {
      AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
      ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
      ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
   }

   for (i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j;
   int         retcode;                 /* for mutexes */
   char        *cp, *infile;
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   /* Copy command-line args, if any.
      Now, command-line args will be available to any subroutine
      in aargc; and char *aargv[], (both declared extern in ugens.h)
      parsing is exactly the same then as standard C routine.
      Maximum of CMAX arguments allowed.
   */
   for (j = 1; j < argc; j++)
      aargv[j - 1] = argv[j];
   aargc = argc;

   /* Banner */
   printf("--------> %s %s (%s) <--------\n",
                                      RTCMIX_NAME, RTCMIX_VERSION, argv[0]);

   /* Process command line. */
   if (argc >= 2) {
      while ((*++argv)[0] == '-') {
         argc -= 1;             /* Take away two args */
         for (cp = argv[0] + 1; *cp; cp++) {
            switch (*cp) {      /* Grap options */
               case 'i':               /* for separate parseit thread */
                  rtInteractive = 1;
                  audio_config = 0;
                  break;
               case 'n':               /* for separate parseit thread */
                  noParse = 1;
                  break;
               case 's':               /* set up a socket offset */
                  socknew = atoi(*++argv);
                  fprintf(stderr, "listening on socket: %d\n",
                                                         MYPORT + socknew);
                  argc -= 1;
                  break;
               case 'c':     /* set up for continuous control (note tags on) */
                  tags_on = 1;
                  printf("rtupdates enabled\n");
                  curtag = 1;          /* "0" is reserved for all notes */
                  for (i = 0; i < MAXPUPS; i++)     /* initialize element 0 */
                     pupdatevals[0][i] = NOPUPDATE;
                  break;
               case 'f':     /* use file name arg instead of stdin as score */
                  infile = *++argv;
                  yyin = fopen(infile, "r+");
                  if (yyin == NULL) {
                     printf("Can't open %s\n", infile);
                     exit(1);
                  }
                  fprintf(stderr, "Using file %s\n", infile);
                  argc -= 1;
                  break;
               default:
                  printf("Don't know about option '%c'\n", *cp);
            }
         }
         if (argc == 1)
            break;
      }
   }

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

      fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         cout << "Parsing once ...\n";
         yyparse();
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
                                                             (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      /* retcode = pthread_join(inTraverseThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      /* retcode = pthread_join(sockitThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

   }
   else {
      yyparse();
      inTraverse(NULL);
   }

   /* DJT:  this instead of above joins */
   while (rtInteractive) {};

   closesf();

   return 0;
}

<commit_msg>New -p option for print_off<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
//#define DBUG
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "defs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"

extern "C" {
  int ug_intro();
  void *yyparse();
  int profile();
  void rtprofile();
#ifdef SGI
  void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
  void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

int interactive;     /* used in y.tab.c - don't remove this! */
Tree program;

#define CMAX 16    /* allow up to 16 command line args to be passed to subs */
char *aargv[CMAX];
char name[NAMESIZE];
int aargc;

/* <yyin> is yacc's input file. If we leave it alone, stdin will be used. */
extern FILE *yyin;

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   int i;

   RTBUFSAMPS = 8192;           /* default, modifyable with rtsetparams */
   NCHANS = 2;
   audioNCHANS = 0;

#ifdef LINUX
   for (i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   interactive = 1;
   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;
   check_peaks = 1;
   report_clipping = 1;

   output_data_format = -1;
   output_header_type = -1;
   normalize_output_floats = 0;
   is_float_format = 0;
   rtoutsfname = NULL;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   for (i = 0; i < MAXBUS; i++) {
      AuxToAuxPlayList[i] = -1; /* The playback order for AUX buses */
      ToOutPlayList[i] = -1;    /* The playback order for AUX buses */
      ToAuxPlayList[i] =-1;     /* The playback order for AUX buses */
   }

   for (i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j;
   int         retcode;                 /* for mutexes */
   char        *cp, *infile;
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   /* Copy command-line args, if any.
      Now, command-line args will be available to any subroutine
      in aargc; and char *aargv[], (both declared extern in ugens.h)
      parsing is exactly the same then as standard C routine.
      Maximum of CMAX arguments allowed.
   */
   for (j = 1; j < argc; j++)
      aargv[j - 1] = argv[j];
   aargc = argc;

   /* Banner */
   printf("--------> %s %s (%s) <--------\n",
                                      RTCMIX_NAME, RTCMIX_VERSION, argv[0]);

   /* Process command line. */
   if (argc >= 2) {
      while ((*++argv)[0] == '-') {
         argc -= 1;             /* Take away two args */
         for (cp = argv[0] + 1; *cp; cp++) {
            switch (*cp) {      /* Grap options */
               case 'i':               /* for separate parseit thread */
                  rtInteractive = 1;
                  audio_config = 0;
                  break;
               case 'n':               /* for separate parseit thread */
                  noParse = 1;
                  break;
               case 'p':               /* for separate parseit thread */
                  print_is_on = 0;
                  break;
               case 's':               /* set up a socket offset */
                  socknew = atoi(*++argv);
                  fprintf(stderr, "listening on socket: %d\n",
                                                         MYPORT + socknew);
                  argc -= 1;
                  break;
               case 'c':     /* set up for continuous control (note tags on) */
                  tags_on = 1;
                  printf("rtupdates enabled\n");
                  curtag = 1;          /* "0" is reserved for all notes */
                  for (i = 0; i < MAXPUPS; i++)     /* initialize element 0 */
                     pupdatevals[0][i] = NOPUPDATE;
                  break;
               case 'f':     /* use file name arg instead of stdin as score */
                  infile = *++argv;
                  yyin = fopen(infile, "r+");
                  if (yyin == NULL) {
                     printf("Can't open %s\n", infile);
                     exit(1);
                  }
                  fprintf(stderr, "Using file %s\n", infile);
                  argc -= 1;
                  break;
               default:
                  printf("Don't know about option '%c'\n", *cp);
            }
         }
         if (argc == 1)
            break;
      }
   }

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

	 if (print_is_on)
      fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         cout << "Parsing once ...\n";
         yyparse();
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse,
                                                             (void *) "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      /* retcode = pthread_join(inTraverseThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      /* retcode = pthread_join(sockitThread, NULL); */
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

   }
   else {
      yyparse();
      inTraverse(NULL);
   }

   /* DJT:  this instead of above joins */
   while (rtInteractive) {};

   closesf();

   return 0;
}

<|endoftext|>


<commit_before>#include "scene.h"
#include "../entity/entity.h"
#include "../scene/background.h"
#include <algorithm>
#include <iostream>

shared_ptr<Scene> Scene::instance_ = nullptr;
Scene::Scene()
    :bg_( nullptr ),
    space_(nullptr),
    player_(nullptr),
    last_update_(SDL_GetTicks()),
    last_draw_(SDL_GetTicks())
{
}
void Scene::init(string name,shared_ptr<PhysicalSpace>& space)
{
    bg_ = make_shared<Background> (Background(name));
    space_ = space;
    name_ = name;
}
void Scene::addEntity(shared_ptr<Entity> entity)
{
    auto it = std::find(entities_.begin(),entities_.end(),entity);
    //already exists
    if(it != entities_.end())
    {
        return;
    }
    entities_.push_back(entity);
    space_->addModel(entity);
}

void Scene::delEntity(shared_ptr<Entity> entity)
{
    entities_.erase(std::find(entities_.begin(), entities_.end(), entity));
    space_->delModel(entity);
}

void Scene::addPlayer(shared_ptr<Entity> player)
{
    player_ = player;
}

void Scene::delPlayer()
{
    player_.reset();
}

//经过Physics类，传过来的entity 是个假的entity
//通过find，找出真正的那个
void Scene::kill(shared_ptr<Entity> entity)
{
    auto it = std::find(entities_.begin(),entities_.end(),entity);
    //already exists
    if(it == entities_.end())
    {
       exit(-1);
    }
    dead_entities_.push_back(*it);
}

void Scene::update(shared_ptr<Camera> camera)
{
    uint32_t curr = SDL_GetTicks();
    uint32_t lag = curr - last_update_;
    shared_ptr<Scene> curr_scene(this, [](Scene* p){ return; });
    auto entitiesCP = entities_;
    while (lag  > UPDATE_GAP)
    {
        //player_->updatePhysics(curr_scene, space_);
        //for (auto& entity : entities_)
        for (auto& entity : entitiesCP)
        {
            entity->updatePhysics(curr_scene, space_);
        }
        last_update_ = SDL_GetTicks();
        lag -= UPDATE_GAP;
    }
    if (curr-last_draw_ > DRAW_GAP)
    {
        //player_->updateImage(camera);
        //for (auto& entity : entities_)
        for (auto& entity : entitiesCP)
        {
            entity->updateImage(camera);
        }
        camera->refresh(player_->getX(), player_->getY());
        last_draw_ = SDL_GetTicks();
    }
    //entities_ 不适合使用std::vector，性能跟不上，日后改
    for (auto& et : dead_entities_)
    {
        auto it = std::find(entities_.begin(), entities_.end(), et);
        space_->delModel(*it);
        entities_.erase(it);
    }
    dead_entities_.clear();
}
<commit_msg>skill update<commit_after>#include "scene.h"
#include "../entity/entity.h"
#include "../scene/background.h"
#include <algorithm>
#include <iostream>

shared_ptr<Scene> Scene::instance_ = nullptr;
Scene::Scene()
    :bg_( nullptr ),
    space_(nullptr),
    player_(nullptr),
    last_update_(SDL_GetTicks()),
    last_draw_(SDL_GetTicks())
{
}
void Scene::init(string name,shared_ptr<PhysicalSpace>& space)
{
    bg_ = make_shared<Background> (Background(name));
    space_ = space;
    name_ = name;
}
void Scene::addEntity(shared_ptr<Entity> entity)
{
    auto it = std::find(entities_.begin(),entities_.end(),entity);
    //already exists
    if(it != entities_.end())
    {
        return;
    }
    entities_.push_back(entity);
    space_->addModel(entity);
}

void Scene::delEntity(shared_ptr<Entity> entity)
{
    entities_.erase(std::find(entities_.begin(), entities_.end(), entity));
    space_->delModel(entity);
}

void Scene::addPlayer(shared_ptr<Entity> player)
{
    player_ = player;
}

void Scene::delPlayer()
{
    player_.reset();
}

//经过Physics类，传过来的entity 是个假的entity
//通过find，找出真正的那个
void Scene::kill(shared_ptr<Entity> entity)
{
    auto it = std::find(entities_.begin(),entities_.end(),entity);
    //already exists
    if(it == entities_.end())
    {
       exit(-1);
    }
    dead_entities_.push_back(*it);
}

void Scene::update(shared_ptr<Camera> camera)
{
    uint32_t curr = SDL_GetTicks();
    uint32_t lag = curr - last_update_;
    shared_ptr<Scene> curr_scene(this, [](Scene* p){ return; });
    auto entitiesTemp = entities_;
    while (lag  > UPDATE_GAP)
    {
        //Modify:将player统一到entities中，从此player和entity地位一样。
        //player_->updatePhysics(curr_scene, space_);
        //for (auto& entity : entities_)
        //Modify:这里我碰到一个问题，SKILL产生的新entity一旦在for循环进行中添加进entities队列中，直接
        //导致了段错误,而本来是没有这个毛病的。这个现象应该是正常的，我不太确定。
        //我临时使用这个策略,暂时用一下
        for (auto& entity : entitiesTemp)
        {
            entity->updatePhysics(curr_scene, space_);
        }
        last_update_ = SDL_GetTicks();
        lag -= UPDATE_GAP;
    }
    if (curr-last_draw_ > DRAW_GAP)
    {
        //player_->updateImage(camera);
        //for (auto& entity : entities_)
        for (auto& entity : entitiesTemp)
        {
            entity->updateImage(camera);
        }
        camera->refresh(player_->getX(), player_->getY());
        last_draw_ = SDL_GetTicks();
    }
    //entities_ 不适合使用std::vector，性能跟不上，日后改
    for (auto& et : dead_entities_)
    {
        auto it = std::find(entities_.begin(), entities_.end(), et);
        space_->delModel(*it);
        entities_.erase(it);
    }
    dead_entities_.clear();
}
<|endoftext|>


<commit_before>/*-
 * Copyright 2009 Colin Percival, 2011 ArtForz, 2011 pooler, 2013 Balthazar
 * 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 THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR 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.
 *
 * This file was originally written by Colin Percival as part of the Tarsnap
 * online backup system.
 */

#include <stdlib.h>
#include <stdint.h>
#if !defined(__arm__)
#include <xmmintrin.h>
#endif

#include "scrypt_mine.h"
#include "pbkdf2.h"

#include "util.h"
#include "net.h"

extern bool fShutdown;
extern bool fGenerateBitcoins;

extern CBlockIndex* pindexBest;
extern uint32_t nTransactionsUpdated;

#if defined(__x86_64__)

#define SCRYPT_3WAY
#define SCRYPT_BUFFER_SIZE (3 * 131072 + 63)

extern "C" int scrypt_best_throughput();
extern "C" void scrypt_core(uint32_t *X, uint32_t *V);
extern "C" void scrypt_core_2way(uint32_t *X, uint32_t *Y, uint32_t *V);
extern "C" void scrypt_core_3way(uint32_t *X, uint32_t *Y, uint32_t *Z, uint32_t *V);

#elif defined(__i386__) || defined(__arm__)

#define SCRYPT_BUFFER_SIZE (131072 + 63)

extern  "C" void scrypt_core(uint32_t *X, uint32_t *V);

#endif

void xor_salsa8(unsigned int B[16], const unsigned int Bx[16])
{
	unsigned int x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
	int i;
	x00 = (B[0] ^= Bx[0]);
	x01 = (B[1] ^= Bx[1]);
	x02 = (B[2] ^= Bx[2]);
	x03 = (B[3] ^= Bx[3]);
	x04 = (B[4] ^= Bx[4]);
	x05 = (B[5] ^= Bx[5]);
	x06 = (B[6] ^= Bx[6]);
	x07 = (B[7] ^= Bx[7]);
	x08 = (B[8] ^= Bx[8]);
	x09 = (B[9] ^= Bx[9]);
	x10 = (B[10] ^= Bx[10]);
	x11 = (B[11] ^= Bx[11]);
	x12 = (B[12] ^= Bx[12]);
	x13 = (B[13] ^= Bx[13]);
	x14 = (B[14] ^= Bx[14]);
	x15 = (B[15] ^= Bx[15]);
	for (i = 0; i < 8; i += 2) {
#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
	/* Operate on columns. */
		x04 ^= R(x00+x12, 7); x09 ^= R(x05+x01, 7);
		x14 ^= R(x10+x06, 7); x03 ^= R(x15+x11, 7);
		x08 ^= R(x04+x00, 9); x13 ^= R(x09+x05, 9);
		x02 ^= R(x14+x10, 9); x07 ^= R(x03+x15, 9);
		x12 ^= R(x08+x04,13); x01 ^= R(x13+x09,13);
		x06 ^= R(x02+x14,13); x11 ^= R(x07+x03,13);
		x00 ^= R(x12+x08,18); x05 ^= R(x01+x13,18);
		x10 ^= R(x06+x02,18); x15 ^= R(x11+x07,18);
	/* Operate on rows. */
		x01 ^= R(x00+x03, 7); x06 ^= R(x05+x04, 7);
		x11 ^= R(x10+x09, 7); x12 ^= R(x15+x14, 7);
		x02 ^= R(x01+x00, 9); x07 ^= R(x06+x05, 9);
		x08 ^= R(x11+x10, 9); x13 ^= R(x12+x15, 9);
		x03 ^= R(x02+x01,13); x04 ^= R(x07+x06,13);
		x09 ^= R(x08+x11,13); x14 ^= R(x13+x12,13);
		x00 ^= R(x03+x02,18); x05 ^= R(x04+x07,18);
		x10 ^= R(x09+x08,18); x15 ^= R(x14+x13,18);
#undef R
	}
	B[0] += x00;
	B[1] += x01;
	B[2] += x02;
	B[3] += x03;
	B[4] += x04;
	B[5] += x05;
	B[6] += x06;
	B[7] += x07;
	B[8] += x08;
	B[9] += x09;
	B[10] += x10;
	B[11] += x11;
	B[12] += x12;
	B[13] += x13;
	B[14] += x14;
	B[15] += x15;
}

void scrypt_core(unsigned int *X, unsigned int *V)
{
	unsigned int i, j, k;
	for (i = 0; i < 1024; i++) {
		memcpy(&V[i * 32], X, 128);
		xor_salsa8(&X[0], &X[16]);
		xor_salsa8(&X[16], &X[0]);
	}
	for (i = 0; i < 1024; i++) {
		j = 32 * (X[16] & 1023);
		for (k = 0; k < 32; k++)
			X[k] ^= V[j + k];
		xor_salsa8(&X[0], &X[16]);
		xor_salsa8(&X[16], &X[0]);
	}
}

void *scrypt_buffer_alloc() {
    return malloc(SCRYPT_BUFFER_SIZE);
}

void scrypt_buffer_free(void *scratchpad)
{
    free(scratchpad);
}

/* cpu and memory intensive function to transform a 80 byte buffer into a 32 byte output
   scratchpad size needs to be at least 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N) bytes
   r = 1, p = 1, N = 1024
 */

static void scrypt(const void* input, size_t inputlen, uint32_t *res, void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input, inputlen, (const uint8_t*)input, sizeof(block_header), 1, (uint8_t *)X, 128);

    scrypt_core(X, V);

    PBKDF2_SHA256((const uint8_t*)input, inputlen, (uint8_t *)X, 128, 1, (uint8_t*)res, 32);
}

void scrypt_hash(const void* input, size_t inputlen, uint32_t *res, void *scratchpad)
{
    return scrypt(input, inputlen, res, scratchpad);
}

#ifdef SCRYPT_3WAY
static void scrypt_2way(const void *input1, const void *input2, size_t input1len, size_t input2len, uint32_t *res1, uint32_t *res2, void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32], Y[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (const uint8_t*)input1, input1len, 1, (uint8_t *)X, 128);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (const uint8_t*)input2, input2len, 1, (uint8_t *)Y, 128);

    scrypt_core_2way(X, Y, V);

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (uint8_t *)X, 128, 1, (uint8_t*)res1, 32);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (uint8_t *)Y, 128, 1, (uint8_t*)res2, 32);
}

static void scrypt_3way(const void *input1, const void *input2, const void *input3,
   size_t input1len, size_t input2len, size_t input3len, uint32_t *res1, uint32_t *res2, uint32_t *res3,
   void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32], Y[32], Z[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (const uint8_t*)input1, input1len, 1, (uint8_t *)X, 128);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (const uint8_t*)input2, input2len, 1, (uint8_t *)Y, 128);
    PBKDF2_SHA256((const uint8_t*)input3, input3len, (const uint8_t*)input3, input3len, 1, (uint8_t *)Z, 128);

    scrypt_core_3way(X, Y, Z, V);

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (uint8_t *)X, 128, 1, (uint8_t*)res1, 32);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (uint8_t *)Y, 128, 1, (uint8_t*)res2, 32);
    PBKDF2_SHA256((const uint8_t*)input3, input3len, (uint8_t *)Z, 128, 1, (uint8_t*)res3, 32);
}
#endif

unsigned int scanhash_scrypt(block_header *pdata, void *scratchbuf,
    uint32_t max_nonce, uint32_t &hash_count,
    void *result, block_header *res_header)
{
    hash_count = 0;
    block_header data = *pdata;
    uint32_t hash[8];
    unsigned char *hashc = (unsigned char *) &hash;

#ifdef SCRYPT_3WAY
    block_header data2 = *pdata;
    uint32_t hash2[8];
    unsigned char *hashc2 = (unsigned char *) &hash2;

    block_header data3 = *pdata;
    uint32_t hash3[8];
    unsigned char *hashc3 = (unsigned char *) &hash3;

    int throughput = scrypt_best_throughput();
#endif

    uint32_t n = 0;

    while (true) {

        data.nonce = n++;

#ifdef SCRYPT_3WAY
        if (throughput >= 2 && n < max_nonce) {
            data2.nonce = n++;
            if(throughput >= 3)
            {
                data3.nonce = n++;
                scrypt_3way(&data, &data2, &data3, 80, 80, 80, hash, hash2, hash3, scratchbuf);
                hash_count += 3;

                if (hashc3[31] == 0 && hashc3[30] == 0) {
                    memcpy(result, hash3, 32);
                    *res_header = data3;

                    return data3.nonce;
                }
            }
            else
            {
                scrypt_2way(&data, &data2, 80, 80, hash, hash2, scratchbuf);
                hash_count += 2;
            }

            if (hashc2[31] == 0 && hashc2[30] == 0) {
                memcpy(result, hash2, 32);

                return data2.nonce;
            }
        } else {
            scrypt(&data, 80, hash, scratchbuf);
            hash_count += 1;
        }
#else
        scrypt(&data, 80, hash, scratchbuf);
        hash_count += 1;
#endif
        if (hashc[31] == 0 && hashc[30] == 0) {
            memcpy(result, hash, 32);

            return data.nonce;
        }

        if (n >= max_nonce) {
            hash_count = 0xffff + 1;
            break;
        }
    }

    return (unsigned int) -1;
}
<commit_msg>Raspbeery Pi arm modif<commit_after>/*-
 * Copyright 2009 Colin Percival, 2011 ArtForz, 2011 pooler, 2013 Balthazar
 * 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 THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR 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.
 *
 * This file was originally written by Colin Percival as part of the Tarsnap
 * online backup system.
 */

#include <stdlib.h>
#include <stdint.h>
#if !defined(__arm__)
#include <xmmintrin.h>
#endif

#include "scrypt_mine.h"
#include "pbkdf2.h"

#include "util.h"
#include "net.h"

extern bool fShutdown;
extern bool fGenerateBitcoins;

extern CBlockIndex* pindexBest;
extern uint32_t nTransactionsUpdated;

#if defined(__x86_64__)

#define SCRYPT_3WAY
#define SCRYPT_BUFFER_SIZE (3 * 131072 + 63)

extern "C" int scrypt_best_throughput();
extern "C" void scrypt_core(uint32_t *X, uint32_t *V);
extern "C" void scrypt_core_2way(uint32_t *X, uint32_t *Y, uint32_t *V);
extern "C" void scrypt_core_3way(uint32_t *X, uint32_t *Y, uint32_t *Z, uint32_t *V);

#elif defined(__i386__) || defined(__arm__)

#define SCRYPT_BUFFER_SIZE (131072 + 63)

extern  "C" void scrypt_core(uint32_t *X, uint32_t *V);

#endif

void xor_salsa8(unsigned int B[16], const unsigned int Bx[16])
{
	unsigned int x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
	int i;
	x00 = (B[0] ^= Bx[0]);
	x01 = (B[1] ^= Bx[1]);
	x02 = (B[2] ^= Bx[2]);
	x03 = (B[3] ^= Bx[3]);
	x04 = (B[4] ^= Bx[4]);
	x05 = (B[5] ^= Bx[5]);
	x06 = (B[6] ^= Bx[6]);
	x07 = (B[7] ^= Bx[7]);
	x08 = (B[8] ^= Bx[8]);
	x09 = (B[9] ^= Bx[9]);
	x10 = (B[10] ^= Bx[10]);
	x11 = (B[11] ^= Bx[11]);
	x12 = (B[12] ^= Bx[12]);
	x13 = (B[13] ^= Bx[13]);
	x14 = (B[14] ^= Bx[14]);
	x15 = (B[15] ^= Bx[15]);
	for (i = 0; i < 8; i += 2) {
#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
	/* Operate on columns. */
		x04 ^= R(x00+x12, 7); x09 ^= R(x05+x01, 7);
		x14 ^= R(x10+x06, 7); x03 ^= R(x15+x11, 7);
		x08 ^= R(x04+x00, 9); x13 ^= R(x09+x05, 9);
		x02 ^= R(x14+x10, 9); x07 ^= R(x03+x15, 9);
		x12 ^= R(x08+x04,13); x01 ^= R(x13+x09,13);
		x06 ^= R(x02+x14,13); x11 ^= R(x07+x03,13);
		x00 ^= R(x12+x08,18); x05 ^= R(x01+x13,18);
		x10 ^= R(x06+x02,18); x15 ^= R(x11+x07,18);
	/* Operate on rows. */
		x01 ^= R(x00+x03, 7); x06 ^= R(x05+x04, 7);
		x11 ^= R(x10+x09, 7); x12 ^= R(x15+x14, 7);
		x02 ^= R(x01+x00, 9); x07 ^= R(x06+x05, 9);
		x08 ^= R(x11+x10, 9); x13 ^= R(x12+x15, 9);
		x03 ^= R(x02+x01,13); x04 ^= R(x07+x06,13);
		x09 ^= R(x08+x11,13); x14 ^= R(x13+x12,13);
		x00 ^= R(x03+x02,18); x05 ^= R(x04+x07,18);
		x10 ^= R(x09+x08,18); x15 ^= R(x14+x13,18);
#undef R
	}
	B[0] += x00;
	B[1] += x01;
	B[2] += x02;
	B[3] += x03;
	B[4] += x04;
	B[5] += x05;
	B[6] += x06;
	B[7] += x07;
	B[8] += x08;
	B[9] += x09;
	B[10] += x10;
	B[11] += x11;
	B[12] += x12;
	B[13] += x13;
	B[14] += x14;
	B[15] += x15;
}

void scrypt_core(unsigned int *X, unsigned int *V)
{
	unsigned int i, j, k;
	for (i = 0; i < 1024; i++) {
		memcpy(&V[i * 32], X, 128);
		xor_salsa8(&X[0], &X[16]);
		xor_salsa8(&X[16], &X[0]);
	}
	for (i = 0; i < 1024; i++) {
		j = 32 * (X[16] & 1023);
		for (k = 0; k < 32; k++)
			X[k] ^= V[j + k];
		xor_salsa8(&X[0], &X[16]);
		xor_salsa8(&X[16], &X[0]);
	}
}

void *scrypt_buffer_alloc() {
    return malloc(SCRYPT_BUFFER_SIZE);
}

void scrypt_buffer_free(void *scratchpad)
{
    free(scratchpad);
}

/* cpu and memory intensive function to transform a 80 byte buffer into a 32 byte output
   scratchpad size needs to be at least 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N) bytes
   r = 1, p = 1, N = 1024
 */

static void scrypt(const void* input, size_t inputlen, uint32_t *res, void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input, inputlen, (const uint8_t*)input, sizeof(block_header), 1, (uint8_t *)X, 128);

    scrypt_core(X, V);

    PBKDF2_SHA256((const uint8_t*)input, inputlen, (uint8_t *)X, 128, 1, (uint8_t*)res, 32);
}

void scrypt_hash(const void* input, size_t inputlen, uint32_t *res, void *scratchpad)
{
    return scrypt(input, inputlen, res, scratchpad);
}

#ifdef SCRYPT_3WAY
static void scrypt_2way(const void *input1, const void *input2, size_t input1len, size_t input2len, uint32_t *res1, uint32_t *res2, void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32], Y[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (const uint8_t*)input1, input1len, 1, (uint8_t *)X, 128);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (const uint8_t*)input2, input2len, 1, (uint8_t *)Y, 128);

    scrypt_core_2way(X, Y, V);

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (uint8_t *)X, 128, 1, (uint8_t*)res1, 32);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (uint8_t *)Y, 128, 1, (uint8_t*)res2, 32);
}

static void scrypt_3way(const void *input1, const void *input2, const void *input3,
   size_t input1len, size_t input2len, size_t input3len, uint32_t *res1, uint32_t *res2, uint32_t *res3,
   void *scratchpad)
{
    uint32_t *V;
    uint32_t X[32], Y[32], Z[32];
    V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (const uint8_t*)input1, input1len, 1, (uint8_t *)X, 128);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (const uint8_t*)input2, input2len, 1, (uint8_t *)Y, 128);
    PBKDF2_SHA256((const uint8_t*)input3, input3len, (const uint8_t*)input3, input3len, 1, (uint8_t *)Z, 128);

    scrypt_core_3way(X, Y, Z, V);

    PBKDF2_SHA256((const uint8_t*)input1, input1len, (uint8_t *)X, 128, 1, (uint8_t*)res1, 32);
    PBKDF2_SHA256((const uint8_t*)input2, input2len, (uint8_t *)Y, 128, 1, (uint8_t*)res2, 32);
    PBKDF2_SHA256((const uint8_t*)input3, input3len, (uint8_t *)Z, 128, 1, (uint8_t*)res3, 32);
}
#endif

unsigned int scanhash_scrypt(block_header *pdata, void *scratchbuf,
    uint32_t max_nonce, uint32_t &hash_count,
    void *result, block_header *res_header)
{
    hash_count = 0;
    block_header data = *pdata;
    uint32_t hash[8];
    unsigned char *hashc = (unsigned char *) &hash;

#ifdef SCRYPT_3WAY
    block_header data2 = *pdata;
    uint32_t hash2[8];
    unsigned char *hashc2 = (unsigned char *) &hash2;

    block_header data3 = *pdata;
    uint32_t hash3[8];
    unsigned char *hashc3 = (unsigned char *) &hash3;

    int throughput = scrypt_best_throughput();
#endif

    uint32_t n = 0;

    while (true) {

        data.nonce = n++;

#ifdef SCRYPT_3WAY
        if (throughput >= 2 && n < max_nonce) {
            data2.nonce = n++;
            if(throughput >= 3)
            {
                data3.nonce = n++;
                scrypt_3way(&data, &data2, &data3, 80, 80, 80, hash, hash2, hash3, scratchbuf);
                hash_count += 3;

                if (hashc3[31] == 0 && hashc3[30] == 0) {
                    memcpy(result, hash3, 32);
                    *res_header = data3;

                    return data3.nonce;
                }
            }
            else
            {
                scrypt_2way(&data, &data2, 80, 80, hash, hash2, scratchbuf);
                hash_count += 2;
            }

            if (hashc2[31] == 0 && hashc2[30] == 0) {
                memcpy(result, hash2, 32);

                return data2.nonce;
            }
        } else {
            scrypt(&data, 80, hash, scratchbuf);
            hash_count += 1;
        }
#else
        scrypt(&data, 80, hash, scratchbuf);
        hash_count += 1;
#endif
        if (hashc[31] == 0 && hashc[30] == 0) {
            memcpy(result, hash, 32);

            return data.nonce;
        }

        if (n >= max_nonce) {
            hash_count = 0xffff + 1;
            break;
        }
    }

    return (unsigned int) -1;
}
<|endoftext|>