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

#ifndef _CONSTANTS_HPP_
#define _CONSTANTS_HPP_

#include <stdint.h>

const uint32_t DYNNPC_BASE = 0xFF800000;
const uint32_t NPC_BASE = 0xFF000000;
const uint32_t MONSTER_BASE = 0xFE000000;

const uint32_t MONSTERVIEWRANGE = 11;

#define MAXPOISONVALUE     400
#define MAXMANA            10000
#define MAXHPS 10000
#define MAXFOOD 60000
#define MAXATTRIB 255

#define WAITINGVALIDATION 1
#define BANNED 30
#define BANNEDFORTIME 31

#define LEFTHANDMODIFIER 2

#define SOUNDFIELD 1
#define MUSICFIELD 2

#define DEPOTITEM 321
#define DEPOTSIZE 100
#define BLOCKEDITEM 228

#define LANGUAGECOUNT 3

#define FLAG_GROUNDLEVEL 3 //!< 0,1,2,3

#define FLAG_SPECIALITEM 8 //!< 1 == true

#define FLAG_PENETRATEABLE 16 //!< 0 == true

#define FLAG_TRANSPARENT 32 //!< 0 == true

#define FLAG_PASSABLE 64 //!< 0 == true

#define FLAG_MAKEPASSABLE 128 //!< 1 == true

#define FLAG_MONSTERONFIELD 4 //!< 1 == true

#define FLAG_NPCONFIELD 8 //!< 1 == true

#define FLAG_PLAYERONFIELD 128 //!< 1 == true

#define FLAG_SPECIALTILE 128  //!< 1 == true

#define FLAG_WARPFIELD 1 //!< 1 == true

// Verwendung siehe Tabelle:
// WERT|      tiles        |   tilesmoditems   |    clientflags     |     extraflags    |
// ----+-------------------+-------------------+--------------------+-------------------+
// 001 |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL    |FLAG_WARPFIELD     |
// ----+-------------------+-------------------+--------------------+-------------------+
// 002 |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL    |                   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 004 |                   |                   |FLAG_MONSTERONFIELD |                   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 008 |                   |FLAG_SPECIALITEM   |FLAG_NPCONFIELD     |FLAG_SPECIALITEM   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 016 |FLAG_PENETRATEABLE |FLAG_PENETRATEABLE |                    |FLAG_PENETRATEABLE |
// ----+-------------------+-------------------+--------------------+-------------------+
// 032 |FLAG_TRANSPARENT   |FLAG_TRANSPARENT   |                    |FLAG_TRANSPARENT   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 064 |FLAG_PASSABLE      |FLAG_PASSABLE      |                    |FLAG_PASSABLE      |
// ----+-------------------+-------------------+--------------------+-------------------+
// 128 |FLAG_SPECIALTILE   |                   |FLAG_PLAYERONFIELD  |FLAG_SPECIALTILE   |
// ----+-------------------+-------------------+--------------------+-------------------+

//! das Verzeichnis der Karte, relativ zum DEFAULTMUDDIR
#define MAPDIR          "map/"

//! das Verzeichnis der Skripte, relativ zum DEFAULTMUDDIR
#define SCRIPTSDIR          "scripts/"

//! Anzahl der maximal sichtbaren Ebenen nach Oben
#define RANGEUP       0x02

//! Anzahl der maximal sichtbaren Ebenen nach Unten
#define RANGEDOWN       0x02

//! Anzahl der Felder zwischen zwei Ebenen
#define LEVELDISTANCE 0x03

//! Typ der maximalen Anzahl von Item in einem Container
#define MAXCOUNTTYPE unsigned char

//! Die maximale Anzahl von Item auf einem Feld
#define MAXITEMS 250 // max 255 da oft als BYTE verwendet

//! die maximale Anzahl von Item am Grtel
#define MAX_BELT_SLOTS 6

//! Die maximale Anzahl von Item direkt am K�per
#define MAX_BODY_ITEMS 12

//! Rucksack
#define BACKPACK 0

//! Kopf
#define HEAD 1

//! Kopf-Flag
#define FLAG_HEAD 1

//! Hals
#define NECK 2

//! Hals-Flag
#define FLAG_NECK 2

//! Brustkorb
#define BREAST 3

//! Brustkorb-Flag
#define FLAG_BREAST 4

//! H�de (fr Handschuhe)
#define HANDS 4

//! H�de-Flag
#define FLAG_HANDS 8

//! Werkzeug / Waffe in der linken Hand
#define LEFT_TOOL 5

//! Werkzeug / Waffe in der rechten Hand
#define RIGHT_TOOL 6

//! Finger der linken Hand
#define FINGER_LEFT_HAND 7

//! Finger der rechten Hand
#define FINGER_RIGHT_HAND 8

//! Finger-Flag
#define FLAG_FINGER 32

//! Beine
#define LEGS 9

//! Beine-Flag
#define FLAG_LEGS 64

//! F�
#define FEET 10

//! F�-Flag
#define FLAG_FEET 128

//! Umhang
#define COAT 11

#define LAST_WEARABLE 11

//! Coat-Flag
#define FLAG_COAT 16

//! Die maximale Anzahl von dargestellten showcases
#define MAXSHOWCASES 100

//! Code fr "kein Feld"
#define NOFIELD 0xFFFF

//-------------- Client to Server ---------------------

//! folgender Wert ist relative x und y Koordinaten eines Items/Bodenplatte/Charakters
#define UID_KOORD 0x01

//! folgender Wert ist Showcasenummer+showcaseposition
#define UID_SHOWC 0x02

//! folgender Wert ist Inventory Position
#define UID_INV 0x03

//! Eine Person wird benutzt
#define UID_PERSON 0x05

#define UID_MAGICWAND 0x06

//-------------- Server to Client ---------------------

//! Code fr "keine Bewegung" (anstatt der Richtung zu senden)
#define NOMOVE 0x0A
#define NORMALMOVE 0x0B
#define PUSH 0x0C
#define RUNNING 0x0D

//! Grund fr Verbindungsabbruch: Client logt aus
#define NORMALLOGOUT       0x00

//! Grund fr Verbindungsabbruch: zu alter Client
#define OLDCLIENT       0x01

//! Grund fr Verbindungsabbruch: Spieler ist schon online
#define DOUBLEPLAYER       0x02

//! Grund fr Verbindungsabbruch: Falsches Pa�ort
#define WRONGPWD         0x03

//! Grund fr Verbindungsabbruch: Servershutdown
#define SERVERSHUTDOWN      0x04

//! Grund fr Verbindungsabbruch: durch Gamemaster entfernt
#define BYGAMEMASTER       0x05

//! Grund fr Verbindungsabbruch: zum Erstellen eines neuen Player
#define FORCREATE            0x06

//! Grund fr Verbindungsabbruch: kein Platz fr den Player
#define NOPLACE               0x07

//! Grund fr Verbindungsabbruch: angegebener Spieler nicht gefunden
#define NOCHARACTERFOUND 0x08

//! Grund fr Verbindungsabbruch: Spieler wurde erstellt
#define PLAYERCREATED 0x09 // string name

//! Grund fr Verbindungsabbruch: UNSTABLECONNECTION
#define UNSTABLECONNECTION 0x0A // string name

//! Reason for Connection shutdown: player has no account
#define NOACCOUNT 0x0B

//! Grund fr Verbindungsabbruch: no skill package chosen
#define NOSKILLS 0x0C

//! Grund fuer Verbindungsabbruch: Spielerdaten korrupt
#define ORRUPTDATA 0x0D

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

#ifndef _CONSTANTS_HPP_
#define _CONSTANTS_HPP_

#include <stdint.h>

const uint32_t DYNNPC_BASE = 0xFF800000;
const uint32_t NPC_BASE = 0xFF000000;
const uint32_t MONSTER_BASE = 0xFE000000;

