mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 00:54:40 +00:00
ArchBlackmann irc bot - works in ReactOS - happy hacking
svn path=/trunk/; revision=12289
This commit is contained in:
parent
f781714ac5
commit
089686cac2
31 changed files with 3845 additions and 0 deletions
5
rosapps/games/ArchBlackmann/.cvsignore
Normal file
5
rosapps/games/ArchBlackmann/.cvsignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
*.ncb
|
||||||
|
*.opt
|
||||||
|
*.plg
|
||||||
|
Debug
|
||||||
|
Release
|
123
rosapps/games/ArchBlackmann/ArchBlackmann.cpp
Normal file
123
rosapps/games/ArchBlackmann/ArchBlackmann.cpp
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// irc_test.cpp
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning ( disable : 4786 )
|
||||||
|
#endif//_MSC_VER
|
||||||
|
|
||||||
|
#include <conio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "IRCClient.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
// do custom stuff with the IRCClient from your subclass via the provided callbacks...
|
||||||
|
class MyIRCClient : public IRCClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// see IRCClient.h for documentation on these callbacks...
|
||||||
|
bool OnConnected()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnJoin ( const string& user, const string& channel )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnEndChannelUsers ( const string& channel )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnPrivMsg ( const string& from, const string& text )
|
||||||
|
{
|
||||||
|
printf ( "<%s> %s\n", from.c_str(), text.c_str() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnChannelMsg ( const string& channel, const string& from, const string& text )
|
||||||
|
{
|
||||||
|
printf ( "%s <%s> %s\n", channel.c_str(), from.c_str(), text.c_str() );
|
||||||
|
if ( !stricmp ( from.c_str(), "royce3" ) )
|
||||||
|
PrivMsg ( channel, text );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnChannelMode ( const string& channel, const string& mode )
|
||||||
|
{
|
||||||
|
//printf ( "OnChannelMode(%s,%s)\n", channel.c_str(), mode.c_str() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnUserModeInChannel ( const string& src, const string& channel, const string& user, const string& mode )
|
||||||
|
{
|
||||||
|
//printf ( "OnUserModeInChannel(%s,%s%s,%s)\n", src.c_str(), channel.c_str(), user.c_str(), mode.c_str() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnMode ( const string& user, const string& mode )
|
||||||
|
{
|
||||||
|
//printf ( "OnMode(%s,%s)\n", user.c_str(), mode.c_str() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool OnChannelUsers ( const string& channel, const vector<string>& users )
|
||||||
|
{
|
||||||
|
printf ( "[%s has %i users]: ", channel.c_str(), users.size() );
|
||||||
|
for ( int i = 0; i < users.size(); i++ )
|
||||||
|
{
|
||||||
|
if ( i )
|
||||||
|
printf ( ", " );
|
||||||
|
printf ( "%s", users[i].c_str() );
|
||||||
|
}
|
||||||
|
printf ( "\n" );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main ( int argc, char** argv )
|
||||||
|
{
|
||||||
|
printf ( "initializing IRCClient debugging\n" );
|
||||||
|
IRCClient::SetDebug ( true );
|
||||||
|
printf ( "calling suStartup()\n" );
|
||||||
|
suStartup();
|
||||||
|
printf ( "creating IRCClient object\n" );
|
||||||
|
MyIRCClient irc;
|
||||||
|
printf ( "connecting to freenode\n" );
|
||||||
|
if ( !irc.Connect ( "140.211.166.3" ) ) // irc.freenode.net
|
||||||
|
{
|
||||||
|
printf ( "couldn't connect to server\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf ( "sending user command\n" );
|
||||||
|
if ( !irc.User ( "Royce3", "", "irc.freenode.net", "Royce Mitchell III" ) )
|
||||||
|
{
|
||||||
|
printf ( "USER command failed\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf ( "sending nick\n" );
|
||||||
|
if ( !irc.Nick ( "Royce3" ) )
|
||||||
|
{
|
||||||
|
printf ( "NICK command failed\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf ( "setting mode\n" );
|
||||||
|
if ( !irc.Mode ( "+i" ) )
|
||||||
|
{
|
||||||
|
printf ( "MODE command failed\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf ( "joining #ReactOS\n" );
|
||||||
|
if ( !irc.Join ( "#ReactOS" ) )
|
||||||
|
{
|
||||||
|
printf ( "JOIN command failed\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf ( "entering irc client processor\n" );
|
||||||
|
irc.Run ( true ); // do the processing in this thread...
|
||||||
|
string cmd;
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
char c = getch();
|
||||||
|
if ( c == '\n' || c == '\r' )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
196
rosapps/games/ArchBlackmann/ArchBlackmann.dsp
Normal file
196
rosapps/games/ArchBlackmann/ArchBlackmann.dsp
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="ArchBlackmann" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=ArchBlackmann - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "ArchBlackmann.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "ArchBlackmann.mak" CFG="ArchBlackmann - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "ArchBlackmann - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "ArchBlackmann - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "ArchBlackmann - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "ArchBlackmann - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "ArchBlackmann - Win32 Release"
|
||||||
|
# Name "ArchBlackmann - Win32 Debug"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ArchBlackmann.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\auto_ptr.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\auto_vector.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\base64.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\base64.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\chomp.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\chomp.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cram_md5.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cram_md5.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IRCClient.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IRCClient.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\MD5.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\MD5.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\panic.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\panic.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\QueueT.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Reli.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ReliMT.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ReliMT.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\SockUtils.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\SockUtils.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\SplitJoin.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\SplitJoin.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ThreadPool.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ThreadPool.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\trim.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\trim.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\verify.h
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
29
rosapps/games/ArchBlackmann/ArchBlackmann.dsw
Normal file
29
rosapps/games/ArchBlackmann/ArchBlackmann.dsw
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "ArchBlackmann"=.\ArchBlackmann.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
322
rosapps/games/ArchBlackmann/IRCClient.cpp
Normal file
322
rosapps/games/ArchBlackmann/IRCClient.cpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
// IRCClient.cpp
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning ( disable : 4786 )
|
||||||
|
#endif//_MSC_VER
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "IRCClient.h"
|
||||||
|
#include "md5.h"
|
||||||
|
#include "cram_md5.h"
|
||||||
|
#include "trim.h"
|
||||||
|
#include "chomp.h"
|
||||||
|
#include "SplitJoin.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::stringstream;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
bool IRCClient::_debug = true;
|
||||||
|
|
||||||
|
IRCClient::IRCClient()
|
||||||
|
: _timeout(10*60*1000), _inRun(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRCClient::Connect ( const string& server, short port )
|
||||||
|
{
|
||||||
|
string buf;
|
||||||
|
Close();
|
||||||
|
Attach ( suTcpSocket() );
|
||||||
|
if ( !suConnect ( *this, server.c_str(), port ) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::User ( const string& user, const string& mode,
|
||||||
|
const string& network, const string& realname )
|
||||||
|
{
|
||||||
|
string buf;
|
||||||
|
buf = "USER " + user + " \"" + mode + "\" \"" + network + "\" :" + realname + "\n";
|
||||||
|
return Send ( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Nick ( const string& nick )
|
||||||
|
{
|
||||||
|
_nick = nick;
|
||||||
|
return Send ( "NICK " + _nick + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Mode ( const string& mode )
|
||||||
|
{
|
||||||
|
return Send ( "MODE " + _nick + " " + mode + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Names ( const string& channel )
|
||||||
|
{
|
||||||
|
return Send ( "NAMES " + channel + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Mode ( const string& channel, const string& mode, const string& target )
|
||||||
|
{
|
||||||
|
return Send ( "MODE " + channel + " " + mode + " " + target + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Join ( const string& channel )
|
||||||
|
{
|
||||||
|
return Send ( "JOIN " + channel + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::PrivMsg ( const string& to, const string& text )
|
||||||
|
{
|
||||||
|
return Send ( "PRIVMSG " + to + " :" + text + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Part ( const string& channel, const string& text )
|
||||||
|
{
|
||||||
|
return Send ( "PART " + channel + " :" + text + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IRCClient::Quit ( const string& text )
|
||||||
|
{
|
||||||
|
return Send( "QUIT :" + text + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRCClient::_Recv ( string& buf )
|
||||||
|
{
|
||||||
|
bool b = (recvUntil ( buf, '\n', _timeout ) > 0);
|
||||||
|
if ( b && _debug )
|
||||||
|
{
|
||||||
|
printf ( ">> %s", buf.c_str() );
|
||||||
|
if ( buf[buf.length()-1] != '\n' )
|
||||||
|
printf ( "\n" );
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRCClient::Send ( const string& buf )
|
||||||
|
{
|
||||||
|
if ( _debug )
|
||||||
|
{
|
||||||
|
printf ( "<< %s", buf.c_str() );
|
||||||
|
if ( buf[buf.length()-1] != '\n' )
|
||||||
|
printf ( "\n" );
|
||||||
|
}
|
||||||
|
return ( buf.length() == (size_t)send ( *this, buf.c_str(), buf.length(), 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRCClient::OnPing( const string& text )
|
||||||
|
{
|
||||||
|
return Send( "PONG " + text + "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int THREADAPI IRCClient::Callback ( IRCClient* irc )
|
||||||
|
{
|
||||||
|
return irc->Run ( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
int IRCClient::Run ( bool launch_thread )
|
||||||
|
{
|
||||||
|
if ( (SOCKET)*this == INVALID_SOCKET )
|
||||||
|
return 0;
|
||||||
|
if ( _inRun ) return 1;
|
||||||
|
if ( launch_thread )
|
||||||
|
{
|
||||||
|
ThreadPool::Instance().Launch ( (ThreadPoolFunc*)IRCClient::Callback, this );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
_inRun = true;
|
||||||
|
if ( _debug ) printf ( "IRCClient::Run() - waiting for responses\n" );
|
||||||
|
string buf;
|
||||||
|
while ( _Recv(buf) )
|
||||||
|
{
|
||||||
|
if ( !strnicmp ( buf.c_str(), "NOTICE ", 7 ) )
|
||||||
|
{
|
||||||
|
//printf ( "recv'd NOTICE msg...\n" );
|
||||||
|
// TODO...
|
||||||
|
//OnAuth (
|
||||||
|
}
|
||||||
|
else if ( !strnicmp ( buf.c_str(), "PING ", 5 ) )
|
||||||
|
{
|
||||||
|
const char* p = &buf[5]; // point to first char after "PING "
|
||||||
|
while ( *p == ':' ) // then read past the colons
|
||||||
|
p++;
|
||||||
|
const char* p2 = strpbrk ( p, "\r\n" ); // find the end of line
|
||||||
|
string text ( p, p2-p ); // and set the text
|
||||||
|
OnPing( text );
|
||||||
|
}
|
||||||
|
else if ( buf[0] == ':' )
|
||||||
|
{
|
||||||
|
const char* p = &buf[1]; // skip first colon...
|
||||||
|
const char* p2 = strpbrk ( p, " !" );
|
||||||
|
if ( !p2 )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 0: ", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string src ( p, p2-p );
|
||||||
|
if ( !src.length() )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 0.5: %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p = p2 + 1;
|
||||||
|
if ( *p2 == '!' )
|
||||||
|
{
|
||||||
|
p2 = strchr ( p, ' ' );
|
||||||
|
if ( !p2 )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 1: %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//string srchost ( p, p2-p );
|
||||||
|
p = p2 + 1;
|
||||||
|
}
|
||||||
|
p2 = strchr ( p, ' ' );
|
||||||
|
if ( !p2 )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 2: %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string cmd ( p, p2-p );
|
||||||
|
p = p2 + 1;
|
||||||
|
p2 = strpbrk ( p, " :" );
|
||||||
|
if ( !p2 )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 3: %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string tgt ( p, p2-p );
|
||||||
|
p = p2 + 1;
|
||||||
|
p += strspn ( p, " " );
|
||||||
|
if ( *p == '=' )
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
p += strspn ( p, " " );
|
||||||
|
}
|
||||||
|
if ( *p == ':' )
|
||||||
|
p++;
|
||||||
|
p2 = strpbrk ( p, "\r\n" );
|
||||||
|
if ( !p2 )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 4: %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string text ( p, p2-p );
|
||||||
|
strlwr ( &cmd[0] );
|
||||||
|
if ( cmd == "privmsg" )
|
||||||
|
{
|
||||||
|
if ( !tgt.length() )
|
||||||
|
{
|
||||||
|
printf ( "!!!:OnRecv failure 5 (PRIVMSG w/o target): %s", buf.c_str() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( tgt[0] == '#' )
|
||||||
|
OnChannelMsg ( tgt, src, text );
|
||||||
|
else
|
||||||
|
OnPrivMsg ( src, text );
|
||||||
|
}
|
||||||
|
else if ( cmd == "mode" )
|
||||||
|
{
|
||||||
|
// two diff. kinds of mode notifications...
|
||||||
|
//printf ( "[MODE] src='%s' cmd='%s' tgt='%s' text='%s'", src.c_str(), cmd.c_str(), tgt.c_str(), text.c_str() );
|
||||||
|
//OnMode (
|
||||||
|
// self mode change:
|
||||||
|
// [MODE] src=Relic3_14 cmd=mode tgt=Relic3_14 text=+i
|
||||||
|
// channel mode change:
|
||||||
|
// [MODE] src=Royce3 cmd=mode tgt=#Royce3 text=+o Relic3_14
|
||||||
|
if ( tgt[0] == '#' )
|
||||||
|
{
|
||||||
|
p = text.c_str();
|
||||||
|
p2 = strchr ( p, ' ' );
|
||||||
|
if ( !p2 )
|
||||||
|
OnChannelMode ( tgt, text );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string user ( p, p2-p );
|
||||||
|
p = p2 + 1;
|
||||||
|
p += strspn ( p, " " );
|
||||||
|
OnUserModeInChannel ( src, tgt, user, p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
OnMode ( tgt, text );
|
||||||
|
}
|
||||||
|
else if ( cmd == "join" )
|
||||||
|
{
|
||||||
|
OnJoin ( src, text );
|
||||||
|
}
|
||||||
|
else if ( isdigit(cmd[0]) )
|
||||||
|
{
|
||||||
|
int i = atoi(cmd.c_str());
|
||||||
|
switch ( i )
|
||||||
|
{
|
||||||
|
case 1: // "Welcome!" - i.e. it's okay to issue commands now...
|
||||||
|
OnConnected();
|
||||||
|
break;
|
||||||
|
case 353: // user list for channel....
|
||||||
|
{
|
||||||
|
p = text.c_str();
|
||||||
|
p2 = strpbrk ( p, " :" );
|
||||||
|
if ( !p2 ) continue;
|
||||||
|
string channel ( p, p2-p );
|
||||||
|
p = strchr ( p2, ':' );
|
||||||
|
if ( !p ) continue;
|
||||||
|
p++;
|
||||||
|
vector<string> users;
|
||||||
|
while ( *p )
|
||||||
|
{
|
||||||
|
p2 = strchr ( p, ' ' );
|
||||||
|
if ( !p2 )
|
||||||
|
p2 = p + strlen(p);
|
||||||
|
users.push_back ( string ( p, p2-p ) );
|
||||||
|
p = p2+1;
|
||||||
|
p += strspn ( p, " " );
|
||||||
|
}
|
||||||
|
OnChannelUsers ( channel, users );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 366: // END of user list for channel
|
||||||
|
{
|
||||||
|
p = text.c_str();
|
||||||
|
p2 = strpbrk ( p, " :" );
|
||||||
|
if ( !p2 ) continue;
|
||||||
|
string channel ( p, p2-p );
|
||||||
|
OnEndChannelUsers ( channel );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ( _debug ) printf ( "unknown command %i: %s", i, buf.c_str() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( _debug ) printf ( "unrecognized ':' response: %s", buf.c_str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( _debug ) printf ( "unrecognized irc msg: %s", buf.c_str() );
|
||||||
|
}
|
||||||
|
//OnRecv ( buf );
|
||||||
|
}
|
||||||
|
if ( _debug ) printf ( "IRCClient::Run() - exiting\n" );
|
||||||
|
_inRun = false;
|
||||||
|
return 0;
|
||||||
|
}
|
124
rosapps/games/ArchBlackmann/IRCClient.h
Normal file
124
rosapps/games/ArchBlackmann/IRCClient.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
// IRCClient.h
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef IRCCLIENT_H
|
||||||
|
#define IRCCLIENT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "SockUtils.h"
|
||||||
|
#include "ThreadPool.h"
|
||||||
|
|
||||||
|
class IRCClient : public suBufferedRecvSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRCClient();
|
||||||
|
|
||||||
|
static bool GetDebug() { return _debug; }
|
||||||
|
static bool SetDebug ( bool debug ) { bool old = _debug; _debug = debug; return old; }
|
||||||
|
|
||||||
|
// connect to server ( record greeting for apop if it exists )
|
||||||
|
bool Connect ( const std::string& server, short port = 6667 );
|
||||||
|
|
||||||
|
bool Running() { return _inRun; }
|
||||||
|
|
||||||
|
////////////////////////// IRC Client Protocol commands ///////////////////////
|
||||||
|
|
||||||
|
// first thing you must call... mode can be ""
|
||||||
|
// network can be same as name of server used in Connect() above
|
||||||
|
bool User ( const std::string& user, const std::string& mode,
|
||||||
|
const std::string& network, const std::string& realname );
|
||||||
|
|
||||||
|
// change nick...
|
||||||
|
bool Nick ( const std::string& nick );
|
||||||
|
|
||||||
|
// change mode for self...
|
||||||
|
bool Mode ( const std::string& mode );
|
||||||
|
|
||||||
|
// set someone's mode in channel ( like oping someone )
|
||||||
|
bool Mode ( const std::string& channel, const std::string& mode, const std::string& target );
|
||||||
|
|
||||||
|
// request a list of names of clients in a channel
|
||||||
|
bool Names ( const std::string& channel );
|
||||||
|
|
||||||
|
// join a channel...
|
||||||
|
bool Join ( const std::string& channel );
|
||||||
|
|
||||||
|
// send message to someone or some channel
|
||||||
|
bool PrivMsg ( const std::string& to, const std::string& text );
|
||||||
|
|
||||||
|
// leave a channel
|
||||||
|
bool Part ( const std::string& channel, const std::string& text );
|
||||||
|
|
||||||
|
// log off
|
||||||
|
bool Quit ( const std::string& text );
|
||||||
|
|
||||||
|
////////////////////// callback functions ////////////////////////////
|
||||||
|
|
||||||
|
// OnConnected: you just successfully logged into irc server
|
||||||
|
virtual bool OnConnected() = 0;
|
||||||
|
|
||||||
|
// OnJoin: you just successfully joined this channel
|
||||||
|
virtual bool OnJoin ( const std::string& user, const std::string& channel ) = 0;
|
||||||
|
|
||||||
|
// OnPrivMsg: you just received a private message from a user
|
||||||
|
virtual bool OnPrivMsg ( const std::string& from, const std::string& text ) = 0;
|
||||||
|
|
||||||
|
// OnChannelMsg: you just received a chat line in a channel
|
||||||
|
virtual bool OnChannelMsg ( const std::string& channel, const std::string& from,
|
||||||
|
const std::string& text ) = 0;
|
||||||
|
|
||||||
|
// OnChannelMode: notification of a change of a channel's mode
|
||||||
|
virtual bool OnChannelMode ( const std::string& channel, const std::string& mode ) = 0;
|
||||||
|
|
||||||
|
// OnUserModeInChannel: notification of a mode change of a user with respect to a channel.
|
||||||
|
// f.ex.: this will be called when someone is oped in a channel.
|
||||||
|
virtual bool OnUserModeInChannel ( const std::string& src, const std::string& channel,
|
||||||
|
const std::string& user, const std::string& mode ) = 0;
|
||||||
|
|
||||||
|
// OnMode: you will receive this when you change your own mode, at least...
|
||||||
|
virtual bool OnMode ( const std::string& user, const std::string& mode ) = 0;
|
||||||
|
|
||||||
|
// notification of what users are in a channel ( you may get multiple of these... )
|
||||||
|
virtual bool OnChannelUsers ( const std::string& channel, const std::vector<std::string>& users ) = 0;
|
||||||
|
|
||||||
|
// notification that you have received the entire list of users for a channel
|
||||||
|
virtual bool OnEndChannelUsers ( const std::string& channel ) = 0;
|
||||||
|
|
||||||
|
// OnPing - default implementation replies to PING with a valid PONG. required on some systems to
|
||||||
|
// log in. Most systems require a response in order to stay connected, used to verify a client hasn't
|
||||||
|
// dropped.
|
||||||
|
virtual bool OnPing ( const std::string& text );
|
||||||
|
|
||||||
|
////////////////////// other functions ////////////////////////////
|
||||||
|
|
||||||
|
// this is for sending data to irc server. it's public in case you need to send some
|
||||||
|
// command not supported by this base class...
|
||||||
|
bool Send ( const std::string& buf );
|
||||||
|
|
||||||
|
// if launch_thread is true, this function will spawn a thread that will process
|
||||||
|
// incoming packets until the socket dies.
|
||||||
|
// otherwise ( launch_thread is false ) this function will do that processing
|
||||||
|
// in *this* thread, and not return until the socket dies.
|
||||||
|
int Run ( bool launch_thread );
|
||||||
|
|
||||||
|
////////////////////// private stuff ////////////////////////////
|
||||||
|
private:
|
||||||
|
bool _Recv ( std::string& buf );
|
||||||
|
|
||||||
|
static int THREADAPI Callback ( IRCClient* irc );
|
||||||
|
|
||||||
|
static bool _debug;
|
||||||
|
std::string _nick;
|
||||||
|
int _timeout;
|
||||||
|
std::string _apop_challenge;
|
||||||
|
|
||||||
|
volatile bool _inRun;
|
||||||
|
|
||||||
|
// disable copy semantics
|
||||||
|
IRCClient ( const IRCClient& );
|
||||||
|
IRCClient& operator = ( const IRCClient& );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//IRCCLIENT_H
|
418
rosapps/games/ArchBlackmann/MD5.cpp
Normal file
418
rosapps/games/ArchBlackmann/MD5.cpp
Normal file
|
@ -0,0 +1,418 @@
|
||||||
|
// MD5.CPP - RSA Data Security, Inc., MD5 message-digest algorithm
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||||
|
rights reserved.
|
||||||
|
|
||||||
|
License to copy and use this software is granted provided that it
|
||||||
|
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||||
|
Algorithm" in all material mentioning or referencing this software
|
||||||
|
or this function.
|
||||||
|
|
||||||
|
License is also granted to make and use derivative works provided
|
||||||
|
that such works are identified as "derived from the RSA Data
|
||||||
|
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||||
|
mentioning or referencing the derived work.
|
||||||
|
|
||||||
|
RSA Data Security, Inc. makes no representations concerning either
|
||||||
|
the merchantability of this software or the suitability of this
|
||||||
|
software for any particular purpose. It is provided "as is"
|
||||||
|
without express or implied warranty of any kind.
|
||||||
|
|
||||||
|
These notices must be retained in any copies of any part of this
|
||||||
|
documentation and/or software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <assert.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "MD5.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
// Constants for MD5Transform routine.
|
||||||
|
#define S11 7
|
||||||
|
#define S12 12
|
||||||
|
#define S13 17
|
||||||
|
#define S14 22
|
||||||
|
#define S21 5
|
||||||
|
#define S22 9
|
||||||
|
#define S23 14
|
||||||
|
#define S24 20
|
||||||
|
#define S31 4
|
||||||
|
#define S32 11
|
||||||
|
#define S33 16
|
||||||
|
#define S34 23
|
||||||
|
#define S41 6
|
||||||
|
#define S42 10
|
||||||
|
#define S43 15
|
||||||
|
#define S44 21
|
||||||
|
|
||||||
|
static void MD5Transform ( UINT4 [4], const uchar [64] );
|
||||||
|
static void Encode ( unsigned char *, UINT4 *, unsigned int );
|
||||||
|
static void Decode ( UINT4 *, const uchar *, unsigned int );
|
||||||
|
|
||||||
|
static unsigned char PADDING[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
|
||||||
|
};
|
||||||
|
|
||||||
|
// F, G, H and I are basic MD5 functions.
|
||||||
|
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||||
|
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||||
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
|
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||||
|
|
||||||
|
// ROTATE_LEFT rotates x left n bits.
|
||||||
|
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||||
|
|
||||||
|
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||||
|
// Rotation is separate from addition to prevent recomputation.
|
||||||
|
#define FF(a, b, c, d, x, s, ac) { \
|
||||||
|
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||||
|
(a) = ROTATE_LEFT ((a), (s)); \
|
||||||
|
(a) += (b); \
|
||||||
|
}
|
||||||
|
#define GG(a, b, c, d, x, s, ac) { \
|
||||||
|
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||||
|
(a) = ROTATE_LEFT ((a), (s)); \
|
||||||
|
(a) += (b); \
|
||||||
|
}
|
||||||
|
#define HH(a, b, c, d, x, s, ac) { \
|
||||||
|
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||||
|
(a) = ROTATE_LEFT ((a), (s)); \
|
||||||
|
(a) += (b); \
|
||||||
|
}
|
||||||
|
#define II(a, b, c, d, x, s, ac) { \
|
||||||
|
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||||
|
(a) = ROTATE_LEFT ((a), (s)); \
|
||||||
|
(a) += (b); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// MD5 initialization. Begins an MD5 operation, writing a new context.
|
||||||
|
void MD5Init (
|
||||||
|
MD5_CTX *context ) // context
|
||||||
|
{
|
||||||
|
context->count[0] = context->count[1] = 0;
|
||||||
|
// Load magic initialization constants.
|
||||||
|
context->state[0] = 0x67452301;
|
||||||
|
context->state[1] = 0xefcdab89;
|
||||||
|
context->state[2] = 0x98badcfe;
|
||||||
|
context->state[3] = 0x10325476;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MD5 block update operation. Continues an MD5 message-digest
|
||||||
|
// operation, processing another message block, and updating the
|
||||||
|
// context.
|
||||||
|
void MD5Update (
|
||||||
|
MD5_CTX *context, // context
|
||||||
|
const char *input_, // input block
|
||||||
|
unsigned int inputLen ) // length of input block
|
||||||
|
{
|
||||||
|
unsigned int i, index, partLen;
|
||||||
|
const uchar* input = (const uchar*)input_;
|
||||||
|
|
||||||
|
// Compute number of bytes mod 64
|
||||||
|
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||||
|
|
||||||
|
// Update number of bits
|
||||||
|
if ((context->count[0] += ((UINT4)inputLen << 3))
|
||||||
|
< ((UINT4)inputLen << 3))
|
||||||
|
context->count[1]++;
|
||||||
|
context->count[1] += ((UINT4)inputLen >> 29);
|
||||||
|
|
||||||
|
partLen = 64 - index;
|
||||||
|
|
||||||
|
// Transform as many times as possible.
|
||||||
|
if (inputLen >= partLen)
|
||||||
|
{
|
||||||
|
memcpy
|
||||||
|
((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||||
|
MD5Transform (context->state, context->buffer);
|
||||||
|
|
||||||
|
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||||
|
MD5Transform (context->state, &input[i]);
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Buffer remaining input
|
||||||
|
memcpy
|
||||||
|
((POINTER)&context->buffer[index], (POINTER)&input[i],
|
||||||
|
inputLen-i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||||
|
// the message digest and zeroizing the context.
|
||||||
|
void MD5Final (
|
||||||
|
unsigned char digest[16], // message digest
|
||||||
|
MD5_CTX *context ) // context
|
||||||
|
{
|
||||||
|
uchar bits[8];
|
||||||
|
unsigned int index, padLen;
|
||||||
|
|
||||||
|
// Save number of bits
|
||||||
|
Encode (bits, context->count, 8);
|
||||||
|
|
||||||
|
// Pad out to 56 mod 64.
|
||||||
|
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||||
|
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||||
|
MD5Update (context, (const char*)PADDING, padLen);
|
||||||
|
|
||||||
|
// Append length (before padding)
|
||||||
|
MD5Update (context, (const char*)bits, 8);
|
||||||
|
|
||||||
|
// Store state in digest
|
||||||
|
Encode (digest, context->state, 16);
|
||||||
|
|
||||||
|
// Zeroize sensitive information.
|
||||||
|
memset ((POINTER)context, 0, sizeof (*context));
|
||||||
|
}
|
||||||
|
|
||||||
|
// MD5 basic transformation. Transforms state based on block.
|
||||||
|
static void MD5Transform (
|
||||||
|
UINT4 state[4],
|
||||||
|
const uchar block[64] )
|
||||||
|
{
|
||||||
|
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||||
|
|
||||||
|
Decode (x, block, 64);
|
||||||
|
|
||||||
|
// Round 1
|
||||||
|
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); // 1
|
||||||
|
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); // 2
|
||||||
|
FF (c, d, a, b, x[ 2], S13, 0x242070db); // 3
|
||||||
|
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); // 4
|
||||||
|
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); // 5
|
||||||
|
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); // 6
|
||||||
|
FF (c, d, a, b, x[ 6], S13, 0xa8304613); // 7
|
||||||
|
FF (b, c, d, a, x[ 7], S14, 0xfd469501); // 8
|
||||||
|
FF (a, b, c, d, x[ 8], S11, 0x698098d8); // 9
|
||||||
|
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); // 10
|
||||||
|
FF (c, d, a, b, x[10], S13, 0xffff5bb1); // 11
|
||||||
|
FF (b, c, d, a, x[11], S14, 0x895cd7be); // 12
|
||||||
|
FF (a, b, c, d, x[12], S11, 0x6b901122); // 13
|
||||||
|
FF (d, a, b, c, x[13], S12, 0xfd987193); // 14
|
||||||
|
FF (c, d, a, b, x[14], S13, 0xa679438e); // 15
|
||||||
|
FF (b, c, d, a, x[15], S14, 0x49b40821); // 16
|
||||||
|
|
||||||
|
// Round 2
|
||||||
|
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); // 17
|
||||||
|
GG (d, a, b, c, x[ 6], S22, 0xc040b340); // 18
|
||||||
|
GG (c, d, a, b, x[11], S23, 0x265e5a51); // 19
|
||||||
|
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20
|
||||||
|
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); // 21
|
||||||
|
GG (d, a, b, c, x[10], S22, 0x2441453); // 22
|
||||||
|
GG (c, d, a, b, x[15], S23, 0xd8a1e681); // 23
|
||||||
|
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24
|
||||||
|
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25
|
||||||
|
GG (d, a, b, c, x[14], S22, 0xc33707d6); // 26
|
||||||
|
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27
|
||||||
|
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); // 28
|
||||||
|
GG (a, b, c, d, x[13], S21, 0xa9e3e905); // 29
|
||||||
|
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30
|
||||||
|
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); // 31
|
||||||
|
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
|
||||||
|
|
||||||
|
// Round 3
|
||||||
|
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); // 33
|
||||||
|
HH (d, a, b, c, x[ 8], S32, 0x8771f681); // 34
|
||||||
|
HH (c, d, a, b, x[11], S33, 0x6d9d6122); // 35
|
||||||
|
HH (b, c, d, a, x[14], S34, 0xfde5380c); // 36
|
||||||
|
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); // 37
|
||||||
|
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38
|
||||||
|
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39
|
||||||
|
HH (b, c, d, a, x[10], S34, 0xbebfbc70); // 40
|
||||||
|
HH (a, b, c, d, x[13], S31, 0x289b7ec6); // 41
|
||||||
|
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42
|
||||||
|
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43
|
||||||
|
HH (b, c, d, a, x[ 6], S34, 0x4881d05); // 44
|
||||||
|
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45
|
||||||
|
HH (d, a, b, c, x[12], S32, 0xe6db99e5); // 46
|
||||||
|
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
|
||||||
|
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48
|
||||||
|
|
||||||
|
// Round 4
|
||||||
|
II (a, b, c, d, x[ 0], S41, 0xf4292244); // 49
|
||||||
|
II (d, a, b, c, x[ 7], S42, 0x432aff97); // 50
|
||||||
|
II (c, d, a, b, x[14], S43, 0xab9423a7); // 51
|
||||||
|
II (b, c, d, a, x[ 5], S44, 0xfc93a039); // 52
|
||||||
|
II (a, b, c, d, x[12], S41, 0x655b59c3); // 53
|
||||||
|
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54
|
||||||
|
II (c, d, a, b, x[10], S43, 0xffeff47d); // 55
|
||||||
|
II (b, c, d, a, x[ 1], S44, 0x85845dd1); // 56
|
||||||
|
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57
|
||||||
|
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
|
||||||
|
II (c, d, a, b, x[ 6], S43, 0xa3014314); // 59
|
||||||
|
II (b, c, d, a, x[13], S44, 0x4e0811a1); // 60
|
||||||
|
II (a, b, c, d, x[ 4], S41, 0xf7537e82); // 61
|
||||||
|
II (d, a, b, c, x[11], S42, 0xbd3af235); // 62
|
||||||
|
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63
|
||||||
|
II (b, c, d, a, x[ 9], S44, 0xeb86d391); // 64
|
||||||
|
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
|
||||||
|
// Zeroize sensitive information.
|
||||||
|
memset ((POINTER)x, 0, sizeof (x));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||||
|
// a multiple of 4.
|
||||||
|
static void Encode (
|
||||||
|
unsigned char *output,
|
||||||
|
UINT4 *input,
|
||||||
|
unsigned int len )
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||||
|
output[j] = (unsigned char)(input[i] & 0xff);
|
||||||
|
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||||
|
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||||
|
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||||
|
// a multiple of 4.
|
||||||
|
static void Decode (
|
||||||
|
UINT4 *output,
|
||||||
|
const uchar *input,
|
||||||
|
unsigned int len )
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||||
|
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
|
||||||
|
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void digest2ascii ( char *ascii, const unsigned char *digest )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
static char* table = "0123456789abcdef";
|
||||||
|
for ( i = 0; i < 16; i++ )
|
||||||
|
{
|
||||||
|
*ascii++ = table[(*digest)>>4];
|
||||||
|
*ascii++ = table[(*digest++)%16];
|
||||||
|
}
|
||||||
|
*ascii++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ascii2digest ( unsigned char *digest, const char *ascii )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#define CONV(c) (unsigned char)( (toupper(c)>='A') ? (toupper(c)+10-'A') : ((c)-'0') )
|
||||||
|
#define MAKECHAR(a,b) ((CONV(a)%16)<<4)|(CONV(b)%16)
|
||||||
|
for ( i = 0; i < 16; i++ )
|
||||||
|
{
|
||||||
|
*digest++ = MAKECHAR(ascii[0],ascii[1]);
|
||||||
|
ascii += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
MD5::MD5()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5::Init()
|
||||||
|
{
|
||||||
|
MD5Init(&_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5::Update ( const string& s )
|
||||||
|
{
|
||||||
|
MD5Update ( &_ctx, s.c_str(), s.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
string MD5::Final ( char* digest )
|
||||||
|
{
|
||||||
|
vector<uchar> v;
|
||||||
|
v.resize(16);
|
||||||
|
MD5Final ( &v[0], &_ctx );
|
||||||
|
if ( digest )
|
||||||
|
memmove ( digest, &v[0], 16 );
|
||||||
|
string s;
|
||||||
|
static char* tohex = "0123456789abcdef";
|
||||||
|
for ( int i = 0; i < 16; i++ )
|
||||||
|
{
|
||||||
|
uchar c = v[i];
|
||||||
|
s += tohex[ (c>>4) & 0xF ];
|
||||||
|
s += tohex[ c & 0xF ];
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
string MD5Hex ( const string& s )
|
||||||
|
{
|
||||||
|
MD5 md5;
|
||||||
|
md5.Update ( s );
|
||||||
|
return md5.Final();
|
||||||
|
}
|
||||||
|
|
||||||
|
string MD5Bin ( const string& s )
|
||||||
|
{
|
||||||
|
MD5 md5;
|
||||||
|
md5.Update ( s );
|
||||||
|
char digest[16];
|
||||||
|
md5.Final ( digest );
|
||||||
|
return string ( digest, 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
string HMAC_MD5 ( const string& key, const string& text, char* out_bin )
|
||||||
|
{
|
||||||
|
MD5 md5;
|
||||||
|
char k_ipad[65]; // inner padding - key XORd with ipad
|
||||||
|
char k_opad[65]; // outer padding - key XORd with opad
|
||||||
|
string tmp;
|
||||||
|
char digest[16];
|
||||||
|
int i;
|
||||||
|
// if key is longer than 64 bytes reset it to key=MD5(key)
|
||||||
|
if ( key.length() > 64 )
|
||||||
|
{
|
||||||
|
md5.Init();
|
||||||
|
md5.Update ( key );
|
||||||
|
md5.Final ( digest );
|
||||||
|
tmp = string ( digest, 16 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp = key;
|
||||||
|
|
||||||
|
// start out by storing key in pads
|
||||||
|
memset ( k_ipad, 0, sizeof(k_ipad) );
|
||||||
|
memset ( k_opad, 0, sizeof(k_opad) );
|
||||||
|
memcpy ( k_ipad, tmp.c_str(), tmp.length() );
|
||||||
|
memcpy ( k_opad, tmp.c_str(), tmp.length() );
|
||||||
|
|
||||||
|
// XOR key with ipad and opad values
|
||||||
|
for ( i=0; i<64; i++ )
|
||||||
|
{
|
||||||
|
k_ipad[i] ^= 0x36;
|
||||||
|
k_opad[i] ^= 0x5c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "inner" MD5
|
||||||
|
md5.Init();
|
||||||
|
md5.Update(k_ipad);
|
||||||
|
md5.Update(text);
|
||||||
|
md5.Final ( digest );
|
||||||
|
|
||||||
|
// "outer" MD5
|
||||||
|
md5.Init();
|
||||||
|
md5.Update(k_opad);
|
||||||
|
md5.Update(string(digest,16));
|
||||||
|
return md5.Final(out_bin);
|
||||||
|
}
|
||||||
|
#endif//__cplusplus
|
95
rosapps/games/ArchBlackmann/MD5.h
Normal file
95
rosapps/games/ArchBlackmann/MD5.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// MD5.H - header file for MD5.CPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||||
|
rights reserved.
|
||||||
|
|
||||||
|
License to copy and use this software is granted provided that it
|
||||||
|
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||||
|
Algorithm" in all material mentioning or referencing this software
|
||||||
|
or this function.
|
||||||
|
|
||||||
|
License is also granted to make and use derivative works provided
|
||||||
|
that such works are identified as "derived from the RSA Data
|
||||||
|
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||||
|
mentioning or referencing the derived work.
|
||||||
|
|
||||||
|
RSA Data Security, Inc. makes no representations concerning either
|
||||||
|
the merchantability of this software or the suitability of this
|
||||||
|
software for any particular purpose. It is provided "as is"
|
||||||
|
without express or implied warranty of any kind.
|
||||||
|
|
||||||
|
These notices must be retained in any copies of any part of this
|
||||||
|
documentation and/or software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MD5_H
|
||||||
|
#define __MD5_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <string>
|
||||||
|
#endif//__cplusplus
|
||||||
|
|
||||||
|
#ifndef uchar
|
||||||
|
#define uchar unsigned char
|
||||||
|
#endif//uchar
|
||||||
|
|
||||||
|
#ifndef ushort
|
||||||
|
#define ushort unsigned short
|
||||||
|
#endif//ushort
|
||||||
|
|
||||||
|
#ifndef ulong
|
||||||
|
#define ulong unsigned long
|
||||||
|
#endif//ulong
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif//__cplusplus
|
||||||
|
|
||||||
|
typedef uchar *POINTER; // POINTER defines a generic pointer type
|
||||||
|
typedef ushort UINT2; // UINT2 defines a two byte word
|
||||||
|
typedef ulong UINT4; // UINT4 defines a four byte word
|
||||||
|
|
||||||
|
// MD5 context.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT4 state[4]; // state (ABCD)
|
||||||
|
UINT4 count[2]; // number of bits, modulo 2^64 (lsb first)
|
||||||
|
unsigned char buffer[64]; // input buffer
|
||||||
|
} MD5_CTX;
|
||||||
|
|
||||||
|
void MD5Init ( MD5_CTX * );
|
||||||
|
void MD5Update ( MD5_CTX *, const char *, unsigned int );
|
||||||
|
void MD5Final ( uchar [16], MD5_CTX * );
|
||||||
|
|
||||||
|
void digest2ascii ( char *ascii, const uchar *digest );
|
||||||
|
void ascii2digest ( uchar *digest, const char *ascii );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
class MD5
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MD5();
|
||||||
|
void Init();
|
||||||
|
void Update ( const std::string& s );
|
||||||
|
std::string Final ( char* digest = 0 );
|
||||||
|
|
||||||
|
private:
|
||||||
|
MD5_CTX _ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string MD5Hex ( const std::string& s );
|
||||||
|
|
||||||
|
std::string MD5Bin ( const std::string& s );
|
||||||
|
|
||||||
|
std::string HMAC_MD5 (
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& text,
|
||||||
|
char* out_bin = NULL );
|
||||||
|
|
||||||
|
#endif//__cplusplus
|
||||||
|
|
||||||
|
#endif//__MD5_H
|
315
rosapps/games/ArchBlackmann/QueueT.h
Normal file
315
rosapps/games/ArchBlackmann/QueueT.h
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
** Author: Samuel R. Blackburn
|
||||||
|
** Internet: wfc@pobox.com
|
||||||
|
**
|
||||||
|
** You can use it any way you like as long as you don't try to sell it.
|
||||||
|
**
|
||||||
|
** Any attempt to sell WFC in source code form must have the permission
|
||||||
|
** of the original author. You can produce commercial executables with
|
||||||
|
** WFC but you can't sell WFC.
|
||||||
|
**
|
||||||
|
** Copyright, 2000, Samuel R. Blackburn
|
||||||
|
**
|
||||||
|
** NOTE: I modified the info block below so it hopefully wouldn't conflict
|
||||||
|
** with the original file. Royce Mitchell III
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUEUET_CLASS_HEADER
|
||||||
|
#define QUEUET_CLASS_HEADER
|
||||||
|
|
||||||
|
#include "ReliMT.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <sys/types.h> // off_t
|
||||||
|
#define HEAPCREATE(size) m_Heap = ::HeapCreate ( HEAP_NO_SERIALIZE, size, 0 )
|
||||||
|
#define HEAPALLOC(size) ::HeapAlloc ( m_Heap, HEAP_NO_SERIALIZE, size )
|
||||||
|
#define HEAPREALLOC(p,size) ::HeapReAlloc( m_Heap, HEAP_NO_SERIALIZE, p, size )
|
||||||
|
#define HEAPFREE(p) ::HeapFree ( m_Heap, HEAP_NO_SERIALIZE, p )
|
||||||
|
#define HEAPDESTROY() ::HeapDestroy ( m_Heap ); m_Heap = 0;
|
||||||
|
#else
|
||||||
|
#define HEAPCREATE(size)
|
||||||
|
#define HEAPALLOC(size) malloc(size)
|
||||||
|
#define HEAPREALLOC(p,size) realloc(p,size);
|
||||||
|
#define HEAPFREE(p) free(p)
|
||||||
|
#define HEAPDESTROY()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CQueueT : public Uncopyable
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// What we want to protect
|
||||||
|
|
||||||
|
Mutex m_AddMutex;
|
||||||
|
Mutex m_GetMutex;
|
||||||
|
|
||||||
|
T* m_Items;
|
||||||
|
|
||||||
|
off_t m_AddIndex;
|
||||||
|
off_t m_GetIndex;
|
||||||
|
size_t m_Size;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE m_Heap;
|
||||||
|
#endif//WIN32
|
||||||
|
inline void m_GrowBy ( size_t number_of_new_items );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline CQueueT ( size_t initial_size = 1024 );
|
||||||
|
inline ~CQueueT();
|
||||||
|
|
||||||
|
inline bool Add( const T& new_item );
|
||||||
|
inline void Empty() { m_AddIndex = 0; m_GetIndex = 0; };
|
||||||
|
inline bool Get( T& item );
|
||||||
|
inline size_t GetLength() const;
|
||||||
|
inline size_t GetMaximumLength() const { return( m_Size ); };
|
||||||
|
inline bool AddArray ( const T* new_items, int item_count );
|
||||||
|
inline int GetArray ( T* items, const int maxget, const T& tEnd );
|
||||||
|
inline bool Contains ( const T& t );
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline CQueueT<T>::CQueueT ( size_t initial_size )
|
||||||
|
{
|
||||||
|
m_AddIndex = 0;
|
||||||
|
m_GetIndex = 0;
|
||||||
|
m_Items = NULL;
|
||||||
|
|
||||||
|
if ( initial_size == 0 )
|
||||||
|
initial_size = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 1999-11-05
|
||||||
|
** We create our own heap because all of the pointers used are allocated
|
||||||
|
** and freed be us. We don't have to worry about a non-serialized thread
|
||||||
|
** accessing something we allocated. Because of this, we can perform our
|
||||||
|
** memory allocations in a heap dedicated to queueing. This means when we
|
||||||
|
** have to allocate more memory, we don't have to wait for all other threads
|
||||||
|
** to pause while we allocate from the shared heap (like the C Runtime heap)
|
||||||
|
*/
|
||||||
|
|
||||||
|
HEAPCREATE( ( ( ( 2 * initial_size * sizeof(T) ) < 65536 ) ? 65536 : (2 * initial_size * sizeof(T) ) ) );
|
||||||
|
|
||||||
|
m_Items = (T*)HEAPALLOC ( initial_size * sizeof(T) );
|
||||||
|
|
||||||
|
m_Size = ( m_Items == NULL ) ? 0 : initial_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline CQueueT<T>::~CQueueT()
|
||||||
|
{
|
||||||
|
m_AddIndex = 0;
|
||||||
|
m_GetIndex = 0;
|
||||||
|
m_Size = 0;
|
||||||
|
|
||||||
|
if ( m_Items != NULL )
|
||||||
|
{
|
||||||
|
HEAPFREE(m_Items);
|
||||||
|
m_Items = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HEAPDESTROY();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool CQueueT<T>::Add ( const T& item )
|
||||||
|
{
|
||||||
|
// Block other threads from entering Add();
|
||||||
|
Mutex::Lock addlock ( m_AddMutex );
|
||||||
|
|
||||||
|
// Add the item
|
||||||
|
|
||||||
|
m_Items[ m_AddIndex ] = item;
|
||||||
|
|
||||||
|
// 1999-12-08
|
||||||
|
// Many many thanks go to Lou Franco (lfranco@spheresoft.com)
|
||||||
|
// for finding an bug here. It rare but recreatable situations,
|
||||||
|
// m_AddIndex could be in an invalid state.
|
||||||
|
|
||||||
|
// Make sure m_AddIndex is never invalid
|
||||||
|
|
||||||
|
off_t new_add_index = ( ( m_AddIndex + 1 ) >= (off_t)m_Size ) ? 0 : m_AddIndex + 1;
|
||||||
|
|
||||||
|
if ( new_add_index == m_GetIndex )
|
||||||
|
{
|
||||||
|
// The queue is full. We need to grow.
|
||||||
|
// Stop anyone from getting from the queue
|
||||||
|
Mutex::Lock getlock ( m_GetMutex );
|
||||||
|
|
||||||
|
m_AddIndex = new_add_index;
|
||||||
|
|
||||||
|
// One last double-check.
|
||||||
|
|
||||||
|
if ( m_AddIndex == m_GetIndex )
|
||||||
|
{
|
||||||
|
m_GrowBy ( m_Size );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_AddIndex = new_add_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool CQueueT<T>::Get( T& item )
|
||||||
|
{
|
||||||
|
// Prevent other threads from entering Get()
|
||||||
|
Mutex::Lock getlock ( m_GetMutex );
|
||||||
|
|
||||||
|
if ( m_GetIndex == m_AddIndex )
|
||||||
|
{
|
||||||
|
// Let's check to see if our queue has grown too big
|
||||||
|
// If it has, then shrink it
|
||||||
|
|
||||||
|
if ( m_Size > 1024 )
|
||||||
|
{
|
||||||
|
// Yup, we're too big for our britches
|
||||||
|
Mutex::TryLock addlock ( m_AddMutex );
|
||||||
|
if ( addlock )
|
||||||
|
{
|
||||||
|
// Now, no one can add to the queue
|
||||||
|
|
||||||
|
if ( m_GetIndex == m_AddIndex ) // is queue empty?
|
||||||
|
{
|
||||||
|
// See if we can just shrink it...
|
||||||
|
T* return_value = (T*)HEAPREALLOC(m_Items,1024 * sizeof(T));
|
||||||
|
|
||||||
|
if ( return_value != NULL )
|
||||||
|
{
|
||||||
|
m_Items = (T*) return_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Looks like we'll have to do it the hard way
|
||||||
|
HEAPFREE ( m_Items );
|
||||||
|
m_Items = (T*) HEAPALLOC ( 1024 * sizeof(T) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Size = ( m_Items == NULL ) ? 0 : 1024;
|
||||||
|
m_AddIndex = 0;
|
||||||
|
m_GetIndex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// m_GetIndex != m_AddIndex, this means that someone added
|
||||||
|
// to the queue between the time we checked m_Size for being
|
||||||
|
// too big and the time we entered the add critical section.
|
||||||
|
// If this happened then we are too busy to shrink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = m_Items[ m_GetIndex ];
|
||||||
|
|
||||||
|
// Make sure m_GetIndex is never invalid
|
||||||
|
|
||||||
|
m_GetIndex = ( ( m_GetIndex + 1 ) >= (off_t)m_Size ) ? 0 : m_GetIndex + 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline int CQueueT<T>::GetArray ( T* items, const int maxget, const T& tEnd )
|
||||||
|
{
|
||||||
|
// TODO - oooh baby does this need to be optimized
|
||||||
|
// Prevent other threads from entering Get()
|
||||||
|
Mutex::Lock getlock ( m_GetMutex ); //::EnterCriticalSection( &m_GetCriticalSection );
|
||||||
|
|
||||||
|
int iResult = 0;
|
||||||
|
for ( int i = 0; i < maxget; i++ )
|
||||||
|
{
|
||||||
|
if ( !Get(items[i]) )
|
||||||
|
break;
|
||||||
|
iResult++;
|
||||||
|
if ( items[i] == tEnd )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Let other threads call Get() now
|
||||||
|
//::LeaveCriticalSection( &m_GetCriticalSection );
|
||||||
|
return iResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline size_t CQueueT<T>::GetLength() const
|
||||||
|
{
|
||||||
|
// This is a very expensive process!
|
||||||
|
// No one can call Add() or Get() while we're computing this
|
||||||
|
|
||||||
|
size_t number_of_items_in_the_queue = 0;
|
||||||
|
|
||||||
|
Mutex::Lock addlock ( m_AddMutex );
|
||||||
|
Mutex::Lock getlock ( m_GetMutex );
|
||||||
|
|
||||||
|
number_of_items_in_the_queue = ( m_AddIndex >= m_GetIndex ) ?
|
||||||
|
( m_AddIndex - m_GetIndex ) :
|
||||||
|
( ( m_AddIndex + m_Size ) - m_GetIndex );
|
||||||
|
|
||||||
|
return number_of_items_in_the_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void CQueueT<T>::m_GrowBy ( size_t number_of_new_items )
|
||||||
|
{
|
||||||
|
// Prevent other threads from calling Get().
|
||||||
|
// We don't need to enter the AddCriticalSection because
|
||||||
|
// m_GrowBy() is only called from Add();
|
||||||
|
|
||||||
|
T* new_array = NULL;
|
||||||
|
T* pointer_to_free = NULL;
|
||||||
|
|
||||||
|
size_t new_size = m_Size + number_of_new_items;
|
||||||
|
|
||||||
|
{ // Prevent other threads from getting
|
||||||
|
Mutex::Lock getlock ( m_GetMutex );
|
||||||
|
|
||||||
|
// 2000-05-16
|
||||||
|
// Thanks go to Royce Mitchell III (royce3@aim-controls.com) for finding
|
||||||
|
// a HUGE bug here. I was using HeapReAlloc as a short cut but my logic
|
||||||
|
// was flawed. In certain circumstances, queue items were being dropped.
|
||||||
|
|
||||||
|
new_array = (T*)HEAPALLOC ( new_size * sizeof(T) );
|
||||||
|
|
||||||
|
// Now copy all of the old items from the old queue to the new one.
|
||||||
|
|
||||||
|
// Get the entries from the get-index to the end of the array
|
||||||
|
memcpy ( new_array, &m_Items[m_GetIndex], ( m_Size - m_GetIndex ) * sizeof(T) );
|
||||||
|
|
||||||
|
// Get the entries from the beginning of the array to the add-index
|
||||||
|
memcpy ( &new_array[m_Size-m_GetIndex], m_Items, m_AddIndex * sizeof(T) );
|
||||||
|
|
||||||
|
m_AddIndex = (off_t)m_Size;
|
||||||
|
m_GetIndex = 0;
|
||||||
|
m_Size = new_size;
|
||||||
|
pointer_to_free = m_Items;
|
||||||
|
m_Items = new_array;
|
||||||
|
} // Mutex::Lock
|
||||||
|
HEAPFREE ( pointer_to_free );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline bool CQueueT<T>::Contains ( const T& t )
|
||||||
|
{
|
||||||
|
Mutex::Lock addlock ( m_AddMutex );
|
||||||
|
Mutex::Lock getlock ( m_GetMutex );
|
||||||
|
|
||||||
|
for ( int i = m_GetIndex; i != m_AddIndex; i++ )
|
||||||
|
{
|
||||||
|
if ( i == m_Size )
|
||||||
|
i = 0;
|
||||||
|
if ( m_Items[i] == t )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return m_Items[m_AddIndex] == t;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef CQueueT<char> CCharQueue;
|
||||||
|
|
||||||
|
#endif // QUEUE_CLASS_HEADER
|
143
rosapps/games/ArchBlackmann/Reli.h
Normal file
143
rosapps/games/ArchBlackmann/Reli.h
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
// Reli.h
|
||||||
|
// lots of code here is (c) Bartosz Milewski, 1996, www.relisoft.com
|
||||||
|
// The rest is (C) 2002-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#ifndef __RELI_H
|
||||||
|
#define __RELI_H
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
#undef Assert
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define Assert(exp) ((void)0)
|
||||||
|
#else
|
||||||
|
void _wassert (char* szExpr, char* szFile, int line);
|
||||||
|
#define Assert(exp) (void)( (exp) || (_wassert(#exp, __FILE__, __LINE__), 0) )
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Swap
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Swap(T a,T b)
|
||||||
|
{
|
||||||
|
T t = a;
|
||||||
|
a = b;
|
||||||
|
b = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Uncopyable - base class disabling copy ctors
|
||||||
|
class Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Uncopyable(){} // need a default ctor
|
||||||
|
private:
|
||||||
|
Uncopyable ( const Uncopyable& );
|
||||||
|
const Uncopyable& operator = ( const Uncopyable& );
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SPtr - Smart Pointer's must be passed by reference or const reference
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class SPtr : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~SPtr () { Destroy(); }
|
||||||
|
T * operator->() { return _p; }
|
||||||
|
T const * operator->() const { return _p; }
|
||||||
|
operator T&() { Assert(_p); return *_p; }
|
||||||
|
operator const T&() const { Assert(_p); return *_p; }
|
||||||
|
void Acquire ( SPtr<T>& t ) { Destroy(); Swap(_p,t._p); }
|
||||||
|
void Destroy() { if ( _p ) { delete _p; _p = 0; } }
|
||||||
|
protected:
|
||||||
|
SPtr (): _p (0) {}
|
||||||
|
explicit SPtr (T* p): _p (p) {}
|
||||||
|
T * _p;
|
||||||
|
private:
|
||||||
|
operator T* () { return _p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DECLARE_SPTR(cls,init,init2) \
|
||||||
|
class S##cls : public SPtr<cls> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
S##cls ( cls* p ) : SPtr<cls>(p) {} \
|
||||||
|
explicit S##cls init : SPtr<cls> (new cls init2) {} \
|
||||||
|
};
|
||||||
|
/* Example Usage of DECLARE_SPTR:
|
||||||
|
class MyClass
|
||||||
|
{
|
||||||
|
public: // can be protected
|
||||||
|
MyClass ( int i )
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}; DECLARE_SPTR(MyClass,(int i),(i))
|
||||||
|
SMyClass ptr(i);
|
||||||
|
*/
|
||||||
|
#define DECLARE_SPTRV(cls) typedef SPtr<cls> S##cls;
|
||||||
|
/* Example Usage of DECLARE_SPTRV:
|
||||||
|
class MyAbstractClass
|
||||||
|
{
|
||||||
|
public: // can be protected
|
||||||
|
MyAbstractClass ( int i )
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
void MyPureVirtFunc() = 0;
|
||||||
|
...
|
||||||
|
}; DECLARE_SPTRV(MyAbstractClass)
|
||||||
|
SMyAbstractClass ptr ( new MySubClass(i) );
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DECLARE_PTR(cls,init,init2) \
|
||||||
|
class Ptr : public SPtr<cls> \
|
||||||
|
{ \
|
||||||
|
Ptr(cls* p) : SPtr<cls> ( p ) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
|
Ptr init : SPtr<cls> ( new cls init2 ) {} \
|
||||||
|
};
|
||||||
|
/* Example Usage of DECLARE_PTR:
|
||||||
|
class MyClass
|
||||||
|
{
|
||||||
|
DECLARE_PTR(MyClass,(int i),(i))
|
||||||
|
public: // can be protected
|
||||||
|
MyClass ( int i )
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
void MyPureVirtFunc() = 0;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
MyClass::Ptr ptr ( i );
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DECLARE_PTRV(cls) \
|
||||||
|
class Ptr : public SPtr<cls> \
|
||||||
|
{ \
|
||||||
|
Ptr(cls* p) : SPtr<cls> ( p ) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
/* Example Usage of DECLARE_PTRV:
|
||||||
|
class MyAbstractClass
|
||||||
|
{
|
||||||
|
DECLARE_PTRV(MyAbstractClass)
|
||||||
|
public: // can be protected
|
||||||
|
MyAbstractClass ( int i )
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
void MyPureVirtFunc() = 0;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
MyAbstractClass::Ptr ptr ( new MySubClass(i) );
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif//__RELI_H
|
331
rosapps/games/ArchBlackmann/ReliMT.cpp
Normal file
331
rosapps/games/ArchBlackmann/ReliMT.cpp
Normal file
|
@ -0,0 +1,331 @@
|
||||||
|
// ReliMT.cpp
|
||||||
|
// lots of code here is (c) Bartosz Milewski, 1996, www.relisoft.com
|
||||||
|
// The rest is (C) 2002-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef WIN32
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# define snprintf _snprintf
|
||||||
|
#elif defined(UNIX)
|
||||||
|
# include <errno.h>
|
||||||
|
# include <sys/sem.h>
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif//WIN32|UNIX
|
||||||
|
#include "verify.h"
|
||||||
|
#include "ReliMT.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
void _wassert ( char* szExpr, char* szFile, int line )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "Assertion Failure: \"%s\" in file %s, line %d", szExpr, szFile, line );
|
||||||
|
exit (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Thread
|
||||||
|
|
||||||
|
Thread::Thread ( long (THREADAPI * pFun) (void* arg), void* pArg )
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( _handle = CreateThread (
|
||||||
|
0, // Security attributes
|
||||||
|
0, // Stack size
|
||||||
|
(DWORD (WINAPI*)(void*))pFun,
|
||||||
|
pArg,
|
||||||
|
0, // don't create suspended.
|
||||||
|
&_tid ));
|
||||||
|
#elif defined(UNIX)
|
||||||
|
// set up the thread attribute: right now, we do nothing with it.
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
|
||||||
|
// this will make the threads created by this process really concurrent
|
||||||
|
verify ( !pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) );
|
||||||
|
|
||||||
|
// create the new OS thread object
|
||||||
|
verify ( !pthread_create ( &_threadId, &attr, (void* (*) (void*))pFun, pArg ) );
|
||||||
|
|
||||||
|
verify ( !pthread_attr_destroy(&attr) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif//WIN32|UNIX
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::~Thread()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( CloseHandle ( _handle ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
verify ( !pthread_cancel ( _threadId ) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif//WIN32|UNIX
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void Thread::Resume()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
ResumeThread (_handle);
|
||||||
|
#elif defined(UNIX)
|
||||||
|
# error how to resume thread in unix?
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif//WIN32|UNIX
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void Thread::WaitForDeath()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dw = WaitForSingleObject ( _handle, 2000 );
|
||||||
|
ASSERT ( dw != WAIT_FAILED );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
verify ( !pthread_join ( _threadId, (void**)NULL ) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif//WIN32|UNIX
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ActiveObject
|
||||||
|
|
||||||
|
// The constructor of the derived class
|
||||||
|
// should call
|
||||||
|
// _thread.Resume();
|
||||||
|
// at the end of construction
|
||||||
|
|
||||||
|
ActiveObject::ActiveObject() : _isDying (0), _thread (0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveObject::~ActiveObject()
|
||||||
|
{
|
||||||
|
ASSERT ( !_thread ); // call Kill() from subclass's dtor
|
||||||
|
// Kill() - // You can't call a virtual function from a dtor, EVEN INDIRECTLY
|
||||||
|
// so, you must call Kill() in the subclass's dtor
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushThread must reset all the events on which the thread might be waiting.
|
||||||
|
void ActiveObject::Kill()
|
||||||
|
{
|
||||||
|
if ( _thread )
|
||||||
|
{
|
||||||
|
_isDying++;
|
||||||
|
FlushThread();
|
||||||
|
// Let's make sure it's gone
|
||||||
|
_thread->WaitForDeath();
|
||||||
|
delete _thread;
|
||||||
|
_thread = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActiveObject::Start()
|
||||||
|
{
|
||||||
|
ASSERT ( !_thread );
|
||||||
|
_thread = new Thread ( ThreadEntry, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
long THREADAPI ActiveObject::ThreadEntry ( void* pArg )
|
||||||
|
{
|
||||||
|
ActiveObject * pActive = (ActiveObject*)pArg;
|
||||||
|
pActive->InitThread();
|
||||||
|
pActive->Run();
|
||||||
|
pActive->Kill();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mutex
|
||||||
|
|
||||||
|
Mutex::Mutex()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( _h = CreateMutex ( NULL, FALSE, NULL ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
pthread_mutexattr_t attrib;
|
||||||
|
verify ( !pthread_mutexattr_init( &attrib ) );
|
||||||
|
// allow recursive locks
|
||||||
|
verify ( !pthread_mutexattr_settype( &attrib, PTHREAD_MUTEX_RECURSIVE ) );
|
||||||
|
verify ( !pthread_mutex_init ( &_mutex, &attrib ) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::~Mutex()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( CloseHandle ( _h ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
verify ( !pthread_mutex_destroy(&_mutex) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::Acquire()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dw = WaitForSingleObject ( _h, INFINITE );
|
||||||
|
ASSERT ( dw == WAIT_OBJECT_0 || dw == WAIT_ABANDONED );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
verify ( !pthread_mutex_lock(&_mutex) );
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mutex::TryAcquire()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dw = WaitForSingleObject ( _h, 1 );
|
||||||
|
ASSERT ( dw == WAIT_OBJECT_0 || dw == WAIT_TIMEOUT || dw == WAIT_ABANDONED );
|
||||||
|
return (dw != WAIT_TIMEOUT);
|
||||||
|
#elif defined(UNIX)
|
||||||
|
int err = pthread_mutex_trylock(&_mutex);
|
||||||
|
ASSERT ( err == EBUSY || err == 0 );
|
||||||
|
return (err == 0);
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::Release()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( ReleaseMutex ( _h ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
verify ( !pthread_mutex_unlock(&_mutex) );
|
||||||
|
// we could allow EPERM return value too, but we are forcing user into RIIA
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::Lock::Lock ( Mutex& m ) : _m(m)
|
||||||
|
{
|
||||||
|
_m.Acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::Lock::~Lock()
|
||||||
|
{
|
||||||
|
_m.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::TryLock::TryLock ( Mutex& m ) : _m(m)
|
||||||
|
{
|
||||||
|
_bLocked = _m.TryAcquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::TryLock::~TryLock()
|
||||||
|
{
|
||||||
|
if ( _bLocked )
|
||||||
|
_m.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event
|
||||||
|
|
||||||
|
Event::Event()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
// start in non-signaled state (red light)
|
||||||
|
// auto reset after every Wait
|
||||||
|
verify ( _handle = CreateEvent ( 0, FALSE, FALSE, 0 ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
//verify ( !pthread_cond_init ( &_cond, NULL /* default attributes */) );
|
||||||
|
sem_init();
|
||||||
|
//verify(sem_init());
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::~Event()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( CloseHandle ( _handle ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
//verify ( !pthread_cond_destroy ( &_cond ) );
|
||||||
|
sem_destroy();
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::Release() // put into signaled state
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
verify ( SetEvent ( _handle ) );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
//verify ( !pthread_cond_signal ( &_cond ) );
|
||||||
|
verify(!sem_V());
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::Wait()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
// Wait until event is in signaled (green) state
|
||||||
|
DWORD dw = WaitForSingleObject ( _handle, INFINITE );
|
||||||
|
ASSERT ( dw == WAIT_OBJECT_0 || dw == WAIT_ABANDONED );
|
||||||
|
#elif defined(UNIX)
|
||||||
|
// According to docs: The pthread_cond_wait() and pthread_cond_timedwait()
|
||||||
|
// functions are used to block on a condition variable. They are called
|
||||||
|
// with mutex locked by the calling thread or undefined behaviour will
|
||||||
|
// result.
|
||||||
|
//Mutex::Lock lock ( _mutex );
|
||||||
|
//verify ( !pthread_cond_wait ( &_cond, _mutex ) );
|
||||||
|
verify(!sem_P());
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
void Event::sem_init()
|
||||||
|
{
|
||||||
|
sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
|
||||||
|
ASSERT(sem_id != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Event::sem_P()
|
||||||
|
{
|
||||||
|
struct sembuf sb;
|
||||||
|
sb.sem_num = 0;
|
||||||
|
sb.sem_op = -1;
|
||||||
|
sb.sem_flg = 0;
|
||||||
|
return semop(sem_id, &sb, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Event::sem_V()
|
||||||
|
{
|
||||||
|
struct sembuf sb;
|
||||||
|
sb.sem_num = 0;
|
||||||
|
sb.sem_op = 1;
|
||||||
|
sb.sem_flg = 0;
|
||||||
|
return semop(sem_id, &sb, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::sem_destroy()
|
||||||
|
{
|
||||||
|
#ifdef MACOSX
|
||||||
|
semun mactmp;
|
||||||
|
mactmp.val = 0;
|
||||||
|
semctl(sem_id, 0, IPC_RMID, mactmp);
|
||||||
|
#else
|
||||||
|
semctl(sem_id, 0, IPC_RMID, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
229
rosapps/games/ArchBlackmann/ReliMT.h
Normal file
229
rosapps/games/ArchBlackmann/ReliMT.h
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
// ReliMT.h
|
||||||
|
// lots of code here is (c) Bartosz Milewski, 1996, www.relisoft.com
|
||||||
|
// The rest is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __RELIMT_H
|
||||||
|
#define __RELIMT_H
|
||||||
|
|
||||||
|
#include "Reli.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# ifndef _WINDOWS_
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# endif
|
||||||
|
# define THREADAPI WINAPI
|
||||||
|
#elif defined(UNIX)
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include "string.h"
|
||||||
|
# include <sys/types.h> //Semaphore
|
||||||
|
# include <sys/ipc.h> //Semaphore
|
||||||
|
# include <sys/sem.h> //Semaphore
|
||||||
|
# define THREADAPI
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Thread
|
||||||
|
|
||||||
|
class Thread : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Thread ( long (THREADAPI * pFun) (void* arg), void* pArg );
|
||||||
|
~Thread();
|
||||||
|
//void Resume();
|
||||||
|
void WaitForDeath();
|
||||||
|
|
||||||
|
// platform-specific stuff:
|
||||||
|
private:
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE _handle;
|
||||||
|
DWORD _tid; // thread id
|
||||||
|
#elif defined(UNIX)
|
||||||
|
pthread_t _threadId; // id of the thread
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
//DECLARE_PTR(Thread,(long (THREADAPI * pFun) (void* arg), void* pArg),(pFun,pArg));
|
||||||
|
}; //DECLARE_SPTR(Thread,(long (THREADAPI * pFun) (void* arg), void* pArg),(pFun,pArg));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ActiveObject
|
||||||
|
|
||||||
|
class ActiveObject : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActiveObject();
|
||||||
|
virtual ~ActiveObject();
|
||||||
|
void Kill();
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void InitThread() = 0;
|
||||||
|
virtual void Run() = 0;
|
||||||
|
virtual void FlushThread() = 0;
|
||||||
|
|
||||||
|
int _isDying;
|
||||||
|
|
||||||
|
static long THREADAPI ThreadEntry ( void *pArg );
|
||||||
|
Thread *_thread;
|
||||||
|
|
||||||
|
//DECLARE_PTRV(ActiveObject);
|
||||||
|
}; //DECLARE_SPTRV(ActiveObject);
|
||||||
|
|
||||||
|
// Last thing in the constructor of a class derived from
|
||||||
|
// ActiveObject you must call
|
||||||
|
// Start();
|
||||||
|
// Inside the loop the Run method you must keep checking _isDying
|
||||||
|
// if (_isDying)
|
||||||
|
// return;
|
||||||
|
// FlushThread must reset all the events on which the thread might be waiting.
|
||||||
|
// Example:
|
||||||
|
#if 0
|
||||||
|
// MyAsyncOutputter - class that outputs strings to a file asynchronously
|
||||||
|
class MyAsyncOutputter : public ActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyAsyncOutputter ( const string& filename ) : _filename(filename), _currentBuf(0)
|
||||||
|
{
|
||||||
|
Start(); // start thread
|
||||||
|
}
|
||||||
|
void InitThread()
|
||||||
|
{
|
||||||
|
_f.open ( _filename, "wb" );
|
||||||
|
}
|
||||||
|
void Output ( const string& s )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// acquire lock long enough to add the string to the active buffer
|
||||||
|
Mutex::Lock lock ( _mutex );
|
||||||
|
_buf[_currentBuf].push_back ( s );
|
||||||
|
}
|
||||||
|
_event.Release(); // don't need the lock fire the event
|
||||||
|
}
|
||||||
|
void Run()
|
||||||
|
{
|
||||||
|
while ( !_isDying )
|
||||||
|
{
|
||||||
|
// wait for signal from Output() or FlushThread()
|
||||||
|
_event.Wait();
|
||||||
|
{
|
||||||
|
// acquire lock long enough to switch active buffers
|
||||||
|
Mutex::Lock lock ( _mutex );
|
||||||
|
_currentBuf = 1-_currentBuf;
|
||||||
|
ASSERT ( !_buf[_currentBuf].size() );
|
||||||
|
}
|
||||||
|
// get a reference to the old buffer
|
||||||
|
vector<string>& buf = _buf[1-_currentBuf];
|
||||||
|
// write each string out to file and then empty the buffer
|
||||||
|
for ( int i = 0; i < buf.size(); i++ )
|
||||||
|
_f.write ( buf[i].c_str(), buf[i].size() );
|
||||||
|
buf.resize(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void FlushThread()
|
||||||
|
{
|
||||||
|
// _isDying is already set: signal thread so it can see that too
|
||||||
|
_event.Release();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
string _filename;
|
||||||
|
File _f;
|
||||||
|
int _currentBuf;
|
||||||
|
vector<string> _buf[2];
|
||||||
|
Event _event;
|
||||||
|
Mutex _mutex;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mutex
|
||||||
|
|
||||||
|
class Mutex : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mutex();
|
||||||
|
~Mutex();
|
||||||
|
private:
|
||||||
|
void Acquire();
|
||||||
|
bool TryAcquire();
|
||||||
|
void Release();
|
||||||
|
public:
|
||||||
|
// sub-class used to lock the Mutex
|
||||||
|
class Lock : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Lock ( Mutex& m );
|
||||||
|
~Lock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// private data
|
||||||
|
Mutex& _m;
|
||||||
|
};
|
||||||
|
friend class Mutex::Lock;
|
||||||
|
|
||||||
|
|
||||||
|
// sub-class used to attempt to lock the mutex. Use operator bool()
|
||||||
|
// to test if the lock was successful
|
||||||
|
class TryLock : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TryLock ( Mutex& m );
|
||||||
|
~TryLock();
|
||||||
|
operator bool () { return _bLocked; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// private data
|
||||||
|
bool _bLocked;
|
||||||
|
Mutex& _m;
|
||||||
|
};
|
||||||
|
friend class Mutex::TryLock;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// platform-specific stuff:
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE _h;
|
||||||
|
#elif defined(UNIX)
|
||||||
|
pthread_mutex_t _mutex;
|
||||||
|
public: operator pthread_mutex_t* () { return &_mutex; }
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event
|
||||||
|
|
||||||
|
class Event : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Event();
|
||||||
|
~Event();
|
||||||
|
void Release(); // put into signaled state
|
||||||
|
void Wait();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE _handle;
|
||||||
|
#elif defined(UNIX)
|
||||||
|
//Sem util functions
|
||||||
|
void sem_init();
|
||||||
|
int sem_P();
|
||||||
|
int sem_V();
|
||||||
|
void sem_destroy();
|
||||||
|
|
||||||
|
int sem_id;
|
||||||
|
//pthread_cond_t _cond;
|
||||||
|
//Mutex _mutex;
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
//DECLARE_PTR(Event,(),());
|
||||||
|
}; //DECLARE_SPTR(Event,(),());
|
||||||
|
|
||||||
|
#endif//__RELIWIN32_H
|
504
rosapps/games/ArchBlackmann/SockUtils.cpp
Normal file
504
rosapps/games/ArchBlackmann/SockUtils.cpp
Normal file
|
@ -0,0 +1,504 @@
|
||||||
|
// SockUtils.cpp - Some basic socket utility functions.
|
||||||
|
// (C) 2002-2004 Royce Mitchell III
|
||||||
|
// This file is under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "SockUtils.h"
|
||||||
|
#ifdef WIN32
|
||||||
|
# ifndef SD_SEND // defined in winsock2.h, but not winsock.h
|
||||||
|
# define SD_SEND 1
|
||||||
|
# endif
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# pragma comment ( lib, "ws2_32.lib" )
|
||||||
|
# endif//_MSC_VER
|
||||||
|
#elif defined(UNIX)
|
||||||
|
# include <errno.h>
|
||||||
|
# include "string.h" // memset
|
||||||
|
# include <netdb.h> // hostent
|
||||||
|
# include <arpa/inet.h> //inet_addr
|
||||||
|
# include <sys/time.h>
|
||||||
|
# define SD_SEND SHUT_WR //bah thou shalt name thy defines the same
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
//// Constants /////////////////////////////////////////////////////////
|
||||||
|
const int kBufferSize = 1024;
|
||||||
|
// creates broadcast address
|
||||||
|
SockAddrIn::SockAddrIn()
|
||||||
|
{
|
||||||
|
memset ( this, 0, sizeof(sockaddr_in) );
|
||||||
|
sin_family = AF_INET;
|
||||||
|
}
|
||||||
|
SockAddrIn::SockAddrIn ( const char* szAddr, u_short iPort )
|
||||||
|
{
|
||||||
|
memset ( this, 0, sizeof(sockaddr_in) );
|
||||||
|
sin_family = AF_INET;
|
||||||
|
sin_addr.s_addr = suLookupAddress(szAddr);
|
||||||
|
sin_port = htons(iPort);
|
||||||
|
}
|
||||||
|
SockAddrIn::SockAddrIn ( in_addr_t iAddr, u_short iPort )
|
||||||
|
{
|
||||||
|
memset ( this, 0, sizeof(sockaddr_in) );
|
||||||
|
sin_family = AF_INET;
|
||||||
|
sin_addr.s_addr = iAddr;
|
||||||
|
sin_port = htons(iPort);
|
||||||
|
}
|
||||||
|
bool suStartup()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
WSADATA wsaData;
|
||||||
|
if ( WSAStartup ( MAKEWORD(2,0), &wsaData ) )
|
||||||
|
return false;
|
||||||
|
if ( wsaData.wVersion != MAKEWORD(2,0) )
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#elif defined(UNIX)
|
||||||
|
// nothing special required here
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//// suTcpSocket ////////////////////////////////////////////////
|
||||||
|
// Creates a TCP socket.
|
||||||
|
SOCKET suTcpSocket()
|
||||||
|
{
|
||||||
|
SOCKET so = socket ( AF_INET, SOCK_STREAM, 0 );
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( so == INVALID_SOCKET && WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
//// suUdpSocket ////////////////////////////////////////////////
|
||||||
|
// Creates a UDP socket. Compensates for new "functionality" introduced
|
||||||
|
// in Win2K with regards to select() calls
|
||||||
|
// MS Transport Provider IOCTL to control
|
||||||
|
// reporting PORT_UNREACHABLE messages
|
||||||
|
// on UDP sockets via recv/WSARecv/etc.
|
||||||
|
// Path TRUE in input buffer to enable (default if supported),
|
||||||
|
// FALSE to disable.
|
||||||
|
#ifndef SIO_UDP_CONNRESET
|
||||||
|
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
|
||||||
|
#endif//SIO_UDP_CONNRESET
|
||||||
|
SOCKET suUdpSocket()
|
||||||
|
{
|
||||||
|
SOCKET so = socket ( AF_INET, SOCK_DGRAM, 0 );
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( so == INVALID_SOCKET && WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
#ifdef WIN32
|
||||||
|
// for Windows 2000, disable new behavior...
|
||||||
|
// see: http://www-pc.uni-regensburg.de/systemsw/W2KPRO/UPDATE/POSTSP1/Q263823.htm
|
||||||
|
// this code is innocuous on other win32 platforms
|
||||||
|
DWORD dwBytesReturned = 0;
|
||||||
|
BOOL bNewBehavior = FALSE;
|
||||||
|
// disable new Win2K behavior using
|
||||||
|
// IOCTL: SIO_UDP_CONNRESET
|
||||||
|
// we don't care about return value :)
|
||||||
|
WSAIoctl(so, SIO_UDP_CONNRESET,
|
||||||
|
&bNewBehavior, sizeof(bNewBehavior),
|
||||||
|
NULL, 0, &dwBytesReturned,
|
||||||
|
NULL, NULL);
|
||||||
|
#endif
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
//// suShutdownConnection ////////////////////////////////////////////////
|
||||||
|
// Gracefully shuts the connection sd down. Returns true if it was able
|
||||||
|
// to shut it down nicely, false if we had to "slam" it shut.
|
||||||
|
// (either way, the socket does get closed)
|
||||||
|
bool suShutdownConnection(SOCKET sd)
|
||||||
|
{
|
||||||
|
if ( sd == INVALID_SOCKET )
|
||||||
|
return true;
|
||||||
|
// Disallow any further data sends. This will tell the other side
|
||||||
|
// that we want to go away now. If we skip this step, we don't
|
||||||
|
// shut the connection down nicely.
|
||||||
|
if (shutdown(sd, SD_SEND) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
closesocket(sd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Receive any extra data still sitting on the socket. After all
|
||||||
|
// data is received, this call will block until the remote host
|
||||||
|
// acknowledges the TCP control packet sent by the shutdown above.
|
||||||
|
// Then we'll get a 0 back from recv, signalling that the remote
|
||||||
|
// host has closed its side of the connection.
|
||||||
|
char acReadBuffer[kBufferSize];
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
int nNewBytes = recv(sd, acReadBuffer, kBufferSize, 0);
|
||||||
|
if (nNewBytes == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
closesocket(sd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (nNewBytes != 0)
|
||||||
|
{
|
||||||
|
// FYI, received (nNewBytes) unexpected bytes during shutdown.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Okay, we're done!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Close the socket.
|
||||||
|
if (closesocket(sd) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//// suLookupAddress ////////////////////////////////////////////////
|
||||||
|
// Basically converts a name address to an ip address
|
||||||
|
in_addr_t suLookupAddress ( const char* pcHost )
|
||||||
|
{
|
||||||
|
in_addr_t nRemoteAddr = inet_addr(pcHost);
|
||||||
|
if ( nRemoteAddr == INADDR_NONE )
|
||||||
|
{
|
||||||
|
// pcHost isn't a dotted IP, so resolve it through DNS
|
||||||
|
hostent* pHE = gethostbyname(pcHost);
|
||||||
|
if ( pHE == 0 )
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
return INADDR_NONE;
|
||||||
|
}
|
||||||
|
nRemoteAddr = *((in_addr_t*)pHE->h_addr_list[0]);
|
||||||
|
}
|
||||||
|
return nRemoteAddr;
|
||||||
|
}
|
||||||
|
bool suConnect ( SOCKET so, in_addr_t iAddress, u_short iPort )
|
||||||
|
{
|
||||||
|
SockAddrIn sinRemote ( iAddress, iPort );
|
||||||
|
if ( SOCKET_ERROR == connect(so,sinRemote,sizeof(sinRemote)) )
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool suConnect ( SOCKET so, const char* szAddress, u_short iPort )
|
||||||
|
{
|
||||||
|
return suConnect ( so, suLookupAddress(szAddress), iPort );
|
||||||
|
}
|
||||||
|
//// suEstablishConnection ////////////////////////////////////////////////
|
||||||
|
// creates a socket of the specified type, connects to the ip address/port
|
||||||
|
// requested, and returns the SOCKET created
|
||||||
|
SOCKET suEstablishConnection ( in_addr_t iAddress, u_short iPort, int type )
|
||||||
|
{
|
||||||
|
// Create a socket
|
||||||
|
if ( type != SOCK_STREAM && type != SOCK_DGRAM )
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
SOCKET so = socket(AF_INET, type, 0);
|
||||||
|
if ( so == INVALID_SOCKET )
|
||||||
|
return so;
|
||||||
|
if ( !suConnect(so, iAddress, iPort) )
|
||||||
|
{
|
||||||
|
closesocket(so);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
//// suEstablishConnection ////////////////////////////////////////////////
|
||||||
|
// creates a socket of the specified type, connects to the address/port
|
||||||
|
// requested, and returns the SOCKET created
|
||||||
|
SOCKET suEstablishConnection ( const char* szAddress, u_short iPort, int type )
|
||||||
|
{
|
||||||
|
return suEstablishConnection ( suLookupAddress ( szAddress ), iPort, type );
|
||||||
|
}
|
||||||
|
//// suBroadcast ////////////////////////////////////////////////
|
||||||
|
// takes a previously created broadcast-enabled UDP socket, and broadcasts
|
||||||
|
// a message on the local network
|
||||||
|
bool suBroadcast ( SOCKET so, u_short port, const char* buf, int len /* = -1 */ )
|
||||||
|
{
|
||||||
|
if ( len == -1 )
|
||||||
|
len = (int)strlen(buf);
|
||||||
|
#if 1
|
||||||
|
SockAddrIn to ( INADDR_BROADCAST, port );
|
||||||
|
#else // some strange MS OS's don't broadcast to localhost...
|
||||||
|
SockAddrIn to ( "127.0.0.1", port );
|
||||||
|
if ( SOCKET_ERROR == sendto ( so, buf, len, 0, to, sizeof(to) ) )
|
||||||
|
return false;
|
||||||
|
to.sin_addr.s_addr = INADDR_BROADCAST;
|
||||||
|
#endif
|
||||||
|
if ( SOCKET_ERROR == sendto ( so, buf, len, 0, to, sizeof(to) ) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//// suRecv ////////////////////////////////////////////////
|
||||||
|
// retrieves data sent to our TCP socket. If no data, waits for
|
||||||
|
// a period of timeout ms.
|
||||||
|
// returns bytes received
|
||||||
|
// -1 == SOCKET_ERROR
|
||||||
|
// -2 == timed out waiting for data
|
||||||
|
int suRecv ( SOCKET so, char* buf, int buflen, int timeout )
|
||||||
|
{
|
||||||
|
struct timeval to;
|
||||||
|
fd_set rread;
|
||||||
|
int res;
|
||||||
|
FD_ZERO(&rread); // clear the fd_set
|
||||||
|
FD_SET(so,&rread); // indicate which socket(s) we want to check
|
||||||
|
memset((char *)&to,0,sizeof(to)); // clear the timeval struct
|
||||||
|
to.tv_sec = timeout; // timeout select after (timeout) seconds
|
||||||
|
// select returns > 0 if there is an event on the socket
|
||||||
|
res = select((int)so+1, &rread, (fd_set *)0, (fd_set *)0, &to );
|
||||||
|
if (res < 0)
|
||||||
|
return -1; // socket error
|
||||||
|
// there was an event on the socket
|
||||||
|
if ( (res>0) && (FD_ISSET(so,&rread)) )
|
||||||
|
return recv ( so, buf, buflen, 0 );
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
//// suRecvFrom ////////////////////////////////////////////////
|
||||||
|
// retrieves data sent to our UDP socket. If no data, waits for
|
||||||
|
// a period of timeout ms.
|
||||||
|
// returns bytes received
|
||||||
|
// returns bytes received
|
||||||
|
// -1 == SOCKET_ERROR
|
||||||
|
// -2 == timed out waiting for data
|
||||||
|
int suRecvFrom ( SOCKET so, char* buf, int buflen, int timeout, sockaddr_in* from, socklen_t* fromlen )
|
||||||
|
{
|
||||||
|
struct timeval to;
|
||||||
|
fd_set rread;
|
||||||
|
int res;
|
||||||
|
FD_ZERO(&rread); // clear the fd_set
|
||||||
|
FD_SET(so,&rread); // indicate which socket(s) we want to check
|
||||||
|
memset((char *)&to,0,sizeof(to)); // clear the timeval struct
|
||||||
|
to.tv_sec = timeout; // timeout select after (timeout) seconds
|
||||||
|
// select returns > 0 if there is an event on the socket
|
||||||
|
res = select((int)so+1, &rread, (fd_set *)0, (fd_set *)0, &to );
|
||||||
|
if (res < 0)
|
||||||
|
return -1; // socket error
|
||||||
|
// there was an event on the socket
|
||||||
|
if ( (res>0) && (FD_ISSET(so,&rread)) )
|
||||||
|
return recvfrom ( so, buf, buflen, 0, (sockaddr*)from, fromlen );
|
||||||
|
return -2; // timeout
|
||||||
|
}
|
||||||
|
//// suBind ////////////////////////////////////////////////
|
||||||
|
// binds a UDP socket to an interface & port to receive
|
||||||
|
// data on that port
|
||||||
|
bool suBind ( SOCKET so, in_addr_t iInterfaceAddress, u_short iListenPort, bool bReuseAddr /* = false */ )
|
||||||
|
{
|
||||||
|
SockAddrIn sinInterface ( iInterfaceAddress, iListenPort );
|
||||||
|
if ( bReuseAddr )
|
||||||
|
{
|
||||||
|
int optval = -1; // true
|
||||||
|
if ( SOCKET_ERROR == setsockopt ( so, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval) ) )
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( SOCKET_ERROR == bind(so, sinInterface, sizeof(sinInterface)) )
|
||||||
|
{
|
||||||
|
int err = SUERRNO;
|
||||||
|
if ( err != EADDRINUSE )
|
||||||
|
return false;
|
||||||
|
#if defined(_DEBUG) && defined(WIN32)
|
||||||
|
if ( WSANOTINITIALISED == WSAGetLastError() )
|
||||||
|
MessageBox ( NULL, "You forgot to call suStartup()!", "SockUtils", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//// suBind ////////////////////////////////////////////////
|
||||||
|
// binds a UDP socket to an interface & port to receive
|
||||||
|
// data on that port
|
||||||
|
bool suBind ( SOCKET so, const char* szInterfaceAddress, u_short iListenPort, bool bReuseAddr /* = false */ )
|
||||||
|
{
|
||||||
|
in_addr_t iInterfaceAddr = inet_addr(szInterfaceAddress);
|
||||||
|
if ( iInterfaceAddr == INADDR_NONE )
|
||||||
|
return false;
|
||||||
|
return suBind ( so, iInterfaceAddr, iListenPort, bReuseAddr );
|
||||||
|
}
|
||||||
|
//// suEnableBroadcast ////////////////////////////////////////////////
|
||||||
|
// in order to send broadcast messages on a UDP socket, this function
|
||||||
|
// must be called first
|
||||||
|
bool suEnableBroadcast ( SOCKET so, bool bEnable /* = true */ )
|
||||||
|
{
|
||||||
|
int optval = bEnable ? -1 : 0;
|
||||||
|
if ( SOCKET_ERROR == setsockopt ( so, SOL_SOCKET, SO_BROADCAST, (const char*)&optval, sizeof(optval) ) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//// suErrDesc ////////////////////////////////////////////////
|
||||||
|
// returns text description of error code
|
||||||
|
const char* suErrDesc ( int err )
|
||||||
|
{
|
||||||
|
static char errbuf[256];
|
||||||
|
#ifdef WIN32
|
||||||
|
switch ( err )
|
||||||
|
{
|
||||||
|
#define X(E) case E: return #E;
|
||||||
|
X(WSAEINTR) X(WSAEBADF)
|
||||||
|
X(WSAEACCES) X(WSAEFAULT)
|
||||||
|
X(WSAEINVAL) X(WSAEMFILE)
|
||||||
|
X(WSAEWOULDBLOCK) X(WSAEINPROGRESS)
|
||||||
|
X(WSAEALREADY) X(WSAENOTSOCK)
|
||||||
|
X(WSAEDESTADDRREQ) X(WSAEMSGSIZE)
|
||||||
|
X(WSAEPROTOTYPE) X(WSAENOPROTOOPT)
|
||||||
|
X(WSAEPROTONOSUPPORT) X(WSAESOCKTNOSUPPORT)
|
||||||
|
X(WSAEOPNOTSUPP) X(WSAEPFNOSUPPORT)
|
||||||
|
X(WSAEAFNOSUPPORT) X(WSAEADDRINUSE)
|
||||||
|
X(WSAEADDRNOTAVAIL) X(WSAENETDOWN)
|
||||||
|
X(WSAENETUNREACH) X(WSAENETRESET)
|
||||||
|
X(WSAECONNABORTED) X(WSAECONNRESET)
|
||||||
|
X(WSAENOBUFS) X(WSAEISCONN)
|
||||||
|
X(WSAENOTCONN) X(WSAESHUTDOWN)
|
||||||
|
X(WSAETOOMANYREFS) X(WSAETIMEDOUT)
|
||||||
|
X(WSAECONNREFUSED) X(WSAELOOP)
|
||||||
|
X(WSAENAMETOOLONG) X(WSAEHOSTDOWN)
|
||||||
|
X(WSAEHOSTUNREACH) X(WSAENOTEMPTY)
|
||||||
|
X(WSAEPROCLIM) X(WSAEUSERS)
|
||||||
|
X(WSAEDQUOT) X(WSAESTALE)
|
||||||
|
X(WSAEREMOTE) X(WSASYSNOTREADY)
|
||||||
|
X(WSAVERNOTSUPPORTED) X(WSANOTINITIALISED)
|
||||||
|
X(WSAEDISCON) X(WSAENOMORE)
|
||||||
|
X(WSAECANCELLED) X(WSAEINVALIDPROCTABLE)
|
||||||
|
X(WSAEINVALIDPROVIDER) X(WSAEPROVIDERFAILEDINIT)
|
||||||
|
X(WSASYSCALLFAILURE) X(WSASERVICE_NOT_FOUND)
|
||||||
|
X(WSATYPE_NOT_FOUND) X(WSA_E_NO_MORE)
|
||||||
|
X(WSA_E_CANCELLED) X(WSAEREFUSED)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
snprintf ( errbuf, sizeof(errbuf), "Unknown socket error (%lu)", err );
|
||||||
|
errbuf[sizeof(errbuf)-1] = '\0';
|
||||||
|
return errbuf;
|
||||||
|
#elif defined(UNIX)
|
||||||
|
perror(errbuf);
|
||||||
|
return errbuf;
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||||||
|
in_addr_t suLookupAddress ( const wchar_t* pcHost )
|
||||||
|
{
|
||||||
|
int len = wcslen(pcHost);
|
||||||
|
char* p = new char[len+1];
|
||||||
|
wcstombs ( p, pcHost, len );
|
||||||
|
p[len] = 0;
|
||||||
|
in_addr_t rc = suLookupAddress ( p );
|
||||||
|
delete[] p;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
bool suBroadcast ( SOCKET so, u_short port, const wchar_t* buf, int len /* = -1 */ )
|
||||||
|
{
|
||||||
|
char* p = new char[len+1];
|
||||||
|
wcstombs ( p, buf, len );
|
||||||
|
p[len] = 0;
|
||||||
|
bool rc = suBroadcast ( so, port, p, len );
|
||||||
|
delete[] p;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
int suRecv ( SOCKET so, wchar_t* buf, int buflen, int timeout )
|
||||||
|
{
|
||||||
|
char* p = new char[buflen+1];
|
||||||
|
int rc = suRecv ( so, p, buflen, timeout );
|
||||||
|
p[buflen] = 0;
|
||||||
|
mbstowcs ( buf, p, buflen );
|
||||||
|
delete[] p;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
int suRecvFrom ( SOCKET so, wchar_t* buf, int buflen, int timeout, sockaddr_in* from, int* fromlen )
|
||||||
|
{
|
||||||
|
char* p = new char[buflen+1];
|
||||||
|
int rc = suRecvFrom ( so, p, buflen, timeout, from, fromlen );
|
||||||
|
p[buflen] = 0;
|
||||||
|
mbs2wcs ( buf, p, buflen );
|
||||||
|
delete[] p;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
bool suBind ( SOCKET so, const wchar_t* szInterfaceAddress, u_short iListenPort, bool bReuseAddr /* = false */ )
|
||||||
|
{
|
||||||
|
int len = wcslen(szInterfaceAddress);
|
||||||
|
char* p = new char[len+1];
|
||||||
|
wcstombs ( p, szInterfaceAddress, len );
|
||||||
|
p[len] = 0;
|
||||||
|
bool rc = suBind ( so, p, iListenPort, bReuseAddr );
|
||||||
|
delete[] p;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif//UNICODE
|
||||||
|
|
||||||
|
suBufferedRecvSocket::suBufferedRecvSocket ( SOCKET so )
|
||||||
|
: suSocket ( so ), _off(0), _len(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int suBufferedRecvSocket::recvUntil ( std::string& buf, char until, int timeout )
|
||||||
|
{
|
||||||
|
if ( !_len )
|
||||||
|
_off = 0;
|
||||||
|
else if ( _off > (sizeof(_buf)>>1) )
|
||||||
|
{
|
||||||
|
memmove ( _buf, &_buf[_off], _len );
|
||||||
|
_off = 0;
|
||||||
|
}
|
||||||
|
char* poff = &_buf[_off];
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
char* p = (char*)memchr ( poff, until, _len );
|
||||||
|
if ( p /*&& p < &poff[_len]*/ )
|
||||||
|
{
|
||||||
|
int ret_len = p-poff+1;
|
||||||
|
buf.resize ( ret_len );
|
||||||
|
memmove ( &buf[0], poff, ret_len );
|
||||||
|
_off += ret_len;
|
||||||
|
_len -= ret_len;
|
||||||
|
return ret_len;
|
||||||
|
}
|
||||||
|
int rc = suRecv ( *this, &poff[_len], sizeof(_buf)-_len-_off, timeout );
|
||||||
|
if ( rc < 0 )
|
||||||
|
{
|
||||||
|
if ( _len )
|
||||||
|
{
|
||||||
|
rc = _len;
|
||||||
|
buf.resize ( rc );
|
||||||
|
memmove ( &buf[0], &_buf[_off], rc );
|
||||||
|
_len = 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
_len += rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void suBufferedRecvSocket::recvPending()
|
||||||
|
{
|
||||||
|
if ( !_len )
|
||||||
|
_off = 0;
|
||||||
|
else if ( _off > (sizeof(_buf)>>1) )
|
||||||
|
{
|
||||||
|
memmove ( _buf, &_buf[_off], _len );
|
||||||
|
_off = 0;
|
||||||
|
}
|
||||||
|
char* poff = &_buf[_off];
|
||||||
|
while ( sizeof(_buf)-_len-_off )
|
||||||
|
{
|
||||||
|
int rc = suRecv ( *this, &poff[_len], sizeof(_buf)-_len-_off, 1 );
|
||||||
|
if ( rc <= 0 )
|
||||||
|
break;
|
||||||
|
_len += rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool suBufferedRecvSocket::recvInStr ( char c )
|
||||||
|
{
|
||||||
|
return NULL != memchr ( &_buf[_off], c, _len );
|
||||||
|
}
|
132
rosapps/games/ArchBlackmann/SockUtils.h
Normal file
132
rosapps/games/ArchBlackmann/SockUtils.h
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// SockUtils.h - Declarations for the Winsock utility functions module.
|
||||||
|
// (C) 2002-2004 Royce Mitchell III
|
||||||
|
// This file is under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef __SOCKUTILS_H
|
||||||
|
#define __SOCKUTILS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <winsock2.h>
|
||||||
|
# define in_addr_t u_long
|
||||||
|
# define SUERRNO WSAGetLastError()
|
||||||
|
# define EADDRINUSE WSAEADDRINUSE
|
||||||
|
# define ENOTSOCK WSAENOTSOCK
|
||||||
|
# define socklen_t int
|
||||||
|
#elif defined(UNIX)
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# define closesocket(so) close(so)
|
||||||
|
# define SOCKET int
|
||||||
|
# define INVALID_SOCKET -1
|
||||||
|
# define SOCKET_ERROR -1
|
||||||
|
# define SUERRNO errno
|
||||||
|
# ifdef MACOSX
|
||||||
|
# define socklen_t int //Stupid mac
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# error unrecognized target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
extern bool suStartup();
|
||||||
|
extern SOCKET suTcpSocket();
|
||||||
|
extern SOCKET suUdpSocket();
|
||||||
|
extern bool suShutdownConnection(SOCKET sd);
|
||||||
|
extern in_addr_t suLookupAddress ( const char* pcHost );
|
||||||
|
extern bool suConnect ( SOCKET so, in_addr_t iAddress, u_short iPort );
|
||||||
|
extern bool suConnect ( SOCKET so, const char* szAddress, u_short iPort );
|
||||||
|
extern SOCKET suEstablishConnection ( in_addr_t iAddress, u_short iPort, int type );
|
||||||
|
extern SOCKET suEstablishConnection ( const char* szAddress, u_short iPort, int type );
|
||||||
|
extern bool suBroadcast ( SOCKET so, u_short port, const char* buf, int len = -1 );
|
||||||
|
extern int suRecv ( SOCKET so, char* buf, int buflen, int timeout );
|
||||||
|
extern int suRecvFrom ( SOCKET so, char* buf, int buflen, int timeout, sockaddr_in* from, socklen_t* fromlen );
|
||||||
|
extern bool suBind ( SOCKET so, in_addr_t iInterfaceAddress, u_short iListenPort, bool bReuseAddr = false );
|
||||||
|
extern bool suBind ( SOCKET so, const char* szInterfaceAddress, u_short iListenPort, bool bReuseAddr = false );
|
||||||
|
extern bool suEnableBroadcast ( SOCKET so, bool bEnable = true );
|
||||||
|
extern const char* suErrDesc ( int err );
|
||||||
|
|
||||||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||||||
|
extern in_addr_t suLookupAddress ( const wchar_t* pcHost );
|
||||||
|
extern bool suBroadcast ( SOCKET so, u_short port, const wchar_t* buf, int len = -1 );
|
||||||
|
extern int suRecv ( SOCKET so, wchar_t* buf, int buflen, int timeout );
|
||||||
|
extern int suRecvFrom ( SOCKET so, wchar_t* buf, int buflen, int timeout, sockaddr_in* from, int* fromlen );
|
||||||
|
extern bool suBind ( SOCKET so, const wchar_t* szInterfaceAddress, u_short iListenPort, bool bReuseAddr = false );
|
||||||
|
#endif//UNICODE
|
||||||
|
|
||||||
|
class suSocket
|
||||||
|
{
|
||||||
|
SOCKET _so;
|
||||||
|
public:
|
||||||
|
suSocket ( SOCKET so = INVALID_SOCKET ) : _so(so)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const suSocket& operator = ( SOCKET so )
|
||||||
|
{
|
||||||
|
assert ( _so == INVALID_SOCKET ); // must Detach() or Close() existing socket first
|
||||||
|
_so = so;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
virtual ~suSocket()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
if ( _so != INVALID_SOCKET )
|
||||||
|
{
|
||||||
|
//suShutdownConnection ( _so ); // TODO - only valid on TCP sockets
|
||||||
|
closesocket ( _so );
|
||||||
|
_so = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operator SOCKET() const
|
||||||
|
{
|
||||||
|
return _so;
|
||||||
|
}
|
||||||
|
SOCKET Attach ( SOCKET so )
|
||||||
|
{
|
||||||
|
SOCKET old = Detach();
|
||||||
|
_so = so;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
SOCKET Detach()
|
||||||
|
{
|
||||||
|
SOCKET so = _so;
|
||||||
|
_so = INVALID_SOCKET;
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// disable copy semantics
|
||||||
|
suSocket ( const suSocket& );
|
||||||
|
const suSocket& operator = ( const suSocket& );
|
||||||
|
};
|
||||||
|
|
||||||
|
class suBufferedRecvSocket : public suSocket
|
||||||
|
{
|
||||||
|
char _buf[2048];
|
||||||
|
int _off;
|
||||||
|
int _len;
|
||||||
|
public:
|
||||||
|
suBufferedRecvSocket ( SOCKET so = INVALID_SOCKET );
|
||||||
|
int recvUntil ( std::string& buf, char until, int timeout );
|
||||||
|
void recvPending();
|
||||||
|
bool recvInStr ( char c );
|
||||||
|
};
|
||||||
|
|
||||||
|
class SockAddrIn : public sockaddr_in
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SockAddrIn(); // creates broadcast address
|
||||||
|
SockAddrIn ( const char* szAddr, u_short iPort );
|
||||||
|
SockAddrIn ( in_addr_t iAddr, u_short iPort );
|
||||||
|
operator sockaddr* () { return (sockaddr*)this; }
|
||||||
|
operator sockaddr_in* () { return (sockaddr_in*)this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//__SOCKUTILS_H
|
96
rosapps/games/ArchBlackmann/SplitJoin.cpp
Normal file
96
rosapps/games/ArchBlackmann/SplitJoin.cpp
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
// SplitJoin.cpp
|
||||||
|
//
|
||||||
|
// This code is copyright 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning ( disable : 4786 ) // MSVC6 can't handle too-long template names
|
||||||
|
#endif//_MSC_VER
|
||||||
|
|
||||||
|
//#include <sstream>
|
||||||
|
|
||||||
|
#include "SplitJoin.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
//using std::stringstream;
|
||||||
|
|
||||||
|
static const char* quotes = "\"\'";
|
||||||
|
|
||||||
|
bool Split ( vector<string>& vec, const char* csv, char sep, bool merge )
|
||||||
|
{
|
||||||
|
string scsv ( csv );
|
||||||
|
char* col = &scsv[0];
|
||||||
|
vec.resize ( 0 );
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
char* p = col;
|
||||||
|
while ( isspace(*p) && *p != sep )
|
||||||
|
p++;
|
||||||
|
char quote = 0;
|
||||||
|
if ( strchr ( quotes, *p ) )
|
||||||
|
quote = *p++;
|
||||||
|
while ( *p && (*p != sep || quote) )
|
||||||
|
{
|
||||||
|
if ( *p++ == quote )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( isspace(*p) && *p != sep )
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if ( *p && *p != sep )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string scol ( col, p-col );
|
||||||
|
|
||||||
|
//quote = scol[0];
|
||||||
|
if ( quote )
|
||||||
|
{
|
||||||
|
if ( scol[scol.size()-1] == quote )
|
||||||
|
scol = string ( &scol[1], scol.size()-2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( scol.length() || !merge )
|
||||||
|
vec.push_back ( scol );
|
||||||
|
|
||||||
|
if ( !*p )
|
||||||
|
break;
|
||||||
|
|
||||||
|
col = p + 1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Join ( string& csv, vector<string>& vec, char sep )
|
||||||
|
{
|
||||||
|
csv.resize(0);
|
||||||
|
for ( int i = 0; i < vec.size(); i++ )
|
||||||
|
{
|
||||||
|
if ( i )
|
||||||
|
csv += sep;
|
||||||
|
string& s = vec[i];
|
||||||
|
if ( strchr ( s.c_str(), sep ) )
|
||||||
|
{
|
||||||
|
if ( strchr ( s.c_str(), '\"' ) )
|
||||||
|
{
|
||||||
|
if ( strchr ( s.c_str(), '\'' ) )
|
||||||
|
return false; // the sep, " and ' are all in the string, can't build valid output
|
||||||
|
csv += '\'';
|
||||||
|
csv += s;
|
||||||
|
csv += '\'';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
csv += '\"';
|
||||||
|
csv += s;
|
||||||
|
csv += '\"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
csv += s;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
32
rosapps/games/ArchBlackmann/SplitJoin.h
Normal file
32
rosapps/games/ArchBlackmann/SplitJoin.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// SplitJoin.h
|
||||||
|
//
|
||||||
|
// This code is copyright 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef SPLITJOIN_H
|
||||||
|
#define SPLITJOIN_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
bool Split (
|
||||||
|
std::vector<std::string>& vec,
|
||||||
|
const char* csv,
|
||||||
|
char sep=',',
|
||||||
|
bool merge=false );
|
||||||
|
|
||||||
|
bool Join (
|
||||||
|
std::string& csv,
|
||||||
|
std::vector<std::string>& vec,
|
||||||
|
char sep=',' );
|
||||||
|
|
||||||
|
inline bool Split (
|
||||||
|
std::vector<std::string>& vec,
|
||||||
|
const std::string& csv,
|
||||||
|
char sep=',',
|
||||||
|
bool merge=false )
|
||||||
|
{
|
||||||
|
return Split ( vec, csv.c_str(), sep, merge );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif//SPLIT_H
|
240
rosapps/games/ArchBlackmann/ThreadPool.cpp
Normal file
240
rosapps/games/ArchBlackmann/ThreadPool.cpp
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
// ThreadPool.cpp
|
||||||
|
// This file is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
using std::vector;
|
||||||
|
#include "ThreadPool.h"
|
||||||
|
#include "QueueT.h"
|
||||||
|
#include "auto_vector.h"
|
||||||
|
#include "verify.h"
|
||||||
|
#include "ReliMT.h"
|
||||||
|
|
||||||
|
class PoolableThread : public ActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PoolableThread ( ThreadPoolImpl& );
|
||||||
|
~PoolableThread()
|
||||||
|
{
|
||||||
|
Kill();
|
||||||
|
}
|
||||||
|
void InitThread();
|
||||||
|
void Run();
|
||||||
|
void FlushThread();
|
||||||
|
|
||||||
|
ThreadPoolImpl& _pool;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThreadPoolLaunchData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadPoolFunc* pFun;
|
||||||
|
void* pArg;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class AtomicCounter : public Uncopyable
|
||||||
|
{
|
||||||
|
Mutex _m;
|
||||||
|
T _t;
|
||||||
|
public:
|
||||||
|
AtomicCounter ( T init = 0 ) : _t(init)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
AtomicCounter ( const AtomicCounter<T>& t )
|
||||||
|
{
|
||||||
|
//Mutex::Lock l ( _m ); // don't need to lock since this is a ctor
|
||||||
|
Mutex::Lock l2 ( t._m );
|
||||||
|
_t = t._t;
|
||||||
|
}
|
||||||
|
const AtomicCounter<T>& operator = ( const AtomicCounter<T>& t )
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
Mutex::Lock l2 ( t._m );
|
||||||
|
_t = t._t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
T operator ++ ()
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
T t = _t++;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
const AtomicCounter<T>& operator ++ ( int )
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
++_t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
T operator -- ()
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
T t = _t--;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
const AtomicCounter<T>& operator -- ( int )
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
--_t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const AtomicCounter<T>& operator += ( T t )
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
return _t += t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const AtomicCounter<T>& operator -= ( T t )
|
||||||
|
{
|
||||||
|
Mutex::Lock l ( _m );
|
||||||
|
return _t -= t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
operator const T& () const
|
||||||
|
{
|
||||||
|
//Mutex::Lock l ( _m );
|
||||||
|
return _t;
|
||||||
|
}
|
||||||
|
T operator !() const
|
||||||
|
{
|
||||||
|
//Mutex::Lock l ( _m );
|
||||||
|
return !_t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThreadPoolImpl : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadPoolImpl() : _isDying(false), _idleThreads(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ThreadPoolImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
_isDying = true;
|
||||||
|
while ( _idleThreads )
|
||||||
|
{
|
||||||
|
_threadWaitEvent.Release();
|
||||||
|
_threadStartEvent.Wait(); // let thread actually get a grip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launch ( ThreadPoolFunc* pFun, void* pArg )
|
||||||
|
{
|
||||||
|
// this mutex is necessary to make sure we never have a conflict
|
||||||
|
// between checking !_idleThreads and the call to _threadStartEvent.Wait()
|
||||||
|
// basically if 2 threads call Launch() simultaneously, and there is only
|
||||||
|
// 1 idle thread, it's possible that a new thread won't be created to
|
||||||
|
// satisfy the 2nd request until an existing thread finishes.
|
||||||
|
Mutex::Lock launchlock ( _launchMutex );
|
||||||
|
|
||||||
|
ASSERT ( pFun );
|
||||||
|
ThreadPoolLaunchData* data;
|
||||||
|
{
|
||||||
|
Mutex::Lock lock ( _vectorMutex );
|
||||||
|
if ( !_spareData.size() )
|
||||||
|
_spareData.push_back ( new ThreadPoolLaunchData() );
|
||||||
|
data = _spareData.pop_back().release();
|
||||||
|
if ( !_idleThreads )
|
||||||
|
_threads.push_back ( new PoolableThread(*this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
data->pFun = pFun;
|
||||||
|
data->pArg = pArg;
|
||||||
|
verify ( _pendingData.Add ( data ) );
|
||||||
|
_threadWaitEvent.Release(); // tell a thread to do it's thing...
|
||||||
|
_threadStartEvent.Wait(); // wait on a thread to pick up the request
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions for threads to call...
|
||||||
|
ThreadPoolLaunchData* GetPendingData()
|
||||||
|
{
|
||||||
|
ThreadPoolLaunchData* data = NULL;
|
||||||
|
++_idleThreads;
|
||||||
|
_threadWaitEvent.Wait(); // waits until there's a request
|
||||||
|
--_idleThreads;
|
||||||
|
_threadStartEvent.Release(); // tell requester we got it
|
||||||
|
if ( _isDying )
|
||||||
|
return NULL;
|
||||||
|
_pendingData.Get ( data );
|
||||||
|
ASSERT ( data );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecycleData ( ThreadPoolLaunchData* data )
|
||||||
|
{
|
||||||
|
Mutex::Lock lock ( _vectorMutex );
|
||||||
|
_spareData.push_back ( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isDying;
|
||||||
|
Mutex _vectorMutex, _launchMutex;
|
||||||
|
auto_vector<PoolableThread> _threads;
|
||||||
|
auto_vector<ThreadPoolLaunchData> _spareData;
|
||||||
|
CQueueT<ThreadPoolLaunchData*> _pendingData;
|
||||||
|
Event _threadWaitEvent, _threadStartEvent;
|
||||||
|
AtomicCounter<int> _idleThreads;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ThreadPool
|
||||||
|
|
||||||
|
/*static*/ ThreadPool& ThreadPool::Instance()
|
||||||
|
{
|
||||||
|
static ThreadPool tp;
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPool::ThreadPool() : _pimpl ( new ThreadPoolImpl )
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
ThreadPool::~ThreadPool()
|
||||||
|
{
|
||||||
|
_pimpl->Shutdown();
|
||||||
|
delete _pimpl;
|
||||||
|
_pimpl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadPool::Launch ( ThreadPoolFunc* pFun, void* pArg )
|
||||||
|
{
|
||||||
|
_pimpl->Launch ( pFun, pArg );
|
||||||
|
}
|
||||||
|
|
||||||
|
int ThreadPool::IdleThreads()
|
||||||
|
{
|
||||||
|
return _pimpl->_idleThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PoolableThread
|
||||||
|
|
||||||
|
PoolableThread::PoolableThread ( ThreadPoolImpl& pool ) : _pool(pool)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoolableThread::InitThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoolableThread::Run()
|
||||||
|
{
|
||||||
|
ThreadPoolLaunchData* data;
|
||||||
|
while ( !_isDying )
|
||||||
|
{
|
||||||
|
data = _pool.GetPendingData(); // enter wait state if none...
|
||||||
|
if ( !data ) // NULL data means kill thread
|
||||||
|
break;
|
||||||
|
(*data->pFun) ( data->pArg ); // call the function
|
||||||
|
_pool.RecycleData ( data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoolableThread::FlushThread()
|
||||||
|
{
|
||||||
|
}
|
28
rosapps/games/ArchBlackmann/ThreadPool.h
Normal file
28
rosapps/games/ArchBlackmann/ThreadPool.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// ThreadPool.h
|
||||||
|
// This file is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#ifndef THREADPOOL_H
|
||||||
|
#define THREADPOOL_H
|
||||||
|
|
||||||
|
#include "ReliMT.h"
|
||||||
|
|
||||||
|
typedef void THREADAPI ThreadPoolFunc ( void* );
|
||||||
|
|
||||||
|
class ThreadPoolImpl;
|
||||||
|
|
||||||
|
class ThreadPool : public Uncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ThreadPool& Instance();
|
||||||
|
~ThreadPool();
|
||||||
|
|
||||||
|
void Launch ( ThreadPoolFunc* pFun, void* pArg );
|
||||||
|
int IdleThreads();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ThreadPool();
|
||||||
|
ThreadPoolImpl *_pimpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif// THREADPOOL_H
|
87
rosapps/games/ArchBlackmann/auto_ptr.h
Normal file
87
rosapps/games/ArchBlackmann/auto_ptr.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// auto_ptr.h
|
||||||
|
// This file is (C) 2002-2003 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#ifndef AUTO_PTR_H
|
||||||
|
#define AUTO_PTR_H
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class auto_ptr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
explicit auto_ptr(T *p = 0) : _p(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr(auto_ptr<T>& rhs) : _p(rhs.release())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr<T>& operator=(auto_ptr<T>& rhs)
|
||||||
|
{
|
||||||
|
if ( &rhs != this )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
_p = rhs.release();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr<T>& set ( auto_ptr<T>& rhs )
|
||||||
|
{
|
||||||
|
if ( &rhs != this )
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
_p = rhs.release();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~auto_ptr()
|
||||||
|
{
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose()
|
||||||
|
{
|
||||||
|
if ( _p )
|
||||||
|
{
|
||||||
|
delete _p;
|
||||||
|
_p = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[] ( int i )
|
||||||
|
{
|
||||||
|
return _p[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*() const
|
||||||
|
{
|
||||||
|
return *_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() const
|
||||||
|
{
|
||||||
|
return _p;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get() const
|
||||||
|
{
|
||||||
|
return _p;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* release()
|
||||||
|
{
|
||||||
|
T* p = _p;
|
||||||
|
_p = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* _p;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//AUTO_PTR_H
|
141
rosapps/games/ArchBlackmann/auto_vector.h
Normal file
141
rosapps/games/ArchBlackmann/auto_vector.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
// auto_vector.h
|
||||||
|
// This file is (C) 2002-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#ifndef AUTO_VECTOR_H
|
||||||
|
#define AUTO_VECTOR_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "verify.h"
|
||||||
|
#include "auto_ptr.h"
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class auto_vector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit auto_vector ( size_t capacity = 0 )
|
||||||
|
: _arr(0), _capacity(0), _end(0)
|
||||||
|
{
|
||||||
|
if ( capacity != 0 )
|
||||||
|
_arr = new auto_ptr<T>[capacity];
|
||||||
|
_capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
~auto_vector()
|
||||||
|
{
|
||||||
|
delete []_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return _end;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto_ptr<T>& operator [] ( size_t i ) const
|
||||||
|
{
|
||||||
|
ASSERT ( i < _end );
|
||||||
|
return _arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr<T>& operator [] ( size_t i )
|
||||||
|
{
|
||||||
|
ASSERT ( i < _end );
|
||||||
|
return _arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign ( size_t i, auto_ptr<T>& p )
|
||||||
|
{
|
||||||
|
ASSERT ( i < _end );
|
||||||
|
_arr[i] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_direct ( size_t i, T * p )
|
||||||
|
{
|
||||||
|
ASSERT ( i < _end );
|
||||||
|
reserve ( i + 1 );
|
||||||
|
_arr[i].reset ( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back ( auto_ptr<T>& p )
|
||||||
|
{
|
||||||
|
reserve ( _end + 1 );
|
||||||
|
_arr[_end++] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr<T>& back()
|
||||||
|
{
|
||||||
|
ASSERT ( _end != 0 );
|
||||||
|
return _arr[_end-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back ( T * p )
|
||||||
|
{
|
||||||
|
reserve ( _end + 1 );
|
||||||
|
auto_ptr<T> tmp(p);
|
||||||
|
_arr[_end++] = tmp;
|
||||||
|
//GCC is pedantic, this is an error.
|
||||||
|
//_arr[_end++] = auto_ptr<T>(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_ptr<T> pop_back()
|
||||||
|
{
|
||||||
|
ASSERT ( _end != 0 );
|
||||||
|
if ( !_end )
|
||||||
|
{
|
||||||
|
auto_ptr<T> tmp((T*)0);
|
||||||
|
return tmp;
|
||||||
|
//GCC, this is an error.
|
||||||
|
//return auto_ptr<T>(NULL);
|
||||||
|
}
|
||||||
|
return _arr[--_end];
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize ( size_t newSize )
|
||||||
|
{
|
||||||
|
ASSERT ( newSize >= 0 );
|
||||||
|
reserve ( newSize ); // make sure we have at least this much room
|
||||||
|
_end = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve ( size_t reqCapacity )
|
||||||
|
{
|
||||||
|
if ( reqCapacity <= _capacity )
|
||||||
|
return;
|
||||||
|
size_t newCapacity = 2 * _capacity;
|
||||||
|
if ( reqCapacity > newCapacity )
|
||||||
|
newCapacity = reqCapacity;
|
||||||
|
// allocate new array
|
||||||
|
auto_ptr<T> * arrNew = new auto_ptr<T> [newCapacity];
|
||||||
|
// transfer all entries
|
||||||
|
for ( size_t i = 0; i < _capacity; ++i )
|
||||||
|
arrNew[i] = _arr[i];
|
||||||
|
_capacity = newCapacity;
|
||||||
|
// free old memory
|
||||||
|
delete[] _arr;
|
||||||
|
// substitute new array for old array
|
||||||
|
_arr = arrNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove ( size_t off )
|
||||||
|
{
|
||||||
|
size_t last = _end-1;
|
||||||
|
if ( off == last )
|
||||||
|
resize ( last );
|
||||||
|
else if ( off < last )
|
||||||
|
{
|
||||||
|
auto_ptr<T> tmp ( pop_back().release() );
|
||||||
|
_arr[off] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//typedef const_auto_iterator<T> const_iterator;
|
||||||
|
//const_iterator begin () const { return _arr; }
|
||||||
|
//const_iterator end () const { return _arr + _end; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto_ptr<T> *_arr;
|
||||||
|
size_t _capacity;
|
||||||
|
size_t _end;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//AUTO_VECTOR_H
|
58
rosapps/games/ArchBlackmann/base64.cpp
Normal file
58
rosapps/games/ArchBlackmann/base64.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// base64.cpp
|
||||||
|
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
static const char* alfabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
string base64_encode ( const string& sInput )
|
||||||
|
{
|
||||||
|
unsigned char x=0, topbit=0;
|
||||||
|
int v=0;
|
||||||
|
string sOutput;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( topbit < 6 )
|
||||||
|
{
|
||||||
|
x++;
|
||||||
|
v <<= 8;
|
||||||
|
if ( x <= sInput.length() ) v += sInput[x-1];
|
||||||
|
topbit += 8;
|
||||||
|
}
|
||||||
|
topbit -= 6;
|
||||||
|
if ( x > sInput.length() && !v )
|
||||||
|
break;
|
||||||
|
sOutput += alfabet[(v >> topbit) & 63];
|
||||||
|
v &= (1 << topbit) - 1;
|
||||||
|
} while ( x < sInput.length() || v );
|
||||||
|
int eq = (8 - (sOutput.length() % 4)) % 4;
|
||||||
|
while ( eq-- )
|
||||||
|
sOutput += '=';
|
||||||
|
return sOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
string base64_decode ( const string& sInput )
|
||||||
|
{
|
||||||
|
unsigned char x=0, topbit=0;
|
||||||
|
int v=0, inlen = sInput.length();
|
||||||
|
string sOutput;
|
||||||
|
while ( inlen && sInput[inlen-1] == '=' )
|
||||||
|
inlen--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while ( topbit < 8 )
|
||||||
|
{
|
||||||
|
x++;
|
||||||
|
v <<= 6;
|
||||||
|
if ( x <= inlen ) v += (strchr(alfabet, sInput[x-1]) - alfabet);
|
||||||
|
topbit += 6;
|
||||||
|
}
|
||||||
|
topbit -= 8;
|
||||||
|
if ( x > inlen && !v )
|
||||||
|
break;
|
||||||
|
sOutput += (char)((v >> topbit) & 255);
|
||||||
|
v &= ((1 << topbit) - 1);
|
||||||
|
} while ( x <= inlen || v );
|
||||||
|
return sOutput;
|
||||||
|
}
|
12
rosapps/games/ArchBlackmann/base64.h
Normal file
12
rosapps/games/ArchBlackmann/base64.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// base64.h
|
||||||
|
|
||||||
|
#ifndef BASE64_H
|
||||||
|
#define BASE64_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string base64_encode ( const std::string& s );
|
||||||
|
|
||||||
|
std::string base64_decode ( const std::string& s );
|
||||||
|
|
||||||
|
#endif//BASE64_H
|
15
rosapps/games/ArchBlackmann/chomp.cpp
Normal file
15
rosapps/games/ArchBlackmann/chomp.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// chomp.cpp
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#include "chomp.h"
|
||||||
|
|
||||||
|
std::string chomp ( const std::string& s )
|
||||||
|
{
|
||||||
|
const char* p = &s[0];
|
||||||
|
const char* p2 = &s[0] + s.size();
|
||||||
|
while ( p2 > p && strchr("\r\n", p2[-1]) )
|
||||||
|
p2--;
|
||||||
|
return std::string ( p, p2-p );
|
||||||
|
}
|
||||||
|
|
13
rosapps/games/ArchBlackmann/chomp.h
Normal file
13
rosapps/games/ArchBlackmann/chomp.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// chomp.h
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef CHOMP_H
|
||||||
|
#define CHOMP_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string chomp ( const std::string& s );
|
||||||
|
|
||||||
|
#endif//TRIM_H
|
||||||
|
|
23
rosapps/games/ArchBlackmann/cram_md5.cpp
Normal file
23
rosapps/games/ArchBlackmann/cram_md5.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// cram_md5.cpp
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
#include "cram_md5.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
string cram_md5 ( const string& username, const string& password, const string& greeting )
|
||||||
|
{
|
||||||
|
string challenge = base64_decode ( greeting );
|
||||||
|
|
||||||
|
string hmac = HMAC_MD5 ( password, challenge );
|
||||||
|
//printf ( "(cram_md5): hmac = %s\n", hmac.c_str() );
|
||||||
|
string raw_response = username;
|
||||||
|
raw_response += " ";
|
||||||
|
raw_response += hmac;
|
||||||
|
//printf ( "(cram_md5): raw_response = %s\n", raw_response.c_str() );
|
||||||
|
|
||||||
|
return base64_encode ( raw_response );
|
||||||
|
}
|
15
rosapps/games/ArchBlackmann/cram_md5.h
Normal file
15
rosapps/games/ArchBlackmann/cram_md5.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// cram_md5.h
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef CRAM_MD5_H
|
||||||
|
#define CRAM_MD5_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string cram_md5 (
|
||||||
|
const std::string& username,
|
||||||
|
const std::string& password,
|
||||||
|
const std::string& greeting );
|
||||||
|
|
||||||
|
#endif//CRAM_MD5_H
|
34
rosapps/games/ArchBlackmann/panic.cpp
Normal file
34
rosapps/games/ArchBlackmann/panic.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// panic.cpp
|
||||||
|
// This file is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <conio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif//WIN32
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
|
void panic ( const char* format, ... )
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
va_start(arg, format);
|
||||||
|
#if defined(WIN32) && !defined(_CONSOLE)
|
||||||
|
char buf[4096];
|
||||||
|
_vsnprintf ( buf, sizeof(buf)-1, format, arg );
|
||||||
|
MessageBox ( NULL, buf, "Panic!", MB_OK|MB_ICONEXCLAMATION );
|
||||||
|
#else
|
||||||
|
done = vprintf(format, arg);
|
||||||
|
printf ( "\n" );
|
||||||
|
#endif
|
||||||
|
va_end(arg);
|
||||||
|
#if defined(WIN32) && defined(_CONSOLE)
|
||||||
|
printf ( "Press any key to exit\n" );
|
||||||
|
(void)getch();
|
||||||
|
#endif//WIN32 && _CONSOLE
|
||||||
|
exit ( -1 );
|
||||||
|
}
|
18
rosapps/games/ArchBlackmann/panic.h
Normal file
18
rosapps/games/ArchBlackmann/panic.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// panic.h
|
||||||
|
// This file is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef PANIC_H
|
||||||
|
#define PANIC_H
|
||||||
|
|
||||||
|
void panic ( const char* format, ... );
|
||||||
|
|
||||||
|
#define suAssert(expr) if ( !(expr) ) panic ( "%s(%lu): SOCKET ERROR %s\nExpression: %s\n", __FILE__, __LINE__, suErrDesc(SUERRNO), #expr )
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
|
# define suVerify(expr) suAssert(expr)
|
||||||
|
#else
|
||||||
|
# define suVerify(expr) expr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif//PANIC_H
|
17
rosapps/games/ArchBlackmann/trim.cpp
Normal file
17
rosapps/games/ArchBlackmann/trim.cpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// trim.cpp
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#include "trim.h"
|
||||||
|
|
||||||
|
std::string trim ( const std::string& s )
|
||||||
|
{
|
||||||
|
const char* p = &s[0];
|
||||||
|
const char* p2 = p + s.size();
|
||||||
|
while ( *p == ' ' )
|
||||||
|
p++;
|
||||||
|
while ( p2 > p && p2[-1] == ' ' )
|
||||||
|
p2--;
|
||||||
|
return std::string ( p, p2-p );
|
||||||
|
}
|
||||||
|
|
13
rosapps/games/ArchBlackmann/trim.h
Normal file
13
rosapps/games/ArchBlackmann/trim.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// trim.h
|
||||||
|
// This file is (C) 2004 Royce Mitchell III
|
||||||
|
// and released under the BSD & LGPL licenses
|
||||||
|
|
||||||
|
#ifndef TRIM_H
|
||||||
|
#define TRIM_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string trim ( const std::string& s );
|
||||||
|
|
||||||
|
#endif//TRIM_H
|
||||||
|
|
37
rosapps/games/ArchBlackmann/verify.h
Normal file
37
rosapps/games/ArchBlackmann/verify.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// verify.h
|
||||||
|
// This code is (C) 2003-2004 Royce Mitchell III
|
||||||
|
// and released under the LGPL & BSD licenses
|
||||||
|
|
||||||
|
#ifndef VERIFY_H
|
||||||
|
#define VERIFY_H
|
||||||
|
|
||||||
|
//#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
#undef ASSERT
|
||||||
|
#endif//ASSERT
|
||||||
|
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
|
inline void AssertHandler ( bool b, const char* str )
|
||||||
|
{
|
||||||
|
if ( !b )
|
||||||
|
panic ( str );
|
||||||
|
}
|
||||||
|
# define ASSERT(x) AssertHandler((x) ? true : false, #x )
|
||||||
|
#else
|
||||||
|
# define ASSERT(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef verify
|
||||||
|
#undef verify
|
||||||
|
#endif//verify
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
|
# define verify(x) ASSERT(x)
|
||||||
|
#else
|
||||||
|
# define verify(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif//VERIFY_H
|
Loading…
Reference in a new issue