Merge pull request #335 from albmed/stable

Stable
This commit is contained in:
Kai Philipp authored and GitHub committed 2017-08-02 14:18:29 +02:00
commit 0b4d0e334c
133 files changed
+6832 -2225

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@ Linux:
- libgsasl version >= 1.4 --> http://www.gnu.org/software/gsasl/
- libboost_thread, libboost_filesystem, libboost_datetime, libboost_program_options,
libboost_iostreams, libboost_asio, libboost_regex, libboost_random, libboost_uuid
(version >= 1.44, latest always recommended) --> http://www.boost.org/
(version >= 1.49, latest always recommended) --> http://www.boost.org/
- libSDL_mixer, libSDL --> http://www.libsdl.org/
- libSQLite3 --> http://sqlite.org/
- libtinyxml > 2.0 --> http://www.sourceforge.net/projects/tinyxml
+2 -2
View File
@@ -9,8 +9,8 @@
# of binary-size if you leave Qt out.
# (see http://trolltech.com/developer/downloads/qt/mac)
QT_FW_PATH="/Developer/Qt5/5/clang_64/lib"
QT_PLUGIN_PATH="/Developer/Qt5/5/clang_64/plugins"
QT_FW_PATH="/Users/$USER/Qt/5.9/clang_64/lib"
QT_PLUGIN_PATH="/Users/$USER/Qt/5.9/clang_64/plugins"
SDL_FW_PATH="/Library/Frameworks"
APPLICATION="./pokerth.app"
BINARY="$APPLICATION/Contents/MacOs/pokerth"
Executable → Regular
View File
File mode changed.
+26
View File
@@ -0,0 +1,26 @@
# QMake pro-file for PokerTH
!c++11 {
system( $$QMAKE_CXX -dumpversion | grep -e "^6.[0-9]" > /dev/null ) {
greaterThan(QT_MAJOR_VERSION, 5) | equals(QT_MAJOR_VERSION, 5) {
CONFIG += c++11
}
else {
equals(QT_MAJOR_VERSION, 4) : greaterThan(QT_MINOR_VERSION, 7) {
CONFIG += "c++11"
QMAKE_CXXFLAGS += "-std=gnu++11"
}
else {
error (QT must be greater and 4.8+)
}
}
}
}
c++11 {
!system( $$QMAKE_CXX -dumpversion | grep -e "^6.[0-9]" > /dev/null ) {
equals(QT_MAJOR_VERSION, 4) : greaterThan(QT_MINOR_VERSION, 7) {
QMAKE_CXXFLAGS += "-std=gnu++11"
}
}
}
+4 -1
View File
@@ -17,6 +17,9 @@ DEFINES += ENABLE_IPV6 TIXML_USE_STL
QT -= core gui
#PRECOMPILED_HEADER = src/pch_lib.h
# Check for c++11
include(pokerth_common.pro)
INCLUDEPATH += . \
src
@@ -57,7 +60,7 @@ mac{
CONFIG += x86_64
CONFIG -= x86
CONFIG -= ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_CXXFLAGS -= -std=gnu++0x
# for universal-compilation on PPC-Mac uncomment the following line
+3
View File
@@ -14,6 +14,9 @@ OBJECTS_DIR = obj
QT -= core \
gui
# Check for c++11
include(pokerth_common.pro)
# PRECOMPILED_HEADER = dbofficial/pch_lib.h
INCLUDEPATH += . \
./src
+46 -14
View File
@@ -26,6 +26,9 @@ DEFINES += ENABLE_IPV6 TIXML_USE_STL BOOST_FILESYSTEM_DEPRECATED
DEFINES += PREFIX=\"$${PREFIX}\"
TARGET = pokerth
# Check for c++11
include(pokerth_common.pro)
# PRECOMPILED_HEADER = src/pch_game.h
android{
@@ -427,6 +430,8 @@ unix:!mac {
boost_system-mt
BOOST_RANDOM = boost_random \
boost_random-mt
BOOST_CHRONO = boost_chrono \
boost_chrono-mt
# searching in $PREFIX/lib, $PREFIX/lib64 and $$system(qmake -query QT_INSTALL_LIBS)
# to override the default '/usr' pass PREFIX
@@ -482,15 +487,37 @@ unix:!mac {
message("Found $$lib")
BOOST_SYS = -l$$lib
}
!c++11 {
for(lib, BOOST_CHRONO):exists($${dir}/lib$${lib}.so*) {
message("Found $$lib")
BOOST_CHRONO = -l$$lib
}
for(lib, BOOST_CHRONO):exists($${dir}/lib$${lib}.a) {
message("Found $$lib")
BOOST_CHRONO = -l$$lib
}
}
}
!android{
BOOST_LIBS = $$BOOST_THREAD \
c++11 {
BOOST_LIBS = $$BOOST_THREAD \
$$BOOST_FS \
$$BOOST_IOSTREAMS \
$$BOOST_REGEX \
$$BOOST_RANDOM \
$$BOOST_SYS
!count(BOOST_LIBS, 6):error("Unable to find boost libraries in PREFIX=$${PREFIX}")
}
!c++11 {
BOOST_LIBS = $$BOOST_THREAD \
$$BOOST_FS \
$$BOOST_IOSTREAMS \
$$BOOST_REGEX \
$$BOOST_RANDOM \
$$$$BOOST_SYS \
$$BOOST_CHRONO
!count(BOOST_LIBS, 7):error("Unable to find boost libraries in PREFIX=$${PREFIX}")
}
if($$system(sdl-config --version)):error("sdl-config not found in PATH - libSDL_mixer, libSDL are required!")
UNAME = $$system(uname -s)
BSD = $$find(UNAME, "BSD")
@@ -549,7 +576,7 @@ mac {
CONFIG += x86_64
CONFIG -= x86
CONFIG -= ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_CXXFLAGS -= -std=gnu++0x
# workaround for problems with boost_filesystem exceptions
@@ -561,19 +588,18 @@ mac {
LIBPATH += lib
# QT dynamic linked framework (see also mac_post_make.sh)
LIBS += -F /Library/Frameworks
LIBS += -framework \
QtCore
LIBS += -framework \
QtGui
# SDL and SDL_mixer come as frameworks
LIBS += -framework \
SDL
LIBS += -framework \
SDL_mixer
LIBS += -framework \
SDL
LIBS += -framework \
SDL_mixer
# make sure you have an x86_64 version of boost
LIBS += /usr/local/lib/libboost_thread.a
LIBS += /usr/local/lib/libboost_thread-mt.a
LIBS += /usr/local/lib/libboost_filesystem.a
LIBS += /usr/local/lib/libboost_regex.a
LIBS += /usr/local/lib/libboost_random.a
@@ -589,15 +615,21 @@ mac {
-lprotobuf \
-lz \
-framework \
Carbon
Cocoa
# set the application icon
RC_FILE = pokerth.icns
LIBPATH += /Developer/SDKs/MacOSX10.6.sdk/usr/lib
INCLUDEPATH += /Developer/SDKs/MacOSX10.6.sdk/usr/include/
INCLUDEPATH += /Library/Frameworks/SDL.framework/Headers
INCLUDEPATH += /Library/Frameworks/SDL_mixer.framework/Headers
LIBPATH += /usr/local/lib
LIBPATH += /usr/local/opt/openssl/lib
LIBPATH += /usr/local/opt/tinyxml/lib
LIBPATH += /usr/local/opt/protobuf/lib
INCLUDEPATH += /usr/local/include
INCLUDEPATH += /usr/local/opt/openssl/include
INCLUDEPATH += /usr/local/opt/tinyxml/include
INCLUDEPATH += /usr/local/opt/protobuf/include
INCLUDEPATH += /Library/Frameworks/SDL.framework/Headers
INCLUDEPATH += /Library/Frameworks/SDL_mixer.framework/Headers
}
OTHER_FILES += docs/infomessage-id-desc.txt
official_server {
+8 -5
View File
@@ -17,6 +17,9 @@ DEFINES += ENABLE_IPV6 TIXML_USE_STL BOOST_FILESYSTEM_DEPRECATED
QT -= core gui
#PRECOMPILED_HEADER = src/pch_lib.h
# Check for c++11
include(pokerth_common.pro)
INCLUDEPATH += . \
src \
src/engine \
@@ -291,17 +294,17 @@ mac{
CONFIG += x86_64
CONFIG -= x86
CONFIG -= ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_CXXFLAGS -= -std=gnu++0x
# for universal-compilation on PPC-Mac uncomment the following line
# on Intel-Mac you have to comment this line out or build will fail.
# QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk/
INCLUDEPATH += /Developer/SDKs/MacOSX10.6.sdk/usr/include/
INCLUDEPATH += /Library/Frameworks/SDL.framework/Headers
INCLUDEPATH += /Library/Frameworks/SDL_mixer.framework/Headers
LIBPATH += /usr/local/opt/openssl/lib
INCLUDEPATH += /usr/local/opt/openssl/include
INCLUDEPATH += /usr/local/include
INCLUDEPATH += /Library/Frameworks/SDL.framework/Headers
INCLUDEPATH += /Library/Frameworks/SDL_mixer.framework/Headers
}
android{
+4 -1
View File
@@ -17,6 +17,9 @@ QT -= core \
gui
# PRECOMPILED_HEADER = src/pch_lib.h
# Check for c++11
include(pokerth_common.pro)
INCLUDEPATH += . \
src
DEPENDPATH += . \
@@ -49,7 +52,7 @@ mac {
CONFIG += x86_64
CONFIG -= x86
CONFIG -= ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
# for universal-compilation on PPC-Mac uncomment the following line
# on Intel-Mac you have to comment this line out or build will fail.
+27 -5
View File
@@ -19,6 +19,9 @@ DEFINES += PREFIX=\"$${PREFIX}\"
QT -= core gui
#PRECOMPILED_HEADER = src/pch_lib.h
# Check for c++11
include(pokerth_common.pro)
INCLUDEPATH += . \
src \
src/engine \
@@ -185,6 +188,7 @@ unix : !mac {
BOOST_SYS = boost_system boost_system-mt
BOOST_REGEX = boost_regex boost_regex-mt
BOOST_RANDOM = boost_random boost_random-mt
BOOST_CHRONO = boost_chrono boost_chrono-mt
#
# searching in $PREFIX/lib, $PREFIX/lib64 and $$system(qmake -query QT_INSTALL_LIBS)
@@ -249,11 +253,29 @@ unix : !mac {
message("Found $$lib")
BOOST_SYS = -l$$lib
}
!c++11 {
for(lib, BOOST_CHRONO):exists($${dir}/lib$${lib}.so*) {
message("Found $$lib")
BOOST_CHRONO = -l$$lib
}
for(lib, BOOST_CHRONO):exists($${dir}/lib$${lib}.a) {
message("Found $$lib")
BOOST_CHRONO = -l$$lib
}
}
}
}
BOOST_LIBS = $$BOOST_THREAD $$BOOST_FS $$BOOST_PROGRAM_OPTIONS $$BOOST_IOSTREAMS $$BOOST_REGEX $$BOOST_RANDOM $$BOOST_SYS
!count(BOOST_LIBS, 7){
error("Unable to find boost libraries in PREFIX=$${PREFIX}")
c++11 {
BOOST_LIBS = $$BOOST_THREAD $$BOOST_FS $$BOOST_PROGRAM_OPTIONS $$BOOST_IOSTREAMS $$BOOST_REGEX $$BOOST_RANDOM $$BOOST_SYS
!count(BOOST_LIBS, 7){
error("Unable to find boost libraries in PREFIX=$${PREFIX}")
}
}
!c++11 {
BOOST_LIBS = $$BOOST_THREAD $$BOOST_FS $$BOOST_PROGRAM_OPTIONS $$BOOST_IOSTREAMS $$BOOST_REGEX $$BOOST_RANDOM $$BOOST_SYS $$BOOST_CHRONO
!count(BOOST_LIBS, 8){
error("Unable to find boost libraries in PREFIX=$${PREFIX}")
}
}
UNAME = $$system(uname -s)
@@ -288,7 +310,7 @@ mac {
CONFIG += x86_64
CONFIG -= x86
CONFIG -= ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_CXXFLAGS -= -std=gnu++0x
# workaround for problems with boost_filesystem exceptions
@@ -300,7 +322,7 @@ mac {
LIBPATH += lib
# make sure you have an x86_64 version of boost
LIBS += /usr/local/lib/libboost_thread.a
LIBS += /usr/local/lib/libboost_thread-mt.a
LIBS += /usr/local/lib/libboost_filesystem.a
LIBS += /usr/local/lib/libboost_regex.a
LIBS += /usr/local/lib/libboost_random.a
+6 -5
View File
@@ -482,11 +482,11 @@ ServerDBThread::EstablishDBConnection()
if (!prepareNick.exec() || !prepareAvatarBlacklist.exec() || !prepareLogin.exec() || !prepareCreateGame.exec()
|| !prepareEndGame.exec() || !prepareRelation.exec() || !prepareScore.exec() || !prepareReportAvatar.exec()
|| !prepareReportGame.exec() || !prepareAdminPlayer.exec() || !prepareBlockPlayer.exec()) {
string tmpError = string(prepareNick.error()) + prepareAvatarBlacklist.error() + prepareLogin.error() + prepareCreateGame.error() +
prepareEndGame.error() + prepareRelation.error() + prepareScore.error() + prepareReportAvatar.error() +
prepareReportGame.error() + prepareAdminPlayer.error() + prepareBlockPlayer.error();
m_connData->conn.disconnect();
m_ioService->post(boost::bind(&ServerDBCallback::ConnectFailed, &m_callback,
string(prepareNick.error()) + prepareAvatarBlacklist.error() + prepareLogin.error() + prepareCreateGame.error()
+ prepareEndGame.error() + prepareRelation.error() + prepareScore.error() + prepareReportAvatar.error()
+ prepareReportGame.error() + prepareAdminPlayer.error() + prepareBlockPlayer.error()));
m_ioService->post(boost::bind(&ServerDBCallback::ConnectFailed, &m_callback, tmpError));
m_permanentError = true;
} else {
m_ioService->post(boost::bind(&ServerDBCallback::ConnectSuccess, &m_callback));
@@ -537,8 +537,9 @@ ServerDBThread::HandleNextQuery()
++i;
}
if (!paramQuery.exec()) {
string tmpError = paramQuery.error();
m_connData->conn.disconnect();
m_ioService->post(boost::bind(&ServerDBCallback::QueryError, &m_callback, paramQuery.error()));
m_ioService->post(boost::bind(&ServerDBCallback::QueryError, &m_callback, tmpError));
break;
}
}
+1 -1
View File
@@ -46,7 +46,7 @@
#define POKERTH_VERSION ((POKERTH_VERSION_MAJOR << 8) | POKERTH_VERSION_MINOR)
#define POKERTH_BETA_REVISION 0
#define POKERTH_BETA_RELEASE_STRING "1.1.1"
#define POKERTH_BETA_RELEASE_STRING "1.1.2"
#define SQLITE_LOG_VERSION 1
+1 -1
View File
@@ -35,7 +35,7 @@
#ifdef ANDROID
#ifndef ANDROID_TEST
#include "QtGui/5.2.0/QtGui/qpa/qplatformnativeinterface.h"
#include "QtGui/5.7.1/QtGui/qpa/qplatformnativeinterface.h"
#include <jni.h>
#endif
#endif
@@ -275,6 +275,9 @@ int gameLobbyDialogImpl::exec()
registeredUserMode();
}
// Bug #320: https://github.com/pokerth/pokerth/issues/320
myChat->refreshIgnoreList();
#ifdef ANDROID
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
#endif
+1 -1
View File
@@ -69,7 +69,7 @@
#ifdef ANDROID
#ifndef ANDROID_TEST
#include "QtGui/5.2.0/QtGui/qpa/qplatformnativeinterface.h"
#include "QtGui/5.7.1/QtGui/qpa/qplatformnativeinterface.h"
#include <jni.h>
#endif
#endif
+7
View File
@@ -73,3 +73,10 @@ bool MyActionButton::event(QEvent *event)
}
return QWidget::event(event);
}
void MyActionButton::click()
{
if (!eatMyEvents) {
QPushButton::click();
}
}
+3
View File
@@ -60,6 +60,9 @@ public:
}
bool event(QEvent *e);
public slots:
void click();
private:
QString fKeyText;
+13 -3
View File
@@ -156,9 +156,14 @@ void MyAvatarLabel::setPlayerRating(QString playerInfo)
std::list<std::string> result;
std::string separator="(!#$%)";
std::list<std::string>::iterator iterator;
// Bug #319: https://github.com/pokerth/pokerth/issues/319
QString playerName = playerInfoList.at(0);
playerName = QUrl::fromPercentEncoding(playerName.toUtf8());
for(iterator = tipsList.begin(); iterator != tipsList.end(); ++iterator) {
tipInfo=QString::fromUtf8(iterator->c_str()).split("(!#$%)", QString::KeepEmptyParts, Qt::CaseSensitive);
if(tipInfo.at(0)==playerInfoList.at(0)) {
if(tipInfo.at(0)==playerName) {
result.push_back(tipInfo.at(0).toUtf8().constData()+separator+tipInfo.at(1).toUtf8().constData()+separator+playerInfoList.at(1).toUtf8().constData()+separator);
found=1;
} else {
@@ -166,7 +171,7 @@ void MyAvatarLabel::setPlayerRating(QString playerInfo)
}
}
if(found==0) {
result.push_back(playerInfoList.at(0).toUtf8().constData()+separator+separator+playerInfoList.at(1).toUtf8().constData()+separator);
result.push_back(playerName.toUtf8().constData()+separator+separator+playerInfoList.at(1).toUtf8().constData()+separator);
}
myW->getMyConfig()->writeConfigStringList("PlayerTooltips", result);
myW->getMyConfig()->writeBuffer();
@@ -224,7 +229,12 @@ void MyAvatarLabel::refreshStars()
for(int i=1; i<=5; i++)myW->playerStarsArray[i][seatPlace]->setText("");
if(myW->myStartWindow->getSession()->getGameType() == Session::GAME_TYPE_INTERNET && !myW->getSession()->getClientPlayerInfo((*it_c)->getMyUniqueID()).isGuest && (*it_c)->getMyType() != PLAYER_TYPE_COMPUTER) {
if((*it_c)->getMyStayOnTableStatus() == true && (*it_c)->getMyName()!="" && seatPlace!=0) {
int playerStars=getPlayerRating(QString::fromUtf8((*it_c)->getMyName().c_str()));
// Bug #319: https://github.com/pokerth/pokerth/issues/319
QString playerName = QString::fromUtf8((*it_c)->getMyName().c_str());
int playerStars=getPlayerRating(playerName);
playerName = QString(QUrl::toPercentEncoding(playerName));
for(int i=1; i<=5; i++) {
myW->playerStarsArray[i][seatPlace]->setText("<a style='color: #"+myW->getMyGameTableStyle()->getRatingStarsColor()+"; "+fontFamily+" font-size: "+fontSize+"px; text-decoration: none;' href='"+QString::fromUtf8((*it_c)->getMyName().c_str())+"\""+QString::number(i)+"'>&#9734;</a>");
}
+12 -2
View File
@@ -92,11 +92,21 @@ void MyNameLabel::setText ( const QString &t, bool trans, bool guest, bool compu
} else {
linkString = QString("http://pokerth.net/redirect_user_profile.php?nick="+QUrl::toPercentEncoding(t));
}
// truncate nicknames longer than 10 characters
QString t2 = t;
if(t2.size() > 10){
int chop = t.size() - 10 - 3;
t2.chop(chop);
t2.append("...");
}
QString tTruncated;
if(trans) {
text = "<a style='color: rgba("+red+", "+green+", "+blue+", 80);' href='"+linkString+"'>"+t+"</a>";
text = "<a style='color: rgba("+red+", "+green+", "+blue+", 80);' href='"+linkString+"'>"+t2+"</a>";
} else {
text = "<a style='color: #"+myW->getMyGameTableStyle()->getPlayerNickTextColor()+";' href='"+linkString+"'>"+t+"</a>";
text = "<a style='color: #"+myW->getMyGameTableStyle()->getPlayerNickTextColor()+";' href='"+linkString+"'>"+t2+"</a>";
}
} else {
+13 -1
View File
@@ -61,7 +61,7 @@
#ifdef ANDROID
#ifndef ANDROID_TEST
#include "QtGui/5.2.0/QtGui/qpa/qplatformnativeinterface.h"
#include "QtGui/5.7.1/QtGui/qpa/qplatformnativeinterface.h"
#include <jni.h>
#endif
#endif
@@ -774,12 +774,24 @@ void startWindowImpl::networkError(int errorID, int /*osErrorID*/)
QMessageBox::Close);
}
break;
case ERR_SOCK_CONNECT_IPV6_FAILED: {
MyMessageBox::warning(this, tr("Network Error"),
tr("Could not connect to the server.\n\nPlease note: IPv6 is enabled in the settings. The connection fails if your provider does not support IPv6.\nThis may be fixed by unchecking the \"Use IPv6\" checkbox in the settings."),
QMessageBox::Close);
}
break;
case ERR_SOCK_CONNECT_TIMEOUT: {
MyMessageBox::warning(this, tr("Network Error"),
tr("Connection timed out.\nPlease check the server address.\n\nIf the server is behind a NAT-Router, make sure port forwarding has been set up on server side."),
QMessageBox::Close);
}
break;
case ERR_SOCK_CONNECT_IPV6_TIMEOUT: {
MyMessageBox::warning(this, tr("Network Error"),
tr("Connection timed out.\nPlease check the server address.\n\nPlease note: IPv6 is enabled in the settings. The connection fails if your provider does not support IPv6.\nThis may be fixed by unchecking the \"Use IPv6\" checkbox in the settings."),
QMessageBox::Close);
}
break;
case ERR_SOCK_SELECT_FAILED: {
MyMessageBox::warning(this, tr("Network Error"),
tr("Internal network error: \"select\" failed."),
+4 -3
View File
@@ -35,6 +35,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <string>
#include <algorithm>
@@ -218,7 +219,7 @@ protected:
ClientState &GetState();
void SetState(ClientState &newState);
boost::asio::deadline_timer &GetStateTimer();
boost::asio::steady_timer &GetStateTimer();
SenderHelper &GetSender();
@@ -341,8 +342,8 @@ private:
mutable boost::mutex m_pingDataMutex;
PingData m_pingData;
boost::asio::deadline_timer m_stateTimer;
boost::asio::deadline_timer m_avatarTimer;
boost::asio::steady_timer m_stateTimer;
boost::asio::steady_timer m_avatarTimer;
friend class AbstractClientStateReceiving;
friend class ClientStateInit;
+26 -11
View File
@@ -60,6 +60,12 @@
using namespace std;
using namespace boost::filesystem;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
#define CLIENT_WAIT_TIMEOUT_MSEC 50
#define CLIENT_CONNECT_TIMEOUT_SEC 10
@@ -238,7 +244,7 @@ void
ClientStateDownloadingServerList::Enter(boost::shared_ptr<ClientThread> client)
{
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateDownloadingServerList::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -265,7 +271,7 @@ ClientStateDownloadingServerList::TimerLoop(const boost::system::error_code& ec,
client->SetState(ClientStateReadingServerList::Instance());
} else {
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateDownloadingServerList::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -409,7 +415,7 @@ void
ClientStateWaitChooseServer::Enter(boost::shared_ptr<ClientThread> client)
{
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateWaitChooseServer::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -432,7 +438,7 @@ ClientStateWaitChooseServer::TimerLoop(const boost::system::error_code& ec, boos
client->SetState(ClientStateStartResolve::Instance());
} else {
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateWaitChooseServer::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -461,7 +467,7 @@ void
ClientStateStartConnect::Enter(boost::shared_ptr<ClientThread> client)
{
client->GetStateTimer().expires_from_now(
boost::posix_time::seconds(CLIENT_CONNECT_TIMEOUT_SEC));
seconds(CLIENT_CONNECT_TIMEOUT_SEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateStartConnect::TimerTimeout, this, boost::asio::placeholders::error, client));
@@ -511,7 +517,11 @@ ClientStateStartConnect::HandleConnect(const boost::system::error_code& ec, boos
client));
} else {
if (ec != boost::asio::error::operation_aborted) {
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, ec.value());
if (client->GetContext().GetAddrFamily() == AF_INET6) {
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_IPV6_FAILED, ec.value());
} else {
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_FAILED, ec.value());
}
}
}
}
@@ -523,7 +533,12 @@ ClientStateStartConnect::TimerTimeout(const boost::system::error_code& ec, boost
if (!ec && &client->GetState() == this) {
boost::system::error_code ec;
client->GetContext().GetSessionData()->GetAsioSocket()->close(ec);
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_TIMEOUT, 0);
if (client->GetContext().GetAddrFamily() == AF_INET6) {
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_IPV6_TIMEOUT, 0);
}
else {
throw ClientException(__FILE__, __LINE__, ERR_SOCK_CONNECT_TIMEOUT, 0);
}
}
}
@@ -986,7 +1001,7 @@ void
ClientStateWaitEnterLogin::Enter(boost::shared_ptr<ClientThread> client)
{
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateWaitEnterLogin::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -1065,7 +1080,7 @@ ClientStateWaitEnterLogin::TimerLoop(const boost::system::error_code& ec, boost:
}
} else {
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateWaitEnterLogin::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -1399,7 +1414,7 @@ void
ClientStateSynchronizeStart::Enter(boost::shared_ptr<ClientThread> client)
{
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateSynchronizeStart::TimerLoop, this, boost::asio::placeholders::error, client));
@@ -1429,7 +1444,7 @@ ClientStateSynchronizeStart::TimerLoop(const boost::system::error_code& ec, boos
client->SetState(ClientStateWaitStart::Instance());
} else {
client->GetStateTimer().expires_from_now(
boost::posix_time::milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
milliseconds(CLIENT_WAIT_TIMEOUT_MSEC));
client->GetStateTimer().async_wait(
boost::bind(
&ClientStateSynchronizeStart::TimerLoop, this, boost::asio::placeholders::error, client));
+9 -3
View File
@@ -66,6 +66,12 @@ using namespace std;
using namespace boost::filesystem;
using boost::asio::ip::tcp;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager, Log *myLog)
: m_ioService(new boost::asio::io_service), m_clientLog(myLog), m_curState(NULL), m_gui(gui),
m_avatarManager(avatarManager), m_isServerSelected(false),
@@ -586,7 +592,7 @@ void
ClientThread::RegisterTimers()
{
m_avatarTimer.expires_from_now(
boost::posix_time::milliseconds(CLIENT_AVATAR_LOOP_MSEC));
milliseconds(CLIENT_AVATAR_LOOP_MSEC));
m_avatarTimer.async_wait(
boost::bind(
&ClientThread::TimerCheckAvatarDownloads, shared_from_this(), boost::asio::placeholders::error));
@@ -910,7 +916,7 @@ ClientThread::TimerCheckAvatarDownloads(const boost::system::error_code& ec)
PassAvatarFileToManager(playerId, tmpAvatar);
}
m_avatarTimer.expires_from_now(
boost::posix_time::milliseconds(CLIENT_AVATAR_LOOP_MSEC));
milliseconds(CLIENT_AVATAR_LOOP_MSEC));
m_avatarTimer.async_wait(
boost::bind(
&ClientThread::TimerCheckAvatarDownloads, shared_from_this(), boost::asio::placeholders::error));
@@ -1022,7 +1028,7 @@ ClientThread::SetState(ClientState &newState)
m_curState->Enter(shared_from_this());
}
boost::asio::deadline_timer &
boost::asio::steady_timer &
ClientThread::GetStateTimer()
{
return m_stateTimer;
+12 -6
View File
@@ -49,6 +49,12 @@
using namespace std;
using namespace boost::filesystem;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
ServerAdminBot::ServerAdminBot(boost::shared_ptr<boost::asio::io_service> ioService)
: m_notifyTimeoutMinutes(0), m_notifyIntervalMinutes(0), m_notifyCounter(0),
m_notifyTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::manual_start),
@@ -272,17 +278,17 @@ ServerAdminBot::Run()
if (m_ircAdminThread) {
// Initialise the timers.
m_reconnectTimer.expires_from_now(
boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
m_reconnectTimer.async_wait(
boost::bind(
&ServerAdminBot::ReconnectHandler, shared_from_this(), boost::asio::placeholders::error));
m_notifyLoopTimer.expires_from_now(
boost::posix_time::seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC));
m_notifyLoopTimer.async_wait(
boost::bind(
&ServerAdminBot::NotifyLoop, shared_from_this(), boost::asio::placeholders::error));
m_checkFileTimer.expires_from_now(
boost::posix_time::seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC));
m_checkFileTimer.async_wait(
boost::bind(
&ServerAdminBot::CheckFileHandler, shared_from_this(), boost::asio::placeholders::error));
@@ -298,7 +304,7 @@ ServerAdminBot::ReconnectHandler(const boost::system::error_code& ec)
Reconnect();
m_reconnectTimer.expires_from_now(
boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
m_reconnectTimer.async_wait(
boost::bind(
&ServerAdminBot::ReconnectHandler, shared_from_this(), boost::asio::placeholders::error));
@@ -330,7 +336,7 @@ ServerAdminBot::CheckFileHandler(const boost::system::error_code& ec)
Reconnect();
}
m_checkFileTimer.expires_from_now(
boost::posix_time::seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC));
m_checkFileTimer.async_wait(
boost::bind(
&ServerAdminBot::CheckFileHandler, shared_from_this(), boost::asio::placeholders::error));
@@ -386,7 +392,7 @@ ServerAdminBot::NotifyLoop(const boost::system::error_code& ec)
}
}
m_notifyLoopTimer.expires_from_now(
boost::posix_time::seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC));
m_notifyLoopTimer.async_wait(
boost::bind(
&ServerAdminBot::NotifyLoop, shared_from_this(), boost::asio::placeholders::error));
+12 -7
View File
@@ -34,6 +34,11 @@
using namespace std;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
ServerBanManager::ServerBanManager(boost::shared_ptr<boost::asio::io_service> ioService)
: m_ioService(ioService), m_curBanId(0)
@@ -126,7 +131,7 @@ ServerBanManager::GetBanList(list<string> &list) const
banText << (*i_nick).first << ": (nickStr) - " << (*i_nick).second.nameStr;
if ((*i_nick).second.timer)
banText << " duration: " << (*i_nick).second.timer->expires_from_now().hours() << "h";
banText << " duration: " << duration_cast<hours>((*i_nick).second.timer->expires_from_now()).count() << "h";
list.push_back(banText.str());
++i_nick;
}
@@ -136,7 +141,7 @@ ServerBanManager::GetBanList(list<string> &list) const
ostringstream banText;
banText << (*i_ip).first << ": (IP) - " << (*i_ip).second.ipAddress;
if ((*i_ip).second.timer)
banText << " duration: " << (*i_ip).second.timer->expires_from_now().hours() << "h";
banText << " duration: " << duration_cast<hours>((*i_ip).second.timer->expires_from_now()).count() << "h";
list.push_back(banText.str());
++i_ip;
}
@@ -235,14 +240,14 @@ ServerBanManager::IsBadGameName(const std::string &name) const
return retVal;
}
boost::shared_ptr<boost::asio::deadline_timer>
boost::shared_ptr<boost::asio::steady_timer>
ServerBanManager::InternalRegisterTimedBan(unsigned timerId, unsigned durationHours)
{
boost::shared_ptr<boost::asio::deadline_timer> tmpTimer;
boost::shared_ptr<boost::asio::steady_timer> tmpTimer;
if (durationHours) {
tmpTimer.reset(new boost::asio::deadline_timer(*m_ioService));
tmpTimer.reset(new boost::asio::steady_timer(*m_ioService));
tmpTimer->expires_from_now(
boost::posix_time::hours(durationHours));
hours(durationHours));
tmpTimer->async_wait(
boost::bind(
&ServerBanManager::TimerRemoveBan, shared_from_this(), boost::asio::placeholders::error, timerId, tmpTimer));
@@ -251,7 +256,7 @@ ServerBanManager::InternalRegisterTimedBan(unsigned timerId, unsigned durationHo
}
void
ServerBanManager::TimerRemoveBan(const boost::system::error_code &ec, unsigned banId, boost::shared_ptr<boost::asio::deadline_timer> timer)
ServerBanManager::TimerRemoveBan(const boost::system::error_code &ec, unsigned banId, boost::shared_ptr<boost::asio::steady_timer> timer)
{
if (!ec && timer)
UnBan(banId);
+10 -4
View File
@@ -53,6 +53,12 @@
using namespace std;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
static bool LessThanPlayerHandStartMoney(const boost::shared_ptr<PlayerInterface> p1, const boost::shared_ptr<PlayerInterface> p2)
{
return p1->getMyRoundStartCash() < p2->getMyRoundStartCash();
@@ -276,7 +282,7 @@ ServerGame::TimerVoteKick(const boost::system::error_code &ec)
m_voteKickData.reset();
}
m_voteKickTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
m_voteKickTimer.async_wait(
boost::bind(
&ServerGame::TimerVoteKick, shared_from_this(), boost::asio::placeholders::error));
@@ -515,7 +521,7 @@ ServerGame::InternalAskVoteKick(boost::shared_ptr<SessionData> byWhom, unsigned
SendToAllPlayers(packet, SessionData::Game);
m_voteKickTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
m_voteKickTimer.async_wait(
boost::bind(
&ServerGame::TimerVoteKick, shared_from_this(), boost::asio::placeholders::error));
@@ -1073,13 +1079,13 @@ ServerGame::SetState(ServerGameState &newState)
m_curState->Enter(shared_from_this());
}
boost::asio::deadline_timer &
boost::asio::steady_timer &
ServerGame::GetStateTimer1()
{
return m_stateTimer1;
}
boost::asio::deadline_timer &
boost::asio::steady_timer &
ServerGame::GetStateTimer2()
{
return m_stateTimer2;
+19 -13
View File
@@ -52,6 +52,12 @@
using namespace std;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
//#define POKERTH_SERVER_TEST
#ifdef POKERTH_SERVER_TEST
@@ -575,7 +581,7 @@ ServerGameStateInit::RegisterAdminTimer(boost::shared_ptr<ServerGame> server)
// No admin timeout in LAN or ranking games.
if (server->GetLobbyThread().GetServerMode() != SERVER_MODE_LAN && server->GetGameData().gameType != GAME_TYPE_RANKING) {
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_GAME_ADMIN_TIMEOUT_SEC - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
seconds(SERVER_GAME_ADMIN_TIMEOUT_SEC - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateInit::TimerAdminWarning, this, boost::asio::placeholders::error, server));
@@ -594,7 +600,7 @@ ServerGameStateInit::RegisterAutoStartTimer(boost::shared_ptr<ServerGame> server
// No autostart in LAN games.
if (server->GetLobbyThread().GetServerMode() != SERVER_MODE_LAN) {
server->GetStateTimer2().expires_from_now(
boost::posix_time::seconds(SERVER_AUTOSTART_GAME_DELAY_SEC));
seconds(SERVER_AUTOSTART_GAME_DELAY_SEC));
server->GetStateTimer2().async_wait(
boost::bind(
&ServerGameStateInit::TimerAutoStart, this, boost::asio::placeholders::error, server));
@@ -632,7 +638,7 @@ ServerGameStateInit::TimerAdminWarning(const boost::system::error_code &ec, boos
}
// Start timeout timer.
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
seconds(SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateInit::TimerAdminTimeout, this, boost::asio::placeholders::error, server));
@@ -767,7 +773,7 @@ void
ServerGameStateStartGame::Enter(boost::shared_ptr<ServerGame> server)
{
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_START_GAME_TIMEOUT_SEC));
seconds(SERVER_START_GAME_TIMEOUT_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateStartGame::TimerTimeout, this, boost::asio::placeholders::error, server));
@@ -930,7 +936,7 @@ void
ServerGameStateHand::Enter(boost::shared_ptr<ServerGame> server)
{
server->GetStateTimer1().expires_from_now(
boost::posix_time::milliseconds(SERVER_LOOP_DELAY_MSEC));
milliseconds(SERVER_LOOP_DELAY_MSEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
@@ -1007,7 +1013,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
curGame.getCurrentHand()->setCardsShown(true);
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_SHOW_CARDS_DELAY_SEC));
seconds(SERVER_SHOW_CARDS_DELAY_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerShowCards, this, boost::asio::placeholders::error, server));
@@ -1015,7 +1021,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
SendNewRoundCards(*server, curGame, newRound);
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(GetDealCardsDelaySec(*server)));
seconds(GetDealCardsDelaySec(*server)));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
@@ -1043,7 +1049,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
// If the player is computer controlled, let the engine act.
if (curPlayer->getMyType() == PLAYER_TYPE_COMPUTER) {
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_COMPUTER_ACTION_DELAY_SEC));
seconds(SERVER_COMPUTER_ACTION_DELAY_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerComputerAction, this, boost::asio::placeholders::error, server));
@@ -1054,7 +1060,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
PerformPlayerAction(*server, curPlayer, PLAYER_ACTION_FOLD, 0);
server->GetStateTimer1().expires_from_now(
boost::posix_time::milliseconds(SERVER_LOOP_DELAY_MSEC));
milliseconds(SERVER_LOOP_DELAY_MSEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
@@ -1122,7 +1128,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
// View a dialog for a new game - delayed.
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(SERVER_DELAY_NEXT_GAME_SEC));
seconds(SERVER_DELAY_NEXT_GAME_SEC));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerNextGame, this, boost::asio::placeholders::error, server, winnerPlayer->getMyUniqueID()));
@@ -1141,7 +1147,7 @@ ServerGameStateHand::TimerShowCards(const boost::system::error_code &ec, boost::
SendNewRoundCards(*server, curGame, curGame.getCurrentHand()->getCurrentRound());
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(GetDealCardsDelaySec(*server)));
seconds(GetDealCardsDelaySec(*server)));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
@@ -1512,7 +1518,7 @@ ServerGameStateWaitPlayerAction::Enter(boost::shared_ptr<ServerGame> server)
int timeoutSec = server->GetGameData().playerActionTimeoutSec + SERVER_PLAYER_TIMEOUT_ADD_DELAY_SEC;
#endif
server->GetStateTimer1().expires_from_now(boost::posix_time::seconds(timeoutSec));
server->GetStateTimer1().expires_from_now(seconds(timeoutSec));
server->GetStateTimer1().async_wait(
boost::bind(
&ServerGameStateWaitPlayerAction::TimerTimeout, this, boost::asio::placeholders::error, server));
@@ -1646,7 +1652,7 @@ ServerGameStateWaitNextHand::Enter(boost::shared_ptr<ServerGame> server)
#endif
server->GetStateTimer1().expires_from_now(
boost::posix_time::seconds(timeoutSec));
seconds(timeoutSec));
server->GetStateTimer1().async_wait(
boost::bind(
+8 -2
View File
@@ -45,6 +45,12 @@
using namespace std;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
ServerLobbyBot::ServerLobbyBot(boost::shared_ptr<boost::asio::io_service> ioService)
: m_reconnectTimer(*ioService)
{
@@ -110,7 +116,7 @@ ServerLobbyBot::Run()
if (m_ircLobbyThread) {
// Initialise the reconnect timer.
m_reconnectTimer.expires_from_now(
boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
m_reconnectTimer.async_wait(
boost::bind(
&ServerLobbyBot::Reconnect, shared_from_this(), boost::asio::placeholders::error));
@@ -132,7 +138,7 @@ ServerLobbyBot::Reconnect(const boost::system::error_code& ec)
}
}
m_reconnectTimer.expires_from_now(
boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
m_reconnectTimer.async_wait(
boost::bind(
&ServerLobbyBot::Reconnect, shared_from_this(), boost::asio::placeholders::error));
+11 -6
View File
@@ -95,6 +95,11 @@
using namespace std;
using boost::asio::ip::tcp;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
class InternalServerCallback : public SessionDataCallback, public ChatCleanerCallback, public ServerDBCallback
{
@@ -860,19 +865,19 @@ ServerLobbyThread::RegisterTimers()
{
// Remove closed games.
m_removeGameTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_REMOVE_GAME_INTERVAL_MSEC));
milliseconds(SERVER_REMOVE_GAME_INTERVAL_MSEC));
m_removeGameTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerRemoveGame, shared_from_this(), boost::asio::placeholders::error));
// Update the statistics file.
m_saveStatisticsTimer.expires_from_now(
boost::posix_time::seconds(SERVER_SAVE_STATISTICS_INTERVAL_SEC));
seconds(SERVER_SAVE_STATISTICS_INTERVAL_SEC));
m_saveStatisticsTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerSaveStatisticsFile, shared_from_this(), boost::asio::placeholders::error));
// Update the avatar upload locks.
m_loginLockTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_UPDATE_LOGIN_LOCK_INTERVAL_MSEC));
milliseconds(SERVER_UPDATE_LOGIN_LOCK_INTERVAL_MSEC));
m_loginLockTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerUpdateClientLoginLock, shared_from_this(), boost::asio::placeholders::error));
@@ -1872,7 +1877,7 @@ ServerLobbyThread::TimerRemoveGame(const boost::system::error_code &ec)
}
// Restart timer
m_removeGameTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_REMOVE_GAME_INTERVAL_MSEC));
milliseconds(SERVER_REMOVE_GAME_INTERVAL_MSEC));
m_removeGameTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerRemoveGame, shared_from_this(), boost::asio::placeholders::error));
@@ -1897,7 +1902,7 @@ ServerLobbyThread::TimerUpdateClientLoginLock(const boost::system::error_code &e
}
// Restart timer
m_loginLockTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_UPDATE_LOGIN_LOCK_INTERVAL_MSEC));
milliseconds(SERVER_UPDATE_LOGIN_LOCK_INTERVAL_MSEC));
m_loginLockTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerUpdateClientLoginLock, shared_from_this(), boost::asio::placeholders::error));
@@ -2244,7 +2249,7 @@ ServerLobbyThread::TimerSaveStatisticsFile(const boost::system::error_code &ec)
}
// Restart timer
m_saveStatisticsTimer.expires_from_now(
boost::posix_time::seconds(SERVER_SAVE_STATISTICS_INTERVAL_SEC));
seconds(SERVER_SAVE_STATISTICS_INTERVAL_SEC));
m_saveStatisticsTimer.async_wait(
boost::bind(
&ServerLobbyThread::TimerSaveStatisticsFile, shared_from_this(), boost::asio::placeholders::error));
+16 -5
View File
@@ -41,6 +41,12 @@
using namespace std;
using boost::asio::ip::tcp;
#ifdef BOOST_ASIO_HAS_STD_CHRONO
using namespace std::chrono;
#else
using namespace boost::chrono;
#endif
SessionData::SessionData(boost::shared_ptr<boost::asio::ip::tcp::socket> sock, SessionId id, SessionDataCallback &cb, boost::asio::io_service &ioService)
: m_socket(sock), m_id(id), m_state(SessionData::Init), m_readyFlag(false), m_wantsLobbyMsg(true),
m_activityTimeoutSec(0), m_activityWarningRemainingSec(0), m_initTimeoutTimer(ioService), m_globalTimeoutTimer(ioService),
@@ -236,7 +242,7 @@ SessionData::TimerActivityWarning(const boost::system::error_code &ec)
m_callback.SessionTimeoutWarning(shared_from_this(), m_activityWarningRemainingSec);
m_activityTimeoutTimer.expires_from_now(
boost::posix_time::seconds(m_activityWarningRemainingSec));
seconds(m_activityWarningRemainingSec));
m_activityTimeoutTimer.async_wait(
boost::bind(
&SessionData::TimerSessionTimeout, shared_from_this(), boost::asio::placeholders::error));
@@ -312,8 +318,13 @@ void
SessionData::CloseWebSocketHandle()
{
if (m_webData) {
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) // c++11
std::error_code std_ec;
m_webData->webSocketServer->close(m_webData->webHandle, websocketpp::close::status::normal, "PokerTH server closed the connection.", std_ec);
#else
boost::system::error_code ec;
m_webData->webSocketServer->close(m_webData->webHandle, websocketpp::close::status::normal, "PokerTH server closed the connection.", ec);
#endif
}
}
@@ -322,7 +333,7 @@ SessionData::ResetActivityTimer()
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_activityTimeoutTimer.expires_from_now(
boost::posix_time::seconds(m_activityTimeoutSec - m_activityWarningRemainingSec));
seconds(m_activityTimeoutSec - m_activityWarningRemainingSec));
m_activityTimeoutTimer.async_wait(
boost::bind(
&SessionData::TimerActivityWarning, shared_from_this(), boost::asio::placeholders::error));
@@ -333,7 +344,7 @@ SessionData::StartTimerInitTimeout(unsigned timeoutSec)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_initTimeoutTimer.expires_from_now(
boost::posix_time::seconds(timeoutSec));
seconds(timeoutSec));
m_initTimeoutTimer.async_wait(
boost::bind(
&SessionData::TimerInitTimeout, shared_from_this(), boost::asio::placeholders::error));
@@ -344,7 +355,7 @@ SessionData::StartTimerGlobalTimeout(unsigned timeoutSec)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_globalTimeoutTimer.expires_from_now(
boost::posix_time::seconds(timeoutSec));
seconds(timeoutSec));
m_globalTimeoutTimer.async_wait(
boost::bind(
&SessionData::TimerSessionTimeout, shared_from_this(), boost::asio::placeholders::error));
@@ -358,7 +369,7 @@ SessionData::StartTimerActivityTimeout(unsigned timeoutSec, unsigned warningRema
m_activityWarningRemainingSec = warningRemainingSec;
m_activityTimeoutTimer.expires_from_now(
boost::posix_time::seconds(timeoutSec - warningRemainingSec));
seconds(timeoutSec - warningRemainingSec));
m_activityTimeoutTimer.async_wait(
boost::bind(
&SessionData::TimerActivityWarning, shared_from_this(), boost::asio::placeholders::error));
+13 -2
View File
@@ -57,9 +57,14 @@ void
WebSendBuffer::AsyncSendNextPacket(boost::shared_ptr<SessionData> session)
{
if (closeAfterSend) {
boost::system::error_code ec;
boost::shared_ptr<WebSocketData> webData = session->GetWebData();
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
std::error_code std_ec;
webData->webSocketServer->close(webData->webHandle, websocketpp::close::status::normal, "PokerTH server closed the connection.", std_ec);
#else
boost::system::error_code ec;
webData->webSocketServer->close(webData->webHandle, websocketpp::close::status::normal, "PokerTH server closed the connection.", ec);
#endif
}
}
@@ -70,10 +75,16 @@ WebSendBuffer::InternalStorePacket(boost::shared_ptr<SessionData> session, boost
google::protobuf::uint8 *buf = new google::protobuf::uint8[packetSize];
packet->GetMsg()->SerializeWithCachedSizesToArray(buf);
boost::system::error_code ec;
boost::shared_ptr<WebSocketData> webData = session->GetWebData();
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
std::error_code std_ec;
webData->webSocketServer->send(webData->webHandle, string((const char *)buf, packetSize), websocketpp::frame::opcode::BINARY, std_ec);
if (std_ec) {
#else
boost::system::error_code ec;
webData->webSocketServer->send(webData->webHandle, string((const char *)buf, packetSize), websocketpp::frame::opcode::BINARY, ec);
if (ec) {
#endif
SetCloseAfterSend();
}
+4 -2
View File
@@ -49,9 +49,11 @@ public:
virtual void Close();
protected:
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) // c++11
typedef std::map<websocketpp::connection_hdl, boost::weak_ptr<SessionData>, std::owner_less<websocketpp::connection_hdl> > SessionMap;
#else
typedef std::map<websocketpp::connection_hdl, boost::weak_ptr<SessionData> > SessionMap;
#endif
bool validate(websocketpp::connection_hdl hdl);
void on_open(websocketpp::connection_hdl hdl);
void on_close(websocketpp::connection_hdl hdl);
+4 -3
View File
@@ -34,6 +34,7 @@
#define _SERVERADMINBOT_H_
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <third_party/boost/timers.hpp>
@@ -96,9 +97,9 @@ private:
boost::shared_ptr<IrcThread> m_ircAdminThread;
boost::timers::portable::second_timer m_notifyTimer;
boost::asio::deadline_timer m_reconnectTimer;
boost::asio::deadline_timer m_notifyLoopTimer;
boost::asio::deadline_timer m_checkFileTimer;
boost::asio::steady_timer m_reconnectTimer;
boost::asio::steady_timer m_notifyLoopTimer;
boost::asio::steady_timer m_checkFileTimer;
};
#endif
+5 -4
View File
@@ -35,6 +35,7 @@
#include <db/dbdefs.h>
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/regex.hpp>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
@@ -67,12 +68,12 @@ public:
protected:
struct TimedPlayerBan {
boost::shared_ptr<boost::asio::deadline_timer> timer;
boost::shared_ptr<boost::asio::steady_timer> timer;
std::string nameStr;
boost::regex nameRegex;
};
struct TimedIPBan {
boost::shared_ptr<boost::asio::deadline_timer> timer;
boost::shared_ptr<boost::asio::steady_timer> timer;
std::string ipAddress;
};
@@ -81,8 +82,8 @@ protected:
typedef std::list<boost::regex> RegexList;
typedef std::vector<DB_id> DBPlayerIdList;
boost::shared_ptr<boost::asio::deadline_timer> InternalRegisterTimedBan(unsigned timerId, unsigned durationHours);
void TimerRemoveBan(const boost::system::error_code &ec, unsigned banId, boost::shared_ptr<boost::asio::deadline_timer> timer);
boost::shared_ptr<boost::asio::steady_timer> InternalRegisterTimedBan(unsigned timerId, unsigned durationHours);
void TimerRemoveBan(const boost::system::error_code &ec, unsigned banId, boost::shared_ptr<boost::asio::steady_timer> timer);
boost::shared_ptr<boost::asio::io_service> m_ioService;
+6 -5
View File
@@ -34,6 +34,7 @@
#define _SERVERGAME_H_
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio/steady_timer.hpp>
#include <third_party/boost/timers.hpp>
#include <map>
@@ -180,8 +181,8 @@ protected:
ServerGameState &GetState();
void SetState(ServerGameState &newState);
boost::asio::deadline_timer &GetStateTimer1();
boost::asio::deadline_timer &GetStateTimer2();
boost::asio::steady_timer &GetStateTimer1();
boost::asio::steady_timer &GetStateTimer2();
const StartData &GetStartData() const;
void SetStartData(const StartData &startData);
@@ -242,9 +243,9 @@ private:
ConfigFile &m_playerConfig;
unsigned m_gameNum;
unsigned m_curPetitionId;
boost::asio::deadline_timer m_voteKickTimer;
boost::asio::deadline_timer m_stateTimer1;
boost::asio::deadline_timer m_stateTimer2;
boost::asio::steady_timer m_voteKickTimer;
boost::asio::steady_timer m_stateTimer1;
boost::asio::steady_timer m_stateTimer2;
bool m_isNameReported;
friend class ServerLobbyThread;
+2 -1
View File
@@ -34,6 +34,7 @@
#define _SERVERLOBBYBOT_H_
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <string>
#include <list>
@@ -86,7 +87,7 @@ private:
boost::shared_ptr<ServerLobbyThread> m_lobbyThread;
boost::shared_ptr<IrcThread> m_ircLobbyThread;
boost::asio::deadline_timer m_reconnectTimer;
boost::asio::steady_timer m_reconnectTimer;
};
#endif
+4 -3
View File
@@ -34,6 +34,7 @@
#define _SERVERLOBBYTHREAD_H_
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/uuid/uuid_generators.hpp>
@@ -268,9 +269,9 @@ private:
boost::shared_ptr<ChatCleanerManager> m_chatCleanerManager;
boost::shared_ptr<ServerDBInterface> m_database;
boost::asio::deadline_timer m_removeGameTimer;
boost::asio::deadline_timer m_saveStatisticsTimer;
boost::asio::deadline_timer m_loginLockTimer;
boost::asio::steady_timer m_removeGameTimer;
boost::asio::steady_timer m_saveStatisticsTimer;
boost::asio::steady_timer m_loginLockTimer;
boost::uuids::random_generator m_sessionIdGenerator;
+4 -3
View File
@@ -36,6 +36,7 @@
typedef unsigned SessionId;
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <string>
@@ -144,9 +145,9 @@ private:
bool m_wantsLobbyMsg;
unsigned m_activityTimeoutSec;
unsigned m_activityWarningRemainingSec;
boost::asio::deadline_timer m_initTimeoutTimer;
boost::asio::deadline_timer m_globalTimeoutTimer;
boost::asio::deadline_timer m_activityTimeoutTimer;
boost::asio::steady_timer m_initTimeoutTimer;
boost::asio::steady_timer m_globalTimeoutTimer;
boost::asio::steady_timer m_activityTimeoutTimer;
SessionDataCallback &m_callback;
Gsasl_session *m_authSession;
int m_curAuthStep;
+2
View File
@@ -61,6 +61,8 @@
#define ERR_SOCK_TRANSFER_INVALID_URL 26
#define ERR_SOCK_TRANSFER_SELECT_FAILED 27
#define ERR_SOCK_TRANSFER_FAILED 28
#define ERR_SOCK_CONNECT_IPV6_FAILED 29
#define ERR_SOCK_CONNECT_IPV6_TIMEOUT 30
// The following errors are game errors.
#define ERR_NET_VERSION_NOT_SUPPORTED 101
#define ERR_NET_SERVER_MAINTENANCE 102
+1 -1
View File
@@ -1,6 +1,6 @@
Main Library:
Copyright (c) 2013, Peter Thorson. All rights reserved.
Copyright (c) 2014, Peter Thorson. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+35 -13
View File
@@ -45,6 +45,11 @@ static std::string const base64_chars =
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
/// Test whether a character is a valid base64 character
/**
* @param c The character to test
* @return true if c is a valid base64 character
*/
static inline bool is_base64(unsigned char c) {
return (c == 43 || // +
(c >= 47 && c <= 57) || // /-9
@@ -52,17 +57,21 @@ static inline bool is_base64(unsigned char c) {
(c >= 97 && c <= 122)); // a-z
}
inline std::string base64_encode(unsigned char const * bytes_to_encode, unsigned
int in_len)
{
/// Encode a char buffer into a base64 string
/**
* @param input The input data
* @param len The length of input in bytes
* @return A base64 encoded string representing input
*/
inline std::string base64_encode(unsigned char const * input, size_t len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
while (len--) {
char_array_3[i++] = *(input++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
@@ -97,25 +106,38 @@ inline std::string base64_encode(unsigned char const * bytes_to_encode, unsigned
while((i++ < 3)) {
ret += '=';
}
}
}
return ret;
return ret;
}
inline std::string base64_encode(std::string const & data) {
return base64_encode(reinterpret_cast<const unsigned char *>(data.data()),data.size());
/// Encode a string into a base64 string
/**
* @param input The input data
* @return A base64 encoded string representing input
*/
inline std::string base64_encode(std::string const & input) {
return base64_encode(
reinterpret_cast<const unsigned char *>(input.data()),
input.size()
);
}
inline std::string base64_decode(std::string const & encoded_string) {
size_t in_len = encoded_string.size();
/// Decode a base64 encoded string into a string of raw bytes
/**
* @param input The base64 encoded input data
* @return A string representing the decoded raw bytes
*/
inline std::string base64_decode(std::string const & input) {
size_t in_len = input.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
while (in_len-- && ( input[in_] != '=') && is_base64(input[in_])) {
char_array_4[i++] = input[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++) {
char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
+61 -2
View File
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -150,6 +150,21 @@ namespace status {
* illegal on the wire.
*/
static value const tls_handshake = 1015;
/// A generic subprotocol error
/**
* Indicates that a subprotocol error occurred. Typically this involves
* receiving a message that is not formatted as a valid message for the
* subprotocol in use.
*/
static value const subprotocol_error = 3000;
/// A invalid subprotocol data
/**
* Indicates that data was received that violated the specification of the
* subprotocol in use.
*/
static value const invalid_subprotocol_data = 3001;
/// First value in range reserved for future protocol use
static value const rsv_start = 1016;
@@ -199,6 +214,50 @@ namespace status {
code == policy_violation || code == message_too_big ||
code == internal_endpoint_error);
}
/// Return a human readable interpretation of a WebSocket close code
/**
* See https://tools.ietf.org/html/rfc6455#section-7.4 for more details.
*
* @since 0.3.0
*
* @param [in] code The code to look up.
* @return A human readable interpretation of the code.
*/
inline std::string get_string(value code) {
switch (code) {
case normal:
return "Normal close";
case going_away:
return "Going away";
case protocol_error:
return "Protocol error";
case unsupported_data:
return "Unsupported data";
case no_status:
return "No status set";
case abnormal_close:
return "Abnormal close";
case invalid_payload:
return "Invalid payload";
case policy_violation:
return "Policy violoation";
case message_too_big:
return "Message too big";
case extension_required:
return "Extension required";
case internal_endpoint_error:
return "Internal endpoint error";
case tls_handshake:
return "TLS handshake failure";
case subprotocol_error:
return "Generic subprotocol error";
case invalid_subprotocol_data:
return "Invalid subprotocol data";
default:
return "Unknown";
}
}
} // namespace status
/// Type used to convert close statuses between integer and wire representations
@@ -263,7 +322,7 @@ inline status::value extract_code(std::string const & payload, lib::error_code
inline std::string extract_reason(std::string const & payload, lib::error_code
& ec)
{
std::string reason = "";
std::string reason;
ec = lib::error_code();
if (payload.size() > 2) {
+131
View File
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2015, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON 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.
*
*/
#ifndef WEBSOCKETPP_COMMON_ASIO_HPP
#define WEBSOCKETPP_COMMON_ASIO_HPP
// This file goes to some length to preserve compatibility with versions of
// boost older than 1.49 (where the first modern steady_timer timer based on
// boost/std chrono was introduced.
//
// For the versions older than 1.49, the deadline_timer is used instead. this
// brings in dependencies on boost date_time and it has a different interface
// that is normalized by the `lib::asio::is_neg` and `lib::asio::milliseconds`
// wrappers provided by this file.
//
// The primary reason for this continued support is that boost 1.48 is the
// default and not easily changeable version of boost supplied by the package
// manager of popular Linux distributions like Ubuntu 12.04 LTS. Once the need
// for this has passed this should be cleaned up and simplified.
#ifdef ASIO_STANDALONE
#include <asio/version.hpp>
#if (ASIO_VERSION/100000) == 1 && ((ASIO_VERSION/100)%1000) < 8
static_assert(false, "The minimum version of standalone Asio is 1.8.0");
#endif
#include <asio.hpp>
#include <asio/steady_timer.hpp>
#include <websocketpp/common/chrono.hpp>
#else
#include <boost/version.hpp>
// See note above about boost <1.49 compatibility. If we are running on
// boost > 1.48 pull in the steady timer and chrono library
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
#include <boost/asio/steady_timer.hpp>
#include <websocketpp/common/chrono.hpp>
#endif
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#endif
namespace websocketpp {
namespace lib {
#ifdef ASIO_STANDALONE
namespace asio {
using namespace ::asio;
// Here we assume that we will be using std::error_code with standalone
// Asio. This is probably a good assumption, but it is possible in rare
// cases that local Asio versions would be used.
using std::errc;
// See note above about boost <1.49 compatibility. Because we require
// a standalone Asio version of 1.8+ we are guaranteed to have
// steady_timer available. By convention we require the chrono library
// (either boost or std) for use with standalone Asio.
template <typename T>
bool is_neg(T duration) {
return duration.count() < 0;
}
inline lib::chrono::milliseconds milliseconds(long duration) {
return lib::chrono::milliseconds(duration);
}
} // namespace asio
#else
namespace asio {
using namespace boost::asio;
// See note above about boost <1.49 compatibility
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
// Using boost::asio >=1.49 so we use chrono and steady_timer
template <typename T>
bool is_neg(T duration) {
return duration.count() < 0;
}
inline lib::chrono::milliseconds milliseconds(long duration) {
return lib::chrono::milliseconds(duration);
}
#else
// Using boost::asio <1.49 we pretend a deadline timer is a steady
// timer and wrap the negative detection and duration conversion
// appropriately.
typedef boost::asio::deadline_timer steady_timer;
template <typename T>
bool is_neg(T duration) {
return duration.is_negative();
}
inline boost::posix_time::time_duration milliseconds(long duration) {
return boost::posix_time::milliseconds(duration);
}
#endif
using boost::system::error_code;
namespace errc = boost::system::errc;
} // namespace asio
#endif
} // namespace lib
} // namespace websocketpp
#endif // WEBSOCKETPP_COMMON_ASIO_HPP
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2015, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON 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.
*
*/
#ifndef WEBSOCKETPP_COMMON_ASIO_SSL_HPP
#define WEBSOCKETPP_COMMON_ASIO_SSL_HPP
// NOTE: This file must be included before common/asio.hpp
#ifdef ASIO_STANDALONE
#include <asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
#endif
#endif // WEBSOCKETPP_COMMON_ASIO_SSL_HPP
+17 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2015, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,7 +28,20 @@
#ifndef WEBSOCKETPP_COMMON_CHRONO_HPP
#define WEBSOCKETPP_COMMON_CHRONO_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 functional header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
#ifndef _WEBSOCKETPP_CPP11_CHRONO_
#define _WEBSOCKETPP_CPP11_CHRONO_
#endif
#endif
// If we're on Visual Studio 2012 or higher and haven't explicitly disabled
// the use of C++11 chrono header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1700 && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
#ifndef _WEBSOCKETPP_CPP11_CHRONO_
#define _WEBSOCKETPP_CPP11_CHRONO_
#endif
@@ -44,9 +57,9 @@ namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_CHRONO_
using std::chrono::system_clock;
namespace chrono = std::chrono;
#else
using boost::chrono::system_clock;
namespace chrono = boost::chrono;
#endif
} // namespace lib
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,7 +34,7 @@ namespace websocketpp {
/// A handle to uniquely identify a connection.
/**
* This type uniquely identifies a connection. It is implimented as a weak
* This type uniquely identifies a connection. It is implemented as a weak
* pointer to the connection in question. This provides uniqueness across
* multiple endpoints and ensures that IDs never conflict or run out.
*
+71 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -40,10 +40,34 @@
#define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
#endif
// The code below attempts to use information provided by the build system or
// user supplied defines to selectively enable C++11 language and library
// features. In most cases features that are targeted individually may also be
// selectively disabled via an associated _WEBSOCKETPP_NOXXX_ define.
#ifdef _WEBSOCKETPP_CPP11_STL_
// This flag indicates that all of the C++11 language features are available
// to us.
#if defined(_WEBSOCKETPP_CPP11_STL_) || __cplusplus >= 201103L || defined(_WEBSOCKETPP_CPP11_STRICT_)
// This check tests for blanket c++11 coverage. It can be activated in one
// of three ways. Either the compiler itself reports that it is a full
// C++11 compiler via the __cplusplus macro or the user/build system
// supplies one of the two preprocessor defines below:
// This is defined to allow other WebSocket++ common headers to enable
// C++11 features when they are detected by this file rather than
// duplicating the above logic in every common header.
#define _WEBSOCKETPP_CPP11_INTERNAL_
// _WEBSOCKETPP_CPP11_STRICT_
//
// This define reports to WebSocket++ that 100% of the language and library
// features of C++11 are available. Using this define on a non-C++11
// compiler will result in problems.
// _WEBSOCKETPP_CPP11_STL_
//
// This define enables *most* C++11 options that were implemented early on
// by compilers. It is typically used for compilers that have many, but not
// all C++11 features. It should be safe to use on GCC 4.7-4.8 and perhaps
// earlier.
#ifndef _WEBSOCKETPP_NOEXCEPT_TOKEN_
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#endif
@@ -53,7 +77,25 @@
#ifndef _WEBSOCKETPP_INITIALIZER_LISTS_
#define _WEBSOCKETPP_INITIALIZER_LISTS_
#endif
#ifndef _WEBSOCKETPP_NULLPTR_TOKEN_
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
#endif
#ifndef _WEBSOCKETPP_MOVE_SEMANTICS_
#define _WEBSOCKETPP_MOVE_SEMANTICS_
#endif
#ifndef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#define _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#endif
#ifndef __GNUC__
// GCC as of version 4.9 (latest) does not support std::put_time yet.
// so ignore it
#define _WEBSOCKETPP_PUTTIME_
#endif
#else
// In the absence of a blanket define, try to use compiler versions or
// feature testing macros to selectively enable what we can.
// Test for noexcept
#ifndef _WEBSOCKETPP_NOEXCEPT_TOKEN_
#ifdef _WEBSOCKETPP_NOEXCEPT_
@@ -63,6 +105,9 @@
#if __has_feature(cxx_noexcept)
// clang feature detect says we have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#elif defined(_MSC_VER) && _MSC_VER >= 1900
// Visual Studio 2015+ has noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#else
// assume we don't have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_
@@ -79,6 +124,9 @@
#if __has_feature(cxx_constexpr)
// clang feature detect says we have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#elif defined(_MSC_VER) && _MSC_VER >= 1900
// Visual Studio 2015+ has constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#else
// assume we don't have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_
@@ -90,6 +138,25 @@
#if __has_feature(cxx_generalized_initializers) && !defined(_WEBSOCKETPP_INITIALIZER_LISTS_)
#define _WEBSOCKETPP_INITIALIZER_LISTS_
#endif
// Test for nullptr
#ifndef _WEBSOCKETPP_NULLPTR_TOKEN_
#ifdef _WEBSOCKETPP_NULLPTR_
// build system says we have nullptr
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
#else
#if __has_feature(cxx_nullptr)
// clang feature detect says we have nullptr
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
#elif defined(_MSC_VER) &&_MSC_VER >= 1600
// Visual Studio version that has nullptr
#define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr
#else
// assume we don't have nullptr
#define _WEBSOCKETPP_NULLPTR_TOKEN_ 0
#endif
#endif
#endif
#endif
#endif // WEBSOCKETPP_COMMON_CPP11_HPP
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,19 +28,37 @@
#ifndef WEBSOCKETPP_COMMON_FUNCTIONAL_HPP
#define WEBSOCKETPP_COMMON_FUNCTIONAL_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 functional header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
#endif
#endif
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
// the use of C++11 functional header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#include <functional>
#else
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#endif
namespace websocketpp {
namespace lib {
@@ -49,6 +67,18 @@ namespace lib {
using std::bind;
using std::ref;
namespace placeholders = std::placeholders;
// There are some cases where a C++11 compiler balks at using std::ref
// but a C++03 compiler using boost function requires boost::ref. As such
// lib::ref is not useful in these cases. Instead this macro allows the use
// of boost::ref in the case of a boost compile or no reference wrapper at
// all in the case of a C++11 compile
#define _WEBSOCKETPP_REF(x) x
template <typename T>
void clear_function(T & x) {
x = nullptr;
}
#else
using boost::function;
using boost::bind;
@@ -57,6 +87,15 @@ namespace lib {
/// \todo this feels hacky, is there a better way?
using ::_1;
using ::_2;
using ::_3;
}
// See above definition for more details on what this is and why it exists
#define _WEBSOCKETPP_REF(x) boost::ref(x)
template <typename T>
void clear_function(T & x) {
x.clear();
}
#endif
+70 -70
View File
@@ -34,7 +34,7 @@
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
@@ -45,12 +45,12 @@
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
@@ -80,9 +80,9 @@ typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
/* Initialize the algorithm. */
@@ -94,7 +94,7 @@ inline void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes)
/* Finish the message and return the digest. */
inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define ZSW_MD5_BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
@@ -169,8 +169,8 @@ inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) {
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if ZSW_MD5_BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
@@ -183,51 +183,51 @@ static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) {
{
#if ZSW_MD5_BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static int const w = 1;
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static int const w = 1;
if (*((md5_byte_t const *)&w)) /* dynamic little-endian */
if (*((md5_byte_t const *)&w)) /* dynamic little-endian */
#endif
#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (md5_byte_t const *)0) & 3)) {
/* data are properly aligned */
X = (md5_word_t const *)data;
} else {
/* not aligned */
std::memcpy(xbuf, data, 64);
X = xbuf;
}
}
#if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (md5_byte_t const *)0) & 3)) {
/* data are properly aligned */
X = (md5_word_t const *)data;
} else {
/* not aligned */
std::memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if ZSW_MD5_BYTE_ORDER == 0
else /* dynamic big-endian */
else /* dynamic big-endian */
#endif
#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
#if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if ZSW_MD5_BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
@@ -361,71 +361,71 @@ void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes) {
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : static_cast<int>(nbytes));
int copy = (offset + nbytes > 64 ? 64 - offset : static_cast<int>(nbytes));
std::memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
std::memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
md5_process(pms, p);
/* Process a final partial block. */
if (left)
std::memcpy(pms->buf, p, left);
std::memcpy(pms->buf, p, left);
}
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) {
static md5_byte_t const pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
// some convenience c++ functions
inline std::string md5_hash_string(std::string const & s) {
char digest[16];
char digest[16];
md5_state_t state;
md5_state_t state;
md5_init(&state);
md5_append(&state, (md5_byte_t const *)s.c_str(), s.size());
md5_finish(&state, (md5_byte_t *)digest);
md5_init(&state);
md5_append(&state, (md5_byte_t const *)s.c_str(), s.size());
md5_finish(&state, (md5_byte_t *)digest);
std::string ret;
ret.resize(16);
std::copy(digest,digest+16,ret.begin());
return ret;
return ret;
}
const char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+23 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,16 +28,32 @@
#ifndef WEBSOCKETPP_COMMON_MEMORY_HPP
#define WEBSOCKETPP_COMMON_MEMORY_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 memory header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
#define _WEBSOCKETPP_CPP11_MEMORY_
#endif
#endif
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
// the use of C++11 functional header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
#define _WEBSOCKETPP_CPP11_MEMORY_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_MEMORY_
#include <memory>
#else
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/scoped_array.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/pointer_cast.hpp>
@@ -49,15 +65,20 @@ namespace lib {
#ifdef _WEBSOCKETPP_CPP11_MEMORY_
using std::shared_ptr;
using std::weak_ptr;
using std::auto_ptr;
using std::enable_shared_from_this;
using std::static_pointer_cast;
using std::make_shared;
using std::unique_ptr;
typedef std::unique_ptr<unsigned char[]> unique_ptr_uchar_array;
#else
using boost::shared_ptr;
using boost::weak_ptr;
using std::auto_ptr;
using boost::enable_shared_from_this;
using boost::static_pointer_cast;
using boost::make_shared;
typedef boost::scoped_array<unsigned char> unique_ptr_uchar_array;
#endif
+30 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,20 +29,22 @@
#define WEBSOCKETPP_COMMON_NETWORK_HPP
// For ntohs and htons
#if defined(WIN32)
#if defined(_WIN32)
#include <winsock2.h>
#else
//#include <arpa/inet.h>
#include <netinet/in.h>
#endif
#include <websocketpp/common/stdint.hpp>
namespace websocketpp {
namespace lib {
namespace net {
inline bool is_little_endian() {
short int val = 0x1;
char *ptr = (char*)&val;
char *ptr = reinterpret_cast<char *>(&val);
return (ptr[0] == 1);
}
@@ -50,7 +52,18 @@ inline bool is_little_endian() {
#define TYP_SMLE 1
#define TYP_BIGE 2
inline uint64_t htonll(uint64_t src) {
/// Convert 64 bit value to network byte order
/**
* This method is prefixed to avoid conflicts with operating system level
* macros for this functionality.
*
* TODO: figure out if it would be beneficial to use operating system level
* macros for this.
*
* @param src The integer in host byte order
* @return src converted to network byte order
*/
inline uint64_t _htonll(uint64_t src) {
static int typ = TYP_INIT;
unsigned char c;
union {
@@ -71,8 +84,19 @@ inline uint64_t htonll(uint64_t src) {
return x.ull;
}
inline uint64_t ntohll(uint64_t src) {
return htonll(src);
/// Convert 64 bit value to host byte order
/**
* This method is prefixed to avoid conflicts with operating system level
* macros for this functionality.
*
* TODO: figure out if it would be beneficial to use operating system level
* macros for this.
*
* @param src The integer in network byte order
* @return src converted to host byte order
*/
inline uint64_t _ntohll(uint64_t src) {
return _htonll(src);
}
} // net
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,9 +33,14 @@
* don't fit somewhere else better.
*/
#if defined(WIN32) && !defined(NOMINMAX)
#if defined(_WIN32) && !defined(NOMINMAX)
// don't define min and max macros that conflict with std::min and std::max
#define NOMINMAX
#endif
// Bump up the variadic parameter max for Visual Studio 2012
#if defined(_MSC_VER) && _MSC_VER == 1700
#define _VARIADIC_MAX 8
#endif
#endif // WEBSOCKETPP_COMMON_PLATFORMS_HPP
+18 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,12 +28,28 @@
#ifndef WEBSOCKETPP_COMMON_RANDOM_DEVICE_HPP
#define WEBSOCKETPP_COMMON_RANDOM_DEVICE_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_RANDOM_DEVICE_
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 random header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_RANDOM_DEVICE_
#ifndef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#define _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#endif
#endif
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
// the use of C++11 random header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
#define _WEBSOCKETPP_CPP11_MEMORY_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#include <random>
#else
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,7 @@
#define __STDC_LIMIT_MACROS 1
#endif
#if WIN32 && (_MSC_VER < 1600)
#if defined (_WIN32) && defined (_MSC_VER) && (_MSC_VER < 1600)
#include <boost/cstdint.hpp>
using boost::int8_t;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,12 +28,28 @@
#ifndef WEBSOCKETPP_COMMON_SYSTEM_ERROR_HPP
#define WEBSOCKETPP_COMMON_SYSTEM_ERROR_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_SYSTEM_ERROR_
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 system_error header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_SYSTEM_ERROR_
#ifndef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#endif
#endif
// If we're on Visual Studio 2010 or higher and haven't explicitly disabled
// the use of C++11 system_error header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1600 && !defined _WEBSOCKETPP_NO_CPP11_SYSTEM_ERROR_
#ifndef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#include <system_error>
#else
@@ -45,6 +61,7 @@ namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
using std::errc;
using std::error_code;
using std::error_category;
using std::error_condition;
@@ -52,6 +69,7 @@ namespace lib {
#define _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_ namespace std {
#define _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_ }
#else
namespace errc = boost::system::errc;
using boost::system::error_code;
using boost::system::error_category;
using boost::system::error_condition;
+19 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2015, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,7 +28,24 @@
#ifndef WEBSOCKETPP_COMMON_THREAD_HPP
#define WEBSOCKETPP_COMMON_THREAD_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_THREAD_
#include <websocketpp/common/cpp11.hpp>
// If we autodetect C++11 and haven't been explicitly instructed to not use
// C++11 threads, then set the defines that instructs the rest of this header
// to use C++11 <thread> and <mutex>
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_THREAD_
// MinGW by default does not support C++11 thread/mutex so even if the
// internal check for C++11 passes, ignore it if we are on MinGW
#if (!defined(__MINGW32__) && !defined(__MINGW64__))
#ifndef _WEBSOCKETPP_CPP11_THREAD_
#define _WEBSOCKETPP_CPP11_THREAD_
#endif
#endif
#endif
// If we're on Visual Studio 2013 or higher and haven't explicitly disabled
// the use of C++11 thread header then prefer it to boost.
#if defined(_MSC_VER) && _MSC_VER >= 1800 && !defined _WEBSOCKETPP_NO_CPP11_THREAD_
#ifndef _WEBSOCKETPP_CPP11_THREAD_
#define _WEBSOCKETPP_CPP11_THREAD_
#endif
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2014, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON 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.
*
*/
#ifndef WEBSOCKETPP_COMMON_TIME_HPP
#define WEBSOCKETPP_COMMON_TIME_HPP
#include <ctime>
namespace websocketpp {
namespace lib {
// Code in this header was inspired by the following article and includes some
// code from the related project g2log. The g2log code is public domain licensed
// http://kjellkod.wordpress.com/2013/01/22/exploring-c11-part-2-localtime-and-time-again/
/// Thread safe cross platform localtime
inline std::tm localtime(std::time_t const & time) {
std::tm tm_snapshot;
#if (defined(__MINGW32__) || defined(__MINGW64__))
memcpy(&tm_snapshot, ::localtime(&time), sizeof(std::tm));
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
localtime_s(&tm_snapshot, &time);
#else
localtime_r(&time, &tm_snapshot); // POSIX
#endif
return tm_snapshot;
}
} // lib
} // websocketpp
#endif // WEBSOCKETPP_COMMON_TIME_HPP
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2015, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,47 +25,41 @@
*
*/
#ifndef WEBSOCKETPP_ERROR_MESSAGE_HPP
#define WEBSOCKETPP_ERROR_MESSAGE_HPP
#ifndef WEBSOCKETPP_COMMON_TYPE_TRAITS_HPP
#define WEBSOCKETPP_COMMON_TYPE_TRAITS_HPP
#include <websocketpp/common/cpp11.hpp>
// If we've determined that we're in full C++11 mode and the user hasn't
// explicitly disabled the use of C++11 functional header, then prefer it to
// boost.
#if defined _WEBSOCKETPP_CPP11_INTERNAL_ && !defined _WEBSOCKETPP_NO_CPP11_TYPE_TRAITS_
#ifndef _WEBSOCKETPP_CPP11_TYPE_TRAITS_
#define _WEBSOCKETPP_CPP11_TYPE_TRAITS_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_TYPE_TRAITS_
#include <type_traits>
#else
#include <boost/aligned_storage.hpp>
#endif
namespace websocketpp {
namespace lib {
/**
* The transport::security::* classes are a set of security/socket related
* policies and support code for the ASIO transport types.
*/
class error_msg {
public:
const std::string& get_msg() const {
return m_error_msg;
}
void set_msg(const std::string& msg) {
m_error_msg = msg;
}
void append_msg(const std::string& msg) {
m_error_msg.append(msg);
}
template <typename T>
void set_msg(const T& thing) {
std::stringsteam val;
val << thing;
this->set_msg(val.str());
}
template <typename T>
void append_msg(const T& thing) {
std::stringsteam val;
val << thing;
this->append_msg(val.str());
}
private:
// error resources
std::string m_error_msg;
};
#ifdef _WEBSOCKETPP_CPP11_TYPE_TRAITS_
using std::aligned_storage;
using std::is_same;
#else
using boost::aligned_storage;
using boost::is_same;
#endif
} // namespace lib
} // namespace websocketpp
#endif // WEBSOCKETPP_ERROR_MESSAGE_HPP
#endif // WEBSOCKETPP_COMMON_TYPE_TRAITS_HPP
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,26 +29,48 @@
#define WEBSOCKETPP_CONCURRENCY_NONE_HPP
namespace websocketpp {
/// Concurrency handling support
namespace concurrency {
/// Implementation for no-op locking primitives
namespace none_impl {
/// A fake mutex implementation that does nothing
class fake_mutex {
public:
fake_mutex() {}
~fake_mutex() {}
};
/// A fake lock guard implementation that does nothing
class fake_lock_guard {
public:
explicit fake_lock_guard(fake_mutex foo) {}
explicit fake_lock_guard(fake_mutex) {}
~fake_lock_guard() {}
};
} // namespace none_impl
/// Stub Concurrency policy to remove locking in single threaded projects
/// Stub concurrency policy that implements the interface using no-ops.
/**
* This policy documents the concurrency policy interface using no-ops. It can
* be used as a reference or base for building a new concurrency policy. It can
* also be used as is to disable all locking for endpoints used in purely single
* threaded programs.
*/
class none {
public:
/// The type of a mutex primitive
/**
* std::mutex is an example.
*/
typedef none_impl::fake_mutex mutex_type;
/// The type of a scoped/RAII lock primitive.
/**
* The scoped lock constructor should take a mutex_type as a parameter,
* acquire that lock, and release it in its destructor. std::lock_guard is
* an example.
*/
typedef none_impl::fake_lock_guard scoped_lock_type;
};
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,9 +25,9 @@
*
*/
// This header defines WebSocket++ macros for C++11 compatibility based on the Boost.Config library.
// This will correctly configure most target platforms simply by including this header before
// any other WebSocket++ header.
// This header defines WebSocket++ macros for C++11 compatibility based on the
// Boost.Config library. This will correctly configure most target platforms
// simply by including this header before any other WebSocket++ header.
#ifndef WEBSOCKETPP_CONFIG_BOOST_CONFIG_HPP
#define WEBSOCKETPP_CONFIG_BOOST_CONFIG_HPP
@@ -41,7 +41,7 @@
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
#endif
#ifndef BOOST_ASIO_HAS_STD_CHRONO
#ifdef BOOST_ASIO_HAS_STD_CHRONO
#define _WEBSOCKETPP_CPP11_CHRONO_
#endif
@@ -67,5 +67,6 @@
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ BOOST_NOEXCEPT
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ BOOST_CONSTEXPR
// TODO: nullptr support
#endif // WEBSOCKETPP_CONFIG_BOOST_CONFIG_HPP
+25 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -215,6 +215,30 @@ struct core {
*/
static const bool silent_close = false;
/// Default maximum message size
/**
* Default value for the processor's maximum message size. Maximum message size
* determines the point at which the library will fail a connection with the
* message_too_big protocol error.
*
* The default is 32MB
*
* @since 0.3.0
*/
static const size_t max_message_size = 32000000;
/// Default maximum http body size
/**
* Default value for the http parser's maximum body size. Maximum body size
* determines the point at which the library will abort reading an HTTP
* connection with the 413/request entity too large error.
*
* The default is 32MB
*
* @since 0.5.0
*/
static const size_t max_http_body_size = 32000000;
/// Global flag for enabling/disabling extensions
static const bool enable_extensions = true;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,7 +34,11 @@
#include <websocketpp/common/stdint.hpp>
// Concurrency
#ifndef _WEBSOCKETPP_NO_THREADING_
#include <websocketpp/concurrency/basic.hpp>
#else
#include <websocketpp/concurrency/none.hpp>
#endif
// Transport
#include <websocketpp/transport/iostream/endpoint.hpp>
@@ -68,7 +72,11 @@ struct core_client {
typedef core_client type;
// Concurrency policy
#ifndef _WEBSOCKETPP_NO_THREADING_
typedef websocketpp::concurrency::basic concurrency_type;
#else
typedef websocketpp::concurrency::none concurrency_type;
#endif
// HTTP Parser Policies
typedef http::parser::request request_type;
@@ -216,6 +224,30 @@ struct core_client {
*/
static const bool silent_close = false;
/// Default maximum message size
/**
* Default value for the processor's maximum message size. Maximum message size
* determines the point at which the library will fail a connection with the
* message_too_big protocol error.
*
* The default is 32MB
*
* @since 0.3.0
*/
static const size_t max_message_size = 32000000;
/// Default maximum http body size
/**
* Default value for the http parser's maximum body size. Maximum body size
* determines the point at which the library will abort reading an HTTP
* connection with the 413/request entity too large error.
*
* The default is 32MB
*
* @since 0.5.0
*/
static const size_t max_http_body_size = 32000000;
/// Global flag for enabling/disabling extensions
static const bool enable_extensions = true;
+25 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -216,6 +216,30 @@ struct debug_core {
*/
static const bool silent_close = false;
/// Default maximum message size
/**
* Default value for the processor's maximum message size. Maximum message size
* determines the point at which the library will fail a connection with the
* message_too_big protocol error.
*
* The default is 32MB
*
* @since 0.3.0
*/
static const size_t max_message_size = 32000000;
/// Default maximum http body size
/**
* Default value for the http parser's maximum body size. Maximum body size
* determines the point at which the library will abort reading an HTTP
* connection with the 413/request entity too large error.
*
* The default is 32MB
*
* @since 0.5.0
*/
static const size_t max_http_body_size = 32000000;
/// Global flag for enabling/disabling extensions
static const bool enable_extensions = true;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. 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,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2014, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON 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.
*
*/
#ifndef WEBSOCKETPP_CONFIG_MINIMAL_CLIENT_HPP
#define WEBSOCKETPP_CONFIG_MINIMAL_CLIENT_HPP
#include <websocketpp/config/minimal_server.hpp>
namespace websocketpp {
namespace config {
/// Client config with minimal dependencies
/**
* This config strips out as many dependencies as possible. It is suitable for
* use as a base class for custom configs that want to implement or choose their
* own policies for components that even the core config includes.
*
* NOTE: this config stubs out enough that it cannot be used directly. You must
* supply at least a transport policy and a cryptographically secure random
* number generation policy for a config based on `minimal_client` to do
* anything useful.
*
* Present dependency list for minimal_server config:
*
* C++98 STL:
* <algorithm>
* <map>
* <sstream>
* <string>
* <vector>
*
* C++11 STL or Boost
* <memory>
* <functional>
* <system_error>
*
* Operating System:
* <stdint.h> or <boost/cstdint.hpp>
* <netinet/in.h> or <winsock2.h> (for ntohl.. could potentially bundle this)
*
* @since 0.4.0-dev
*/
typedef minimal_server minimal_client;
} // namespace config
} // namespace websocketpp
#endif // WEBSOCKETPP_CONFIG_MINIMAL_CLIENT_HPP
@@ -0,0 +1,312 @@
/*
* Copyright (c) 2014, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON 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.
*
*/
#ifndef WEBSOCKETPP_CONFIG_MINIMAL_HPP
#define WEBSOCKETPP_CONFIG_MINIMAL_HPP
// Non-Policy common stuff
#include <websocketpp/common/platforms.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/stdint.hpp>
// Concurrency
#include <websocketpp/concurrency/none.hpp>
// Transport
#include <websocketpp/transport/stub/endpoint.hpp>
// HTTP
#include <websocketpp/http/request.hpp>
#include <websocketpp/http/response.hpp>
// Messages
#include <websocketpp/message_buffer/message.hpp>
#include <websocketpp/message_buffer/alloc.hpp>
// Loggers
#include <websocketpp/logger/stub.hpp>
// RNG
#include <websocketpp/random/none.hpp>
// User stub base classes
#include <websocketpp/endpoint_base.hpp>
#include <websocketpp/connection_base.hpp>
// Extensions
#include <websocketpp/extensions/permessage_deflate/disabled.hpp>
namespace websocketpp {
namespace config {
/// Server config with minimal dependencies
/**
* This config strips out as many dependencies as possible. It is suitable for
* use as a base class for custom configs that want to implement or choose their
* own policies for components that even the core config includes.
*
* NOTE: this config stubs out enough that it cannot be used directly. You must
* supply at least a transport policy for a config based on `minimal_server` to
* do anything useful.
*
* Present dependency list for minimal_server config:
*
* C++98 STL:
* <algorithm>
* <map>
* <sstream>
* <string>
* <vector>
*
* C++11 STL or Boost
* <memory>
* <functional>
* <system_error>
*
* Operating System:
* <stdint.h> or <boost/cstdint.hpp>
* <netinet/in.h> or <winsock2.h> (for ntohl.. could potentially bundle this)
*
* @since 0.4.0-dev
*/
struct minimal_server {
typedef minimal_server type;
// Concurrency policy
typedef websocketpp::concurrency::none concurrency_type;
// HTTP Parser Policies
typedef http::parser::request request_type;
typedef http::parser::response response_type;
// Message Policies
typedef message_buffer::message<message_buffer::alloc::con_msg_manager>
message_type;
typedef message_buffer::alloc::con_msg_manager<message_type>
con_msg_manager_type;
typedef message_buffer::alloc::endpoint_msg_manager<con_msg_manager_type>
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::stub elog_type;
typedef websocketpp::log::stub alog_type;
/// RNG policies
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
/// Controls compile time enabling/disabling of thread syncronization
/// code Disabling can provide a minor performance improvement to single
/// threaded applications
static bool const enable_multithreading = true;
struct transport_config {
typedef type::concurrency_type concurrency_type;
typedef type::elog_type elog_type;
typedef type::alog_type alog_type;
typedef type::request_type request_type;
typedef type::response_type response_type;
/// Controls compile time enabling/disabling of thread syncronization
/// code Disabling can provide a minor performance improvement to single
/// threaded applications
static bool const enable_multithreading = true;
/// Default timer values (in ms)
/// Length of time to wait for socket pre-initialization
/**
* Exactly what this includes depends on the socket policy in use
*/
static const long timeout_socket_pre_init = 5000;
/// Length of time to wait before a proxy handshake is aborted
static const long timeout_proxy = 5000;
/// Length of time to wait for socket post-initialization
/**
* Exactly what this includes depends on the socket policy in use.
* Often this means the TLS handshake
*/
static const long timeout_socket_post_init = 5000;
/// Length of time to wait for dns resolution
static const long timeout_dns_resolve = 5000;
/// Length of time to wait for TCP connect
static const long timeout_connect = 5000;
/// Length of time to wait for socket shutdown
static const long timeout_socket_shutdown = 5000;
};
/// Transport Endpoint Component
typedef websocketpp::transport::stub::endpoint<transport_config>
transport_type;
/// User overridable Endpoint base class
typedef websocketpp::endpoint_base endpoint_base;
/// User overridable Connection base class
typedef websocketpp::connection_base connection_base;
/// Default timer values (in ms)
/// Length of time before an opening handshake is aborted
static const long timeout_open_handshake = 5000;
/// Length of time before a closing handshake is aborted
static const long timeout_close_handshake = 5000;
/// Length of time to wait for a pong after a ping
static const long timeout_pong = 5000;
/// WebSocket Protocol version to use as a client
/**
* What version of the WebSocket Protocol to use for outgoing client
* connections. Setting this to a value other than 13 (RFC6455) is not
* recommended.
*/
static const int client_version = 13; // RFC6455
/// Default static error logging channels
/**
* Which error logging channels to enable at compile time. Channels not
* enabled here will be unable to be selected by programs using the library.
* This option gives an optimizing compiler the ability to remove entirely
* code to test whether or not to print out log messages on a certain
* channel
*
* Default is all except for development/debug level errors
*/
static const websocketpp::log::level elog_level =
websocketpp::log::elevel::none;
/// Default static access logging channels
/**
* Which access logging channels to enable at compile time. Channels not
* enabled here will be unable to be selected by programs using the library.
* This option gives an optimizing compiler the ability to remove entirely
* code to test whether or not to print out log messages on a certain
* channel
*
* Default is all except for development/debug level access messages
*/
static const websocketpp::log::level alog_level =
websocketpp::log::alevel::none;
///
static const size_t connection_read_buffer_size = 16384;
/// Drop connections immediately on protocol error.
/**
* Drop connections on protocol error rather than sending a close frame.
* Off by default. This may result in legit messages near the error being
* dropped as well. It may free up resources otherwise spent dealing with
* misbehaving clients.
*/
static const bool drop_on_protocol_error = false;
/// Suppresses the return of detailed connection close information
/**
* Silence close suppresses the return of detailed connection close
* information during the closing handshake. This information is useful
* for debugging and presenting useful errors to end users but may be
* undesirable for security reasons in some production environments.
* Close reasons could be used by an attacker to confirm that the endpoint
* is out of resources or be used to identify the WebSocket implementation
* in use.
*
* Note: this will suppress *all* close codes, including those explicitly
* sent by local applications.
*/
static const bool silent_close = false;
/// Default maximum message size
/**
* Default value for the processor's maximum message size. Maximum message size
* determines the point at which the library will fail a connection with the
* message_too_big protocol error.
*
* The default is 32MB
*
* @since 0.4.0-alpha1
*/
static const size_t max_message_size = 32000000;
/// Default maximum http body size
/**
* Default value for the http parser's maximum body size. Maximum body size
* determines the point at which the library will abort reading an HTTP
* connection with the 413/request entity too large error.
*
* The default is 32MB
*
* @since 0.5.0
*/
static const size_t max_http_body_size = 32000000;
/// Global flag for enabling/disabling extensions
static const bool enable_extensions = true;
/// Extension specific settings:
/// permessage_compress extension
struct permessage_deflate_config {
typedef core::request_type request_type;
/// If the remote endpoint requests that we reset the compression
/// context after each message should we honor the request?
static const bool allow_disabling_context_takeover = true;
/// If the remote endpoint requests that we reduce the size of the
/// LZ77 sliding window size this is the lowest value that will be
/// allowed. Values range from 8 to 15. A value of 8 means we will
/// allow any possible window size. A value of 15 means do not allow
/// negotiation of the window size (ie require the default).
static const uint8_t minimum_outgoing_window_bits = 8;
};
typedef websocketpp::extensions::permessage_deflate::disabled
<permessage_deflate_config> permessage_deflate_type;
/// Autonegotiate permessage-deflate
/**
* Automatically enables the permessage-deflate extension.
*
* For clients this results in a permessage-deflate extension request being
* sent with every request rather than requiring it to be requested manually
*
* For servers this results in accepting the first set of extension settings
* requested by the client that we understand being used. The alternative is
* requiring the extension to be manually negotiated in `validate`. With
* auto-negotiate on, you may still override the auto-negotiate manually if
* needed.
*/
//static const bool autonegotiate_compression = false;
};
} // namespace config
} // namespace websocketpp
#endif // WEBSOCKETPP_CONFIG_MINIMAL_HPP
+313 -93
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,19 +29,20 @@
#define WEBSOCKETPP_CONNECTION_HPP
#include <websocketpp/close.hpp>
#include <websocketpp/common/connection_hdl.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/functional.hpp>
#include <websocketpp/error.hpp>
#include <websocketpp/frame.hpp>
#include <websocketpp/http/constants.hpp>
#include <websocketpp/logger/levels.hpp>
#include <websocketpp/processors/processor.hpp>
#include <websocketpp/transport/base/connection.hpp>
#include <websocketpp/http/constants.hpp>
#include <websocketpp/common/connection_hdl.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/functional.hpp>
#include <algorithm>
#include <iostream>
#include <queue>
#include <sstream>
#include <string>
#include <vector>
@@ -118,7 +119,7 @@ typedef lib::function<void(connection_hdl,std::string)> pong_timeout_handler;
/**
* The validate handler is called after a WebSocket handshake has been received
* and processed but before it has been accepted. This gives the application a
* chance to impliment connection details specific policies for accepting
* chance to implement connection details specific policies for accepting
* connections and the ability to negotiate extensions and subprotocols.
*
* The validate handler return value indicates whether or not the connection
@@ -213,6 +214,20 @@ namespace internal_state {
PROCESS_CONNECTION = 7
};
} // namespace internal_state
namespace http_state {
// states to keep track of the progress of http connections
enum value {
init = 0,
deferred = 1,
headers_written = 2,
body_written = 3,
closed = 4
};
} // namespace http_state
} // namespace session
/// Represents an individual WebSocket connection
@@ -279,9 +294,9 @@ private:
};
public:
explicit connection(bool is_server, std::string const & ua, alog_type& alog,
explicit connection(bool p_is_server, std::string const & ua, alog_type& alog,
elog_type& elog, rng_type & rng)
: transport_con_type(is_server,alog,elog)
: transport_con_type(p_is_server, alog, elog)
, m_handle_read_frame(lib::bind(
&type::handle_read_frame,
this,
@@ -297,17 +312,21 @@ public:
, m_open_handshake_timeout_dur(config::timeout_open_handshake)
, m_close_handshake_timeout_dur(config::timeout_close_handshake)
, m_pong_timeout_dur(config::timeout_pong)
, m_max_message_size(config::max_message_size)
, m_state(session::state::connecting)
, m_internal_state(session::internal_state::USER_INIT)
, m_msg_manager(new con_msg_manager_type())
, m_send_buffer_size(0)
, m_write_flag(false)
, m_is_server(is_server)
, m_read_flag(true)
, m_is_server(p_is_server)
, m_alog(alog)
, m_elog(elog)
, m_rng(rng)
, m_local_close_code(close::status::abnormal_close)
, m_remote_close_code(close::status::abnormal_close)
, m_is_http(false)
, m_http_state(session::http_state::init)
, m_was_clean(false)
{
m_alog.write(log::alevel::devel,"connection constructor");
@@ -455,9 +474,9 @@ public:
m_message_handler = h;
}
/////////////////////////
// Connection timeouts //
/////////////////////////
//////////////////////////////////////////
// Connection timeouts and other limits //
//////////////////////////////////////////
/// Set open handshake timeout
/**
@@ -528,6 +547,70 @@ public:
m_pong_timeout_dur = dur;
}
/// Get maximum message size
/**
* Get maximum message size. Maximum message size determines the point at
* which the connection will fail with the message_too_big protocol error.
*
* The default is set by the endpoint that creates the connection.
*
* @since 0.3.0
*/
size_t get_max_message_size() const {
return m_max_message_size;
}
/// Set maximum message size
/**
* Set maximum message size. Maximum message size determines the point at
* which the connection will fail with the message_too_big protocol error.
* This value may be changed during the connection.
*
* The default is set by the endpoint that creates the connection.
*
* @since 0.3.0
*
* @param new_value The value to set as the maximum message size.
*/
void set_max_message_size(size_t new_value) {
m_max_message_size = new_value;
if (m_processor) {
m_processor->set_max_message_size(new_value);
}
}
/// Get maximum HTTP message body size
/**
* Get maximum HTTP message body size. Maximum message body size determines
* the point at which the connection will stop reading an HTTP request whose
* body is too large.
*
* The default is set by the endpoint that creates the connection.
*
* @since 0.5.0
*
* @return The maximum HTTP message body size
*/
size_t get_max_http_body_size() const {
return m_request.get_max_body_size();
}
/// Set maximum HTTP message body size
/**
* Set maximum HTTP message body size. Maximum message body size determines
* the point at which the connection will stop reading an HTTP request whose
* body is too large.
*
* The default is set by the endpoint that creates the connection.
*
* @since 0.5.0
*
* @param new_value The value to set as the maximum message size.
*/
void set_max_http_body_size(size_t new_value) {
m_request.set_max_body_size(new_value);
}
//////////////////////////////////
// Uncategorized public methods //
//////////////////////////////////
@@ -545,7 +628,10 @@ public:
*/
size_t get_buffered_amount() const;
/// DEPRECATED: use get_buffered_amount instead
/// Get the size of the outgoing write buffer (in payload bytes)
/**
* @deprecated use `get_buffered_amount` instead
*/
size_t buffered_amount() const {
return get_buffered_amount();
}
@@ -615,9 +701,46 @@ public:
* @return An error code
*/
lib::error_code interrupt();
/// Transport inturrupt callback
void handle_interrupt();
/// Pause reading of new data
/**
* Signals to the connection to halt reading of new data. While reading is paused,
* the connection will stop reading from its associated socket. In turn this will
* result in TCP based flow control kicking in and slowing data flow from the remote
* endpoint.
*
* This is useful for applications that push new requests to a queue to be processed
* by another thread and need a way to signal when their request queue is full without
* blocking the network processing thread.
*
* Use `resume_reading()` to resume.
*
* If supported by the transport this is done asynchronously. As such reading may not
* stop until the current read operation completes. Typically you can expect to
* receive no more bytes after initiating a read pause than the size of the read
* buffer.
*
* If reading is paused for this connection already nothing is changed.
*/
lib::error_code pause_reading();
/// Pause reading callback
void handle_pause_reading();
/// Resume reading of new data
/**
* Signals to the connection to resume reading of new data after it was paused by
* `pause_reading()`.
*
* If reading is not paused for this connection already nothing is changed.
*/
lib::error_code resume_reading();
/// Resume reading callback
void handle_resume_reading();
/// Send a ping
/**
@@ -827,7 +950,18 @@ public:
* @param key Name of the header to get
* @return The value of the header
*/
std::string const & get_request_header(std::string const & key);
std::string const & get_request_header(std::string const & key) const;
/// Retrieve a request body
/**
* Retrieve the value of the request body. This value is typically used with
* PUT and POST requests to upload files or other data. Only HTTP
* connections will ever have bodies. WebSocket connection's will always
* have blank bodies.
*
* @return The value of the request body.
*/
std::string const & get_request_body() const;
/// Retrieve a response header
/**
@@ -836,8 +970,32 @@ public:
* @param key Name of the header to get
* @return The value of the header
*/
std::string const & get_response_header(std::string const & key);
std::string const & get_response_header(std::string const & key) const;
/// Get response HTTP status code
/**
* Gets the response status code
*
* @since 0.7.0
*
* @return The response status code sent
*/
http::status_code::value get_response_code() const {
return m_response.get_status_code();
}
/// Get response HTTP status message
/**
* Gets the response status message
*
* @since 0.7.0
*
* @return The response status message sent
*/
std::string const & get_response_msg() const {
return m_response.get_status_msg();
}
/// Set response status code and message
/**
* Sets the response status code to `code` and looks up the corresponding
@@ -944,6 +1102,71 @@ public:
request_type const & get_request() const {
return m_request;
}
/// Get response object
/**
* Direct access to the HTTP response sent or received as a part of the
* opening handshake. This can be used to call methods of the response
* object that are not part of the standard request API that connection
* wraps.
*
* Note use of this method involves using behavior specific to the
* configured HTTP policy. Such behavior may not work with alternate HTTP
* policies.
*
* @since 0.7.0
*
* @return A const reference to the raw response object
*/
response_type const & get_response() const {
return m_response;
}
/// Defer HTTP Response until later (Exception free)
/**
* Used in the http handler to defer the HTTP response for this connection
* until later. Handshake timers will be canceled and the connection will be
* left open until `send_http_response` or an equivalent is called.
*
* Warning: deferred connections won't time out and as a result can tie up
* resources.
*
* @since 0.6.0
*
* @return A status code, zero on success, non-zero otherwise
*/
lib::error_code defer_http_response();
/// Send deferred HTTP Response (exception free)
/**
* Sends an http response to an HTTP connection that was deferred. This will
* send a complete response including all headers, status line, and body
* text. The connection will be closed afterwards.
*
* @since 0.6.0
*
* @param ec A status code, zero on success, non-zero otherwise
*/
void send_http_response(lib::error_code & ec);
/// Send deferred HTTP Response
void send_http_response();
// TODO HTTPNBIO: write_headers
// function that processes headers + status so far and writes it to the wire
// beginning the HTTP response body state. This method will ignore anything
// in the response body.
// TODO HTTPNBIO: write_body_message
// queues the specified message_buffer for async writing
// TODO HTTPNBIO: finish connection
//
// TODO HTTPNBIO: write_response
// Writes the whole response, headers + body and closes the connection
/////////////////////////////////////////////////////////////
// Pass-through access to the other connection information //
@@ -1032,26 +1255,6 @@ public:
return m_ec;
}
////////////////////////////////////////////////////////////////////////
// The remaining public member functions are for internal/policy use //
// only. Do not call from application code unless you understand what //
// you are doing. //
////////////////////////////////////////////////////////////////////////
/// Set Connection Handle
/**
* The connection handle is a token that can be shared outside the
* WebSocket++ core for the purposes of identifying a connection and
* sending it messages.
*
* @param hdl A connection_hdl that the connection will use to refer
* to itself.
*/
void set_handle(connection_hdl hdl) {
m_connection_hdl = hdl;
transport_con_type::set_handle(hdl);
}
/// Get a message buffer
/**
* Warning: The API related to directly sending message buffers may change
@@ -1077,7 +1280,13 @@ public:
return m_msg_manager->get_message(op, size);
}
void start();
////////////////////////////////////////////////////////////////////////
// The remaining public member functions are for internal/policy use //
// only. Do not call from application code unless you understand what //
// you are doing. //
////////////////////////////////////////////////////////////////////////
void read_handshake(size_t num_bytes);
@@ -1086,17 +1295,18 @@ public:
void handle_read_http_response(lib::error_code const & ec,
size_t bytes_transferred);
void handle_send_http_response(lib::error_code const & ec);
void handle_write_http_response(lib::error_code const & ec);
void handle_send_http_request(lib::error_code const & ec);
void handle_open_handshake_timeout(lib::error_code const & ec);
void handle_close_handshake_timeout(lib::error_code const & ec);
void handle_read_frame(lib::error_code const & ec,
size_t bytes_transferred);
void handle_read_frame(lib::error_code const & ec, size_t bytes_transferred);
void read_frame();
/// Get array of WebSocket protocol versions that this connection supports.
const std::vector<int>& get_supported_versions() const;
std::vector<int> const & get_supported_versions() const;
/// Sets the handler for a terminating connection. Should only be used
/// internally by the endpoint class.
@@ -1126,64 +1336,48 @@ public:
* non-zero otherwise.
*/
void handle_write_frame(lib::error_code const & ec);
// protected:
// This set of methods would really like to be protected, but doing so
// requires that the endpoint be able to friend the connection. This is
// allowed with C++11, but not prior versions
/// Start the connection state machine
void start();
/// Set Connection Handle
/**
* The connection handle is a token that can be shared outside the
* WebSocket++ core for the purposes of identifying a connection and
* sending it messages.
*
* @param hdl A connection_hdl that the connection will use to refer
* to itself.
*/
void set_handle(connection_hdl hdl) {
m_connection_hdl = hdl;
transport_con_type::set_handle(hdl);
}
protected:
void handle_transport_init(lib::error_code const & ec);
/// Set m_processor based on information in m_request. Set m_response
/// status and return false on error.
bool initialize_processor();
/// status and return an error code indicating status.
lib::error_code initialize_processor();
/// Perform WebSocket handshake validation of m_request using m_processor.
/// set m_response and return false on error.
bool process_handshake_request();
/// Atomically change the internal connection state.
/**
* @param req The required starting state. If the internal state does not
* match req an exception is thrown.
*
* @param dest The state to change to.
*
* @param msg The message to include in the exception thrown
*/
void atomic_state_change(istate_type req, istate_type dest,
std::string msg);
/// Atomically change the internal and external connection state.
/**
* @param ireq The required starting internal state. If the internal state
* does not match ireq an exception is thrown.
*
* @param idest The internal state to change to.
*
* @param ereq The required starting external state. If the external state
* does not match ereq an exception is thrown.
*
* @param edest The external state to change to.
*
* @param msg The message to include in the exception thrown
*/
void atomic_state_change(istate_type ireq, istate_type idest,
session::state::value ereq, session::state::value edest,
std::string msg);
/// Atomically read and compared the internal state.
/**
* @param req The state to test against. If the internal state does not
* match req an exception is thrown.
*
* @param msg The message to include in the exception thrown
*/
void atomic_state_check(istate_type req, std::string msg);
/// set m_response and return an error code indicating status.
lib::error_code process_handshake_request();
private:
/// Completes m_response, serializes it, and sends it out on the wire.
void send_http_response();
void write_http_response(lib::error_code const & ec);
/// Sends an opening WebSocket connect request
void send_http_request();
/// Alternate path for send_http_response in error conditions
void send_http_response_error();
/// Alternate path for write_http_response in error conditions
void write_http_response_error(lib::error_code const & ec);
/// Process control message
/**
@@ -1203,7 +1397,7 @@ private:
* @return A status code, zero on success, non-zero otherwise
*/
lib::error_code send_close_ack(close::status::value code =
close::status::blank, std::string const & reason = "");
close::status::blank, std::string const & reason = std::string());
/// Send close frame
/**
@@ -1221,7 +1415,7 @@ private:
* @return A status code, zero on success, non-zero otherwise
*/
lib::error_code send_close_frame(close::status::value code =
close::status::blank, std::string const & reason = "", bool ack = false,
close::status::blank, std::string const & reason = std::string(), bool ack = false,
bool terminal = false);
/// Get a pointer to a new WebSocket protocol processor for a given version
@@ -1280,6 +1474,20 @@ private:
* Includes: error code and message for why it was failed
*/
void log_fail_result();
/// Prints information about HTTP connections
/**
* Includes: TODO
*/
void log_http_result();
/// Prints information about an arbitrary error code on the specified channel
template <typename error_type>
void log_err(log::level l, char const * msg, error_type const & ec) {
std::stringstream s;
s << msg << " error: " << ec << " (" << ec.message() << ")";
m_elog.write(l, s.str());
}
// internal handler functions
read_handler m_handle_read_frame;
@@ -1307,6 +1515,7 @@ private:
long m_open_handshake_timeout_dur;
long m_close_handshake_timeout_dur;
long m_pong_timeout_dur;
size_t m_max_message_size;
/// External connection state
/**
@@ -1370,9 +1579,9 @@ private:
*/
std::vector<transport::buffer> m_send_buffer;
/// a pointer to hold on to the current message being written to keep it
/// a list of pointers to hold on to the messages being written to keep them
/// from going out of scope before the write is complete.
message_ptr m_current_msg;
std::vector<message_ptr> m_current_msgs;
/// True if there is currently an outstanding transport write
/**
@@ -1380,6 +1589,9 @@ private:
*/
bool m_write_flag;
/// True if this connection is presently reading new data
bool m_read_flag;
// connection data
request_type m_request;
response_type m_response;
@@ -1411,6 +1623,14 @@ private:
/// Detailed internal error code
lib::error_code m_ec;
/// A flag that gets set once it is determined that the connection is an
/// HTTP connection and not a WebSocket one.
bool m_is_http;
/// A flag that gets set when the completion of an http connection is
/// deferred until later.
session::http_state::value m_http_state;
bool m_was_clean;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
+201 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,11 +29,11 @@
#define WEBSOCKETPP_ENDPOINT_HPP
#include <websocketpp/connection.hpp>
#include <websocketpp/logger/levels.hpp>
#include <websocketpp/version.hpp>
#include <iostream>
#include <set>
#include <string>
namespace websocketpp {
@@ -85,25 +85,78 @@ public:
// TODO: organize these
typedef typename connection_type::termination_handler termination_handler;
typedef lib::shared_ptr<connection_weak_ptr> hdl_type;
// This would be ideal. Requires C++11 though
//friend connection;
explicit endpoint(bool is_server)
: m_alog(config::alog_level, &std::cout)
, m_elog(config::elog_level, &std::cerr)
explicit endpoint(bool p_is_server)
: m_alog(config::alog_level, log::channel_type_hint::access)
, m_elog(config::elog_level, log::channel_type_hint::error)
, m_user_agent(::websocketpp::user_agent)
, m_open_handshake_timeout_dur(config::timeout_open_handshake)
, m_close_handshake_timeout_dur(config::timeout_close_handshake)
, m_pong_timeout_dur(config::timeout_pong)
, m_is_server(is_server)
, m_max_message_size(config::max_message_size)
, m_max_http_body_size(config::max_http_body_size)
, m_is_server(p_is_server)
{
m_alog.set_channels(config::alog_level);
m_elog.set_channels(config::elog_level);
m_alog.write(log::alevel::devel,"endpoint constructor");
m_alog.write(log::alevel::devel, "endpoint constructor");
transport_type::init_logging(&m_alog,&m_elog);
transport_type::init_logging(&m_alog, &m_elog);
}
/// Destructor
~endpoint<connection,config>() {}
#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
// no copy constructor because endpoints are not copyable
endpoint(endpoint &) = delete;
// no copy assignment operator because endpoints are not copyable
endpoint & operator=(endpoint const &) = delete;
#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
/// Move constructor
endpoint(endpoint && o)
: config::transport_type(std::move(o))
, config::endpoint_base(std::move(o))
, m_alog(std::move(o.m_alog))
, m_elog(std::move(o.m_elog))
, m_user_agent(std::move(o.m_user_agent))
, m_open_handler(std::move(o.m_open_handler))
, m_close_handler(std::move(o.m_close_handler))
, m_fail_handler(std::move(o.m_fail_handler))
, m_ping_handler(std::move(o.m_ping_handler))
, m_pong_handler(std::move(o.m_pong_handler))
, m_pong_timeout_handler(std::move(o.m_pong_timeout_handler))
, m_interrupt_handler(std::move(o.m_interrupt_handler))
, m_http_handler(std::move(o.m_http_handler))
, m_validate_handler(std::move(o.m_validate_handler))
, m_message_handler(std::move(o.m_message_handler))
, m_open_handshake_timeout_dur(o.m_open_handshake_timeout_dur)
, m_close_handshake_timeout_dur(o.m_close_handshake_timeout_dur)
, m_pong_timeout_dur(o.m_pong_timeout_dur)
, m_max_message_size(o.m_max_message_size)
, m_max_http_body_size(o.m_max_http_body_size)
, m_rng(std::move(o.m_rng))
, m_is_server(o.m_is_server)
{}
#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
// no move assignment operator because of const member variables
endpoint & operator=(endpoint &&) = delete;
#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#endif // _WEBSOCKETPP_MOVE_SEMANTICS_
/// Returns the user agent string that this endpoint will use
/**
* Returns the user agent string that this endpoint will use when creating
@@ -272,9 +325,9 @@ public:
m_message_handler = h;
}
/////////////////////////
// Connection timeouts //
/////////////////////////
//////////////////////////////////////////
// Connection timeouts and other limits //
//////////////////////////////////////////
/// Set open handshake timeout
/**
@@ -348,6 +401,72 @@ public:
m_pong_timeout_dur = dur;
}
/// Get default maximum message size
/**
* Get the default maximum message size that will be used for new
* connections created by this endpoint. The maximum message size determines
* the point at which the connection will fail a connection with the
* message_too_big protocol error.
*
* The default is set by the max_message_size value from the template config
*
* @since 0.3.0
*/
size_t get_max_message_size() const {
return m_max_message_size;
}
/// Set default maximum message size
/**
* Set the default maximum message size that will be used for new
* connections created by this endpoint. Maximum message size determines the
* point at which the connection will fail a connection with the
* message_too_big protocol error.
*
* The default is set by the max_message_size value from the template config
*
* @since 0.3.0
*
* @param new_value The value to set as the maximum message size.
*/
void set_max_message_size(size_t new_value) {
m_max_message_size = new_value;
}
/// Get maximum HTTP message body size
/**
* Get maximum HTTP message body size. Maximum message body size determines
* the point at which the connection will stop reading an HTTP request whose
* body is too large.
*
* The default is set by the max_http_body_size value from the template
* config
*
* @since 0.5.0
*
* @return The maximum HTTP message body size
*/
size_t get_max_http_body_size() const {
return m_max_http_body_size;
}
/// Set maximum HTTP message body size
/**
* Set maximum HTTP message body size. Maximum message body size determines
* the point at which the connection will stop reading an HTTP request whose
* body is too large.
*
* The default is set by the max_http_body_size value from the template
* config
*
* @since 0.5.1
*
* @param new_value The value to set as the maximum message size.
*/
void set_max_http_body_size(size_t new_value) {
m_max_http_body_size = new_value;
}
/*************************************/
/* Connection pass through functions */
/*************************************/
@@ -363,6 +482,72 @@ public:
void interrupt(connection_hdl hdl, lib::error_code & ec);
void interrupt(connection_hdl hdl);
/// Pause reading of new data (exception free)
/**
* Signals to the connection to halt reading of new data. While reading is
* paused, the connection will stop reading from its associated socket. In
* turn this will result in TCP based flow control kicking in and slowing
* data flow from the remote endpoint.
*
* This is useful for applications that push new requests to a queue to be
* processed by another thread and need a way to signal when their request
* queue is full without blocking the network processing thread.
*
* Use `resume_reading()` to resume.
*
* If supported by the transport this is done asynchronously. As such
* reading may not stop until the current read operation completes.
* Typically you can expect to receive no more bytes after initiating a read
* pause than the size of the read buffer.
*
* If reading is paused for this connection already nothing is changed.
*/
void pause_reading(connection_hdl hdl, lib::error_code & ec);
/// Pause reading of new data
void pause_reading(connection_hdl hdl);
/// Resume reading of new data (exception free)
/**
* Signals to the connection to resume reading of new data after it was
* paused by `pause_reading()`.
*
* If reading is not paused for this connection already nothing is changed.
*/
void resume_reading(connection_hdl hdl, lib::error_code & ec);
/// Resume reading of new data
void resume_reading(connection_hdl hdl);
/// Send deferred HTTP Response
/**
* Sends an http response to an HTTP connection that was deferred. This will
* send a complete response including all headers, status line, and body
* text. The connection will be closed afterwards.
*
* Exception free variant
*
* @since 0.6.0
*
* @param hdl The connection to send the response on
* @param ec A status code, zero on success, non-zero otherwise
*/
void send_http_response(connection_hdl hdl, lib::error_code & ec);
/// Send deferred HTTP Response (exception free)
/**
* Sends an http response to an HTTP connection that was deferred. This will
* send a complete response including all headers, status line, and body
* text. The connection will be closed afterwards.
*
* Exception variant
*
* @since 0.6.0
*
* @param hdl The connection to send the response on
*/
void send_http_response(connection_hdl hdl);
/// Create a message and add it to the outgoing send queue (exception free)
/**
* Convenience method to send a message given a payload string and an opcode
@@ -456,7 +641,6 @@ public:
* @return the connection_ptr. May be NULL if the handle was invalid.
*/
connection_ptr get_con_from_hdl(connection_hdl hdl, lib::error_code & ec) {
scoped_lock_type lock(m_mutex);
connection_ptr con = lib::static_pointer_cast<connection_type>(
hdl.lock());
if (!con) {
@@ -470,7 +654,7 @@ public:
lib::error_code ec;
connection_ptr con = this->get_con_from_hdl(hdl,ec);
if (ec) {
throw ec;
throw exception(ec);
}
return con;
}
@@ -497,6 +681,8 @@ private:
long m_open_handshake_timeout_dur;
long m_close_handshake_timeout_dur;
long m_pong_timeout_dur;
size_t m_max_message_size;
size_t m_max_http_body_size;
rng_type m_rng;
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
+60 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,7 +28,9 @@
#ifndef WEBSOCKETPP_ERROR_HPP
#define WEBSOCKETPP_ERROR_HPP
#include <exception>
#include <string>
#include <utility>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/system_error.hpp>
@@ -38,7 +40,7 @@ namespace websocketpp {
/// Combination error code / string type for returning two values
typedef std::pair<lib::error_code,std::string> err_str_pair;
// setup for errors that should be propogated back to the user.
/// Library level error codes
namespace error {
enum value {
/// Catch-all library error
@@ -86,7 +88,8 @@ enum value {
/// Invalid subprotocol
invalid_subprotocol,
/// Bad or unknown connection
/// An operation was attempted on a connection that did not exist or was
/// already deleted.
bad_connection,
/// Unit testing utility error code
@@ -114,7 +117,33 @@ enum value {
close_handshake_timeout,
/// Invalid port in URI
invalid_port
invalid_port,
/// An async accept operation failed because the underlying transport has been
/// requested to not listen for new connections anymore.
async_accept_not_listening,
/// The requested operation was canceled
operation_canceled,
/// Connection rejected
rejected,
/// Upgrade Required. This happens if an HTTP request is made to a
/// WebSocket++ server that doesn't implement an http handler
upgrade_required,
/// Invalid WebSocket protocol version
invalid_version,
/// Unsupported WebSocket protocol version
unsupported_version,
/// HTTP parse error
http_parse_error,
/// Extension negotiation failed
extension_neg_failed
}; // enum value
@@ -176,6 +205,22 @@ public:
return "The closing handshake timed out";
case error::invalid_port:
return "Invalid URI port";
case error::async_accept_not_listening:
return "Async Accept not listening";
case error::operation_canceled:
return "Operation canceled";
case error::rejected:
return "Connection rejected";
case error::upgrade_required:
return "Upgrade required";
case error::invalid_version:
return "Invalid version";
case error::unsupported_version:
return "Unsupported version";
case error::http_parse_error:
return "HTTP parse error";
case error::extension_neg_failed:
return "Extension negotiation failed";
default:
return "Unknown";
}
@@ -205,21 +250,26 @@ namespace websocketpp {
class exception : public std::exception {
public:
exception(std::string const & msg,
error::value code = error::general)
: m_msg(msg),m_code(code) {}
exception(std::string const & msg, lib::error_code ec = make_error_code(error::general))
: m_msg(msg.empty() ? ec.message() : msg), m_code(ec)
{}
explicit exception(lib::error_code ec)
: m_msg(ec.message()), m_code(ec)
{}
~exception() throw() {}
virtual char const * what() const throw() {
return m_msg.c_str();
}
error::value code() const throw() {
lib::error_code code() const throw() {
return m_code;
}
std::string m_msg;
error::value m_code;
const std::string m_msg;
lib::error_code m_code;
};
} // namespace websocketpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -78,7 +78,7 @@ public:
}
};
inline const lib::error_category& get_category() {
inline lib::error_category const & get_category() {
static category instance;
return instance;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -53,10 +53,29 @@ class disabled {
typedef std::pair<lib::error_code,std::string> err_str_pair;
public:
err_str_pair negotiate(http::attribute_list const & attributes) {
/// Negotiate extension
/**
* The disabled extension always fails the negotiation with a disabled
* error.
*
* @param offer Attribute from client's offer
* @return Status code and value to return to remote endpoint
*/
err_str_pair negotiate(http::attribute_list const &) {
return make_pair(make_error_code(error::disabled),std::string());
}
/// Initialize state
/**
* For the disabled extension state initialization is a no-op.
*
* @param is_server True to initialize as a server, false for a client.
* @return A code representing the error that occurred, if any
*/
lib::error_code init(bool) {
return lib::error_code();
}
/// Returns true if the extension is capable of providing
/// permessage_deflate functionality
bool is_implemented() const {
@@ -69,17 +88,35 @@ public:
return false;
}
lib::error_code compress(std::string const & in, std::string & out) {
/// Generate extension offer
/**
* Creates an offer string to include in the Sec-WebSocket-Extensions
* header of outgoing client requests.
*
* @return A WebSocket extension offer string for this extension
*/
std::string generate_offer() const {
return "";
}
/// Compress bytes
/**
* @param [in] in String to compress
* @param [out] out String to append compressed bytes to
* @return Error or status code
*/
lib::error_code compress(std::string const &, std::string &) {
return make_error_code(error::disabled);
}
lib::error_code decompress(uint8_t const * buf, size_t len,
std::string & out)
{
return make_error_code(error::disabled);
}
lib::error_code decompress(std::string const & in, std::string & out) {
/// Decompress bytes
/**
* @param buf Byte buffer to decompress
* @param len Length of buf
* @param out String to append decompressed bytes to
* @return Error or status code
*/
lib::error_code decompress(uint8_t const *, size_t, std::string &) {
return make_error_code(error::disabled);
}
};
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2015, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,8 +28,10 @@
#ifndef WEBSOCKETPP_PROCESSOR_EXTENSION_PERMESSAGEDEFLATE_HPP
#define WEBSOCKETPP_PROCESSOR_EXTENSION_PERMESSAGEDEFLATE_HPP
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/common/platforms.hpp>
#include <websocketpp/common/system_error.hpp>
#include <websocketpp/error.hpp>
@@ -44,10 +46,14 @@
namespace websocketpp {
namespace extensions {
/// Implimentation of the draft permessage-deflate WebSocket extension
/// Implementation of the draft permessage-deflate WebSocket extension
/**
* ### permessage-deflate interface
*
* **init**\n
* `lib::error_code init(bool is_server)`\n
* Performs initialization
*
* **is_implimented**\n
* `bool is_implimented()`\n
* Returns whether or not the object impliments the extension or not
@@ -134,7 +140,7 @@ public:
case zlib_error:
return "A zlib function returned an error";
case uninitialized:
return "Object must be initialized before use";
return "Deflate extension must be initialized before use";
default:
return "Unknown permessage-compress error";
}
@@ -142,13 +148,13 @@ public:
};
/// Get a reference to a static copy of the permessage-deflate error category
lib::error_category const & get_category() {
inline lib::error_category const & get_category() {
static category instance;
return instance;
}
/// Create an error code in the permessage-deflate category
lib::error_code make_error_code(error::value e) {
inline lib::error_code make_error_code(error::value e) {
return lib::error_code(static_cast<int>(e), get_category());
}
@@ -168,19 +174,19 @@ namespace websocketpp {
namespace extensions {
namespace permessage_deflate {
/// Default value for s2c_max_window_bits as defined by RFC6455
static uint8_t const default_s2c_max_window_bits = 15;
/// Minimum value for s2c_max_window_bits as defined by RFC6455
static uint8_t const min_s2c_max_window_bits = 8;
/// Maximum value for s2c_max_window_bits as defined by RFC6455
static uint8_t const max_s2c_max_window_bits = 15;
/// Default value for server_max_window_bits as defined by draft 17
static uint8_t const default_server_max_window_bits = 15;
/// Minimum value for server_max_window_bits as defined by draft 17
static uint8_t const min_server_max_window_bits = 8;
/// Maximum value for server_max_window_bits as defined by draft 17
static uint8_t const max_server_max_window_bits = 15;
/// Default value for c2s_max_window_bits as defined by RFC6455
static uint8_t const default_c2s_max_window_bits = 15;
/// Minimum value for c2s_max_window_bits as defined by RFC6455
static uint8_t const min_c2s_max_window_bits = 8;
/// Maximum value for c2s_max_window_bits as defined by RFC6455
static uint8_t const max_c2s_max_window_bits = 15;
/// Default value for client_max_window_bits as defined by draft 17
static uint8_t const default_client_max_window_bits = 15;
/// Minimum value for client_max_window_bits as defined by draft 17
static uint8_t const min_client_max_window_bits = 8;
/// Maximum value for client_max_window_bits as defined by draft 17
static uint8_t const max_client_max_window_bits = 15;
namespace mode {
enum value {
@@ -200,12 +206,12 @@ class enabled {
public:
enabled()
: m_enabled(false)
, m_s2c_no_context_takeover(false)
, m_c2s_no_context_takeover(false)
, m_s2c_max_window_bits(15)
, m_c2s_max_window_bits(15)
, m_s2c_max_window_bits_mode(mode::accept)
, m_c2s_max_window_bits_mode(mode::accept)
, m_server_no_context_takeover(false)
, m_client_no_context_takeover(false)
, m_server_max_window_bits(15)
, m_client_max_window_bits(15)
, m_server_max_window_bits_mode(mode::accept)
, m_client_max_window_bits_mode(mode::accept)
, m_initialized(false)
, m_compress_buffer_size(16384)
{
@@ -242,20 +248,25 @@ public:
/// Initialize zlib state
/**
* Note: this should be called *after* the negotiation methods. It will use
* information from the negotiation to determine how to initialize the zlib
* data structures.
*
* @todo memory level, strategy, etc are hardcoded
* @todo server detection is hardcoded
*
* @param is_server True to initialize as a server, false for a client.
* @return A code representing the error that occurred, if any
*/
lib::error_code init() {
lib::error_code init(bool is_server) {
uint8_t deflate_bits;
uint8_t inflate_bits;
if (true /*is_server*/) {
deflate_bits = m_s2c_max_window_bits;
inflate_bits = m_c2s_max_window_bits;
if (is_server) {
deflate_bits = m_server_max_window_bits;
inflate_bits = m_client_max_window_bits;
} else {
deflate_bits = m_c2s_max_window_bits;
inflate_bits = m_s2c_max_window_bits;
deflate_bits = m_client_max_window_bits;
inflate_bits = m_server_max_window_bits;
}
int ret = deflateInit2(
@@ -263,8 +274,8 @@ public:
Z_DEFAULT_COMPRESSION,
Z_DEFLATED,
-1*deflate_bits,
8, // memory level 1-9
/*Z_DEFAULT_STRATEGY*/Z_FIXED
4, // memory level 1-9
Z_DEFAULT_STRATEGY
);
if (ret != Z_OK) {
@@ -281,15 +292,22 @@ public:
}
m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]);
if ((m_server_no_context_takeover && is_server) ||
(m_client_no_context_takeover && !is_server))
{
m_flush = Z_FULL_FLUSH;
} else {
m_flush = Z_SYNC_FLUSH;
}
m_initialized = true;
return lib::error_code();
}
/// Test if this object impliments the permessage-deflate specification
/// Test if this object implements the permessage-deflate specification
/**
* Because this object does impliment it, it will always return true.
* Because this object does implieent it, it will always return true.
*
* @return Whether or not this object impliments permessage-deflate
* @return Whether or not this object implements permessage-deflate
*/
bool is_implemented() const {
return true;
@@ -327,8 +345,8 @@ public:
* the option will be in use so they can optimize resource usage if they
* are able.
*/
void enable_s2c_no_context_takeover() {
m_s2c_no_context_takeover = true;
void enable_server_no_context_takeover() {
m_server_no_context_takeover = true;
}
/// Reset client's outgoing LZ77 sliding window for each new message
@@ -346,8 +364,8 @@ public:
* This option is supported by all compliant clients and servers. Enabling
* it via either endpoint should be sufficient to ensure it is used.
*/
void enable_c2s_no_context_takeover() {
m_c2s_no_context_takeover = true;
void enable_client_no_context_takeover() {
m_client_no_context_takeover = true;
}
/// Limit server LZ77 sliding window size
@@ -372,12 +390,12 @@ public:
* @param mode The mode to use for negotiating this parameter
* @return A status code
*/
lib::error_code set_s2c_max_window_bits(uint8_t bits, mode::value mode) {
if (bits < min_s2c_max_window_bits || bits > max_s2c_max_window_bits) {
lib::error_code set_server_max_window_bits(uint8_t bits, mode::value mode) {
if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) {
return error::make_error_code(error::invalid_max_window_bits);
}
m_s2c_max_window_bits = bits;
m_s2c_max_window_bits_mode = mode;
m_server_max_window_bits = bits;
m_server_max_window_bits_mode = mode;
return lib::error_code();
}
@@ -403,12 +421,12 @@ public:
* @param mode The mode to use for negotiating this parameter
* @return A status code
*/
lib::error_code set_c2s_max_window_bits(uint8_t bits, mode::value mode) {
if (bits < min_c2s_max_window_bits || bits > max_c2s_max_window_bits) {
lib::error_code set_client_max_window_bits(uint8_t bits, mode::value mode) {
if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) {
return error::make_error_code(error::invalid_max_window_bits);
}
m_c2s_max_window_bits = bits;
m_c2s_max_window_bits_mode = mode;
m_client_max_window_bits = bits;
m_client_max_window_bits_mode = mode;
return lib::error_code();
}
@@ -421,7 +439,8 @@ public:
* @return A WebSocket extension offer string for this extension
*/
std::string generate_offer() const {
return "";
// TODO: this should be dynamically generated based on user settings
return "permessage-deflate; client_no_context_takeover; client_max_window_bits";
}
/// Validate extension response
@@ -432,8 +451,8 @@ public:
* @param response The server response attribute list to validate
* @return Validation error or 0 on success
*/
lib::error_code validate_offer(http::attribute_list const & response) {
lib::error_code validate_offer(http::attribute_list const &) {
return lib::error_code();
}
/// Negotiate extension
@@ -450,14 +469,14 @@ public:
http::attribute_list::const_iterator it;
for (it = offer.begin(); it != offer.end(); ++it) {
if (it->first == "s2c_no_context_takeover") {
negotiate_s2c_no_context_takeover(it->second,ret.first);
} else if (it->first == "c2s_no_context_takeover") {
negotiate_c2s_no_context_takeover(it->second,ret.first);
} else if (it->first == "s2c_max_window_bits") {
negotiate_s2c_max_window_bits(it->second,ret.first);
} else if (it->first == "c2s_max_window_bits") {
negotiate_c2s_max_window_bits(it->second,ret.first);
if (it->first == "server_no_context_takeover") {
negotiate_server_no_context_takeover(it->second,ret.first);
} else if (it->first == "client_no_context_takeover") {
negotiate_client_no_context_takeover(it->second,ret.first);
} else if (it->first == "server_max_window_bits") {
negotiate_server_max_window_bits(it->second,ret.first);
} else if (it->first == "client_max_window_bits") {
negotiate_client_max_window_bits(it->second,ret.first);
} else {
ret.first = make_error_code(error::invalid_attributes);
}
@@ -477,6 +496,9 @@ public:
/// Compress bytes
/**
* @todo: avail_in/out is 32 bit, need to fix for cases of >32 bit frames
* on 64 bit machines.
*
* @param [in] in String to compress
* @param [out] out String to append compressed bytes to
* @return Error or status code
@@ -487,9 +509,14 @@ public:
}
size_t output;
int ret;
m_dstate.avail_out = m_compress_buffer_size;
if (in.empty()) {
uint8_t buf[6] = {0x02, 0x00, 0x00, 0x00, 0xff, 0xff};
out.append((char *)(buf),6);
return lib::error_code();
}
m_dstate.avail_in = in.size();
m_dstate.next_in = (unsigned char *)(const_cast<char *>(in.data()));
do {
@@ -497,7 +524,7 @@ public:
m_dstate.avail_out = m_compress_buffer_size;
m_dstate.next_out = m_compress_buffer.get();
ret = deflate(&m_dstate, Z_SYNC_FLUSH);
deflate(&m_dstate, m_flush);
output = m_compress_buffer_size - m_dstate.avail_out;
@@ -552,35 +579,35 @@ private:
std::string generate_response() {
std::string ret = "permessage-deflate";
if (m_s2c_no_context_takeover) {
ret += "; s2c_no_context_takeover";
if (m_server_no_context_takeover) {
ret += "; server_no_context_takeover";
}
if (m_c2s_no_context_takeover) {
ret += "; c2s_no_context_takeover";
if (m_client_no_context_takeover) {
ret += "; client_no_context_takeover";
}
if (m_s2c_max_window_bits < default_s2c_max_window_bits) {
if (m_server_max_window_bits < default_server_max_window_bits) {
std::stringstream s;
s << int(m_s2c_max_window_bits);
ret += "; s2c_max_window_bits="+s.str();
s << int(m_server_max_window_bits);
ret += "; server_max_window_bits="+s.str();
}
if (m_c2s_max_window_bits < default_c2s_max_window_bits) {
if (m_client_max_window_bits < default_client_max_window_bits) {
std::stringstream s;
s << int(m_c2s_max_window_bits);
ret += "; c2s_max_window_bits="+s.str();
s << int(m_client_max_window_bits);
ret += "; client_max_window_bits="+s.str();
}
return ret;
}
/// Negotiate s2c_no_context_takeover attribute
/// Negotiate server_no_context_takeover attribute
/**
* @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via
*/
void negotiate_s2c_no_context_takeover(std::string const & value,
void negotiate_server_no_context_takeover(std::string const & value,
lib::error_code & ec)
{
if (!value.empty()) {
@@ -588,15 +615,15 @@ private:
return;
}
m_s2c_no_context_takeover = true;
m_server_no_context_takeover = true;
}
/// Negotiate c2s_no_context_takeover attribute
/// Negotiate client_no_context_takeover attribute
/**
* @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via
*/
void negotiate_c2s_no_context_takeover(std::string const & value,
void negotiate_client_no_context_takeover(std::string const & value,
lib::error_code & ec)
{
if (!value.empty()) {
@@ -604,13 +631,13 @@ private:
return;
}
m_c2s_no_context_takeover = true;
m_client_no_context_takeover = true;
}
/// Negotiate s2c_max_window_bits attribute
/// Negotiate server_max_window_bits attribute
/**
* When this method starts, m_s2c_max_window_bits will contain the server's
* preferred value and m_s2c_max_window_bits_mode will contain the mode the
* When this method starts, m_server_max_window_bits will contain the server's
* preferred value and m_server_max_window_bits_mode will contain the mode the
* server wants to use to for negotiation. `value` contains the value the
* client requested that we use.
*
@@ -623,39 +650,39 @@ private:
* @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via
*/
void negotiate_s2c_max_window_bits(std::string const & value,
void negotiate_server_max_window_bits(std::string const & value,
lib::error_code & ec)
{
uint8_t bits = uint8_t(atoi(value.c_str()));
if (bits < min_s2c_max_window_bits || bits > max_s2c_max_window_bits) {
if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) {
ec = make_error_code(error::invalid_attribute_value);
m_s2c_max_window_bits = default_s2c_max_window_bits;
m_server_max_window_bits = default_server_max_window_bits;
return;
}
switch (m_s2c_max_window_bits_mode) {
switch (m_server_max_window_bits_mode) {
case mode::decline:
m_s2c_max_window_bits = default_s2c_max_window_bits;
m_server_max_window_bits = default_server_max_window_bits;
break;
case mode::accept:
m_s2c_max_window_bits = bits;
m_server_max_window_bits = bits;
break;
case mode::largest:
m_s2c_max_window_bits = std::min(bits,m_s2c_max_window_bits);
m_server_max_window_bits = std::min(bits,m_server_max_window_bits);
break;
case mode::smallest:
m_s2c_max_window_bits = min_s2c_max_window_bits;
m_server_max_window_bits = min_server_max_window_bits;
break;
default:
ec = make_error_code(error::invalid_mode);
m_s2c_max_window_bits = default_s2c_max_window_bits;
m_server_max_window_bits = default_server_max_window_bits;
}
}
/// Negotiate c2s_max_window_bits attribute
/// Negotiate client_max_window_bits attribute
/**
* When this method starts, m_c2s_max_window_bits and m_c2s_max_window_mode
* When this method starts, m_client_max_window_bits and m_c2s_max_window_mode
* will contain the server's preferred values for window size and
* negotiation mode.
*
@@ -668,49 +695,50 @@ private:
* @param [in] value The value of the attribute from the offer
* @param [out] ec A reference to the error code to return errors via
*/
void negotiate_c2s_max_window_bits(std::string const & value,
void negotiate_client_max_window_bits(std::string const & value,
lib::error_code & ec)
{
uint8_t bits = uint8_t(atoi(value.c_str()));
if (value.empty()) {
bits = default_c2s_max_window_bits;
} else if (bits < min_c2s_max_window_bits ||
bits > max_c2s_max_window_bits)
bits = default_client_max_window_bits;
} else if (bits < min_client_max_window_bits ||
bits > max_client_max_window_bits)
{
ec = make_error_code(error::invalid_attribute_value);
m_c2s_max_window_bits = default_c2s_max_window_bits;
m_client_max_window_bits = default_client_max_window_bits;
return;
}
switch (m_c2s_max_window_bits_mode) {
switch (m_client_max_window_bits_mode) {
case mode::decline:
m_c2s_max_window_bits = default_c2s_max_window_bits;
m_client_max_window_bits = default_client_max_window_bits;
break;
case mode::accept:
m_c2s_max_window_bits = bits;
m_client_max_window_bits = bits;
break;
case mode::largest:
m_c2s_max_window_bits = std::min(bits,m_c2s_max_window_bits);
m_client_max_window_bits = std::min(bits,m_client_max_window_bits);
break;
case mode::smallest:
m_c2s_max_window_bits = min_c2s_max_window_bits;
m_client_max_window_bits = min_client_max_window_bits;
break;
default:
ec = make_error_code(error::invalid_mode);
m_c2s_max_window_bits = default_c2s_max_window_bits;
m_client_max_window_bits = default_client_max_window_bits;
}
}
bool m_enabled;
bool m_s2c_no_context_takeover;
bool m_c2s_no_context_takeover;
uint8_t m_s2c_max_window_bits;
uint8_t m_c2s_max_window_bits;
mode::value m_s2c_max_window_bits_mode;
mode::value m_c2s_max_window_bits_mode;
bool m_server_no_context_takeover;
bool m_client_no_context_takeover;
uint8_t m_server_max_window_bits;
uint8_t m_client_max_window_bits;
mode::value m_server_max_window_bits_mode;
mode::value m_client_max_window_bits_mode;
bool m_initialized;
int m_flush;
size_t m_compress_buffer_size;
lib::unique_ptr_uchar_array m_compress_buffer;
z_stream m_dstate;
+4 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,6 +29,7 @@
#define WEBSOCKETPP_FRAME_HPP
#include <algorithm>
#include <string>
#include <websocketpp/common/system_error.hpp>
#include <websocketpp/common/network.hpp>
@@ -266,7 +267,7 @@ private:
}
uint64_converter temp64;
temp64.i = lib::net::htonll(payload_size);
temp64.i = lib::net::_htonll(payload_size);
std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
return 8-payload_offset;
@@ -456,35 +457,6 @@ inline size_t get_header_len(basic_header const & h) {
return size;
}
/// Set the frame's size
/**
* @param [out] h The basic header to set.
* @param [out] eh The extended header to set.
* @param [in] The size to set.
* @return What error occurred, if any.
*/
inline lib::error_code set_size(basic_header & h, extended_header & eh, uint64_t
size)
{
// make sure value isn't too big
uint8_t basic_value;
if (size <= limits::payload_size_basic) {
basic_value = static_cast<uint8_t>(size);
} else if (size <= limits::payload_size_extended) {
basic_value = payload_size_code_16bit;
} else if (size <= limits::payload_size_jumbo) {
basic_value = payload_size_code_64bit;
} else {
// error
return lib::error_code();
}
h.b1 = (basic_value & BHB1_PAYLOAD) | (h.b1 & BHB1_MASK);
return lib::error_code();
}
/// Calculate the offset location of the masking key within the extended header
/**
* Calculate the offset location of the masking key within the extended header
@@ -583,7 +555,7 @@ inline uint16_t get_extended_size(const extended_header &e) {
inline uint64_t get_jumbo_size(const extended_header &e) {
uint64_converter temp64;
std::copy(e.bytes,e.bytes+8,temp64.c);
return lib::net::ntohll(temp64.i);
return lib::net::_ntohll(temp64.i);
}
/// Extract the full payload size field from a WebSocket header
+11 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,11 +28,14 @@
#ifndef HTTP_CONSTANTS_HPP
#define HTTP_CONSTANTS_HPP
#include <exception>
#include <map>
#include <string>
#include <vector>
#include <utility>
namespace websocketpp {
/// HTTP handling support
namespace http {
/// The type of an HTTP attribute list
/**
@@ -56,10 +59,13 @@ namespace http {
static char const header_separator[] = ":";
/// Literal value of an empty header
static std::string const empty_header = "";
static std::string const empty_header;
/// Maximum size in bytes before rejecting an HTTP header as too big.
size_t const max_header_size = 16000;
/// Default Maximum size in bytes for HTTP message bodies.
size_t const max_body_size = 32000000;
/// Number of bytes to use for temporary istream read buffers
size_t const istream_buffer = 512;
@@ -255,7 +261,7 @@ namespace http {
case internal_server_error:
return "Internal Server Error";
case not_implemented:
return "Not Implimented";
return "Not Implemented";
case bad_gateway:
return "Bad Gateway";
case service_unavailable:
@@ -278,8 +284,8 @@ namespace http {
public:
exception(const std::string& log_msg,
status_code::value error_code,
const std::string& error_msg = "",
const std::string& body = "")
const std::string& error_msg = std::string(),
const std::string& body = std::string())
: m_msg(log_msg)
, m_error_msg(error_msg)
, m_body(body)
+45 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,6 +29,8 @@
#define HTTP_PARSER_IMPL_HPP
#include <algorithm>
#include <cstdlib>
#include <istream>
#include <sstream>
#include <string>
@@ -69,7 +71,7 @@ inline void parser::append_header(std::string const & key, std::string const &
throw exception("Invalid header name",status_code::bad_request);
}
if (this->get_header(key) == "") {
if (this->get_header(key).empty()) {
m_headers[key] = val;
} else {
m_headers[key] += ", " + val;
@@ -89,10 +91,13 @@ inline void parser::remove_header(std::string const & key) {
inline void parser::set_body(std::string const & value) {
if (value.size() == 0) {
remove_header("Content-Length");
m_body = "";
m_body.clear();
return;
}
// TODO: should this method respect the max size? If so how should errors
// be indicated?
std::stringstream len;
len << value.size();
replace_header("Content-Length", len.str());
@@ -111,26 +116,46 @@ inline bool parser::parse_parameter_list(std::string const & in,
return (it == in.begin());
}
inline bool parser::parse_headers(std::istream & s) {
std::string header;
std::string::size_type end;
// get headers
while (std::getline(s, header) && header != "\r") {
if (header[header.size()-1] != '\r') {
continue; // ignore malformed header lines?
} else {
header.erase(header.end()-1);
}
end = header.find(header_separator,0);
if (end != std::string::npos) {
append_header(header.substr(0,end),header.substr(end+2));
inline bool parser::prepare_body() {
if (!get_header("Content-Length").empty()) {
std::string const & cl_header = get_header("Content-Length");
char * end;
// TODO: not 100% sure what the compatibility of this method is. Also,
// I believe this will only work up to 32bit sizes. Is there a need for
// > 4GiB HTTP payloads?
m_body_bytes_needed = std::strtoul(cl_header.c_str(),&end,10);
if (m_body_bytes_needed > m_body_bytes_max) {
throw exception("HTTP message body too large",
status_code::request_entity_too_large);
}
m_body_encoding = body_encoding::plain;
return true;
} else if (get_header("Transfer-Encoding") == "chunked") {
// TODO
//m_body_encoding = body_encoding::chunked;
return false;
} else {
return false;
}
}
return true;
inline size_t parser::process_body(char const * buf, size_t len) {
if (m_body_encoding == body_encoding::plain) {
size_t processed = (std::min)(m_body_bytes_needed,len);
m_body.append(buf,processed);
m_body_bytes_needed -= processed;
return processed;
} else if (m_body_encoding == body_encoding::chunked) {
// TODO:
throw exception("Unexpected body encoding",
status_code::internal_server_error);
} else {
throw exception("Unexpected body encoding",
status_code::internal_server_error);
}
}
inline void parser::process_header(std::string::iterator begin,
+57 -57
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,6 +30,7 @@
#include <algorithm>
#include <sstream>
#include <string>
#include <websocketpp/http/parser.hpp>
@@ -37,40 +38,17 @@ namespace websocketpp {
namespace http {
namespace parser {
inline bool request::parse_complete(std::istream& s) {
std::string request;
// get status line
std::getline(s, request);
if (request[request.size()-1] == '\r') {
request.erase(request.end()-1);
std::stringstream ss(request);
std::string val;
ss >> val;
set_method(val);
ss >> val;
set_uri(val);
ss >> val;
set_version(val);
} else {
return false;
}
return parse_headers(s);
}
inline size_t request::consume(const char *buf, size_t len) {
inline size_t request::consume(char const * buf, size_t len) {
size_t bytes_processed;
if (m_ready) {return 0;}
if (m_buf->size() + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
if (m_body_bytes_needed > 0) {
bytes_processed = process_body(buf,len);
if (body_ready()) {
m_ready = true;
}
return bytes_processed;
}
// copy new header bytes into buffer
@@ -88,15 +66,21 @@ inline size_t request::consume(const char *buf, size_t len) {
header_delimiter,
header_delimiter+sizeof(header_delimiter)-1
);
//std::cout << "mark5: " << end-begin << std::endl;
//std::cout << "mark6: " << sizeof(header_delimiter) << std::endl;
m_header_bytes += (end-begin+sizeof(header_delimiter));
if (m_header_bytes > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
m_header_bytes -= m_buf->size();
return len;
}
@@ -104,12 +88,11 @@ inline size_t request::consume(const char *buf, size_t len) {
//the range [begin,end) now represents a line to be processed.
if (end-begin == 0) {
// we got a blank line
if (m_method.empty() || get_header("Host") == "") {
if (m_method.empty() || get_header("Host").empty()) {
throw exception("Incomplete Request",status_code::bad_request);
}
m_ready = true;
size_t bytes_processed = (
bytes_processed = (
len - static_cast<std::string::size_type>(m_buf->end()-end)
+ sizeof(header_delimiter) - 1
);
@@ -117,8 +100,22 @@ inline size_t request::consume(const char *buf, size_t len) {
// frees memory used temporarily during request parsing
m_buf.reset();
// return number of bytes processed (starting bytes - bytes left)
return bytes_processed;
// if this was not an upgrade request and has a content length
// continue capturing content-length bytes and expose them as a
// request body.
if (prepare_body()) {
bytes_processed += process_body(buf+bytes_processed,len-bytes_processed);
if (body_ready()) {
m_ready = true;
}
return bytes_processed;
} else {
m_ready = true;
// return number of bytes processed (starting bytes - bytes left)
return bytes_processed;
}
} else {
if (m_method.empty()) {
this->process(begin,end);
@@ -127,21 +124,31 @@ inline size_t request::consume(const char *buf, size_t len) {
}
}
begin = end+sizeof(header_delimiter)-1;
begin = end+(sizeof(header_delimiter)-1);
}
}
inline std::string request::raw() {
inline std::string request::raw() const {
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
std::stringstream ret;
raw << m_method << " " << m_uri << " " << get_version() << "\r\n";
raw << raw_headers() << "\r\n" << m_body;
ret << m_method << " " << m_uri << " " << get_version() << "\r\n";
ret << raw_headers() << "\r\n" << m_body;
return raw.str();
return ret.str();
}
inline void request::set_method(const std::string& method) {
inline std::string request::raw_head() const {
// TODO: validation. Make sure all required fields have been set?
std::stringstream ret;
ret << m_method << " " << m_uri << " " << get_version() << "\r\n";
ret << raw_headers() << "\r\n";
return ret.str();
}
inline void request::set_method(std::string const & method) {
if (std::find_if(method.begin(),method.end(),is_not_token_char) != method.end()) {
throw exception("Invalid method token.",status_code::bad_request);
}
@@ -149,14 +156,7 @@ inline void request::set_method(const std::string& method) {
m_method = method;
}
/// Set HTTP body
/**
* Sets the body of the HTTP object and fills in the appropriate content length
* header
*
* @param value The value to set the body to.
*/
inline void request::set_uri(const std::string& uri) {
inline void request::set_uri(std::string const & uri) {
// TODO: validation?
m_uri = uri;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,7 +29,9 @@
#define HTTP_PARSER_RESPONSE_IMPL_HPP
#include <algorithm>
#include <istream>
#include <sstream>
#include <string>
#include <websocketpp/http/parser.hpp>
@@ -37,19 +39,13 @@ namespace websocketpp {
namespace http {
namespace parser {
inline size_t response::consume(const char *buf, size_t len) {
inline size_t response::consume(char const * buf, size_t len) {
if (m_state == DONE) {return 0;}
if (m_state == BODY) {
return this->process_body(buf,len);
}
if (m_read + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
// copy new header bytes into buffer
m_buf->append(buf,len);
@@ -67,13 +63,22 @@ inline size_t response::consume(const char *buf, size_t len) {
header_delimiter + sizeof(header_delimiter) - 1
);
m_header_bytes += (end-begin+sizeof(header_delimiter));
if (m_header_bytes > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
m_read +=len;
m_read += len;
m_header_bytes -= m_buf->size();
return len;
}
@@ -89,7 +94,7 @@ inline size_t response::consume(const char *buf, size_t len) {
// TODO: grab content-length
std::string length = get_header("Content-Length");
if (length == "") {
if (length.empty()) {
// no content length found, read indefinitely
m_read = 0;
} else {
@@ -170,45 +175,17 @@ inline size_t response::consume(std::istream & s) {
return total;
}
inline bool response::parse_complete(std::istream& s) {
// parse a complete header (ie \r\n\r\n MUST be in the input stream)
std::string response;
// get status line
std::getline(s, response);
if (response[response.size()-1] == '\r') {
response.erase(response.end()-1);
std::stringstream ss(response);
std::string str_val;
int int_val;
char char_val[256];
ss >> str_val;
set_version(str_val);
ss >> int_val;
ss.getline(char_val,256);
set_status(status_code::value(int_val),std::string(char_val));
} else {
return false;
}
return parse_headers(s);
}
inline std::string response::raw() const {
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
std::stringstream ret;
raw << get_version() << " " << m_status_code << " " << m_status_msg;
raw << "\r\n" << raw_headers() << "\r\n";
ret << get_version() << " " << m_status_code << " " << m_status_msg;
ret << "\r\n" << raw_headers() << "\r\n";
raw << m_body;
ret << m_body;
return raw.str();
return ret.str();
}
inline void response::set_status(status_code::value code) {
@@ -217,7 +194,7 @@ inline void response::set_status(status_code::value code) {
m_status_msg = get_string(code);
}
inline void response::set_status(status_code::value code, const std::string&
inline void response::set_status(status_code::value code, std::string const &
msg)
{
// TODO: validation?
@@ -255,7 +232,7 @@ inline void response::process(std::string::iterator begin,
set_status(status_code::value(code),std::string(cursor_end+1,end));
}
inline size_t response::process_body(const char *buf, size_t len) {
inline size_t response::process_body(char const * buf, size_t len) {
// If no content length was set then we read forever and never set m_ready
if (m_read == 0) {
//m_body.append(buf,len);
+105 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,8 +29,9 @@
#define HTTP_PARSER_HPP
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <websocketpp/utilities.hpp>
#include <websocketpp/http/constants.hpp>
@@ -48,6 +49,14 @@ namespace state {
};
}
namespace body_encoding {
enum value {
unknown,
plain,
chunked
};
}
typedef std::map<std::string, std::string, utility::ci_less > header_list;
/// Read and return the next token in the stream
@@ -221,7 +230,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end,
cursor = http::parser::extract_all_lws(cursor,end);
ret = http::parser::extract_token(cursor,end);
if (ret.first == "") {
if (ret.first.empty()) {
// error: expected a token
return begin;
} else {
@@ -233,7 +242,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end,
if (cursor == end || *cursor != '=') {
// if there is an equals sign, read the attribute value. Otherwise
// record a blank value and continue
attributes[name] = "";
attributes[name].clear();
continue;
}
@@ -254,7 +263,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end,
}
ret = http::parser::extract_token(cursor,end);
if (ret.first == "") {
if (ret.first.empty()) {
// error : expected token or quoted string
return begin;
} else {
@@ -312,7 +321,7 @@ InputIterator extract_parameters(InputIterator begin, InputIterator end,
ret = http::parser::extract_token(cursor,end);
if (ret.first == "") {
if (ret.first.empty()) {
// error: expected a token
return begin;
} else {
@@ -369,9 +378,16 @@ InputIterator extract_parameters(InputIterator begin, InputIterator end,
inline std::string strip_lws(std::string const & input) {
std::string::const_iterator begin = extract_all_lws(input.begin(),input.end());
std::string::const_reverse_iterator end = extract_all_lws(input.rbegin(),input.rend());
if (begin == input.end()) {
return std::string();
}
return std::string(begin,end.base());
std::string::const_reverse_iterator rbegin = extract_all_lws(input.rbegin(),input.rend());
if (rbegin == input.rend()) {
return std::string();
}
return std::string(begin,rbegin.base());
}
/// Base HTTP parser
@@ -381,6 +397,12 @@ inline std::string strip_lws(std::string const & input) {
*/
class parser {
public:
parser()
: m_header_bytes(0)
, m_body_bytes_needed(0)
, m_body_bytes_max(max_body_size)
, m_body_encoding(body_encoding::unknown) {}
/// Get the HTTP version string
/**
* @return The version string for this parser
@@ -464,12 +486,11 @@ public:
*/
void remove_header(std::string const & key);
/// Set HTTP body
/// Get HTTP body
/**
* Sets the body of the HTTP object and fills in the appropriate content
* length header.
* Gets the body of the HTTP object
*
* @param [in] value The value to set the body to.
* @return The body of the HTTP message.
*/
std::string const & get_body() const {
return m_body;
@@ -486,6 +507,32 @@ public:
*/
void set_body(std::string const & value);
/// Get body size limit
/**
* Retrieves the maximum number of bytes to parse & buffer before canceling
* a request.
*
* @since 0.5.0
*
* @return The maximum length of a message body.
*/
size_t get_max_body_size() const {
return m_body_bytes_max;
}
/// Set body size limit
/**
* Set the maximum number of bytes to parse and buffer before canceling a
* request.
*
* @since 0.5.0
*
* @param value The size to set the max body length to.
*/
void set_max_body_size(size_t value) {
m_body_bytes_max = value;
}
/// Extract an HTTP parameter list from a string.
/**
* @param [in] in The input string.
@@ -495,14 +542,6 @@ public:
bool parse_parameter_list(std::string const & in, parameter_list & out)
const;
protected:
/// Parse headers from an istream
/**
* @deprecated Use process_header instead.
*
* @param [in] s The istream to extract headers from.
*/
bool parse_headers(std::istream & s);
/// Process a header line
/**
* @todo Update this method to be exception free.
@@ -512,6 +551,45 @@ protected:
*/
void process_header(std::string::iterator begin, std::string::iterator end);
/// Prepare the parser to begin parsing body data
/**
* Inspects headers to determine if the message has a body that needs to be
* read. If so, sets up the necessary state, otherwise returns false. If
* this method returns true and loading the message body is desired call
* `process_body` until it returns zero bytes or an error.
*
* Must not be called until after all headers have been processed.
*
* @since 0.5.0
*
* @return True if more bytes are needed to load the body, false otherwise.
*/
bool prepare_body();
/// Process body data
/**
* Parses body data.
*
* @since 0.5.0
*
* @param [in] begin An iterator to the beginning of the sequence.
* @param [in] end An iterator to the end of the sequence.
* @return The number of bytes processed
*/
size_t process_body(char const * buf, size_t len);
/// Check if the parser is done parsing the body
/**
* Behavior before a call to `prepare_body` is undefined.
*
* @since 0.5.0
*
* @return True if the message body has been completed loaded.
*/
bool body_ready() const {
return (m_body_bytes_needed == 0);
}
/// Generate and return the HTTP headers as a string
/**
* Each headers will be followed by the \r\n sequence including the last one.
@@ -523,7 +601,13 @@ protected:
std::string m_version;
header_list m_headers;
std::string m_body;
size_t m_header_bytes;
std::string m_body;
size_t m_body_bytes_needed;
size_t m_body_bytes_max;
body_encoding::value m_body_encoding;
};
} // namespace parser
+14 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,8 @@
#ifndef HTTP_PARSER_REQUEST_HPP
#define HTTP_PARSER_REQUEST_HPP
#include <string>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/http/parser.hpp>
@@ -51,12 +53,9 @@ public:
typedef lib::shared_ptr<type> ptr;
request()
: m_buf(new std::string())
: m_buf(lib::make_shared<std::string>())
, m_ready(false) {}
/// DEPRECATED parse a complete header (\r\n\r\n MUST be in the istream)
bool parse_complete(std::istream& s);
/// Process bytes in the input buffer
/**
* Process up to len bytes from input buffer buf. Returns the number of
@@ -77,29 +76,32 @@ public:
* @param len Size of byte buffer
* @return Number of bytes processed.
*/
size_t consume(const char *buf, size_t len);
size_t consume(char const * buf, size_t len);
/// Returns whether or not the request is ready for reading.
bool ready() const {
return m_ready;
}
/// Returns the full raw request
std::string raw();
/// Returns the full raw request (including the body)
std::string raw() const;
/// Returns the raw request headers only (similar to an HTTP HEAD request)
std::string raw_head() const;
/// Set the HTTP method. Must be a valid HTTP token
void set_method(const std::string& method);
void set_method(std::string const & method);
/// Return the request method
const std::string& get_method() const {
std::string const & get_method() const {
return m_method;
}
/// Set the HTTP uri. Must be a valid HTTP uri
void set_uri(const std::string& uri);
void set_uri(std::string const & uri);
/// Return the requested URI
const std::string& get_uri() const {
std::string const & get_uri() const {
return m_uri;
}
+28 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,9 @@
#ifndef HTTP_PARSER_RESPONSE_HPP
#define HTTP_PARSER_RESPONSE_HPP
#include <iostream>
#include <string>
#include <websocketpp/http/parser.hpp>
namespace websocketpp {
@@ -58,7 +61,7 @@ public:
response()
: m_read(0)
, m_buf(new std::string())
, m_buf(lib::make_shared<std::string>())
, m_status_code(status_code::uninitialized)
, m_state(RESPONSE_LINE) {}
@@ -82,8 +85,28 @@ public:
* @param len Size of byte buffer
* @return Number of bytes processed.
*/
size_t consume(const char *buf, size_t len);
size_t consume(char const * buf, size_t len);
/// Process bytes in the input buffer (istream version)
/**
* Process bytes from istream s. Returns the number of bytes processed.
* Bytes left unprocessed means bytes left over after the final header
* delimiters.
*
* Consume is a streaming processor. It may be called multiple times on one
* response and the full headers need not be available before processing can
* begin. If the end of the response was reached during this call to consume
* the ready flag will be set. Further calls to consume once ready will be
* ignored.
*
* Consume will throw an http::exception in the case of an error. Typical
* error reasons include malformed responses, incomplete responses, and max
* header size being reached.
*
* @param buf Pointer to byte buffer
* @param len Size of byte buffer
* @return Number of bytes processed.
*/
size_t consume(std::istream & s);
/// Returns true if the response is ready.
@@ -99,9 +122,6 @@ public:
return (m_state == BODY || m_state == DONE);
}
/// DEPRECATED parse a complete response from a pre-delimited istream
bool parse_complete(std::istream& s);
/// Returns the full raw response
std::string raw() const;
@@ -126,7 +146,7 @@ public:
* @param code Code to set
* @param msg Message to set
*/
void set_status(status_code::value code, const std::string& msg);
void set_status(status_code::value code, std::string const & msg);
/// Return the response status code
status_code::value get_status_code() const {
@@ -142,7 +162,7 @@ private:
void process(std::string::iterator begin, std::string::iterator end);
/// Helper function for processing body bytes
size_t process_body(const char *buf, size_t len);
size_t process_body(char const * buf, size_t len);
enum state {
RESPONSE_LINE = 0,
File diff suppressed because it is too large. Load diff
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,8 @@
#ifndef WEBSOCKETPP_ENDPOINT_IMPL_HPP
#define WEBSOCKETPP_ENDPOINT_IMPL_HPP
#include <string>
namespace websocketpp {
template <typename connection, typename config>
@@ -42,8 +44,8 @@ endpoint<connection,config>::create_connection() {
//scoped_lock_type guard(m_mutex);
// Create a connection on the heap and manage it using a shared pointer
connection_ptr con(new connection_type(m_is_server,m_user_agent,m_alog,
m_elog, m_rng));
connection_ptr con = lib::make_shared<connection_type>(m_is_server,
m_user_agent, lib::ref(m_alog), lib::ref(m_elog), lib::ref(m_rng));
connection_weak_ptr w(con);
@@ -64,16 +66,20 @@ endpoint<connection,config>::create_connection() {
con->set_http_handler(m_http_handler);
con->set_validate_handler(m_validate_handler);
con->set_message_handler(m_message_handler);
if (m_open_handshake_timeout_dur == config::timeout_open_handshake) {
if (m_open_handshake_timeout_dur != config::timeout_open_handshake) {
con->set_open_handshake_timeout(m_open_handshake_timeout_dur);
}
if (m_close_handshake_timeout_dur == config::timeout_close_handshake) {
if (m_close_handshake_timeout_dur != config::timeout_close_handshake) {
con->set_close_handshake_timeout(m_close_handshake_timeout_dur);
}
if (m_pong_timeout_dur == config::timeout_pong) {
if (m_pong_timeout_dur != config::timeout_pong) {
con->set_pong_timeout(m_pong_timeout_dur);
}
if (m_max_message_size != config::max_message_size) {
con->set_max_message_size(m_max_message_size);
}
con->set_max_http_body_size(m_max_http_body_size);
lib::error_code ec;
@@ -87,8 +93,7 @@ endpoint<connection,config>::create_connection() {
}
template <typename connection, typename config>
void endpoint<connection,config>::interrupt(connection_hdl hdl,
lib::error_code & ec)
void endpoint<connection,config>::interrupt(connection_hdl hdl, lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
@@ -102,12 +107,60 @@ template <typename connection, typename config>
void endpoint<connection,config>::interrupt(connection_hdl hdl) {
lib::error_code ec;
interrupt(hdl,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
void endpoint<connection,config>::send(connection_hdl hdl, std::string const &
payload, frame::opcode::value op, lib::error_code & ec)
void endpoint<connection,config>::pause_reading(connection_hdl hdl, lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
ec = con->pause_reading();
}
template <typename connection, typename config>
void endpoint<connection,config>::pause_reading(connection_hdl hdl) {
lib::error_code ec;
pause_reading(hdl,ec);
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
void endpoint<connection,config>::resume_reading(connection_hdl hdl, lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
ec = con->resume_reading();
}
template <typename connection, typename config>
void endpoint<connection,config>::resume_reading(connection_hdl hdl) {
lib::error_code ec;
resume_reading(hdl,ec);
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
void endpoint<connection,config>::send_http_response(connection_hdl hdl,
lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
con->send_http_response(ec);
}
template <typename connection, typename config>
void endpoint<connection,config>::send_http_response(connection_hdl hdl) {
lib::error_code ec;
send_http_response(hdl,ec);
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
void endpoint<connection,config>::send(connection_hdl hdl, std::string const & payload,
frame::opcode::value op, lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
@@ -116,12 +169,12 @@ void endpoint<connection,config>::send(connection_hdl hdl, std::string const &
}
template <typename connection, typename config>
void endpoint<connection,config>::send(connection_hdl hdl, std::string const &
payload, frame::opcode::value op)
void endpoint<connection,config>::send(connection_hdl hdl, std::string const & payload,
frame::opcode::value op)
{
lib::error_code ec;
send(hdl,payload,op,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
@@ -139,7 +192,7 @@ void endpoint<connection,config>::send(connection_hdl hdl, void const * payload,
{
lib::error_code ec;
send(hdl,payload,len,op,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
@@ -155,7 +208,7 @@ template <typename connection, typename config>
void endpoint<connection,config>::send(connection_hdl hdl, message_ptr msg) {
lib::error_code ec;
send(hdl,msg,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
@@ -174,7 +227,7 @@ void endpoint<connection,config>::close(connection_hdl hdl, close::status::value
{
lib::error_code ec;
close(hdl,code,reason,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
@@ -187,17 +240,16 @@ void endpoint<connection,config>::ping(connection_hdl hdl, std::string const &
}
template <typename connection, typename config>
void endpoint<connection,config>::ping(connection_hdl hdl, std::string const &
payload)
void endpoint<connection,config>::ping(connection_hdl hdl, std::string const & payload)
{
lib::error_code ec;
ping(hdl,payload,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
template <typename connection, typename config>
void endpoint<connection,config>::pong(connection_hdl hdl, std::string const &
payload, lib::error_code & ec)
void endpoint<connection,config>::pong(connection_hdl hdl, std::string const & payload,
lib::error_code & ec)
{
connection_ptr con = get_con_from_hdl(hdl,ec);
if (ec) {return;}
@@ -205,12 +257,11 @@ void endpoint<connection,config>::pong(connection_hdl hdl, std::string const &
}
template <typename connection, typename config>
void endpoint<connection,config>::pong(connection_hdl hdl, std::string const &
payload)
void endpoint<connection,config>::pong(connection_hdl hdl, std::string const & payload)
{
lib::error_code ec;
pong(hdl,payload,ec);
if (ec) { throw ec; }
if (ec) { throw exception(ec); }
}
} // namespace websocketpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,9 @@
#ifndef WEBSOCKETPP_UTILITIES_IMPL_HPP
#define WEBSOCKETPP_UTILITIES_IMPL_HPP
#include <algorithm>
#include <string>
namespace websocketpp {
namespace utility {
@@ -37,7 +40,7 @@ inline std::string to_lower(std::string const & in) {
return out;
}
inline std::string to_hex(const std::string& input) {
inline std::string to_hex(std::string const & input) {
std::string output;
std::string hex = "0123456789ABCDEF";
@@ -50,7 +53,7 @@ inline std::string to_hex(const std::string& input) {
return output;
}
inline std::string to_hex(const uint8_t* input,size_t length) {
inline std::string to_hex(uint8_t const * input, size_t length) {
std::string output;
std::string hex = "0123456789ABCDEF";
@@ -67,8 +70,8 @@ inline std::string to_hex(const char* input,size_t length) {
return to_hex(reinterpret_cast<const uint8_t*>(input),length);
}
inline std::string string_replace_all(std::string subject, const std::string&
search, const std::string& replace)
inline std::string string_replace_all(std::string subject, std::string const &
search, std::string const & replace)
{
size_t pos = 0;
while((pos = subject.find(search, pos)) != std::string::npos) {
+71 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -40,13 +40,16 @@
*
*/
#include <ctime>
#include <iostream>
#include <iomanip>
#include <websocketpp/logger/levels.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/stdint.hpp>
#include <websocketpp/logger/levels.hpp>
#include <websocketpp/common/time.hpp>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <string>
namespace websocketpp {
namespace log {
@@ -55,16 +58,58 @@ namespace log {
template <typename concurrency, typename names>
class basic {
public:
basic<concurrency,names>(std::ostream * out = &std::cout)
basic<concurrency,names>(channel_type_hint::value h =
channel_type_hint::access)
: m_static_channels(0xffffffff)
, m_dynamic_channels(0)
, m_out(h == channel_type_hint::error ? &std::cerr : &std::cout) {}
basic<concurrency,names>(std::ostream * out)
: m_static_channels(0xffffffff)
, m_dynamic_channels(0)
, m_out(out) {}
basic<concurrency,names>(level c, std::ostream * out = &std::cout)
basic<concurrency,names>(level c, channel_type_hint::value h =
channel_type_hint::access)
: m_static_channels(c)
, m_dynamic_channels(0)
, m_out(h == channel_type_hint::error ? &std::cerr : &std::cout) {}
basic<concurrency,names>(level c, std::ostream * out)
: m_static_channels(c)
, m_dynamic_channels(0)
, m_out(out) {}
/// Destructor
~basic<concurrency,names>() {}
/// Copy constructor
basic<concurrency,names>(basic<concurrency,names> const & other)
: m_static_channels(other.m_static_channels)
, m_dynamic_channels(other.m_dynamic_channels)
, m_out(other.m_out)
{}
#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
// no copy assignment operator because of const member variables
basic<concurrency,names> & operator=(basic<concurrency,names> const &) = delete;
#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
/// Move constructor
basic<concurrency,names>(basic<concurrency,names> && other)
: m_static_channels(other.m_static_channels)
, m_dynamic_channels(other.m_dynamic_channels)
, m_out(other.m_out)
{}
#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
// no move assignment operator because of const member variables
basic<concurrency,names> & operator=(basic<concurrency,names> &&) = delete;
#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
#endif // _WEBSOCKETPP_MOVE_SEMANTICS_
void set_ostream(std::ostream * out = &std::cout) {
m_out = out;
}
@@ -84,6 +129,11 @@ public:
m_dynamic_channels &= ~channels;
}
/// Write a string message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, std::string const & msg) {
scoped_lock_type lock(m_lock);
if (!this->dynamic_test(channel)) { return; }
@@ -93,6 +143,11 @@ public:
m_out->flush();
}
/// Write a cstring message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, char const * msg) {
scoped_lock_type lock(m_lock);
if (!this->dynamic_test(channel)) { return; }
@@ -109,10 +164,13 @@ public:
bool dynamic_test(level channel) {
return ((channel & m_dynamic_channels) != 0);
}
private:
protected:
typedef typename concurrency::scoped_lock_type scoped_lock_type;
typedef typename concurrency::mutex_type mutex_type;
mutex_type m_lock;
private:
// The timestamp does not include the time zone, because on Windows with the
// default registry settings, the time zone would be written out in full,
// which would be obnoxiously verbose.
@@ -120,18 +178,16 @@ private:
// TODO: find a workaround for this or make this format user settable
static std::ostream & timestamp(std::ostream & os) {
std::time_t t = std::time(NULL);
std::tm* lt = std::localtime(&t);
#ifdef _WEBSOCKETPP_CPP11_CHRONO_
return os << std::put_time(lt,"%Y-%m-%d %H:%M:%S");
std::tm lt = lib::localtime(t);
#ifdef _WEBSOCKETPP_PUTTIME_
return os << std::put_time(&lt,"%Y-%m-%d %H:%M:%S");
#else // Falls back to strftime, which requires a temporary copy of the string.
char buffer[20];
std::strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",lt);
return os << buffer;
size_t result = std::strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",&lt);
return os << (result == 0 ? "Unknown" : buffer);
#endif
}
mutex_type m_lock;
level const m_static_channels;
level m_dynamic_channels;
std::ostream * m_out;
+31 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -36,6 +36,25 @@ namespace log {
/// Type of a channel package
typedef uint32_t level;
/// Package of values for hinting at the nature of a given logger.
/**
* Used by the library to signal to the logging class a hint that it can use to
* set itself up. For example, the `access` hint indicates that it is an access
* log that might be suitable for being printed to an access log file or to cout
* whereas `error` might be suitable for an error log file or cerr.
*/
struct channel_type_hint {
/// Type of a channel type hint value
typedef uint32_t value;
/// No information
static value const none = 0;
/// Access log
static value const access = 1;
/// Error log
static value const error = 2;
};
/// Package of log levels for logging errors
struct elevel {
/// Special aggregate value representing "no levels"
@@ -122,6 +141,13 @@ struct alevel {
static level const devel = 0x400;
/// Special channel for application specific logs. Not used by the library.
static level const app = 0x800;
/// Access related to HTTP requests
static level const http = 0x1000;
/// One line for each failed WebSocket connection with details
static level const fail = 0x2000;
/// Aggregate package representing the commonly used core access channels
/// Connect, Disconnect, Fail, and HTTP
static level const access_core = 0x00003003;
/// Special aggregate value representing "all levels"
static level const all = 0xffffffff;
@@ -161,6 +187,10 @@ struct alevel {
return "devel";
case app:
return "application";
case http:
return "http";
case fail:
return "fail";
default:
return "unknown";
}
+67 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,10 +28,11 @@
#ifndef WEBSOCKETPP_LOGGER_STUB_HPP
#define WEBSOCKETPP_LOGGER_STUB_HPP
#include <iostream>
#include <websocketpp/logger/levels.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/logger/levels.hpp>
#include <string>
namespace websocketpp {
namespace log {
@@ -39,20 +40,75 @@ namespace log {
/// Stub logger that ignores all input
class stub {
public:
explicit stub(std::ostream * out) {}
stub(level c, std::ostream * out) {}
/// Construct the logger
/**
* @param hint A channel type specific hint for how to construct the logger
*/
explicit stub(channel_type_hint::value) {}
/// Construct the logger
/**
* @param default_channels A set of channels to statically enable
* @param hint A channel type specific hint for how to construct the logger
*/
stub(level, channel_type_hint::value) {}
_WEBSOCKETPP_CONSTEXPR_TOKEN_ stub() {}
void set_channels(level channels) {}
void clear_channels(level channels) {}
/// Dynamically enable the given list of channels
/**
* All operations on the stub logger are no-ops and all arguments are
* ignored
*
* @param channels The package of channels to enable
*/
void set_channels(level) {}
void write(level channel, std::string const & msg) {}
void write(level channel, char const * msg) {}
/// Dynamically disable the given list of channels
/**
* All operations on the stub logger are no-ops and all arguments are
* ignored
*
* @param channels The package of channels to disable
*/
void clear_channels(level) {}
_WEBSOCKETPP_CONSTEXPR_TOKEN_ bool static_test(level channel) const {
/// Write a string message to the given channel
/**
* Writing on the stub logger is a no-op and all arguments are ignored
*
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level, std::string const &) {}
/// Write a cstring message to the given channel
/**
* Writing on the stub logger is a no-op and all arguments are ignored
*
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level, char const *) {}
/// Test whether a channel is statically enabled
/**
* The stub logger has no channels so all arguments are ignored and
* `static_test` always returns false.
*
* @param channel The package of channels to test
*/
_WEBSOCKETPP_CONSTEXPR_TOKEN_ bool static_test(level) const {
return false;
}
bool dynamic_test(level channel) {
/// Test whether a channel is dynamically enabled
/**
* The stub logger has no channels so all arguments are ignored and
* `dynamic_test` always returns false.
*
* @param channel The package of channels to test
*/
bool dynamic_test(level) {
return false;
}
};
@@ -0,0 +1,146 @@
/*
* Copyright (c) 2014, Peter Thorson. 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 WebSocket++ Project 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 PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The initial version of this logging policy was contributed to the WebSocket++
* project by Tom Hughes.
*/
#ifndef WEBSOCKETPP_LOGGER_SYSLOG_HPP
#define WEBSOCKETPP_LOGGER_SYSLOG_HPP
#include <syslog.h>
#include <websocketpp/logger/basic.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/logger/levels.hpp>
namespace websocketpp {
namespace log {
/// Basic logger that outputs to syslog
template <typename concurrency, typename names>
class syslog : public basic<concurrency, names> {
public:
typedef basic<concurrency, names> base;
/// Construct the logger
/**
* @param hint A channel type specific hint for how to construct the logger
*/
syslog<concurrency,names>(channel_type_hint::value hint =
channel_type_hint::access)
: basic<concurrency,names>(hint), m_channel_type_hint(hint) {}
/// Construct the logger
/**
* @param channels A set of channels to statically enable
* @param hint A channel type specific hint for how to construct the logger
*/
syslog<concurrency,names>(level channels, channel_type_hint::value hint =
channel_type_hint::access)
: basic<concurrency,names>(channels, hint), m_channel_type_hint(hint) {}
/// Write a string message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, std::string const & msg) {
write(channel, msg.c_str());
}
/// Write a cstring message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, char const * msg) {
scoped_lock_type lock(base::m_lock);
if (!this->dynamic_test(channel)) { return; }
::syslog(syslog_priority(channel), "[%s] %s",
names::channel_name(channel), msg);
}
private:
typedef typename base::scoped_lock_type scoped_lock_type;
/// The default level is used for all access logs and any error logs that
/// don't trivially map to one of the standard syslog levels.
static int const default_level = LOG_INFO;
/// retrieve the syslog priority code given a WebSocket++ channel
/**
* @param channel The level to look up
* @return The syslog level associated with `channel`
*/
int syslog_priority(level channel) const {
if (m_channel_type_hint == channel_type_hint::access) {
return syslog_priority_access(channel);
} else {
return syslog_priority_error(channel);
}
}
/// retrieve the syslog priority code given a WebSocket++ error channel
/**
* @param channel The level to look up
* @return The syslog level associated with `channel`
*/
int syslog_priority_error(level channel) const {
switch (channel) {
case elevel::devel:
return LOG_DEBUG;
case elevel::library:
return LOG_DEBUG;
case elevel::info:
return LOG_INFO;
case elevel::warn:
return LOG_WARNING;
case elevel::rerror:
return LOG_ERR;
case elevel::fatal:
return LOG_CRIT;
default:
return default_level;
}
}
/// retrieve the syslog priority code given a WebSocket++ access channel
/**
* @param channel The level to look up
* @return The syslog level associated with `channel`
*/
_WEBSOCKETPP_CONSTEXPR_TOKEN_ int syslog_priority_access(level) const {
return default_level;
}
channel_type_hint::value m_channel_type_hint;
};
} // log
} // websocketpp
#endif // WEBSOCKETPP_LOGGER_SYSLOG_HPP
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -53,7 +53,7 @@ public:
* @return A shared pointer to an empty new message
*/
message_ptr get_message() {
return message_ptr(new message(type::shared_from_this()));
return message_ptr(lib::make_shared<message>(type::shared_from_this()));
}
/// Get a message buffer with specified size and opcode
@@ -64,7 +64,7 @@ public:
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(frame::opcode::value op,size_t size) {
return message_ptr(new message(type::shared_from_this(),op,size));
return message_ptr(lib::make_shared<message>(type::shared_from_this(),op,size));
}
/// Recycle a message
@@ -77,7 +77,7 @@ public:
*
* @return true if the message was successfully recycled, false otherwse.
*/
bool recycle(message * msg) {
bool recycle(message *) {
return false;
}
};
@@ -94,7 +94,7 @@ public:
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
return con_msg_man_ptr(lib::make_shared<con_msg_manager>());
}
};
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -43,7 +43,7 @@ namespace message_buffer {
*
* # connection_message_manager:
* An object that manages all of the message_buffers associated with a given
* connection. Impliments the get_message_buffer(size) method that returns
* connection. Implements the get_message_buffer(size) method that returns
* a message buffer at least size bytes long.
*
* Message buffers are reference counted with shared ownership semantics. Once
@@ -54,7 +54,7 @@ namespace message_buffer {
* in the manager.
*
* # endpoint_message_manager:
* An object that manages connection_message_managers. Impliments the
* An object that manages connection_message_managers. Implements the
* get_message_manager() method. This is used once by each connection to
* request the message manager that they are supposed to use to manage message
* buffers for their own use.
@@ -146,10 +146,10 @@ public:
/// Set or clear the compression flag
/**
* The compression flag is used to indicate whether or not the message is
* or should be compressed. Compression is not guaranteed. Both endpoints
* must support a compression extension and the connection must have had
* that extension negotiated in its handshake.
* Setting the compression flag indicates that the data in this message
* would benefit from compression. If both endpoints negotiate a compression
* extension WebSocket++ will attempt to compress messages with this flag.
* Setting this flag does not guarantee that the message will be compressed.
*
* @param value The value to set the compressed flag to
*/
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Peter Thorson. All rights reserved.
* Copyright (c) 2014, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -42,7 +42,7 @@ namespace message_buffer {
*
* # connection_message_manager:
* An object that manages all of the message_buffers associated with a given
* connection. Impliments the get_message_buffer(size) method that returns
* connection. Implements the get_message_buffer(size) method that returns
* a message buffer at least size bytes long.
*
* Message buffers are reference counted with shared ownership semantics. Once
@@ -53,7 +53,7 @@ namespace message_buffer {
* in the manager.
*
* # endpoint_message_manager:
* An object that manages connection_message_managers. Impliments the
* An object that manages connection_message_managers. Implements the
* get_message_manager() method. This is used once by each connection to
* request the message manager that they are supposed to use to manage message
* buffers for their own use.
@@ -171,7 +171,7 @@ public:
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(size_t size) const {
return message_ptr(new message(size));
return lib::make_shared<message>(size);
}
/// Recycle a message
@@ -201,7 +201,7 @@ public:
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
return lib::make_shared<con_msg_manager>();
}
};
Loaded 100 of 133 files, more files were not shown because too many files have changed in this diff. Show more