const uint32_t MONSTERVIEWRANGE = 11;

#define MAXPOISONVALUE     400
#define MAXMANA            10000
#define MAXHPS 10000
#define MAXFOOD 60000
#define MAXATTRIB 255

#define WAITINGVALIDATION 1
#define BANNED 30
#define BANNEDFORTIME 31

#define SOUNDFIELD 1
#define MUSICFIELD 2

#define DEPOTITEM 321
#define DEPOTSIZE 100
#define BLOCKEDITEM 228

#define FLAG_GROUNDLEVEL 3 //!< 0,1,2,3

#define FLAG_SPECIALITEM 8 //!< 1 == true

#define FLAG_PENETRATEABLE 16 //!< 0 == true

#define FLAG_TRANSPARENT 32 //!< 0 == true

#define FLAG_PASSABLE 64 //!< 0 == true

#define FLAG_MAKEPASSABLE 128 //!< 1 == true

#define FLAG_MONSTERONFIELD 4 //!< 1 == true

#define FLAG_NPCONFIELD 8 //!< 1 == true

#define FLAG_PLAYERONFIELD 128 //!< 1 == true

#define FLAG_SPECIALTILE 128  //!< 1 == true

#define FLAG_WARPFIELD 1 //!< 1 == true

// Verwendung siehe Tabelle:
// WERT|      tiles        |   tilesmoditems   |    clientflags     |     extraflags    |
// ----+-------------------+-------------------+--------------------+-------------------+
// 001 |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL    |FLAG_WARPFIELD     |
// ----+-------------------+-------------------+--------------------+-------------------+
// 002 |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL   |FLAG_GROUNDLEVEL    |                   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 004 |                   |                   |FLAG_MONSTERONFIELD |                   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 008 |                   |FLAG_SPECIALITEM   |FLAG_NPCONFIELD     |FLAG_SPECIALITEM   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 016 |FLAG_PENETRATEABLE |FLAG_PENETRATEABLE |                    |FLAG_PENETRATEABLE |
// ----+-------------------+-------------------+--------------------+-------------------+
// 032 |FLAG_TRANSPARENT   |FLAG_TRANSPARENT   |                    |FLAG_TRANSPARENT   |
// ----+-------------------+-------------------+--------------------+-------------------+
// 064 |FLAG_PASSABLE      |FLAG_PASSABLE      |                    |FLAG_PASSABLE      |
// ----+-------------------+-------------------+--------------------+-------------------+
// 128 |FLAG_SPECIALTILE   |                   |FLAG_PLAYERONFIELD  |FLAG_SPECIALTILE   |
// ----+-------------------+-------------------+--------------------+-------------------+

//! das Verzeichnis der Karte, relativ zum DEFAULTMUDDIR
#define MAPDIR          "map/"

//! das Verzeichnis der Skripte, relativ zum DEFAULTMUDDIR
#define SCRIPTSDIR          "scripts/"

//! Anzahl der maximal sichtbaren Ebenen nach Oben
#define RANGEUP       0x02

//! Anzahl der maximal sichtbaren Ebenen nach Unten
#define RANGEDOWN       0x02

//! Anzahl der Felder zwischen zwei Ebenen
#define LEVELDISTANCE 0x03

//! Typ der maximalen Anzahl von Item in einem Container
#define MAXCOUNTTYPE unsigned char

//! Die maximale Anzahl von Item auf einem Feld
#define MAXITEMS 250 // max 255 da oft als BYTE verwendet

//! die maximale Anzahl von Item am Grtel
#define MAX_BELT_SLOTS 6

//! Die maximale Anzahl von Item direkt am K�per
#define MAX_BODY_ITEMS 12

//! Rucksack
#define BACKPACK 0

//! Kopf
#define HEAD 1

//! Kopf-Flag
#define FLAG_HEAD 1

//! Hals
#define NECK 2

//! Hals-Flag
#define FLAG_NECK 2

//! Brustkorb
#define BREAST 3

//! Brustkorb-Flag
#define FLAG_BREAST 4

//! H�de (fr Handschuhe)
#define HANDS 4

//! H�de-Flag
#define FLAG_HANDS 8

//! Werkzeug / Waffe in der linken Hand
#define LEFT_TOOL 5

//! Werkzeug / Waffe in der rechten Hand
#define RIGHT_TOOL 6

//! Finger der linken Hand
#define FINGER_LEFT_HAND 7

//! Finger der rechten Hand
#define FINGER_RIGHT_HAND 8

//! Finger-Flag
#define FLAG_FINGER 32

//! Beine
#define LEGS 9

//! Beine-Flag
#define FLAG_LEGS 64

//! F�
#define FEET 10

//! F�-Flag
#define FLAG_FEET 128

//! Umhang
#define COAT 11

#define LAST_WEARABLE 11

//! Coat-Flag
#define FLAG_COAT 16

//! Die maximale Anzahl von dargestellten showcases
#define MAXSHOWCASES 100

//! Code fr "kein Feld"
#define NOFIELD 0xFFFF

//-------------- Client to Server ---------------------

//! folgender Wert ist relative x und y Koordinaten eines Items/Bodenplatte/Charakters
#define UID_KOORD 0x01

//! folgender Wert ist Showcasenummer+showcaseposition
#define UID_SHOWC 0x02

//! folgender Wert ist Inventory Position
#define UID_INV 0x03

//! Eine Person wird benutzt
#define UID_PERSON 0x05

#define UID_MAGICWAND 0x06

//-------------- Server to Client ---------------------

//! Code fr "keine Bewegung" (anstatt der Richtung zu senden)
#define NOMOVE 0x0A
#define NORMALMOVE 0x0B
#define PUSH 0x0C
#define RUNNING 0x0D

//! Grund fr Verbindungsabbruch: Client logt aus
#define NORMALLOGOUT       0x00

//! Grund fr Verbindungsabbruch: zu alter Client
#define OLDCLIENT       0x01

//! Grund fr Verbindungsabbruch: Spieler ist schon online
#define DOUBLEPLAYER       0x02

//! Grund fr Verbindungsabbruch: Falsches Pa�ort
#define WRONGPWD         0x03

//! Grund fr Verbindungsabbruch: Servershutdown
#define SERVERSHUTDOWN      0x04

//! Grund fr Verbindungsabbruch: durch Gamemaster entfernt
#define BYGAMEMASTER       0x05

//! Grund fr Verbindungsabbruch: zum Erstellen eines neuen Player
#define FORCREATE            0x06

//! Grund fr Verbindungsabbruch: kein Platz fr den Player
#define NOPLACE               0x07

//! Grund fr Verbindungsabbruch: angegebener Spieler nicht gefunden
#define NOCHARACTERFOUND 0x08

//! Grund fr Verbindungsabbruch: Spieler wurde erstellt
#define PLAYERCREATED 0x09 // string name

//! Grund fr Verbindungsabbruch: UNSTABLECONNECTION
#define UNSTABLECONNECTION 0x0A // string name

//! Reason for Connection shutdown: player has no account
#define NOACCOUNT 0x0B

//! Grund fr Verbindungsabbruch: no skill package chosen
#define NOSKILLS 0x0C

//! Grund fuer Verbindungsabbruch: Spielerdaten korrupt
#define ORRUPTDATA 0x0D

#endif
<|endoftext|>


<commit_before>#include <event/event_callback.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>

/*
 * PipeProducer is a pipe with a producer-consume API.
 */

PipeProducer::PipeProducer(const LogHandle& log)
: log_(log),
  output_buffer_(),
  output_action_(NULL),
  output_callback_(NULL),
  output_eos_(false),
  error_(false)
{
}

PipeProducer::~PipeProducer()
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);
}

Action *
PipeProducer::input(Buffer *buf, EventCallback *cb)
{
	if (!error_) {
		/*
		 * XXX
		 * Allow consume() to only consume part of buf, and to
		 * delay further input.
		 */
		consume(buf);
		ASSERT(buf->empty());
	} else {
		buf->clear();
	}

	if (error_)
		cb->param(Event::Error);
	else
		cb->param(Event::Done);
	return (cb->schedule());
}

Action *
PipeProducer::output(EventCallback *cb)
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);

	Action *a = output_do(cb);
	if (a != NULL)
		return (a);

	output_callback_ = cb;

	return (cancellation(this, &PipeProducer::output_cancel));
}

void
PipeProducer::output_cancel(void)
{
	if (output_action_ != NULL) {
		ASSERT(output_callback_ == NULL);

		output_action_->cancel();
		output_action_ = NULL;
	}

	if (output_callback_ != NULL) {
		delete output_callback_;
		output_callback_ = NULL;
	}
}

Action *
PipeProducer::output_do(EventCallback *cb)
{
	if (error_) {
		ASSERT(output_buffer_.empty());

		cb->param(Event::Error);
		return (cb->schedule());
	}

	if (!output_buffer_.empty()) {
		cb->param(Event(Event::Done, output_buffer_));
		output_buffer_.clear();
		return (cb->schedule());
	}

	if (output_eos_) {
		cb->param(Event::EOS);
		return (cb->schedule());
	}

	return (NULL);
}

void
PipeProducer::produce(Buffer *buf)
{
	ASSERT(!error_);
	ASSERT(!output_eos_);

	if (!buf->empty()) {
		output_buffer_.append(buf);
		buf->clear();
	} else {
		output_eos_ = true;
	}

	if (output_callback_ != NULL) {
		ASSERT(output_action_ == NULL);

		Action *a = output_do(output_callback_);
		if (a != NULL) {
			output_action_ = a;
			output_callback_ = NULL;
		}
	}
}

void
PipeProducer::produce_error(void)
{
	ASSERT(!error_);
	ASSERT(!output_eos_);

	error_ = true;
	output_buffer_.clear();

	if (output_callback_ != NULL) {
		ASSERT(output_action_ == NULL);

		Action *a = output_do(output_callback_);
		if (a != NULL) {
			output_action_ = a;
			output_callback_ = NULL;
		}
	}
}
<commit_msg>Clear out buffer on error if there was more data.<commit_after>#include <event/event_callback.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>

/*
 * PipeProducer is a pipe with a producer-consume API.
 */

PipeProducer::PipeProducer(const LogHandle& log)
: log_(log),
  output_buffer_(),
  output_action_(NULL),
  output_callback_(NULL),
  output_eos_(false),
  error_(false)
{
}

PipeProducer::~PipeProducer()
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);
}

Action *
PipeProducer::input(Buffer *buf, EventCallback *cb)
{
	if (!error_) {
		/*
		 * XXX
		 * Allow consume() to only consume part of buf, and to
		 * delay further input.
		 */
		consume(buf);
		if (error_ && !buf->empty())
			buf->clear();
		ASSERT(buf->empty());
	} else {
		buf->clear();
	}

	if (error_)
		cb->param(Event::Error);
	else
		cb->param(Event::Done);
	return (cb->schedule());
}

Action *
PipeProducer::output(EventCallback *cb)
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);

	Action *a = output_do(cb);
	if (a != NULL)
		return (a);

	output_callback_ = cb;

	return (cancellation(this, &PipeProducer::output_cancel));
}

void
PipeProducer::output_cancel(void)
{
	if (output_action_ != NULL) {
		ASSERT(output_callback_ == NULL);

		output_action_->cancel();
		output_action_ = NULL;
	}

	if (output_callback_ != NULL) {
		delete output_callback_;
		output_callback_ = NULL;
	}
}

Action *
PipeProducer::output_do(EventCallback *cb)
{
	if (error_) {
		ASSERT(output_buffer_.empty());

		cb->param(Event::Error);
		return (cb->schedule());
	}

	if (!output_buffer_.empty()) {
		cb->param(Event(Event::Done, output_buffer_));
		output_buffer_.clear();
		return (cb->schedule());
	}

	if (output_eos_) {
		cb->param(Event::EOS);
		return (cb->schedule());
	}

	return (NULL);
}

void
PipeProducer::produce(Buffer *buf)
{
	ASSERT(!error_);
	ASSERT(!output_eos_);

	if (!buf->empty()) {
		output_buffer_.append(buf);
		buf->clear();
	} else {
		output_eos_ = true;
	}

	if (output_callback_ != NULL) {
		ASSERT(output_action_ == NULL);

		Action *a = output_do(output_callback_);
		if (a != NULL) {
			output_action_ = a;
			output_callback_ = NULL;
		}
	}
}

void
PipeProducer::produce_error(void)
{
	ASSERT(!error_);
	ASSERT(!output_eos_);

	error_ = true;
	output_buffer_.clear();

	if (output_callback_ != NULL) {
		ASSERT(output_action_ == NULL);

		Action *a = output_do(output_callback_);
		if (a != NULL) {
			output_action_ = a;
			output_callback_ = NULL;
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix unfinished output<commit_after><|endoftext|>


<commit_before>
#include "firebasepush.hh"
#include <iostream>
#include <string.h>
#include <flexisip/logmanager.hh>

using namespace std;
using namespace flexisip;

FirebasePushNotificationRequest::FirebasePushNotificationRequest(const PushInfo &pinfo)
: PushNotificationRequest(pinfo.mAppId, "firebase") {
	const string &deviceToken = pinfo.mDeviceToken;
	const string &apiKey = pinfo.mApiKey;
	ostringstream httpBody;
	string date = getPushTimeStamp();

	httpBody << "{\"to\":\"" << deviceToken << "\", \"priority\":\"high\"" << ", \"uuid\":" << quoteStringIfNeeded(pinfo.mUid)
		<< ", \"send-time\":\"" << date << "\"}";
	mHttpBody = httpBody.str();
	LOGD("Push notification https post body is %s", mHttpBody.c_str());

	ostringstream httpHeader;
	httpHeader << "POST /fcm/send "
	"HTTP/1.1\r\nHost:fcm.googleapis.com\r\nContent-Type:application/json\r\nAuthorization:key="
	<< apiKey << "\r\nContent-Length:" << httpBody.str().size() << "\r\n\r\n";
	mHttpHeader = httpHeader.str();
	SLOGD << "PNR " << this << " https post header is " << mHttpHeader;
}

void FirebasePushNotificationRequest::createPushNotification() {
	int headerLength = mHttpHeader.length();
	int bodyLength = mHttpBody.length();

	mBuffer.clear();
	mBuffer.resize(headerLength + bodyLength);

	char *binaryMessageBuff = &mBuffer[0];
	char *binaryMessagePt = binaryMessageBuff;

	memcpy(binaryMessagePt, &mHttpHeader[0], headerLength);
	binaryMessagePt += headerLength;

	memcpy(binaryMessagePt, &mHttpBody[0], bodyLength);
	binaryMessagePt += bodyLength;
}

const vector<char> &FirebasePushNotificationRequest::getData() {
	createPushNotification();
	return mBuffer;
}

string FirebasePushNotificationRequest::isValidResponse(const string &str) {
	static const char expected[] = "HTTP/1.1 200";
	return strncmp(expected, str.c_str(), sizeof(expected) - 1) == 0 ? "" : "Unexpected HTTP response value (not 200 OK)";
}
<commit_msg>Add call-id parameter into firebase notifications, similarly to what we do already for apple push notifications.<commit_after>
#include "firebasepush.hh"
#include <iostream>
#include <string.h>
#include <flexisip/logmanager.hh>

using namespace std;
using namespace flexisip;

FirebasePushNotificationRequest::FirebasePushNotificationRequest(const PushInfo &pinfo)
: PushNotificationRequest(pinfo.mAppId, "firebase") {
	const string &deviceToken = pinfo.mDeviceToken;
	const string &apiKey = pinfo.mApiKey;
	ostringstream httpBody;
	string date = getPushTimeStamp();

	httpBody << "{\"to\":\"" << deviceToken << "\", \"priority\":\"high\"" << ", \"uuid\":" << quoteStringIfNeeded(pinfo.mUid)
		<< ", \"call-id\":" << quoteStringIfNeeded(pinfo.mCallId)
		<< ", \"send-time\":\"" << date << "\"}";
	mHttpBody = httpBody.str();
	LOGD("Push notification https post body is %s", mHttpBody.c_str());

	ostringstream httpHeader;
	httpHeader << "POST /fcm/send "
	"HTTP/1.1\r\nHost:fcm.googleapis.com\r\nContent-Type:application/json\r\nAuthorization:key="
	<< apiKey << "\r\nContent-Length:" << httpBody.str().size() << "\r\n\r\n";
	mHttpHeader = httpHeader.str();
	SLOGD << "PNR " << this << " https post header is " << mHttpHeader;
}

void FirebasePushNotificationRequest::createPushNotification() {
	int headerLength = mHttpHeader.length();
	int bodyLength = mHttpBody.length();

	mBuffer.clear();
	mBuffer.resize(headerLength + bodyLength);

	char *binaryMessageBuff = &mBuffer[0];
	char *binaryMessagePt = binaryMessageBuff;

	memcpy(binaryMessagePt, &mHttpHeader[0], headerLength);
	binaryMessagePt += headerLength;

	memcpy(binaryMessagePt, &mHttpBody[0], bodyLength);
	binaryMessagePt += bodyLength;
}

const vector<char> &FirebasePushNotificationRequest::getData() {
	createPushNotification();
	return mBuffer;
}

string FirebasePushNotificationRequest::isValidResponse(const string &str) {
	static const char expected[] = "HTTP/1.1 200";
	return strncmp(expected, str.c_str(), sizeof(expected) - 1) == 0 ? "" : "Unexpected HTTP response value (not 200 OK)";
}
<|endoftext|>


<commit_before><commit_msg>MIPS64: Fix asm_store_imm64.<commit_after><|endoftext|>


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

#include "ipc/ipc_message_utils.h"

#include "base/file_path.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/nullable_string16.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#if defined(OS_POSIX)
#include "ipc/file_descriptor_set_posix.h"
#endif
#include "ipc/ipc_channel_handle.h"

namespace IPC {

const int kMaxRecursionDepth = 100;

// Value serialization

static bool ReadValue(const Message* m, void** iter, Value** value,
                      int recursion);

static void WriteValue(Message* m, const Value* value, int recursion) {
  if (recursion > kMaxRecursionDepth) {
    LOG(WARNING) << "Max recursion depth hit in WriteValue.";
    return;
  }

  m->WriteInt(value->GetType());

  switch (value->GetType()) {
    case Value::TYPE_NULL:
    break;
    case Value::TYPE_BOOLEAN: {
      bool val;
      value->GetAsBoolean(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_INTEGER: {
      int val;
      value->GetAsInteger(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_DOUBLE: {
      double val;
      value->GetAsDouble(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_STRING: {
      std::string val;
      value->GetAsString(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_BINARY: {
      const BinaryValue* binary = static_cast<const BinaryValue*>(value);
      m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
      break;
    }
    case Value::TYPE_DICTIONARY: {
      const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);

      WriteParam(m, static_cast<int>(dict->size()));

      for (DictionaryValue::key_iterator it = dict->begin_keys();
           it != dict->end_keys(); ++it) {
        Value* subval;
        if (dict->GetWithoutPathExpansion(*it, &subval)) {
          WriteParam(m, *it);
          WriteValue(m, subval, recursion + 1);
        } else {
          NOTREACHED() << "DictionaryValue iterators are filthy liars.";
        }
      }
      break;
    }
    case Value::TYPE_LIST: {
      const ListValue* list = static_cast<const ListValue*>(value);
      WriteParam(m, static_cast<int>(list->GetSize()));
      for (size_t i = 0; i < list->GetSize(); ++i) {
        Value* subval;
        if (list->Get(i, &subval)) {
          WriteValue(m, subval, recursion + 1);
        } else {
          NOTREACHED() << "ListValue::GetSize is a filthy liar.";
        }
      }
      break;
    }
  }
}

// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
// object.
static bool ReadDictionaryValue(const Message* m, void** iter,
                                DictionaryValue* value, int recursion) {
  int size;
  if (!ReadParam(m, iter, &size))
    return false;

  for (int i = 0; i < size; ++i) {
    std::string key;
    Value* subval;
    if (!ReadParam(m, iter, &key) ||
        !ReadValue(m, iter, &subval, recursion + 1))
      return false;
    value->Set(key, subval);
  }

  return true;
}

// Helper for ReadValue that reads a ReadListValue into a pre-allocated
// object.
static bool ReadListValue(const Message* m, void** iter,
                          ListValue* value, int recursion) {
  int size;
  if (!ReadParam(m, iter, &size))
    return false;

  for (int i = 0; i < size; ++i) {
    Value* subval;
    if (!ReadValue(m, iter, &subval, recursion + 1))
      return false;
    value->Set(i, subval);
  }

  return true;
}

static bool ReadValue(const Message* m, void** iter, Value** value,
                      int recursion) {
  if (recursion > kMaxRecursionDepth) {
    LOG(WARNING) << "Max recursion depth hit in ReadValue.";
    return false;
  }

  int type;
  if (!ReadParam(m, iter, &type))
    return false;

  switch (type) {
    case Value::TYPE_NULL:
    *value = Value::CreateNullValue();
    break;
    case Value::TYPE_BOOLEAN: {
      bool val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateBooleanValue(val);
      break;
    }
    case Value::TYPE_INTEGER: {
      int val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateIntegerValue(val);
      break;
    }
    case Value::TYPE_DOUBLE: {
      double val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateDoubleValue(val);
      break;
    }
    case Value::TYPE_STRING: {
      std::string val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateStringValue(val);
      break;
    }
    case Value::TYPE_BINARY: {
      const char* data;
      int length;
      if (!m->ReadData(iter, &data, &length))
        return false;
      *value = BinaryValue::CreateWithCopiedBuffer(data, length);
      break;
    }
    case Value::TYPE_DICTIONARY: {
      scoped_ptr<DictionaryValue> val(new DictionaryValue());
      if (!ReadDictionaryValue(m, iter, val.get(), recursion))
        return false;
      *value = val.release();
      break;
    }
    case Value::TYPE_LIST: {
      scoped_ptr<ListValue> val(new ListValue());
      if (!ReadListValue(m, iter, val.get(), recursion))
        return false;
      *value = val.release();
      break;
    }
    default:
    return false;
  }

  return true;
}

void ParamTraits<int>::Log(const param_type& p, std::string* l) {
  l->append(base::IntToString(p));
}

void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
  l->append(base::UintToString(p));
}

void ParamTraits<long>::Log(const param_type& p, std::string* l) {
  l->append(base::Int64ToString(static_cast<int64>(p)));
}

void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
  l->append(base::Uint64ToString(static_cast<uint64>(p)));
}

void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
  l->append(base::Int64ToString(static_cast<int64>(p)));
}

void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
  l->append(base::Uint64ToString(p));
}

void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
  m->WriteBytes(&p, sizeof(param_type));
}

bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
                                       param_type* r) {
  const char* data;
  if (!m->ReadBytes(iter, &data, sizeof(param_type)))
    return false;
  memcpy(r, data, sizeof(param_type));
  return true;
}

void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
  l->append(base::UintToString(p));
}

void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
  ParamTraits<int64>::Write(m, p.ToInternalValue());
}

bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
                                   param_type* r) {
  int64 value;
  if (!ParamTraits<int64>::Read(m, iter, &value))
    return false;
  *r = base::Time::FromInternalValue(value);
  return true;
}

void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
  ParamTraits<int64>::Log(p.ToInternalValue(), l);
}

void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
  ParamTraits<int64> ::Write(m, p.InMicroseconds());
}

bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
                                         void** iter,
                                         param_type* r) {
  int64 value;
  bool ret = ParamTraits<int64> ::Read(m, iter, &value);
  if (ret)
    *r = base::TimeDelta::FromMicroseconds(value);

  return ret;
}

void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
  ParamTraits<int64> ::Log(p.InMicroseconds(), l);
}

void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
  WriteValue(m, &p, 0);
}

bool ParamTraits<DictionaryValue>::Read(
    const Message* m, void** iter, param_type* r) {
  int type;
  if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
    return false;

  return ReadDictionaryValue(m, iter, r, 0);
}

void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
  std::string json;
  base::JSONWriter::Write(&p, false, &json);
  l->append(json);
}

void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
  WriteValue(m, &p, 0);
}

bool ParamTraits<ListValue>::Read(
    const Message* m, void** iter, param_type* r) {
  int type;
  if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
    return false;

  return ReadListValue(m, iter, r, 0);
}

void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
  std::string json;
  base::JSONWriter::Write(&p, false, &json);
  l->append(json);
}

void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
  l->append(WideToUTF8(p));
}

void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.string());
  WriteParam(m, p.is_null());
}

bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
                                         param_type* r) {
  string16 string;
  if (!ReadParam(m, iter, &string))
    return false;
  bool is_null;
  if (!ReadParam(m, iter, &is_null))
    return false;
  *r = NullableString16(string, is_null);
  return true;
}

void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
  l->append("(");
  LogParam(p.string(), l);
  l->append(", ");
  LogParam(p.is_null(), l);
  l->append(")");
}

#if !defined(WCHAR_T_IS_UTF16)
void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
  l->append(UTF16ToUTF8(p));
}
#endif

void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
  ParamTraits<FilePath::StringType>::Write(m, p.value());
}

bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
  FilePath::StringType value;
  if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
    return false;
  *r = FilePath(value);
  return true;
}

void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
  ParamTraits<FilePath::StringType>::Log(p.value(), l);
}

#if defined(OS_POSIX)
void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
  const bool valid = p.fd >= 0;
  WriteParam(m, valid);

  if (valid) {
    if (!m->WriteFileDescriptor(p))
      NOTREACHED();
  }
}

bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
                                             param_type* r) {
  bool valid;
  if (!ReadParam(m, iter, &valid))
    return false;

  if (!valid) {
    r->fd = -1;
    r->auto_close = false;
    return true;
  }

  return m->ReadFileDescriptor(iter, r);
}

void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
                                            std::string* l) {
  if (p.auto_close) {
    l->append(StringPrintf("FD(%d auto-close)", p.fd));
  } else {
    l->append(StringPrintf("FD(%d)", p.fd));
  }
}
#endif  // defined(OS_POSIX)

void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.name);
#if defined(OS_POSIX)
  WriteParam(m, p.socket);
#endif
}

bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
                                           param_type* r) {
  return ReadParam(m, iter, &r->name)
#if defined(OS_POSIX)
      && ReadParam(m, iter, &r->socket)
#endif
      ;
}

void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
                                          std::string* l) {
  l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
#if defined(OS_POSIX)
  ParamTraits<base::FileDescriptor>::Log(p.socket, l);
#endif
  l->append(")");
}

LogData::LogData() {
}

LogData::~LogData() {
}

void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.channel);
  WriteParam(m, p.routing_id);
  WriteParam(m, static_cast<int>(p.type));
  WriteParam(m, p.flags);
  WriteParam(m, p.sent);
  WriteParam(m, p.receive);
  WriteParam(m, p.dispatch);
  WriteParam(m, p.params);
}

bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
  int type;
  bool result =
      ReadParam(m, iter, &r->channel) &&
      ReadParam(m, iter, &r->routing_id) &&
      ReadParam(m, iter, &type) &&
      ReadParam(m, iter, &r->flags) &&
      ReadParam(m, iter, &r->sent) &&
      ReadParam(m, iter, &r->receive) &&
      ReadParam(m, iter, &r->dispatch) &&
      ReadParam(m, iter, &r->params);
  r->type = static_cast<uint16>(type);
  return result;
}

}  // namespace IPC
<commit_msg>Initialize struct member in LogData.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ipc/ipc_message_utils.h"

#include "base/file_path.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/nullable_string16.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#if defined(OS_POSIX)
#include "ipc/file_descriptor_set_posix.h"
#endif
#include "ipc/ipc_channel_handle.h"

namespace IPC {

const int kMaxRecursionDepth = 100;

// Value serialization

static bool ReadValue(const Message* m, void** iter, Value** value,
                      int recursion);

static void WriteValue(Message* m, const Value* value, int recursion) {
  if (recursion > kMaxRecursionDepth) {
    LOG(WARNING) << "Max recursion depth hit in WriteValue.";
    return;
  }

  m->WriteInt(value->GetType());

  switch (value->GetType()) {
    case Value::TYPE_NULL:
    break;
    case Value::TYPE_BOOLEAN: {
      bool val;
      value->GetAsBoolean(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_INTEGER: {
      int val;
      value->GetAsInteger(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_DOUBLE: {
      double val;
      value->GetAsDouble(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_STRING: {
      std::string val;
      value->GetAsString(&val);
      WriteParam(m, val);
      break;
    }
    case Value::TYPE_BINARY: {
      const BinaryValue* binary = static_cast<const BinaryValue*>(value);
      m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
      break;
    }
    case Value::TYPE_DICTIONARY: {
      const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);

      WriteParam(m, static_cast<int>(dict->size()));

      for (DictionaryValue::key_iterator it = dict->begin_keys();
           it != dict->end_keys(); ++it) {
        Value* subval;
        if (dict->GetWithoutPathExpansion(*it, &subval)) {
          WriteParam(m, *it);
          WriteValue(m, subval, recursion + 1);
        } else {
          NOTREACHED() << "DictionaryValue iterators are filthy liars.";
        }
      }
      break;
    }
    case Value::TYPE_LIST: {
      const ListValue* list = static_cast<const ListValue*>(value);
      WriteParam(m, static_cast<int>(list->GetSize()));
      for (size_t i = 0; i < list->GetSize(); ++i) {
        Value* subval;
        if (list->Get(i, &subval)) {
          WriteValue(m, subval, recursion + 1);
        } else {
          NOTREACHED() << "ListValue::GetSize is a filthy liar.";
        }
      }
      break;
    }
  }
}

// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
// object.
static bool ReadDictionaryValue(const Message* m, void** iter,
                                DictionaryValue* value, int recursion) {
  int size;
  if (!ReadParam(m, iter, &size))
    return false;

  for (int i = 0; i < size; ++i) {
    std::string key;
    Value* subval;
    if (!ReadParam(m, iter, &key) ||
        !ReadValue(m, iter, &subval, recursion + 1))
      return false;
    value->Set(key, subval);
  }

  return true;
}

// Helper for ReadValue that reads a ReadListValue into a pre-allocated
// object.
static bool ReadListValue(const Message* m, void** iter,
                          ListValue* value, int recursion) {
  int size;
  if (!ReadParam(m, iter, &size))
    return false;

  for (int i = 0; i < size; ++i) {
    Value* subval;
    if (!ReadValue(m, iter, &subval, recursion + 1))
      return false;
    value->Set(i, subval);
  }

  return true;
}

static bool ReadValue(const Message* m, void** iter, Value** value,
                      int recursion) {
  if (recursion > kMaxRecursionDepth) {
    LOG(WARNING) << "Max recursion depth hit in ReadValue.";
    return false;
  }

  int type;
  if (!ReadParam(m, iter, &type))
    return false;

  switch (type) {
    case Value::TYPE_NULL:
    *value = Value::CreateNullValue();
    break;
    case Value::TYPE_BOOLEAN: {
      bool val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateBooleanValue(val);
      break;
    }
    case Value::TYPE_INTEGER: {
      int val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateIntegerValue(val);
      break;
    }
    case Value::TYPE_DOUBLE: {
      double val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateDoubleValue(val);
      break;
    }
    case Value::TYPE_STRING: {
      std::string val;
      if (!ReadParam(m, iter, &val))
        return false;
      *value = Value::CreateStringValue(val);
      break;
    }
    case Value::TYPE_BINARY: {
      const char* data;
      int length;
      if (!m->ReadData(iter, &data, &length))
        return false;
      *value = BinaryValue::CreateWithCopiedBuffer(data, length);
      break;
    }
    case Value::TYPE_DICTIONARY: {
      scoped_ptr<DictionaryValue> val(new DictionaryValue());
      if (!ReadDictionaryValue(m, iter, val.get(), recursion))
        return false;
      *value = val.release();
      break;
    }
    case Value::TYPE_LIST: {
      scoped_ptr<ListValue> val(new ListValue());
      if (!ReadListValue(m, iter, val.get(), recursion))
        return false;
      *value = val.release();
      break;
    }
    default:
    return false;
  }

  return true;
}

void ParamTraits<int>::Log(const param_type& p, std::string* l) {
  l->append(base::IntToString(p));
}

void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
  l->append(base::UintToString(p));
}

void ParamTraits<long>::Log(const param_type& p, std::string* l) {
  l->append(base::Int64ToString(static_cast<int64>(p)));
}

void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
  l->append(base::Uint64ToString(static_cast<uint64>(p)));
}

void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
  l->append(base::Int64ToString(static_cast<int64>(p)));
}

void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
  l->append(base::Uint64ToString(p));
}

void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
  m->WriteBytes(&p, sizeof(param_type));
}

bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
                                       param_type* r) {
  const char* data;
  if (!m->ReadBytes(iter, &data, sizeof(param_type)))
    return false;
  memcpy(r, data, sizeof(param_type));
  return true;
}

void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
  l->append(base::UintToString(p));
}

void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
  ParamTraits<int64>::Write(m, p.ToInternalValue());
}

bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
                                   param_type* r) {
  int64 value;
  if (!ParamTraits<int64>::Read(m, iter, &value))
    return false;
  *r = base::Time::FromInternalValue(value);
  return true;
}

void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
  ParamTraits<int64>::Log(p.ToInternalValue(), l);
}

void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
  ParamTraits<int64> ::Write(m, p.InMicroseconds());
}

bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
                                         void** iter,
                                         param_type* r) {
  int64 value;
  bool ret = ParamTraits<int64> ::Read(m, iter, &value);
  if (ret)
    *r = base::TimeDelta::FromMicroseconds(value);

  return ret;
}

void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
  ParamTraits<int64> ::Log(p.InMicroseconds(), l);
}

void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
  WriteValue(m, &p, 0);
}

bool ParamTraits<DictionaryValue>::Read(
    const Message* m, void** iter, param_type* r) {
  int type;
  if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
    return false;

  return ReadDictionaryValue(m, iter, r, 0);
}

void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
  std::string json;
  base::JSONWriter::Write(&p, false, &json);
  l->append(json);
}

void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
  WriteValue(m, &p, 0);
}

bool ParamTraits<ListValue>::Read(
    const Message* m, void** iter, param_type* r) {
  int type;
  if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
    return false;

  return ReadListValue(m, iter, r, 0);
}

void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
  std::string json;
  base::JSONWriter::Write(&p, false, &json);
  l->append(json);
}

void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
  l->append(WideToUTF8(p));
}

void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.string());
  WriteParam(m, p.is_null());
}

bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
                                         param_type* r) {
  string16 string;
  if (!ReadParam(m, iter, &string))
    return false;
  bool is_null;
  if (!ReadParam(m, iter, &is_null))
    return false;
  *r = NullableString16(string, is_null);
  return true;
}

void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
  l->append("(");
  LogParam(p.string(), l);
  l->append(", ");
  LogParam(p.is_null(), l);
  l->append(")");
}

#if !defined(WCHAR_T_IS_UTF16)
void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
  l->append(UTF16ToUTF8(p));
}
#endif

void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
  ParamTraits<FilePath::StringType>::Write(m, p.value());
}

bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
  FilePath::StringType value;
  if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
    return false;
  *r = FilePath(value);
  return true;
}

void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
  ParamTraits<FilePath::StringType>::Log(p.value(), l);
}

#if defined(OS_POSIX)
void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
  const bool valid = p.fd >= 0;
  WriteParam(m, valid);

  if (valid) {
    if (!m->WriteFileDescriptor(p))
      NOTREACHED();
  }
}

bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
                                             param_type* r) {
  bool valid;
  if (!ReadParam(m, iter, &valid))
    return false;

  if (!valid) {
    r->fd = -1;
    r->auto_close = false;
    return true;
  }

  return m->ReadFileDescriptor(iter, r);
}

void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
                                            std::string* l) {
  if (p.auto_close) {
    l->append(StringPrintf("FD(%d auto-close)", p.fd));
  } else {
    l->append(StringPrintf("FD(%d)", p.fd));
  }
}
#endif  // defined(OS_POSIX)

void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.name);
#if defined(OS_POSIX)
  WriteParam(m, p.socket);
#endif
}

bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
                                           param_type* r) {
  return ReadParam(m, iter, &r->name)
#if defined(OS_POSIX)
      && ReadParam(m, iter, &r->socket)
#endif
      ;
}

void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
                                          std::string* l) {
  l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
#if defined(OS_POSIX)
  ParamTraits<base::FileDescriptor>::Log(p.socket, l);
#endif
  l->append(")");
}

LogData::LogData()
    : routing_id(0),
      type(0),
      sent(0),
      receive(0),
      dispatch(0) {
}

LogData::~LogData() {
}

void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
  WriteParam(m, p.channel);
  WriteParam(m, p.routing_id);
  WriteParam(m, static_cast<int>(p.type));
  WriteParam(m, p.flags);
  WriteParam(m, p.sent);
  WriteParam(m, p.receive);
  WriteParam(m, p.dispatch);
  WriteParam(m, p.params);
}

bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
  int type = -1;
  bool result =
      ReadParam(m, iter, &r->channel) &&
      ReadParam(m, iter, &r->routing_id) &&
      ReadParam(m, iter, &type) &&
      ReadParam(m, iter, &r->flags) &&
      ReadParam(m, iter, &r->sent) &&
      ReadParam(m, iter, &r->receive) &&
      ReadParam(m, iter, &r->dispatch) &&
      ReadParam(m, iter, &r->params);
  r->type = static_cast<uint16>(type);
  return result;
}

}  // namespace IPC
<|endoftext|>


<commit_before>#include "ssh.hh"

namespace nix {

SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD)
    : host(host)
    , fakeSSH(host == "localhost")
    , keyFile(keyFile)
    , sshPublicHostKey(sshPublicHostKey)
    , useMaster(useMaster && !fakeSSH)
    , compress(compress)
    , logFD(logFD)
{
    if (host == "" || hasPrefix(host, "-"))
        throw Error("invalid SSH host name '%s'", host);

    auto state(state_.lock());
    state->tmpDir = std::make_unique<AutoDelete>(createTempDir("", "nix", true, true, 0700));
}

void SSHMaster::addCommonSSHOpts(Strings & args)
{
    auto state(state_.lock());

    for (auto & i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS").value_or("")))
        args.push_back(i);
    if (!keyFile.empty())
        args.insert(args.end(), {"-i", keyFile});
    if (!sshPublicHostKey.empty()) {
        Path fileName = (Path) *state->tmpDir + "/host-key";
        auto p = host.rfind("@");
        std::string thost = p != std::string::npos ? std::string(host, p + 1) : host;
        writeFile(fileName, thost + " " + base64Decode(sshPublicHostKey) + "\n");
        args.insert(args.end(), {"-oUserKnownHostsFile=" + fileName});
    }
    if (compress)
        args.push_back("-C");
}

std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string & command)
{
    Path socketPath = startMaster();

    Pipe in, out;
    in.create();
    out.create();

    auto conn = std::make_unique<Connection>();
    ProcessOptions options;
    options.dieWithParent = false;

    conn->sshPid = startProcess([&]() {
        restoreProcessContext();

        close(in.writeSide.get());
        close(out.readSide.get());

        if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
            throw SysError("duping over stdin");
        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");
        if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
            throw SysError("duping over stderr");

        Strings args;

        if (fakeSSH) {
            args = { "bash", "-c" };
        } else {
            args = { "ssh", host.c_str(), "-x", "-a" };
            addCommonSSHOpts(args);
            if (socketPath != "")
                args.insert(args.end(), {"-S", socketPath});
            if (verbosity >= lvlChatty)
                args.push_back("-v");
        }

        args.push_back(command);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        // could not exec ssh/bash
        throw SysError("unable to execute '%s'", args.front());
    }, options);

    in.readSide = -1;
    out.writeSide = -1;

    conn->out = std::move(out.readSide);
    conn->in = std::move(in.writeSide);

    return conn;
}

Path SSHMaster::startMaster()
{
    if (!useMaster) return "";

    auto state(state_.lock());

    if (state->sshMaster != -1) return state->socketPath;

    state->socketPath = (Path) *state->tmpDir + "/ssh.sock";

    Pipe out;
    out.create();

    ProcessOptions options;
    options.dieWithParent = false;

    state->sshMaster = startProcess([&]() {
        restoreProcessContext();

        close(out.readSide.get());

        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");

        Strings args =
            { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath
            , "-o", "LocalCommand=echo started"
            , "-o", "PermitLocalCommand=yes"
            };
        if (verbosity >= lvlChatty)
            args.push_back("-v");
        addCommonSSHOpts(args);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        throw SysError("unable to execute '%s'", args.front());
    }, options);

    out.writeSide = -1;

    std::string reply;
    try {
        reply = readLine(out.readSide.get());
    } catch (EndOfFile & e) { }

    if (reply != "started")
        throw Error("failed to start SSH master connection to '%s'", host);

    return state->socketPath;
}

}
<commit_msg>Defer to SSH config files for ForwardAgent option<commit_after>#include "ssh.hh"

namespace nix {

SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD)
    : host(host)
    , fakeSSH(host == "localhost")
    , keyFile(keyFile)
    , sshPublicHostKey(sshPublicHostKey)
    , useMaster(useMaster && !fakeSSH)
    , compress(compress)
    , logFD(logFD)
{
    if (host == "" || hasPrefix(host, "-"))
        throw Error("invalid SSH host name '%s'", host);

    auto state(state_.lock());
    state->tmpDir = std::make_unique<AutoDelete>(createTempDir("", "nix", true, true, 0700));
}

void SSHMaster::addCommonSSHOpts(Strings & args)
{
    auto state(state_.lock());

    for (auto & i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS").value_or("")))
        args.push_back(i);
    if (!keyFile.empty())
        args.insert(args.end(), {"-i", keyFile});
    if (!sshPublicHostKey.empty()) {
        Path fileName = (Path) *state->tmpDir + "/host-key";
        auto p = host.rfind("@");
        std::string thost = p != std::string::npos ? std::string(host, p + 1) : host;
        writeFile(fileName, thost + " " + base64Decode(sshPublicHostKey) + "\n");
        args.insert(args.end(), {"-oUserKnownHostsFile=" + fileName});
    }
    if (compress)
        args.push_back("-C");
}

std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string & command)
{
    Path socketPath = startMaster();

    Pipe in, out;
    in.create();
    out.create();

    auto conn = std::make_unique<Connection>();
    ProcessOptions options;
    options.dieWithParent = false;

    conn->sshPid = startProcess([&]() {
        restoreProcessContext();

        close(in.writeSide.get());
        close(out.readSide.get());

        if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
            throw SysError("duping over stdin");
        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");
        if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
            throw SysError("duping over stderr");

        Strings args;

        if (fakeSSH) {
            args = { "bash", "-c" };
        } else {
            args = { "ssh", host.c_str(), "-x" };
            addCommonSSHOpts(args);
            if (socketPath != "")
                args.insert(args.end(), {"-S", socketPath});
            if (verbosity >= lvlChatty)
                args.push_back("-v");
        }

        args.push_back(command);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        // could not exec ssh/bash
        throw SysError("unable to execute '%s'", args.front());
    }, options);

    in.readSide = -1;
    out.writeSide = -1;

    conn->out = std::move(out.readSide);
    conn->in = std::move(in.writeSide);

    return conn;
}

Path SSHMaster::startMaster()
{
    if (!useMaster) return "";

    auto state(state_.lock());

    if (state->sshMaster != -1) return state->socketPath;

    state->socketPath = (Path) *state->tmpDir + "/ssh.sock";

    Pipe out;
    out.create();

    ProcessOptions options;
    options.dieWithParent = false;

    state->sshMaster = startProcess([&]() {
        restoreProcessContext();

        close(out.readSide.get());

        if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
            throw SysError("duping over stdout");

        Strings args =
            { "ssh", host.c_str(), "-M", "-N", "-S", state->socketPath
            , "-o", "LocalCommand=echo started"
            , "-o", "PermitLocalCommand=yes"
            };
        if (verbosity >= lvlChatty)
            args.push_back("-v");
        addCommonSSHOpts(args);
        execvp(args.begin()->c_str(), stringsToCharPtrs(args).data());

        throw SysError("unable to execute '%s'", args.front());
    }, options);

    out.writeSide = -1;

    std::string reply;
    try {
        reply = readLine(out.readSide.get());
    } catch (EndOfFile & e) { }

    if (reply != "started")
        throw Error("failed to start SSH master connection to '%s'", host);

    return state->socketPath;
}

}
<|endoftext|>


<commit_before><commit_msg>Fix 'else' style nit.<commit_after><|endoftext|>


<commit_before><commit_msg>Updated todo<commit_after><|endoftext|>


<commit_before><commit_msg>Fix Android compilation<commit_after><|endoftext|>


<commit_before>#include <Game.h>

void Game::Start(void) {
  if(_game_state != Unintialized)
    return;   //Doesn't throw error because program exits

  //Game runs at fixed resolution of 1024x768
  _main_window.create(sf::VideoMode(1024, 768, 32), "Cell Defense!");

  _game_state = Game::ShowingSplash;

  while(!isExiting()) {
    gameLoop();
  }

  _main_window.close();
}

bool Game::isExiting() {
  if(_game_state == Game::Exiting)
    return true;
  else
    return false;
}

void Game::gameLoop() {
  sf::Event current_event;
  while(_main_window.pollEvent(current_event)) {
    switch(_game_state) {
      case Game::ShowingMenu: {
        showMenu();
        break;
      }
      case Game::ShowingSplash: {
        showSplashScreen();
        break;
      }
      case Game::Playing: {
        sf::Event current_event;
        while(_main_window.pollEvent(current_event)) {
          _main_window.clear(sf::Color(0, 0, 0));
          _main_window.display();

          if(current_event.type == sf::Event::Closed) {
            _game_state = Game::Exiting;
          }

          if(current_event.type == sf::Event::KeyPressed) {
            if(current_event.key.code == sf::Keyboard::Key::Escape) showMenu(); }
        }
      break;
      }
    }
  }
}

void Game::showSplashScreen() {
  SplashScreen splash_screen;
  splash_screen.show(_main_window);
  _game_state = Game::ShowingMenu;
}

void Game::showMenu() {
  MainMenu main_menu;
  MainMenu::MenuAction action = main_menu.show(_main_window);

  switch(action) {
    case MainMenu::Exit:
      _game_state = Game::Exiting;
      break;
    case MainMenu::Play:
      _game_state = Game::Playing;
      break;
  }
}

Game::GameState Game::_game_state = Unintialized;
sf::RenderWindow Game::_main_window;<commit_msg>Fixed something in Game::gameLoop<commit_after>#include <Game.h>

void Game::Start(void) {
  if(_game_state != Unintialized)
    return;   //Doesn't throw error because program exits

  //Game runs at fixed resolution of 1024x768
  _main_window.create(sf::VideoMode(1024, 768, 32), "Cell Defense!");

  _game_state = Game::ShowingSplash;

  while(!isExiting()) {
    gameLoop();
  }

  _main_window.close();
}

bool Game::isExiting() {
  if(_game_state == Game::Exiting)
    return true;
  else
    return false;
}

void Game::gameLoop() {
  switch(_game_state) {
    case Game::ShowingMenu: {
      showMenu();
      break;
    }
    case Game::ShowingSplash: {
      showSplashScreen();
      break;
    }
    case Game::Playing: {
      sf::Event current_event;
      while(_main_window.pollEvent(current_event)) {
        _main_window.clear(sf::Color(0, 0, 0));
        _main_window.display();

        if(current_event.type == sf::Event::Closed) {
          _game_state = Game::Exiting;
        }

        if(current_event.type == sf::Event::KeyPressed) {
          if(current_event.key.code == sf::Keyboard::Key::Escape) showMenu(); }
      }
    break;
    }
  }
}

void Game::showSplashScreen() {
  SplashScreen splash_screen;
  splash_screen.show(_main_window);
  _game_state = Game::ShowingMenu;
}

void Game::showMenu() {
  MainMenu main_menu;
  MainMenu::MenuAction action = main_menu.show(_main_window);

  switch(action) {
    case MainMenu::Exit:
      _game_state = Game::Exiting;
      break;
    case MainMenu::Play:
      _game_state = Game::Playing;
      break;
  }
}

Game::GameState Game::_game_state = Unintialized;
sf::RenderWindow Game::_main_window;<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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

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

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

*/

#include <boost/version.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<commit_msg>added missing include<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

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

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

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

*/

#include <boost/version.hpp>
#include <boost/bind.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<|endoftext|>


<commit_before>#ifndef _ad03a310_3d97_4841_a98d_7b7a65870185
#define _ad03a310_3d97_4841_a98d_7b7a65870185

#include "optional.hpp"

namespace fn {

namespace fn_ {

struct chained
{
    chained(): prev(this), next(this) {}

    chained(chained& o):
        prev(&o),
        next(o.next)
    {
        prev->next = this;
        next->prev = this;
    }

    chained(chained&& o):
        prev(o.prev),
        next(o.next)
    {
        prev->next = this;
        next->prev = this;
        o.prev = &o;
        o.next = &o;
    }

    ~chained()
    {
        prev->next = next;
        next->prev = prev;
    }

    template<typename F>
    void for_all(F f)
    {
        auto cur = this;
        do {
            f(*cur);
            cur = cur->next;
        } while(cur != this);
    }

    size_t count()
    {
        size_t c = 0;
        for_all([&](chained&){ ++c; });
        return c;
    }

    chained* prev;
    chained* next;
};

}

template<typename T> struct ref;

template<typename T>
struct shared
{
    explicit shared(T const& value): value(value) { }

    shared(shared&& o): value(fn_::move(o.value)), refs(fn_::move(o.refs))
    {
        refs >>[this](ref<T>& refs) {
            refs.retarget(this->value);
        };
        o.refs = {};
    }

    shared(shared const&) = delete;
    shared& operator=(shared const&) = delete;

    shared& operator=(T const& v)
    {
        value = v;
        return *this;
    }

    ~shared()
    {
        refs >>[this](ref<T>& refs) {
            refs.invalidate();
        };
    }

    operator T& () { return value; }

private:
    T value;

    friend struct ref<T>;
    optional<ref<T>&> refs;
};

template<typename T>
struct ref : public fn_::chained, public optional<T&>
{
    ref() {}
    ref(shared<T>& o): optional<T&>(o.value)
    {
        o.refs = *this;
    }

private:
    friend struct shared<T>;
    void retarget(T& value)
    {
        for_all([&](fn_::chained& x){
            auto& r = static_cast<ref&>(x);
            static_cast<optional<T&>&>(r) = value;
        });
    }

    void invalidate()
    {
        for_all([](fn_::chained& x){
            auto& r = static_cast<ref&>(x);
            static_cast<optional<T&>&>(r) = {};
        });
    }
};

}

#endif
<commit_msg>make things private<commit_after>#ifndef _ad03a310_3d97_4841_a98d_7b7a65870185
#define _ad03a310_3d97_4841_a98d_7b7a65870185

#include "optional.hpp"

namespace fn {

namespace fn_ {

struct chained
{
    chained(): prev(this), next(this) {}

    chained(chained& o):
        prev(&o),
        next(o.next)
    {
        prev->next = this;
        next->prev = this;
    }

    chained(chained&& o):
        prev(o.prev),
        next(o.next)
    {
        prev->next = this;
        next->prev = this;
        o.prev = &o;
        o.next = &o;
    }

    ~chained()
    {
        prev->next = next;
        next->prev = prev;
    }

    template<typename F>
    void for_all(F f)
    {
        auto cur = this;
        do {
            f(*cur);
            cur = cur->next;
        } while(cur != this);
    }

    size_t count()
    {
        size_t c = 0;
        for_all([&](chained&){ ++c; });
        return c;
    }

private:
    chained* prev;
    chained* next;
};

}

template<typename T> struct ref;

template<typename T>
struct shared
{
    explicit shared(T const& value): value(value) { }

    shared(shared&& o): value(fn_::move(o.value)), refs(fn_::move(o.refs))
    {
        refs >>[this](ref<T>& refs) {
            refs.retarget(this->value);
        };
        o.refs = {};
    }

    shared(shared const&) = delete;
    shared& operator=(shared const&) = delete;

    shared& operator=(T const& v)
    {
        value = v;
        return *this;
    }

    ~shared()
    {
        refs >>[this](ref<T>& refs) {
            refs.invalidate();
        };
    }

    operator T& () { return value; }

private:
    T value;

    friend struct ref<T>;
    optional<ref<T>&> refs;
};

template<typename T>
struct ref : private fn_::chained, public optional<T&>
{
    ref() {}
    ref(shared<T>& o): optional<T&>(o.value)
    {
        o.refs = *this;
    }

private:
    friend struct shared<T>;
    void retarget(T& value)
    {
        for_all([&](fn_::chained& x){
            auto& r = static_cast<ref&>(x);
            static_cast<optional<T&>&>(r) = value;
        });
    }

    void invalidate()
    {
        for_all([](fn_::chained& x){
            auto& r = static_cast<ref&>(x);
            static_cast<optional<T&>&>(r) = {};
        });
    }
};

}

#endif
<|endoftext|>