Added gamespy SDK

This commit is contained in:
L 2023-02-04 21:00:01 +01:00
parent 294ca5ffd2
commit dd44f78fc5
642 changed files with 186078 additions and 0 deletions

View file

@ -0,0 +1,131 @@
Changelog for: GameSpy Chat SDK
--------------------------------------------------------
DATE VERSION BY TYPE DESCRIPTION
---------- ------- --- ------- ---------------------------------------------------------
12-12-2007 1.15.00 RMV RELEASE Released to Developer Site
08-06-2007 1.14.00 RMV RELEASE Released to Developer Site
07-10-2007 1.13.01 RMV FIX Fixed chatc Project files to get rid of Unicode warnings and fixed other compiler warnings
06-28-2007 1.13.00 DDW FEATURE Added UDP relay support
12-15-2006 1.12.00 MJW RELEASE Released to Developer Site
12-11-2006 1.11.40 SN OTHER Added visual studio 2005 projects for samples
SN OTHER Fixed warnings with visual studio 2005 projects
10-05-2006 1.11.39 SAH FIX Updated MacOSX Makefile
09-28-2006 1.11.38 SAH FIX Fixed PS3 project to work with PS3 095.00x SDK; changed included libaries in linker input.
09-05-2006 1.11.37 SN FIX Updated Revolution support
Fixed bug in the case where null strings were being ignored.
08-02-2006 1.11.36 SAH RELEASE Releasing to developer site
07-31-2006 1.11.36 SAH FIX Fixed PS3 project file - added post-build step to create *.SELF for execution
07-24-2006 1.11.35 SAH FIX Fixed NITRO project, include for crt0.o now above others so it add correct file
07-06-2006 1.11.34 SAH FIX Fixed PSP project file - the linker file was explicitly included in a project
06-30-2006 1.11.33 SAH FIX Fixed NITRO project & linker command file (for Codewarrior 2.0/NitroSDK 3.1)
SAH FIX Fixed Linux makefile
06-02-2006 1.11.32 SAH FIX Added GS_STATIC_CALLBACK on comparator functions for __fastcall support
05-31-2006 1.11.31 SAH RELEASE Releasing to developer site
SAH FIX Fixed Linux makefiles
05-25-2006 1.11.31 SAH FIX Added some GSI_UNUSED calls to get rid of PSP warnings
SAH FIX Changed PS3 project settings to compile with 084_001 SDK
05-19-2006 1.11.30 SAH FIX Added gsTestMain.c to nitro CodeWarrior project
04-25-2006 1.11.29 SAH RELEASE Releasing to developer site
04-24-2006 1.11.29 SAH FIX Fixed the nitro project to work on test machine, removed unncessary source files
04-20-2006 1.11.28 SAH FIX commented out unused variables to get rid of warnings
01-27-2006 1.11.27 SN RELEASE Releasing to developer site
01-26-2006 1.11.27 SN OTHER Added psp prodg solution and project to sgv
01-09-2006 1.11.27 SN FIX Updated code to use default server address and port
12-13-2005 1.11.26 SN OTHER Updated Visual Studio .NET Projects to use new common dir
Created Visual Studio .NET Solution
Removed old Static Library chat.vcproj
12-02-2005 1.11.26 SN FIX Added a check before freeing variable
11-17-2005 1.11.25 DES FIX Removed unneeded assert.
DES FIX Compatibility fix.
DES FIX Updated Nitro Makefile.
11-14-2005 1.11.24 DES FIX Updated the OSX Makefile.
DES FEATURE Adding GSI_DOMAIN_NAME support.
09-21-2005 1.11.23 DES FEATURE Updated DS support
07-28-2005 1.11.22 SN RELEASE Releasing to developer site.
06-03-2005 1.11.22 SN RELEASE Releasing to developer site.
04-29-2005 1.11.22 SN OTHER Created Visual Studio .NET projects for existing projects.
04-28-2005 1.11.22 SN RELEASE Releasing to developer site.
04-27-2005 1.11.22 DES RELEASE Limited release to Nintendo DS developers.
04-04-2005 1.11.22 SN RELEASE Releasing to developer site.
03-31-2005 1.11.22 SN FIX Added some preprocessor code to stop compiler warnings.
03-14-2005 1.11.21 DES FEATURE Nintendo DS support
11-25-2004 1.11.20 SN FIX Added const qualifiers to function parameters not modified
10-15-2004 1.11.19 SN FEATURE Added SDK side nickname checking
09-20-2004 1.11.18 BED FIX ciUserTableCompareFn now treats NULL parameter as "less than" (Arcade helper)
09-16-2004 1.11.17 SN RELEASE Releasing to developer site.
09-15-2004 1.11.17 DDW FEATURE Added global version var to pass on crypt for Arcade blacklisting
09-13-2004 1.11.16 BED FEATURE Added support for channel mode "e". (Ops obey channel limit)
08-27-2004 1.11.15 DES CLEANUP Removed MacOS style includes
DES CLEANUP General Unicode cleanup
DES CLEANUP Updated Win32 project configurations
DES CLEANUP Fixed warnings under OSX
DES CLEANUP Updated OSX Makefile
08-10-2004 1.11.14 BED FIX ciSocketRecv will now process remaining messages after a disconnect.
08-05-2004 1.11.13 SN RELEASE Releasing to developer site.
07-19-2004 1.11.13 SN FIX Updated code with explicit casts to remove implicit cast error when compiling
at highest level and warnings treated as errors.
06-18-2004 1.11.12 BED RELEASE Releasing to developer site.
06-16-2004 1.11.12 BED FEATURE Added PS2 Insock (LibNet) support
04-19-2004 1.11.11 DDW FIX Fixed USRIP handler - handles message correctly after login
12-08-2003 1.11.10 BED FIX Updated PS2 sample for Sony 3.0. UNICODE no longer defined.
11-10-2003 1.11.09 DES RELEASE Releasing to developer site.
11-07-2003 1.11.09 DES FIX Updated the linux makefile to include the MD5 code.
11-06-2003 1.11.08 BED FIX Removed some unnecessary asserts in Unicode layer.
BED FIX Slight correction in sample callback.
BED FIX Sample no longer includes <crtdbg.h> Leftover from memory leak testing.
10-23-2003 1.11.07 BED FIX Changed StringUtil to accept char* instead of unsigned char*
BED FIX Removed additional warnings for various compilers.
10-22-2003 1.11.06 BED RELEASE Releasing to developer site. (UNIQUE NICK AND UNICODE SUPPORT)
10-21-2003 1.11.06 BED FIX Added ChatASCII.h to silence all the CodeWarrior prototype warnings
BED FIX Cleaned up other misc warnings.
10-17-2003 1.11.05 DES FIX It now always picks the correct name to use for the socket log.
10-16-2003 1.11.04 BED FIX Switched from UTF8 to Ascii when dealing with nicknames.
DES FIX Always pass the appropriate nick to the chatNickErrorCallback.
FIX Correctly handle chatConnectLogin with a 0 namespaceID.
10-09-2003 1.11.03 BED FIX Switched to gsi_time type instead of unsinged long for PS2 compatibility
10-06-2003 1.11.02 DES FIX chatGet[User|Profile]ID now return values during the connection attempt.
10-01-2003 1.11.01 DES FEATURE Added a reason code for failed connect attempts.
FEATURE Added suggested nicks for a CHAT_INVALID_UNIQUENICK nick errors.
09-30-2003 1.11.00 DES FEATURE Uniquenick support.
09-30-2003 1.10.27 BED FEATURE Update Chat sample to support GSI_UNICODE mode.
09-15-2003 1.10.26 JED FIX Minor change to CONNECTED macro to be more robust.
09-08-2003 1.10.25 BED FEATURE Added UTF-8 Wrapper for UNICODE support.
FIX Fixed crash when chatRetryWithNick was called with NULL. (As directed in the documentation)
07-24-2003 1.10.24 DES RELEASE Releasing to developer site.
07-24-2003 1.10.24 DES FIX Added GSI_UNUSED around an unused param.
07-18-2003 1.10.23 BED FEATURE Added CodeWarrior (PS2) sample project file.
CLEANUP General cleanup to remove CodeWarrior (PS2) warnings.
07-17-2003 1.10.22 DES CLEANUP Cleaned up the PS2 Makefile, it now uses Makefile.commmon.
07-16-2003 1.10.21 BED FIX Added a newline at end of chatmain.c
DES FIX Changed two __mips64 checks to _PS2 checks.
BED FEATURE Added ProDG sample project files.
07-14-2003 1.10.20 BED FIX Now using ciNickIsValid to validate nicknames on client side.
07-14-2003 1.10.19 DES FIX Correctly handle being disconnected during the connection attempt.
07-11-2003 1.10.18 BED FIX Updated sample to join nonrestricted channel.
06-26-2003 1.10.17 DES CLEANUP Reduced the initial sizes of the channel and user hash tables.
06-11-2003 1.10.16 DES RELEASE Releasing to developer site.
05-09-2003 1.10.16 DES CLEANUP Removed Dreamcast support.
FIX Metrowerks for Win32 is no longer falsely identified as MacOS.
05-07-2003 1.10.15 DES RELEASE Releasing to developer site.
04-23-2003 1.10.15 BGW FIX Now handling the case of localtime() returning NULL.
04-17-2003 1.10.14 DES FIX Fix for simultaneous WHO requests on a single user.
04-16-2003 1.10.13 DDW FEATURE Added chatInChannel function exposing ciInChannel functionality
03-19-2003 1.10.12 DES FEATURE IRC logging (IRC_LOG) now uses the nick as part of the filename.
03-12-2003 1.10.11 DES FIX If requesting 0 keys for a channel, correctly request all keys.
03-11-2003 1.10.10 DES FIX chatGetChannelKeys no longer asserts if keys is NULL.
If keys is NULL and num is 0, all keys are returned.
03-03-2003 1.10.09 DES CLEANUP General cleanup to remove warnings.
FEATURE Added chatSetChannelLimit for directly setting a channel limit.
01-09-2003 1.10.08 DES CLEANUP Removed an unneeded assert.
12-19-2002 1.10.07 DES RELEASE Releasing to developer site.
12-19-2002 1.10.07 DES CLEANUP Removed assert.h includes.
12-13-2002 1.10.06 DES FEATURE Added PS2 eenet stack support.
12-05-2002 1.10.05 DES CLEANUP Added some explicit type casting to eliminate warnings.
11-22-2002 1.10.04 DES RELEASE Releasing to developer site.
11-20-2002 1.10.04 DES CLEANUP Cleaned up to remove compiler warings on the PS2.
11-15-2002 1.10.03 DES OTHER Changed chatc to use chatConnectSecure.
11-07-2002 1.10.02 DES FIX Fixed negative hash due to high-ascii characters in hashed string.
10-17-2002 1.10.01 DES RELEASE Limited release on developer site
10-17-2002 1.10.01 DES FIX Fixed bug where incoming data was not processed when disconnected.
09-25-2002 1.10.00 DDW OTHER Changelog started

998
code/gamespy/Chat/chat.h Normal file
View file

@ -0,0 +1,998 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHAT_H_
#define _CHAT_H_
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "../common/gsCommon.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
/************
** DEFINES **
************/
// User and channel message types.
//////////////////////////////////
#define CHAT_MESSAGE 0
#define CHAT_ACTION 1
#define CHAT_NOTICE 2
#define CHAT_UTM 3
#define CHAT_ATM 4
// User modes.
// PANTS|03.12.01 - These are now bitflags!
// Both CHAT_VOICE and CHAT_OP can be set at the same time.
///////////////////////////////////////////////////////////
#define CHAT_NORMAL 0
#define CHAT_VOICE 1
#define CHAT_OP 2
// Part reasons (see the chatUserParted callback).
//////////////////////////////////////////////////
#define CHAT_LEFT 0 // The user left the channel.
#define CHAT_QUIT 1 // The user quit the chat network.
#define CHAT_KICKED 2 // The user was kicked from the channel.
#define CHAT_KILLED 3 // The user was kicked off the chat network.
// Possible nick errors while connecting.
/////////////////////////////////////////
#define CHAT_NICK_OK 0
#define CHAT_IN_USE 1
#define CHAT_INVALID 2
#define CHAT_UNIQUENICK_EXPIRED 3
#define CHAT_NO_UNIQUENICK 4
#define CHAT_INVALID_UNIQUENICK 5
#define CHAT_NICK_TOO_LONG 6
// Reasons why a connect attempt could fail.
////////////////////////////////////////////
#define CHAT_DISCONNECTED 0
#define CHAT_NICK_ERROR 1
#define CHAT_LOGIN_FAILED 2
/**********
** TYPES **
**********/
// Boolean type.
////////////////
typedef enum { CHATFalse, CHATTrue } CHATBool;
// A CHAT object represents a client connection to a chat server.
/////////////////////////////////////////////////////////////////
typedef void * CHAT;
// Object representing a channel's mode.
////////////////////////////////////////
typedef struct CHATChannelMode
{
CHATBool InviteOnly;
CHATBool Private;
CHATBool Secret;
CHATBool Moderated;
CHATBool NoExternalMessages;
CHATBool OnlyOpsChangeTopic;
CHATBool OpsObeyChannelLimit;
int Limit;
} CHATChannelMode;
// The result of a channel enter attempt,
// passed into the chatEnterChannelCallback().
//////////////////////////////////////////////
typedef enum
{
CHATEnterSuccess, // The channel was successfully entered.
CHATBadChannelName, // The channel name was invalid.
CHATChannelIsFull, // The channel is at its user limit.
CHATInviteOnlyChannel, // The channel is invite only.
CHATBannedFromChannel, // The local user is banned from this channel.
CHATBadChannelPassword, // The channel has a password, and a bad password (or none) was given.
CHATTooManyChannels, // The server won't allow this user in any more channels.
CHATEnterTimedOut, // The attempt to enter timed out.
CHATBadChannelMask // Not sure if any servers use this, or what it means! (ERR_BADCHANMASK)
} CHATEnterResult;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifndef GSI_UNICODE
#define chatConnect chatConnectA
#define chatConnectSpecial chatConnectSpecialA
#define chatConnectSecure chatConnectSecureA
#define chatConnectLogin chatConnectLoginA
#define chatConnectPreAuth chatConnectPreAuthA
#define chatRetryWithNick chatRetryWithNickA
#define chatRegisterUniqueNick chatRegisterUniqueNickA
#define chatSendRaw chatSendRawA
#define chatChangeNick chatChangeNickA
#define chatFixNick chatFixNickA
#define chatTranslateNick chatTranslateNickA
#define chatAuthenticateCDKey chatAuthenticateCDKeyA
#define chatEnumChannels chatEnumChannelsA
#define chatEnterChannel chatEnterChannelA
#define chatLeaveChannel chatLeaveChannelA
#define chatSendChannelMessage chatSendChannelMessageA
#define chatSetChannelTopic chatSetChannelTopicA
#define chatGetChannelTopic chatGetChannelTopicA
#define chatSetChannelMode chatSetChannelModeA
#define chatGetChannelMode chatGetChannelModeA
#define chatSetChannelPassword chatSetChannelPasswordA
#define chatGetChannelPassword chatGetChannelPasswordA
#define chatSetChannelLimit chatSetChannelLimitA
#define chatEnumChannelBans chatEnumChannelBansA
#define chatAddChannelBan chatAddChannelBanA
#define chatRemoveChannelBan chatRemoveChannelBanA
#define chatSetChannelGroup chatSetChannelGroupA
#define chatGetChannelNumUsers chatGetChannelNumUsersA
#define chatInChannel chatInChannelA
#define chatEnumUsers chatEnumUsersA
#define chatSendUserMessage chatSendUserMessageA
#define chatGetUserInfo chatGetUserInfoA
#define chatGetBasicUserInfo chatGetBasicUserInfoA
#define chatGetBasicUserInfoNoWait chatGetBasicUserInfoNoWaitA
#define chatGetChannelBasicUserInfo chatGetChannelBasicUserInfoA
#define chatInviteUser chatInviteUserA
#define chatKickUser chatKickUserA
#define chatBanUser chatBanUserA
#define chatSetUserMode chatSetUserModeA
#define chatGetUserMode chatGetUserModeA
#define chatGetUserModeNoWait chatGetUserModeNoWaitA
#define chatSetGlobalKeys chatSetGlobalKeysA
#define chatSetChannelKeys chatSetChannelKeysA
#define chatGetGlobalKeys chatGetGlobalKeysA
#define chatGetChannelKeys chatGetChannelKeysA
#define chatGetNick chatGetNickA
#define chatGetUdpRelay chatGetUdpRelayA
#else
#define chatConnect chatConnectW
#define chatConnectSpecial chatConnectSpecialW
#define chatConnectSecure chatConnectSecureW
#define chatConnectLogin chatConnectLoginW
#define chatConnectPreAuth chatConnectPreAuthW
#define chatRetryWithNick chatRetryWithNickW
#define chatRegisterUniqueNick chatRegisterUniqueNickW
#define chatSendRaw chatSendRawW
#define chatChangeNick chatChangeNickW
#define chatFixNick chatFixNickW
#define chatTranslateNick chatTranslateNickW
#define chatAuthenticateCDKey chatAuthenticateCDKeyW
#define chatEnumChannels chatEnumChannelsW
#define chatEnterChannel chatEnterChannelW
#define chatLeaveChannel chatLeaveChannelW
#define chatSendChannelMessage chatSendChannelMessageW
#define chatSetChannelTopic chatSetChannelTopicW
#define chatGetChannelTopic chatGetChannelTopicW
#define chatSetChannelMode chatSetChannelModeW
#define chatGetChannelMode chatGetChannelModeW
#define chatSetChannelPassword chatSetChannelPasswordW
#define chatGetChannelPassword chatGetChannelPasswordW
#define chatSetChannelLimit chatSetChannelLimitW
#define chatEnumChannelBans chatEnumChannelBansW
#define chatAddChannelBan chatAddChannelBanW
#define chatRemoveChannelBan chatRemoveChannelBanW
#define chatSetChannelGroup chatSetChannelGroupW
#define chatGetChannelNumUsers chatGetChannelNumUsersW
#define chatInChannel chatInChannelW
#define chatEnumUsers chatEnumUsersW
#define chatSendUserMessage chatSendUserMessageW
#define chatGetUserInfo chatGetUserInfoW
#define chatGetBasicUserInfo chatGetBasicUserInfoW
#define chatGetBasicUserInfoNoWait chatGetBasicUserInfoNoWaitW
#define chatGetChannelBasicUserInfo chatGetChannelBasicUserInfoW
#define chatInviteUser chatInviteUserW
#define chatKickUser chatKickUserW
#define chatBanUser chatBanUserW
#define chatSetUserMode chatSetUserModeW
#define chatGetUserMode chatGetUserModeW
#define chatGetUserModeNoWait chatGetUserModeNoWaitW
#define chatSetGlobalKeys chatSetGlobalKeysW
#define chatSetChannelKeys chatSetChannelKeysW
#define chatGetGlobalKeys chatGetGlobalKeysW
#define chatGetChannelKeys chatGetChannelKeysW
#define chatGetNick chatGetNickW
#define chatGetUdpRelay chatGetUdpRelayW
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/**********************
** GLOBALS CALLBACKS **
**********************/
// Gets raw incoming network traffic.
/////////////////////////////////////
typedef void (* chatRaw)(CHAT chat,
const gsi_char * raw,
void * param);
// Called when the client has been disconnected.
////////////////////////////////////////////////
typedef void (* chatDisconnected)(CHAT chat,
const gsi_char * reason,
void * param);
// Called when a private message from another user is received.
// If user==NULL, this is a message from the server.
///////////////////////////////////////////////////////////////
typedef void (* chatPrivateMessage)(CHAT chat,
const gsi_char * user,
const gsi_char * message,
int type, // See defined message types above.
void * param);
// Called when invited into a channel.
//////////////////////////////////////
typedef void (* chatInvited)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
void * param);
// A connection's global callbacks.
///////////////////////////////////
typedef struct chatGlobalCallbacks
{
chatRaw raw;
chatDisconnected disconnected;
chatPrivateMessage privateMessage;
chatInvited invited;
void * param;
} chatGlobalCallbacks;
/**********************
** CHANNEL CALLBACKS **
**********************/
// Called when a message is received in a channel.
//////////////////////////////////////////////////
typedef void (* chatChannelMessage)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
const gsi_char * message,
int type, // See defined message types above.
void * param);
// Called when the local client is kicked from a channel.
/////////////////////////////////////////////////////////
typedef void (* chatKicked)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
const gsi_char * reason,
void * param);
// Called when a user joins a channel we're in.
///////////////////////////////////////////////
typedef void (* chatUserJoined)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int mode, // See defined user modes above.
void * param);
// Called when a user parts a channel we're in.
///////////////////////////////////////////////
typedef void (* chatUserParted)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int why, // See defined part reasons above.
const gsi_char * reason,
const gsi_char * kicker,
void * param);
// Called when a user in a channel we're in changes nicks.
//////////////////////////////////////////////////////////
typedef void (* chatUserChangedNick)(CHAT chat,
const gsi_char * channel,
const gsi_char * oldNick,
const gsi_char * newNick,
void * param);
// Called when the topic changes in a channel we're in.
///////////////////////////////////////////////////////
typedef void (* chatTopicChanged)(CHAT chat,
const gsi_char * channel,
const gsi_char * topic,
void * param);
// Called when the mode changes in a channel we're in.
//////////////////////////////////////////////////////
typedef void (* chatChannelModeChanged)(CHAT chat,
const gsi_char * channel,
CHATChannelMode * mode,
void * param);
// Called when a user's mode changes in a channel we're in.
///////////////////////////////////////////////////////////
typedef void (* chatUserModeChanged)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int mode, // See defined user modes above.
void * param);
// Called when the user list changes (due to a join or a part) in a channel we're in.
/////////////////////////////////////////////////////////////////////////////////////
typedef void (* chatUserListUpdated)(CHAT chat,
const gsi_char * channel,
void * param);
// Called when the chat server sends an entire new user list for a channel we're in.
////////////////////////////////////////////////////////////////////////////////////
typedef void (* chatNewUserList)(CHAT chat,
const gsi_char * channel,
int num,
const gsi_char ** users,
int * modes,
void * param);
// Called when a user changes a broadcast key in a channel we're in.
////////////////////////////////////////////////////////////////////
typedef void (* chatBroadcastKeyChanged)(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
const gsi_char * key,
const gsi_char * value,
void * param);
// A channel's callbacks.
/////////////////////////
typedef struct chatChannelCallbacks
{
chatChannelMessage channelMessage;
chatKicked kicked;
chatUserJoined userJoined;
chatUserParted userParted;
chatUserChangedNick userChangedNick;
chatTopicChanged topicChanged;
chatChannelModeChanged channelModeChanged;
chatUserModeChanged userModeChanged;
chatUserListUpdated userListUpdated;
chatNewUserList newUserList;
chatBroadcastKeyChanged broadcastKeyChanged;
void * param;
} chatChannelCallbacks;
/************
** GENERAL **
************/
// Called when a connect attempt completes.
// failureReason is only set if success is CHATFalse.
/////////////////////////////////////////////////////
typedef void (* chatConnectCallback)(CHAT chat,
CHATBool success,
int failureReason, // CHAT_DISCONNECTED, CHAT_NICK_ERROR, etc.
void * param);
// Called if there is an error with the nick while connecting.
// To retry with a new nick, call chatRetryWithNick.
// Otherwise, call chatDisconnect to stop the connection.
// Suggested nicks are only provided if type is CHAT_INVALID_UNIQUENICK.
////////////////////////////////////////////////////////////////////////
typedef void (* chatNickErrorCallback)(CHAT chat,
int type, // CHAT_IN_USE, CHAT_INVALID, etc.
const gsi_char * nick,
int numSuggestedNicks,
const gsi_char ** suggestedNicks,
void * param);
typedef void (* chatFillInUserCallback)(CHAT chat,
unsigned int IP, // PANTS|08.21.00 - changed from unsigned long
gsi_char user[128],
void * param);
// Connects you to a chat server and returns a CHAT object.
///////////////////////////////////////////////////////////
CHAT chatConnect(const gsi_char * serverAddress,
int port,
const gsi_char * nick,
const gsi_char * user,
const gsi_char * name,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectSpecial(const gsi_char * serverAddress,
int port,
const gsi_char * nick,
const gsi_char * name,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectSecure(const gsi_char * serverAddress,
int port,
const gsi_char * nick,
const gsi_char * name,
const gsi_char * gamename,
const gsi_char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectLogin(const gsi_char * serverAddress,
int port,
int namespaceID,
const gsi_char * email,
const gsi_char * profilenick,
const gsi_char * uniquenick,
const gsi_char * password,
const gsi_char * name,
const gsi_char * gamename,
const gsi_char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectPreAuth(const gsi_char * serverAddress,
int port,
const gsi_char * authtoken,
const gsi_char * partnerchallenge,
const gsi_char * name,
const gsi_char * gamename,
const gsi_char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
// If the chatNickErrorCallback gets called, then this can be called
// with a new nick to retry. If this isn't called, the connection can be
// disconnected with chatDisconnect. If the new nick is successful, then
// the chatConnectCallback will get called. If there's another nick
// error, the chatNickErrorCallback will get called again.
/////////////////////////////////////////////////////////////////////////
void chatRetryWithNick(CHAT chat,
const gsi_char * nick);
// Register a uniquenick.
// Should be called in response to the chatNickErrorCallback being called
// with a type of CHAT_UNIQUENICK_EXPIRED or CHAT_NO_UNIQUENICK.
// If the uniquenick cannot be registered, the chatNickErrorCallback will
// be called again with a type of CHAT_IN_USE or CHAT_INVALID.
/////////////////////////////////////////////////////////////////////////
void chatRegisterUniqueNick(CHAT chat,
int namespaceID,
const gsi_char * uniquenick,
const gsi_char * cdkey);
// Disconnect the chat connection.
//////////////////////////////////
void chatDisconnect(CHAT chat);
// Processes the chat connection.
/////////////////////////////////
void chatThink(CHAT chat);
// Sends raw data, without any interpretation.
//////////////////////////////////////////////
void chatSendRaw(CHAT chat,
const gsi_char * command);
// Called as a result of a nick change attempt.
///////////////////////////////////////////////
typedef void (* chatChangeNickCallback)(CHAT chat,
CHATBool success,
const gsi_char * oldNick,
const gsi_char * newNick,
void * param);
// Change the local user's nick.
////////////////////////////////
void chatChangeNick(CHAT chat,
const gsi_char * newNick,
chatChangeNickCallback callback,
void * param,
CHATBool blocking);
// Get our local nickname.
//////////////////////////
const gsi_char * chatGetNick(CHAT chat);
// Copies the oldNick to the newNick, replacing any invalid characters with legal ones.
///////////////////////////////////////////////////////////////////////////////////////
void chatFixNick(gsi_char * newNick,
const gsi_char * oldNick);
// Removes the namespace extension from a chat nick.
////////////////////////////////////////////////////
const gsi_char * chatTranslateNick(gsi_char * nick,
const gsi_char * extension);
// Gets the local userID.
// Only valid if connected with chatConnectLogin or chatConnectPreAuth.
///////////////////////////////////////////////////////////////////////
int chatGetUserID(CHAT chat);
// Gets the local profileID.
// Only valid if connected with chatConnectLogin or chatConnectPreAuth.
///////////////////////////////////////////////////////////////////////
int chatGetProfileID(CHAT chat);
// Turn on/off quiet mode.
//////////////////////////
void chatSetQuietMode(CHAT chat,
CHATBool quiet);
// Called as a result of an authenticate CD key attempt.
////////////////////////////////////////////////////////
typedef void (* chatAuthenticateCDKeyCallback)(CHAT chat,
int result,
const gsi_char * message,
void * param);
// Attempts to authenticates a CD key.
//////////////////////////////////////
void chatAuthenticateCDKey(CHAT chat,
const gsi_char * cdkey,
chatAuthenticateCDKeyCallback callback,
void * param,
CHATBool blocking);
/*************
** CHANNELS **
*************/
// Gets called for each channel enumerated.
///////////////////////////////////////////
typedef void (* chatEnumChannelsCallbackEach)(CHAT chat,
CHATBool success,
int index,
const gsi_char * channel,
const gsi_char * topic,
int numUsers,
void * param);
// Gets called after all channels have been enumerated.
///////////////////////////////////////////////////////
typedef void (* chatEnumChannelsCallbackAll)(CHAT chat,
CHATBool success,
int numChannels,
const gsi_char ** channels,
const gsi_char ** topics,
int * numUsers,
void * param);
// Enumerates the channels available on a chat server.
//////////////////////////////////////////////////////
void chatEnumChannels(CHAT chat,
const gsi_char * filter,
chatEnumChannelsCallbackEach callbackEach,
chatEnumChannelsCallbackAll callbackAll,
void * param,
CHATBool blocking);
// Gets called for each channel enumerated.
///////////////////////////////////////////
typedef void (* chatEnumJoinedChannelsCallback)(CHAT chat,
int index,
const gsi_char * channel,
void * param);
// Enumerates the channels that we are joined to
//////////////////////////////////////////////////////
void chatEnumJoinedChannels(CHAT chat,
chatEnumJoinedChannelsCallback callback,
void * param);
// Gets called when a channel has been entered.
///////////////////////////////////////////////
typedef void (* chatEnterChannelCallback)(CHAT chat,
CHATBool success,
CHATEnterResult result,
const gsi_char * channel,
void * param);
// Enters a channel.
////////////////////
void chatEnterChannel(CHAT chat,
const gsi_char * channel,
const gsi_char * password,
chatChannelCallbacks * callbacks,
chatEnterChannelCallback callback,
void * param,
CHATBool blocking);
// Leaves a channel.
////////////////////
void chatLeaveChannel(CHAT chat,
const gsi_char * channel,
const gsi_char * reason); // PANTS|03.13.01
// Sends a message to a channel.
////////////////////////////////
void chatSendChannelMessage(CHAT chat,
const gsi_char * channel,
const gsi_char * message,
int type);
// Sets the topic in a channel.
///////////////////////////////
void chatSetChannelTopic(CHAT chat,
const gsi_char * channel,
const gsi_char * topic);
// Gets called when a channel's topic has been retrieved.
/////////////////////////////////////////////////////////
typedef void (* chatGetChannelTopicCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
const gsi_char * topic,
void * param);
// Gets a channel's topic.
//////////////////////////
void chatGetChannelTopic(CHAT chat,
const gsi_char * channel,
chatGetChannelTopicCallback callback,
void * param,
CHATBool blocking);
// Sets a channel's mode.
/////////////////////////
void chatSetChannelMode(CHAT chat,
const gsi_char * channel,
CHATChannelMode * mode);
// Gets called when a channel's mode has been retrieved.
////////////////////////////////////////////////////////
typedef void (* chatGetChannelModeCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
CHATChannelMode * mode,
void * param);
// Gets a channel's mode.
/////////////////////////
void chatGetChannelMode(CHAT chat,
const gsi_char * channel,
chatGetChannelModeCallback callback,
void * param,
CHATBool blocking);
// Sets the password in a channel.
//////////////////////////////////
void chatSetChannelPassword(CHAT chat,
const gsi_char * channel,
CHATBool enable,
const gsi_char * password);
// Called when the channel's password has been retrieved.
/////////////////////////////////////////////////////////
typedef void (* chatGetChannelPasswordCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
CHATBool enabled,
const gsi_char * password,
void * param);
// Gets the password in a channel.
//////////////////////////////////
void chatGetChannelPassword(CHAT chat,
const gsi_char * channel,
chatGetChannelPasswordCallback callback,
void * param,
CHATBool blocking);
// Set the maximum number of users allowed in a channel.
////////////////////////////////////////////////////////
void chatSetChannelLimit(CHAT chat,
const gsi_char * channel,
int limit);
// Called with the list of bans in a channel.
/////////////////////////////////////////////
typedef void (* chatEnumChannelBansCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
int numBans,
const gsi_char ** bans,
void * param);
// Enumerate through the bans in a channel.
///////////////////////////////////////////
void chatEnumChannelBans(CHAT chat,
const gsi_char * channel,
chatEnumChannelBansCallback callback,
void * param,
CHATBool blocking);
// Adds a channel ban.
//////////////////////
void chatAddChannelBan(CHAT chat,
const gsi_char * channel,
const gsi_char * ban);
// Removes a ban string from a channel.
///////////////////////////////////////
void chatRemoveChannelBan(CHAT chat,
const gsi_char * channel,
const gsi_char * ban);
// Set the group this channel is a part of.
///////////////////////////////////////////
void chatSetChannelGroup(CHAT chat,
const gsi_char * channel,
const gsi_char * group);
// Get the number of users in the channel.
// Returns -1 if we are not in the channel.
///////////////////////////////////////////
int chatGetChannelNumUsers(CHAT chat,
const gsi_char * channel);
// Returns CHATTrue if we are in the channel
///////////////////////////////////////////
CHATBool chatInChannel(CHAT chat,
const gsi_char * channel);
/**********
** USERS **
**********/
// Called with the list of users in a channel.
//////////////////////////////////////////////
typedef void (* chatEnumUsersCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel, //PANTS|02.11.00|added paramater
int numUsers,
const gsi_char ** users,
int * modes,
void * param);
// Enumerate through the users in a channel.
////////////////////////////////////////////
void chatEnumUsers(CHAT chat,
const gsi_char * channel,
chatEnumUsersCallback callback,
void * param,
CHATBool blocking);
// Send a private message to a user.
////////////////////////////////////
void chatSendUserMessage(CHAT chat,
const gsi_char * user,
const gsi_char * message,
int type);
// Called with a user's info.
/////////////////////////////
typedef void (* chatGetUserInfoCallback)(CHAT chat,
CHATBool success,
const gsi_char * nick, //PANTS|02.14.2000|added nick and user
const gsi_char * user,
const gsi_char * name,
const gsi_char * address,
int numChannels,
const gsi_char ** channels,
void * param);
// Get a user's info.
/////////////////////
void chatGetUserInfo(CHAT chat,
const gsi_char * user,
chatGetUserInfoCallback callback,
void * param,
CHATBool blocking);
// Called with a user's basic info.
///////////////////////////////////
typedef void (* chatGetBasicUserInfoCallback)(CHAT chat,
CHATBool success,
const gsi_char * nick,
const gsi_char * user,
const gsi_char * address,
void * param);
// Get some basic info on the user.
// PANTS|12.08.2000
///////////////////////////////////
void chatGetBasicUserInfo(CHAT chat,
const gsi_char * user,
chatGetBasicUserInfoCallback callback,
void * param,
CHATBool blocking);
// Get basic info without waiting.
// Returns CHATFalse if the info isn't available.
/////////////////////////////////////////////////
CHATBool chatGetBasicUserInfoNoWait(CHAT chat,
const gsi_char * nick,
const gsi_char ** user,
const gsi_char ** address);
// Called with a user's basic info for everyone in a channel.
// Called with a NULL nick/user/address at the end.
/////////////////////////////////////////////////////////////
typedef void (* chatGetChannelBasicUserInfoCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
const gsi_char * nick,
const gsi_char * user,
const gsi_char * address,
void * param);
// Get basic info on all the users in a channel.
// PANTS|12.19.00
////////////////////////////////////////////////
void chatGetChannelBasicUserInfo(CHAT chat,
const gsi_char * channel,
chatGetChannelBasicUserInfoCallback callback,
void * param,
CHATBool blocking);
// Invite a user into a channel.
////////////////////////////////
void chatInviteUser(CHAT chat,
const gsi_char * channel,
const gsi_char * user);
// Kick a user from a channel.
//////////////////////////////
void chatKickUser(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
const gsi_char * reason);
// Ban a user from a channel.
/////////////////////////////
void chatBanUser(CHAT chat,
const gsi_char * channel,
const gsi_char * user);
// Sets a user's mode in a channel.
///////////////////////////////////
void chatSetUserMode(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int mode);
// Called with the user's mode.
///////////////////////////////
typedef void (* chatGetUserModeCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
const gsi_char * user,
int mode,
void * param);
// Gets a user's mode in a channel.
///////////////////////////////////
void chatGetUserMode(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
chatGetUserModeCallback callback,
void * param,
CHATBool blocking);
// Gets a user's mode in a channel.
///////////////////////////////////
CHATBool chatGetUserModeNoWait(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int * mode);
// Called in response to a request for the UDP relay for a channel
////////////////////////////////////////////////////////////////////
typedef void (* chatGetUdpRelayCallback)(CHAT chat,
const gsi_char * channel,
const gsi_char * udpIp,
unsigned short udpPort,
int udpKey,
void * param);
// Get the UDP relay address for a channel
///////////////////////////////////
void chatGetUdpRelay(CHAT chat,
const gsi_char * channel,
chatGetUdpRelayCallback callback,
void * param,
CHATBool blocking);
/*********
** KEYS **
*********/
// Sets global key/values for the local user.
// Set a value to NULL or "" to clear that key.
///////////////////////////////////////////////
void chatSetGlobalKeys(CHAT chat,
int num,
const gsi_char ** keys,
const gsi_char ** values);
// Called with a user's global key/values.
// If used for a set of users, will be
// called with user==NULL when done.
//////////////////////////////////////////
typedef void (* chatGetGlobalKeysCallback)(CHAT chat,
CHATBool success,
const gsi_char * user,
int num,
const gsi_char ** keys,
const gsi_char ** values,
void * param);
// Gets global key/values for a user or users.
// To get the global key/values for one user, pass in that
// user's nick as the target. To get the global key/values
// for every user in a channel, use the channel name as the target.
///////////////////////////////////////////////////////////////////
void chatGetGlobalKeys(CHAT chat,
const gsi_char * target,
int num,
const gsi_char ** keys,
chatGetGlobalKeysCallback callback,
void * param,
CHATBool blocking);
// Sets channel key/values.
// If user is NULL or "", the keys will be set on the channel.
// Otherwise, they will be set on the user,
// Only ops can set channel keys on other users.
// Set a value to NULL or "" to clear that key.
//////////////////////////////////////////////////////////////
void chatSetChannelKeys(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int num,
const gsi_char ** keys,
const gsi_char ** values);
// Called with a user's channel key/values, or a channel's key/values.
// If used for a set of users, will be called with user==NULL when done.
// If used for a channel, will be called once with user==NULL.
////////////////////////////////////////////////////////////////////////
typedef void (* chatGetChannelKeysCallback)(CHAT chat,
CHATBool success,
const gsi_char * channel,
const gsi_char * user,
int num,
const gsi_char ** keys,
const gsi_char ** values,
void * param);
// Gets channel key/values for a user or users, or for a channel.
// To get the channel key/values for every user in
// a channel, pass in "*" as the user. To get the keys for a channel,
// pass in NULL or "".
//////////////////////////////////////////////////////////////////////
void chatGetChannelKeys(CHAT chat,
const gsi_char * channel,
const gsi_char * user,
int num,
const gsi_char ** keys,
chatGetChannelKeysCallback callback,
void * param,
CHATBool blocking);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// This ASCII versions must be available even when GSI_UNICODE is defined
#ifdef GSI_UNICODE
CHATBool chatGetBasicUserInfoNoWaitA(CHAT chat,
const char * nick,
const char ** user,
const char ** address);
#endif
/*
void chatGetBasicUserInfoA(CHAT chat,
const char * user,
chatGetBasicUserInfoCallback callback,
void * param,
CHATBool blocking);
*/
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
} // extern "C"
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#endif // _CHAT_H_

View file

@ -0,0 +1,441 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATASCII_H_
#define _CHATASCII_H_
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "chat.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
// Connects you to a chat server and returns a CHAT object.
///////////////////////////////////////////////////////////
CHAT chatConnectA(const char * serverAddress,
int port,
const char * nick,
const char * user,
const char * name,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectSpecialA(const char * serverAddress,
int port,
const char * nick,
const char * name,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectSecureA(const char * serverAddress,
int port,
const char * nick,
const char * name,
const char * gamename,
const char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectLoginA(const char * serverAddress,
int port,
int namespaceID,
const char * email,
const char * profilenick,
const char * uniquenick,
const char * password,
const char * name,
const char * gamename,
const char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
CHAT chatConnectPreAuthA(const char * serverAddress,
int port,
const char * authtoken,
const char * partnerchallenge,
const char * name,
const char * gamename,
const char * secretKey,
chatGlobalCallbacks * callbacks,
chatNickErrorCallback nickErrorCallback,
chatFillInUserCallback fillInUserCallback,
chatConnectCallback connectCallback,
void * param,
CHATBool blocking);
// If the chatNickErrorCallback gets called, then this can be called
// with a new nick to retry. If this isn't called, the connection can be
// disconnected with chatDisconnect. If the new nick is successful, then
// the chatConnectCallback will get called. If there's another nick
// error, the chatNickErrorCallback will get called again.
/////////////////////////////////////////////////////////////////////////
void chatRetryWithNickA(CHAT chat,
const char * nick);
// Register a uniquenick.
// Should be called in response to the chatNickErrorCallback being called
// with a type of CHAT_UNIQUENICK_EXPIRED or CHAT_NO_UNIQUENICK.
// If the uniquenick cannot be registered, the chatNickErrorCallback will
// be called again with a type of CHAT_IN_USE or CHAT_INVALID.
/////////////////////////////////////////////////////////////////////////
void chatRegisterUniqueNickA(CHAT chat,
int namespaceID,
const char * uniquenick,
const char * cdkey);
// Sends raw data, without any interpretation.
//////////////////////////////////////////////
void chatSendRawA(CHAT chat,
const char * command);
// Change the local user's nick.
////////////////////////////////
void chatChangeNickA(CHAT chat,
const char * newNick,
chatChangeNickCallback callback,
void * param,
CHATBool blocking);
// Get our local nickname.
//////////////////////////
const char * chatGetNickA(CHAT chat);
// Copies the oldNick to the newNick, replacing any invalid characters with legal ones.
///////////////////////////////////////////////////////////////////////////////////////
void chatFixNickA(char * newNick,
const char * oldNick);
// Removes the namespace extension from a chat nick.
////////////////////////////////////////////////////
const char * chatTranslateNickA(char * nick,
const char * extension);
// Attempts to authenticates a CD key.
//////////////////////////////////////
void chatAuthenticateCDKeyA(CHAT chat,
const char * cdkey,
chatAuthenticateCDKeyCallback callback,
void * param,
CHATBool blocking);
/*************
** CHANNELS **
*************/
// Enumerates the channels available on a chat server.
//////////////////////////////////////////////////////
void chatEnumChannelsA(CHAT chat,
const char * filter,
chatEnumChannelsCallbackEach callbackEach,
chatEnumChannelsCallbackAll callbackAll,
void * param,
CHATBool blocking);
// Enters a channel.
////////////////////
void chatEnterChannelA(CHAT chat,
const char * channel,
const char * password,
chatChannelCallbacks * callbacks,
chatEnterChannelCallback callback,
void * param,
CHATBool blocking);
// Leaves a channel.
////////////////////
void chatLeaveChannelA(CHAT chat,
const char * channel,
const char * reason); // PANTS|03.13.01
// Sends a message to a channel.
////////////////////////////////
void chatSendChannelMessageA(CHAT chat,
const char * channel,
const char * message,
int type);
// Sets the topic in a channel.
///////////////////////////////
void chatSetChannelTopicA(CHAT chat,
const char * channel,
const char * topic);
// Gets a channel's topic.
//////////////////////////
void chatGetChannelTopicA(CHAT chat,
const char * channel,
chatGetChannelTopicCallback callback,
void * param,
CHATBool blocking);
// Sets a channel's mode.
/////////////////////////
void chatSetChannelModeA(CHAT chat,
const char * channel,
CHATChannelMode * mode);
// Gets a channel's mode.
/////////////////////////
void chatGetChannelModeA(CHAT chat,
const char * channel,
chatGetChannelModeCallback callback,
void * param,
CHATBool blocking);
// Sets the password in a channel.
//////////////////////////////////
void chatSetChannelPasswordA(CHAT chat,
const char * channel,
CHATBool enable,
const char * password);
// Gets the password in a channel.
//////////////////////////////////
void chatGetChannelPasswordA(CHAT chat,
const char * channel,
chatGetChannelPasswordCallback callback,
void * param,
CHATBool blocking);
// Set the maximum number of users allowed in a channel.
////////////////////////////////////////////////////////
void chatSetChannelLimitA(CHAT chat,
const char * channel,
int limit);
// Enumerate through the bans in a channel.
///////////////////////////////////////////
void chatEnumChannelBansA(CHAT chat,
const char * channel,
chatEnumChannelBansCallback callback,
void * param,
CHATBool blocking);
// Adds a channel ban.
//////////////////////
void chatAddChannelBanA(CHAT chat,
const char * channel,
const char * ban);
// Removes a ban string from a channel.
///////////////////////////////////////
void chatRemoveChannelBanA(CHAT chat,
const char * channel,
const char * ban);
// Set the group this channel is a part of.
///////////////////////////////////////////
void chatSetChannelGroupA(CHAT chat,
const char * channel,
const char * group);
// Get the number of users in the channel.
// Returns -1 if we are not in the channel.
///////////////////////////////////////////
int chatGetChannelNumUsersA(CHAT chat,
const char * channel);
// Returns CHATTrue if we are in the channel
///////////////////////////////////////////
CHATBool chatInChannelA(CHAT chat,
const char * channel);
/**********
** USERS **
**********/
// Enumerate through the users in a channel.
////////////////////////////////////////////
void chatEnumUsersA(CHAT chat,
const char * channel,
chatEnumUsersCallback callback,
void * param,
CHATBool blocking);
// Send a private message to a user.
////////////////////////////////////
void chatSendUserMessageA(CHAT chat,
const char * user,
const char * message,
int type);
// Get a user's info.
/////////////////////
void chatGetUserInfoA(CHAT chat,
const char * user,
chatGetUserInfoCallback callback,
void * param,
CHATBool blocking);
// Get some basic info on the user.
// PANTS|12.08.2000
///////////////////////////////////
void chatGetBasicUserInfoA(CHAT chat,
const char * user,
chatGetBasicUserInfoCallback callback,
void * param,
CHATBool blocking);
// Get basic info without waiting.
// Returns CHATFalse if the info isn't available.
/////////////////////////////////////////////////
CHATBool chatGetBasicUserInfoNoWaitA(CHAT chat,
const char * nick,
const char ** user,
const char ** address);
// Get basic info on all the users in a channel.
// PANTS|12.19.00
////////////////////////////////////////////////
void chatGetChannelBasicUserInfoA(CHAT chat,
const char * channel,
chatGetChannelBasicUserInfoCallback callback,
void * param,
CHATBool blocking);
// Invite a user into a channel.
////////////////////////////////
void chatInviteUserA(CHAT chat,
const char * channel,
const char * user);
// Kick a user from a channel.
//////////////////////////////
void chatKickUserA(CHAT chat,
const char * channel,
const char * user,
const char * reason);
// Ban a user from a channel.
/////////////////////////////
void chatBanUserA(CHAT chat,
const char * channel,
const char * user);
// Sets a user's mode in a channel.
///////////////////////////////////
void chatSetUserModeA(CHAT chat,
const char * channel,
const char * user,
int mode);
// Gets a user's mode in a channel.
///////////////////////////////////
void chatGetUserModeA(CHAT chat,
const char * channel,
const char * user,
chatGetUserModeCallback callback,
void * param,
CHATBool blocking);
// Gets a user's mode in a channel.
///////////////////////////////////
CHATBool chatGetUserModeNoWaitA(CHAT chat,
const char * channel,
const char * user,
int * mode);
// Get the UDP relay address for a channel
///////////////////////////////////
void chatGetUdpRelayA(CHAT chat,
const char * channel,
chatGetUdpRelayCallback callback,
void * param,
CHATBool blocking);
/*********
** KEYS **
*********/
// Sets global key/values for the local user.
// Set a value to NULL or "" to clear that key.
///////////////////////////////////////////////
void chatSetGlobalKeysA(CHAT chat,
int num,
const char ** keys,
const char ** values);
// Gets global key/values for a user or users.
// To get the global key/values for one user, pass in that
// user's nick as the target. To get the global key/values
// for every user in a channel, use the channel name as the target.
///////////////////////////////////////////////////////////////////
void chatGetGlobalKeysA(CHAT chat,
const char * target,
int num,
const char ** keys,
chatGetGlobalKeysCallback callback,
void * param,
CHATBool blocking);
// Sets channel key/values.
// If user is NULL or "", the keys will be set on the channel.
// Otherwise, they will be set on the user,
// Only ops can set channel keys on other users.
// Set a value to NULL or "" to clear that key.
//////////////////////////////////////////////////////////////
void chatSetChannelKeysA(CHAT chat,
const char * channel,
const char * user,
int num,
const char ** keys,
const char ** values);
// Gets channel key/values for a user or users, or for a channel.
// To get the channel key/values for every user in
// a channel, pass in "*" as the user. To get the keys for a channel,
// pass in NULL or "".
//////////////////////////////////////////////////////////////////////
void chatGetChannelKeysA(CHAT chat,
const char * channel,
const char * user,
int num,
const char ** keys,
chatGetChannelKeysCallback callback,
void * param,
CHATBool blocking);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// This ASCII versions must be available even when GSI_UNICODE is defined
CHATBool chatGetBasicUserInfoNoWaitA(CHAT chat,
const char * nick,
const char ** user,
const char ** address);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
} // extern "C"
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#endif // _CHATASCII_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,329 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATCALLBACKS_H_
#define _CHATCALLBACKS_H_
/*************
** INCLUDES **
*************/
#include "chat.h"
#include "chatMain.h"
/************
** DEFINES **
************/
enum
{
CALLBACK_RAW,
CALLBACK_DISCONNECTED,
CALLBACK_PRIVATE_MESSAGE,
CALLBACK_INVITED,
CALLBACK_CHANNEL_MESSAGE,
CALLBACK_KICKED,
CALLBACK_USER_JOINED,
CALLBACK_USER_PARTED,
CALLBACK_USER_CHANGED_NICK,
CALLBACK_TOPIC_CHANGED,
CALLBACK_CHANNEL_MODE_CHANGED,
CALLBACK_USER_MODE_CHANGED,
CALLBACK_USER_LIST_UPDATED,
CALLBACK_ENUM_CHANNELS_EACH,
CALLBACK_ENUM_CHANNELS_ALL,
CALLBACK_ENTER_CHANNEL,
CALLBACK_GET_CHANNEL_TOPIC,
CALLBACK_GET_CHANNEL_MODE,
CALLBACK_GET_CHANNEL_PASSWORD,
CALLBACK_ENUM_USERS,
CALLBACK_GET_USER_INFO,
CALLBACK_GET_BASIC_USER_INFO,
CALLBACK_GET_CHANNEL_BASIC_USER_INFO,
CALLBACK_GET_USER_MODE,
CALLBACK_ENUM_CHANNEL_BANS,
CALLBACK_NICK_ERROR,
CALLBACK_CHANGE_NICK,
CALLBACK_NEW_USER_LIST,
CALLBACK_BROADCAST_KEY_CHANGED,
CALLBACK_GET_GLOBAL_KEYS,
CALLBACK_GET_CHANNEL_KEYS,
CALLBACK_AUTHENTICATE_CDKEY,
CALLBACK_GET_UDPRELAY,
CALLBACK_NUM
};
/**********
** TYPES **
**********/
typedef struct ciCallbackRawParams
{
char * raw;
} ciCallbackRawParams;
typedef struct ciCallbackDisconnectedParams
{
char * reason;
} ciCallbackDisconnectedParams;
typedef struct ciCallbackPrivateMessageParams
{
char * user;
char * message;
int type;
} ciCallbackPrivateMessageParams;
typedef struct ciCallbackInvitedParams
{
char * channel;
char * user;
} ciCallbackInvitedParams;
typedef struct ciCallbackChannelMessageParams
{
char * channel;
char * user;
char * message;
int type;
} ciCallbackChannelMessageParams;
typedef struct ciCallbackKickedParams
{
char * channel;
char * user;
char * reason;
} ciCallbackKickedParams;
typedef struct ciCallbackUserJoinedParams
{
char * channel;
char * user;
int mode;
} ciCallbackUserJoinedParams;
typedef struct ciCallbackUserPartedParams
{
char * channel;
char * user;
int why;
char * reason;
char * kicker;
} ciCallbackUserPartedParams;
typedef struct ciCallbackUserChangedNickParams
{
char * channel;
char * oldNick;
char * newNick;
} ciCallbackUserChangedNickParams;
typedef struct ciCallbackTopicChangedParams
{
char * channel;
char * topic;
} ciCallbackTopicChangedParams;
typedef struct ciCallbackChannelModeChangedParams
{
char * channel;
CHATChannelMode * mode;
} ciCallbackChannelModeChangedParams;
typedef struct ciCallbackUserModeChangedParams
{
char * channel;
char * user;
int mode;
} ciCallbackUserModeChangedParams;
typedef struct ciCallbackUserListUpdatedParams
{
char * channel;
} ciCallbackUserListUpdatedParams;
typedef struct ciCallbackConnectParams
{
CHATBool success;
} ciCallbackConnectParams;
typedef struct ciCallbackEnumChannelsEachParams
{
CHATBool success;
int index;
char * channel;
char * topic;
int numUsers;
void * param;
} ciCallbackEnumChannelsEachParams;
typedef struct ciCallbackEnumChannelsAllParams
{
CHATBool success;
int numChannels;
char ** channels;
char ** topics;
int * numUsers;
} ciCallbackEnumChannelsAllParams;
typedef struct ciCallbackEnterChannelParams
{
CHATBool success;
CHATEnterResult result;
char * channel;
} ciCallbackEnterChannelParams;
typedef struct ciCallbackGetChannelTopicParams
{
CHATBool success;
char * channel;
char * topic;
} ciCallbackGetChannelTopicParams;
typedef struct ciCallbackGetChannelModeParams
{
CHATBool success;
char * channel;
CHATChannelMode * mode;
} ciCallbackGetChannelModeParams;
typedef struct ciCallbackGetChannelPasswordParams
{
CHATBool success;
char * channel;
CHATBool enabled;
char * password;
} ciCallbackGetChannelPasswordParams;
typedef struct ciCallbackEnumUsersParams
{
CHATBool success;
char * channel;
int numUsers;
char ** users;
int * modes;
} ciCallbackEnumUsersParams;
typedef struct ciCallbackGetUserInfoParams
{
CHATBool success;
char * nick;
char * user;
char * name;
char * address;
int numChannels;
char ** channels;
} ciCallbackGetUserInfoParams;
typedef struct ciCallbackGetBasicUserInfoParams
{
CHATBool success;
char * nick;
char * user;
char * address;
} ciCallbackGetBasicUserInfoParams;
typedef struct ciCallbackGetChannelBasicUserInfoParams
{
CHATBool success;
char * channel;
char * nick;
char * user;
char * address;
} ciCallbackGetChannelBasicUserInfoParams;
typedef struct ciCallbackGetUserModeParams
{
CHATBool success;
char * channel;
char * user;
int mode;
} ciCallbackGetUserModeParams;
typedef struct ciCallbackEnumChannelBansParams
{
CHATBool success;
char * channel;
int numBans;
char ** bans;
} ciCallbackEnumChannelBansParams;
typedef struct ciCallbackNickErrorParams
{
int type;
char * nick;
int numSuggestedNicks;
char ** suggestedNicks;
} ciCallbackNickErrorParams;
typedef struct ciCallbackChangeNickParams
{
CHATBool success;
char * oldNick;
char * newNick;
} ciCallbackChangeNickParams;
typedef struct ciCallbackNewUserListParams
{
char * channel;
int numUsers;
char ** users;
int * modes;
} ciCallbackNewUserListParams;
typedef struct ciCallbackBroadcastKeyChangedParams
{
char * channel;
char * user;
char * key;
char * value;
} ciCallbackBroadcastKeyChangedParams;
typedef struct ciCallbackGetGlobalKeysParams
{
CHATBool success;
char * user;
int num;
char ** keys;
char ** values;
} ciCallbackGetGlobalKeysParams;
typedef struct ciCallbackGetChannelKeysParams
{
CHATBool success;
char * channel;
char * user;
int num;
char ** keys;
char ** values;
} ciCallbackGetChannelKeysParams;
typedef struct ciCallbackAuthenticateCDKeyParams
{
int result;
char * message;
} ciCallbackAuthenticateCDKeyParams;
typedef struct ciCallbackGetUdpRelayParams
{
char * channel;
char * udpIp;
unsigned short udpPort;
int udpKey;
} ciCallbackGetUdpRelayParams;
/**************
** FUNCTIONS **
**************/
CHATBool ciInitCallbacks(ciConnection * connection);
void ciCleanupCallbacks(CHAT chat);
#define ciAddCallback(chat, type, callback, callbackParams, param, ID, channel) ciAddCallback_(chat, type, callback, callbackParams, param, ID, channel, sizeof(*callbackParams))
CHATBool ciAddCallback_(CHAT chat, int type, void * callback, void * callbackParams, void * param, int ID, const char * channel, size_t callbackParamsSize);
void ciCallCallbacks(CHAT chat, int ID);
CHATBool ciCheckCallbacksForID(CHAT chat, int ID);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATCHANNEL_H_
#define _CHATCHANNEL_H_
/*************
** INCLUDES **
*************/
#include "chat.h"
/************
** DEFINES **
************/
/**************
** FUNCTIONS **
**************/
CHATBool ciInitChannels(ciConnection * connection);
void ciCleanupChannels(CHAT chat);
void ciChannelEntering(CHAT chat, const char * channel);
CHATBool ciIsEnteringChannel(CHAT chat, const char * channel);
void ciChannelEntered(CHAT chat, const char * channel, chatChannelCallbacks * callbacks);
void ciChannelLeft(CHAT chat, const char * channel);
chatChannelCallbacks * ciGetChannelCallbacks(CHAT chat, const char * channel);
typedef void (* ciChannelListUsersCallback)(CHAT chat, const char * channel, int numUsers, const char ** users, int * modes, void * param);
void ciChannelListUsers(CHAT chat, const char * channel, ciChannelListUsersCallback callback, void * param);
CHATBool ciInChannel(CHAT chat, const char * channel);
CHATBool ciGetChannelMode(CHAT chat, const char * channel, CHATChannelMode * mode);
void ciSetChannelMode(CHAT chat, const char * channel, CHATChannelMode * mode);
void ciSetChannelPassword(CHAT chat, const char * channel, const char * password);
const char * ciGetChannelPassword(CHAT chat, const char * channel);
void ciJoinCallbackCalled(CHAT chat, const char * channel);
CHATBool ciWasJoinCallbackCalled(CHAT chat, const char * channel);
void ciSetChannelTopic(CHAT chat, const char * channel, const char * topic);
const char * ciGetChannelTopic(CHAT chat, const char * channel);
int ciGetChannelNumUsers(CHAT chat, const char * channel);
void ciUserEnteredChannel(CHAT chat, const char * nick, const char * channel, int mode, const char * user, const char * address);
void ciUserLeftChannel(CHAT chat, const char * user, const char * channel);
void ciUserChangedNick(CHAT chat, const char * oldNick, const char * newNick);
void ciUserChangedMode(CHAT chat, const char * user, const char * channel, int mode, CHATBool enabled);
typedef void (* ciUserEnumChannelsCallback)(CHAT chat, const char * user, const char * channel, void * param);
void ciUserEnumChannels(CHAT chat, const char * user, ciUserEnumChannelsCallback callback, void * param);
CHATBool ciUserInChannel(CHAT chat, const char * channel, const char * user);
int ciGetUserMode(CHAT chat, const char * channel, const char * user);
void ciEnumJoinedChannels(CHAT chat, chatEnumJoinedChannelsCallback callback, void * param);
void ciSetUserBasicInfo(CHAT chat, const char * nick, const char * user, const char * address);
void ciClearAllUsers(CHAT chat);
// Because these return pointers to SDK memory, we must have a widestring version
// so we can return a pointer to widestring data
// DO NOT CHANGE nick to an unsigned short*, nicks are internally store as char*
CHATBool ciGetUserBasicInfoA(CHAT chat, const char * nick, const char ** user, const char ** address);
CHATBool ciGetUserBasicInfoW(CHAT chat, const char * nick, const unsigned short ** user, const unsigned short ** address);
#endif

View file

@ -0,0 +1,65 @@
#include "chatCrypt.h"
#define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
void gs_prepare_key(const unsigned char *key_data_ptr, int key_data_len, gs_crypt_key *key)
{
unsigned char t;
unsigned char index1;
unsigned char index2;
unsigned char* state;
int counter;
state = &key->state[0];
for(counter = 0; counter < 256; counter++)
state[255 - counter] = (unsigned char)counter; //crt - we fill reverse of normal
key->x = 0;
key->y = 0;
index1 = 0;
index2 = 0;
for(counter = 0; counter < 256; counter++)
{
index2 = (unsigned char)((key_data_ptr[index1] + state[counter] + index2) % 256);
swap_byte(&state[counter], &state[index2]);
index1 = (unsigned char)((index1 + 1) % key_data_len);
}
}
void gs_crypt(unsigned char *buffer_ptr, int buffer_len, gs_crypt_key *key)
{
unsigned char t;
unsigned char x;
unsigned char y;
unsigned char* state;
unsigned char xorIndex;
int counter;
x = key->x;
y = key->y;
state = &key->state[0];
for(counter = 0; counter < buffer_len; counter++)
{
x = (unsigned char)((x + 1) % 256);
y = (unsigned char)((state[x] + y) % 256);
swap_byte(&state[x], &state[y]);
xorIndex = (unsigned char)((state[x] + state[y]) % 256);
buffer_ptr[counter] ^= state[xorIndex];
}
key->x = x;
key->y = y;
}
void gs_xcode_buf(char *buf, int len, char *enckey)
{
int i;
char *pos = enckey;
for (i = 0 ; i < len ; i++)
{
buf[i] ^= *pos++;
if (*pos == 0)
pos = enckey;
}
}

View file

@ -0,0 +1,24 @@
#ifndef _CHATCRYPT_H_
#define _CHATCRYPT_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _gs_crypt_key
{
unsigned char state[256];
unsigned char x;
unsigned char y;
} gs_crypt_key;
void gs_prepare_key(const unsigned char *key_data_ptr, int key_data_len, gs_crypt_key *key);
void gs_crypt(unsigned char *buffer_ptr, int buffer_len, gs_crypt_key *key);
void gs_xcode_buf(char *buf, int len, char *enckey);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATHANDLERS_H_
#define _CHATHANDLERS_H_
/*************
** INCLUDES **
*************/
#include "chat.h"
#include "chatSocket.h"
/**********
** TYPES **
**********/
typedef struct ciServerMessageType
{
char * command;
void (* handler)(CHAT chat, const ciServerMessage * message);
} ciServerMessageType;
typedef char ** ciCommands;
typedef struct ciServerMessageFilter
{
int type;
gsi_time timeout;
char * name;
char * name2;
void * callback;
void * callback2;
void * param;
void * data;
int ID;
struct ciServerMessageFilter * pnext;
} ciServerMessageFilter;
/************
** GLOBALS **
************/
extern ciServerMessageType serverMessageTypes[];
extern int numServerMessageTypes;
/**************
** FUNCTIONS **
**************/
void ciFilterThink(CHAT chat);
void ciCleanupFilters(CHAT chat);
int ciAddLISTFilter(CHAT chat, chatEnumChannelsCallbackEach callbackEach, chatEnumChannelsCallbackAll callbackAll, void * param);
int ciAddJOINFilter(CHAT chat, const char * channel, chatEnterChannelCallback callback, void * param, chatChannelCallbacks * callbacks, const char * password);
int ciAddTOPICFilter(CHAT chat, const char * channel, chatGetChannelTopicCallback callback, void * param);
int ciAddNAMESFilter(CHAT chat, const char * channel, chatEnumUsersCallback callback, void * param);
int ciAddWHOISFilter(CHAT chat, const char * user, chatGetUserInfoCallback callback, void * param);
int ciAddWHOFilter(CHAT chat, const char * user, chatGetBasicUserInfoCallback callback, void * param);
int ciAddCWHOFilter(CHAT chat, const char * channel, chatGetChannelBasicUserInfoCallback callback, void * param);
int ciAddCMODEFilter(CHAT chat, const char * channel, chatGetChannelModeCallback callback, void * param);
int ciAddUMODEFilter(CHAT chat, const char * user, const char * channel, chatGetUserModeCallback callback, void * param);
int ciAddBANFilter(CHAT chat, const char * user, const char * channel);
int ciAddGETBANFilter(CHAT chat, const char * channel, chatEnumChannelBansCallback callback, void * param);
int ciAddNICKFilter(CHAT chat, const char * oldNick, const char * newNick, chatChangeNickCallback callback, void * param);
int ciAddUNQUIETFilter(CHAT chat, const char * channel);
int ciAddGETKEYFilter(CHAT chat, const char * cookie, int num, const char ** keys, const char * channel, chatGetGlobalKeysCallback callback, void * param);
int ciAddGETCKEYFilter(CHAT chat, const char * cookie, int num, const char ** keys, CHATBool channel, CHATBool getBroadcastKeys, chatGetChannelKeysCallback callback, void * param);
int ciAddGETCHANKEYFilter(CHAT chat, const char * cookie, int num, const char ** keys, CHATBool getBroadcastKeys, chatGetChannelKeysCallback callback, void * param);
int ciAddCDKEYFilter(CHAT chat, chatAuthenticateCDKeyCallback callback, void * param);
int ciAddGETUDPRELAYFilter(CHAT chat, const char * channel, chatGetUdpRelayCallback callback, void * param);
int ciGetNextID(CHAT chat);
CHATBool ciCheckFiltersForID(CHAT chat, int ID);
#endif

3075
code/gamespy/Chat/chatMain.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATMAIN_H_
#define _CHATMAIN_H_
/*************
** INCLUDES **
*************/
#include "chat.h"
#include "chatSocket.h"
#include "chatHandlers.h"
#include "../hashtable.h"
#include "../darray.h"
#include "../md5.h"
/************
** DEFINES **
************/
#define MAX_NICK 64
#define MAX_CHAT_NICK 21
#define MAX_NAME 128
#define MAX_USER 128
#define MAX_SERVER 128
#define MAX_PARAM 512
#define MAX_SECRETKEY 128
#define MAX_EMAIL 64
#define MAX_PROFILENICK 32
#define MAX_UNIQUENICK 64
#define MAX_PASSWORD 32
#define MAX_AUTHTOKEN 256
#define MAX_PARTNERCHALLENGE 256
#define CONNECTION ciConnection * connection;\
assert(chat != NULL);\
connection = (ciConnection *)chat;\
GSI_UNUSED(connection);
#define CONNECTED if(!connection || !connection->connected) return; //ERRCON
#if 0
ciConnection * connection; // for visual assist
#endif
#define VALID_NICK_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"#$%&'()*+,-./:;<=>?@[]^_`{|}~"
#define CI_DEFAULT_SERVER_ADDRESS "peerchat." GSI_DOMAIN_NAME
#define CI_DEFUILT_SERVER_PORT 6667
/**********
** TYPES **
**********/
typedef enum
{
CINoLogin,
CIUniqueNickLogin,
CIProfileLogin,
CIPreAuthLogin
} CILoginType;
typedef struct ciConnection
{
CHATBool connected;
CHATBool connecting;
CHATBool disconnected;
chatNickErrorCallback nickErrorCallback;
chatFillInUserCallback fillInUserCallback;
chatConnectCallback connectCallback;
void * connectParam;
ciSocket chatSocket;
char nick[MAX_NICK];
char name[MAX_NAME];
char user[MAX_USER];
int namespaceID;
char email[MAX_EMAIL];
char profilenick[MAX_PROFILENICK];
char uniquenick[MAX_UNIQUENICK];
char password[MAX_PASSWORD];
char authtoken[MAX_AUTHTOKEN];
char partnerchallenge[MAX_PARTNERCHALLENGE];
#ifdef GSI_UNICODE
unsigned short nickW[MAX_NICK];
unsigned short userW[MAX_NAME];
#endif
unsigned int IP;
char server[MAX_SERVER];
int port;
chatGlobalCallbacks globalCallbacks;
HashTable channelTable;
DArray enteringChannelList;
ciServerMessageFilter * filterList;
ciServerMessageFilter * lastFilter;
int nextID;
DArray callbackList;
CHATBool quiet;
char secretKey[MAX_SECRETKEY];
CILoginType loginType;
int userID;
int profileID;
} ciConnection;
void ciSendNickAndUser(CHAT chat);
void ciSendNick(CHAT chat);
void ciSendUser(CHAT chat);
void ciSendLogin(CHAT chat);
void ciHandleDisconnect(CHAT chat, const char * reason);
int ciNickIsValid(const char* nick);
void ciNickError(CHAT chat, int type, const char * nick, int numSuggestedNicks, char ** suggestedNicks);
#define strzcpy(dest, src, len) { strncpy(dest, src, (len)); (dest)[(len) - 1] = '\0'; }
#define wcszcpy(dest, src, len) { wcsncpy(dest, src, (len)); (dest)[(len) - 1] = 0; }
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
/*
GameSpy Chat SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
*/
#ifndef _CHATSOCKET_H_
#define _CHATSOCKET_H_
/*************
** INCLUDES **
*************/
#include "chat.h"
#include "chatCrypt.h"
/**********
** ENUMS **
**********/
typedef enum ciConnectState
{
ciNotConnected,
ciConnected,
ciDisconnected
} ciConnectState;
/**********
** TYPES **
**********/
typedef struct ciBuffer
{
char * buffer;
int length;
int size;
} ciBuffer;
typedef struct ciServerMessage
{
char * message;
char * server;
char * nick;
char * user;
char * host;
char * command;
char * middle;
char * param;
char ** params;
int numParams;
} ciServerMessage;
typedef struct ciSocket
{
SOCKET sock;
ciConnectState connectState;
char serverAddress[256];
ciBuffer inputQueue;
ciBuffer outputQueue;
CHATBool secure;
gs_crypt_key inKey;
gs_crypt_key outKey;
ciServerMessage lastMessage;
#ifdef IRC_LOG
char filename[FILENAME_MAX];
#endif
} ciSocket;
/**************
** FUNCTIONS **
**************/
CHATBool ciSocketInit(ciSocket * sock, const char * nick);
CHATBool ciSocketConnect(ciSocket * sock,
const char * serverAddress,
int port);
void ciSocketDisconnect(ciSocket * sock);
void ciSocketThink(ciSocket * sock);
CHATBool ciSocketSend(ciSocket * sock,
const char * buffer);
CHATBool ciSocketSendf(ciSocket * sock,
const char * format,
...);
ciServerMessage * ciSocketRecv(ciSocket * sock);
#endif

View file

@ -0,0 +1,552 @@
// GameSpy Chat SDK C Test App
// Dan "Mr. Pants" Schoenblum
// dan@gamespy.com
/*************
** INCLUDES **
*************/
#include "../chat.h"
#include "../../common/gsStringUtil.h"
#ifdef UNDER_CE
void RetailOutputA(CHAR *tszErr, ...);
#define printf RetailOutputA
#elif defined(_NITRO)
#include "../../common/nitro/screen.h"
#define printf Printf
#define vprintf VPrintf
#endif
#define MAX_MESSAGE_SIZE 200
#define CHAT_NICK_SIZE 128
/************
** GLOBALS **
************/
// mj Nov 7th, zero out to known state globals.
int port = 0;
CHAT chat = {0};
gsi_char serverAddress[128] = {0};
gsi_char chatNick[128] = {0};
gsi_char chatUser[128] = {0};
gsi_char chatName[128] = {0};
gsi_char chatChannel[128] = {0};
gsi_char gamename[128] = {0};
gsi_char secretKey[128] = {0};
CHATBool quit = CHATFalse;
#ifdef __MWERKS__ // CodeWarrior will warn if functions not prototyped
/***************
** PROTOTYPES **
***************/
int test_main(int argc, char **argv);
#endif
/**************
** FUNCTIONS **
**************/
#ifdef GSI_UNICODE
#define _tstrcasecmp WideCaseCompare
#define _tstrncasecmp WideCaseNCompare
#else
#define _tstrcasecmp strcasecmp
#define _tstrncasecmp strncasecmp
#endif
// Simulate case insensitive compare functions
#if defined(GSI_UNICODE)
int WideCaseCompare(const unsigned short* s1, const unsigned short* s2);
int WideCaseNCompare(const unsigned short* s1, const unsigned short* s2, size_t count);
int WideCaseCompare(const unsigned short* s1, const unsigned short* s2)
{
char s1_A[512];
char s2_A[512];
UCS2ToAsciiString(s1, s1_A);
UCS2ToAsciiString(s2, s2_A);
return strcasecmp(s1_A, s2_A);
}
int WideCaseNCompare(const unsigned short* s1, const unsigned short* s2, size_t count)
{
char s1_A[512];
char s2_A[512];
unsigned short temp[512];
// null terminate
temp[count+1] = 0;
// Copy to temp buffer, then convert to ascii
memcpy(temp, s1, count * sizeof(unsigned short));
UCS2ToAsciiString(temp, s1_A);
memcpy(temp, s2, count * sizeof(unsigned short));
UCS2ToAsciiString(temp, s2_A);
return strncasecmp(s1_A, s2_A, count);
}
#endif
static void Raw(CHAT chat, const gsi_char * raw, void * param)
{
_tprintf(_T("RAW: %s\n"), raw);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void Disconnected(CHAT chat, const gsi_char * reason, void * param)
{
_tprintf(_T("Disconnected: %s\n"), reason);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void ChangedNickCallback(CHAT chat, CHATBool success, const gsi_char * oldNick, const gsi_char * newNick, void * param)
{
if(success)
{
_tprintf(_T("Successfully changed"));
_tcscpy(chatNick, newNick);
}
else
_tprintf(_T("Failed to change"));
_tprintf(_T(" nick from %s to %s\n"), oldNick, newNick);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void PrivateMessage(CHAT chat, const gsi_char * user, const gsi_char * message, int type, void * param)
{
_tprintf(_T("Private message from %s: %s\n"), user, message);
// Nick change?
///////////////
if(_tstrncasecmp(_T("nick"), message, 4) == 0)
{
chatChangeNick(chat, &message[5], ChangedNickCallback, NULL, CHATFalse);
}
GSI_UNUSED(type);
GSI_UNUSED(param);
}
static void Invited(CHAT chat, const gsi_char * channel, const gsi_char * user, void * param)
{
_tprintf(_T("Invited by %s to %s\n"), user, channel);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void ChannelMessage(CHAT chat, const gsi_char * channel, const gsi_char * user, const gsi_char * message, int type, void * param)
{
gsi_char buffer[MAX_MESSAGE_SIZE];
_tprintf(_T("%s, in %s, said \"%s\"\n"), user, channel, message);
// Is this from us?
///////////////////
if(_tstrcasecmp(user, chatNick) == 0)
return;
// Is it a command?
///////////////////
if(message[0] == '!')
{
message++;
if(!_tstrcasecmp(message, _T("quit")) || !_tstrcasecmp(message, _T("exit")))
quit = CHATTrue;
return;
}
_tsnprintf(buffer, MAX_MESSAGE_SIZE, _T("%s: I agree"), user);
buffer[MAX_MESSAGE_SIZE - 1] = '\0';
chatSendChannelMessage(chat, channel, buffer, CHAT_MESSAGE);
GSI_UNUSED(type);
GSI_UNUSED(param);
}
static void Kicked(CHAT chat, const gsi_char * channel, const gsi_char * user, const gsi_char * reason, void * param)
{
_tprintf(_T("Kicked from %s by %s: %s\n"), channel, user, reason);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void UserJoined(CHAT chat, const gsi_char * channel, const gsi_char * user, int mode, void * param)
{
_tprintf(_T("%s joined %s"), user, channel);
GSI_UNUSED(chat);
GSI_UNUSED(param);
GSI_UNUSED(mode);
}
static void UserParted(CHAT chat, const gsi_char * channel, const gsi_char * user, int why, const gsi_char * reason, const gsi_char * kicker, void * param)
{
if(why == CHAT_LEFT)
_tprintf(_T("%s left %s\n"), user, channel);
else if(why == CHAT_QUIT)
_tprintf(_T("%s quit: %s\n"), user, reason);
else if(why == CHAT_KICKED)
_tprintf(_T("%s was kicked from %s by %s: %s"), user, channel, kicker, reason);
else if(why == CHAT_KILLED)
_tprintf(_T("%s was killed: %s\n"), user, reason);
else
_tprintf(_T("UserParted() called with unknown part-type\n"));
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void UserChangedNick(CHAT chat, const gsi_char * channel, const gsi_char * oldNick, const gsi_char * newNick, void * param)
{
_tprintf(_T("%s changed nicks to %s\n"), oldNick, newNick);
GSI_UNUSED(chat);
GSI_UNUSED(channel);
GSI_UNUSED(param);
}
static void UserModeChanged(CHAT chat, const gsi_char * channel, const gsi_char * user, int mode, void * param)
{
_tprintf(_T("%s's new mode in %s is "), user, channel);;
if(mode == CHAT_VOICE)
_tprintf(_T("voice\n"));
else if(mode == CHAT_OP)
_tprintf(_T("ops\n"));
else if(mode == (CHAT_VOICE | CHAT_OP))
_tprintf(_T("voice+ops\n"));
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void TopicChanged(CHAT chat, const gsi_char * channel, const gsi_char * topic, void * param)
{
_tprintf(_T("The topic in %s changed to %s\n"), channel, topic);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void ChannelModeChanged(CHAT chat, const gsi_char * channel, CHATChannelMode * mode, void * param)
{
_tprintf(_T("The mode in %s has changed:\n"), channel);
_tprintf(_T(" InviteOnly: %d\n"), mode->InviteOnly);
_tprintf(_T(" Private: %d\n"), mode->Private);
_tprintf(_T(" Secret: %d\n"), mode->Secret);
_tprintf(_T(" Moderated: %d\n"), mode->Moderated);
_tprintf(_T(" NoExternalMessages: %d\n"), mode->NoExternalMessages);
_tprintf(_T(" OnlyOpsChangeTopic: %d\n"), mode->OnlyOpsChangeTopic);
_tprintf(_T(" Limit: "));
if(mode->Limit == 0)
_tprintf(_T("N/A\n"));
else
_tprintf(_T("%d\n"), mode->Limit);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
static void UserListUpdated(CHAT chat, const gsi_char * channel, void * param)
{
_tprintf(_T("User list updated\n"));
GSI_UNUSED(chat);
GSI_UNUSED(channel);
GSI_UNUSED(param);
}
static void ConnectCallback(CHAT chat, CHATBool success, int failureReason, void * param)
{
if (success == CHATFalse)
_tprintf(_T("Failed to connect (%d)\n"), failureReason);
else
_tprintf(_T("Connected\n"));
GSI_UNUSED(chat);
GSI_UNUSED(success);
GSI_UNUSED(param);
}
static void FillInUserCallback(CHAT chat, unsigned int IP, gsi_char user[128], void * param)
{
_tcscpy(user, chatUser);
GSI_UNUSED(chat);
GSI_UNUSED(IP);
GSI_UNUSED(param);
}
static void NickErrorCallback(CHAT chat, int type, const gsi_char * nick, int numSuggestedNicks, const gsi_char ** suggestedNicks, void * param)
{
if(type == CHAT_IN_USE)
{
_tprintf(_T("The nick %s is already being used.\n"), nick);
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
chatNick[CHAT_NICK_SIZE - 1] = '\0';
chatRetryWithNick(chat, chatNick);
}
else if(type == CHAT_INVALID)
{
_tprintf(_T("The nick %s is invalid!\n"), nick);
// chatDisconnect(chat); THIS CRASHES
// 10-14-2004: Added By Saad Nader
// this is necessary as the function will fail if a new nick is not retries.
////////////////////////////////////////////////////////////////////////////
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
chatNick[CHAT_NICK_SIZE - 1] = '\0';
chatRetryWithNick(chat, chatNick);
}
else if((type == CHAT_UNIQUENICK_EXPIRED) || (type == CHAT_NO_UNIQUENICK))
{
_tprintf(_T("This account has no uniquenick or an expired uniquenick!\n"));
chatRegisterUniqueNick(chat, 2, _T("MrPants"), _T(""));
}
else if(type == CHAT_INVALID_UNIQUENICK)
{
int i;
_tprintf(_T("The uniquenick %s is invalid or in use\n"), nick);
_tprintf(_T("There are %d suggested nicks:\n"), numSuggestedNicks);
for(i = 0 ; i < numSuggestedNicks ; i++)
_tprintf(_T(" %s\n"), suggestedNicks[i]);
}
// 10-14-2004: Added By Saad Nader
// added for the addition of a new error code.
////////////////////////////////////////////////////////////////////////////
else if(type == CHAT_NICK_TOO_LONG)
{
_tprintf(_T("The nick %s is too long.\n"), nick);
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
chatNick[CHAT_NICK_SIZE - 1] = '\0';
chatRetryWithNick(chat, chatNick);
}
GSI_UNUSED(param);
}
CHATBool enterChannelSuccess;
static void EnterChannelCallback(CHAT chat, CHATBool success, CHATEnterResult result, const gsi_char * channel, void * param)
{
enterChannelSuccess = success;
GSI_UNUSED(chat);
GSI_UNUSED(result);
GSI_UNUSED(channel);
GSI_UNUSED(param);
}
static void GetUserInfoCallback(CHAT chat, CHATBool success, const gsi_char * nick, const gsi_char * user, const gsi_char * name, const gsi_char * address, int numChannels, const gsi_char ** channels, void * param)
{
int i;
if(!success)
{
_tprintf(_T("GetUserInfo failed\n"));
return;
}
_tprintf(_T("%s's Info:\n"), nick);
_tprintf(_T(" User: %s\n"), user);
_tprintf(_T(" Name: %s\n"), name);
_tprintf(_T(" Address: %s\n"), address);
_tprintf(_T(" Channels (%d):\n"), numChannels);
for(i = 0 ; i < numChannels ; i++)
_tprintf(_T(" %s\n"), channels[i]);
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
/*
static void EnumChannelsAllCallback(CHAT chat, CHATBool success, int numChannels, const gsi_char ** channel, const gsi_char ** topic, int* numUsers, void * param)
{
GSI_UNUSED(chat);
GSI_UNUSED(success);
GSI_UNUSED(numChannels);
GSI_UNUSED(channel);
GSI_UNUSED(topic);
GSI_UNUSED(numUsers);
GSI_UNUSED(param);
}
*/
static void EnumUsersCallback(CHAT chat, CHATBool success, const gsi_char * channel, int numUsers, const gsi_char ** users, int * modes, void * param)
{
int i;
if(!success)
{
_tprintf(_T("EnumUsers failed\n"));
return;
}
for(i = 0 ; i < numUsers ; i++)
chatGetUserInfo(chat, users[i], GetUserInfoCallback, NULL, CHATFalse);
GSI_UNUSED(channel);
GSI_UNUSED(modes);
GSI_UNUSED(param);
}
int test_main(int argc, char **argv)
{
int i;
chatGlobalCallbacks globalCallbacks;
chatChannelCallbacks channelCallbacks;
unsigned long stopTime;
// Set default options.
///////////////////////
// SDK takes care of default server address and port now
//_tcscpy(serverAddress, _T("peerchat." GSI_DOMAIN_NAME));
//port = 6667;
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time() % 1000);
chatNick[CHAT_NICK_SIZE - 1] = '\0';
_tcscpy(chatUser, _T("ChatCUser"));
_tcscpy(chatName, _T("ChatCName"));
_tcscpy(chatChannel, _T("#GSP!gmtest"));
_tcscpy(gamename, _T("gmtest"));
secretKey[0] = 'H';
secretKey[1] = 'A';
secretKey[2] = '6';
secretKey[3] = 'z';
secretKey[4] = 'k';
secretKey[5] = 'S';
secretKey[6] = '\0';
// Go through command-line options.
///////////////////////////////////
for(i = 1 ; i < argc ; i++)
{
if((argv[i][0] == '-') && ((i + 1) < argc))
{
switch(argv[i][1])
{
case 's':
#ifndef GSI_UNICODE
strcpy(serverAddress, argv[++i]);
#else
AsciiToUCS2String(argv[++i], serverAddress);
#endif
break;
case 'p':
port = atoi(argv[++i]);
break;
case 'n':
#ifndef GSI_UNICODE
strcpy(chatNick, argv[++i]);
#else
AsciiToUCS2String(argv[++i], chatNick);
#endif
break;
case 'u':
#ifndef GSI_UNICODE
strcpy(chatUser, argv[++i]);
#else
AsciiToUCS2String(argv[++i], chatUser);
#endif
break;
case 'c':
#ifndef GSI_UNICODE
strcpy(chatChannel, argv[++i]);
#else
AsciiToUCS2String(argv[++i], chatChannel);
#endif
break;
default:
_tprintf(_T("Error parsing command-line: %s\n"), argv[i]);
return 1;
}
}
else
{
_tprintf(_T("Error parsing command-line: %s\n"), argv[i]);
return 1;
}
}
// Set global callbacks.
////////////////////////
memset(&globalCallbacks, 0, sizeof(chatGlobalCallbacks));
globalCallbacks.raw = Raw;
globalCallbacks.disconnected = Disconnected;
globalCallbacks.privateMessage = PrivateMessage;
globalCallbacks.invited = Invited;
globalCallbacks.param = NULL;
// Connect.
///////////
chat = chatConnectSecure(serverAddress[0]?serverAddress:NULL, port, chatNick, chatName, gamename, secretKey, &globalCallbacks, NickErrorCallback, FillInUserCallback, ConnectCallback, NULL, CHATTrue);
if(!chat)
{
_tprintf(_T("Connect failed\n"));
return 1;
}
// Set channel callbacks.
/////////////////////////
memset(&channelCallbacks, 0, sizeof(chatChannelCallbacks));
channelCallbacks.channelMessage = ChannelMessage;
channelCallbacks.channelModeChanged = ChannelModeChanged;
channelCallbacks.kicked = Kicked;
channelCallbacks.topicChanged = TopicChanged;
channelCallbacks.userParted = UserParted;
channelCallbacks.userJoined = UserJoined;
channelCallbacks.userListUpdated = UserListUpdated;
channelCallbacks.userModeChanged = UserModeChanged;
channelCallbacks.userChangedNick = UserChangedNick;
channelCallbacks.param = NULL;
// Join.
////////
chatEnterChannel(chat, chatChannel, NULL, &channelCallbacks, EnterChannelCallback, NULL, CHATTrue);
if(!enterChannelSuccess)
{
_tprintf(_T("Enter Channel failed\n"));
return 1;
}
// Say hi.
//////////
chatSendChannelMessage(chat, chatChannel, _T("Hi"), CHAT_MESSAGE);
// Enum through the players.
////////////////////////////
chatEnumUsers(chat, chatChannel, EnumUsersCallback, NULL, CHATFalse);
// Stay for a while.
////////////////////
stopTime = (current_time() + 60000);
do
{
chatThink(chat);
msleep(50);
}
while(!quit && (current_time() < stopTime));
// Say bye.
///////////
chatSendChannelMessage(chat, chatChannel, _T("Bye"), CHAT_MESSAGE);
// Leave.
/////////
chatLeaveChannel(chat, chatChannel, NULL);
// Disconnect.
//////////////
chatDisconnect(chat);
_tprintf(_T("All Done!\n"));
return 0;
}

View file

@ -0,0 +1,493 @@
#---------------------------------------------------------------------------
# Project: NitroSDK - tools - makelcf
# File: ARM9-TS.lcf.template
#
# Copyright 2003-2006 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: ARM9-TS.lcf.template,v $
# Revision 1.34 04/06/2006 09:02:36 kitase_hirotake
# support for .itcm.bss and .dtcm.bss
#
# Revision 1.33 03/30/2006 23:59:22 AM yasu
# changed creation year
#
# Revision 1.32 03/29/2006 13:14:22 AM yasu
# support for overlays in CWVER 2.x
#
# Revision 1.31 11/24/2005 01:16:47 yada
# change start address of mainEX arena from 0x2400000 to 0x23e0000
#
# Revision 1.30 09/02/2005 04:14:22 AM yasu
# Old symbols were redefined so they can be used even under SDK2.2
#
# Revision 1.29 08/31/2005 09:34:57 AM yasu
# Corrected a problem where code would not function normally when using section names such as section_BSS
#
# Revision 1.28 08/26/2005 11:22:16 AM yasu
# overlay support for ITCM/DTCM
#
# Revision 1.27 06/20/2005 12:29:20 AM yasu
# Changed Surffix to Suffix
#
# Revision 1.26 06/14/2005 09:03:42 yada
# fix around minus value of SDK_STACKSIZE
#
# Revision 1.25 04/13/2005 12:51:00 terui
# Change SDK_AUTOLOAD.DTCM.START 0x027c0000 -> 0x027e0000
#
# Revision 1.24 03/30/2005 00:02:14 yosizaki
# fix copyright header.
#
# Revision 1.23 03/25/2005 12:54:59 AM yasu
# Include .version section
#
# Revision 1.22 10/03/2004 02:00:56 AM yasu
# Output component file list for compstatic tool
#
# Revision 1.21 09/27/2004 05:28:21 AM yasu
# Support .sinit
#
# Revision 1.20 09/09/2004 11:49:20 AM yasu
# Support compstatic in default
#
# Revision 1.19 09/06/2004 06:40:00 AM yasu
# Add labels for digest
#
# Revision 1.18 08/20/2004 06:19:59 AM yasu
# DTCM moves to 0x027c0000 at default
#
# Revision 1.17 08/02/2004 10:38:53 AM yasu
# Add autoload-done callback address in overlaydefs
#
# Revision 1.16 07/26/2004 02:22:32 AM yasu
# Change DTCM address to 0x023c0000
#
# Revision 1.15 07/26/2004 00:08:27 AM yasu
# Fix label of exception table
#
# Revision 1.14 07/24/2004 05:42:25 AM yasu
# Set default values for SDK_AUTOGEN_xTCM_START
#
# Revision 1.13 07/23/2004 11:32:14 AM yasu
# Define labels for __exception_table_start__ and _end__
#
# Revision 1.12 07/12/2004 12:21:08 AM yasu
# Check size of ITCM/DTCM
#
# Revision 1.11 07/10/2004 04:10:26 AM yasu
# Support command 'Library'
#
# Revision 1.10 07/02/2004 08:13:02 AM yasu
# Support OBJECT( )
#
# Revision 1.9 07/01/2004 12:54:38 yasu
# support ITCM/DTCM/WRAM autoload
#
# Revision 1.8 07/01/2004 10:41:46 yasu
# support autoload
#
# Revision 1.7 06/02/2004 07:35:37 yasu
# Set libsyscall.a in FORCE_ACTIVE
# Put NitroMain at the top of ROM image
#
# Revision 1.6 06/02/2004 04:56:28 yasu
# Change to fit to new ROM map of TS
#
# Revision 1.5 2004/06/01 06:12:00 miya
# add padding at top of ROM image.
#
# Revision 1.4 04/26/2004 12:16:48 yasu
# add KEEP_SECTIONS
#
# Revision 1.3 04/20/2004 07:41:32 yasu
# Set STATICINIT instead of .ctor temporarily
#
# Revision 1.2 04/14/2004 07:16:42 yasu
# add ALIGN(32) for convenience to handle cache line
#
# Revision 1.1 04/06/2004 01:59:54 yasu
# newly added
#
# $NoKeywords: $
#---------------------------------------------------------------------------
MEMORY
{
main (RWX) : ORIGIN = 0x02000000, LENGTH = 0x0 > main.sbin
ITCM (RWX) : ORIGIN = 0x01ff8000, LENGTH = 0x0 >> main.sbin
DTCM (RWX) : ORIGIN = 0x027e0000, LENGTH = 0x0 >> main.sbin
binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> main.sbin
binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> main.sbin
main_defs (RW) : ORIGIN = AFTER(main), LENGTH = 0x0 > main_defs.sbin
main_table (RW) : ORIGIN = AFTER(main), LENGTH = 0x0 > main_table.sbin
dummy.MAIN_EX (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0
arena.MAIN (RW) : ORIGIN = AFTER(main), LENGTH = 0x0
arena.MAIN_EX (RW) : ORIGIN = AFTER(dummy.MAIN_EX), LENGTH = 0x0
arena.ITCM (RW) : ORIGIN = AFTER(ITCM), LENGTH = 0x0
arena.DTCM (RW) : ORIGIN = AFTER(DTCM), LENGTH = 0x0
binary.MODULE_FILES (RW) : ORIGIN = 0x0, LENGTH = 0x0 > component.files
check.ITCM (RWX) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check
check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check
}
FORCE_ACTIVE
{
SVC_SoftReset
}
KEEP_SECTION
{
.sinit
}
SECTIONS
{
############################ STATIC #################################
.main:
{
ALIGNALL(4); . = ALIGN(32); # Fit to cache line
#
# TEXT BLOCK: READ ONLY
#
SDK_STATIC_START =.;
SDK_STATIC_TEXT_START =.;
#:::::::::: text/rodata
libsyscall.a (.text)
crt0.o (.text)
crt0.o (.rodata)
* (.version)
OBJECT(NitroMain,*)
GROUP(ROOT) (.text)
. = ALIGN(4);
* (.exception)
. = ALIGN(4);
SDK_STATIC_ETABLE_START =.;
EXCEPTION
SDK_STATIC_ETABLE_END =.;
. = ALIGN(4);
GROUP(ROOT) (.init)
. = ALIGN(4);
GROUP(ROOT) (.rodata)
. = ALIGN(4);
SDK_STATIC_SINIT_START =.;
#:::::::::: ctor
GROUP(ROOT) (.ctor)
GROUP(ROOT) (.sinit)
WRITEW 0;
#:::::::::: ctor
SDK_STATIC_SINIT_END =.;
#:::::::::: text/rodata
. = ALIGN(32);
SDK_STATIC_TEXT_END =.;
#
# DATA BLOCK: READ WRITE
#
SDK_STATIC_DATA_START =.;
#:::::::::: data
GROUP(ROOT) (.sdata)
. = ALIGN(4);
GROUP(ROOT) (.data)
. = ALIGN(4);
SDK_OVERLAY_DIGEST =.;
# NO DIGEST
SDK_OVERLAY_DIGEST_END =.;
#:::::::::: data
. = ALIGN(32);
SDK_STATIC_DATA_END =.;
SDK_STATIC_END =.;
SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START;
SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START;
SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START;
__sinit__ = SDK_STATIC_SINIT_START; # for static initializer
__exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table
__exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table
} > main
.main.bss:
{
ALIGNALL(4); . = ALIGN(32);
#
# BSS BLOCK
#
SDK_STATIC_BSS_START =.;
#:::::::::: bss
GROUP(ROOT) (.sbss)
. = ALIGN(4);
GROUP(ROOT) (.bss)
. = ALIGN(4);
#:::::::::: bss
. = ALIGN(32);
SDK_STATIC_BSS_END = .;
SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START;
} >> main
############################ AUTOLOADS ##############################
SDK_AUTOLOAD.ITCM.START = 0x01ff8000;
SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START;
SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START;
SDK_AUTOLOAD.ITCM.SIZE = 0;
SDK_AUTOLOAD.ITCM.BSS_SIZE = 0;
SDK_AUTOLOAD.DTCM.START = 0x027e0000;
SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START;
SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START;
SDK_AUTOLOAD.DTCM.SIZE = 0;
SDK_AUTOLOAD.DTCM.BSS_SIZE = 0;
SDK_AUTOLOAD_START = SDK_STATIC_END;
SDK_AUTOLOAD_SIZE = 0;
SDK_AUTOLOAD_NUMBER = 2;
.ITCM:
{
ALIGNALL(4); . = ALIGN(32);
#
# TEXT BLOCK: READ ONLY
#
SDK_AUTOLOAD_ITCM_ID =0;
SDK_AUTOLOAD.ITCM.ID =0;
SDK_AUTOLOAD.ITCM.START =.;
SDK_AUTOLOAD.ITCM.TEXT_START =.;
#:::::::::: text/rodata
. = ALIGN(4);
* (.itcm)
. = ALIGN(4);
. = ALIGN(4);
#:::::::::: text/rodata
SDK_AUTOLOAD.ITCM.TEXT_END =.;
#
# DATA BLOCK: READ WRITE BLOCK
#
SDK_AUTOLOAD.ITCM.DATA_START =.;
#:::::::::: data
. = ALIGN(4);
. = ALIGN(4);
. = ALIGN(4);
#:::::::::: data
. = ALIGN(32);
SDK_AUTOLOAD.ITCM.DATA_END =.;
SDK_AUTOLOAD.ITCM.END =.;
SDK_AUTOLOAD.ITCM.TEXT_SIZE = SDK_AUTOLOAD.ITCM.TEXT_END - SDK_AUTOLOAD.ITCM.TEXT_START;
SDK_AUTOLOAD.ITCM.DATA_SIZE = SDK_AUTOLOAD.ITCM.DATA_END - SDK_AUTOLOAD.ITCM.DATA_START;
SDK_AUTOLOAD.ITCM.SIZE = SDK_AUTOLOAD.ITCM.END - SDK_AUTOLOAD.ITCM.START;
SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD.ITCM.SIZE;
} > ITCM
.ITCM.bss:
{
ALIGNALL(4); . = ALIGN(32);
#
# BSS BLOCK
#
SDK_AUTOLOAD.ITCM.BSS_START = .;
#:::::::::: bss
. = ALIGN(4);
. = ALIGN(4);
. = ALIGN(4);
* (.itcm.bss)
. = ALIGN(4);
#:::::::::: bss
. = ALIGN(32);
SDK_AUTOLOAD.ITCM.BSS_END = .;
SDK_AUTOLOAD.ITCM.BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_END - SDK_AUTOLOAD.ITCM.BSS_START;
} >> ITCM
.DTCM:
{
ALIGNALL(4); . = ALIGN(32);
#
# TEXT BLOCK: READ ONLY
#
SDK_AUTOLOAD_DTCM_ID =1;
SDK_AUTOLOAD.DTCM.ID =1;
SDK_AUTOLOAD.DTCM.START =.;
SDK_AUTOLOAD.DTCM.TEXT_START =.;
#:::::::::: text/rodata
. = ALIGN(4);
. = ALIGN(4);
. = ALIGN(4);
#:::::::::: text/rodata
SDK_AUTOLOAD.DTCM.TEXT_END =.;
#
# DATA BLOCK: READ WRITE BLOCK
#
SDK_AUTOLOAD.DTCM.DATA_START =.;
#:::::::::: data
. = ALIGN(4);
. = ALIGN(4);
* (.dtcm)
. = ALIGN(4);
#:::::::::: data
. = ALIGN(32);
SDK_AUTOLOAD.DTCM.DATA_END =.;
SDK_AUTOLOAD.DTCM.END =.;
SDK_AUTOLOAD.DTCM.TEXT_SIZE = SDK_AUTOLOAD.DTCM.TEXT_END - SDK_AUTOLOAD.DTCM.TEXT_START;
SDK_AUTOLOAD.DTCM.DATA_SIZE = SDK_AUTOLOAD.DTCM.DATA_END - SDK_AUTOLOAD.DTCM.DATA_START;
SDK_AUTOLOAD.DTCM.SIZE = SDK_AUTOLOAD.DTCM.END - SDK_AUTOLOAD.DTCM.START;
SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD.DTCM.SIZE;
} > DTCM
.DTCM.bss:
{
ALIGNALL(4); . = ALIGN(32);
#
# BSS BLOCK
#
SDK_AUTOLOAD.DTCM.BSS_START = .;
#:::::::::: bss
. = ALIGN(4);
. = ALIGN(4);
* (.dtcm.bss)
. = ALIGN(4);
. = ALIGN(4);
#:::::::::: bss
. = ALIGN(32);
SDK_AUTOLOAD.DTCM.BSS_END = .;
SDK_AUTOLOAD.DTCM.BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_END - SDK_AUTOLOAD.DTCM.BSS_START;
} >> DTCM
SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START;
SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END;
SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END;
SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE;
SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE;
SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START;
SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END;
SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END;
SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE;
SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE;
############################ AUTOLOAD_INFO ##########################
.binary.AUTOLOAD_INFO:
{
WRITEW ADDR(.ITCM);
WRITEW SDK_AUTOLOAD.ITCM.SIZE;
WRITEW SDK_AUTOLOAD.ITCM.BSS_SIZE;
WRITEW ADDR(.DTCM);
WRITEW SDK_AUTOLOAD.DTCM.SIZE;
WRITEW SDK_AUTOLOAD.DTCM.BSS_SIZE;
} > binary.AUTOLOAD_INFO
SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE;
SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO);
SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO);
############################ STATIC_FOOTER ##########################
.binary.STATIC_FOOTER:
{
WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE
WRITEW _start_ModuleParams - ADDR(.main);
WRITEW 0; # NO DIGEST
} > binary.STATIC_FOOTER
############################ OVERLAYS ###############################
SDK_OVERLAY_NUMBER = 0;
############################ MAIN EX ##################################
# MAIN EX Area
.dummy.MAIN_EX:
{
. = ALIGN(32);
} > dummy.MAIN_EX
############################ ARENA ##################################
.arena.MAIN:
{
. = ALIGN(32);
SDK_SECTION_ARENA_START =.;
} > arena.MAIN
.arena.MAIN_EX:
{
. = ALIGN(32);
SDK_SECTION_ARENA_EX_START =.;
} > arena.MAIN_EX
.arena.ITCM:
{
. = ALIGN(32);
SDK_SECTION_ARENA_ITCM_START =.;
} > arena.ITCM
.arena.DTCM:
{
. = ALIGN(32);
SDK_SECTION_ARENA_DTCM_START =.;
} > arena.DTCM
############################ OVERLAYDEFS ############################
.main_defs:
{
### main module information
WRITEW ADDR(.main); # load address
WRITEW _start; # entry address
WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module
WRITEW _start_AutoloadDoneCallback; # callback autoload done
### overlay filename
} > main_defs
############################ OVERLAYTABLE ###########################
.main_table:
{
} > main_table
############################ OTHERS #################################
SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START;
SDK_IRQ_STACKSIZE = 4096; # allocated in DTCM
SDK_SYS_STACKSIZE = 0; # when 0 means all remains of DTCM
# Module filelist
.binary.MODULE_FILES:
{
WRITES ("main.sbin");
WRITES ("main_defs.sbin");
WRITES ("main_table.sbin");
} > binary.MODULE_FILES
# ITCM/DTCM size checker => check AUTOLOAD_ITCM/DTCM
.check.ITCM:
{
. = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE;
} > check.ITCM
SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1;
.check.DTCM:
{
. = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE;
. = . + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN;
} > check.DTCM
}

View file

@ -0,0 +1,116 @@
#----------------------------------------------------------------------------
# Project: NitroSDK - include
# File: ROM-TS.lsf
#
# Copyright 2003-2005 Nintendo. All rights reserved.
#
# These coded insructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: ROM-TS.rsf,v $
# Revision 1.6 2005/04/05 23:52:58 yosizaki
# fix copyright date.
#
# Revision 1.5 2005/04/05 12:16:10 yosizaki
# support RomSpeedType parameter.
#
# Revision 1.4 2004/09/21 02:18:49 yasu
# Add default banner
#
# Revision 1.3 2004/09/09 11:39:09 yasu
# Unified ROM-TS and ROM-TS-C, also ROM-TEG and ROM-TEG-C
#
# Revision 1.2 2004/05/26 12:03:38 yasu
# add :r option to get basename for supporting IDE with makerom
#
# Revision 1.1 2004/04/06 01:59:59 yasu
# newly added
#
# $NoKeywords: $
#----------------------------------------------------------------------------
#
# Nitro ROM SPEC FILE
#
Arm9
{
Static "$(MAKEROM_ARM9:r).sbin$(COMPSUFFIX9)"
OverlayDefs "$(MAKEROM_ARM9:r)_defs.sbin$(COMPSUFFIX9)"
OverlayTable "$(MAKEROM_ARM9:r)_table.sbin$(COMPSUFFIX9)"
Elf "$(MAKEROM_ARM9:r).nef"
}
Arm7
{
Static "$(MAKEROM_ARM7:r).sbin$(COMPSUFFIX7)"
OverlayDefs "$(MAKEROM_ARM7:r)_defs.sbin$(COMPSUFFIX7)"
OverlayTable "$(MAKEROM_ARM7:r)_table.sbin$(COMPSUFFIX7)"
Elf "$(MAKEROM_ARM7:r).nef"
}
Property
{
###
### Settings for FinalROM
###
#### BEGIN
#
# TITLE NAME: Your product name within 12bytes
#
#TitleName "YourAppName"
#
# MAKER CODE: Your company ID# in 2 ascii words
# issued by NINTENDO
#
#MakerCode "00"
#
# REMASTER VERSION: Mastering version
#
#RomVersion 0
#
# ROM SPEED TYPE: [MROM/1TROM/UNDEFINED]
#
RomSpeedType $(MAKEROM_ROMSPEED)
#
# ROM SIZE: in bit [64M/128M/256M/512M/1G/2G]
#
#RomSize 128M
#RomSize 256M
#
# ROM PADDING: TRUE if finalrom
#
#RomFootPadding TRUE
#
# ROM HEADER TEMPLATE: Provided to every product by NINTENDO
#
#RomHeaderTemplate ./etc/rom_header.template.sbin
#
# BANNER FILE: generated from Banner Spec File
#
#BannerFile ./etc/myGameBanner.bnr
BannerFile $(NITROSDK_ROOT)/include/nitro/specfiles/default.bnr
###
###
###
#### END
}
RomSpec
{
Offset 0x00000000
Segment ALL
HostRoot $(MAKEROM_ROMROOT)
Root /
File $(MAKEROM_ROMFILES)
}

View file

@ -0,0 +1,384 @@
# Microsoft Developer Studio Project File - Name="chatps2prodg" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=chatps2prodg - Win32 PS2 EE Release Insock
!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 "chatps2prodg.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 "chatps2prodg.mak" CFG="chatps2prodg - Win32 PS2 EE Release Insock"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "chatps2prodg - Win32 PS2 EE Debug EENet" (based on "Win32 (x86) Console Application")
!MESSAGE "chatps2prodg - Win32 PS2 EE Debug SNSystems" (based on "Win32 (x86) Console Application")
!MESSAGE "chatps2prodg - Win32 PS2 EE Debug Insock" (based on "Win32 (x86) Console Application")
!MESSAGE "chatps2prodg - Win32 PS2 EE Release EENet" (based on "Win32 (x86) Console Application")
!MESSAGE "chatps2prodg - Win32 PS2 EE Release SNSystems" (based on "Win32 (x86) Console Application")
!MESSAGE "chatps2prodg - Win32 PS2 EE Release Insock" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""$/Gamespy/GOA/Chat/chatc/chatps2prodg", DSEDAAAA"
# PROP Scc_LocalPath "."
CPP=snCl.exe
RSC=rc.exe
!IF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Debug EENet"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "PS2 EE Debug EENet"
# PROP BASE Intermediate_Dir "PS2 EE Debug EENet"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_EENet"
# PROP Intermediate_Dir "Debug_EENet"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /Fo"PS2_EE_Debug/" /FD /debug /c
# ADD CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /I "C:\usr\local\sce\ee\include\libeenet" /D "SN_TARGET_PS2" /D "_DEBUG" /D "EENET" /FD /debug /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /debug /machine:IX86 /out:"PS2_EE_Debug\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 ent_smap.a ent_eth.a ent_ppp.a eenetctl.a libeenet.a libcdvd.a libscf.a libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /debug /machine:IX86 /out:"Debug_EENet\chatps2prodg.elf" /D:SN_TARGET_PS2
!ELSEIF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Debug SNSystems"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "PS2 EE Debug SNSystems"
# PROP BASE Intermediate_Dir "PS2 EE Debug SNSystems"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_SNSystems"
# PROP Intermediate_Dir "Debug_SNSystems"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /Fo"PS2_EE_Debug/" /FD /debug /c
# ADD CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /D "_DEBUG" /D "SN_SYSTEMS" /FD /debug /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /debug /machine:IX86 /out:"PS2_EE_Debug\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 sneetcp.a libcdvd.a libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /debug /machine:IX86 /out:"Debug_SNSystems\chatps2prodg.elf" /D:SN_TARGET_PS2
!ELSEIF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Debug Insock"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "chatps2prodg___Win32_PS2_EE_Debug_Insock"
# PROP BASE Intermediate_Dir "chatps2prodg___Win32_PS2_EE_Debug_Insock"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_Insock"
# PROP Intermediate_Dir "Debug_Insock"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /I "C:\usr\local\sce\ee\include\libeenet" /D "SN_TARGET_PS2" /D "_DEBUG" /D "EENET" /FD /debug /c
# ADD CPP /nologo /W3 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /D "_DEBUG" /D "INSOCK" /FD /debug /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 ent_smap.a ent_eth.a ent_ppp.a eenetctl.a libeenet.a libcdvd.a libscf.a libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /debug /machine:IX86 /out:"Debug_EENet\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 libinsck.a libnet.a libmrpc.a libkernl.a libcdvd.a libnetif.a netcnfif.a /nologo /pdb:none /debug /machine:IX86 /out:"Debug_Insock\chatps2prodg.elf" /D:SN_TARGET_PS2
!ELSEIF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Release EENet"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "PS2 EE Release EENet"
# PROP BASE Intermediate_Dir "PS2 EE Release EENet"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Release_EENet"
# PROP Intermediate_Dir "Release_EENet"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /O2 /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /Fo"PS2_EE_Release/" /FD /c
# ADD CPP /nologo /W4 /WX /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /I "C:\usr\local\sce\ee\include\libeenet" /D "SN_TARGET_PS2" /D "EENET" /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /machine:IX86 /out:"PS2_EE_Release\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 ent_smap.a ent_eth.a ent_ppp.a eenetctl.a libeenet.a libcdvd.a libscf.a libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /machine:IX86 /out:"Release_EENet\chatps2prodg.elf" /D:SN_TARGET_PS2
!ELSEIF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Release SNSystems"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "PS2 EE Release SNSystems"
# PROP BASE Intermediate_Dir "PS2 EE Release SNSystems"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Release_SNSystems"
# PROP Intermediate_Dir "Release_SNSystems"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /O2 /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /Fo"PS2_EE_Release/" /FD /c
# ADD CPP /nologo /W4 /WX /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /D "SN_SYSTEMS" /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /machine:IX86 /out:"PS2_EE_Release\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 sneetcp.a libcdvd.a libsn.a libgraph.a libdma.a libdev.a libpad.a libpkt.a libvu0.a /nologo /pdb:none /machine:IX86 /out:"Release_SNSystems\chatps2prodg.elf" /D:SN_TARGET_PS2
!ELSEIF "$(CFG)" == "chatps2prodg - Win32 PS2 EE Release Insock"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "chatps2prodg___Win32_PS2_EE_Release_Insock"
# PROP BASE Intermediate_Dir "chatps2prodg___Win32_PS2_EE_Release_Insock"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "chatps2prodg___Win32_PS2_EE_Release_Insock"
# PROP Intermediate_Dir "chatps2prodg___Win32_PS2_EE_Release_Insock"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /w /W0 /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /D "_DEBUG" /D "INSOCK" /Fo"Debug_Insock/" /Fd"Debug_Insock/" /FD /debug /c
# ADD CPP /nologo /W4 /WX /Od /I "C:\usr\local\sce\ee\include" /I "C:\usr\local\sce\common\include" /D "SN_TARGET_PS2" /D "INSOCK" /Fo"Release_Insock/" /Fd"Release_Insock/" /FD /debug /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=snBsc.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=snLink.exe
# ADD BASE LINK32 libinsck.a libnet.a libmrpc.a libkernl.a libcdvd.a libnetif.a netcnfif.a /nologo /pdb:none /debug /machine:IX86 /out:"Debug_Insock\chatps2prodg.elf" /D:SN_TARGET_PS2
# ADD LINK32 libinsck.a libnet.a libmrpc.a libkernl.a libcdvd.a libnetif.a netcnfif.a /nologo /pdb:none /debug /machine:IX86 /out:"Release_Insock\chatps2prodg.elf" /D:SN_TARGET_PS2
!ENDIF
# Begin Target
# Name "chatps2prodg - Win32 PS2 EE Debug EENet"
# Name "chatps2prodg - Win32 PS2 EE Debug SNSystems"
# Name "chatps2prodg - Win32 PS2 EE Debug Insock"
# Name "chatps2prodg - Win32 PS2 EE Release EENet"
# Name "chatps2prodg - Win32 PS2 EE Release SNSystems"
# Name "chatps2prodg - Win32 PS2 EE Release Insock"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\chatc.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\ps2\ps2common.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\..\common\ps2\prodg\PS2_in_VC.h
# End Source File
# End Group
# Begin Group "ChatSDK"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\chat.h
# End Source File
# Begin Source File
SOURCE=..\..\chatCallbacks.c
# End Source File
# Begin Source File
SOURCE=..\..\chatCallbacks.h
# End Source File
# Begin Source File
SOURCE=..\..\chatChannel.c
# End Source File
# Begin Source File
SOURCE=..\..\chatChannel.h
# End Source File
# Begin Source File
SOURCE=..\..\chatCrypt.c
# End Source File
# Begin Source File
SOURCE=..\..\chatCrypt.h
# End Source File
# Begin Source File
SOURCE=..\..\chatHandlers.c
# End Source File
# Begin Source File
SOURCE=..\..\chatHandlers.h
# End Source File
# Begin Source File
SOURCE=..\..\chatMain.c
# End Source File
# Begin Source File
SOURCE=..\..\chatMain.h
# End Source File
# Begin Source File
SOURCE=..\..\chatSocket.c
# End Source File
# Begin Source File
SOURCE=..\..\chatSocket.h
# End Source File
# End Group
# Begin Group "GsCommon"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\darray.c
# End Source File
# Begin Source File
SOURCE=..\..\..\darray.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsAssert.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsAssert.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsAvailable.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsAvailable.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsCommon.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsDebug.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsDebug.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsMemory.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsMemory.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatform.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatform.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformSocket.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformSocket.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformThread.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformThread.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformUtil.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsPlatformUtil.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsStringUtil.c
# End Source File
# Begin Source File
SOURCE=..\..\..\common\gsStringUtil.h
# End Source File
# Begin Source File
SOURCE=..\..\..\hashtable.c
# End Source File
# Begin Source File
SOURCE=..\..\..\hashtable.h
# End Source File
# Begin Source File
SOURCE=..\..\..\md5.h
# End Source File
# Begin Source File
SOURCE=..\..\..\md5c.c
# End Source File
# End Group
# Begin Source File
SOURCE=c:\usr\local\sce\ee\lib\app.cmd
# End Source File
# Begin Source File
SOURCE=c:\usr\local\sce\ee\lib\crt0.s
# End Source File
# Begin Source File
SOURCE=..\..\..\ps2common\prodg\ps2.lk
# End Source File
# End Target
# End Project

View file

@ -0,0 +1,37 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "chatps2prodg"=.\chatps2prodg.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/Gamespy/GOA/Chat/chatc/chatps2prodg", DSEDAAAA
.
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
begin source code control
"$/Gamespy/GOA/Chat/chatc/chatps2prodg", DSEDAAAA
.
end source code control
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -0,0 +1,164 @@
// ChannelListDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "ChannelListDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChannelListDlg dialog
CChannelListDlg::CChannelListDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChannelListDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChannelListDlg)
m_filter = _T("");
//}}AFX_DATA_INIT
}
void CChannelListDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChannelListDlg)
DDX_Control(pDX, IDC_NUM, m_num);
DDX_Control(pDX, IDC_LIST, m_list);
DDX_Text(pDX, IDC_FILTER, m_filter);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChannelListDlg, CDialog)
//{{AFX_MSG_MAP(CChannelListDlg)
ON_BN_CLICKED(ID_CHANNELS, OnChannels)
ON_BN_CLICKED(ID_USERS, OnUsers)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChannelListDlg message handlers
void EnumChannelsCallbackEach(CHAT chat, CHATBool success, int index, const char * channel, const char * topic, int numUsers, void * param)
{
if(success)
{
CChannelListDlg * dlg = (CChannelListDlg *)param;
CListBox * list = &dlg->m_list;
CString str;
str = channel;
str += " (";
char buffer[16];
itoa(numUsers, buffer, 10);
str += buffer;
str += "): ";
str += topic;
list->AddString(str);
char buf[16];
itoa(index + 1, buf, 10);
dlg->m_num.SetWindowText(buf);
}
GSI_UNUSED(chat);
}
void EnumJoinedChannelsCallback(CHAT chat,
int index,
const char * channel,
void * param)
{
CChannelListDlg * dlg = (CChannelListDlg *)param;
CListBox * list = &dlg->m_list;
CString str;
str = "IN: ";
str += channel;
str += " (";
char buffer[16];
itoa(index, buffer, 10);
str += buffer;
str += "): ";
list->AddString(str);
GSI_UNUSED(chat);
}
void EnumChannelsCallbackAll(CHAT chat, CHATBool success, int numChannels, const char ** channels, const char ** topics, int * numUsers, void * param)
{
if(success)
{
CChannelListDlg * dlg = (CChannelListDlg *)param;
dlg->MessageBox("Search Complete");
}
GSI_UNUSED(numUsers);
GSI_UNUSED(topics);
GSI_UNUSED(channels);
GSI_UNUSED(numChannels);
GSI_UNUSED(chat);
}
void ListUsers(CHAT chat, CHATBool success, const char * channel, int numUsers, const char ** users, int * modes, void * param)
{
if(success)
{
CChannelListDlg * dlg = (CChannelListDlg *)param;
CListBox * list = &dlg->m_list;
CString str;
for(int i = 0 ; i < numUsers ; i++)
{
str = users[i];
if(modes[i] & CHAT_OP)
str.Insert(0, '@');
else if(modes[i] & CHAT_VOICE)
str.Insert(0, '?');
list->AddString(str);
}
char buf[16];
itoa(numUsers, buf, 10);
dlg->m_num.SetWindowText(buf);
}
GSI_UNUSED(channel);
GSI_UNUSED(chat);
}
void CChannelListDlg::OnChannels()
{
// Clear the list.
//////////////////
m_list.ResetContent();
// Get the list.
////////////////
UpdateData();
chatEnumJoinedChannels(theApp.m_chat, EnumJoinedChannelsCallback, this);
chatEnumChannels(theApp.m_chat, m_filter, EnumChannelsCallbackEach, EnumChannelsCallbackAll, this, CHATFalse);
}
void CChannelListDlg::OnUsers()
{
// Clear the list.
//////////////////
m_list.ResetContent();
// Get the list.
////////////////
UpdateData();
chatEnumUsers(theApp.m_chat, m_filter, ListUsers, this, CHATFalse);
}

View file

@ -0,0 +1,49 @@
#if !defined(AFX_CHANNELLISTDLG_H__2D417F5B_EB62_4913_BB7A_6B20477ED21D__INCLUDED_)
#define AFX_CHANNELLISTDLG_H__2D417F5B_EB62_4913_BB7A_6B20477ED21D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ChannelListDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CChannelListDlg dialog
class CChannelListDlg : public CDialog
{
// Construction
public:
CChannelListDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CChannelListDlg)
enum { IDD = IDD_CHANNEL_LIST };
CEdit m_num;
CListBox m_list;
CString m_filter;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChannelListDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CChannelListDlg)
afx_msg void OnChannels();
afx_msg void OnUsers();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHANNELLISTDLG_H__2D417F5B_EB62_4913_BB7A_6B20477ED21D__INCLUDED_)

View file

@ -0,0 +1,56 @@
// ChannelModeDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "ChannelModeDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChannelModeDlg dialog
CChannelModeDlg::CChannelModeDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChannelModeDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChannelModeDlg)
m_inviteOnly = FALSE;
m_limit = 0;
m_moderated = FALSE;
m_noExternalMessages = FALSE;
m_onlyOpsChangeTopic = FALSE;
m_private = FALSE;
m_secret = FALSE;
//}}AFX_DATA_INIT
}
void CChannelModeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChannelModeDlg)
DDX_Check(pDX, IDC_INVITE_ONLY, m_inviteOnly);
DDX_Text(pDX, IDC_LIMIT, m_limit);
DDV_MinMaxInt(pDX, m_limit, 0, 9999);
DDX_Check(pDX, IDC_MODERATED, m_moderated);
DDX_Check(pDX, IDC_NO_EXTERNAL_MESSAGES, m_noExternalMessages);
DDX_Check(pDX, IDC_ONLY_OPS_CHANGE_TOPIC, m_onlyOpsChangeTopic);
DDX_Check(pDX, IDC_PRIVATE, m_private);
DDX_Check(pDX, IDC_SECRET, m_secret);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChannelModeDlg, CDialog)
//{{AFX_MSG_MAP(CChannelModeDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChannelModeDlg message handlers

View file

@ -0,0 +1,52 @@
#if !defined(AFX_CHANNELMODEDLG_H__87449420_C42C_11D3_BD38_00C0F056BC39__INCLUDED_)
#define AFX_CHANNELMODEDLG_H__87449420_C42C_11D3_BD38_00C0F056BC39__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ChannelModeDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CChannelModeDlg dialog
class CChannelModeDlg : public CDialog
{
// Construction
public:
CChannelModeDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CChannelModeDlg)
enum { IDD = IDD_CHANNEL_MODE };
BOOL m_inviteOnly;
int m_limit;
BOOL m_moderated;
BOOL m_noExternalMessages;
BOOL m_onlyOpsChangeTopic;
BOOL m_private;
BOOL m_secret;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChannelModeDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CChannelModeDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHANNELMODEDLG_H__87449420_C42C_11D3_BD38_00C0F056BC39__INCLUDED_)

View file

@ -0,0 +1,69 @@
// ChildFrm.cpp : implementation of the CChildFrame class
//
#include "stdafx.h"
#include "chatty.h"
#include "ChildFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChildFrame
IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)
BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
//{{AFX_MSG_MAP(CChildFrame)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChildFrame construction/destruction
CChildFrame::CChildFrame()
{
// TODO: add member initialization code here
}
CChildFrame::~CChildFrame()
{
}
BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
if( !CMDIChildWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CChildFrame diagnostics
#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
CMDIChildWnd::AssertValid();
}
void CChildFrame::Dump(CDumpContext& dc) const
{
CMDIChildWnd::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CChildFrame message handlers

View file

@ -0,0 +1,51 @@
// ChildFrm.h : interface of the CChildFrame class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_CHILDFRM_H__CECBEADE_E41E_4FB6_93DD_C3735CFC4679__INCLUDED_)
#define AFX_CHILDFRM_H__CECBEADE_E41E_4FB6_93DD_C3735CFC4679__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CChildFrame : public CMDIChildWnd
{
DECLARE_DYNCREATE(CChildFrame)
public:
CChildFrame();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChildFrame)
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CChildFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
protected:
//{{AFX_MSG(CChildFrame)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHILDFRM_H__CECBEADE_E41E_4FB6_93DD_C3735CFC4679__INCLUDED_)

View file

@ -0,0 +1,47 @@
// ConnectDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "ConnectDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CConnectDlg dialog
CConnectDlg::CConnectDlg(CWnd* pParent /*=NULL*/)
: CDialog(CConnectDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CConnectDlg)
m_address = _T("");
m_nick = _T("");
m_port = 0;
//}}AFX_DATA_INIT
}
void CConnectDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CConnectDlg)
DDX_Text(pDX, IDC_ADDRESS, m_address);
DDX_Text(pDX, IDC_NICK, m_nick);
DDX_Text(pDX, IDC_PORT, m_port);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CConnectDlg, CDialog)
//{{AFX_MSG_MAP(CConnectDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CConnectDlg message handlers

View file

@ -0,0 +1,48 @@
#if !defined(AFX_CONNECTDLG_H__999D9DD8_12B0_4F46_BF46_F607FB3341A0__INCLUDED_)
#define AFX_CONNECTDLG_H__999D9DD8_12B0_4F46_BF46_F607FB3341A0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ConnectDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CConnectDlg dialog
class CConnectDlg : public CDialog
{
// Construction
public:
CConnectDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CConnectDlg)
enum { IDD = IDD_CONNECT };
CString m_address;
CString m_nick;
int m_port;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CConnectDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CConnectDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CONNECTDLG_H__999D9DD8_12B0_4F46_BF46_F607FB3341A0__INCLUDED_)

View file

@ -0,0 +1,74 @@
// EnterDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "EnterDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEnterDlg dialog
CEnterDlg::CEnterDlg(CWnd* pParent /*=NULL*/)
: CDialog(CEnterDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CEnterDlg)
m_channel = _T("");
m_password = _T("");
//}}AFX_DATA_INIT
m_quickChannel = "";
}
void CEnterDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CEnterDlg)
DDX_Text(pDX, IDC_CHANNEL, m_channel);
DDX_Text(pDX, IDC_PASSWORD, m_password);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CEnterDlg, CDialog)
//{{AFX_MSG_MAP(CEnterDlg)
ON_BN_CLICKED(IDC_QUICK1, OnQuick1)
ON_BN_CLICKED(IDC_QUICK2, OnQuick2)
ON_BN_CLICKED(IDC_QUICK3, OnQuick3)
ON_BN_CLICKED(IDC_QUICK4, OnQuick4)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEnterDlg message handlers
void CEnterDlg::OnQuick1()
{
m_quickChannel = "#istanbul";
OnOK();
}
void CEnterDlg::OnQuick2()
{
m_quickChannel = "#montreal";
OnOK();
}
void CEnterDlg::OnQuick3()
{
m_quickChannel = "#pants-test";
OnOK();
}
void CEnterDlg::OnQuick4()
{
m_quickChannel = "#zurna";
OnOK();
}

View file

@ -0,0 +1,52 @@
#if !defined(AFX_ENTERDLG_H__56D121BA_9750_4FF9_AEA2_0CDAC1CB1DC2__INCLUDED_)
#define AFX_ENTERDLG_H__56D121BA_9750_4FF9_AEA2_0CDAC1CB1DC2__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EnterDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CEnterDlg dialog
class CEnterDlg : public CDialog
{
// Construction
public:
CEnterDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CEnterDlg)
enum { IDD = IDD_ENTER };
CString m_channel;
CString m_password;
//}}AFX_DATA
CString m_quickChannel;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEnterDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CEnterDlg)
afx_msg void OnQuick1();
afx_msg void OnQuick2();
afx_msg void OnQuick3();
afx_msg void OnQuick4();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ENTERDLG_H__56D121BA_9750_4FF9_AEA2_0CDAC1CB1DC2__INCLUDED_)

View file

@ -0,0 +1,80 @@
// GetUserInfoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "GetUserInfoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGetUserInfoDlg dialog
CGetUserInfoDlg::CGetUserInfoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CGetUserInfoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CGetUserInfoDlg)
m_address = _T("");
m_name = _T("");
m_user = _T("");
m_nick = _T("");
//}}AFX_DATA_INIT
}
void CGetUserInfoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CGetUserInfoDlg)
DDX_Control(pDX, IDC_CHANNELS, m_channels);
DDX_Text(pDX, IDC_ADDRESS, m_address);
DDX_Text(pDX, IDC_NAME, m_name);
DDX_Text(pDX, IDC_USER, m_user);
DDX_Text(pDX, IDC_NICK, m_nick);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CGetUserInfoDlg, CDialog)
//{{AFX_MSG_MAP(CGetUserInfoDlg)
ON_BN_CLICKED(ID_GET_INFO, OnGetInfo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGetUserInfoDlg message handlers
void GetUserInfoCallback(CHAT chat, CHATBool success, const char * nick, const char * user, const char * name, const char * address, int numChannels, const char ** channels, void * param)
{
CGetUserInfoDlg * dlg = (CGetUserInfoDlg *)param;
if(success)
{
dlg->m_user = user;
dlg->m_name = name;
dlg->m_address = address;
dlg->UpdateData(FALSE);
dlg->m_channels.ResetContent();
for(int i = 0 ; i < numChannels ; i++)
dlg->m_channels.AddString(channels[i]);
}
dlg->MessageBox("done");
GSI_UNUSED(nick);
GSI_UNUSED(chat);
}
void CGetUserInfoDlg::OnGetInfo()
{
if(theApp.m_chat != NULL)
{
UpdateData();
chatGetUserInfo(theApp.m_chat, m_nick, GetUserInfoCallback, this, CHATTrue);
}
}

View file

@ -0,0 +1,50 @@
#if !defined(AFX_GETUSERINFODLG_H__600E8857_A5B5_41DF_973E_0A3DCCF0DCEB__INCLUDED_)
#define AFX_GETUSERINFODLG_H__600E8857_A5B5_41DF_973E_0A3DCCF0DCEB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// GetUserInfoDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CGetUserInfoDlg dialog
class CGetUserInfoDlg : public CDialog
{
// Construction
public:
CGetUserInfoDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CGetUserInfoDlg)
enum { IDD = IDD_GET_USER_INFO };
CListBox m_channels;
CString m_address;
CString m_name;
CString m_user;
CString m_nick;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGetUserInfoDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CGetUserInfoDlg)
afx_msg void OnGetInfo();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GETUSERINFODLG_H__600E8857_A5B5_41DF_973E_0A3DCCF0DCEB__INCLUDED_)

View file

@ -0,0 +1,43 @@
// KickReasonDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "KickReasonDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CKickReasonDlg dialog
CKickReasonDlg::CKickReasonDlg(CWnd* pParent /*=NULL*/)
: CDialog(CKickReasonDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CKickReasonDlg)
m_reason = _T("");
//}}AFX_DATA_INIT
}
void CKickReasonDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CKickReasonDlg)
DDX_Text(pDX, IDC_REASON, m_reason);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CKickReasonDlg, CDialog)
//{{AFX_MSG_MAP(CKickReasonDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CKickReasonDlg message handlers

View file

@ -0,0 +1,46 @@
#if !defined(AFX_KICKREASONDLG_H__25C49432_E9A9_4BEF_8C47_31F8DF889DF0__INCLUDED_)
#define AFX_KICKREASONDLG_H__25C49432_E9A9_4BEF_8C47_31F8DF889DF0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// KickReasonDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CKickReasonDlg dialog
class CKickReasonDlg : public CDialog
{
// Construction
public:
CKickReasonDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CKickReasonDlg)
enum { IDD = IDD_KICK_REASON };
CString m_reason;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CKickReasonDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CKickReasonDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_KICKREASONDLG_H__25C49432_E9A9_4BEF_8C47_31F8DF889DF0__INCLUDED_)

View file

@ -0,0 +1,133 @@
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "chatty.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndDlgBar.Create(this, IDR_MAINFRAME,
CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("Failed to create dialogbar\n");
return -1; // fail to create
}
if (!m_wndReBar.Create(this) ||
!m_wndReBar.AddBar(&m_wndToolBar) ||
!m_wndReBar.AddBar(&m_wndDlgBar))
{
TRACE0("Failed to create rebar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// TODO: Remove this if you don't want tool tips
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY);
/****************
** TIMER SETUP **
****************/
SetTimer(50, 50, NULL);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CMDIFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CMDIFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CMDIFrameWnd::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
void CMainFrame::OnTimer(UINT nIDEvent)
{
if(nIDEvent == 50)
{
if(theApp.m_chat != NULL)
chatThink(theApp.m_chat);
}
CMDIFrameWnd::OnTimer(nIDEvent);
}

View file

@ -0,0 +1,58 @@
// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_MAINFRM_H__501D21BC_112E_496A_A17B_FB30CD931AF1__INCLUDED_)
#define AFX_MAINFRM_H__501D21BC_112E_496A_A17B_FB30CD931AF1__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMainFrame)
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
CReBar m_wndReBar;
CDialogBar m_wndDlgBar;
// Generated message map functions
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MAINFRM_H__501D21BC_112E_496A_A17B_FB30CD931AF1__INCLUDED_)

View file

@ -0,0 +1,117 @@
========================================================================
MICROSOFT FOUNDATION CLASS LIBRARY : chatty
========================================================================
AppWizard has created this chatty application for you. This application
not only demonstrates the basics of using the Microsoft Foundation classes
but is also a starting point for writing your application.
This file contains a summary of what you will find in each of the files that
make up your chatty application.
chatty.dsp
This file (the project file) contains information at the project level and
is used to build a single project or subproject. Other users can share the
project (.dsp) file, but they should export the makefiles locally.
chatty.h
This is the main header file for the application. It includes other
project specific headers (including Resource.h) and declares the
CChattyApp application class.
chatty.cpp
This is the main application source file that contains the application
class CChattyApp.
chatty.rc
This is a listing of all of the Microsoft Windows resources that the
program uses. It includes the icons, bitmaps, and cursors that are stored
in the RES subdirectory. This file can be directly edited in Microsoft
Visual C++.
chatty.clw
This file contains information used by ClassWizard to edit existing
classes or add new classes. ClassWizard also uses this file to store
information needed to create and edit message maps and dialog data
maps and to create prototype member functions.
res\chatty.ico
This is an icon file, which is used as the application's icon. This
icon is included by the main resource file chatty.rc.
res\chatty.rc2
This file contains resources that are not edited by Microsoft
Visual C++. You should place all resources not editable by
the resource editor in this file.
/////////////////////////////////////////////////////////////////////////////
For the main frame window:
MainFrm.h, MainFrm.cpp
These files contain the frame class CMainFrame, which is derived from
CMDIFrameWnd and controls all MDI frame features.
res\Toolbar.bmp
This bitmap file is used to create tiled images for the toolbar.
The initial toolbar and status bar are constructed in the CMainFrame
class. Edit this toolbar bitmap using the resource editor, and
update the IDR_MAINFRAME TOOLBAR array in chatty.rc to add
toolbar buttons.
/////////////////////////////////////////////////////////////////////////////
For the child frame window:
ChildFrm.h, ChildFrm.cpp
These files define and implement the CChildFrame class, which
supports the child windows in an MDI application.
/////////////////////////////////////////////////////////////////////////////
AppWizard creates one document type and one view:
chattyDoc.h, chattyDoc.cpp - the document
These files contain your CChattyDoc class. Edit these files to
add your special document data and to implement file saving and loading
(via CChattyDoc::Serialize).
chattyView.h, chattyView.cpp - the view of the document
These files contain your CChattyView class.
CChattyView objects are used to view CChattyDoc objects.
res\chattyDoc.ico
This is an icon file, which is used as the icon for MDI child windows
for the CChattyDoc class. This icon is included by the main
resource file chatty.rc.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named chatty.pch and a precompiled types file named StdAfx.obj.
Resource.h
This is the standard header file, which defines new resource IDs.
Microsoft Visual C++ reads and updates this file.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" to indicate parts of the source code you
should add to or customize.
If your application uses MFC in a shared DLL, and your application is
in a language other than the operating system's current language, you
will need to copy the corresponding localized resources MFC42XXX.DLL
from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,
and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation.
For example, MFC42DEU.DLL contains resources translated to German.) If you
don't do this, some of the UI elements of your application will remain in the
language of the operating system.
/////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,43 @@
// SendRawDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "SendRawDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSendRawDlg dialog
CSendRawDlg::CSendRawDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSendRawDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSendRawDlg)
m_raw = _T("");
//}}AFX_DATA_INIT
}
void CSendRawDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSendRawDlg)
DDX_Text(pDX, IDC_RAW, m_raw);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSendRawDlg, CDialog)
//{{AFX_MSG_MAP(CSendRawDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSendRawDlg message handlers

View file

@ -0,0 +1,46 @@
#if !defined(AFX_SENDRAWDLG_H__543BE7A8_4BE8_4ED0_972D_2339364077F6__INCLUDED_)
#define AFX_SENDRAWDLG_H__543BE7A8_4BE8_4ED0_972D_2339364077F6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// SendRawDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSendRawDlg dialog
class CSendRawDlg : public CDialog
{
// Construction
public:
CSendRawDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CSendRawDlg)
enum { IDD = IDD_SEND_RAW };
CString m_raw;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSendRawDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CSendRawDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SENDRAWDLG_H__543BE7A8_4BE8_4ED0_972D_2339364077F6__INCLUDED_)

View file

@ -0,0 +1,45 @@
// SetPasswordDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "SetPasswordDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSetPasswordDlg dialog
CSetPasswordDlg::CSetPasswordDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSetPasswordDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSetPasswordDlg)
m_password = _T("");
m_enable = FALSE;
//}}AFX_DATA_INIT
}
void CSetPasswordDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSetPasswordDlg)
DDX_Text(pDX, IDC_PASSWORD, m_password);
DDX_Check(pDX, IDC_ENABLE, m_enable);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSetPasswordDlg, CDialog)
//{{AFX_MSG_MAP(CSetPasswordDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSetPasswordDlg message handlers

View file

@ -0,0 +1,47 @@
#if !defined(AFX_SETPASSWORDDLG_H__666C66DA_E10E_420D_954E_FB2BCE01D798__INCLUDED_)
#define AFX_SETPASSWORDDLG_H__666C66DA_E10E_420D_954E_FB2BCE01D798__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// SetPasswordDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSetPasswordDlg dialog
class CSetPasswordDlg : public CDialog
{
// Construction
public:
CSetPasswordDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CSetPasswordDlg)
enum { IDD = IDD_SET_PASSWORD };
CString m_password;
BOOL m_enable;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSetPasswordDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CSetPasswordDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SETPASSWORDDLG_H__666C66DA_E10E_420D_954E_FB2BCE01D798__INCLUDED_)

View file

@ -0,0 +1,43 @@
// SetTopicDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "SetTopicDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSetTopicDlg dialog
CSetTopicDlg::CSetTopicDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSetTopicDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSetTopicDlg)
m_topic = _T("");
//}}AFX_DATA_INIT
}
void CSetTopicDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSetTopicDlg)
DDX_Text(pDX, IDC_TOPIC, m_topic);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSetTopicDlg, CDialog)
//{{AFX_MSG_MAP(CSetTopicDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSetTopicDlg message handlers

View file

@ -0,0 +1,46 @@
#if !defined(AFX_SETTOPICDLG_H__15C72001_C3D8_11D3_BD38_00C0F056BC39__INCLUDED_)
#define AFX_SETTOPICDLG_H__15C72001_C3D8_11D3_BD38_00C0F056BC39__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// SetTopicDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CSetTopicDlg dialog
class CSetTopicDlg : public CDialog
{
// Construction
public:
CSetTopicDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CSetTopicDlg)
enum { IDD = IDD_SET_TOPIC };
CString m_topic;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSetTopicDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CSetTopicDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SETTOPICDLG_H__15C72001_C3D8_11D3_BD38_00C0F056BC39__INCLUDED_)

View file

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// chatty.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

View file

@ -0,0 +1,31 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__4CAB521F_F4DE_4629_A857_08E96E0C89E8__INCLUDED_)
#define AFX_STDAFX_H__4CAB521F_F4DE_4629_A857_08E96E0C89E8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxsock.h> // MFC socket extensions
#include <Afxtempl.h>
#include "../chat.h"
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__4CAB521F_F4DE_4629_A857_08E96E0C89E8__INCLUDED_)

View file

@ -0,0 +1,45 @@
// TalkDlg.cpp : implementation file
//
#include "stdafx.h"
#include "chatty.h"
#include "TalkDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTalkDlg dialog
CTalkDlg::CTalkDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTalkDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTalkDlg)
m_message = _T("");
m_type = -1;
//}}AFX_DATA_INIT
}
void CTalkDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTalkDlg)
DDX_Text(pDX, IDC_MESSAGE, m_message);
DDX_Radio(pDX, IDC_NORMAL, m_type);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTalkDlg, CDialog)
//{{AFX_MSG_MAP(CTalkDlg)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTalkDlg message handlers

View file

@ -0,0 +1,47 @@
#if !defined(AFX_TALKDLG_H__87449421_C42C_11D3_BD38_00C0F056BC39__INCLUDED_)
#define AFX_TALKDLG_H__87449421_C42C_11D3_BD38_00C0F056BC39__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TalkDlg.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CTalkDlg dialog
class CTalkDlg : public CDialog
{
// Construction
public:
CTalkDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CTalkDlg)
enum { IDD = IDD_TALK };
CString m_message;
int m_type;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTalkDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CTalkDlg)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TALKDLG_H__87449421_C42C_11D3_BD38_00C0F056BC39__INCLUDED_)

View file

@ -0,0 +1,377 @@
// chatty.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "chatty.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "chattyDoc.h"
#include "chattyView.h"
#include "ConnectDlg.h"
#include "ChannelListDlg.h"
#include "SendRawDlg.h"
#include "GetUserInfoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChattyApp
BEGIN_MESSAGE_MAP(CChattyApp, CWinApp)
//{{AFX_MSG_MAP(CChattyApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_CONNECT, OnFileConnect)
ON_COMMAND(ID_FILE_DISCONNECT, OnFileDisconnect)
ON_COMMAND(ID_FILE_LISTCHANNELS, OnFileListchannels)
ON_COMMAND(ID_FILE_SENDRAW, OnFileSendraw)
ON_COMMAND(ID_FILE_GETUSERINFO, OnFileGetuserinfo)
ON_COMMAND(ID_FILE_SILENCE, OnFileSilence)
ON_COMMAND(ID_FILE_UNSILENCE, OnFileUnsilence)
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChattyApp construction
CChattyApp::CChattyApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
m_chat = NULL;
m_connected = false;
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CChattyApp object
CChattyApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CChattyApp initialization
BOOL CChattyApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
/*
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
*/
// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("GameSpy"));
LoadStdProfileSettings(0); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_CHATTYTYPE,
RUNTIME_CLASS(CChattyDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CChattyView));
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
// Parse command line for standard shell commands, DDE, file open
// Removed for VS .NET
/*
CCommandLineInfo cmdInfo;
cmdInfo.m_nShellCommand = CCommandLineInfo.FileNothing;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
*/
// The main window has been initialized, so show and update it.
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
// No message handlers
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// App command to run the dialog
void CChattyApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CChattyApp message handlers
/*********************
** GLOBAL CALLBACKS **
*********************/
void Raw(CHAT chat, const char * raw, void * param)
{
GSI_UNUSED(chat);
GSI_UNUSED(raw);
GSI_UNUSED(param);
}
void Disconnected(CHAT chat, const char * reason, void * param)
{
OutputDebugString("Disconnected called\n");
char buffer[256];
sprintf(buffer, "You have been disconnected: %s", reason);
theApp.m_pActiveWnd->MessageBox(buffer);
//chatDisconnect(theApp.m_chat);
theApp.m_chat = NULL;
GSI_UNUSED(chat);
GSI_UNUSED(param);
}
void PrivateMessage(CHAT chat, const char * user, const char * message, int type, void * param)
{
OutputDebugString("PrivateMessage called\n");
#ifdef FEEDBACK
CString str = user;
str.MakeLower();
// Ignore of this is from a server.
///////////////////////////////////
if(strstr(str, ".org") || strstr(str, ".net") || strstr(str, ".com"))
return;
char buffer[256];
sprintf(buffer, "%s: %s", user, message);
if(type == CHAT_ACTION)
strcat(buffer, "<action>");
else if(type == CHAT_NOTICE)
strcat(buffer, "<notice>");
theApp.m_pActiveWnd->MessageBox(buffer);
#endif
GSI_UNUSED(param);
GSI_UNUSED(type);
GSI_UNUSED(message);
GSI_UNUSED(user);
GSI_UNUSED(chat);
}
void Invited(CHAT chat, const char * channel, const char * user, void * param)
{
OutputDebugString("Invited called\n");
#ifdef FEEDBACK
char buffer[256];
sprintf(buffer, "%s has invited you to join %s", user, channel);
theApp.m_pActiveWnd->MessageBox(buffer);
#endif
GSI_UNUSED(param);
GSI_UNUSED(user);
GSI_UNUSED(channel);
GSI_UNUSED(chat);
}
void NickErrorCallback(CHAT chat, int type, const char * nick, int numSuggestedNicks, const char ** suggestedNicks, void * param)
{
OutputDebugString("NickErrorCallback called\n");
// Try a new nick.
//////////////////
chatRetryWithNick(chat, "testnick");
GSI_UNUSED(param);
GSI_UNUSED(suggestedNicks);
GSI_UNUSED(numSuggestedNicks);
GSI_UNUSED(nick);
GSI_UNUSED(type);
}
void ConnectCallback(CHAT chat, CHATBool success, int failureReason, void * param)
{
OutputDebugString("ConnectCallback called\n");
if(success)
{
theApp.m_pMainWnd->MessageBox("Connected!");
theApp.m_connected = true;
}
else
{
theApp.m_pMainWnd->MessageBox("Connect Failed!");
theApp.m_connected = false;
}
GSI_UNUSED(param);
GSI_UNUSED(failureReason);
GSI_UNUSED(chat);
}
void CChattyApp::OnFileConnect()
{
if(m_chat == NULL)
{
CConnectDlg dlg;
dlg.m_nick = "Pants";
dlg.m_address = "peerchat." GSI_DOMAIN_NAME;
//dlg.m_address = "baltimore.md.us.undernet.org";
//dlg.m_address = "saltlake.ut.us.undernet.org";
dlg.m_port = 6667;
if(dlg.DoModal() == IDOK)
{
chatGlobalCallbacks callbacks;
memset(&callbacks, 0, sizeof(chatGlobalCallbacks));
callbacks.raw = Raw;
callbacks.disconnected = Disconnected;
callbacks.privateMessage = PrivateMessage;
callbacks.invited = Invited;
m_chat = chatConnect(dlg.m_address, dlg.m_port, dlg.m_nick, "pants", "pants", &callbacks, NickErrorCallback, ConnectCallback, this, CHATTrue);
// Check for a NULL chat object.
// PANTS|05.15.2000
////////////////////////////////
if(!m_chat)
MessageBox(NULL, "chatConnect() failed", NULL, MB_OK);
}
}
}
void CChattyApp::OnFileDisconnect()
{
if(m_chat != NULL)
{
chatDisconnect(m_chat);
m_chat = NULL;
}
}
int CChattyApp::ExitInstance()
{
if(m_chat != NULL)
{
chatDisconnect(m_chat);
m_chat = NULL;
}
return CWinApp::ExitInstance();
}
void CChattyApp::OnFileListchannels()
{
if(theApp.m_chat != NULL)
{
CChannelListDlg dlg;
dlg.DoModal();
}
}
void CChattyApp::OnFileSendraw()
{
if(theApp.m_chat != NULL)
{
CSendRawDlg dlg;
if(dlg.DoModal() == IDOK)
{
chatSendRaw(theApp.m_chat, dlg.m_raw);
}
}
}
void CChattyApp::OnFileGetuserinfo()
{
if(theApp.m_chat != NULL)
{
CGetUserInfoDlg dlg;
dlg.DoModal();
}
}
void CChattyApp::OnFileSilence()
{
if(theApp.m_chat != NULL)
chatSetQuietMode(theApp.m_chat, CHATTrue);
}
void CChattyApp::OnFileUnsilence()
{
if(theApp.m_chat != NULL)
chatSetQuietMode(theApp.m_chat, CHATFalse);
}

View file

@ -0,0 +1,59 @@
// chatty.h : main header file for the CHATTY application
//
#if !defined(AFX_CHATTY_H__D2C88C24_CA2E_4ED3_B08E_BF48F6C0A36B__INCLUDED_)
#define AFX_CHATTY_H__D2C88C24_CA2E_4ED3_B08E_BF48F6C0A36B__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CChattyApp:
// See chatty.cpp for the implementation of this class
//
class CChattyApp : public CWinApp
{
public:
CChattyApp();
CHAT m_chat;
bool m_connected;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChattyApp)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
// Implementation
//{{AFX_MSG(CChattyApp)
afx_msg void OnAppAbout();
afx_msg void OnFileConnect();
afx_msg void OnFileDisconnect();
afx_msg void OnFileListchannels();
afx_msg void OnFileSendraw();
afx_msg void OnFileGetuserinfo();
afx_msg void OnFileSilence();
afx_msg void OnFileUnsilence();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
extern CChattyApp theApp;
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHATTY_H__D2C88C24_CA2E_4ED3_B08E_BF48F6C0A36B__INCLUDED_)

View file

@ -0,0 +1,737 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
"#ifdef _WIN32\r\n"
"LANGUAGE 9, 1\r\n"
"#pragma code_page(1252)\r\n"
"#endif //_WIN32\r\n"
"#include ""res\\chatty.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON DISCARDABLE "res\\chatty.ico"
IDR_CHATTYTYPE ICON DISCARDABLE "res\\chattyDoc.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Toolbar
//
IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15
BEGIN
BUTTON ID_FILE_CONNECT
BUTTON ID_FILE_DISCONNECT
SEPARATOR
BUTTON ID_FILE_LISTCHANNELS
BUTTON ID_FILE_SENDRAW
SEPARATOR
BUTTON ID_FILE_NEW
BUTTON ID_FILE_CLOSE
SEPARATOR
BUTTON ID_CHANNEL_SET_TOPIC
BUTTON ID_CHANNEL_MODE
BUTTON ID_CHANNEL_TALK
BUTTON ID_CHANNEL_PASSWORD
SEPARATOR
BUTTON ID_FILE_GETUSERINFO
SEPARATOR
BUTTON ID_FILE_SILENCE
BUTTON ID_FILE_UNSILENCE
SEPARATOR
BUTTON ID_BUTTON32802
BUTTON ID_BUTTON32803
SEPARATOR
BUTTON ID_FILE_OPEN
BUTTON ID_FILE_SAVE
SEPARATOR
BUTTON ID_EDIT_CUT
BUTTON ID_EDIT_COPY
BUTTON ID_EDIT_PASTE
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MAINFRAME MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Connect...", ID_FILE_CONNECT
MENUITEM "&Disconnect", ID_FILE_DISCONNECT
MENUITEM SEPARATOR
MENUITEM "&Enter...\tCtrl+N", ID_FILE_NEW
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM SEPARATOR
MENUITEM "&List Channels...", ID_FILE_LISTCHANNELS
MENUITEM "&Send Raw...", ID_FILE_SENDRAW
MENUITEM "&Get User Info...", ID_FILE_GETUSERINFO
MENUITEM "&Silence", ID_FILE_SILENCE
MENUITEM "&Unsilence", ID_FILE_UNSILENCE
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Help"
BEGIN
MENUITEM "&About chatty...", ID_APP_ABOUT
END
END
IDR_CHATTYTYPE MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Enter\tCtrl+N", ID_FILE_NEW
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "&Leave", ID_FILE_CLOSE
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
MENUITEM "Save &As...", ID_FILE_SAVE_AS
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
MENUITEM SEPARATOR
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Window"
BEGIN
MENUITEM "&New Window", ID_WINDOW_NEW
MENUITEM "&Cascade", ID_WINDOW_CASCADE
MENUITEM "&Tile", ID_WINDOW_TILE_HORZ
MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
END
POPUP "&Help"
BEGIN
MENUITEM "&About chatty...", ID_APP_ABOUT
END
POPUP "&Channel"
BEGIN
MENUITEM "Set &Topic", ID_CHANNEL_SET_TOPIC
MENUITEM "&Mode", ID_CHANNEL_MODE
MENUITEM "&Talk", ID_CHANNEL_TALK
MENUITEM "&Password", ID_CHANNEL_PASSWORD
MENUITEM "&Get Ban List", ID_CHANNEL_GETBANLIST
END
POPUP "User"
BEGIN
MENUITEM "Get Info", ID_USER_GETINFO
MENUITEM "Kick", ID_USER_KICK
MENUITEM "Ban", ID_USER_BAN
POPUP "Mode"
BEGIN
MENUITEM "Op", ID_USER_MODE_OP
MENUITEM "Voice", ID_USER_MODE_VOICE
MENUITEM "Normal", ID_USER_MODE_NORMAL
END
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL
"X", ID_EDIT_CUT, VIRTKEY, CONTROL
"C", ID_EDIT_COPY, VIRTKEY, CONTROL
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
VK_F6, ID_NEXT_PANE, VIRTKEY
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About chatty"
FONT 8, "MS Sans Serif"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
LTEXT "chatty Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX
LTEXT "Copyright (C) 2000",IDC_STATIC,40,25,119,8
DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP
END
IDD_CHATTY_FORM DIALOG DISCARDABLE 0, 0, 427, 304
STYLE WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
LISTBOX IDC_LIST,7,7,343,173,NOT LBS_NOTIFY |
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
WS_TABSTOP
EDITTEXT IDC_EDIT,7,185,343,13,ES_AUTOHSCROLL | ES_WANTRETURN
LISTBOX IDC_USERS,352,20,68,146,LBS_SORT | LBS_NOINTEGRALHEIGHT |
LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
LISTBOX IDC_CALLBACKS,7,202,415,95,NOT LBS_NOTIFY |
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
WS_HSCROLL | WS_TABSTOP
LTEXT "Num Users:",IDC_STATIC,353,7,38,8
EDITTEXT IDC_NUM_USERS,394,7,26,12,ES_AUTOHSCROLL | ES_READONLY |
ES_NUMBER | NOT WS_BORDER
CONTROL "Hide Stuff",IDC_HIDE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,353,170,47,10
DEFPUSHBUTTON "Send",IDC_SENDBUTT,353,184,50,14
END
IDR_MAINFRAME DIALOG DISCARDABLE 0, 0, 330, 16
STYLE WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "TODO: layout dialog bar ",IDC_STATIC,20,8,300,8
END
IDD_CONNECT DIALOG DISCARDABLE 0, 0, 187, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Connect"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,130,5,50,14
PUSHBUTTON "Cancel",IDCANCEL,130,25,50,14
LTEXT "Nick:",IDC_STATIC,5,9,18,8
LTEXT "Address:",IDC_STATIC,5,24,28,8
LTEXT "Port:",IDC_STATIC,5,39,16,8
EDITTEXT IDC_NICK,45,5,80,12,ES_AUTOHSCROLL
EDITTEXT IDC_ADDRESS,45,20,80,12,ES_AUTOHSCROLL
EDITTEXT IDC_PORT,45,35,80,12,ES_AUTOHSCROLL
END
IDD_ENTER DIALOG DISCARDABLE 0, 0, 186, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,130,5,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
LTEXT "Channel:",IDC_STATIC,5,9,29,8
EDITTEXT IDC_CHANNEL,45,5,80,12,ES_AUTOHSCROLL
LTEXT "Password:",IDC_STATIC,5,30,34,8
EDITTEXT IDC_PASSWORD,45,26,80,12,ES_PASSWORD | ES_AUTOHSCROLL
PUSHBUTTON "istanbul",IDC_QUICK1,7,45,35,14
PUSHBUTTON "montreal",IDC_QUICK2,52,45,35,14
PUSHBUTTON "pants-test",IDC_QUICK3,97,45,35,14
PUSHBUTTON "zurna",IDC_QUICK4,142,45,35,14
END
IDD_SET_TOPIC DIALOG DISCARDABLE 0, 0, 186, 46
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Set Topic"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
LTEXT "Topic:",IDC_STATIC,5,19,21,8
EDITTEXT IDC_TOPIC,30,16,90,12,ES_AUTOHSCROLL
END
IDD_CHANNEL_MODE DIALOG DISCARDABLE 0, 0, 128, 114
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Channel Mode"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,71,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,71,24,50,14
LTEXT "Limit:",IDC_STATIC,7,97,17,8
CONTROL "Invite Only",IDC_INVITE_ONLY,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,7,49,10
CONTROL "Private",IDC_PRIVATE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,22,38,10
CONTROL "Secret",IDC_SECRET,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,37,37,10
CONTROL "Moderated",IDC_MODERATED,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,52,50,10
CONTROL "No External Messages",IDC_NO_EXTERNAL_MESSAGES,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,67,87,10
CONTROL "Only Ops Change Topic",IDC_ONLY_OPS_CHANGE_TOPIC,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,82,91,10
EDITTEXT IDC_LIMIT,30,96,26,12,ES_AUTOHSCROLL
END
IDD_TALK DIALOG DISCARDABLE 0, 0, 186, 47
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Talk"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
LTEXT "Talk:",IDC_STATIC,7,10,17,8
EDITTEXT IDC_MESSAGE,32,7,90,12,ES_AUTOHSCROLL
CONTROL "Normal",IDC_NORMAL,"Button",BS_AUTORADIOBUTTON |
WS_GROUP,7,30,38,10
CONTROL "Action",IDC_ACTION,"Button",BS_AUTORADIOBUTTON,47,30,36,
10
CONTROL "Notice",IDC_NOTICE,"Button",BS_AUTORADIOBUTTON,85,30,37,
10
END
IDD_CHANNEL_LIST DIALOG DISCARDABLE 0, 0, 288, 257
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Channel List"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,231,7,50,14
LISTBOX IDC_LIST,7,24,274,226,LBS_SORT | LBS_NOINTEGRALHEIGHT |
WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Channels",ID_CHANNELS,7,7,41,14
EDITTEXT IDC_FILTER,107,7,96,12,ES_AUTOHSCROLL
EDITTEXT IDC_NUM,209,7,17,12,ES_AUTOHSCROLL | ES_READONLY | NOT
WS_BORDER
DEFPUSHBUTTON "Users",ID_USERS,57,7,44,14
END
IDD_SEND_RAW DIALOG DISCARDABLE 0, 0, 186, 46
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Send Raw"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
LTEXT "Raw:",IDC_STATIC,7,19,18,8
EDITTEXT IDC_RAW,30,16,90,12,ES_AUTOHSCROLL
END
IDD_SET_PASSWORD DIALOG DISCARDABLE 0, 0, 220, 47
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Set Password"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,163,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,163,24,50,14
LTEXT "Password:",IDC_STATIC,7,20,34,8
EDITTEXT IDC_PASSWORD,46,17,76,12,ES_AUTOHSCROLL
CONTROL "Enable",IDC_ENABLE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,125,18,38,10
END
IDD_GET_USER_INFO DIALOG DISCARDABLE 0, 0, 186, 202
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Get User Info"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,23,50,14
LTEXT "Nick:",IDC_STATIC,7,7,18,8
EDITTEXT IDC_NICK,42,7,80,12,ES_AUTOHSCROLL
LTEXT "Address:",IDC_STATIC,7,41,28,8
EDITTEXT IDC_ADDRESS,42,39,80,12,ES_AUTOHSCROLL | ES_READONLY
LISTBOX IDC_CHANNELS,7,85,172,110,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
LTEXT "Channels:",IDC_STATIC,7,73,32,8
DEFPUSHBUTTON "Get Info",ID_GET_INFO,129,7,50,14
LTEXT "Name:",IDC_STATIC,7,23,22,8
EDITTEXT IDC_NAME,42,23,80,12,ES_AUTOHSCROLL | ES_READONLY
LTEXT "User:",IDC_STATIC,7,57,18,8
EDITTEXT IDC_USER,42,54,80,12,ES_AUTOHSCROLL | ES_READONLY
END
IDD_KICK_REASON DIALOG DISCARDABLE 0, 0, 186, 46
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Kick Reason"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
LTEXT "Reason:",IDC_STATIC,7,18,28,8
EDITTEXT IDC_REASON,37,16,83,12,ES_AUTOHSCROLL
END
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "chatty MFC Application\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
VALUE "InternalName", "chatty\0"
VALUE "LegalCopyright", "Copyright (C) 2000\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "chatty.EXE\0"
VALUE "ProductName", "chatty Application\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_CHATTY_FORM, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 420
TOPMARGIN, 7
BOTTOMMARGIN, 297
END
IDD_CONNECT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 180
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_ENTER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 59
END
IDD_SET_TOPIC, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 39
END
IDD_CHANNEL_MODE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 121
TOPMARGIN, 7
BOTTOMMARGIN, 107
END
IDD_TALK, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 40
END
IDD_CHANNEL_LIST, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 281
TOPMARGIN, 7
BOTTOMMARGIN, 250
END
IDD_SEND_RAW, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 39
END
IDD_SET_PASSWORD, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 40
END
IDD_GET_USER_INFO, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 195
END
IDD_KICK_REASON, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 39
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed."
END
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
IDR_MAINFRAME "chatty"
IDR_CHATTYTYPE "\nChatty\nChatty\n\n\nChatty.Document\nChatty Document"
END
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
AFX_IDS_APP_TITLE "chatty"
AFX_IDS_IDLEMESSAGE "Ready"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_INDICATOR_EXT "EXT"
ID_INDICATOR_CAPS "CAP"
ID_INDICATOR_NUM "NUM"
ID_INDICATOR_SCRL "SCRL"
ID_INDICATOR_OVR "OVR"
ID_INDICATOR_REC "REC"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_NEW "Create a new document\nNew"
ID_FILE_OPEN "Open an existing document\nOpen"
ID_FILE_CLOSE "Close the active document\nClose"
ID_FILE_SAVE "Save the active document\nSave"
ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_MRU_FILE1 "Open this document"
ID_FILE_MRU_FILE2 "Open this document"
ID_FILE_MRU_FILE3 "Open this document"
ID_FILE_MRU_FILE4 "Open this document"
ID_FILE_MRU_FILE5 "Open this document"
ID_FILE_MRU_FILE6 "Open this document"
ID_FILE_MRU_FILE7 "Open this document"
ID_FILE_MRU_FILE8 "Open this document"
ID_FILE_MRU_FILE9 "Open this document"
ID_FILE_MRU_FILE10 "Open this document"
ID_FILE_MRU_FILE11 "Open this document"
ID_FILE_MRU_FILE12 "Open this document"
ID_FILE_MRU_FILE13 "Open this document"
ID_FILE_MRU_FILE14 "Open this document"
ID_FILE_MRU_FILE15 "Open this document"
ID_FILE_MRU_FILE16 "Open this document"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_WINDOW_NEW "Open another window for the active document\nNew Window"
ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons"
ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows"
ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows"
ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows"
ID_WINDOW_SPLIT "Split the active window into panes\nSplit"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_EDIT_CLEAR "Erase the selection\nErase"
ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy"
ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut"
ID_EDIT_FIND "Find the specified text\nFind"
ID_EDIT_PASTE "Insert Clipboard contents\nPaste"
ID_EDIT_REPEAT "Repeat the last action\nRepeat"
ID_EDIT_REPLACE "Replace specific text with different text\nReplace"
ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
ID_EDIT_UNDO "Undo the last action\nUndo"
ID_EDIT_REDO "Redo the previously undone action\nRedo"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar"
ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar"
END
STRINGTABLE DISCARDABLE
BEGIN
AFX_IDS_SCSIZE "Change the window size"
AFX_IDS_SCMOVE "Change the window position"
AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents"
END
STRINGTABLE DISCARDABLE
BEGIN
AFX_IDS_SCRESTORE "Restore the window to normal size"
AFX_IDS_SCTASKLIST "Activate Task List"
AFX_IDS_MDICHILD "Activate this window"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_CONNECT "Connect to the chat server\nConnect"
ID_FILE_DISCONNECT "Disconnect from the chat server\nDisconnect"
ID_CHANNEL_SET_TOPIC "Set the channel topic\nTopic"
ID_CHANNEL_MODE "View/Set the channel mode\nMode"
ID_CHANNEL_TALK "Send a message\nTalk"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE 9, 1
#pragma code_page(1252)
#endif //_WIN32
#include "res\chatty.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,586 @@
// chattyDoc.cpp : implementation of the CChattyDoc class
//
#include "stdafx.h"
#include "chatty.h"
#include "chattyDoc.h"
#include "EnterDlg.h"
#include "SetTopicDlg.h"
#include "ChannelModeDlg.h"
#include "TalkDlg.h"
#include "SetPasswordDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChattyDoc
IMPLEMENT_DYNCREATE(CChattyDoc, CDocument)
BEGIN_MESSAGE_MAP(CChattyDoc, CDocument)
//{{AFX_MSG_MAP(CChattyDoc)
ON_COMMAND(ID_CHANNEL_SET_TOPIC, OnChannelSetTopic)
ON_COMMAND(ID_CHANNEL_MODE, OnChannelMode)
ON_COMMAND(ID_CHANNEL_TALK, OnChannelTalk)
ON_COMMAND(ID_CHANNEL_PASSWORD, OnChannelPassword)
ON_COMMAND(ID_CHANNEL_GETBANLIST, OnChannelGetbanlist)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChattyDoc construction/destruction
CChattyDoc::CChattyDoc()
{
m_inChannel = FALSE;
m_hide = FALSE;
}
CChattyDoc::~CChattyDoc()
{
}
/**********************
** CHANNEL CALLBACKS **
**********************/
#if 0
CChattyDoc * pDoc; // Get rid of VA complaints.
#endif
#define DOC CChattyDoc * pDoc;\
pDoc = (CChattyDoc *)param;\
ASSERT(pDoc != NULL);\
if(!pDoc->m_inChannel) { OutputDebugString("Not in channel anymore!\n"); return; }
#define ADD(s) *str += " | ";\
*str += #s;\
*str += "--";\
*str += s;
char __i__[32];
#define ADD_INT(i) *str += " | ";\
*str += #i;\
*str += "--";\
itoa(i, __i__, 10);\
*str += __i__;
void ChannelMessage(CHAT chat, const char * channel, const char * user, const char * message, int type, void * param)
{
OutputDebugString("ChannelMessage called\n");
DOC;
CString * str;
str = new CString("ChannelMessage");
ADD(channel);
ADD(user);
ADD(message);
ADD_INT(type);
pDoc->m_addCallbacks.AddTail(str); // MORE DESCRIPTIVE (SHOW PARAMS)
str = new CString;
if(type == CHAT_MESSAGE)
{
*str = user;
*str += ": ";
*str += message;
}
else if(type == CHAT_ACTION)
{
*str += user;
*str += " ";
*str += message;
}
else
{
*str += user;
*str += "* ";
*str += message;
}
pDoc->m_newStuff.AddTail(str);
GSI_UNUSED(chat);
}
void Kicked(CHAT chat, const char * channel, const char * user, const char * reason, void * param)
{
OutputDebugString("Kicked called\n");
DOC;
// Not in the channel anymore.
//////////////////////////////
pDoc->m_inChannel = FALSE;
POSITION pos = pDoc->GetFirstViewPosition();
pDoc->GetNextView(pos)->GetParentFrame()->DestroyWindow();
GSI_UNUSED(reason);
GSI_UNUSED(user);
GSI_UNUSED(channel);
GSI_UNUSED(chat);
}
void UserJoined(CHAT chat, const char * channel, const char * user, int mode, void * param)
{
OutputDebugString("UserJoined called\n");
DOC;
CString * str;
if(!pDoc->m_hide)
{
str = new CString("UserJoined");
ADD(channel);
ADD(user);
ADD_INT(mode);
pDoc->m_addCallbacks.AddTail(str);
}
CModUsers * mod = new CModUsers;
mod->type = NEW;
mod->nick = user;
mod->mode = mode;
pDoc->m_modUsers.AddTail(mod);
GSI_UNUSED(chat);
}
void UserParted(CHAT chat, const char * channel, const char * user, int why, const char * reason, const char * kicker, void * param)
{
OutputDebugString("UserParted called\n");
DOC;
CString * str;
if(!pDoc->m_hide)
{
str = new CString("UserParted");
ADD(channel);
ADD(user);
ADD_INT(why);
ADD(reason);
ADD(kicker);
pDoc->m_addCallbacks.AddTail(str);
}
CModUsers * mod = new CModUsers;
mod->type = DEL;
mod->nick = user;
pDoc->m_modUsers.AddTail(mod);
GSI_UNUSED(chat);
}
void UserChangedNick(CHAT chat, const char * channel, const char * oldNick, const char * newNick, void * param)
{
OutputDebugString("UserChangedNick called\n");
DOC;
CString * str;
if(!pDoc->m_hide)
{
str = new CString("UserChangedNick");
ADD(channel);
ADD(oldNick);
ADD(newNick);
pDoc->m_addCallbacks.AddTail(str);
}
CModUsers * mod = new CModUsers;
mod->type = RENAME;
mod->nick = oldNick;
mod->newNick = newNick;
pDoc->m_modUsers.AddTail(mod);
GSI_UNUSED(chat);
}
void UserModeChanged(CHAT chat, const char * channel, const char * user, int mode, void * param)
{
OutputDebugString("UserModeChanged called\n");
DOC;
CString *str;
str = new CString("UserModeChanged");
ADD(channel);
ADD(user);
ADD_INT(mode);
pDoc->m_addCallbacks.AddTail(str);
CModUsers * mod = new CModUsers;
mod->type = MODE;
mod->nick = user;
mod->mode = mode;
pDoc->m_modUsers.AddTail(mod);
GSI_UNUSED(chat);
}
void TopicChanged(CHAT chat, const char * channel, const char * topic, void * param)
{
OutputDebugString("TopicChanged called\n");
DOC;
CString * str;
str = new CString("TopicChanged");
ADD(channel);
ADD(topic);
pDoc->m_addCallbacks.AddTail(str);
CString title = channel;
title += " - ";
title += topic;
pDoc->SetTitle(title);
pDoc->m_topic = topic;
GSI_UNUSED(chat);
}
void ChannelModeChanged(CHAT chat, const char * channel, CHATChannelMode * mode, void * param)
{
OutputDebugString("ChannelModeChanged called\n");
DOC;
CString * str;
str = new CString("ChannelModeChanged");
ADD(channel);
ADD_INT(mode->InviteOnly);
ADD_INT(mode->Limit);
ADD_INT(mode->Moderated);
ADD_INT(mode->NoExternalMessages);
ADD_INT(mode->OnlyOpsChangeTopic);
ADD_INT(mode->Private);
ADD_INT(mode->Secret);
pDoc->m_addCallbacks.AddTail(str);
str = new CString("Channel Mode Changed");
pDoc->m_newStuff.AddTail(str);
GSI_UNUSED(chat);
}
void UserListUpdated(CHAT chat, const char * channel, void * param)
{
OutputDebugString("UserListUpdated called\n");
DOC;
CString * str;
if(!pDoc->m_hide)
{
str = new CString("UserListUpdated");
ADD(channel);
pDoc->m_addCallbacks.AddTail(str);
}
GSI_UNUSED(chat);
}
void EnumUsersCallback(CHAT chat, CHATBool success, const char * channel, int numUsers, const char ** users, int * modes, void * param)
{
OutputDebugString("EnumUsersCallback called\n");
CChattyDoc * pDoc = (CChattyDoc *)param;
if(success)
{
pDoc->m_numUsers = numUsers;
int i;
for(i = 0 ; i < numUsers ; i++)
{
CModUsers * mod = new CModUsers;
ASSERT(mod != NULL);
mod->type = NEW;
mod->nick = users[i];
mod->mode = modes[i];
pDoc->m_modUsers.AddTail(mod);
}
}
GSI_UNUSED(chat);
GSI_UNUSED(channel);
}
void EnterChannelCallback(CHAT chat, CHATBool success, CHATEnterResult result, const char * channel, void * param)
{
OutputDebugString("EnterChannelCallback called\n");
CChattyDoc * pDoc = (CChattyDoc *)param;
// Check for success or failure.
////////////////////////////////
if(success)
{
pDoc->m_inChannel = TRUE;
// Get the inital list of users.
////////////////////////////////
DWORD before = GetTickCount();
chatEnumUsers(theApp.m_chat, channel, EnumUsersCallback, pDoc, CHATTrue);
DWORD after = GetTickCount();
char buffer[128];
sprintf(buffer, "%dms to enum %d users in %s\n", after - before, pDoc->m_numUsers, pDoc->m_channelName);
OutputDebugString(buffer);
}
GSI_UNUSED(chat);
GSI_UNUSED(result);
}
BOOL CChattyDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// Check for no connection.
///////////////////////////
if(theApp.m_chat == NULL)
return FALSE;
// Set the dialog defaults.
///////////////////////////
CEnterDlg dlg;
//dlg.m_channel = "#test";
//dlg.m_channel = "#montreal";
dlg.m_channel = "#istanbul";
dlg.m_password = "";
// Go modal.
////////////
int rcode = dlg.DoModal();
// Check for a cancel.
//////////////////////
if(rcode != IDOK)
return FALSE;
// Setup the callbacks.
///////////////////////
chatChannelCallbacks callbacks;
memset(&callbacks, 0, sizeof(chatChannelCallbacks));
callbacks.channelMessage = ChannelMessage;
callbacks.channelModeChanged = ChannelModeChanged;
callbacks.kicked = Kicked;
callbacks.topicChanged = TopicChanged;
callbacks.userParted = UserParted;
callbacks.userJoined = UserJoined;
callbacks.userListUpdated = UserListUpdated;
callbacks.userModeChanged = UserModeChanged;
callbacks.userChangedNick = UserChangedNick;
callbacks.param = this;
// Join the group.
//////////////////
if(dlg.m_quickChannel != "")
m_channelName = dlg.m_quickChannel;
else
m_channelName = dlg.m_channel;
chatEnterChannel(theApp.m_chat, m_channelName, dlg.m_password, &callbacks, EnterChannelCallback, this, CHATTrue);
// Check for failure.
/////////////////////
if(!m_inChannel)
return FALSE;
// Set the name.
////////////////
SetTitle(m_channelName);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CChattyDoc serialization
void CChattyDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CChattyDoc diagnostics
#ifdef _DEBUG
void CChattyDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CChattyDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CChattyDoc commands
void CChattyDoc::OnCloseDocument()
{
// Did we ever get in the channel?
//////////////////////////////////
if(m_inChannel)
{
if(theApp.m_chat != NULL)
{
// Leave the channel.
/////////////////////
chatLeaveChannel(theApp.m_chat, m_channelName, NULL);
OutputDebugString("LEFT channel\n");
}
m_inChannel = FALSE;
}
CDocument::OnCloseDocument();
}
void CChattyDoc::OnChannelSetTopic()
{
if(theApp.m_chat != NULL)
{
CSetTopicDlg dlg;
dlg.m_topic = m_topic;
if(dlg.DoModal() == IDOK)
{
chatSetChannelTopic(theApp.m_chat, m_channelName, dlg.m_topic);
}
}
}
void GetChannelModeCallback(CHAT chat, CHATBool success, const char * channel, CHATChannelMode * mode, void * param)
{
CHATChannelMode * modeParam = (CHATChannelMode *)param;
*modeParam = *mode;
GSI_UNUSED(chat);
GSI_UNUSED(channel);
GSI_UNUSED(success);
}
void CChattyDoc::OnChannelMode()
{
if(theApp.m_chat != NULL)
{
CHATChannelMode mode;
// Get the channel mode.
////////////////////////
chatGetChannelMode(theApp.m_chat, m_channelName, GetChannelModeCallback, &mode, CHATTrue);
// Setup the dlg.
/////////////////
CChannelModeDlg dlg;
dlg.m_inviteOnly = mode.InviteOnly;
dlg.m_private = mode.Private;
dlg.m_secret = mode.Secret;
dlg.m_moderated = mode.Moderated;
dlg.m_noExternalMessages = mode.NoExternalMessages;
dlg.m_onlyOpsChangeTopic = mode.OnlyOpsChangeTopic;
dlg.m_limit = mode.Limit;
// Show the dlg.
////////////////
if(dlg.DoModal() == IDOK)
{
// Copy back the new mode.
//////////////////////////
mode.InviteOnly = (CHATBool)dlg.m_inviteOnly;
mode.Private = (CHATBool)dlg.m_private;
mode.Secret = (CHATBool)dlg.m_secret;
mode.Moderated = (CHATBool)dlg.m_moderated;
mode.NoExternalMessages = (CHATBool)dlg.m_noExternalMessages;
mode.OnlyOpsChangeTopic = (CHATBool)dlg.m_onlyOpsChangeTopic;
mode.Limit = (CHATBool)dlg.m_limit;
// Set the mode.
////////////////
chatSetChannelMode(theApp.m_chat, m_channelName, &mode);
}
}
}
void CChattyDoc::OnChannelTalk()
{
if(theApp.m_chat != NULL)
{
CTalkDlg dlg;
dlg.m_type = 0;
if(dlg.DoModal() == IDOK)
{
int type;
if(dlg.m_type == 0)
type = CHAT_NORMAL;
else if(dlg.m_type == 1)
type = CHAT_ACTION;
else
type = CHAT_NOTICE;
chatSendChannelMessage(theApp.m_chat, m_channelName, dlg.m_message, type);
}
}
}
void GetChannelPasswordCallback(CHAT chat, CHATBool success, const char * channel, CHATBool enabled, const char * password, void * param)
{
CSetPasswordDlg * dlg = (CSetPasswordDlg *)param;
if(success)
{
dlg->m_password = password;
dlg->m_enable = enabled;
}
else
{
dlg->m_password = "";
dlg->m_enable = FALSE;
}
GSI_UNUSED(channel);
GSI_UNUSED(chat);
}
void CChattyDoc::OnChannelPassword()
{
if(theApp.m_chat != NULL)
{
CSetPasswordDlg dlg;
chatGetChannelPassword(theApp.m_chat, m_channelName, GetChannelPasswordCallback, &dlg, CHATTrue);
if(dlg.DoModal() == IDOK)
{
chatSetChannelPassword(theApp.m_chat, m_channelName, (CHATBool)dlg.m_enable, dlg.m_password);
}
}
}
void EnumChannelBansCallback(CHAT chat, CHATBool success, const char * channel, int numBans, const char ** bans, void * param)
{
DOC;
int i;
pDoc->m_newStuff.AddTail(new CString("Bans:"));
for(i = 0 ; i < numBans ; i++)
{
pDoc->m_newStuff.AddTail(new CString(bans[i]));
}
GSI_UNUSED(channel);
GSI_UNUSED(success);
GSI_UNUSED(chat);
}
void CChattyDoc::OnChannelGetbanlist()
{
if(theApp.m_chat != NULL)
{
chatEnumChannelBans(theApp.m_chat, m_channelName, EnumChannelBansCallback, this, CHATFalse);
}
}

View file

@ -0,0 +1,80 @@
// chattyDoc.h : interface of the CChattyDoc class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_CHATTYDOC_H__A9A7E462_6E3D_4AE0_9DF8_355AE2D28FBC__INCLUDED_)
#define AFX_CHATTYDOC_H__A9A7E462_6E3D_4AE0_9DF8_355AE2D28FBC__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define NEW 1
#define DEL 2
#define RENAME 3
#define MODE 4
struct CModUsers
{
int type;
CString nick;
CString newNick;
int mode;
};
class CChattyDoc : public CDocument
{
protected: // create from serialization only
CChattyDoc();
DECLARE_DYNCREATE(CChattyDoc)
// Attributes
public:
BOOL m_inChannel;
CString m_channelName;
CList <CString *, CString *> m_newStuff;
CString m_topic;
CList <CString *, CString *> m_addCallbacks;
CList <CModUsers *, CModUsers *> m_modUsers;
BOOL m_hide;
int m_numUsers;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChattyDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
virtual void OnCloseDocument();
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CChattyDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CChattyDoc)
afx_msg void OnChannelSetTopic();
afx_msg void OnChannelMode();
afx_msg void OnChannelTalk();
afx_msg void OnChannelPassword();
afx_msg void OnChannelGetbanlist();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHATTYDOC_H__A9A7E462_6E3D_4AE0_9DF8_355AE2D28FBC__INCLUDED_)

View file

@ -0,0 +1,391 @@
// chattyView.cpp : implementation of the CChattyView class
//
#include "stdafx.h"
#include "chatty.h"
#include "chattyDoc.h"
#include "chattyView.h"
#include "TalkDlg.h"
#include "KickReasonDlg.h"
#include "GetUserInfoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChattyView
IMPLEMENT_DYNCREATE(CChattyView, CFormView)
BEGIN_MESSAGE_MAP(CChattyView, CFormView)
//{{AFX_MSG_MAP(CChattyView)
ON_WM_CREATE()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_HIDE, OnHide)
ON_LBN_SELCHANGE(IDC_CALLBACKS, OnSelchangeCallbacks)
ON_LBN_DBLCLK(IDC_USERS, OnDblclkUsers)
ON_COMMAND(ID_USER_BAN, OnUserBan)
ON_COMMAND(ID_USER_GETINFO, OnUserGetinfo)
ON_COMMAND(ID_USER_KICK, OnUserKick)
ON_COMMAND(ID_USER_MODE_OP, OnUserModeOp)
ON_COMMAND(ID_USER_MODE_VOICE, OnUserModeVoice)
ON_COMMAND(ID_USER_MODE_NORMAL, OnUserModeNormal)
ON_BN_CLICKED(IDC_SENDBUTT, OnSendbutt)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChattyView construction/destruction
CChattyView::CChattyView()
: CFormView(CChattyView::IDD)
{
//{{AFX_DATA_INIT(CChattyView)
m_edit = _T("");
m_hide = FALSE;
//}}AFX_DATA_INIT
// TODO: add construction code here
}
CChattyView::~CChattyView()
{
}
void CChattyView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChattyView)
DDX_Control(pDX, IDC_NUM_USERS, m_numUsers);
DDX_Control(pDX, IDC_CALLBACKS, m_callbacks);
DDX_Control(pDX, IDC_USERS, m_users);
DDX_Control(pDX, IDC_LIST, m_list);
DDX_Text(pDX, IDC_EDIT, m_edit);
DDX_Check(pDX, IDC_HIDE, m_hide);
//}}AFX_DATA_MAP
}
BOOL CChattyView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
}
void CChattyView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
ResizeParentToFit();
SetTimer(100, 50, NULL);
}
/////////////////////////////////////////////////////////////////////////////
// CChattyView diagnostics
#ifdef _DEBUG
void CChattyView::AssertValid() const
{
CFormView::AssertValid();
}
void CChattyView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CChattyDoc* CChattyView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CChattyDoc)));
return (CChattyDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CChattyView message handlers
int CChattyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CChattyView::OnTimer(UINT nIDEvent)
{
if(nIDEvent == 100)
{
CChattyDoc * pDoc = GetDocument();
if(pDoc != NULL)
{
CString * str;
while(!pDoc->m_newStuff.IsEmpty())
{
str = pDoc->m_newStuff.GetHead();
pDoc->m_newStuff.RemoveHead();
m_list.InsertString(0, *str);
delete str;
}
while(!pDoc->m_addCallbacks.IsEmpty())
{
str = pDoc->m_addCallbacks.GetHead();
pDoc->m_addCallbacks.RemoveHead();
m_callbacks.InsertString(0, *str);
delete str;
}
CModUsers * mod;
CString name;
CString newName;
UINT index;
while(!pDoc->m_modUsers.IsEmpty())
{
mod = pDoc->m_modUsers.GetHead();
pDoc->m_modUsers.RemoveHead();
if(mod->type == NEW)
{
name = mod->nick;
if(mod->mode & CHAT_OP)
name.Insert(0, '@');
else if(mod->mode & CHAT_VOICE)
name.Insert(0, '?');
m_users.AddString(name);
}
else if(mod->type == DEL)
{
name = mod->nick;
index = m_users.FindStringExact(-1, name);
if(index == LB_ERR)
index = m_users.FindStringExact(-1, '@' + name);
if(index == LB_ERR)
index = m_users.FindStringExact(-1, '?' + name);
if(index == LB_ERR)
ASSERT(0);
m_users.DeleteString(index);
}
else if(mod->type == RENAME)
{
name = mod->nick;
newName = "";
index = m_users.FindStringExact(-1, name);
if(index == LB_ERR)
{
newName = '@';
index = m_users.FindStringExact(-1, '@' + name);
}
if(index == LB_ERR)
{
newName = '?';
index = m_users.FindStringExact(-1, '?' + name);
}
if(index == LB_ERR)
ASSERT(0);
m_users.DeleteString(index);
newName += mod->newNick;
m_users.AddString(newName);
}
else if(mod->type == MODE)
{
name = mod->nick;
index = m_users.FindStringExact(-1, name);
if(index == LB_ERR)
index = m_users.FindStringExact(-1, '@' + name);
if(index == LB_ERR)
index = m_users.FindStringExact(-1, '?' + name);
if(index == LB_ERR)
ASSERT(0);
m_users.DeleteString(index);
if(mod->mode & CHAT_OP)
name.Insert(0, '@');
else if(mod->mode & CHAT_VOICE)
name.Insert(0, '?');
m_users.AddString(name);
}
else
ASSERT(0);
delete mod;
}
char buf[16];
itoa(m_users.GetCount(), buf, 10);
m_numUsers.SetWindowText(buf);
}
SetTimer(100, 50, NULL);
}
CFormView::OnTimer(nIDEvent);
}
void CChattyView::OnHide()
{
UpdateData();
GetDocument()->m_hide = m_hide;
}
void CChattyView::OnSelchangeCallbacks()
{
UpdateData();
m_callbacks.GetText(m_callbacks.GetCurSel(), m_edit);
UpdateData(FALSE);
}
void CChattyView::OnDblclkUsers()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
CTalkDlg dlg;
dlg.m_type = 0;
if(dlg.DoModal() == IDOK)
chatSendUserMessage(theApp.m_chat, user, dlg.m_message, dlg.m_type);
}
}
}
void CChattyView::OnUserBan()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
chatBanUser(theApp.m_chat, GetDocument()->m_channelName, user);
}
}
}
void CChattyView::OnUserGetinfo()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
CGetUserInfoDlg dlg;
dlg.m_user = user;
dlg.DoModal();
}
}
}
void CChattyView::OnUserKick()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
CKickReasonDlg dlg;
if(dlg.DoModal() == IDOK)
{
chatKickUser(theApp.m_chat, GetDocument()->m_channelName, user, dlg.m_reason);
}
}
}
}
void CChattyView::OnUserModeOp()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
chatSetUserMode(theApp.m_chat, GetDocument()->m_channelName, user, CHAT_OP);
}
}
}
void CChattyView::OnUserModeVoice()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
chatSetUserMode(theApp.m_chat, GetDocument()->m_channelName, user, CHAT_VOICE);
}
}
}
void CChattyView::OnUserModeNormal()
{
if(theApp.m_chat != NULL)
{
int index = m_users.GetCurSel();
if(index != LB_ERR)
{
CString user;
m_users.GetText(index, user);
if((user.Left(1) == "@") || (user.Left(1) == "?"))
user = user.Mid(1);
chatSetUserMode(theApp.m_chat, GetDocument()->m_channelName, user, CHAT_NORMAL);
}
}
}
void CChattyView::OnSendbutt()
{
// TODO: Add your control notification handler code here
if(theApp.m_chat != NULL)
{
UpdateData();
chatSendChannelMessage(theApp.m_chat, GetDocument()->m_channelName, (LPCSTR)m_edit,CHAT_MESSAGE);
m_edit.Empty();
UpdateData(FALSE);
}
}

View file

@ -0,0 +1,86 @@
// chattyView.h : interface of the CChattyView class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_CHATTYVIEW_H__E1B25967_4DA7_4ABD_A404_9C60D59E1C60__INCLUDED_)
#define AFX_CHATTYVIEW_H__E1B25967_4DA7_4ABD_A404_9C60D59E1C60__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CChattyView : public CFormView
{
protected: // create from serialization only
CChattyView();
DECLARE_DYNCREATE(CChattyView)
public:
//{{AFX_DATA(CChattyView)
enum { IDD = IDD_CHATTY_FORM };
CEdit m_numUsers;
CListBox m_callbacks;
CListBox m_users;
CListBox m_list;
CString m_edit;
BOOL m_hide;
//}}AFX_DATA
// Attributes
public:
CChattyDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChattyView)
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnInitialUpdate(); // called first time after construct
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CChattyView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CChattyView)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnHide();
afx_msg void OnSelchangeCallbacks();
afx_msg void OnDblclkUsers();
afx_msg void OnUserBan();
afx_msg void OnUserGetinfo();
afx_msg void OnUserKick();
afx_msg void OnUserModeOp();
afx_msg void OnUserModeVoice();
afx_msg void OnUserModeNormal();
afx_msg void OnSendbutt();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in chattyView.cpp
inline CChattyDoc* CChattyView::GetDocument()
{ return (CChattyDoc*)m_pDocument; }
#endif
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHATTYVIEW_H__E1B25967_4DA7_4ABD_A404_9C60D59E1C60__INCLUDED_)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,13 @@
//
// CHATTY.RC2 - resources Microsoft Visual C++ does not edit directly
//
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Add manually edited resources here...
/////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,91 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by chatty.rc
//
#define ID_CHANNELS 2
#define ID_GET_INFO 2
#define ID_USERS 3
#define IDD_ABOUTBOX 100
#define IDD_CHATTY_FORM 101
#define IDP_SOCKETS_INIT_FAILED 104
#define IDR_MAINFRAME 128
#define IDR_CHATTYTYPE 129
#define IDD_SET_TOPIC 130
#define IDD_CHANNEL_MODE 131
#define IDD_CONNECT 132
#define IDD_ENTER 133
#define IDD_TALK 134
#define IDD_CHANNEL_LIST 136
#define IDD_SEND_RAW 137
#define IDD_SET_PASSWORD 138
#define IDD_GET_USER_INFO 139
#define IDD_KICK_REASON 140
#define IDC_LIST 1000
#define IDC_EDIT 1001
#define IDC_TOPIC 1002
#define IDC_USERS 1002
#define IDC_NICK 1003
#define IDC_INVITE_ONLY 1003
#define IDC_CALLBACKS 1003
#define IDC_ADDRESS 1004
#define IDC_PASSWORD 1004
#define IDC_PRIVATE 1004
#define IDC_PORT 1005
#define IDC_CHANNEL 1005
#define IDC_SECRET 1005
#define IDC_USER 1005
#define IDC_MODERATED 1006
#define IDC_NO_EXTERNAL_MESSAGES 1007
#define IDC_ONLY_OPS_CHANGE_TOPIC 1008
#define IDC_LIMIT 1009
#define IDC_MESSAGE 1010
#define IDC_NORMAL 1012
#define IDC_ACTION 1013
#define IDC_NOTICE 1014
#define IDC_NUM_USERS 1015
#define IDC_HIDE 1016
#define IDC_FILTER 1018
#define IDC_RAW 1019
#define IDC_ENABLE 1020
#define IDC_NUM 1021
#define IDC_NAME 1023
#define IDC_CHANNELS 1025
#define IDC_QUICK1 1026
#define IDC_QUICK2 1027
#define IDC_REASON 1027
#define IDC_QUICK3 1028
#define IDC_SENDBUTT 1028
#define IDC_QUICK4 1029
#define ID_FILE_CONNECT 32771
#define ID_FILE_DISCONNECT 32772
#define ID_CHANNEL_SET_TOPIC 32776
#define ID_CHANNEL_MODE 32778
#define ID_CHANNEL_TALK 32781
#define ID_BUTTON32782 32782
#define ID_FILE_LISTCHANNELS 32783
#define ID_FILE_SENDRAW 32784
#define ID_CHANNEL_PASSWORD 32786
#define ID_FILE_GETUSERINFO 32789
#define ID_USER_GETINFO 32790
#define ID_USER_KICK 32792
#define ID_USER_BAN 32793
#define ID_USER_MODE_OP 32796
#define ID_USER_MODE_VOICE 32798
#define ID_USER_MODE_NORMAL 32800
#define ID_CHANNEL_GETBANLIST 32801
#define ID_BUTTON32802 32802
#define ID_BUTTON32803 32803
#define ID_FILE_SILENCE 32804
#define ID_FILE_UNSILENCE 32805
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 141
#define _APS_NEXT_COMMAND_VALUE 32806
#define _APS_NEXT_CONTROL_VALUE 1029
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,182 @@
Changelog for: GameSpy Presence & Messaging SDK
--------------------------------------------------------
DATE VERSION BY TYPE DESCRIPTION
---------- ------- --- ------- ---------------------------------------------------------
12-12-2007 1.13.00 RMV RELEASE Released to Developer Site
12-12-2007 1.12.15 RMV OTHER Updated gptest app to include block list functions and cleaned up buddy messaging
12-05-2007 1.12.14 SN OTHER Added test for searching unique nickes across namespaces
11-27-2007 1.12.13 SAH CLEANUP Moved extern "c" block below includes to prevent linker errors
11-19-2007 1.12.12 SAH OTHER Marked gpFindPlayers and gpSetInvitableGames as DEPRECATED
SAH CLEANUP Removed gpFindPlayers and gpSetInvitableGames from MFC app
11-13-2007 1.12.11 SAH OTHER Modified GP MFC App to support Blocked Lists
SAH FIX Fixed bug where blocked list was deleted from disabling info cache
11-12-2007 1.12.10 MWJ FEATURE Added/updated Add/Remove Block List error messages
11-09-2007 1.12.09 SAH CLEANUP Switched to using a darray for NP Id lookup transactions
SAH FIX Fixed NP Block List Add to keep trying if NP returns busy
11-08-2007 1.12.08 SAH CLEANUP Removed gpGetBlockedList to replace with more consistent functions
SAH FEATURE Added gpGetNumBlocked, gpGetBlockedProfile, gpIsBlocked
11-05-2007 1.12.07 SAH FEATURE Added NP Block List mirroring for gpAddtoBlockedList
SAH FEATURE Added initial support for PS3 NP Block List Syncing
10-30-2007 1.12.06 SAH FEATURE Added BlockedList support and buddy/block list retrieval upon login
SAH FIX Fixed bug causing infoCache to not save when disconnect called before destroy
SAH FIX Fixed memory leak from infoCacheBuddyOnly not freeing up status data
10-23-2007 1.12.05 SAH FIX Fixed NP Sync so it only destroys NP if GP was the one that initialized it
10-11-2007 1.12.04 SAH FIX Fixed gpiPS3.c to use gpSendBuddyRequest to remove errors using GSI_UNICODE
09-14-2007 1.12.03 SAH FEATURE Added initial support for PS3 NP Buddy Syncing
SAH FIX Fixed two bugs in gpSearch.c - searches causing assert and missing unicode support
09-11-2007 1.12.02 DES FEATURE Added support for a search by uniquenick across multiple namespaces
08-23-2007 1.12.01 SAH OTHER Added gpRegisterCdKey to gptest MFC sample
08-06-2007 1.12.00 RMV RELEASE Released to Developer Site
07-27-2007 1.11.03 BED FEATURE Added gpRegisterCdKey
07-19-2007 1.11.02 SAH FIX Added explicit typecasts to remove compiler warnings, Fixed DS project
07-10-2007 1.11.01 RMV FIX Fixed gptest/gptestc Project files to get rid of Unicode warnings
RMV FIX Fixed memory allocation to prevent possible use of uninitialized pointer in gp.c
06-07-2007 1.11.00 SN RELEASE Releasing to developer site
06-07-2007 1.11.00 SN FEATURE Added newer style buddy status info
SN FEATURE Replaced old TCP peer to peer code with UDP Layer
SN FEATURE Added keys/values pair feature
05-22-2007 1.10.05 DES FEATURE Added gpGetInfoNoWait
05-17-2007 1.10.04 DES FIX Added a few explicit casts to avoid warnings
02-21-2007 1.10.03 SN FEATURE Added a version of get reverse buddies that allows a specified list of profiles to be passed in.
01-16-2007 1.10.02 DES FEATURE Added X360 support
12-21-2006 1.10.01 DES FEATURE Added initial support for quiet mode
12-15-2006 1.10.00 MJW RELEASE Released to Developer Site
12-13-2006 1.09.69 SN FIX Removed connection state change to allow the internal disconnect function to change the state
10-05-2006 1.09.68 SAH FIX Updated MacOSX Makefile
09-28-2006 1.09.67 SAH FIX Fixed PS3 project to work with PS3 095.00x SDK; changed included libaries in linker input.
08-07-2006 1.09.66 SAH FIX fixed gpGetBuddyStatus to set 'status' output to '\0' if it encounters NULL data
08-04-2006 1.09.65 SAH OTHER Changed ctime/gmtime calls to gsi time wrapper calls
08-03-2006 1.09.64 DDW FEATURE Added support for automatic login ticket renewal
08-02-2006 1.09.63 DDW OTHER Added productID to GUI for gptest sample
08-02-2006 1.09.62 SAH RELEASE Releasing to developer site
07-31-2006 1.09.62 SAH FIX Fixed PS3 project file - added post-build step to create *.SELF for execution
07-25-2006 1.09.61 SAH FIX Fixed NITRO project, include for crt0.o now above others so it add correct file
07-24-2006 1.09.60 SAH FIX Removed #ifdef _PS3 for socket calls (changed platformSocket.h to typecast calls)
07-06-2006 1.09.59 SAH FIX Fixed PSP project file to not explicitly include the PSP linker file
06-30-2006 1.09.58 SAH FIX Fixed NITRO project & linker command file (to work with CW 2.0/NitroSDK 3.1)
SAH FIX Fixed Linux makefile
06-27-2006 1.09.57 SAH FIX Removed unused variables in gpiInfo.c and gpiSearch.c
06-26-2006 1.09.56 BMS FEATURE Passwords no longer go over the wire in cleartext
05-31-2006 1.09.55 SAH RELEASE Releasing to developer site
SAH FIX Fixed Linux makefile
05-30-2006 1.09.54 SAH FIX Fixed PS3 project to work with newest PS3(084_001 SDK) release
05-25-2006 1.09.53 SAH FIX Added PS3 required typecasts
SAH FIX Changed PSP project warning levels
SAH FIX Fixed PS3 project to compile with 084_001 SDK
05-22-2006 1.09.52 SAH FIX Added GSI_UNUSED calls to get rid of codewarrior warnings
05-19-2006 1.09.51 SAH FIX Added gsTestMain.c to nitro CodeWarrior project
05-15-2006 1.09.50 SAH FIX Added "PS3 Release" configuration to project
05-08-2006 1.09.49 SAH FIX Changed some sprintf calls on empty string to strcpy
04-27-2006 1.09.48 BMS FEATURE Updates to Fedreg implementation: login and profile update also needed partner ID.
04-25-2006 1.09.47 SAH RELEASE Releasing to developer site
04-24-2006 1.09.47 SAH FIX Fixed Nitro project files to work on build machine
04-13-2006 1.09.46 SAH FIX Replaced all (rcode == SOCKET_ERROR) w/ (gsiSocketIsError(rcode))
04-12-2006 1.09.45 BMS FEATURE Updates for Fedreg. Includes new partner ID parameter on gpInitialize.
02-27-2006 1.09.44 SN FIX Added check to determine if hard coded IP was used for connection manager
02-03-2006 1.09.43 SN FIX Added checks for character string limits within gpConnectNewUser
01-26-2006 1.09.42 SN FIX Added psp prodg solution and project to sgv
01-19-2006 1.09.42 RH FIX Changed gpSendBuddyUTM message type from char * to gsi_char *.
12-16-2005 1.09.41 SN OTHER Cleaned up projects to missing common code if any
12-12-2005 1.09.40 SN FIX Removed connection closed check, eliminating false timeouts
11-18-2005 1.09.40 SN FEATURE Added timeout errors to searches which are non-fatal.
11-17-2005 1.09.39 DES FIX Updated Nitro Makefile.
DES FIX Fixed Unicode incompatibility in gptestc.
11-14-2005 1.09.38 DES FIX Updated the OSX Makefile.
DES FEATURE Added support for GSI_DOMAIN_NAME
11-03-2005 1.09.37 BED FEATURE Added ps3 makefile.
09-21-2005 1.09.36 DES FEATURE Updated DS support
DES FEATURE Updated to use the common debug code
DES FIX All connection operation errors are now fatal errors
DES CLEANUP Cleaned up gptestc and added a firewall option
09-16-2005 1.09.35 BED FEATURE Added a callback for buddy revoke notifications.
08-19-2005 1.09.34 BED FIX Update linux makefile
08-11-2005 1.09.33 BED FEATURE Added support for Buddy UTMs (part one, text messages on separate channel)
07-28-2005 1.09.32 SN RELEASE Releasing to developer site.
07-27-2005 1.09.32 SN FEATURE Added support for new style responses for both gpdeleteprofile and buddy authorizations.
06-03-2005 1.09.31 SN RELEASE Releasing to developer site.
05-26-2005 1.09.31 SN FIX Fixed the setinfo function that sent passwords in clear text. Now passwords are encrypted for security purposes.
05-05-2005 1.09.30 BED FIX Updated projects to use new common folder
04-29-2005 1.09.29 SN OTHER Created a Visual Studio .NET project
04-28-2005 1.09.29 SN RELEASE Releasing to developer site.
04-27-2005 1.09.29 DES RELEASE Limited release to Nintendo DS developers.
04-27-2005 1.09.29 DES CLEANUP Extra printfs in gptestc.
DES FEATURE Always assume a firewall on the DS.
04-25-2005 1.09.28 DES FIX Cleaned up a Nitro warning.
DES CLEANUP General cleanup of gptestc.
DES CLEANUP Disable Win32 linker warning.
04-04-2005 1.09.27 SN RELEASE Releasing to developer site.
04-01-2005 1.09.27 DDW FIX Use gsi_time in transfer file structure to match nonport definition
03-30-2005 1.09.26 SN FIX Changed size of unique nick to match DB size plus null character
03-30-2005 1.09.25 SN FIX Fixed case where time was of type long instead of 32 bit int
03-28-2005 1.09.24 SN FIX Fixed bug with all transfers being deleted when deleting only those associated with a single peer
03-18-2005 1.09.24 DES FIX Fixed typo in parameter explanation.
03-14-2005 1.09.23 DES FEATURE Nintendo DS support
12-28-2004 1.09.22 SN FIX Added const qualifiers to function parameters not modified
09-24-2004 1.09.21 BED FIX SDK now allows you to delete buddies that it doesn't have a status for.
09-16-2004 1.09.20 SN RELEASE Releasing to developer site.
08-31-2004 1.09.20 SN FIX Added call to reset the GP internal connection structure fixing memory leaks
08-27-2004 1.09.19 DES CLEANUP Removed MacOS style includes
DES CLEANUP Removed headers already included in nonport.h
XGD bug in caching profile marketing info
DES CLEANUP Updated Win32 project configurations
DES CLEANUP Fixed warnings under OSX
DES CLEANUP Updated OSX Makefile
08-05-2004 1.09.18 SN RELEASE Releasing to developer site.
07-19-2004 1.09.18 SN FIX Updated code with explicit casts to remove implicit cast error
when compiling at highest level and warnings treated as errors.
06-25-2004 1.09.18 BED FEATURE Added location string to gpInvitePlayer
06-24-2004 1.09.17 BED FEATURE Now encrypting password and cdkey for gpNewUser
06-18-2004 1.09.16 BED RELEASE Releasing to developer site.
06-17-2004 1.09.16 DDW FEATURE Added login ticket support
06-16-2004 1.09.15 BED FEATURE Added PS2 Insock support
05-20-2004 1.09.14 BED RELEASE Releasing to developer site.
05-20-2004 1.09.14 BED FEATURE Added state GP_INFO_CACHING_BUDDY_ONLY.
04-05-2004 1.09.13 BED FIX Fixed small allocation bug in Unicode interface.
03-30-2004 1.09.12 BED FIX Removed misc compiler warnings for VC7 strict compiling.
01-10-2004 1.09.11 BED FIX Fixed typo'd length for email addresses in gpNewUser.
01-08-2004 1.09.10 BED FIX ProfileID was not initialized when receiving a buddy message in UNICODE mode.
01-03-2004 1.09.09 DES FIX Receive and send buffer sizes are now set on incoming Peer sockets.
11-10-2003 1.09.08 DES RELEASE Releasing to developer site.
11-07-2003 1.09.08 BED FIX Removed CodeWarrior strictest warnings.
11-07-2003 1.09.07 DES FIX Updated the linux and PS2 makefiles.
11-04-2003 1.09.06 DES FEATURE Added availability check code.
11-03-2003 1.09.05 BED FIX Converting email and passwords to Ascii instead of UTF8 now.
FIX Removed misc. strict warnings in sample.
10-29-2003 1.09.04 DES FEATURE Pass the gamename to the backend when connecting or searching.
10-21-2003 1.09.03 BED RELEASE Releasing to developer site. (UNIQUE NICK AND UNICODE SUPPORT)
10-21-2003 1.09.03 DES FEATURE Updated gptest to handle new connect methods.
10-17-2003 1.09.02 DES FIX Changed gptest to use the default GameSpy namespace.
10-16-2003 1.09.01 DES FIX The desirednick pased to gpSuggestUniqueNick now has a
length of GP_UNIQUENICK_LEN instead of GP_NICK_LEN.
09-22-2003 1.09.00 DES FEATURE Added support for unique nicks.
FEATURE Added support for associating a cdkey with a unique nick.
FEATURE Added a namespaceID parameter to gpInitialize for setting the current namespace.
FEATURE Added gpConnectPreAuthenticated for logging in from a partner system.
FIX Minor internal cleanup and fixes.
09-14-2003 1.08.17 DES FIX Removed Unicode defines for gptest debug project.
09-08-2003 1.08.16 BED FEATURE Added wrapper for UNICODE support.
07-24-2003 1.08.15 DES RELEASE Releasing to developer site.
07-24-2003 1.08.15 DES CLEANUP Removed unused gpiSendInfo().
CLEANUP Fixed up NOFILE usage to prevent warnings.
07-18-2003 1.08.14 BED FEATURE Added CodeWarrior (PS2) sample project file.
BED CLEANUP General cleanup to remove CodeWarrior warnings.
07-17-2003 1.08.13 DES CLEANUP Cleaned up the PS2 Makefile, it now uses Makefile.commmon.
07-16-2003 1.08.12 BED FEATURE Added ProDG sample project files.
07-14-2003 1.08.11 DES FIX Changed check for __mips64 to check for _PS2.
07-10-2003 1.08.10 BED CLEANUP Changed GP to use GSI_UNUSED for silencing unused variable warnings.
CLEANUP Added newline to end of gpiUtility.c to silence compiler warning.
05-09-2003 1.08.09 DES CLEANUP Removed Dreamcast support.
FIX Metrowerks for Win32 is no longer falsely identified as MacOS.
04-08-2003 1.08.08 JED FIX Cleanup up code to remove multiple DevStudio level4 compiler warnings
03-26-2003 1.08.07 DES FIX gpiDisconnect now checks if sockets are valid before attempting to close them.
03-20-2003 1.08.06 DES FEATURE The productID is now reported to the backend on connect.
03-03-2003 1.08.05 DES CLEANUP General cleanup to remove warnings.
12-19-2002 1.08.04 DES RELEASE Releasing to developer site.
12-19-2002 1.08.04 DES CLEANUP Removed assert.h includes.
12-16-2002 1.08.03 DES FIX Set listen call to use SOMAXCONN for the backlog paramter.
CLEANUP Removed call to GOAClearSocketError.
12-13-2002 1.08.02 DES FEATURE Added PS2 eenet stack support.
CLEANUP Cleaned up code to remove PS2 compiler warnings.
12-11-2002 1.08.01 DES OTHER Moved SetSendBufferSize(), GetSendBufferSize(), and GetReceiveBufferSize() to nonport.
09-25-2002 1.08.00 DDW OTHER Changelog started

4318
code/gamespy/GP/gp.c Normal file

File diff suppressed because it is too large Load diff

1631
code/gamespy/GP/gp.h Normal file

File diff suppressed because it is too large Load diff

816
code/gamespy/GP/gpi.c Normal file
View file

@ -0,0 +1,816 @@
/*
gpi.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include <string.h>
#include "gpi.h"
// DEFINES
//////////
#define KEEPALIVE_TIMEOUT (60 * 2000)
// This is so VisualAssist will know about these functions.
///////////////////////////////////////////////////////////
#if 0
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [16], MD5_CTX *);
void MD5Print(unsigned char [16], char[33]);
void MD5Digest(unsigned char *, unsigned int, char[33]);
#endif
//FUNCTIONS
///////////
GPResult
gpiInitialize(
GPConnection * connection,
int productID,
int namespaceID,
int partnerID
)
{
GPIConnection * iconnection;
int i;
GPResult result;
// Set the connection to NULL in case of error.
///////////////////////////////////////////////
*connection = NULL;
// Allocate the connection.
///////////////////////////
iconnection = (GPIConnection *)gsimalloc(sizeof(GPIConnection));
if(iconnection == NULL)
return GP_MEMORY_ERROR;
// Initialize connection-specific variables.
////////////////////////////////////////////
memset(iconnection, 0, sizeof(GPIConnection));
iconnection->errorString[0] = '\0';
iconnection->errorCode = (GPErrorCode)0;
iconnection->infoCaching = GPITrue;
iconnection->infoCachingBuddyAndBlockOnly = GPIFalse;
iconnection->simulation = GPIFalse;
iconnection->firewall = GPIFalse;
iconnection->productID = productID;
iconnection->namespaceID = namespaceID;
iconnection->partnerID = partnerID;
#ifdef GSI_UNICODE
iconnection->errorString_W[0] = '\0';
#endif
if(!gpiInitProfiles((GPConnection *)&iconnection))
{
freeclear(iconnection);
return GP_MEMORY_ERROR;
}
iconnection->diskCache = NULL;
for(i = 0 ; i < GPI_NUM_CALLBACKS ; i++)
{
iconnection->callbacks[i].callback = NULL;
iconnection->callbacks[i].param = NULL;
}
// Reset connection-specific stuff.
///////////////////////////////////
result = gpiReset((GPConnection *)&iconnection);
if(result != GP_NO_ERROR)
{
gpiDestroy((GPConnection *)&iconnection);
return result;
}
// Initialize the sockets library.
//////////////////////////////////
SocketStartUp();
// Seed the random number generator.
////////////////////////////////////
srand((unsigned int)current_time());
#ifndef NOFILE
// Load profiles cached on disk.
////////////////////////////////
result = gpiLoadDiskProfiles((GPConnection *)&iconnection);
if(result != GP_NO_ERROR)
{
gpiDestroy((GPConnection *)&iconnection);
return result;
}
#endif
#ifndef NOFILE
result = gpiInitTransfers((GPConnection *)&iconnection);
if(result != GP_NO_ERROR)
{
gpiDestroy((GPConnection *)&iconnection);
return result;
}
#endif
// Set the connection.
//////////////////////
*connection = (GPConnection)iconnection;
return GP_NO_ERROR;
}
void
gpiDestroy(
GPConnection * connection
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Cleanup connection-specific stuff.
/////////////////////////////////////
gpiDisconnect(connection, GPITrue);
gpiStatusInfoKeysDestroy(connection);
#ifdef _PS3
// Destroy NP
/////////////
if (iconnection->npInitialized)
gpiDestroyNpBasic(connection);
#endif
#ifndef NOFILE
// Write the profile info to disk.
// BD - Don't update if we never connected.
//////////////////////////////////
if(iconnection->infoCaching && iconnection->connectState != GPI_NOT_CONNECTED)
{
if(gpiSaveDiskProfiles(connection) != GP_NO_ERROR)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_File, GSIDebugLevel_HotError,
"Error saving profiles to disk.");
}
}
#endif
// Free the profile list.
/////////////////////////
TableFree(iconnection->profileList.profileTable);
#ifndef NOFILE
// Free the transfers.
//////////////////////
gpiCleanupTransfers(connection);
#endif
// Free the memory.
///////////////////
freeclear(iconnection);
// Set the connection pointer to NULL.
//////////////////////////////////////
*connection = NULL;
}
static GPIBool
gpiResetProfile(
GPConnection * connection,
GPIProfile * profile,
void * data
)
{
GSI_UNUSED(connection);
GSI_UNUSED(data);
profile->buddyStatus = NULL;
profile->buddyStatusInfo = NULL;
profile->authSig = NULL;
profile->requestCount = 0;
profile->peerSig = NULL;
profile->blocked = gsi_false;
profile->buddyOrBlockCache = gsi_false;
return GPITrue;
}
GPResult
gpiReset(
GPConnection * connection
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GPResult result;
iconnection->nick[0] = '\0';
iconnection->uniquenick[0] = '\0';
iconnection->email[0] = '\0';
iconnection->cmSocket = INVALID_SOCKET;
iconnection->connectState = GPI_NOT_CONNECTED;
iconnection->socketBuffer.len = 0;
iconnection->socketBuffer.pos = 0;
iconnection->socketBuffer.size = 0;
freeclear(iconnection->socketBuffer.buffer);
iconnection->socketBuffer.buffer = NULL;
iconnection->inputBufferSize = 0;
freeclear(iconnection->inputBuffer);
iconnection->inputBuffer = NULL;
iconnection->outputBuffer.len = 0;
iconnection->outputBuffer.pos = 0;
iconnection->outputBuffer.size = 0;
freeclear(iconnection->outputBuffer.buffer);
iconnection->outputBuffer.buffer = NULL;
iconnection->updateproBuffer.len = 0;
iconnection->updateproBuffer.pos = 0;
iconnection->updateproBuffer.size = 0;
freeclear(iconnection->updateproBuffer.buffer);
iconnection->updateproBuffer.buffer = NULL;
iconnection->updateuiBuffer.len = 0;
iconnection->updateuiBuffer.pos = 0;
iconnection->updateuiBuffer.size = 0;
freeclear(iconnection->updateuiBuffer.buffer);
iconnection->updateuiBuffer.buffer = NULL;
gpiStatusInfoKeysDestroy(connection);
result = gpiStatusInfoKeysInit((GPConnection *)&iconnection);
if (result != GP_NO_ERROR)
{
gpiDestroy((GPConnection *)&iconnection);
return result;
}
//iconnection->peerSocket = INVALID_SOCKET;
iconnection->nextOperationID = 2;
while(iconnection->operationList != NULL)
gpiRemoveOperation(connection, iconnection->operationList);
iconnection->operationList = NULL;
iconnection->profileList.numBuddies = 0;
iconnection->profileList.numBlocked = 0;
gpiProfileMap(connection, gpiResetProfile, NULL);
iconnection->userid = 0;
iconnection->profileid = 0;
iconnection->sessKey = 0;
iconnection->numSearches = 0;
iconnection->fatalError = GPIFalse;
iconnection->peerList = NULL;
iconnection->lastStatusState = (GPEnum)-1;
iconnection->lastStatusString[0] = '\0';
iconnection->lastLocationString[0] = '\0';
iconnection->kaTransmit = 0;
#ifdef GSI_UNICODE
iconnection->nick_W[0] = '\0';
iconnection->uniquenick_W[0] = '\0';
iconnection->email_W[0] = '\0';
iconnection->lastStatusString_W[0] = '\0';
iconnection->lastLocationString_W[0] = '\0';
#endif
return GP_NO_ERROR;
}
GPResult
gpiProcessConnectionManager(
GPConnection * connection
)
{
char * next;
char * str;
int id;
GPIOperation * operation;
char * tempPtr;
int len;
GPIBool connClosed = GPIFalse;
GPIConnection * iconnection = (GPIConnection*)*connection;
GPResult result;
GPIBool loop;
gsi_time now = current_time();
// Loop through the rest while waiting for any blocking operations.
///////////////////////////////////////////////////////////////////
do
{
// Add any waiting info to the output buffer.
/////////////////////////////////////////////
gpiAddLocalInfo(connection, &iconnection->outputBuffer);
// Send anything that needs to be sent.
///////////////////////////////////////
if ( iconnection->outputBuffer.len > 0 )
iconnection->kaTransmit = now; // data already being transmitted. We don't need to send keep alives
CHECK_RESULT(gpiSendFromBuffer(connection, iconnection->cmSocket, &iconnection->outputBuffer, &connClosed, GPITrue, "CM"));
// Read everything the connection manager sent.
///////////////////////////////////////////////
result = gpiRecvToBuffer(connection, iconnection->cmSocket, &iconnection->socketBuffer, &len, &connClosed, "CM");
if(result != GP_NO_ERROR)
{
if(result == GP_NETWORK_ERROR)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error reading from the server.");
return result;
}
// Check if we have a completed command.
////////////////////////////////////////
while((next = strstr(iconnection->socketBuffer.buffer, "\\final\\")) != NULL)
{
// Received command. Connection is still valid
//////////////////////////////////////////////
iconnection->kaTransmit = now;
// NUL terminate the command.
/////////////////////////////
next[0] = '\0';
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
"CMD: %s\n", iconnection->socketBuffer.buffer);
// Copy the command to the input buffer.
////////////////////////////////////////
len = (next - iconnection->socketBuffer.buffer);
if(len > iconnection->inputBufferSize)
{
iconnection->inputBufferSize += max(GPI_READ_SIZE, len);
tempPtr = (char*)gsirealloc(iconnection->inputBuffer, (unsigned int)iconnection->inputBufferSize + 1);
if(tempPtr == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
iconnection->inputBuffer = tempPtr;
}
memcpy(iconnection->inputBuffer, iconnection->socketBuffer.buffer, (unsigned int)len + 1);
// Point to the start of the next one.
//////////////////////////////////////
next += 7;
// Move the rest of the connect buffer up to the front.
///////////////////////////////////////////////////////
iconnection->socketBuffer.len -= (next - iconnection->socketBuffer.buffer);
memmove(iconnection->socketBuffer.buffer, next, (unsigned int)iconnection->socketBuffer.len + 1);
// Check for an id.
///////////////////
str = strstr(iconnection->inputBuffer, "\\id\\");
if(str != NULL)
{
// Get the id.
//////////////
id = atoi(str + 4);
// Try and match the id with an operation.
//////////////////////////////////////////
if(!gpiFindOperationByID(connection, &operation, id))
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError,
"No matching operation found for id %d\n", id);
}
else
{
// Process the operation.
/////////////////////////
CHECK_RESULT(gpiProcessOperation(connection, operation, iconnection->inputBuffer));
}
}
// This is an unsolicited message.
//////////////////////////////////
else
{
// Check for an error.
//////////////////////
if(gpiCheckForError(connection, iconnection->inputBuffer, GPITrue))
{
return GP_SERVER_ERROR;
}
else if(strncmp(iconnection->inputBuffer, "\\bm\\", 4) == 0)
{
CHECK_RESULT(gpiProcessRecvBuddyMessage(connection, iconnection->inputBuffer));
}
else if(strncmp(iconnection->inputBuffer, "\\ka\\", 4) == 0)
{
// Ignore the keep-alive.
/////////////////////////
}
else if(strncmp(iconnection->inputBuffer, "\\lt\\", 4) == 0)
{
// Process the login ticket
/////////////////////////
gpiValueForKey(iconnection->inputBuffer, "\\lt\\", iconnection->loginTicket, sizeof(iconnection->loginTicket));
}
else if(strncmp(iconnection->inputBuffer, "\\bsi\\", 5) == 0)
{
CHECK_RESULT(gpiProcessRecvBuddyStatusInfo(connection, iconnection->inputBuffer));
}
else if(strncmp(iconnection->inputBuffer, "\\bdy\\", 5) == 0)
{
// Process the buddy list - retrieved upon login before final login response
// * Note: this only gets the list of your buddies so at least you'll know who
// is a buddy while the status of each is asynchronously updated.
//////////////////////////////////////////////////////////////////////////////
CHECK_RESULT(gpiProcessRecvBuddyList(connection, iconnection->inputBuffer));
}
else if(strncmp(iconnection->inputBuffer, "\\blk\\", 5) == 0)
{
// Process the block list - retrieved upon login before final login response
//////////////////////////////////////////////////////////////////////////////
CHECK_RESULT(gpiProcessRecvBlockedList(connection, iconnection->inputBuffer));
}
else
{
// This is an unrecognized message.
///////////////////////////////////
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError,
"Received an unrecognized message.\n");
}
}
}
// Check for a closed connection.
/////////////////////////////////
if(connClosed && iconnection->connectState != GPI_PROFILE_DELETING)
{
// We've been disconnected.
///////////////////////////
// Let gpiDisconnect change the state to GPI_DISCONNECTED
//iconnection->connectState = GPI_DISCONNECTED;
gpiSetError(connection, GP_CONNECTION_CLOSED, "The server has closed the connection.");
gpiCallErrorCallback(connection, GP_NETWORK_ERROR, GP_FATAL);
return GP_NO_ERROR;
}
//PANTS|05.23.00 - removed sleep
//crt - added it back 6/13/00
//PANTS|07.10.00 - only sleep if looping
loop = gpiOperationsAreBlocking(connection);
if(loop)
msleep(10);
}
while(loop);
// Send Keep-Alive. Just need TCP to ack the data
/////////////////////////////////////////////////
if ( now - iconnection->kaTransmit > KEEPALIVE_TIMEOUT )
{
// keep alive packet will be sent next think
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\ka\\\\final\\");
iconnection->kaTransmit = now;
}
return GP_NO_ERROR;
}
GPResult
gpiProcess(
GPConnection * connection,
int blockingOperationID
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GPIOperation * operation;
GPIOperation * delOperation;
GPResult result = GP_NO_ERROR;
GPIBool loop;
assert((iconnection->connectState == GPI_NOT_CONNECTED) ||
(iconnection->connectState == GPI_CONNECTING) ||
(iconnection->connectState == GPI_NEGOTIATING) ||
(iconnection->connectState == GPI_CONNECTED) ||
(iconnection->connectState == GPI_DISCONNECTED) ||
(iconnection->connectState == GPI_PROFILE_DELETING));
// Check if no connection was attempted.
////////////////////////////////////////
/* if(iconnection->connectState == GPI_NOT_CONNECTED)
return GP_NO_ERROR;
// Check for a disconnection.
/////////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
return GP_NO_ERROR;
*/
// Check if we're connecting.
/////////////////////////////
if(iconnection->connectState == GPI_CONNECTING)
{
do
{
result = gpiCheckConnect(connection);
//PANTS|07.10.00 - only sleep if looping
loop = (((result == GP_NO_ERROR) && (blockingOperationID != 0) && (iconnection->connectState == GPI_CONNECTING))) ? GPITrue:GPIFalse;
if(loop)
msleep(10);
}
while(loop);
if(result != GP_NO_ERROR)
{
// Find the connect operation.
//////////////////////////////
if(gpiFindOperationByID(connection, &operation, 1))
{
operation->result = GP_SERVER_ERROR;
}
else
{
// Couldn't find the connect operation.
///////////////////////////////////////
assert(0);
}
}
}
// Only do this stuff if we're connected.
/////////////////////////////////////////
if((iconnection->connectState == GPI_CONNECTED) || (iconnection->connectState == GPI_NEGOTIATING) ||
(iconnection->connectState == GPI_PROFILE_DELETING))
{
#ifdef _PS3
// initialize NP during the sync delay, if initialized wait for status == online
////////////////////////////////////////////////////////////////////////////////
if (iconnection->npInitialized && !iconnection->npStatusRetrieved)
gpiCheckNpStatus(connection);
// TODO: handle non-fatal errors (consider all errors from sync non-fatal?)
if (iconnection->npInitialized && iconnection->npStatusRetrieved)
{
// Delay sync after initialization to ensure block list has been received
/////////////////////////////////////////////////////////////////////////
if ((current_time() - iconnection->loginTime) > GPI_NP_SYNC_DELAY)
{
if (iconnection->npPerformBuddySync)
gpiSyncNpBuddies(connection);
if (iconnection->npPerformBlockSync)
gpiSyncNpBlockList(connection);
}
// Need to check callback for lookups
gpiProcessNp(connection);
}
#endif
// Process the connection.
//////////////////////////
if(result == GP_NO_ERROR)
result = gpiProcessConnectionManager(connection);
// Process peer messaging stuff.
////////////////////////////////
if(result == GP_NO_ERROR)
result = gpiProcessPeers(connection);
#ifndef NOFILE
// Process transfers.
/////////////////////
if(result == GP_NO_ERROR)
result = gpiProcessTransfers(connection);
#endif
}
// Process searches.
////////////////////
if(result == GP_NO_ERROR)
result = gpiProcessSearches(connection);
// Look for failed operations.
//////////////////////////////
for(operation = iconnection->operationList ; operation != NULL ; )
{
if(operation->result != GP_NO_ERROR)
{
gpiFailedOpCallback(connection, operation);
delOperation = operation;
operation = operation->pnext;
gpiRemoveOperation(connection, delOperation);
}
else
{
operation = operation->pnext;
}
}
// Call callbacks.
//////////////////
CHECK_RESULT(gpiProcessCallbacks(connection, blockingOperationID));
if(iconnection->fatalError)
{
gpiDisconnect(connection, GPIFalse);
gpiReset(connection);
}
else
{
//assert(!((result != GP_NO_ERROR) && (iconnection->connectState != GPI_CONNECTED)));
}
return result;
}
GPResult
gpiEnable(
GPConnection * connection,
GPEnum state
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Enable the state.
////////////////////
switch(state)
{
case GP_INFO_CACHING:
iconnection->infoCaching = GPITrue;
break;
case GP_SIMULATION:
iconnection->simulation = GPITrue;
break;
case GP_INFO_CACHING_BUDDY_AND_BLOCK_ONLY:
iconnection->infoCachingBuddyAndBlockOnly = GPITrue;
break;
default:
Error(connection, GP_PARAMETER_ERROR, "Invalid state.");
}
return GP_NO_ERROR;
}
static GPIBool gpiFreeProfileInfo(
GPConnection * connection,
GPIProfile * profile,
void * data
)
{
GSI_UNUSED(data);
gpiFreeInfoCache(profile);
freeclear(profile->peerSig);
if(gpiCanFreeProfile(profile))
{
gpiRemoveProfile(connection, profile);
return GPIFalse;
}
return GPITrue;
}
GPResult
gpiDisable(
GPConnection * connection,
GPEnum state
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
if(state == GP_INFO_CACHING)
{
iconnection->infoCaching = GPIFalse;
// freeclear everyone's info.
////////////////////////
while(!gpiProfileMap(connection, gpiFreeProfileInfo, NULL)) { };
}
else if(state == GP_SIMULATION)
{
iconnection->simulation = GPIFalse;
}
else if(state == GP_INFO_CACHING_BUDDY_AND_BLOCK_ONLY)
{
iconnection->infoCachingBuddyAndBlockOnly = GPIFalse;
}
else
{
Error(connection, GP_PARAMETER_ERROR, "Invalid state.");
}
return GP_NO_ERROR;
}
#ifdef _DEBUG
static int nProfiles;
static int nUserID;
static int nBuddyStatus;
static int nBuddyMemory;
static int nInfoCache;
static int nInfoMemory;
static int nAuthSig;
static int nPeerSig;
static int nTotalMemory;
static int nBlocked;
static GPIBool
gpiReportProfile(
GPConnection * connection,
GPIProfile * profile,
void * data
)
{
int temp;
GSI_UNUSED(connection);
GSI_UNUSED(data);
nProfiles++;
nTotalMemory += sizeof(GPIProfile);
if(profile->userId) nUserID++;
if(profile->buddyStatus)
{
nBuddyStatus++;
temp = sizeof(GPIBuddyStatus);
if(profile->buddyStatus->statusString)
temp += (int)(strlen(profile->buddyStatus->statusString) + 1);
if(profile->buddyStatus->locationString)
temp += (int)(strlen(profile->buddyStatus->locationString) + 1);
#ifdef GSI_UNICODE
// if(profile->buddyStatus->statusString_W)
// temp += (wcslen(profile->buddyStatus->statusString_W) + 2);
// if(profile->buddyStatus->locationString_W)
// temp += (wcslen(profile->buddyStatus->locationString_W) + 2);
#endif
nBuddyMemory += temp;
nTotalMemory += temp;
}
if(profile->cache)
{
nInfoCache++;
temp = sizeof(GPIInfoCache);
if(profile->cache->nick)
temp += (int)(strlen(profile->cache->nick) + 1);
if(profile->cache->uniquenick)
temp += (int)(strlen(profile->cache->uniquenick) + 1);
if(profile->cache->email)
temp += (int)(strlen(profile->cache->email) + 1);
if(profile->cache->firstname)
temp += (int)(strlen(profile->cache->firstname) + 1);
if(profile->cache->lastname)
temp += (int)(strlen(profile->cache->lastname) + 1);
if(profile->cache->homepage)
temp += (int)(strlen(profile->cache->homepage) + 1);
nInfoMemory += temp;
nTotalMemory += temp;
}
if(profile->authSig) nAuthSig++;
if(profile->peerSig) nPeerSig++;
if(profile->blocked) nBlocked++;
return GPITrue;
}
void
gpiReport(
GPConnection * connection,
void (* report)(const char * output)
)
{
char buf[128];
nProfiles = 0;
nUserID = 0;
nBuddyStatus = 0;
nBuddyMemory = 0;
nInfoCache = 0;
nInfoMemory = 0;
nAuthSig = 0;
nPeerSig = 0;
nTotalMemory = 0;
nBlocked = 0;
report("START PROFILE MAP");
report("-----------------");
gpiProfileMap(connection, gpiReportProfile, NULL);
sprintf(buf, "%d profiles %d bytes (%d avg)", nProfiles, nTotalMemory, nTotalMemory / max(nProfiles, 1));
report(buf);
if(nProfiles)
{
sprintf(buf, "UserID: %d (%d%%)", nUserID, nUserID * 100 / nProfiles);
report(buf);
sprintf(buf, "BuddyStatus: %d (%d%%) %d bytes (%d avg)", nBuddyStatus, nBuddyStatus * 100 / nProfiles, nBuddyMemory, nBuddyMemory / max(nBuddyStatus, 1));
report(buf);
sprintf(buf, "InfoCache: %d (%d%%) %d bytes (%d avg)", nInfoCache, nInfoCache * 100 / nProfiles, nInfoMemory, nInfoMemory / max(nInfoCache, 1));
report(buf);
sprintf(buf, "AuthSig: %d (%d%%)", nAuthSig, nAuthSig * 100 / nProfiles);
report(buf);
sprintf(buf, "PeerSig: %d (%d%%)", nPeerSig, nPeerSig * 100 / nProfiles);
report(buf);
sprintf(buf, "Blocked: %d (%d%%)", nBlocked, nBlocked * 100 / nProfiles);
report(buf);
}
report("---------------");
report("END PROFILE MAP");
}
#endif

231
code/gamespy/GP/gpi.h Normal file
View file

@ -0,0 +1,231 @@
/*
gpi.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPI_H_
#define _GPI_H_
//INCLUDES
//////////
#include "../common/gsCommon.h"
#include "../common/gsAvailable.h"
#include "../common/gsUdpEngine.h"
#include "../hashtable.h"
#include "../darray.h"
#include "../md5.h"
#include "gp.h"
// Extended message support
#define GPI_NEW_AUTH_NOTIFICATION (1<<0)
#define GPI_NEW_REVOKE_NOTIFICATION (1<<1)
// New Status Info support
#define GPI_NEW_STATUS_NOTIFICATION (1<<2)
// Buddy List + Block List retrieval on login
#define GPI_NEW_LIST_RETRIEVAL_ON_LOGIN (1<<3)
// Extended SDK features
#ifndef GPI_SDKREV
#ifdef GP_NEW_STATUS_INFO
#define GPI_SDKREV (GPI_NEW_AUTH_NOTIFICATION | GPI_NEW_REVOKE_NOTIFICATION | GPI_NEW_STATUS_NOTIFICATION | GPI_NEW_LIST_RETRIEVAL_ON_LOGIN)
#else
#define GPI_SDKREV (GPI_NEW_AUTH_NOTIFICATION | GPI_NEW_REVOKE_NOTIFICATION | GPI_NEW_LIST_RETRIEVAL_ON_LOGIN)
#endif
#endif
// New UDP Layer port
#define GPI_PEER_PORT 6500
//TYPES
///////
// Boolean.
///////////
typedef enum _GPIBool
{
GPIFalse,
GPITrue
} GPIBool;
#include "gpiUtility.h"
#include "gpiCallback.h"
#include "gpiOperation.h"
#include "gpiConnect.h"
#include "gpiBuffer.h"
#include "gpiInfo.h"
#include "gpiProfile.h"
#include "gpiPeer.h"
#include "gpiSearch.h"
#include "gpiBuddy.h"
#include "gpiTransfer.h"
#include "gpiUnique.h"
#include "gpiKeys.h"
// For PS3 NP Sync functionality
#ifdef _PS3
#include "gpiPS3.h"
#endif
// Connection data.
///////////////////
typedef struct
{
char errorString[GP_ERROR_STRING_LEN];
GPIBool infoCaching;
GPIBool infoCachingBuddyAndBlockOnly;
GPIBool simulation;
GPIBool firewall;
char nick[GP_NICK_LEN];
char uniquenick[GP_UNIQUENICK_LEN];
char email[GP_EMAIL_LEN];
char password[GP_PASSWORD_LEN];
int sessKey;
int userid;
int profileid;
int partnerID;
GPICallback callbacks[GPI_NUM_CALLBACKS];
SOCKET cmSocket;
int connectState;
GPIBuffer socketBuffer;
char * inputBuffer;
int inputBufferSize;
GPIBuffer outputBuffer;
// Replaced by UDP Layer
//SOCKET peerSocket;
char mHeader[GS_UDP_MSG_HEADER_LEN];
unsigned short peerPort;
int nextOperationID;
int numSearches;
// new style status info
GPEnum lastStatusState;
unsigned int hostIp;
unsigned int hostPrivateIp;
unsigned short queryPort;
unsigned short hostPort;
unsigned int sessionFlags;
char richStatus[GP_RICH_STATUS_LEN];
char gameType[GP_STATUS_BASIC_STR_LEN];
char gameVariant[GP_STATUS_BASIC_STR_LEN];
char gameMapName[GP_STATUS_BASIC_STR_LEN];
// New Status Info extended info Keys
DArray extendedInfoKeys;
// Deprecated
char lastStatusString[GP_STATUS_STRING_LEN];
char lastLocationString[GP_LOCATION_STRING_LEN];
GPErrorCode errorCode;
GPIBool fatalError;
FILE * diskCache;
GPIOperation * operationList;
GPIProfileList profileList;
GPIPeer * peerList;
GPICallbackData * callbackList;
GPICallbackData * lastCallback;
GPIBuffer updateproBuffer;
GPIBuffer updateuiBuffer;
DArray transfers;
unsigned int nextTransferID;
int productID;
int namespaceID;
char loginTicket[GP_LOGIN_TICKET_LEN];
GPEnum quietModeFlags;
gsi_time kaTransmit;
#ifdef GSI_UNICODE
unsigned short errorString_W[GP_ERROR_STRING_LEN];
unsigned short nick_W[GP_NICK_LEN];
unsigned short uniquenick_W[GP_UNIQUENICK_LEN];
unsigned short email_W[GP_EMAIL_LEN];
unsigned short password_W[GP_PASSWORD_LEN];
// Deprecated
unsigned short lastStatusString_W[GP_STATUS_STRING_LEN];
unsigned short lastLocationString_W[GP_LOCATION_STRING_LEN];
unsigned short richStatus_W[GP_RICH_STATUS_LEN];
unsigned short gameType_W[GP_STATUS_BASIC_STR_LEN];
unsigned short gameVariant_W[GP_STATUS_BASIC_STR_LEN];
unsigned short gameMapName_W[GP_STATUS_BASIC_STR_LEN];
#endif
#ifdef _PS3
// NP sync info
gsi_bool npInitialized;
gsi_bool npStatusRetrieved;
gsi_bool npBasicGameInitialized;
gsi_bool npLookupGameInitialized;
gsi_bool npPerformBuddySync;
gsi_bool npPerformBlockSync;
gsi_bool npSyncLock;
int npLookupTitleCtxId;
DArray npTransactionList;
gsi_time loginTime;
#endif
} GPIConnection;
//FUNCTIONS
///////////
GPResult
gpiInitialize(
GPConnection * connection,
int productID,
int namespaceID,
int partnerID
);
void
gpiDestroy(
GPConnection * connection
);
GPResult
gpiReset(
GPConnection * connection
);
GPResult
gpiProcessConnectionManager(
GPConnection * connection
);
GPResult
gpiProcess(
GPConnection * connection,
int blockingOperationID
);
GPResult
gpiEnable(
GPConnection * connection,
GPEnum state
);
GPResult
gpiDisable(
GPConnection * connection,
GPEnum state
);
#ifdef _DEBUG
void
gpiReport(
GPConnection * connection,
void (* report)(const char * output)
);
#endif
#endif

1064
code/gamespy/GP/gpiBuddy.c Normal file

File diff suppressed because it is too large Load diff

104
code/gamespy/GP/gpiBuddy.h Normal file
View file

@ -0,0 +1,104 @@
/*
gpiBuddy.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIBUDDY_H_
#define _GPIBUDDY_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Types of bm's.
/////////////////
#define GPI_BM_MESSAGE 1
#define GPI_BM_REQUEST 2
#define GPI_BM_REPLY 3 // only used on the backend
#define GPI_BM_AUTH 4
#define GPI_BM_UTM 5
#define GPI_BM_REVOKE 6 // remote buddy removed from local list
#define GPI_BM_STATUS 100
#define GPI_BM_INVITE 101
#define GPI_BM_PING 102
#define GPI_BM_PONG 103
#define GPI_BM_KEYS_REQUEST 104
#define GPI_BM_KEYS_REPLY 105
#define GPI_BM_FILE_SEND_REQUEST 200
#define GPI_BM_FILE_SEND_REPLY 201
#define GPI_BM_FILE_BEGIN 202
#define GPI_BM_FILE_END 203
#define GPI_BM_FILE_DATA 204
#define GPI_BM_FILE_SKIP 205
#define GPI_BM_FILE_TRANSFER_THROTTLE 206
#define GPI_BM_FILE_TRANSFER_CANCEL 207
#define GPI_BM_FILE_TRANSFER_KEEPALIVE 208
//FUNCTIONS
///////////
GPResult
gpiProcessRecvBuddyMessage(
GPConnection * connection,
const char * input
);
GPResult gpiProcessRecvBuddyStatusInfo(GPConnection *connection, const char *input);
GPResult
gpiProcessRecvBuddyList(
GPConnection * connection,
const char * input
);
GPResult
gpiSendServerBuddyMessage(
GPConnection * connection,
int profileid,
int type,
const char * message
);
GPResult
gpiSendBuddyMessage(
GPConnection * connection,
int profileid,
int type,
const char * message,
int sendOptions,
GPIPeerOp *peerOp
);
GPResult gpiBuddyHandleKeyRequest(GPConnection *connection, GPIPeer *peer);
GPResult gpiBuddyHandleKeyReply(GPConnection *connection, GPIPeer *peer, char *buffer);
GPResult
gpiAuthBuddyRequest(
GPConnection * connection,
GPProfile profile
);
GPIBool
gpiFixBuddyIndices(
GPConnection * connection,
GPIProfile * profile,
void * data
);
GPResult
gpiDeleteBuddy(
GPConnection * connection,
GPProfile profile,
GPIBool sendServerRequest
);
#endif

766
code/gamespy/GP/gpiBuffer.c Normal file
View file

@ -0,0 +1,766 @@
/*
gpiBuffer.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include <string.h>
#include "gpi.h"
//DEFINES
/////////
#define GPI_DUMP_NET_TRAFFIC
//FUNCTIONS
///////////
GPResult
gpiAppendCharToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
char c
)
{
int len;
int size;
char * output;
assert(outputBuffer != NULL);
// Init locals.
///////////////
len = outputBuffer->len;
size = outputBuffer->size;
output = outputBuffer->buffer;
// Check if it needs to be resized.
///////////////////////////////////
if(size == len)
{
size += GPI_READ_SIZE;
output = (char*)gsirealloc(output, (unsigned int)size + 1);
if(output == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
// Do the copy.
///////////////
output[len] = c;
output[len + 1] = '\0';
// Update the buffer info.
//////////////////////////
outputBuffer->len++;
outputBuffer->size = size;
outputBuffer->buffer = output;
return GP_NO_ERROR;
}
GPResult
gpiAppendStringToBufferLen(
GPConnection * connection,
GPIBuffer * outputBuffer,
const char * string,
int stringLen
)
{
int len;
int size;
char * output;
assert(string != NULL);
assert(stringLen >= 0);
assert(outputBuffer != NULL);
if(!string)
return GP_NO_ERROR;
// Init locals.
///////////////
len = outputBuffer->len;
size = outputBuffer->size;
output = outputBuffer->buffer;
// Check if it needs to be resized.
///////////////////////////////////
if((size - len) < stringLen)
{
size += max(GPI_READ_SIZE, stringLen);
output = (char*)gsirealloc(output, (unsigned int)size + 1);
if(output == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
// Do the copy.
///////////////
memcpy(&output[len], string, (unsigned int)stringLen);
output[len + stringLen] = '\0';
// Update the buffer info.
//////////////////////////
outputBuffer->len += stringLen;
outputBuffer->size = size;
outputBuffer->buffer = output;
return GP_NO_ERROR;
}
GPResult
gpiAppendStringToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
const char * buffer
)
{
return gpiAppendStringToBufferLen(connection, outputBuffer, buffer, (int)strlen(buffer));
}
GPResult gpiAppendShortToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
short num)
{
char shortVal[8];
sprintf(shortVal, "%d", num);
return gpiAppendStringToBuffer(connection, outputBuffer, shortVal);
}
GPResult gpiAppendUShortToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
unsigned short num)
{
char shortVal[8];
sprintf(shortVal, "%u", num);
return gpiAppendStringToBuffer(connection, outputBuffer, shortVal);
}
GPResult
gpiAppendIntToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
int num
)
{
char intValue[16];
sprintf(intValue,"%d",num);
return gpiAppendStringToBuffer(connection, outputBuffer, intValue);
}
GPResult
gpiAppendUIntToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
unsigned int num
)
{
char intValue[16];
sprintf(intValue,"%u",num);
return gpiAppendStringToBuffer(connection, outputBuffer, intValue);
}
static GPResult
gpiSendData(
GPConnection * connection,
SOCKET sock,
const char * buffer,
int bufferLen,
GPIBool * closed,
int * sent,
char id[3]
)
{
int rcode;
rcode = send(sock, buffer, bufferLen, 0);
if(gsiSocketIsError(rcode))
{
rcode = GOAGetLastError(sock);
if((rcode != WSAEWOULDBLOCK) && (rcode != WSAEINPROGRESS) && (rcode != WSAETIMEDOUT) )
{
// handle peer connections specially
if((id[0] == 'P') && (id[1] == 'R'))
return GP_NETWORK_ERROR;
CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error sending on a socket.");
}
*sent = 0;
*closed = GPIFalse;
}
else if(rcode == 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment,
"SENDXXXX(%s): Connection closed\n", id);
*sent = 0;
*closed = GPITrue;
}
else
{
#if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG)
{
static int sendCount;
char *buf = (char *)gsimalloc((size_t)(rcode + 1));
memcpy(buf, buffer, (size_t)rcode);
buf[rcode] = '\0';
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %s\n", sendCount++, id, buf);
freeclear(buf);
}
#elif defined(GSI_COMMON_DEBUG)
{
static int sendCount;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
"SENT%04d(%s): %d\n", sendCount++, id, rcode);
}
#endif
*sent = rcode;
*closed = GPIFalse;
}
return GP_NO_ERROR;
}
GPResult
gpiSendOrBufferChar(
GPConnection * connection,
GPIPeer_st peer,
char c
)
{
//GPIBool closed;
//int sent;
/*
assert(peer->outputBuffer.buffer != NULL);
// Only try to send if the buffer is empty and there are no messages.
/////////////////////////////////////////////////////////////////////
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
{
CHECK_RESULT(gpiSendData(connection, peer->sock, &c, 1, &closed, &sent, "PT"));
if(sent)
return GP_NO_ERROR;
}
// Buffer if not sent.
//////////////////////
return gpiAppendCharToBuffer(connection, &peer->outputBuffer, c);
*/
GSI_UNUSED(c);
GSI_UNUSED(peer);
GSI_UNUSED(connection);
return GP_NO_ERROR;
}
GPResult
gpiSendOrBufferStringLenToPeer(
GPConnection * connection,
GPIPeer_st peer,
const char * string,
int stringLen
)
{
GPIConnection *iconnection;
unsigned int sent;
unsigned int total;
unsigned int remaining;
assert(peer->outputBuffer.buffer != NULL);
sent = 0;
iconnection = (GPIConnection *)*connection;
remaining = (unsigned int)stringLen;
total = 0;
// Check for nothing to send.
/////////////////////////////
if(stringLen == 0)
return GP_NO_ERROR;
// Only try to send if the buffer is empty and there are no messages.
/////////////////////////////////////////////////////////////////////
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
{
if ((int)remaining <= (gsUdpEngineGetPeerOutBufferFreeSpace(peer->ip, peer->port) - GS_UDP_RELIABLE_MSG_HEADER - GS_UDP_MSG_HEADER_LEN))
{
gsUdpEngineSendMessage(peer->ip, peer->port, iconnection->mHeader, (unsigned char *)string, remaining, gsi_true);
total = remaining;
remaining = 0;
}
else
{
unsigned int freeSpace = (unsigned int)gsUdpEngineGetPeerOutBufferFreeSpace(peer->ip, peer->port);
if (freeSpace > (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER))
{
sent = freeSpace - (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER);
gsUdpEngineSendMessage(peer->ip, peer->port, iconnection->mHeader, (unsigned char *)string,
sent, gsi_true);
total = sent;
remaining -= sent;
}
}
}
// Buffer what wasn't sent.
///////////////////////////
if(remaining)
CHECK_RESULT(gpiAppendStringToBufferLen(connection, &peer->outputBuffer, &string[total], (int)remaining));
return GP_NO_ERROR;
}
/*
GPResult
gpiSendOrBufferStringLen(
GPConnection * connection,
GPIPeer_st peer,
const char * string,
int stringLen
)
{
GPIBool closed;
int sent;
int total;
int remaining;
assert(peer->outputBuffer.buffer != NULL);
remaining = stringLen;
total = 0;
// Check for nothing to send.
/////////////////////////////
if(stringLen == 0)
return GP_NO_ERROR;
// Only try to send if the buffer is empty and there are no messages.
/////////////////////////////////////////////////////////////////////
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
{
do
{
CHECK_RESULT(gpiSendData(connection, peer->sock, &string[total], remaining, &closed, &sent, "PT"));
if(sent)
{
total += sent;
remaining -= sent;
}
}
while(sent && remaining);
}
// Buffer what wasn't sent.
///////////////////////////
if(remaining)
CHECK_RESULT(gpiAppendStringToBufferLen(connection, &peer->outputBuffer, &string[total], remaining));
GSI_UNUSED(stringLen);
GSI_UNUSED(string);
GSI_UNUSED(peer);
GSI_UNUSED(connection);
return GP_NO_ERROR;
}
*/
GPResult
gpiSendOrBufferString(
GPConnection * connection,
GPIPeer_st peer,
char * string
)
{
return gpiSendOrBufferStringLenToPeer(connection, peer, string, (int)strlen(string));
}
GPResult
gpiSendOrBufferInt(
GPConnection * connection,
GPIPeer_st peer,
int num
)
{
char intValue[16];
sprintf(intValue,"%d",num);
return gpiSendOrBufferString(connection, peer, intValue);
}
GPResult
gpiSendOrBufferUInt(
GPConnection * connection,
GPIPeer_st peer,
unsigned int num
)
{
char intValue[16];
sprintf(intValue,"%u",num);
return gpiSendOrBufferString(connection, peer, intValue);
}
GPResult
gpiRecvToBuffer(
GPConnection * connection,
SOCKET sock,
GPIBuffer * inputBuffer,
int * bytesRead,
GPIBool * connClosed,
char id[3]
)
{
char * buffer;
int len;
int size;
int rcode;
int total;
GPIBool closed;
assert(sock != INVALID_SOCKET);
assert(inputBuffer != NULL);
assert(bytesRead != NULL);
assert(connClosed != NULL);
// Init locals.
///////////////
buffer = inputBuffer->buffer;
len = inputBuffer->len;
size = inputBuffer->size;
total = 0;
closed = GPIFalse;
do
{
// Check if the buffer needs to be resized.
///////////////////////////////////////////
if((len + GPI_READ_SIZE) > size)
{
size = (len + GPI_READ_SIZE);
buffer = (char *)gsirealloc(buffer, (unsigned int)size + 1);
if(buffer == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
// Read from the network.
rcode = recv(sock, &buffer[len], size - len, 0);
if(gsiSocketIsError(rcode))
{
int error = GOAGetLastError(sock);
if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT) )
{
Error(connection, GP_NETWORK_ERROR, "There was an error reading from a socket.");
}
}
else if(rcode == 0)
{
// Check for a closed connection.
/////////////////////////////////
closed = GPITrue;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment,
"RECVXXXX(%s): Connection closed\n", id);
}
else
{
#if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG)
{
static int recvCount;
char *buf = (char *)gsimalloc((size_t)(rcode + 1));
memcpy(buf, &buffer[len], (size_t)rcode);
buf[rcode] = '\0';
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
"RECV%04d(%s): %s\n", recvCount++, id, buf);
freeclear(buf);
}
#elif defined(GSI_COMMON_DEBUG)
{
static int recvCount;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
"RECV%04d(%s): %d\n", recvCount++, id, rcode);
}
#endif
// Update the buffer len.
/////////////////////////
len += rcode;
// Update the total.
////////////////////
total += rcode;
}
buffer[len] = '\0';
}
while((rcode >= 0) && !closed && (total < (128 * 1024)));
if(total)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
"RECVTOTL(%s): %d\n", id, total);
}
// Set output stuff.
////////////////////
inputBuffer->buffer = buffer;
inputBuffer->len = len;
inputBuffer->size = size;
*bytesRead = total;
*connClosed = closed;
GSI_UNUSED(id); //to get rid of codewarrior warnings
return GP_NO_ERROR;
}
GPResult
gpiSendFromBuffer(
GPConnection * connection,
SOCKET sock,
GPIBuffer * outputBuffer,
GPIBool * connClosed,
GPIBool clipSentData,
char id[3]
)
{
GPIBool closed;
int sent;
int total;
int remaining;
char * buffer;
int pos;
int len;
assert(outputBuffer != NULL);
buffer = outputBuffer->buffer;
len = outputBuffer->len;
pos = outputBuffer->pos;
remaining = (len - pos);
total = 0;
// Check for nothing to send.
/////////////////////////////
if(remaining == 0)
return GP_NO_ERROR;
do
{
CHECK_RESULT(gpiSendData(connection, sock, &buffer[pos + total], remaining, &closed, &sent, id));
if(sent)
{
total += sent;
remaining -= sent;
}
}
while(sent && remaining);
if(clipSentData)
{
if(total > 0)
{
memmove(buffer, &buffer[total], (unsigned int)remaining + 1);
len -= total;
}
}
else
{
pos += total;
}
assert(len >= 0);
assert(pos >= 0);
assert(pos <= len);
// Set outputs.
///////////////
outputBuffer->len = len;
outputBuffer->pos = pos;
if(connClosed)
*connClosed = closed;
return GP_NO_ERROR;
}
GPResult gpiSendBufferToPeer(GPConnection * connection, unsigned int ip, unsigned short port,
GPIBuffer * outputBuffer, GPIBool *closed, GPIBool clipSentData)
{
GPIConnection *iconnection = (GPIConnection *)*connection;
//GPIBool closed;
unsigned int remaining;
unsigned char * buffer;
unsigned int pos;
unsigned int len;
unsigned int total = 0;
GSUdpPeerState aPeerState;
assert(outputBuffer != NULL);
buffer = (unsigned char *)outputBuffer->buffer;
len = (unsigned int)outputBuffer->len;
pos = (unsigned int)outputBuffer->pos;
remaining = (len - pos);
// Check for nothing to send.
/////////////////////////////
if(remaining == 0)
return GP_NO_ERROR;
// length of message remaining must be smaller than total buffer size minus gt2 reliable msg header size minus
// in order to send the message in one shot.
if ((int)remaining <= (gsUdpEngineGetPeerOutBufferFreeSpace(ip, port) - GS_UDP_RELIABLE_MSG_HEADER - GS_UDP_MSG_HEADER_LEN))
{
gsUdpEngineSendMessage(ip, port, iconnection->mHeader, &buffer[pos], remaining, gsi_true);
total = remaining;
remaining = 0;
}
else
{
unsigned int freeSpace =0;
unsigned int sendAmount = 0;
do
{
freeSpace = (unsigned int)gsUdpEngineGetPeerOutBufferFreeSpace(ip, port);
sendAmount = freeSpace - (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER);
if (sendAmount <= (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER))
break;
if (gsUdpEngineSendMessage(ip, port, iconnection->mHeader, &buffer[pos+total], sendAmount, gsi_true) == GS_UDP_SEND_FAILED)
break;
total += sendAmount;
remaining -= sendAmount;
}while (remaining);
}
if(clipSentData)
{
if (total > 0)
{
memmove(buffer, &buffer[total], remaining + 1);
len -= total;
}
}
else
{
pos += total;
}
// Set outputs.
///////////////
outputBuffer->len = (int)len;
outputBuffer->pos = (int)pos;
gsUdpEngineGetPeerState(ip, port, &aPeerState);
if (aPeerState == GS_UDP_PEER_CLOSED)
*closed = GPITrue;
else
*closed = GPIFalse;
return GP_NO_ERROR;
}
GPResult
gpiReadMessageFromBuffer(
GPConnection * connection,
GPIBuffer * inputBuffer,
char ** message,
int * type,
int * plen
)
{
char * str;
int len;
char intValue[16];
// Default.
///////////
*message = NULL;
// Check for not enough data.
/////////////////////////////
if(inputBuffer->len < 5)
return GP_NO_ERROR;
// Find the end of the header.
//////////////////////////////
str = strchr(inputBuffer->buffer, '\n');
if(str != NULL)
{
// Check that this is the msg.
//////////////////////////////
if(strncmp(str - 5, "\\msg\\", 5) != 0)
return GP_NETWORK_ERROR;
// Cap the header.
//////////////////
*str = '\0';
// Read the header.
///////////////////
if(!gpiValueForKey(inputBuffer->buffer, "\\m\\", intValue, sizeof(intValue)))
return GP_NETWORK_ERROR;
*type = atoi(intValue);
// Get the length.
//////////////////
if(!gpiValueForKey(inputBuffer->buffer, "\\len\\", intValue, sizeof(intValue)))
return GP_NETWORK_ERROR;
len = atoi(intValue);
len++;
// Is the whole message available?
//////////////////////////////////
if(inputBuffer->len > ((str - inputBuffer->buffer) + len))
{
// Does it not end with a NUL?
//////////////////////////////
if(str[len] != '\0')
return GP_NETWORK_ERROR;
// Set the message stuff.
/////////////////////////
*message = &str[1];
*plen = (len - 1);
// Set the position to the end of the message.
//////////////////////////////////////////////
inputBuffer->pos = ((str - inputBuffer->buffer) + len + 1);
}
else
{
// Put the LF back.
///////////////////
*str = '\n';
}
}
GSI_UNUSED(connection);
return GP_NO_ERROR;
}
GPResult
gpiClipBufferToPosition(
GPConnection * connection,
GPIBuffer * buffer
)
{
if(!buffer || !buffer->buffer || !buffer->pos)
return GP_NO_ERROR;
buffer->len -= buffer->pos;
if(buffer->len)
memmove(buffer->buffer, buffer->buffer + buffer->pos, (unsigned int)buffer->len);
buffer->buffer[buffer->len] = '\0';
buffer->pos = 0;
GSI_UNUSED(connection);
return GP_NO_ERROR;
}

167
code/gamespy/GP/gpiBuffer.h Normal file
View file

@ -0,0 +1,167 @@
/*
gpiBuffer.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIBUFFER_H_
#define _GPIBUFFER_H_
//INCLUDES
//////////
#include "gpi.h"
//TYPES
///////
// A buffer.
////////////
typedef struct
{
char * buffer;
int size;
int len;
int pos;
} GPIBuffer;
typedef struct GPIPeer_s * GPIPeer_st;
//FUNCTIONS
///////////
GPResult
gpiAppendCharToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
char c
);
GPResult
gpiAppendStringToBufferLen(
GPConnection * connection,
GPIBuffer * outputBuffer,
const char * string,
int stringLen
);
GPResult
gpiAppendStringToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
const char * buffer
);
GPResult gpiAppendShortToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
short num
);
GPResult gpiAppendUShortToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
unsigned short num
);
GPResult
gpiAppendIntToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
int num
);
GPResult
gpiAppendUIntToBuffer(
GPConnection * connection,
GPIBuffer * outputBuffer,
unsigned int num
);
GPResult
gpiSendOrBufferChar(
GPConnection * connection,
GPIPeer_st peer,
char c
);
/*
GPResult
gpiSendOrBufferStringLen(
GPConnection * connection,
GPIPeer_st peer,
const char * string,
int stringLen
);
*/
GPResult
gpiSendOrBufferStringLenToPeer(
GPConnection * connection,
GPIPeer_st peer,
const char * string,
int stringLen
);
GPResult
gpiSendOrBufferString(
GPConnection * connection,
GPIPeer_st peer,
char * string
);
GPResult
gpiSendOrBufferInt(
GPConnection * connection,
GPIPeer_st peer,
int num
);
GPResult
gpiSendOrBufferUInt(
GPConnection * connection,
GPIPeer_st peer,
unsigned int num
);
GPResult
gpiSendFromBuffer(
GPConnection * connection,
SOCKET sock,
GPIBuffer * outputBuffer,
GPIBool * connClosed,
GPIBool clipSentData,
char id[3]
);
GPResult
gpiRecvToBuffer(
GPConnection * connection,
SOCKET sock,
GPIBuffer * inputBuffer,
int * bytesRead,
GPIBool * connClosed,
char id[3]
);
GPResult
gpiReadMessageFromBuffer(
GPConnection * connection,
GPIBuffer * inputBuffer,
char ** message,
int * type,
int * len
);
GPResult
gpiClipBufferToPosition(
GPConnection * connection,
GPIBuffer * buffer
);
GPResult gpiSendBufferToPeer(GPConnection * connection, unsigned int ip, unsigned short port,
GPIBuffer * outputBuffer, GPIBool *closed, GPIBool clipSentData);
#endif

View file

@ -0,0 +1,277 @@
/*
gpiCallback.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include "gpi.h"
//FUNCTIONS
///////////
void
gpiCallErrorCallback(
GPConnection * connection,
GPResult result,
GPEnum fatal
)
{
GPICallback callback;
GPIConnection * iconnection = (GPIConnection*)*connection;
assert(iconnection != NULL);
assert(result != GP_NO_ERROR);
assert((fatal == GP_FATAL) || (fatal == GP_NON_FATAL));
if(fatal == GP_FATAL)
iconnection->fatalError = GPITrue;
callback = iconnection->callbacks[GPI_ERROR];
if(callback.callback != NULL)
{
GPErrorArg * arg;
arg = (GPErrorArg *)gsimalloc(sizeof(GPErrorArg));
if(arg != NULL)
{
arg->result = result;
arg->fatal = fatal;
arg->errorCode = iconnection->errorCode;
#ifndef GSI_UNICODE
arg->errorString = iconnection->errorString;
#else
arg->errorString = iconnection->errorString_W;
#endif
}
gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_ERROR);
}
}
GPResult
gpiAddCallback(
GPConnection * connection,
GPICallback callback,
void * arg,
const struct GPIOperation_s * operation,
int type
)
{
GPICallbackData * data;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Allocate the callback data.
//////////////////////////////
data = (GPICallbackData *)gsimalloc(sizeof(GPICallbackData));
if(data == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
data->callback = callback;
data->arg = arg;
if(operation != NULL)
data->operationID = operation->id;
else
data->operationID = 0;
data->type = type;
data->pnext = NULL;
// Update the list.
///////////////////
if(iconnection->callbackList == NULL)
iconnection->callbackList = data;
if(iconnection->lastCallback != NULL)
iconnection->lastCallback->pnext = data;
iconnection->lastCallback = data;
return GP_NO_ERROR;
}
static void
gpiCallCallback(
GPConnection * connection,
GPICallbackData * data
)
{
// Call the callback.
/////////////////////
assert(data->callback.callback != NULL);
assert(data->arg != NULL);
data->callback.callback(connection, data->arg, data->callback.param);
if(data->type == GPI_ADD_MESSAGE)
{
freeclear(((GPRecvBuddyMessageArg *)data->arg)->message);
}
else if (data->type == GPI_ADD_BUDDYUTM)
{
freeclear(((GPRecvBuddyUTMArg *)data->arg)->message);
}
else if(data->type == GPI_ADD_NICKS)
{
int i;
GPGetUserNicksResponseArg * arg = (GPGetUserNicksResponseArg *)data->arg;
for(i = 0 ; i < arg->numNicks ; i++)
{
freeclear(arg->nicks[i]);
freeclear(arg->uniquenicks[i]);
}
freeclear(arg->nicks);
freeclear(arg->uniquenicks)
}
else if(data->type == GPI_ADD_PMATCH)
{
GPFindPlayersResponseArg * arg = (GPFindPlayersResponseArg *)data->arg;
freeclear(arg->matches);
}
else if(data->type == GPI_ADD_TRANSFER_CALLBACK)
{
GPTransferCallbackArg * arg = (GPTransferCallbackArg *)data->arg;
if(arg->message)
freeclear(arg->message);
}
else if(data->type == GPI_ADD_REVERSE_BUDDIES)
{
GPGetReverseBuddiesResponseArg * arg = (GPGetReverseBuddiesResponseArg *)data->arg;
if(arg->profiles)
freeclear(arg->profiles);
}
else if(data->type == GPI_ADD_SUGGESTED_UNIQUE)
{
int i;
GPSuggestUniqueNickResponseArg * arg = (GPSuggestUniqueNickResponseArg *)data->arg;
for(i = 0 ; i < arg->numSuggestedNicks ; i++)
{
freeclear(arg->suggestedNicks[i]);
}
freeclear(arg->suggestedNicks);
}
else if (data->type == GPI_ADD_BUDDYREVOKE)
{
GPRecvBuddyRevokeArg * arg = (GPRecvBuddyRevokeArg *)data->arg;
// Remove the profile from our local lists AFTER the callback has been called
gpiDeleteBuddy(connection, arg->profile, GPIFalse);
}
else if (data->type == GPI_ADD_REVERSE_BUDDIES_LIST)
{
GPGetReverseBuddiesListResponseArg * arg = (GPGetReverseBuddiesListResponseArg *)data->arg;
if(arg->matches)
freeclear(arg->matches);
}
else if (data->type == GPI_ADD_BUDDYKEYS)
{
GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)data->arg;
if (arg->numKeys != 0)
{
int i;
for (i=0; i < arg->numKeys; i++)
{
freeclear(arg->keys[i]);
freeclear(arg->values[i]);
}
freeclear(arg->keys);
freeclear(arg->values);
}
}
freeclear(data->arg);
freeclear(data);
}
GPResult
gpiProcessCallbacks(
GPConnection * connection,
int blockingOperationID
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GPICallbackData * list;
GPICallbackData * last;
GPICallbackData * pcurr;
GPICallbackData * pnext;
GPICallbackData * pprev;
if(blockingOperationID != 0)
{
list = iconnection->callbackList;
last = iconnection->lastCallback;
iconnection->callbackList = NULL;
iconnection->lastCallback = NULL;
pprev = NULL;
for(pcurr = list ; pcurr != NULL ; )
{
pnext = pcurr->pnext;
if((pcurr->operationID == blockingOperationID) || (pcurr->type == GPI_ADD_ERROR))
{
// Take this one out of the list.
/////////////////////////////////
if(pprev != NULL)
pprev->pnext = pcurr->pnext;
else
list = pcurr->pnext;
if(last == pcurr)
last = pprev;
// Call the callback.
/////////////////////
gpiCallCallback(connection, pcurr);
}
else
{
pprev = pcurr;
}
pcurr = pnext;
}
// Were callbacks added within the callback?
////////////////////////////////////////////
if(iconnection->callbackList != NULL)
{
iconnection->lastCallback->pnext = list;
iconnection->lastCallback = last;
}
else
{
// Reset the list.
//////////////////
iconnection->callbackList = list;
iconnection->lastCallback = last;
}
return GP_NO_ERROR;
}
while(iconnection->callbackList != NULL)
{
list = iconnection->callbackList;
iconnection->callbackList = NULL;
iconnection->lastCallback = NULL;
for(pcurr = list ; pcurr != NULL ; pcurr = pnext)
{
pnext = pcurr->pnext;
// Call the callback.
/////////////////////
gpiCallCallback(connection, pcurr);
}
}
return GP_NO_ERROR;
}

View file

@ -0,0 +1,109 @@
/*
gpiCallback.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPICALLBACK_H_
#define _GPICALLBACK_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Unsolicited Callbacks.
/////////////////////////
enum GPICallbackId
{
GPI_ERROR = GP_ERROR,
GPI_RECV_BUDDY_REQUEST = GP_RECV_BUDDY_REQUEST,
GPI_RECV_BUDDY_STATUS = GP_RECV_BUDDY_STATUS,
GPI_RECV_BUDDY_MESSAGE = GP_RECV_BUDDY_MESSAGE,
GPI_RECV_BUDDY_UTM = GP_RECV_BUDDY_UTM,
GPI_RECV_GAME_INVITE = GP_RECV_GAME_INVITE,
GPI_TRANSFER_CALLBACK = GP_TRANSFER_CALLBACK,
GPI_RECV_BUDDY_AUTH = GP_RECV_BUDDY_AUTH,
GPI_RECV_BUDDY_REVOKE = GP_RECV_BUDDY_REVOKE,
GPI_NUM_CALLBACKS
};
// Add type - not 0 only for a few.
///////////////////////////////////
enum GPIAddCallbackType
{
GPI_ADD_NORMAL,
GPI_ADD_ERROR,
GPI_ADD_MESSAGE,
GPI_ADD_NICKS,
GPI_ADD_PMATCH,
GPI_ADD_STATUS,
GPI_ADD_BUDDDYREQUEST,
GPI_ADD_TRANSFER_CALLBACK,
GPI_ADD_REVERSE_BUDDIES,
GPI_ADD_SUGGESTED_UNIQUE,
GPI_ADD_BUDDYAUTH,
GPI_ADD_BUDDYUTM,
GPI_ADD_BUDDYREVOKE,
GPI_ADD_REVERSE_BUDDIES_LIST,
GPI_ADD_BUDDYKEYS,
GPI_NUM_ADD_CALLBACK_TYPES
};
//TYPES
///////
// A Callback.
//////////////
typedef struct
{
GPCallback callback;
void * param;
} GPICallback;
// Data for a pending callback.
///////////////////////////////
typedef struct GPICallbackData
{
GPICallback callback;
void * arg;
int type;
int operationID;
struct GPICallbackData * pnext;
} GPICallbackData;
//FUNCTIONS
///////////
void
gpiCallErrorCallback(
GPConnection * connection,
GPResult result,
GPEnum fatal
);
typedef struct GPIOperation_s *GPIOperation_st;
GPResult
gpiAddCallback(
GPConnection * connection,
GPICallback callback,
void * arg,
const struct GPIOperation_s * operation,
int type
);
GPResult
gpiProcessCallbacks(
GPConnection * connection,
int blockingOperationID
);
#endif

View file

@ -0,0 +1,988 @@
/*
gpiConnect.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdio.h>
#include <stdlib.h>
#include "gpi.h"
#include <string.h>
//DEFINES
/////////
// Connection Manager Address.
//////////////////////////////
#define GPI_CONNECTION_MANAGER_NAME "gpcm." GSI_DOMAIN_NAME
#define GPI_CONNECTION_MANAGER_PORT 29900
#define GPI_UDP_HEADER "gamespygp"
// Random String stuff.
///////////////////////
#define RANDSTRING "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
//this is off by one
//#define RANDOMCHAR() (RANDSTRING[(rand() * sizeof(RANDSTRING)) / (RAND_MAX + 1)])
#define RANDOMCHAR() (RANDSTRING[rand() % (sizeof(RANDSTRING) - 1)])
//GLOBALS
/////////
char GPConnectionManagerHostname[64] = GPI_CONNECTION_MANAGER_NAME;
//FUNCTIONS
///////////
static void randomString(
char * buffer,
int numChars
)
{
int i;
for(i = 0 ; i < numChars ; i++)
buffer[i] = RANDOMCHAR();
buffer[i] = '\0';
}
static GPResult
gpiStartConnect(
GPConnection * connection,
GPIOperation * operation
)
{
struct sockaddr_in address;
int rcode;
//int len;
GPIConnection * iconnection = (GPIConnection*)*connection;
struct hostent * host;
GSUdpErrorCode anError;
strncpy(iconnection->mHeader, GPI_UDP_HEADER, GS_UDP_MSG_HEADER_LEN);
if (!gsUdpEngineIsInitialized())
{
unsigned short peerPort = GPI_PEER_PORT;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Notice,
"Initializing UDP Layer\n");
anError = gsUdpEngineInitialize(peerPort, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (anError != GS_UDP_NO_ERROR)
{
while (anError != GS_UDP_NO_ERROR && peerPort < GPI_PEER_PORT + 100)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment,
"Port %d failed, trying next port\n", peerPort);
anError = gsUdpEngineInitialize(++peerPort, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
if (anError != GS_UDP_NO_ERROR)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError,
"Tryed all 100 ports after default port, giving up.\n");
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_UDP_LAYER,
"There was error starting the UDP layer.");
}
}
if (!iconnection->firewall)
{
iconnection->peerPort = peerPort;
}
}
else
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Notice,
"UDP Layer already initialized, using existing port.\n");
iconnection->peerPort = gsUdpEngineGetLocalPort();
}
anError = gsUdpEngineAddMsgHandler(iconnection->mHeader, iconnection->mHeader, NULL, gpiPeerAcceptedCallback, gpiPeerLeftCallback,
gpiPeerPingReplyCallback, gpiPeerMessageCallback, connection);
if (anError != GS_UDP_NO_ERROR)
{
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_UDP_LAYER, "There was an error starting the UDP Layer.");
}
if(iconnection->firewall)
{
/*
// Create the peer listening socket.
////////////////////////////////////
iconnection->peerSocket = socket(AF_INET, SOCK_STREAM, 0);
if(iconnection->peerSocket == INVALID_SOCKET)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error creating a socket.");
// Make it non-blocking.
////////////////////////
rcode = SetSockBlocking(iconnection->peerSocket,0);
if (rcode == 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error making a socket non-blocking.");
// Bind the socket.
///////////////////
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
rcode = bind(iconnection->peerSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in));
if(gsiSocketIsError(rcode))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error binding a socket.");
// Start listening on the socket.
/////////////////////////////////
rcode = listen(iconnection->peerSocket, SOMAXCONN);
if(gsiSocketIsError(rcode))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error listening on a socket.");
// Get the socket's port.
/////////////////////////
len = sizeof(struct sockaddr_in);
rcode = getsockname(iconnection->peerSocket, (struct sockaddr *)&address, &len);
if (gsiSocketIsError(rcode))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error getting a socket's addres.");
iconnection->peerPort = address.sin_port;
*/
iconnection->peerPort = 0;
}
/*
else
{
// Deprecated TCP code; Replaced by UDP Layer
// No local port.
/////////////////
//iconnection->peerSocket = INVALID_SOCKET;
// Set to nothing because NN will determine this
//////////////////////////
//iconnection->peerPort = 0;
}
*/
// Create the cm socket.
////////////////////////
iconnection->cmSocket = socket(AF_INET, SOCK_STREAM, 0);
if(iconnection->cmSocket == INVALID_SOCKET)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error creating a socket.");
// Make it non-blocking.
////////////////////////
rcode = SetSockBlocking(iconnection->cmSocket,0);
if(rcode == 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error making a socket non-blocking.");
/*
// Bind the socket.
///////////////////
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
rcode = bind(iconnection->cmSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in));
if (gsiSocketIsError(rcode))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error binding a socket.");
*/
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
// Get the server host.
///////////////////////
if (inet_addr(GPConnectionManagerHostname) == INADDR_NONE)
{
host = gethostbyname(GPConnectionManagerHostname);
if(host == NULL)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "Could not resolve connection mananger host name.");
address.sin_addr.s_addr = *(unsigned int *)host->h_addr_list[0];
//printf("Resolved Hostname and copied address: %s\n", inet_ntoa(address.sin_addr));
}
else
{
address.sin_addr.s_addr = inet_addr(GPConnectionManagerHostname);
//printf("Using hardcoded address: %s", GPConnectionManagerHostname);
}
// Connect the socket.
//////////////////////
assert(address.sin_addr.s_addr != 0);
address.sin_port = htons(GPI_CONNECTION_MANAGER_PORT);
rcode = connect(iconnection->cmSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in));
if (gsiSocketIsError(rcode))
{
int error = GOAGetLastError(iconnection->cmSocket);
if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT))
{
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error connecting a socket.");
}
}
// We're waiting for the connect to complete.
/////////////////////////////////////////////
operation->state = GPI_CONNECTING;
iconnection->connectState = GPI_CONNECTING;
return GP_NO_ERROR;
}
GPResult
gpiConnect(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char uniquenick[GP_UNIQUENICK_LEN],
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
const char authtoken[GP_AUTHTOKEN_LEN],
const char partnerchallenge[GP_PARTNERCHALLENGE_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum firewall,
GPIBool newuser,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnectData * data;
GPIOperation * operation;
GPIConnection * iconnection = (GPIConnection*)*connection;
GPResult result;
// Reset if this connection was already used.
/////////////////////////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
CHECK_RESULT(gpiReset(connection));
// Error check.
///////////////
if(iconnection->connectState != GPI_NOT_CONNECTED)
Error(connection, GP_PARAMETER_ERROR, "Invalid connection.");
// Get the firewall setting.
////////////////////////////
#if defined(GS_WIRELESS_DEVICE)
GSI_UNUSED(firewall);
iconnection->firewall = GPITrue;
#else
switch(firewall)
{
case GP_FIREWALL:
iconnection->firewall = GPITrue;
break;
case GP_NO_FIREWALL:
iconnection->firewall = GPIFalse;
break;
default:
Error(connection, GP_PARAMETER_ERROR, "Invalid firewall.");
}
#endif
// Get the nick, uniquenick, email, and password.
/////////////////////////////////////////////////
strzcpy(iconnection->nick, nick, GP_NICK_LEN);
strzcpy(iconnection->uniquenick, uniquenick, GP_UNIQUENICK_LEN);
strzcpy(iconnection->email, email, GP_EMAIL_LEN);
strzcpy(iconnection->password, password, GP_PASSWORD_LEN);
#ifdef GSI_UNICODE
// Create the _W version in addition
UTF8ToUCS2StringLen(iconnection->nick, iconnection->nick_W, GP_NICK_LEN);
UTF8ToUCS2StringLen(iconnection->uniquenick, iconnection->uniquenick_W, GP_UNIQUENICK_LEN);
UTF8ToUCS2StringLen(iconnection->email, iconnection->email_W, GP_EMAIL_LEN);
UTF8ToUCS2StringLen(iconnection->password, iconnection->password_W, GP_PASSWORD_LEN);
#endif
// Lowercase the email.
///////////////////////
_strlwr(iconnection->email);
#ifdef GSI_UNICODE
// Update the UCS2 version (emails are ASCII anyhow so lowercasing didn't data)
AsciiToUCS2String(iconnection->email, iconnection->email_W);
#endif
// Create a connect operation data struct.
//////////////////////////////////////////
data = (GPIConnectData *)gsimalloc(sizeof(GPIConnectData));
if(data == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(data, 0, sizeof(GPIConnectData));
// Check for new user.
//////////////////////
data->newuser = newuser;
// Store pre-auth data.
///////////////////////
if(authtoken[0] && partnerchallenge[0])
{
strzcpy(data->authtoken, authtoken, GP_AUTHTOKEN_LEN);
strzcpy(data->partnerchallenge, partnerchallenge, GP_PARTNERCHALLENGE_LEN);
}
// Store cdkey if we have one.
//////////////////////////////
if(cdkey)
strzcpy(data->cdkey, cdkey, GP_CDKEY_LEN);
// Add the operation to the list.
/////////////////////////////////
CHECK_RESULT(gpiAddOperation(connection, GPI_CONNECT, data, &operation, blocking, callback, param));
// Start it.
////////////
result = gpiStartConnect(connection, operation);
if(result != GP_NO_ERROR)
{
operation->result = result;
gpiFailedOpCallback(connection, operation);
gpiDisconnect(connection, GPIFalse);
return result;
}
// Process it if blocking.
//////////////////////////
if(operation->blocking)
CHECK_RESULT(gpiProcess(connection, operation->id));
return GP_NO_ERROR;
}
static GPResult
gpiSendLogin(
GPConnection * connection,
GPIConnectData * data
)
{
char buffer[512];
char response[33];
GPIConnection * iconnection = (GPIConnection*)*connection;
GPIProfile * profile;
char * passphrase;
char userBuffer[GP_NICK_LEN + GP_EMAIL_LEN];
char partnerBuffer[11];
char * user;
// Construct the user challenge.
////////////////////////////////
randomString(data->userChallenge, sizeof(data->userChallenge) - 1);
// Hash the password.
/////////////////////
if(data->partnerchallenge[0])
passphrase = data->partnerchallenge;
else
passphrase = iconnection->password;
MD5Digest((unsigned char*)passphrase, strlen(passphrase), data->passwordHash);
// Construct the user.
//////////////////////
if(iconnection->partnerID != GP_PARTNERID_GAMESPY)
{
sprintf(partnerBuffer, "%d@", iconnection->partnerID);
}
else
{
// GS ID's do not stash the partner ID in the auth challenge to support legacy clients.
strcpy(partnerBuffer, "");
}
if(data->authtoken[0])
user = data->authtoken;
else if(iconnection->uniquenick[0])
{
sprintf(userBuffer, "%s%s", partnerBuffer, iconnection->uniquenick);
user = userBuffer;
}
else
{
sprintf(userBuffer, "%s%s@%s", partnerBuffer, iconnection->nick, iconnection->email);
user = userBuffer;
}
// Construct the response.
//////////////////////////
sprintf(buffer, "%s%s%s%s%s%s",
data->passwordHash,
" ",
user,
data->userChallenge,
data->serverChallenge,
data->passwordHash);
MD5Digest((unsigned char *)buffer, strlen(buffer), response);
// Check for an existing profile.
/////////////////////////////////
if(iconnection->infoCaching)
{
gpiFindProfileByUser(connection, iconnection->nick, iconnection->email, &profile);
if(profile != NULL)
{
// Get the userid and profileid.
////////////////////////////////
iconnection->userid = profile->userId;
iconnection->profileid = profile->profileId;
}
}
// Construct the outgoing message.
//////////////////////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\login\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\challenge\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, data->userChallenge);
if(data->authtoken[0])
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\authtoken\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, data->authtoken);
}
else if(iconnection->uniquenick[0])
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\uniquenick\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->uniquenick);
}
else
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\user\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->nick);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "@");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->email);
}
if(iconnection->userid != 0)
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\userid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->userid);
}
if(iconnection->profileid != 0)
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\profileid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->profileid);
}
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\partnerid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->partnerID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\response\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, response);
if(iconnection->firewall == GP_FIREWALL)
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\firewall\\1");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\port\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->peerPort);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\productid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->productID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\gamename\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, __GSIACGamename);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\namespaceid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->namespaceID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sdkrevision\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, GPI_SDKREV);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\quiet\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->quietModeFlags);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\id\\1");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
static GPResult
gpiSendNewuser(
GPConnection * connection,
GPIConnectData * data
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
size_t i;
const int useAlternateEncoding = 1;
// Encrypt the password (xor with random values)
char passwordenc[GP_PASSWORDENC_LEN];
gpiEncodeString(iconnection->password, passwordenc);
// Construct the outgoing message.
//////////////////////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\newuser\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\email\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->email);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\nick\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->nick);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\passwordenc\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, passwordenc);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\productid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->productID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\gamename\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, __GSIACGamename);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\namespaceid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->namespaceID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\uniquenick\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, iconnection->uniquenick);
if(data->cdkey[0])
{
// Encrypt the cdkey (xor with random values)
char cdkeyxor[GP_CDKEY_LEN];
char cdkeyenc[GP_CDKEYENC_LEN];
size_t cdkeylen = strlen(data->cdkey);
Util_RandSeed((unsigned long)GP_XOR_SEED);
for (i=0; i < cdkeylen; i++)
{
// XOR each character with the next rand
char aRand = (char)Util_RandInt(0, 0xFF);
cdkeyxor[i] = (char)(data->cdkey[i] ^ aRand);
}
cdkeyxor[i] = '\0';
// Base 64 it (printable chars only)
B64Encode(cdkeyxor, cdkeyenc, (int)cdkeylen, useAlternateEncoding);
//gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\cdkey\\");
//gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, data->cdkey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\cdkeyenc\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, cdkeyenc);
}
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\partnerid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->partnerID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\id\\1");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
GPResult
gpiProcessConnect(
GPConnection * connection,
GPIOperation * operation,
const char * input
)
{
char buffer[512];
char check[33];
char uniquenick[GP_UNIQUENICK_LEN];
GPIConnectData * data;
GPIConnection * iconnection = (GPIConnection*)*connection;
GPICallback callback;
GPIProfile * profile;
char userBuffer[GP_NICK_LEN + GP_EMAIL_LEN];
char partnerBuffer[11];
char * user;
// Check for an error.
//////////////////////
if(gpiCheckForError(connection, input, GPIFalse))
{
// Is this a deleted profile?
/////////////////////////////
if((iconnection->errorCode == GP_LOGIN_PROFILE_DELETED) && iconnection->profileid)
{
// Remove this profile object.
//////////////////////////////
gpiRemoveProfileByID(connection, iconnection->profileid);
// If we have the profileid/userid cached, lose them.
/////////////////////////////////////////////////////
iconnection->userid = 0;
iconnection->profileid = 0;
}
// Check for creating an existing profile.
//////////////////////////////////////////
else if(iconnection->errorCode == GP_NEWUSER_BAD_NICK)
{
// Store the pid.
/////////////////
if(gpiValueForKey(input, "\\pid\\", buffer, sizeof(buffer)))
iconnection->profileid = atoi(buffer);
}
// Call the callbacks.
//////////////////////
CallbackFatalError(connection, GP_SERVER_ERROR, iconnection->errorCode, iconnection->errorString);
}
// Get a pointer to the data.
/////////////////////////////
data = (GPIConnectData*)operation->data;
switch(operation->state)
{
case GPI_CONNECTING:
// This should be \lc\1.
////////////////////////
if(strncmp(input, "\\lc\\1", 5) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Get the server challenge.
////////////////////////////
if(!gpiValueForKey(input, "\\challenge\\", data->serverChallenge, sizeof(data->serverChallenge)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Check if this is a new user.
///////////////////////////////
if(data->newuser)
{
// Send a new user message.
///////////////////////////
CHECK_RESULT(gpiSendNewuser(connection, data));
// Update the operation's state.
////////////////////////////////
operation->state = GPI_REQUESTING;
}
else
{
// Send a login message.
////////////////////////
CHECK_RESULT(gpiSendLogin(connection, data));
// Update the operation's state.
////////////////////////////////
operation->state = GPI_LOGIN;
}
break;
case GPI_REQUESTING:
// This should be \nur\.
////////////////////////
if(strncmp(input, "\\nur\\", 5) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Get the userid.
//////////////////
if(!gpiValueForKey(input, "\\userid\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
iconnection->userid = atoi(buffer);
// Get the profileid.
/////////////////////
if(!gpiValueForKey(input, "\\profileid\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
iconnection->profileid = atoi(buffer);
// Send a login request.
////////////////////////
CHECK_RESULT(gpiSendLogin(connection, data));
// Update the operation's state.
////////////////////////////////
operation->state = GPI_LOGIN;
break;
case GPI_LOGIN:
// This should be \lc\2.
////////////////////////
if(strncmp(input, "\\lc\\2", 5) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Get the sesskey.
///////////////////
if(!gpiValueForKey(input, "\\sesskey\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
iconnection->sessKey = atoi(buffer);
// Get the userid.
//////////////////
if(!gpiValueForKey(input, "\\userid\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
iconnection->userid = atoi(buffer);
// Get the profileid.
/////////////////////
if(!gpiValueForKey(input, "\\profileid\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
iconnection->profileid = atoi(buffer);
// Get the uniquenick.
//////////////////////
if(!gpiValueForKey(input, "\\uniquenick\\", uniquenick, sizeof(uniquenick)))
uniquenick[0] = '\0';
// Get the loginticket.
//////////////////////
if(!gpiValueForKey(input, "\\lt\\", iconnection->loginTicket, sizeof(iconnection->loginTicket)))
iconnection->loginTicket[0] = '\0';
// Construct the user.
//////////////////////
if(iconnection->partnerID != GP_PARTNERID_GAMESPY)
{
sprintf(partnerBuffer, "%d@", iconnection->partnerID);
}
else
{
// GS ID's do not stash the partner ID in the auth challenge to support legacy clients.
strcpy(partnerBuffer, "");
}
if(data->authtoken[0])
user = data->authtoken;
else if(iconnection->uniquenick[0])
{
sprintf(userBuffer, "%s%s", partnerBuffer, iconnection->uniquenick);
user = userBuffer;
}
else
{
sprintf(userBuffer, "%s%s@%s", partnerBuffer, iconnection->nick, iconnection->email);
user = userBuffer;
}
// Construct the check.
///////////////////////
sprintf(buffer, "%s%s%s%s%s%s",
data->passwordHash,
" ",
user,
data->serverChallenge,
data->userChallenge,
data->passwordHash);
MD5Digest((unsigned char *)buffer, strlen(buffer), check);
// Get the proof.
/////////////////
if(!gpiValueForKey(input, "\\proof\\", buffer, sizeof(buffer)))
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexepected data was received from the server.");
// Check the server authentication.
///////////////////////////////////
if(memcmp(check, buffer, 32) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_LOGIN_SERVER_AUTH_FAILED, "Could not authenticate server.");
// Add the local profile to the list.
/////////////////////////////////////
if(iconnection->infoCaching)
{
profile = gpiProfileListAdd(connection, iconnection->profileid);
profile->profileId = iconnection->profileid;
profile->userId = iconnection->userid;
}
// Set the connect state.
/////////////////////////
iconnection->connectState = GPI_CONNECTED;
// Call the connect-response callback.
//////////////////////////////////////
callback = operation->callback;
if(callback.callback != NULL)
{
GPConnectResponseArg * arg;
arg = (GPConnectResponseArg *)gsimalloc(sizeof(GPConnectResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPConnectResponseArg));
arg->profile = (GPProfile)iconnection->profileid;
arg->result = GP_NO_ERROR;
#ifndef GSI_UNICODE
strzcpy(arg->uniquenick, uniquenick, GP_UNIQUENICK_LEN);
#else
UTF8ToUCS2StringLen(uniquenick, arg->uniquenick, GP_UNIQUENICK_LEN);
#endif
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
}
// This operation is complete.
//////////////////////////////
gpiRemoveOperation(connection, operation);
// Get the local profile's info.
////////////////////////////////
#if 0
gpiAddOperation(connection, GPI_GET_INFO, NULL, &operation, GP_NON_BLOCKING, NULL, NULL);
gpiSendGetInfo(connection, iconnection->profileid, operation->id);
#endif
#ifdef _PS3
// We just connected, so setup buddy sync && start NP init
// For future, we can limit syncs by setting flags to turn on/off here
//////////////////////////////////////////////////////////////////////
iconnection->npPerformBuddySync = gsi_true;
iconnection->npPerformBlockSync = gsi_true;
iconnection->loginTime = current_time();
if (!iconnection->npInitialized)
gpiInitializeNpBasic(connection);
#endif
break;
default:
break;
}
return GP_NO_ERROR;
}
GPResult
gpiCheckConnect(
GPConnection * connection
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
int state;
// Check if the connection is completed.
////////////////////////////////////////
CHECK_RESULT(gpiCheckSocketConnect(connection, iconnection->cmSocket, &state));
// Check for a failed attempt.
//////////////////////////////
if(state == GPI_DISCONNECTED)
CallbackFatalError(connection, GP_SERVER_ERROR, GP_LOGIN_CONNECTION_FAILED, "The server has refused the connection.");
// Check if not finished connecting.
////////////////////////////////////
if(state == GPI_NOT_CONNECTED)
return GP_NO_ERROR;
// We're now negotiating the connection.
////////////////////////////////////////
assert(state == GPI_CONNECTED);
iconnection->connectState = GPI_NEGOTIATING;
return GP_NO_ERROR;
}
static GPIBool
gpiDisconnectCleanupProfile(
GPConnection * connection,
GPIProfile * profile,
void * data
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GSI_UNUSED(data);
// Even if we cache buddy/block info, free it up to get rid of mem
// leaks, just don't remove the profile until we save the cache.
//////////////////////////////////////////////////////////////////
if(profile->buddyStatus)
{
profile->buddyOrBlockCache = gsi_true;
freeclear(profile->buddyStatus->statusString);
freeclear(profile->buddyStatus->locationString);
freeclear(profile->buddyStatus);
}
if (profile->buddyStatusInfo)
{
profile->buddyOrBlockCache = gsi_true;
freeclear(profile->buddyStatusInfo->richStatus);
freeclear(profile->buddyStatusInfo->gameType);
freeclear(profile->buddyStatusInfo->gameVariant);
freeclear(profile->buddyStatusInfo->gameMapName);
if (profile->buddyStatusInfo->extendedInfoKeys)
{
ArrayFree(profile->buddyStatusInfo->extendedInfoKeys);
profile->buddyStatusInfo->extendedInfoKeys = NULL;
}
freeclear(profile->buddyStatusInfo);
}
if (profile->blocked)
profile->buddyOrBlockCache = gsi_true;
freeclear(profile->authSig);
freeclear(profile->peerSig);
profile->requestCount = 0;
// Remove Profile if:
// (there is no info to cache) or
// (we only cache buddies/blocked and the user is not a buddy or a block)
if ((!profile->cache) ||
(iconnection->infoCachingBuddyAndBlockOnly==GPITrue && !profile->buddyOrBlockCache))
{
gpiRemoveProfile(connection, profile);
return GPIFalse;
}
return GPITrue;
}
void
gpiDisconnect(
GPConnection * connection,
GPIBool tellServer
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GPIPeer * peer;
GPIPeer * delPeer;
GPIBool connClosed;
// Check if we're already disconnected.
// PANTS|05.15.00
///////////////////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
return;
// Skip most of this stuff if we never actually connected.
// PANTS|05.16.00
//////////////////////////////////////////////////////////
if(iconnection->connectState != GPI_NOT_CONNECTED)
{
// Are we connected?
////////////////////
if(tellServer && (iconnection->connectState == GPI_CONNECTED))
{
// Send the disconnect.
///////////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\logout\\\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
}
// Always flush remaining messages.
// PANTS|05.16.00
///////////////////////////////////
gpiSendFromBuffer(connection, iconnection->cmSocket, &iconnection->outputBuffer, &connClosed, GPITrue, "CM");
// Cleanup the connection.
//////////////////////////
if(iconnection->cmSocket != INVALID_SOCKET)
{
shutdown(iconnection->cmSocket, 2);
closesocket(iconnection->cmSocket);
iconnection->cmSocket = INVALID_SOCKET;
}
if(/*iconnection->peerSocket != INVALID_SOCKET*/ gsUdpEngineIsInitialized())
{
//shutdown(iconnection->peerSocket, 2);
//closesocket(iconnection->peerSocket);
//iconnection->peerSocket = INVALID_SOCKET;
gsUdpEngineRemoveMsgHandler(iconnection->mHeader);
if (gsUdpEngineNoMoreMsgHandlers() && gsUdpEngineNoApp())
gsUdpEngineShutdown();
}
// We're disconnected.
//////////////////////
iconnection->connectState = GPI_DISCONNECTED;
// Don't keep the userid/profileid.
///////////////////////////////////
iconnection->userid = 0;
iconnection->profileid = 0;
}
// freeclear all the memory.
///////////////////////
freeclear(iconnection->socketBuffer.buffer);
freeclear(iconnection->inputBuffer);
freeclear(iconnection->outputBuffer.buffer);
freeclear(iconnection->updateproBuffer.buffer);
freeclear(iconnection->updateuiBuffer.buffer);
while(iconnection->operationList != NULL)
gpiRemoveOperation(connection, iconnection->operationList);
iconnection->operationList = NULL;
for(peer = iconnection->peerList ; peer != NULL ; )
{
delPeer = peer;
peer = peer->pnext;
gpiDestroyPeer(connection, delPeer);
}
iconnection->peerList = NULL;
// Cleanup buddies.
// This is not optimal - because we can't continue the mapping
// after freeing a profile, we need to start it all over again.
///////////////////////////////////////////////////////////////
while(!gpiProfileMap(connection, gpiDisconnectCleanupProfile, NULL)) { };
}

View file

@ -0,0 +1,69 @@
/*
gpiConnect.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPICONNECT_H_
#define _GPICONNECT_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Connect States.
//////////////////
#define GPI_NOT_CONNECTED 0
#define GPI_CONNECTING 1
#define GPI_NEGOTIATING 2
#define GPI_CONNECTED 3
#define GPI_DISCONNECTED 4
#define GPI_PROFILE_DELETING 5
//FUNCTIONS
///////////
GPResult
gpiConnect(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char uniquenick[GP_UNIQUENICK_LEN],
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
const char authtoken[GP_AUTHTOKEN_LEN],
const char partnerchallenge[GP_PARTNERCHALLENGE_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum firewall,
GPIBool newuser,
GPEnum blocking,
GPCallback callback,
void * param
);
void
gpiDisconnect(
GPConnection * connection,
GPIBool tellServer
);
GPResult
gpiProcessConnect(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
GPResult
gpiCheckConnect(
GPConnection * connection
);
#endif

1286
code/gamespy/GP/gpiInfo.c Normal file

File diff suppressed because it is too large Load diff

144
code/gamespy/GP/gpiInfo.h Normal file
View file

@ -0,0 +1,144 @@
/*
gpiInfo.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIINFO_H_
#define _GPIINFO_H_
//INCLUDES
//////////
#include "gpi.h"
//TYPES
///////
// Profile info cache.
//////////////////////
typedef struct
{
char * nick;
char * uniquenick;
char * email;
char * firstname;
char * lastname;
char * homepage;
int icquin;
char zipcode[GP_ZIPCODE_LEN];
char countrycode[GP_COUNTRYCODE_LEN];
float longitude; // negative is west, positive is east. (0, 0) means unknown.
float latitude; // negative is south, positive is north. (0, 0) means unknown.
char place[GP_PLACE_LEN]; // e.g., "USA|California|Irvine", "South Korea|Seoul", "Turkey"
int birthday;
int birthmonth;
int birthyear;
GPEnum sex;
int publicmask;
char * aimname;
int pic;
int occupationid;
int industryid;
int incomeid;
int marriedid;
int childcount;
int interests1;
int ownership1;
int conntypeid;
} GPIInfoCache;
//FUNCTIONS
///////////
GPResult
gpiSetInfoi(
GPConnection * connection,
GPEnum info,
int value
);
GPResult
gpiSetInfos(
GPConnection * connection,
GPEnum info,
const char * value
);
GPResult
gpiSetInfod(
GPConnection * connection,
GPEnum info,
int day,
int month,
int year
);
GPResult
gpiSetInfoMask(
GPConnection * connection,
GPEnum mask
);
void
gpiInfoCacheToArg(
const GPIInfoCache * cache,
GPGetInfoResponseArg * arg
);
GPResult
gpiGetInfo(
GPConnection * connection,
GPProfile profile,
GPEnum checkCache,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiGetInfoNoWait(
GPConnection * connection,
GPProfile profile,
GPGetInfoResponseArg * arg
);
GPResult
gpiProcessGetInfo(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
GPResult
gpiSendGetInfo(
GPConnection * connection,
int profileid,
int operationid
);
GPResult
gpiAddLocalInfo(
GPConnection * connection,
GPIBuffer * buffer
);
typedef struct GPIProfile *pGPIProfile;
GPIBool
gpiSetInfoCache(
GPConnection * connection,
pGPIProfile profile,
const GPIInfoCache * cache
);
void
gpiFreeInfoCache(
pGPIProfile profile
);
#endif

196
code/gamespy/GP/gpiKeys.c Normal file
View file

@ -0,0 +1,196 @@
#include "gpi.h"
void gpiStatusInfoKeyFree(void *element)
{
GPIKey *aKey = (GPIKey *)element;
freeclear(aKey->keyName);
freeclear(aKey->keyValue);
}
GPResult gpiStatusInfoKeysInit(GPConnection * connection)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
iconnection->extendedInfoKeys = ArrayNew(sizeof(GPIKey), GPI_INITIAL_NUM_KEYS, gpiStatusInfoKeyFree);
if(!iconnection->extendedInfoKeys)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
return GP_NO_ERROR;
}
void gpiStatusInfoKeysDestroy(GPConnection * connection)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
if (iconnection->extendedInfoKeys)
{
ArrayFree(iconnection->extendedInfoKeys);
iconnection->extendedInfoKeys = NULL;
}
}
int gpiStatusInfoKeyCompFunc(const void *elem1, const void *elem2)
{
GPIKey *key1 = (GPIKey *)elem1,
*key2 = (GPIKey *)elem2;
return strcmp(key1->keyName, key2->keyName);
}
GPResult gpiStatusInfoAddKey(GPConnection *connection, DArray keys, const char *theKeyName, const char *theKeyValue)
{
GPIKey aKey;
GS_ASSERT(keys);
GS_ASSERT(theKeyName);
GS_ASSERT(theKeyValue);
if (!theKeyName)
Error(connection, GP_PARAMETER_ERROR, "Invalid key name");
if (!theKeyValue)
Error(connection, GP_PARAMETER_ERROR, "Invalid key value");
aKey.keyName = goastrdup(theKeyName);
aKey.keyValue = goastrdup(theKeyValue);
ArrayInsertSorted(keys, &aKey, gpiStatusInfoKeyCompFunc);
return GP_NO_ERROR;
}
GPResult gpiStatusInfoDelKey(GPConnection *connection, DArray keys, const char *keyName)
{
GPIKey aKey;
int anIndex;
GS_ASSERT(keys);
GS_ASSERT(keyName);
if (!keyName)
Error(connection, GP_PARAMETER_ERROR, "Invalid key name");
aKey.keyName = goastrdup(keyName);
anIndex = ArraySearch(keys, &aKey, gpiStatusInfoKeyCompFunc, 0, 1);
if (anIndex != NOT_FOUND)
{
ArrayDeleteAt(keys, anIndex);
}
freeclear(aKey.keyName);
return GP_NO_ERROR;
}
GPResult gpiStatusInfoSetKey(GPConnection *connection, DArray keys, const char *keyName, const char *newKeyValue)
{
GPIKey aKey;
int anIndex;
GS_ASSERT(keys);
GS_ASSERT(keyName);
if (!keyName)
Error(connection, GP_PARAMETER_ERROR, "Invalid key name");
aKey.keyName = goastrdup(keyName);
anIndex = ArraySearch(keys, &aKey, gpiStatusInfoKeyCompFunc, 0, 1);
if (anIndex != NOT_FOUND)
{
GPIKey *aKeyFound = (GPIKey *)ArrayNth(keys, anIndex);
gsifree(aKeyFound->keyValue);
aKeyFound->keyValue = goastrdup(newKeyValue);
}
freeclear(aKey.keyName);
return GP_NO_ERROR;
}
GPResult gpiStatusInfoGetKey(GPConnection *connection, DArray keys, const char *keyName, char **keyValue)
{
GPIKey aKey;
int anIndex;
GS_ASSERT(keys);
GS_ASSERT(keyName);
if (!keyName)
Error(connection, GP_PARAMETER_ERROR, "Invalid key name");
aKey.keyName = goastrdup(keyName);
anIndex = ArraySearch(keys, &aKey, gpiStatusInfoKeyCompFunc, 0, 1);
if (anIndex != NOT_FOUND)
{
GPIKey *aKeyFound = (GPIKey *)ArrayNth(keys, anIndex);
*keyValue = goastrdup(aKeyFound->keyValue);
}
freeclear(aKey.keyName);
return GP_NO_ERROR;
}
GPResult gpiStatusInfoCheckKey(GPConnection *connection, DArray keys, const char *keyName, char **keyValue)
{
GPIKey aKey;
int anIndex;
GS_ASSERT(keys);
GS_ASSERT(keyName);
if (!keyName)
Error(connection, GP_PARAMETER_ERROR, "Invalid key name");
aKey.keyName = goastrdup(keyName);
anIndex = ArraySearch(keys, &aKey, gpiStatusInfoKeyCompFunc, 0, 1);
if (anIndex != NOT_FOUND)
{
GPIKey *aKeyFound = (GPIKey *)ArrayNth(keys, anIndex);
*keyValue = aKeyFound->keyValue;
}
freeclear(aKey.keyName);
return GP_NO_ERROR;
}
GPResult gpiSaveKeysToBuffer(GPConnection *connection, char **buffer)
{
GPIConnection *iconnection = (GPIConnection *)*connection;
char *tempPoint;
int sizeKeys = 0, i, bytesWritten;
int base64KeyNameLen, base64KeyValLen;
int aLength = ArrayLength(iconnection->extendedInfoKeys);
char keysHeader[64];
sprintf(keysHeader, "\\keys\\%d", aLength);
// figure out the size of the buffer to allocate
// by adding up the key value pairs with backslashes
for (i = 0; i < aLength; i++)
{
GPIKey *aKey = (GPIKey *)ArrayNth(iconnection->extendedInfoKeys, i);
if (strlen(aKey->keyName) % 3 != 0)
base64KeyNameLen = (int)(strlen(aKey->keyName) * 4 / 3) + (int)(4 - (strlen(aKey->keyName) % 3));
else
base64KeyNameLen = (int)(strlen(aKey->keyName) * 4 / 3);
if (strlen(aKey->keyValue) % 3 != 0)
base64KeyValLen= (int)(strlen(aKey->keyValue) * 4 / 3) + (int)(4 - (strlen(aKey->keyValue) % 3));
else
base64KeyValLen = (int)(strlen(aKey->keyValue) * 4 / 3);
sizeKeys += 1 + base64KeyNameLen + 1 + base64KeyValLen;
}
*buffer = (char *)gsimalloc(strlen(keysHeader) + (size_t)sizeKeys + 1);
if (*buffer == NULL)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Memory, GSIDebugLevel_HotError, "gpiSaveKeysToBuffer: buffer Out of memory.");
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
bytesWritten = sprintf(*buffer, keysHeader);
tempPoint = *buffer + bytesWritten;
for (i = 0; i < aLength; i++)
{
GPIKey *aKey = (GPIKey *)ArrayNth(iconnection->extendedInfoKeys, i);
strcat(tempPoint, "\\");
tempPoint++;
B64Encode(aKey->keyName, tempPoint, (int)strlen(aKey->keyName), 2);
if (strlen(aKey->keyName) % 3 != 0)
tempPoint+= (int)(strlen(aKey->keyName) * 4 / 3) + (4 - (strlen(aKey->keyName) % 3));
else
tempPoint+= (int)(strlen(aKey->keyName) * 4 / 3);
strcat(tempPoint, "\\");
tempPoint++;
B64Encode(aKey->keyValue, tempPoint, (int)strlen(aKey->keyValue), 2);
if (strlen(aKey->keyValue) % 3 != 0)
tempPoint+= (int)(strlen(aKey->keyValue) * 4 / 3) + (4 - (strlen(aKey->keyValue) % 3));
else
tempPoint+= (int)(strlen(aKey->keyValue) * 4 / 3);
}
return GP_NO_ERROR;
}

23
code/gamespy/GP/gpiKeys.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef _GPIKEYS_H_
#define _GPIKEYS_H_
#include "gpi.h"
#define GPI_INITIAL_NUM_KEYS 1
typedef struct
{
char *keyName;
char *keyValue;
} GPIKey;
void gpiStatusInfoKeyFree(void *element);
GPResult gpiStatusInfoKeysInit(GPConnection * connection);
void gpiStatusInfoKeysDestroy(GPConnection * connection);
int gpiStatusInfoKeyCompFunc(const void *elem1, const void *elem2);
GPResult gpiStatusInfoAddKey(GPConnection *connection, DArray keys, const char *theKeyName, const char *theKeyValue);
GPResult gpiStatusInfoDelKey(GPConnection *connection, DArray keys, const char *keyName);
GPResult gpiStatusInfoSetKey(GPConnection *connection, DArray keys, const char *keyName, const char *newKeyValue);
GPResult gpiStatusInfoGetKey(GPConnection *connection, DArray keys, const char *keyName, char **keyValue);
GPResult gpiSaveKeysToBuffer(GPConnection *connection, char **buffer);
GPResult gpiStatusInfoCheckKey(GPConnection *connection, DArray keys, const char *keyName, char **keyValue);
#endif

View file

@ -0,0 +1,363 @@
/*
gpiOperation.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include "gpi.h"
//FUNCTIONS
///////////
GPResult
gpiFailedOpCallback(
GPConnection * connection,
const GPIOperation * operation
)
{
GPICallback callback;
GPIConnection * iconnection = (GPIConnection*)*connection;
assert(connection != NULL);
assert(*connection != NULL);
assert(operation != NULL);
callback = operation->callback;
if(callback.callback != NULL)
{
// Handle based on operation type.
//////////////////////////////////
switch(operation->type)
{
case GPI_CONNECT:
{
GPConnectResponseArg * arg;
arg = (GPConnectResponseArg *)gsimalloc(sizeof(GPConnectResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPConnectResponseArg));
arg->result = operation->result;
if(iconnection->errorCode == GP_NEWUSER_BAD_NICK)
{
arg->profile = (GPProfile)iconnection->profileid;
iconnection->profileid = 0;
}
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_NEW_PROFILE:
{
GPNewProfileResponseArg * arg;
arg = (GPNewProfileResponseArg *)gsimalloc(sizeof(GPNewProfileResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPNewProfileResponseArg));
arg->result = operation->result;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_DELETE_PROFILE:
{
GPDeleteProfileResponseArg * arg;
arg = (GPDeleteProfileResponseArg *)gsimalloc(sizeof(GPDeleteProfileResponseArg));
if (arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPDeleteProfileResponseArg));
arg->result = operation->result;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_GET_INFO:
{
GPGetInfoResponseArg * arg;
arg = (GPGetInfoResponseArg *)gsimalloc(sizeof(GPGetInfoResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPGetInfoResponseArg));
arg->result = operation->result;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_PROFILE_SEARCH:
{
GPProfileSearchResponseArg * arg;
arg = (GPProfileSearchResponseArg *)gsimalloc(sizeof(GPProfileSearchResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPProfileSearchResponseArg));
arg->result = operation->result;
((GPProfileSearchResponseArg *)arg)->matches = NULL;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_REGISTER_UNIQUENICK:
{
GPRegisterUniqueNickResponseArg * arg;
arg = (GPRegisterUniqueNickResponseArg *)gsimalloc(sizeof(GPRegisterUniqueNickResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPRegisterUniqueNickResponseArg));
arg->result = operation->result;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
case GPI_REGISTER_CDKEY:
{
GPRegisterCdKeyResponseArg * arg;
arg = (GPRegisterCdKeyResponseArg *)gsimalloc(sizeof(GPRegisterCdKeyResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
memset(arg, 0, sizeof(GPRegisterCdKeyResponseArg));
arg->result = operation->result;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
break;
}
default:
assert(0);
}
}
return GP_NO_ERROR;
}
GPResult
gpiAddOperation(
GPConnection * connection,
int type,
void * data,
GPIOperation ** op,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIOperation * operation;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Create a new operation struct.
/////////////////////////////////
operation = (GPIOperation *)gsimalloc(sizeof(GPIOperation));
if(operation == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
// Set the data.
////////////////
operation->type = type;
operation->data = data;
operation->blocking = (GPIBool)blocking;
operation->state = GPI_START;
if(type == GPI_CONNECT)
{
// Connect is always ID 1.
//////////////////////////
operation->id = 1;
}
else
{
operation->id = iconnection->nextOperationID++;
if(iconnection->nextOperationID < 2)
iconnection->nextOperationID = 2;
}
operation->result = GP_NO_ERROR;
operation->callback.callback = callback;
operation->callback.param = param;
// Add it to the list.
//////////////////////
operation->pnext = iconnection->operationList;
iconnection->operationList = operation;
*op = operation;
return GP_NO_ERROR;
}
void
gpiDestroyOperation(
GPConnection * connection,
GPIOperation * operation
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Search?
//////////
if(operation->type == GPI_PROFILE_SEARCH)
{
GPISearchData * data = (GPISearchData *)operation->data;
// One less.
////////////
iconnection->numSearches--;
assert(iconnection->numSearches >= 0);
// Close the socket.
////////////////////
shutdown(data->sock, 2);
closesocket(data->sock);
// freeclear the buffers.
////////////////////
freeclear(data->outputBuffer.buffer);
freeclear(data->inputBuffer.buffer);
}
// freeclear the data.
/////////////////
freeclear(operation->data);
// freeclear the operation struct.
/////////////////////////////
freeclear(operation);
}
void
gpiRemoveOperation(
GPConnection * connection,
GPIOperation * operation
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
GPIOperation * pcurr = iconnection->operationList;
GPIOperation * pprev = NULL;
// Go through the list of operations.
/////////////////////////////////////
while(pcurr != NULL)
{
// Check for a match.
/////////////////////
if(pcurr == operation)
{
// Update the list.
///////////////////
if(pprev == NULL)
iconnection->operationList = pcurr->pnext;
else
pprev->pnext = operation->pnext;
gpiDestroyOperation(connection, operation);
return;
}
pprev = pcurr;
pcurr = pcurr->pnext;
}
}
GPIBool
gpiFindOperationByID(
const GPConnection * connection,
GPIOperation ** operation,
int id
)
{
GPIOperation * op;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Go through the list of operations.
/////////////////////////////////////
for(op = iconnection->operationList ; op != NULL ; op = op->pnext)
{
// Check the id.
////////////////
if(op->id == id)
{
// Found it.
////////////
if(operation != NULL)
*operation = op;
return GPITrue;
}
}
// Didn't find it.
//////////////////
if(operation != NULL)
*operation = NULL;
return GPIFalse;
}
GPIBool
gpiOperationsAreBlocking(
const GPConnection * connection
)
{
GPIOperation * operation;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Loop through the operations.
///////////////////////////////
for(operation = iconnection->operationList ; operation != NULL ; operation = operation->pnext)
{
// Check if it's blocking.
//////////////////////////
if((operation->blocking) && (operation->type != GPI_PROFILE_SEARCH))
return GPITrue;
}
// Nothing was blocking.
////////////////////////
return GPIFalse;
}
GPResult
gpiProcessOperation(
GPConnection * connection,
GPIOperation * operation,
const char * input
)
{
GPResult result = GP_NO_ERROR;
// Check the operation type.
////////////////////////////
switch(operation->type)
{
case GPI_CONNECT:
result = gpiProcessConnect(connection, operation, input);
break;
case GPI_NEW_PROFILE:
result = gpiProcessNewProfile(connection, operation, input);
break;
case GPI_DELETE_PROFILE:
result = gpiProcessDeleteProfle(connection, operation, input);
break;
case GPI_GET_INFO:
result = gpiProcessGetInfo(connection, operation, input);
break;
case GPI_REGISTER_UNIQUENICK:
result = gpiProcessRegisterUniqueNick(connection, operation, input);
break;
case GPI_REGISTER_CDKEY:
result = gpiProcessRegisterCdKey(connection, operation, input);
break;
default:
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiProcessOperation was passed an operation with an invalid type (%d)\n", operation->type);
assert(0);
break;
}
if(result != GP_NO_ERROR)
operation->result = result;
return result;
}

View file

@ -0,0 +1,120 @@
/*
gpiOperation.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIOPERATION_H_
#define _GPIOPERATION_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Operation Types.
///////////////////
#define GPI_CONNECT 0
#define GPI_NEW_PROFILE 1
#define GPI_GET_INFO 2
#define GPI_PROFILE_SEARCH 3
#define GPI_REGISTER_UNIQUENICK 4
#define GPI_DELETE_PROFILE 5
#define GPI_REGISTER_CDKEY 6
// Operation States.
////////////////////
#define GPI_START 0
//#define GPI_CONNECTING 1
#define GPI_LOGIN 2
#define GPI_REQUESTING 3
#define GPI_WAITING 4
#define GPI_FINISHING 5
//TYPES
///////
// Operation data.
//////////////////
typedef struct GPIOperation_s
{
int type;
void * data;
GPIBool blocking;
GPICallback callback;
int state;
int id;
GPResult result;
struct GPIOperation_s * pnext;
} GPIOperation;
// Connect operation data.
//////////////////////////
typedef struct
{
char serverChallenge[128];
char userChallenge[33];
char passwordHash[33];
char authtoken[GP_AUTHTOKEN_LEN];
char partnerchallenge[GP_PARTNERCHALLENGE_LEN];
char cdkey[GP_CDKEY_LEN];
GPIBool newuser;
} GPIConnectData;
//FUNCTIONS
///////////
GPResult
gpiAddOperation(
GPConnection * connection,
int type,
void * data,
GPIOperation ** op,
GPEnum blocking,
GPCallback callback,
void * param
);
void
gpiRemoveOperation(
GPConnection * connection,
GPIOperation * operation
);
void
gpiDestroyOperation(
GPConnection * connection,
GPIOperation * operation
);
GPIBool
gpiFindOperationByID(
const GPConnection * connection,
GPIOperation ** operation,
int id
);
GPIBool
gpiOperationsAreBlocking(
const GPConnection * connection
);
GPResult
gpiProcessOperation(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
GPResult
gpiFailedOpCallback(
GPConnection * connection,
const GPIOperation * operation
);
#endif

592
code/gamespy/GP/gpiPS3.c Normal file
View file

@ -0,0 +1,592 @@
/*
gpiPS3.c
GameSpy Presence SDK
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include <string.h>
#include "gpi.h"
#ifdef _PS3
//GLOBALS
//////////
uint8_t gpi_np_pool[SCE_NP_MIN_POOL_SIZE];
SceNpCommunicationId gpi_communication_id = {
{'N','P','X','S','0','0','0','0','5'},
'\0',
0,
0
};
//FUNCTIONS
///////////
int gpiNpBasicCallback(
int event,
int retCode,
uint32_t reqId,
void *arg
)
{
// No-op - can ignore any events
////////////////////////////////
return 0;
}
GPResult gpiInitializeNpBasic(
GPConnection * connection
)
{
int ret = 0;
GPIConnection * iconnection = (GPIConnection*)*connection;
iconnection->npInitialized = gsi_true;
// Initial NP init - after this we wait for status to get to online
////////////////////////////////////////////////////////////////////
ret = sceNpInit(SCE_NP_MIN_POOL_SIZE, gpi_np_pool);
if (ret == SCE_NP_ERROR_ALREADY_INITIALIZED)
{
// If already initialized - DO NOT terminate after sync (game might need it)
////////////////////////////////////////////////////////////////////////////
iconnection->npBasicGameInitialized = gsi_true;
}
else if (ret < 0)
{
iconnection->npBasicGameInitialized = gsi_true;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiInitializeNpBasic: sceNpInit() failed, NP-functionality disabled. ret = 0x%x\n", ret);
return GP_MISC_ERROR;
}
else
iconnection->npBasicGameInitialized = gsi_false; //GP initialized, so destroy after complete
return GP_NO_ERROR;
}
// Freeing up transaction list darray
void gpiNpTransactionListFree(void *element)
{
npIdLookupTrans *aTrans = (npIdLookupTrans *)element;
freeclear(aTrans->npIdForAdd);
}
GPResult gpiCheckNpStatus(
GPConnection * connection
)
{
int ret = 0;
int status = SCE_NP_MANAGER_STATUS_OFFLINE;
SceNpId npId;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Get NP status
////////////////
ret = sceNpManagerGetStatus(&status);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpGetStatus() failed. ret = 0x%x\n", ret);
}
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"gpiCheckNpStatus: sceNpGetStatus - status = %d\n", status);
// If NP status != online after the timeout period, stop syncing
////////////////////////////////////////////////////////////////
if (status != SCE_NP_MANAGER_STATUS_ONLINE && (current_time() - iconnection->loginTime > GPI_NP_STATUS_TIMEOUT))
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: NP Status not online - timed out\n");
// Flag to stop the sync process
////////////////////////////////
iconnection->npPerformBuddySync = gsi_false;
iconnection->npPerformBlockSync = gsi_false;
return GP_MISC_ERROR;
}
// Once status is online, finish NP init
////////////////////////////////////////
if (status == SCE_NP_MANAGER_STATUS_ONLINE)
{
iconnection->loginTime = current_time();
// Note - we ignore error messages here - if something fails we really don't care
/////////////////////////////////////////////////////////////////////////////////
if (!iconnection->npBasicGameInitialized)
{
ret = sceNpBasicInit(); //obsolete?
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpBasicInit() failed. ret = 0x%x\n", ret);
}
ret = sceNpBasicRegisterHandler(&gpi_communication_id, gpiNpBasicCallback, NULL);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpBasicRegisterHandler() failed. ret = 0x%x\n", ret);
}
}
ret = sceNpLookupInit();
if (ret == SCE_NP_COMMUNITY_ERROR_ALREADY_INITIALIZED)
{
// If already initialized - DO NOT terminate after GP destroy (game might need it)
//////////////////////////////////////////////////////////////////////////////////
iconnection->npLookupGameInitialized = gsi_true;
}
else if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpLookupInit() failed. ret = 0x%x\n", ret);
iconnection->npLookupGameInitialized = gsi_true;
}
else
iconnection->npLookupGameInitialized = gsi_false;
// Regardless of game, create a title context id for GP to use for lookups
///////////////////////////////////////////////////////////////////////////
ret = sceNpManagerGetNpId(&npId);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpManagerGetNpId() failed. ret = 0x%x\n", ret);
}
ret = sceNpLookupCreateTitleCtx(&gpi_communication_id, &npId);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"gpiCheckNpStatus: sceNpLookupCreateTitleCtx() failed. ret = 0x%x\n", ret);
}
iconnection->npLookupTitleCtxId = ret;
// Mark status retrieval completed
//////////////////////////////////
iconnection->npStatusRetrieved = gsi_true;
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"gpiCheckNpStatus: NP is now initialized with status.\n");
iconnection->npTransactionList = ArrayNew(sizeof(npIdLookupTrans), 1, gpiNpTransactionListFree);
if (!iconnection->npTransactionList)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
return GP_NO_ERROR;
}
GPResult gpiDestroyNpBasic(
GPConnection * connection
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Explicitly destroy title context we used for lookup
//////////////////////////////////////////////////////
if (iconnection->npLookupTitleCtxId >= 0)
sceNpLookupDestroyTitleCtx(iconnection->npLookupTitleCtxId);
// Do not destroy NpLookup or NpBasic if Game is using it
/////////////////////////////////////////////////////////
if (!iconnection->npLookupGameInitialized)
sceNpLookupTerm();
if (!iconnection->npBasicGameInitialized)
{
sceNpBasicUnregisterHandler();
// Obsolete?
sceNpBasicTerm();
sceNpTerm();
}
// Free up transaction list used for NP lookups
///////////////////////////////////////////////
if (iconnection->npTransactionList)
ArrayFree(iconnection->npTransactionList);
iconnection->npInitialized = gsi_false;
iconnection->npStatusRetrieved = gsi_false;
return GP_NO_ERROR;
}
GPResult gpiSyncNpBuddies(
GPConnection * connection
)
{
int ret;
SceNpId npId; //Buffer to store friend list entry's NP ID
gsi_u32 i, count = 0;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Flag sync as complete so we don't do it more than once per login
////////////////////////////////////////////////////////////////////
iconnection->npPerformBuddySync = gsi_false;
// Get buddy count
///////////////////
ret = sceNpBasicGetFriendListEntryCount(&count);
if ( ret < 0 )
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BuddySync: Failed to get NP friend list count\n");
}
// Loop through each buddy, check for existence of GSID account
///////////////////////////////////////////////////////////////
for (i = 0; i < count; i++)
{
memset(&npId, 0x00, sizeof(npId));
ret = sceNpBasicGetFriendListEntry(i, &npId);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BuddySync: Failed to get NP friend entry #%d\n", i);
return GP_MISC_ERROR;
}
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BuddySync: NP friend entry #%d, npid = %s. Queueing Search.\n", i, npId.handle.data);
gpiProfileSearchUniquenick(connection, npId.handle.data, &iconnection->namespaceID,
1, GP_NON_BLOCKING, (GPCallback)gpiSyncNpBuddiesCallback, NULL);
}
return GP_NO_ERROR;
}
void gpiSyncNpBuddiesCallback(
GPConnection * pconnection,
GPProfileSearchResponseArg * arg,
void * param
)
{
if(arg->result == GP_NO_ERROR)
{
if(arg->numMatches == 1)
{
// Check if already a buddy
////////////////////////////
if (!gpIsBuddy(pconnection, arg->matches[0].profile))
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BuddySync: NP Buddy \"%s\" found in namespace %d. Sending Request.\n",
arg->matches[0].uniquenick, arg->matches[0].namespaceID);
// Send the add request
////////////////////////
gpSendBuddyRequest(pconnection, arg->matches[0].profile, _T("PS3 Buddy Sync"));
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BuddySync: \"%s\" is already a buddy\n", arg->matches[0].uniquenick);
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BuddySync: No suitable match found\n");
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BuddySync: Buddy Search FAILED!\n");
GSI_UNUSED(pconnection);
GSI_UNUSED(param);
}
GPResult gpiSyncNpBlockList(
GPConnection * connection
)
{
int ret;
SceNpId npId; //Buffer to store block list entry's NP ID
gsi_u32 i, count = 0;
GPIConnection * iconnection = (GPIConnection*)*connection;
// Flag sync as complete so we don't do it more than once per login
////////////////////////////////////////////////////////////////////
iconnection->npPerformBlockSync = gsi_false;
// Get block list count
///////////////////////
ret = sceNpBasicGetBlockListEntryCount(&count);
if ( ret < 0 )
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BlockSync: Failed to get NP block list count\n");
}
// Loop through each entry, check for existence of GSID account
///////////////////////////////////////////////////////////////
for (i = 0; i < count; i++)
{
memset(&npId, 0x00, sizeof(npId));
ret = sceNpBasicGetBlockListEntry(i, &npId);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BlockSync: Failed to get NP block entry #%d\n", i);
return GP_MISC_ERROR;
}
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BlockSync: NP block entry #%d, npid = %s. Queueing Search.\n", i, npId.handle.data);
gpiProfileSearchUniquenick(connection, npId.handle.data, &iconnection->namespaceID,
1, GP_NON_BLOCKING, (GPCallback)gpiSyncNpBlockListCallback, NULL);
}
return GP_NO_ERROR;
}
void gpiSyncNpBlockListCallback(
GPConnection * pconnection,
GPProfileSearchResponseArg * arg,
void * param
)
{
GPIProfile * pProfile;
GPIConnection * iconnection = (GPIConnection*)*pconnection;
if(arg->result == GP_NO_ERROR)
{
if(arg->numMatches == 1)
{
// Check if already blocked
////////////////////////////
if(!gpiGetProfile(pconnection, arg->matches[0].profile, &pProfile) || !pProfile->blocked)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BlockSync: NP Block Entry \"%s\" found in namespace %d. Adding to BlockedList.\n",
arg->matches[0].uniquenick, arg->matches[0].namespaceID);
// Add to GP Blocked List - set lock to make sure we dont try to add to NP list
///////////////////////////////////////////////////////////////////////////////
iconnection->npSyncLock = gsi_true;
gpiAddToBlockedList(pconnection, arg->matches[0].profile);
iconnection->npSyncLock = gsi_false;
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BlockSync: \"%s\" is already blocked\n", arg->matches[0].uniquenick);
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3BlockSync: No suitable match found\n");
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3BlockSync: Block Entry Search FAILED!\n");
GSI_UNUSED(param);
}
GPResult gpiAddToNpBlockList(
GPConnection * connection,
int profileid
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// TODO: consider developer method for cache input in order to check HDD cache?
// If NP status not resolved, don't bother with lookup
///////////////////////////////////////////////////////
if (!iconnection->npTransactionList || iconnection->npLookupTitleCtxId < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: Cancelling add - NP status not yet resolved.\n");
return GP_NO_ERROR;
}
// Do an info lookup to find out if this player has an NP account.
/////////////////////////////////////////////////////////////////
gpiGetInfo(connection, profileid, GP_CHECK_CACHE, GP_NON_BLOCKING,
(GPCallback)gpiAddToNpBlockListInfoCallback, NULL);
return GP_NO_ERROR;
}
void gpiAddToNpBlockListInfoCallback(
GPConnection * pconnection,
GPGetInfoResponseArg * arg,
void * param
)
{
SceNpOnlineId onlineId;
int ret;
npIdLookupTrans transaction;
GPIConnection * iconnection = (GPIConnection*)*pconnection;
#ifdef GSI_UNICODE
char asciiUniquenick[GP_UNIQUENICK_LEN];
#endif
if(arg->result == GP_NO_ERROR)
{
// Make sure its a PS3 uniquenick (e.g. we have the uniquenick)
///////////////////////////////////////////////////////////////
if (_tcslen(arg->uniquenick) != 0)
{
memset(&onlineId, 0, sizeof(onlineId));
#ifdef GSI_UNICODE
UCS2ToAsciiString(arg->uniquenick, (char*)asciiUniquenick);
strncpy(onlineId.data, asciiUniquenick, SCE_NET_NP_ONLINEID_MAX_LENGTH);
#else
strncpy(onlineId.data, arg->uniquenick, SCE_NET_NP_ONLINEID_MAX_LENGTH);
#endif
if (ArrayLength(iconnection->npTransactionList) < GPI_NP_NUM_TRANSACTIONS)
{
ret = sceNpLookupCreateTransactionCtx(iconnection->npLookupTitleCtxId);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: sceNpLookupCreateTransactionCtx() failed. ret = 0x%x\n", ret);
}
else
{
transaction.npIdForAdd = (SceNpId*)gsimalloc(sizeof(SceNpId));
if(transaction.npIdForAdd == NULL)
{
sceNpLookupDestroyTransactionCtx(ret);
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: Out of memory.\n");
return;
}
transaction.npTransId = ret;
transaction.npLookupDone = gsi_false;
ArrayAppend(iconnection->npTransactionList, &transaction);
// Perform NP lookup to get the NpId
/////////////////////////////////////
ret = sceNpLookupNpIdAsync(transaction.npTransId, &onlineId,
transaction.npIdForAdd, 0, NULL);
if (ret < 0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: sceNpLookupNpIdAsync() failed. ret = 0x%x\n", ret);
}
}
}
else
{
// Can only have a max of 32 simultaneous transactions (based on PS3 lib)
/////////////////////////////////////////////////////////////////////////
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_WarmError,
"PS3AddToNpBlockList: Transactions limit reached for np lookups\n");
}
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: Profile [%d] does not have a uniquenick in namespace %d!\n",
arg->profile, iconnection->namespaceID);
}
else
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: Player Info lookup FAILED!\n");
GSI_UNUSED(pconnection);
GSI_UNUSED(param);
}
GPResult gpiProcessNp(GPConnection * connection)
{
int i, ret=0;
GPIConnection * iconnection = (GPIConnection*)*connection;
npIdLookupTrans * transaction;
// Check for uninitialized transaction darray
//////////////////////////////////////////////
if (!iconnection->npTransactionList)
return GP_NO_ERROR;
// Need to process Sysutil for the Async lookups
/////////////////////////////////////////////////
if (ArrayLength(iconnection->npTransactionList) > 0)
cellSysutilCheckCallback();
// Loop through all current transactions, check if complete
///////////////////////////////////////////////////////////
for (i=0; i < ArrayLength(iconnection->npTransactionList); i++)
{
// Grab next transaction in the list
/////////////////////////////////////
transaction = (npIdLookupTrans *)ArrayNth(iconnection->npTransactionList, i);
if (!transaction->npLookupDone)
{
if (sceNpLookupPollAsync(transaction->npTransId, &ret)==0)
transaction->npLookupDone = gsi_true;
}
else
{
if (ret<0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: sceNpLookupWaitAsync. ret = 0x%x\n", ret);
if (ret == (int)SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_USER_NPID)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: Player '%s' is not an NP user.\n",
transaction->npIdForAdd->handle.data);
}
}
else
{
// Found an NpId, try to add
/////////////////////////////
ret = sceNpBasicAddBlockListEntry(transaction->npIdForAdd);
if (ret == (int)SCE_NP_BASIC_ERROR_BUSY)
{
// Oh nice, NP is too busy to help us.... keep on trying
/////////////////////////////////////////////////////////
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3AddToNpBlockList: SCE_NP_BASIC_ERROR_BUSY. continue trying to add to NP\n");
return GP_NO_ERROR;
}
else if ( ret < 0 )
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: sceNpBasicAddBlockListEntry() failed. ret = 0x%x\n", ret);
}
else
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
"PS3AddToNpBlockList: Player '%s' added to NP Block list.\n",
transaction->npIdForAdd->handle.data);
}
}
ret = sceNpLookupDestroyTransactionCtx(transaction->npTransId);
if (ret<0)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
"PS3AddToNpBlockList: sceNpLookupDestroyTransactionCtx() failed. ret = 0x%x\n", ret);
}
// Delete Transaction when its complete
////////////////////////////////////////
ArrayDeleteAt(iconnection->npTransactionList, i);
}
}
return GP_NO_ERROR;
}
#endif

54
code/gamespy/GP/gpiPS3.h Normal file
View file

@ -0,0 +1,54 @@
/*
gpiPS3.h
GameSpy Presence SDK
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIPS3_H_
#define _GPIPS3_H_
//INCLUDES
//////////
#include "gpi.h"
#include <np.h>
#include <np\common.h>
#include <sysutil/sysutil_common.h>
//DEFINES
/////////
#define GPI_NP_SYNC_DELAY 5000 //wait 5 seconds after login before doing any syncs
#define GPI_NP_STATUS_TIMEOUT 5000 //timeout after 5 second max if NP status is not online
#define GPI_NP_NUM_TRANSACTIONS 32 //Max num of simultaneous NP lookup transactions
//STRUCTURES
////////////
typedef struct
{
int npTransId;
SceNpId *npIdForAdd;
gsi_bool npLookupDone;
} npIdLookupTrans;
//FUNCTIONS
///////////
GPResult gpiInitializeNpBasic();
GPResult gpiCheckNpStatus(GPConnection * connection);
GPResult gpiDestroyNpBasic(GPConnection * connection);
GPResult gpiProcessNp(GPConnection * connection);
int gpiNpBasicCallback(int event, int retCode, uint32_t reqId, void *arg);
GPResult gpiSyncNpBuddies(GPConnection * connection);
void gpiSyncNpBuddiesCallback(GPConnection * pconnection, GPProfileSearchResponseArg * arg, void * param);
GPResult gpiSyncNpBlockList(GPConnection * connection);
void gpiSyncNpBlockListCallback(GPConnection * pconnection, GPProfileSearchResponseArg * arg, void * param);
GPResult gpiAddToNpBlockList(GPConnection * connection, int profileid);
void gpiAddToNpBlockListInfoCallback(GPConnection * pconnection, GPGetInfoResponseArg * arg, void * param);
#endif

1308
code/gamespy/GP/gpiPeer.c Normal file

File diff suppressed because it is too large Load diff

186
code/gamespy/GP/gpiPeer.h Normal file
View file

@ -0,0 +1,186 @@
/*
gpiPeer.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIPEER_H_
#define _GPIPEER_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Peer states.
///////////////
#define GPI_PEER_NOT_CONNECTED 100
#define GPI_PEER_GETTING_SIG 101
#define GPI_PEER_GOT_SIG 102
#define GPI_PEER_CONNECTING 103
#define GPI_PEER_WAITING 104
#define GPI_PEER_CONNECTED 105
#define GPI_PEER_DISCONNECTED 106
// Timeout for a peer connection, in milliseconds.
/////////////////////////////////////////////
#define GPI_PEER_TIMEOUT (10 * 1000)
// Timeout for a peer operation, in milliseconds
////////////////////////////////////////////
#define GPI_PEER_OP_TIMEOUT 60000
typedef enum
{
GPI_PEER_OP_STATE_NONE,
GPI_PEER_OP_STATE_REQUESTED,
GPI_PEER_OP_STATE_FINISHED
} GPIPeerOpState;
typedef struct GPITransferID_s * GPITransferID_st;
//TYPES
///////
// A peer message.
//////////////////
typedef struct GPIMessage
{
GPIBuffer buffer;
int type;
int start;
} GPIMessage;
typedef struct _GPIPeerOp
{
GPIPeerOpState state;
void *userData;
GPCallback callback;
struct _GPIPeerOp * next;
int type;
gsi_time timeout;
} GPIPeerOp;
typedef struct _GPIPeerOpQueue
{
GPIPeerOp * opList;
GPIPeerOp * first;
GPIPeerOp * last;
} GPIPeerOpQueue;
// A peer connection.
/////////////////////
typedef struct GPIPeer_s
{
int state;
GPIBool initiated;
//SOCKET sock;
unsigned int ip;
unsigned short port;
GPProfile profile;
time_t timeout;
int nackCount;
GPIBuffer inputBuffer;
GPIBuffer outputBuffer;
DArray messages;
GPIPeerOpQueue peerOpQueue;
struct GPIPeer_s * pnext;
} GPIPeer;
//FUNCTIONS
///////////
GPResult
gpiProcessPeers(
GPConnection * connection
);
GPResult
gpiPeerGetSig(
GPConnection * connection,
GPIPeer * peer
);
GPResult
gpiPeerStartConnect(
GPConnection * connection,
GPIPeer * peer
);
// NOTE: use this function when in a gp function
GPIPeer * gpiGetPeerByProfile(const GPConnection * connection,
int profileid);
// NOTE: use this function only when in a UDP layer callback
GPIPeer *gpiGetPeerByAddr(const GPConnection *connection,
unsigned int ip,
unsigned short port);
gsi_bool gpiIsPeerConnected(GPIPeer *peer);
GPIPeer *
gpiAddPeer(
GPConnection * connection,
int profileid,
GPIBool initiate
);
void
gpiDestroyPeer(
GPConnection * connection,
GPIPeer * peer
);
void
gpiRemovePeer(
GPConnection * connection,
GPIPeer * peer
);
GPResult
gpiPeerAddMessage(
GPConnection * connection,
GPIPeer * peer,
int type,
const char * message
);
GPResult
gpiPeerStartTransferMessage(
GPConnection * connection,
GPIPeer * peer,
int type,
const struct GPITransferID_s * transferID
);
GPResult
gpiPeerFinishTransferMessage(
GPConnection * connection,
GPIPeer * peer,
const char * message,
int len
);
GPResult
gpiPeerSendMessages(
GPConnection * connection,
GPIPeer * peer
);
void gpiPeerLeftCallback(unsigned int ip, unsigned short port, GSUdpCloseReason reason, void *userData);
void gpiPeerMessageCallback(unsigned int ip, unsigned short port, unsigned char *message,
unsigned int messageLength, gsi_bool reliable, void *userData);
void gpiPeerAcceptedCallback(unsigned int ip, unsigned short port,
GSUdpErrorCode error, gsi_bool rejected, void *userData);
void gpiPeerPingReplyCallback(unsigned int ip, unsigned short port, unsigned int latency, void *userData);
void gpiPeerAddOp(GPIPeer *peer, GPIPeerOp *operation);
void gpiPeerRemoveOp(GPIPeer *peer, GPIPeerOp *operation);
void gpiCheckTimedOutPeerOperations(GPConnection * connection, GPIPeer * peer);
#endif

1390
code/gamespy/GP/gpiProfile.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,229 @@
/*
gpiProfile.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIPROFILE_H_
#define _GPIPROFILE_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
#define GPI_SIG_LEN 33
//TYPES
///////
// The status for a buddy profile.
//////////////////////////////////
// New Status Info
typedef struct _GPIBuddyStatusInfo
{
int buddyIndex;
GPEnum statusState;
char *richStatus;
char *gameType;
char *gameVariant;
char *gameMapName;
unsigned int sessionFlags;
unsigned int buddyIp;
unsigned short buddyPort;
unsigned int hostIp;
unsigned int hostPrivateIp;
unsigned short queryPort;
unsigned short hostPort;
GPEnum quietModeFlags;
int productId;
// New Status Info extended info Keys
DArray extendedInfoKeys;
} GPIBuddyStatusInfo;
// Old status
typedef struct
{
int buddyIndex;
GPEnum status;
char * statusString;
char * locationString;
unsigned int ip;
unsigned short port;
GPEnum quietModeFlags;
} GPIBuddyStatus;
// Profile data.
////////////////
typedef struct GPIProfile
{
int profileId;
int userId;
GPIBuddyStatus * buddyStatus;
GPIBuddyStatusInfo *buddyStatusInfo;
GPIInfoCache * cache;
char * authSig;
int requestCount;
char * peerSig;
gsi_bool blocked;
int blockIndex;
gsi_bool buddyOrBlockCache;
} GPIProfile;
// A list of profiles.
//////////////////////
typedef struct
{
HashTable profileTable;
int num;
int numBuddies;
int numBlocked;
} GPIProfileList;
//FUNCTIONS
///////////
GPIBool
gpiInitProfiles(
GPConnection * connection
);
GPIProfile *
gpiProfileListAdd(
GPConnection * connection,
int id
);
GPIBool
gpiGetProfile(
GPConnection * connection,
GPProfile profileid,
GPIProfile ** pProfile
);
GPResult
gpiProcessNewProfile(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
GPResult
gpiNewProfile(
GPConnection * connection,
const char nick[GP_NICK_LEN],
GPEnum replace,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiProcessDeleteProfle
(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
GPResult gpiDeleteProfile(
GPConnection * connection,
GPCallback callback,
void * param
);
void
gpiRemoveProfile(
GPConnection * connection,
GPIProfile * profile
);
void
gpiRemoveProfileByID(
GPConnection * connection,
int profileid
);
GPResult
gpiLoadDiskProfiles(
GPConnection * connection
);
GPResult
gpiSaveDiskProfiles(
GPConnection * connection
);
GPResult
gpiFindProfileByUser(
GPConnection * connection,
char nick[GP_NICK_LEN],
char email[GP_EMAIL_LEN],
GPIProfile ** profile
);
// return false to stop the mapping
typedef GPIBool
(* gpiProfileMapFunc)(
GPConnection * connection,
GPIProfile * profile,
void * data
);
GPIBool
gpiProfileMap(
GPConnection * connection,
gpiProfileMapFunc func,
void * data
);
GPIProfile *
gpiFindBuddy(
GPConnection * connection,
int buddyIndex
);
void gpiRemoveBuddyStatus(GPIBuddyStatus *buddyStatus);
void gpiRemoveBuddyStatusInfo(GPIBuddyStatusInfo *buddyStatusInfo);
GPIBool
gpiCanFreeProfile(
GPIProfile * profile
);
void gpiSetInfoCacheFilename(
const char filename[FILENAME_MAX + 1]
);
// BLOCK LIST
GPResult
gpiAddToBlockedList(
GPConnection * connection,
int profileid
);
GPResult
gpiRemoveFromBlockedList(
GPConnection * connection,
int profileid
);
GPIProfile *
gpiFindBlockedProfile(
GPConnection * connection,
int blockIndex
);
GPResult
gpiProcessRecvBlockedList(
GPConnection * connection,
const char * input
);
#endif

1656
code/gamespy/GP/gpiSearch.c Normal file

File diff suppressed because it is too large Load diff

172
code/gamespy/GP/gpiSearch.h Normal file
View file

@ -0,0 +1,172 @@
/*
gpiSearch.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPISEARCH_H_
#define _GPISEARCH_H_
//INCLUDES
//////////
#include "gpi.h"
//TYPES
///////
#define GPI_SEARCH_PROFILE 1
#define GPI_SEARCH_IS_VALID 2
#define GPI_SEARCH_NICKS 3
#define GPI_SEARCH_PLAYERS 4
#define GPI_SEARCH_CHECK 5
#define GPI_SEARCH_NEWUSER 6
#define GPI_SEARCH_OTHERS_BUDDY 7
#define GPI_SEARCH_SUGGEST_UNIQUE 8
#define GPI_SEARCH_OTHERS_BUDDY_LIST 9
#define GPI_SEARCH_PROFILE_UNIQUENICK 10
// A timeout used to abort searches taking too long
#define GPI_SEARCH_TIMEOUT 60000
// Profile Search operation data.
/////////////////////////////////
typedef struct
{
int type;
SOCKET sock;
GPIBuffer inputBuffer;
GPIBuffer outputBuffer;
char nick[GP_NICK_LEN];
char uniquenick[GP_UNIQUENICK_LEN];
int namespaceIDs[GP_MAX_NAMESPACEIDS];
int numNamespaces;
char email[GP_EMAIL_LEN];
char firstname[GP_FIRSTNAME_LEN];
char lastname[GP_LASTNAME_LEN];
char password[GP_PASSWORD_LEN];
char cdkey[GP_CDKEY_LEN];
int partnerID;
int icquin;
int skip;
int productID;
GPIBool processing;
GPIBool remove;
gsi_time searchStartTime;
int *revBuddyProfileIds;
int numOfRevBuddyProfiles;
} GPISearchData;
//FUNCTIONS
///////////
GPResult
gpiProfileSearch(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char uniquenick[GP_UNIQUENICK_LEN],
const char email[GP_EMAIL_LEN],
const char firstname[GP_FIRSTNAME_LEN],
const char lastname[GP_LASTNAME_LEN],
int icquin,
int skip,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiProfileSearchUniquenick(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const int namespaceIDs[],
int numNamespaces,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiIsValidEmail(
GPConnection * connection,
const char email[GP_EMAIL_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiGetUserNicks(
GPConnection * connection,
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiFindPlayers(
GPConnection * connection,
int productID,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiCheckUser(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiNewUser(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char uniquenick[GP_UNIQUENICK_LEN],
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiOthersBuddy(
GPConnection * connection,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiOthersBuddyList(
GPConnection * connection,
int *profiles,
int numOfProfiles,
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiSuggestUniqueNick(
GPConnection * connection,
const char desirednick[GP_NICK_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult
gpiProcessSearches(
GPConnection * connection
);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,210 @@
/*
gpiTransfer.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPITRANSFER_H_
#define _GPITRANSFER_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
#define GPI_FILE_DIRECTORY (1 << 1)
#define GPI_FILE_SKIP (1 << 2)
#define GPI_FILE_FAILED (1 << 3)
#define GPI_FILE_COMPLETED (1 << 4)
#define GPI_FILE_CONFIRMING (1 << 5)
#define GPI_ACCEPTED 0
#define GPI_REJECTED 1
#define GPI_NOT_ACCEPTING 2
#define GPI_SKIP_READ_ERROR 0
#define GPI_SKIP_WRITE_ERROR 1
#define GPI_SKIP_USER_SKIP 2
//TYPES
///////
typedef enum
{
GPITransferPinging,
GPITransferWaiting,
GPITransferTransferring,
GPITransferComplete,
GPITransferCancelled,
GPITransferNoConnection
} GPITransferState;
typedef struct GPITransferID_s
{
int profileid;
unsigned int count;
unsigned int time;
} GPITransferID;
typedef struct
{
GPITransferState state;
DArray files;
GPITransferID transferID;
int localID;
GPIBool sender;
GPProfile profile;
GPIPeer * peer;
int currentFile;
int throttle;
char * baseDirectory;
unsigned long lastSend;
char * message;
int totalSize;
int progress;
void * userData;
} GPITransfer;
typedef struct
{
char * path;
char * name;
#ifdef GSI_UNICODE
unsigned short* name_W; // must have this since developers are given pointers to internal memory
unsigned short* path_W;
#endif
int progress;
int size;
int acknowledged;
FILE * file;
int flags;
gsi_time modTime;
MD5_CTX md5;
int reason;
} GPIFile;
//FUNCTIONS
///////////
#ifndef NOFILE
GPResult gpiInitTransfers(
GPConnection * connection
);
void gpiCleanupTransfers(
GPConnection * connection
);
GPResult gpiProcessTransfers
(
GPConnection * connection
);
GPResult gpiNewSenderTransfer
(
GPConnection * connection,
GPITransfer ** transfer,
GPProfile profile
);
void gpiFreeTransfer
(
GPConnection * connection,
GPITransfer * transfer
);
void gpiCancelTransfer
(
GPConnection * connection,
GPITransfer * transfer
);
void gpiTransferError
(
GPConnection * connection,
const GPITransfer * transfer
);
GPITransfer * gpiFindTransferByLocalID
(
GPConnection * connection,
int localID
);
int gpiGetTransferLocalIDByIndex
(
GPConnection * connection,
int index
);
GPIFile * gpiAddFileToTransfer
(
GPITransfer * transfer,
const char * path,
const char * name
);
void gpiSkipFile
(
GPConnection * connection,
GPITransfer * transfer,
int file,
int reason
);
void gpiSkipCurrentFile
(
GPConnection * connection,
GPITransfer * transfer,
int reason
);
GPIBool gpiGetTransferFileInfo
(
FILE * file,
int * size,
gsi_time * modTime
);
void gpiTransferPeerDestroyed
(
GPConnection * connection,
GPIPeer * peer
);
void gpiTransfersHandlePong
(
GPConnection * connection,
GPProfile profile,
GPIPeer * peer
);
#endif
GPResult gpiSendTransferReply
(
GPConnection * connection,
const GPITransferID * transferID,
GPIPeer * peer,
int result,
const char * message
);
void gpiHandleTransferMessage
(
GPConnection * connection,
GPIPeer * peer,
int type,
const char * headers,
const char * buffer,
int len
);
#endif

234
code/gamespy/GP/gpiUnique.c Normal file
View file

@ -0,0 +1,234 @@
/*
gpiUnique.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include "gpi.h"
//FUNCTIONS
///////////
static GPResult
gpiSendRegisterUniqueNick(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const char cdkey[GP_CDKEY_LEN],
int operationid
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\registernick\\\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\uniquenick\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, uniquenick);
if(cdkey)
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\cdkey\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, cdkey);
}
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\partnerid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->partnerID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\id\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, operationid);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
GPResult gpiRegisterUniqueNick(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIOperation * operation = NULL;
GPResult result;
// Add the operation.
/////////////////////
CHECK_RESULT(gpiAddOperation(connection, GPI_REGISTER_UNIQUENICK, NULL, &operation, blocking, callback, param));
// Send a request for info.
///////////////////////////
result = gpiSendRegisterUniqueNick(connection, uniquenick, cdkey, operation->id);
CHECK_RESULT(result);
// Process it if blocking.
//////////////////////////
if(blocking)
{
result = gpiProcess(connection, operation->id);
CHECK_RESULT(result);
}
return GP_NO_ERROR;
}
GPResult gpiProcessRegisterUniqueNick(
GPConnection * connection,
GPIOperation * operation,
const char * input
)
{
GPICallback callback;
// Check for an error.
//////////////////////
if(gpiCheckForError(connection, input, GPITrue))
return GP_SERVER_ERROR;
// This should be \rn\.
///////////////////////
if(strncmp(input, "\\rn\\", 4) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Call the callback.
/////////////////////
callback = operation->callback;
if(callback.callback != NULL)
{
GPRegisterUniqueNickResponseArg * arg;
arg = (GPRegisterUniqueNickResponseArg *)gsimalloc(sizeof(GPRegisterUniqueNickResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
arg->result = GP_NO_ERROR;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
}
// This operation is complete.
//////////////////////////////
gpiRemoveOperation(connection, operation);
return GP_NO_ERROR;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Registration of cdKey now offered separately from uniquenick
static GPResult
gpiSendRegisterCdKey(
GPConnection * connection,
const char cdkey[GP_CDKEY_LEN],
int operationid
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Encrypt the cdkey (xor with random values)
const int useAlternateEncoding = 1;
char cdkeyxor[GP_CDKEY_LEN];
char cdkeyenc[GP_CDKEYENC_LEN];
int cdkeylen = (int)strlen(cdkey);
int i=0;
Util_RandSeed((unsigned long)GP_XOR_SEED);
for (i=0; i < cdkeylen; i++)
{
// XOR each character with the next rand
char aRand = (char)Util_RandInt(0, 0xFF);
cdkeyxor[i] = (char)(cdkey[i] ^ aRand);
}
cdkeyxor[i] = '\0';
// Base 64 it (printable chars only)
B64Encode(cdkeyxor, cdkeyenc, (int)cdkeylen, useAlternateEncoding);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\registercdkey\\\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\cdkeyenc\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, cdkeyenc);
// gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\partnerid\\");
// gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->partnerID);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\id\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, operationid);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
GPResult gpiRegisterCdKey(
GPConnection * connection,
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIOperation * operation = NULL;
GPResult result;
// Add the operation.
/////////////////////
CHECK_RESULT(gpiAddOperation(connection, GPI_REGISTER_CDKEY, NULL, &operation, blocking, callback, param));
// Send a request for info.
///////////////////////////
result = gpiSendRegisterCdKey(connection, cdkey, operation->id);
CHECK_RESULT(result);
// Process it if blocking.
//////////////////////////
if(blocking)
{
result = gpiProcess(connection, operation->id);
CHECK_RESULT(result);
}
return GP_NO_ERROR;
}
GPResult gpiProcessRegisterCdKey(
GPConnection * connection,
GPIOperation * operation,
const char * input
)
{
GPICallback callback;
// Check for an error.
//////////////////////
if(gpiCheckForError(connection, input, GPITrue))
return GP_SERVER_ERROR;
// This should be \rc\.
///////////////////////
if(strncmp(input, "\\rc\\", 4) != 0)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
// Call the callback.
/////////////////////
callback = operation->callback;
if(callback.callback != NULL)
{
GPRegisterCdKeyResponseArg * arg;
arg = (GPRegisterCdKeyResponseArg *)gsimalloc(sizeof(GPRegisterCdKeyResponseArg));
if(arg == NULL)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
arg->result = GP_NO_ERROR;
CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0));
}
// This operation is complete.
//////////////////////////////
gpiRemoveOperation(connection, operation);
return GP_NO_ERROR;
}

View file

@ -0,0 +1,53 @@
/*
gpiUnique.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIUNIQUE_H_
#define _GPIUNIQUE_H_
//INCLUDES
//////////
#include "gpi.h"
//FUNCTIONS
///////////
GPResult gpiRegisterUniqueNick(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiProcessRegisterUniqueNick(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
// Seperated registration of unique nick and cdkey
GPResult gpiRegisterCdKey(
GPConnection * connection,
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
);
GPResult gpiProcessRegisterCdKey(
GPConnection * connection,
GPIOperation * operation,
const char * input
);
#endif

View file

@ -0,0 +1,407 @@
/*
gpiUtility.c
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
//INCLUDES
//////////
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "gpi.h"
//DEFINES
/////////
#define OUTPUT_MAX_COL 100
// Disable compiler warnings for issues that are unavoidable.
/////////////////////////////////////////////////////////////
#if defined(_MSC_VER) // DevStudio
// Level4, "conditional expression is constant".
// Occurs with use of the MS provided macro FD_SET
#pragma warning ( disable: 4127 )
#endif // _MSC_VER
//FUNCTIONS
///////////
void
strzcpy(
char * dest,
const char * src,
size_t len
)
{
assert(dest != NULL);
assert(src != NULL);
strncpy(dest, src, len);
dest[len - 1] = '\0';
}
GPIBool
gpiCheckForError(
GPConnection * connection,
const char * input,
GPIBool callErrorCallback
)
{
char buffer[16];
GPIConnection * iconnection = (GPIConnection*)*connection;
if(strncmp(input, "\\error\\", 7) == 0)
{
// Get the err code.
////////////////////
if(gpiValueForKey(input, "\\err\\", buffer, sizeof(buffer)))
iconnection->errorCode = (GPErrorCode)atoi(buffer);
// Get the error string.
////////////////////////
if(!gpiValueForKey(input, "\\errmsg\\", iconnection->errorString, sizeof(iconnection->errorString)))
iconnection->errorString[0] = '\0';
#ifdef GSI_UNICODE
// Update the UNICODE version
UTF8ToUCS2String(iconnection->errorString, iconnection->errorString_W);
#endif
// Call the error callback?
///////////////////////////
if(callErrorCallback)
{
GPIBool fatal = (GPIBool)(strstr(input, "\\fatal\\") != NULL);
gpiCallErrorCallback(connection, GP_SERVER_ERROR, fatal ? GP_FATAL : GP_NON_FATAL);
}
return GPITrue;
}
return GPIFalse;
}
GPIBool
gpiValueForKeyWithIndex(
const char * command,
const char * key,
int * index,
char * value,
int len
)
{
char delimiter;
const char * start;
int i;
char c;
// Check for NULL.
//////////////////
assert(command != NULL);
assert(key != NULL);
assert(value != NULL);
assert(len > 0);
// Find which char is the delimiter.
////////////////////////////////////
delimiter = key[0];
// Find the key - first navigate to the index
/////////////////////////////////////////////
command += *index;
start = strstr(command, key);
if(start == NULL)
return GPIFalse;
// Get to the start of the value.
/////////////////////////////////
start += strlen(key);
// Copy in the value.
/////////////////////
len--;
for(i = 0 ; (i < len) && ((c = start[i]) != '\0') && (c != delimiter) ; i++)
{
value[i] = c;
}
value[i] = '\0';
// Copy back current end point for index
////////////////////////////////////////
*index += ((start - command) + strlen(value));
return GPITrue;
}
GPIBool
gpiValueForKey(
const char * command,
const char * key,
char * value,
int len
)
{
char delimiter;
const char * start;
int i;
char c;
// Check for NULL.
//////////////////
assert(command != NULL);
assert(key != NULL);
assert(value != NULL);
assert(len > 0);
// Find which char is the delimiter.
////////////////////////////////////
delimiter = key[0];
// Find the key.
////////////////
start = strstr(command, key);
if(start == NULL)
return GPIFalse;
// Get to the start of the value.
/////////////////////////////////
start += strlen(key);
// Copy in the value.
/////////////////////
len--;
for(i = 0 ; (i < len) && ((c = start[i]) != '\0') && (c != delimiter) ; i++)
{
value[i] = c;
}
value[i] = '\0';
return GPITrue;
}
char *
gpiValueForKeyAlloc(
const char * command,
const char * key
)
{
char delimiter;
const char * start;
char c;
char * value;
int len;
// Check for NULL.
//////////////////
assert(command != NULL);
assert(key != NULL);
// Find which char is the delimiter.
////////////////////////////////////
delimiter = key[0];
// Find the key.
////////////////
start = strstr(command, key);
if(start == NULL)
return NULL;
// Get to the start of the value.
/////////////////////////////////
start += strlen(key);
// Find the key length.
///////////////////////
for(len = 0 ; ((c = start[len]) != '\0') && (c != delimiter) ; len++) { };
// Allocate the value.
//////////////////////
value = (char *)gsimalloc((unsigned int)len + 1);
if(!value)
return NULL;
// Copy in the value.
/////////////////////
memcpy(value, start, (unsigned int)len);
value[len] = '\0';
return value;
}
GPResult
gpiCheckSocketConnect(
GPConnection * connection,
SOCKET sock,
int * state
)
{
int aWriteFlag = 0;
int aExceptFlag = 0;
int aReturnCode = 0;
// Check if the connect is completed.
/////////////////////////////////////
aReturnCode = GSISocketSelect(sock, NULL, &aWriteFlag, &aExceptFlag);
if ( gsiSocketIsError(aReturnCode))
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError,
"Error connecting\n");
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error checking for a completed connection.");
}
if (aReturnCode > 0)
{
// Check for a failed attempt.
//////////////////////////////
if(aExceptFlag)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError,
"Connection rejected\n");
*state = GPI_DISCONNECTED;
return GP_NO_ERROR;
}
// Check for a successful attempt.
//////////////////////////////////
if(aWriteFlag)
{
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Notice,
"Connection accepted\n");
*state = GPI_CONNECTED;
return GP_NO_ERROR;
}
}
// Not connected yet.
/////////////////////
*state = GPI_NOT_CONNECTED;
return GP_NO_ERROR;
}
GPResult
gpiReadKeyAndValue(
GPConnection * connection,
const char * buffer,
int * index,
char key[512],
char value[512]
)
{
int c;
int i;
char * start;
assert(buffer != NULL);
assert(key != NULL);
assert(value != NULL);
buffer += *index;
start = (char *)buffer;
if(*buffer++ != '\\')
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Parse Error.");
for(i = 0 ; (c = *buffer++) != '\\' ; i++)
{
if(c == '\0')
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Parse Error.");
if(i == 511)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Parse Error.");
*key++ = (char)c;
}
*key = '\0';
for(i = 0 ; ((c = *buffer++) != '\\') && (c != '\0') ; i++)
{
if(i == 511)
CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Parse Error.");
*value++ = (char)c;
}
*value = '\0';
*index += (buffer - start - 1);
return GP_NO_ERROR;
}
void
gpiSetError(
GPConnection * connection,
GPErrorCode errorCode,
const char * errorString
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Copy the string.
///////////////////
strzcpy(iconnection->errorString, errorString, GP_ERROR_STRING_LEN);
#ifdef GSI_UNICODE
// Update the unicode version
UTF8ToUCS2StringLen(iconnection->errorString, iconnection->errorString_W, GP_ERROR_STRING_LEN);
#endif
// Set the code.
////////////////
iconnection->errorCode = errorCode;
}
void
gpiSetErrorString(
GPConnection * connection,
const char * errorString
)
{
GPIConnection * iconnection = (GPIConnection*)*connection;
// Copy the string.
///////////////////
strzcpy(iconnection->errorString, errorString, GP_ERROR_STRING_LEN);
#ifdef GSI_UNICODE
// Update the unicode version
UTF8ToUCS2StringLen(iconnection->errorString, iconnection->errorString_W, GP_ERROR_STRING_LEN);
#endif
}
void
gpiEncodeString(
const char * unencodedString,
char * encodedString
)
{
size_t i;
const int useAlternateEncoding = 1;
// Encrypt the password (xor with random values)
char passwordxor[GP_PASSWORD_LEN];
size_t passwordlen = strlen(unencodedString);
Util_RandSeed((unsigned long)GP_XOR_SEED);
for (i=0; i < passwordlen; i++)
{
// XOR each character with the next rand
char aRand = (char)Util_RandInt(0, 0xFF);
passwordxor[i] = (char)(unencodedString[i] ^ aRand);
}
passwordxor[i] = '\0';
// Base 64 it (printable chars only)
B64Encode(passwordxor, encodedString, (int)passwordlen, useAlternateEncoding);
}
// Re-enable previously disabled compiler warnings
///////////////////////////////////////////////////
#if defined(_MSC_VER)
#pragma warning ( default: 4127 )
#endif // _MSC_VER

View file

@ -0,0 +1,127 @@
/*
gpiUtility.h
GameSpy Presence SDK
Dan "Mr. Pants" Schoenblum
Copyright 1999-2007 GameSpy Industries, Inc
devsupport@gamespy.com
***********************************************************************
Please see the GameSpy Presence SDK documentation for more information
**********************************************************************/
#ifndef _GPIUTILITY_H_
#define _GPIUTILITY_H_
//INCLUDES
//////////
#include "gpi.h"
//DEFINES
/////////
// Buffer read size.
////////////////////
#define GPI_READ_SIZE (16 * 1024)
//MACROS
////////
#define freeclear(mem) { gsifree(mem); (mem) = NULL; }
#define Error(connection, result, string) { gpiSetErrorString(connection, string);\
return (result);}
#define CallbackError(connection, result, code, string) { gpiSetError(connection, code, string);\
gpiCallErrorCallback(connection, result, GP_NON_FATAL);\
return result;}
#define CallbackFatalError(connection, result, code, string) { gpiSetError(connection, code, string);\
gpiCallErrorCallback(connection, result, GP_FATAL);\
return result;}
#define CHECK_RESULT(result) { GPResult __result__ = (result);\
if(__result__ != GP_NO_ERROR){\
return __result__;}}
//FUNCTIONS
///////////
void
strzcpy(
char * dest,
const char * src,
size_t len // length of buffer, including space for '\0'
);
void
gpiDebug(
GPConnection * connection,
const char * fmt,
...
);
GPIBool
gpiValueForKeyWithIndex(
const char * command,
const char * key,
int * index,
char * value,
int len
);
GPIBool
gpiValueForKey(
const char * command,
const char * key,
char * value,
int len
);
char *
gpiValueForKeyAlloc(
const char * command,
const char * key
);
GPResult
gpiCheckSocketConnect(
GPConnection * connection,
SOCKET sock,
int * state
);
GPResult
gpiReadKeyAndValue(
GPConnection * connection,
const char * buffer,
int * index,
char key[512],
char value[512]
);
GPIBool
gpiCheckForError(
GPConnection * connection,
const char * input,
GPIBool callErrorCallback
);
void
gpiSetError(
GPConnection * connection,
GPErrorCode errorCode,
const char * errorString
);
void
gpiSetErrorString(
GPConnection * connection,
const char * errorString
);
void
gpiEncodeString(
const char * unencodedString,
char * encodedString
);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,762 @@
// ConnectPage.cpp : implementation file
//
#include "stdafx.h"
#include "PeerLobby.h"
#include "ConnectPage.h"
#include "TitlePage.h"
#include "LobbyWizard.h"
#include "GroupPage.h"
#include "StagingPage.h"
#include "CreatePage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CConnectPage * ConnectPage;
/////////////////////////////////////////////////////////////////////////////
// CConnectPage property page
IMPLEMENT_DYNCREATE(CConnectPage, CPropertyPage)
// Set page defaults.
/////////////////////
CConnectPage::CConnectPage() : CPropertyPage(CConnectPage::IDD)
{
//{{AFX_DATA_INIT(CConnectPage)
m_nick = _T("PeerPlayer");
m_title = _T("gmtest");
m_groupRooms = FALSE;
m_key = _T("HA6zkS");
//}}AFX_DATA_INIT
}
CConnectPage::~CConnectPage()
{
}
void CConnectPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CConnectPage)
DDX_Text(pDX, IDC_NICK, m_nick);
DDX_Text(pDX, IDC_TITLE, m_title);
DDX_Check(pDX, IDC_GROUP_ROOMS, m_groupRooms);
DDX_Text(pDX, IDC_KEY, m_key);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CConnectPage, CPropertyPage)
//{{AFX_MSG_MAP(CConnectPage)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// Used for printing callback info to the debug window.
///////////////////////////////////////////////////////
static void PrintCallback(const char * callback)
{
CString buffer;
buffer = callback;
buffer += " (callback)\n";
OutputDebugString(buffer);
}
static void PrintStringParam(const char * param, const char * value)
{
CString buffer;
buffer += " ";
buffer += param;
buffer += " = \"";
buffer += value;
buffer += "\"\n";
OutputDebugString(buffer);
}
static void PrintIntParam(const char * param, int value)
{
char string[16];
sprintf(string, "%d", value);
PrintStringParam(param, string);
}
static void PrintBoolParam(const char * param, PEERBool value)
{
if(value)
PrintStringParam(param, "True");
else
PrintStringParam(param, "False");
}
static void PrintRoomParam(const char * param, RoomType roomType)
{
if(roomType == TitleRoom)
PrintStringParam("roomType", "Title Room");
else if(roomType == GroupRoom)
PrintStringParam("roomType", "Group Room");
else if(roomType == StagingRoom)
PrintStringParam("roomType", "Staging Room");
else
PrintStringParam("roomType", "<unknown>");
GSI_UNUSED(param);
}
///////////////////////////
// Peer Global Callbacks //
///////////////////////////
// Called if peer gets disconnected from chat.
//////////////////////////////////////////////
static void DisconnectedCallback
(
PEER peer,
const char * reason,
void * param
)
{
PrintCallback("Disconnected");
PrintStringParam("reason", reason);
CString text = "You were disconnected from the server: ";
if(reason)
text += reason;
Wizard->MessageBox(text);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when a message arrives in a room.
///////////////////////////////////////////
static void RoomMessageCallback
(
PEER peer,
RoomType roomType,
const char * nick,
const char * message,
MessageType messageType,
void * param
)
{
PrintCallback("RoomMessage");
PrintStringParam("nick", nick);
PrintStringParam("message", message);
// Form the message.
////////////////////
CString buffer;
if(messageType == NormalMessage)
buffer.Format("%s: %s", nick, message);
else if(messageType == ActionMessage)
buffer.Format("%s %s", nick, message);
else
buffer.Format("*%s* %s", nick, message);
// Send it to the right place.
//////////////////////////////
if(roomType == StagingRoom)
{
StagingPage->m_chatWindow.InsertString(-1, buffer);
StagingPage->m_chatWindow.SetTopIndex(StagingPage->m_chatWindow.GetCount() - 1);
}
else if((roomType == GroupRoom) || !Wizard->m_groupRooms)
{
GroupPage->m_chatWindow.InsertString(-1, buffer);
GroupPage->m_chatWindow.SetTopIndex(GroupPage->m_chatWindow.GetCount() - 1);
}
else
{
TitlePage->m_chatWindow.InsertString(-1, buffer);
TitlePage->m_chatWindow.SetTopIndex(TitlePage->m_chatWindow.GetCount() - 1);
}
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when a staging room player's ready state changes.
///////////////////////////////////////////////////////////
static void ReadyChangedCallback
(
PEER peer,
const char * nick,
PEERBool ready,
void * param
)
{
PrintCallback("ReadyChanged");
PrintStringParam("nick", nick);
PrintBoolParam("ready", ready);
// Update his ready state.
//////////////////////////
StagingPage->UpdatePlayerReady(nick, (BOOL)ready);
// Check if we should enable the finish button.
///////////////////////////////////////////////
if(Wizard->m_hosting)
StagingPage->CheckEnableFinish();
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when the game launches in a staging room we've joined.
////////////////////////////////////////////////////////////////
static void GameStartedCallback
(
PEER peer,
SBServer server,
const char * message,
void * param
)
{
const char * address = SBServerGetPublicAddress(server);
PrintCallback("GameStarted");
PrintStringParam("IP", address);
PrintStringParam("message", message);
char buffer[256];
sprintf(buffer,
"The game has been started.\n"
"The host is at %s.\n"
"Message: %s\n"
"Hit OK to return to the staging room.",
address,
message);
StagingPage->MessageBox(buffer);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when a player joins a room we're in.
//////////////////////////////////////////////
static void PlayerJoinedCallback
(
PEER peer,
RoomType roomType,
const char * nick,
void * param
)
{
PrintCallback("PlayerJoined");
PrintRoomParam("roomType", roomType);
PrintStringParam("nick", nick);
if(roomType == StagingRoom)
{
StagingPage->UpdatePlayerPing(nick, 9999);
if(Wizard->m_hosting)
Wizard->SetWizardButtons(PSWIZB_BACK | PSWIZB_DISABLEDFINISH);
}
else if((roomType == GroupRoom) || !Wizard->m_groupRooms)
GroupPage->UpdatePlayerPing(nick, 9999);
else
TitlePage->UpdatePlayerPing(nick, 9999);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when a player leaves a room we're in.
///////////////////////////////////////////////
static void PlayerLeftCallback
(
PEER peer,
RoomType roomType,
const char * nick,
const char * reason,
void * param
)
{
PrintCallback("PlayerLeft");
PrintRoomParam("roomType", roomType);
PrintStringParam("nick", nick);
if(roomType == StagingRoom)
{
StagingPage->RemovePlayer(nick);
if(Wizard->m_hosting)
StagingPage->CheckEnableFinish();
}
else if((roomType == GroupRoom) || !Wizard->m_groupRooms)
GroupPage->RemovePlayer(nick);
else
TitlePage->RemovePlayer(nick);
GSI_UNUSED(param);
GSI_UNUSED(reason);
GSI_UNUSED(peer);
}
// Called when a player's nickname changes.
///////////////////////////////////////////
static void PlayerChangedNickCallback
(
PEER peer,
RoomType roomType,
const char * oldNick,
const char * newNick,
void * param
)
{
PrintCallback("PlayerChangedNick");
PrintRoomParam("roomType", roomType);
PrintStringParam("oldNick", oldNick);
PrintStringParam("newNick", newNick);
if(roomType == StagingRoom)
StagingPage->ChangePlayerNick(oldNick, newNick);
else if((roomType == GroupRoom) || !Wizard->m_groupRooms)
GroupPage->ChangePlayerNick(oldNick, newNick);
else
TitlePage->ChangePlayerNick(oldNick, newNick);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called whenever a new ping time is available.
////////////////////////////////////////////////
static void PingCallback
(
PEER peer,
const char * nick,
int ping,
void * param
)
{
PrintCallback("Ping");
PrintStringParam("nick", nick);
PrintIntParam("ping", ping);
if(Wizard->m_groupRooms && TitlePage->m_hWnd && TitlePage->FindPlayer(nick) != -1)
TitlePage->UpdatePlayerPing(nick, ping);
if(GroupPage->m_hWnd && GroupPage->FindPlayer(nick) != -1)
GroupPage->UpdatePlayerPing(nick, ping);
if(StagingPage->m_hWnd && StagingPage->FindPlayer(nick) != -1)
StagingPage->UpdatePlayerPing(nick, ping);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called whenever a crossping is available.
////////////////////////////////////////////
static void CrossPingCallback
(
PEER peer,
const char * nick1,
const char * nick2,
int crossPing,
void * param
)
{
PrintCallback("CrossPing");
PrintStringParam("nick1", nick1);
PrintStringParam("nick2", nick2);
PrintIntParam("crossPing", crossPing);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Player info for server reporting.
////////////////////////////////////
const int NumPlayers = 2;
const char * Players[] = { "Bob", "Joe" };
// Converts a key index to a string.
////////////////////////////////////
static const char * KeyToString(int key)
{
return qr2_registered_key_list[key];
}
// Converts a key type to a string.
///////////////////////////////////
static const char * KeyTypeToString(qr2_key_type type)
{
switch(type)
{
case key_server:
return "server";
case key_player:
return "player";
case key_team:
return "team";
}
ASSERT(0);
return "Unkown key type";
}
// Converts an error code to a string.
//////////////////////////////////////
static const char * ErrorTypeToString(qr2_error_t error)
{
switch(error)
{
case e_qrnoerror:
return "noerror";
case e_qrwsockerror:
return "wsockerror";
case e_qrbinderror:
return "rbinderror";
case e_qrdnserror:
return "dnserror";
case e_qrconnerror:
return "connerror";
}
ASSERT(0);
return "Unknown error type";
}
// Reports server keys.
///////////////////////
static void QRServerKeyCallback
(
PEER peer,
int key,
qr2_buffer_t buffer,
void * param
)
{
PrintCallback("QRServerKey");
PrintStringParam("key", KeyToString(key));
switch(key)
{
case GAMEVER_KEY:
qr2_buffer_add(buffer, "1.01");
break;
case HOSTNAME_KEY:
qr2_buffer_add(buffer, (LPCSTR)CreatePage->m_name);
break;
case NUMPLAYERS_KEY:
qr2_buffer_add_int(buffer, NumPlayers);
break;
case MAXPLAYERS_KEY:
qr2_buffer_add_int(buffer, NumPlayers + 2);
break;
default:
qr2_buffer_add(buffer, "");
break;
}
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Reports player keys.
///////////////////////
static void QRPlayerKeyCallback
(
PEER peer,
int key,
int index,
qr2_buffer_t buffer,
void * param
)
{
PrintCallback("QRPlayerKey");
PrintStringParam("key", KeyToString(key));
PrintIntParam("index", index);
switch(key)
{
case PLAYER__KEY:
qr2_buffer_add(buffer, Players[index]);
break;
case PING__KEY:
qr2_buffer_add_int(buffer, rand() % 100);
break;
default:
qr2_buffer_add(buffer, "");
break;
}
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Reports team keys.
/////////////////////
static void QRTeamKeyCallback
(
PEER peer,
int key,
int index,
qr2_buffer_t buffer,
void * param
)
{
PrintCallback("QRTeamKey");
PrintStringParam("key", KeyToString(key));
PrintIntParam("index", index);
// we don't report teams, so this shouldn't get called
qr2_buffer_add(buffer, "");
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Reports supported keys.
//////////////////////////
static void QRKeyListCallback
(
PEER peer,
qr2_key_type type,
qr2_keybuffer_t keyBuffer,
void * param
)
{
PrintCallback("QRKeyList");
PrintStringParam("type", KeyTypeToString(type));
// register the keys we use
switch(type)
{
case key_server:
qr2_keybuffer_add(keyBuffer, GAMEVER_KEY);
break;
case key_player:
// no custom player keys
break;
case key_team:
// no custom team keys
break;
}
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Reports the players and team counts.
///////////////////////////////////////
static int QRCountCallback
(
PEER peer,
qr2_key_type type,
void * param
)
{
PrintCallback("QRCount");
PrintStringParam("type", KeyTypeToString(type));
if(type == key_player)
return NumPlayers;
else if(type == key_team)
return 0;
return 0;
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Called when there is a server reporting error.
/////////////////////////////////////////////////
static void QRAddErrorCallback
(
PEER peer,
qr2_error_t error,
char * errorString,
void * param
)
{
PrintCallback("QRKeyList");
PrintStringParam("type", ErrorTypeToString(error));
PrintStringParam("errorString", errorString);
CString str;
str.Format("Peer: Server Reporting error: %s (%s)", ErrorTypeToString(error), errorString);
Wizard->MessageBox(str);
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Switching to this page.
//////////////////////////
BOOL CConnectPage::OnSetActive()
{
// Set which buttons the wizard shows.
//////////////////////////////////////
Wizard->SetWizardButtons(PSWIZB_NEXT);
//PEERSTART
if(Wizard->m_peer)
{
// Shutdown peer.
/////////////////
peerShutdown(Wizard->m_peer);
Wizard->m_peer = NULL;
}
//PEERSTOP
return CPropertyPage::OnSetActive();
}
// Called when peerConnect completes.
/////////////////////////////////////
static PEERBool connectSuccess;
static void ConnectCallback
(
PEER peer,
PEERBool success,
int failureReason,
void * param
)
{
connectSuccess = success;
if(!success)
ConnectPage->MessageBox("Failed to connect.");
GSI_UNUSED(param);
GSI_UNUSED(peer);
GSI_UNUSED(param);
GSI_UNUSED(failureReason);
}
// Called if there's an error with the nick.
////////////////////////////////////////////
static void NickErrorCallback
(
PEER peer,
int type,
const char * nick,
int numSuggestedNicks,
const char ** suggestedNicks,
void * param
)
{
connectSuccess = PEERFalse;
// Let the user know.
/////////////////////
if(type == PEER_IN_USE)
ConnectPage->MessageBox("That nickname is already taken, please choose another one.");
else
ConnectPage->MessageBox("That nickname contains at least 1 invalid character, please choose another one.");
//PEERSTART
// Cancel the connect.
// Could display a window here asking for an alternate nick.
////////////////////////////////////////////////////////////
peerRetryWithNick(peer, NULL);
//PEERSTOP
GSI_UNUSED(param);
GSI_UNUSED(suggestedNicks);
GSI_UNUSED(numSuggestedNicks);
GSI_UNUSED(nick);
}
// Going to the next page.
//////////////////////////
LRESULT CConnectPage::OnWizardNext()
{
// Check data.
//////////////
UpdateData();
Wizard->m_groupRooms = m_groupRooms;
if(m_nick == "")
{
MessageBox("You must enter a nickname.");
return -1;
}
if(m_title == "")
{
MessageBox("You must enter a title.");
return -1;
}
//PEERSTART
// Check that the game's backend is available.
//////////////////////////////////////////////
GSIACResult result;
GSIStartAvailableCheck(m_title);
while((result = GSIAvailableCheckThink()) == GSIACWaiting)
msleep(5);
if(result != GSIACAvailable)
{
MessageBox("The backend is not available\n");
return -1;
}
// Setup the callbacks.
///////////////////////
PEERCallbacks callbacks;
memset(&callbacks, 0, sizeof(PEERCallbacks));
callbacks.disconnected = DisconnectedCallback;
callbacks.readyChanged = ReadyChangedCallback;
callbacks.roomMessage = RoomMessageCallback;
callbacks.gameStarted = GameStartedCallback;
callbacks.playerJoined = PlayerJoinedCallback;
callbacks.playerLeft = PlayerLeftCallback;
callbacks.playerChangedNick = PlayerChangedNickCallback;
callbacks.ping = PingCallback;
callbacks.crossPing = CrossPingCallback;
callbacks.qrServerKey = QRServerKeyCallback;
callbacks.qrPlayerKey = QRPlayerKeyCallback;
callbacks.qrTeamKey = QRTeamKeyCallback;
callbacks.qrKeyList = QRKeyListCallback;
callbacks.qrCount = QRCountCallback;
callbacks.qrAddError = QRAddErrorCallback;
callbacks.param = NULL;
// Init peer.
/////////////
Wizard->m_peer = peerInitialize(&callbacks);
if(!Wizard->m_peer)
{
MessageBox("Error initializing peer.");
return -1;
}
// Setup which rooms to do pings and cross-pings in.
////////////////////////////////////////////////////
PEERBool pingRooms[NumRooms];
PEERBool crossPingRooms[NumRooms];
pingRooms[TitleRoom] = PEERFalse;
pingRooms[GroupRoom] = PEERTrue;
pingRooms[StagingRoom] = PEERTrue;
crossPingRooms[TitleRoom] = PEERFalse;
crossPingRooms[GroupRoom] = PEERFalse;
crossPingRooms[StagingRoom] = PEERTrue;
// Set the title.
/////////////////
if(!peerSetTitle(Wizard->m_peer, m_title, m_key, m_title, m_key, 0, 30, PEERFalse, pingRooms, crossPingRooms))
{
MessageBox("Error setting title.");
peerShutdown(Wizard->m_peer);
Wizard->m_peer = NULL;
return -1;
}
// Connect to chat.
///////////////////
Wizard->StartHourglass();
peerConnect(Wizard->m_peer, m_nick, 0, NickErrorCallback, ConnectCallback, NULL, PEERTrue);
Wizard->StopHourglass();
if(!connectSuccess)
{
MessageBox("Error connecting.");
peerShutdown(Wizard->m_peer);
Wizard->m_peer = NULL;
return -1;
}
//PEERSTOP
if(!m_groupRooms)
return IDD_GROUP_PAGE;
return CPropertyPage::OnWizardNext();
}

View file

@ -0,0 +1,57 @@
#if !defined(AFX_CONNECTPAGE_H__70C3619F_ED14_49F8_9155_9F96147FF4C2__INCLUDED_)
#define AFX_CONNECTPAGE_H__70C3619F_ED14_49F8_9155_9F96147FF4C2__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ConnectPage.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CConnectPage dialog
class CConnectPage : public CPropertyPage
{
DECLARE_DYNCREATE(CConnectPage)
// Construction
public:
CConnectPage();
~CConnectPage();
// Dialog Data
//{{AFX_DATA(CConnectPage)
enum { IDD = IDD_CONNECT_PAGE };
CString m_nick;
CString m_title;
BOOL m_groupRooms;
CString m_key;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CConnectPage)
public:
virtual BOOL OnSetActive();
virtual LRESULT OnWizardNext();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CConnectPage)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
extern CConnectPage * ConnectPage;
#endif // !defined(AFX_CONNECTPAGE_H__70C3619F_ED14_49F8_9155_9F96147FF4C2__INCLUDED_)

View file

@ -0,0 +1,115 @@
// CreatePage.cpp : implementation file
//
#include "stdafx.h"
#include "PeerLobby.h"
#include "CreatePage.h"
#include "LobbyWizard.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CCreatePage * CreatePage;
/////////////////////////////////////////////////////////////////////////////
// CCreatePage property page
IMPLEMENT_DYNCREATE(CCreatePage, CPropertyPage)
// Set page defaults.
/////////////////////
CCreatePage::CCreatePage() : CPropertyPage(CCreatePage::IDD)
{
//{{AFX_DATA_INIT(CCreatePage)
m_name = _T("My Server");
m_maxPlayers = 8;
//}}AFX_DATA_INIT
}
CCreatePage::~CCreatePage()
{
}
void CCreatePage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCreatePage)
DDX_Text(pDX, IDC_NAME, m_name);
DDX_Text(pDX, IDC_MAX_PLAYERS, m_maxPlayers);
DDV_MinMaxInt(pDX, m_maxPlayers, 2, 9999);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCreatePage, CPropertyPage)
//{{AFX_MSG_MAP(CCreatePage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// Switching to this page.
//////////////////////////
BOOL CCreatePage::OnSetActive()
{
// Show the back and next buttons.
//////////////////////////////////
Wizard->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
// We're hosting the room.
//////////////////////////
Wizard->m_hosting = TRUE;
return CPropertyPage::OnSetActive();
}
// Going to the previous page.
//////////////////////////////
LRESULT CCreatePage::OnWizardBack()
{
// Not hosting anymore.
///////////////////////
Wizard->m_hosting = FALSE;
return CPropertyPage::OnWizardBack();
}
// Called when the staging room has been created (or the attempt failed).
/////////////////////////////////////////////////////////////////////////
static PEERBool createStagingSuccess;
static void CreateStagingRoomCallback
(
PEER peer,
PEERBool success,
PEERJoinResult result,
RoomType roomType,
void * param
)
{
createStagingSuccess = success;
GSI_UNUSED(param);
GSI_UNUSED(roomType);
GSI_UNUSED(result);
GSI_UNUSED(peer);
}
// Going to the next page.
//////////////////////////
LRESULT CCreatePage::OnWizardNext()
{
// Update the data.
///////////////////
UpdateData();
//PEERSTART
// Create the room.
///////////////////
Wizard->StartHourglass();
peerCreateStagingRoom(Wizard->m_peer, m_name, m_maxPlayers, NULL, CreateStagingRoomCallback, NULL, PEERTrue);
Wizard->StopHourglass();
//PEERSTOP
return CPropertyPage::OnWizardNext();
}

View file

@ -0,0 +1,55 @@
#if !defined(AFX_CREATEPAGE_H__4FC1C8CA_9B4C_47F6_B226_C211DC74D504__INCLUDED_)
#define AFX_CREATEPAGE_H__4FC1C8CA_9B4C_47F6_B226_C211DC74D504__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// CreatePage.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CCreatePage dialog
class CCreatePage : public CPropertyPage
{
DECLARE_DYNCREATE(CCreatePage)
// Construction
public:
CCreatePage();
~CCreatePage();
// Dialog Data
//{{AFX_DATA(CCreatePage)
enum { IDD = IDD_CREATE_PAGE };
CString m_name;
int m_maxPlayers;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CCreatePage)
public:
virtual BOOL OnSetActive();
virtual LRESULT OnWizardBack();
virtual LRESULT OnWizardNext();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CCreatePage)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
extern CCreatePage * CreatePage;
#endif // !defined(AFX_CREATEPAGE_H__4FC1C8CA_9B4C_47F6_B226_C211DC74D504__INCLUDED_)

View file

@ -0,0 +1,668 @@
// GroupPage.cpp : implementation file
//
#include "stdafx.h"
#include "PeerLobby.h"
#include "GroupPage.h"
#include "LobbyWizard.h"
#include "ConnectPage.h"
#include "TitlePage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CGroupPage * GroupPage;
#define COL_NAME 0
#define COL_PING 1
#define COL_RUNNING 2
#define COL_NUM_PLAYERS 3
/////////////////////////////////////////////////////////////////////////////
// CGroupPage property page
IMPLEMENT_DYNCREATE(CGroupPage, CPropertyPage)
// Set page defaults.
/////////////////////
CGroupPage::CGroupPage() : CPropertyPage(CGroupPage::IDD)
{
//{{AFX_DATA_INIT(CGroupPage)
m_message = _T("");
//}}AFX_DATA_INIT
}
CGroupPage::~CGroupPage()
{
}
void CGroupPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CGroupPage)
DDX_Control(pDX, IDC_PLAYERS, m_players);
DDX_Control(pDX, IDC_GAMES, m_games);
DDX_Control(pDX, IDC_CHAT_WINDOW, m_chatWindow);
DDX_Control(pDX, IDC_PROGRESS, m_progress);
DDX_Text(pDX, IDC_MESSAGE, m_message);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CGroupPage, CPropertyPage)
//{{AFX_MSG_MAP(CGroupPage)
ON_BN_CLICKED(IDC_CREATE, OnCreate)
ON_NOTIFY(NM_CLICK, IDC_GAMES, OnClickGames)
ON_NOTIFY(LVN_BEGINDRAG, IDC_GAMES, OnBegindragGames)
ON_NOTIFY(NM_DBLCLK, IDC_GAMES, OnDblclkGames)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// Gets called to maintain the game list.
/////////////////////////////////////////
static void ListingGamesCallback
(
PEER peer,
PEERBool success,
const char * name,
SBServer server,
PEERBool staging,
int msg,
int progress,
void * param
)
{
LVITEM item;
// Check for failure.
/////////////////////
if(!success)
{
Wizard->MessageBox("Listing games failed!");
Wizard->EndDialog(IDOK);
return;
}
// Cache pointers.
//////////////////
CListCtrl * games = &GroupPage->m_games;
CListedGame * game = NULL;
BOOL doUpdate = FALSE;
int nIndex = -1;
// Set the progress.
////////////////////
GroupPage->m_progress.SetPos(progress);
// Handle the message based on its type.
////////////////////////////////////////
if(msg == PEER_CLEAR)
{
GroupPage->ClearGames();
}
else if(msg == PEER_ADD)
{
// Add this to the list.
////////////////////////
game = new CListedGame;
game->server = server;
game->name = name;
game->staging = staging;
game->ping = SBServerGetPing(server);
game->numPlayers = SBServerGetIntValue(server, "numplayers", 0);
game->maxPlayers = SBServerGetIntValue(server, "maxplayers", 0);
nIndex = games->InsertItem(LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE,
0,
(LPCTSTR)name,
0, 0,
staging ? Wizard->m_stagingRoomIndex : Wizard->m_runningGameIndex,
(LPARAM)game);
if(nIndex == -1)
{
delete game;
return;
}
doUpdate = TRUE;
}
else if(msg == PEER_UPDATE)
{
nIndex = GroupPage->FindListedGame(server);
if(nIndex != -1)
{
// Update values.
/////////////////
game = (CListedGame *)games->GetItemData(nIndex);
game->name = name;
game->staging = staging;
game->ping = SBServerGetPing(server);
game->numPlayers = SBServerGetIntValue(server, "numplayers", 0);
game->maxPlayers = SBServerGetIntValue(server, "maxplayers", 0);
// Update the list.
///////////////////
item.mask = LVIF_IMAGE;
item.iItem = nIndex;
item.iSubItem = 0;
item.iImage = staging ? Wizard->m_stagingRoomIndex : Wizard->m_runningGameIndex;
games->SetItem(&item);
doUpdate = TRUE;
}
}
else if(msg == PEER_REMOVE)
{
nIndex = GroupPage->FindListedGame(server);
if(nIndex != -1)
{
delete (CListedGame *)games->GetItemData(nIndex);
games->DeleteItem(nIndex);
}
}
if(doUpdate)
{
item.mask = LVIF_TEXT;
item.iItem = nIndex;
item.iSubItem = COL_PING;
char buffer[32];
sprintf(buffer, "%d", game->ping);
item.pszText = buffer;
games->SetItem(&item);
item.iSubItem = COL_RUNNING;
if(staging)
item.pszText = "No";
else
item.pszText = "Yes";
games->SetItem(&item);
item.iSubItem = COL_NUM_PLAYERS;
sprintf(buffer, "%d/%d", game->numPlayers, game->maxPlayers);
item.pszText = buffer;
games->SetItem(&item);
}
GSI_UNUSED(param);
GSI_UNUSED(peer);
}
// Used to list the players in the room.
////////////////////////////////////////
static void EnumPlayersCallback
(
PEER peer,
PEERBool success,
RoomType roomType,
int index,
const char * nick,
int flags,
void * param
)
{
if(!success)
{
Wizard->MessageBox("Error listing players.");
return;
}
if(index == -1)
return;
GroupPage->UpdatePlayerPing(nick, 9999);
GSI_UNUSED(param);
GSI_UNUSED(flags);
GSI_UNUSED(roomType);
GSI_UNUSED(peer);
}
static PEERBool joinSuccess;
static void JoinTitleRoomCallback
(
PEER peer,
PEERBool success,
PEERJoinResult result,
RoomType roomType,
void * param
)
{
joinSuccess = success;
if(success)
{
//PEERSTART
// List the players in the room.
////////////////////////////////
peerEnumPlayers(Wizard->m_peer, TitleRoom, EnumPlayersCallback, NULL);
//PEERSTOP
}
GSI_UNUSED(param);
GSI_UNUSED(roomType);
GSI_UNUSED(result);
GSI_UNUSED(peer);
}
// Switching to this page.
//////////////////////////
BOOL CGroupPage::OnSetActive()
{
// Start off with only a back button.
/////////////////////////////////////
Wizard->SetWizardButtons(PSWIZB_BACK);
// Rename the next button.
//////////////////////////
::SetWindowText(Wizard->m_nextButtonWnd, "&Join >");
// Clear the progress bar.
//////////////////////////
m_progress.SetPos(0);
// Clear the game list.
///////////////////////
ClearGames();
// Clear the chat log.
//////////////////////
m_chatWindow.ResetContent();
//PEERSTART
if(!Wizard->m_groupRooms)
{
// Join the title room.
///////////////////////
Wizard->StartHourglass();
peerJoinTitleRoom(Wizard->m_peer, NULL, JoinTitleRoomCallback, NULL, PEERTrue);
Wizard->StopHourglass();
if(!joinSuccess)
{
MessageBox("Error joining the title room.");
return FALSE;
}
}
else
{
// List the players in the room.
////////////////////////////////
peerEnumPlayers(Wizard->m_peer, GroupRoom, EnumPlayersCallback, NULL);
}
// Start listing games.
////////////////////////
unsigned char fields[] = { GAMEVER_KEY, NUMPLAYERS_KEY, MAXPLAYERS_KEY };
peerStartListingGames(Wizard->m_peer, fields, sizeof(fields), NULL, ListingGamesCallback, NULL);
//PEERSTOP
// Setup the player's box columns.
//////////////////////////////////
if(Wizard->m_groupRooms)
{
m_players.InsertColumn(COL_NAME, "Player", LVCFMT_LEFT, 70);
m_players.InsertColumn(COL_PING, "Ping", LVCFMT_LEFT, 50);
}
else
m_players.InsertColumn(COL_NAME, "Player", LVCFMT_LEFT, 120);
return CPropertyPage::OnSetActive();
}
// Leaving this page.
/////////////////////
BOOL CGroupPage::OnKillActive()
{
//PEERSTART
if(!Wizard->m_groupRooms)
peerLeaveRoom(Wizard->m_peer, TitleRoom, NULL);
//PEERSTOP
// Delete player columns.
/////////////////////////
m_players.DeleteColumn(0);
if(Wizard->m_groupRooms)
m_players.DeleteColumn(1);
// Reset the "next" button's name.
//////////////////////////////////
::SetWindowText(Wizard->m_nextButtonWnd, "&Next >");
// Clear the players.
/////////////////////
m_players.DeleteAllItems();
return CPropertyPage::OnKillActive();
}
// Going to the next page.
//////////////////////////
LRESULT CGroupPage::OnWizardNext()
{
// Update vars.
///////////////
UpdateData();
// Make sure something was selected.
////////////////////////////////////
int nIndex = m_games.GetSelectionMark();
if(nIndex == -1)
{
MessageBox("You must have a game selected.");
return -1;
}
// Join the game.
/////////////////
JoinGame(nIndex);
return (LRESULT)1;
}
LRESULT CGroupPage::OnWizardBack()
{
//PEERSTART
// Leave the group room.
////////////////////////
if(Wizard->m_groupRooms)
peerLeaveRoom(Wizard->m_peer, GroupRoom, NULL);
else
return IDD_CONNECT_PAGE;
//PEERSTOP
return CPropertyPage::OnWizardBack();
}
// Init the page.
/////////////////
BOOL CGroupPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// Set the games columns.
/////////////////////////
m_games.InsertColumn(COL_NAME, "Server Name", LVCFMT_LEFT, 170);
m_games.InsertColumn(COL_PING, "Ping", LVCFMT_LEFT, 50);
m_games.InsertColumn(COL_RUNNING, "Running", LVCFMT_LEFT, 60);
m_games.InsertColumn(COL_NUM_PLAYERS, "Num Players", LVCFMT_LEFT, 75);
ListView_SetExtendedListViewStyle(m_games.m_hWnd,LVS_EX_FULLROWSELECT);
// Image list setup.
////////////////////
m_games.SetImageList(&Wizard->m_imageList, LVSIL_SMALL);
return TRUE;
}
// Cleanup the page.
////////////////////
void CGroupPage::OnDestroy()
{
CPropertyPage::OnDestroy();
// Clear the game list.
///////////////////////
ClearGames();
}
// Clear the list of games.
///////////////////////////
void CGroupPage::ClearGames()
{
// Free the data first.
///////////////////////
int count = m_games.GetItemCount();
int i;
for(i = 0 ; i < count ; i++)
{
LVITEM item;
item.mask = LVIF_PARAM;
item.iItem = i;
item.iSubItem = 0;
if(m_games.GetItem(&item) && item.lParam)
delete (CListedGame *)item.lParam;
}
// Clear the list.
//////////////////
m_games.DeleteAllItems();
}
// Create a staging room.
/////////////////////////
void CGroupPage::OnCreate()
{
//PEERSTART
// Stop listing games.
//////////////////////
peerStopListingGames(Wizard->m_peer);
//PEERSTOP
// Goto the create page.
////////////////////////
Wizard->SetActivePage(CREATE_PAGE);
}
// Join a game.
///////////////
void CGroupPage::OnDblclkGames(NMHDR* pNMHDR, LRESULT* pResult)
{
NMHEADER * header = (NMHEADER *)pNMHDR;
// If something was double-clicked, join it.
////////////////////////////////////////////
if(header->iItem != -1)
JoinGame(header->iItem);
*pResult = 0;
}
// Handle game list clicks.
///////////////////////////
void CGroupPage::OnClickGames(NMHDR* pNMHDR, LRESULT* pResult)
{
// Enable/Disable join based on if something is selected.
/////////////////////////////////////////////////////////
BOOL enable = (m_games.GetSelectedCount() > 0);
::EnableWindow(Wizard->m_nextButtonWnd, enable);
*pResult = 0;
GSI_UNUSED(pNMHDR);
}
void CGroupPage::OnBegindragGames(NMHDR* pNMHDR, LRESULT* pResult)
{
// Treat this like a click.
// (OnClick() isn't called for "drags".
///////////////////////////////////////
OnClickGames(pNMHDR, pResult);
}
// Find the index of a game in the list by its SBServer object.
///////////////////////////////////////////////////////////////
int CGroupPage::FindListedGame(SBServer server)
{
int count = m_games.GetItemCount();
int i;
CListedGame * game;
for(i = 0 ; i < count ; i++)
{
game = (CListedGame *)m_games.GetItemData(i);
if(game && game->server == server)
return i;
}
return -1;
}
// Find the index of a player in the list by its nick.
//////////////////////////////////////////////////////
int CGroupPage::FindPlayer(const char * nick)
{
// Always deal in lower-case.
/////////////////////////////
CString loweredNick = nick;
loweredNick.MakeLower();
nick = loweredNick;
// Look for this player.
////////////////////////
LVFINDINFO findInfo;
findInfo.flags = LVFI_STRING;
findInfo.psz = nick;
// Find the player.
///////////////////
int nIndex = m_players.FindItem(&findInfo);
return nIndex;
}
// Updates the player's ping in the player list, and adds the player
// if its not on the list.
////////////////////////////////////////////////////////////////////
void CGroupPage::UpdatePlayerPing(const char * nick, int ping)
{
LVITEM item;
// Is this us?
//////////////
if(strcasecmp(nick, ConnectPage->m_nick) == 0)
ping = 0;
// Always deal in lower-case.
/////////////////////////////
CString loweredNick = nick;
loweredNick.MakeLower();
nick = loweredNick;
// Find the player.
///////////////////
int nIndex = FindPlayer(nick);
// Check for a new nick.
////////////////////////
if(nIndex == -1)
{
item.iItem = 0;
item.iSubItem = 0;
item.mask = LVIF_TEXT;
item.pszText = (char *)nick;
nIndex = m_players.InsertItem(&item);
if(nIndex == -1)
return;
}
// Add the ping.
////////////////
char intValue[16];
sprintf(intValue, "%d", ping);
item.iItem = nIndex;
item.iSubItem = 1;
item.mask = LVIF_TEXT;
item.pszText = intValue;
m_players.SetItem(&item);
}
// Remove the player from the list.
///////////////////////////////////
void CGroupPage::RemovePlayer(const char * nick)
{
// Always deal in lower-case.
/////////////////////////////
CString loweredNick = nick;
loweredNick.MakeLower();
nick = loweredNick;
// Find the player.
///////////////////
int nIndex = FindPlayer(nick);
// Remove it.
/////////////
m_players.DeleteItem(nIndex);
}
// Change a nick in the player list.
////////////////////////////////////
void CGroupPage::ChangePlayerNick(const char * oldNick, const char * newNick)
{
// Always deal in lower-case.
/////////////////////////////
CString loweredNick = oldNick;
loweredNick.MakeLower();
oldNick = loweredNick;
loweredNick = newNick;
loweredNick.MakeLower();
newNick = loweredNick;
// Find the player.
///////////////////
int nIndex = FindPlayer(oldNick);
// Update the nick.
///////////////////
LVITEM item;
item.iItem = nIndex;
item.iSubItem = 0;
item.mask = LVIF_TEXT;
item.pszText = (char *)newNick;
m_players.SetItem(&item);
}
// Join a game based on its index in the game list.
///////////////////////////////////////////////////
void CGroupPage::JoinGame(int nIndex)
{
// Get the data.
////////////////
CListedGame * game = (CListedGame *)m_games.GetItemData(nIndex);
ASSERT(game);
// Is it staging?
/////////////////
if(game->staging)
{
// Goto the staging room page.
//////////////////////////////
Wizard->SetActivePage(STAGING_PAGE);
}
else
{
//PEERSTART
// Because there's no staging room for this game, it can just be joined.
// You can get info on the server using the GOA ServerGet*() functions.
////////////////////////////////////////////////////////////////////////
CString buffer = "You are now playing at ";
buffer += SBServerGetPublicAddress(game->server);
buffer += ".\nHit enter when you are done.";
MessageBox(buffer);
//PEERSTOP
}
}
// Does the actual chat message sending.
////////////////////////////////////////
void CGroupPage::SendMessage()
{
UpdateData();
// Ignore blank message.
////////////////////////
if(m_message == "")
return;
//PEERSTART
// Send it.
///////////
peerMessageRoom(Wizard->m_peer, Wizard->m_groupRooms?GroupRoom:TitleRoom, m_message, NormalMessage);
//PEERSTOP
// Clear it.
////////////
m_message = "";
UpdateData(FALSE);
}

View file

@ -0,0 +1,88 @@
#if !defined(AFX_GROUPPAGE_H__BC96C600_E6B9_49FF_8E49_75A013B824B2__INCLUDED_)
#define AFX_GROUPPAGE_H__BC96C600_E6B9_49FF_8E49_75A013B824B2__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// GroupPage.h : header file
//
#include "../peer.h"
/////////////////////////////////////////////////////////////////////////////
// CGroupPage dialog
struct CListedGame
{
SBServer server;
CString name;
PEERBool staging;
int ping;
int numPlayers;
int maxPlayers;
};
class CGroupPage : public CPropertyPage
{
DECLARE_DYNCREATE(CGroupPage)
// Construction
public:
CGroupPage();
~CGroupPage();
// Dialog Data
//{{AFX_DATA(CGroupPage)
enum { IDD = IDD_GROUP_PAGE };
CListCtrl m_players;
CListCtrl m_games;
CListBox m_chatWindow;
CProgressCtrl m_progress;
CButton m_sendButton;
CString m_message;
//}}AFX_DATA
void ClearGames();
int FindListedGame(SBServer server);
int FindPlayer(const char * nick);
void UpdatePlayerPing(const char * nick, int ping);
void RemovePlayer(const char * nick);
void ChangePlayerNick(const char * oldNick, const char * newNick);
void JoinGame(int nIndex);
void SendMessage();
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CGroupPage)
public:
virtual BOOL OnSetActive();
virtual LRESULT OnWizardNext();
virtual BOOL OnKillActive();
virtual LRESULT OnWizardBack();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CGroupPage)
virtual BOOL OnInitDialog();
afx_msg void OnCreate();
afx_msg void OnClickGames(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnBegindragGames(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDblclkGames(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
extern CGroupPage * GroupPage;
#endif // !defined(AFX_GROUPPAGE_H__BC96C600_E6B9_49FF_8E49_75A013B824B2__INCLUDED_)

View file

@ -0,0 +1,200 @@
// LobbyWizard.cpp : implementation file
//
#include "stdafx.h"
#include "PeerLobby.h"
#include "LobbyWizard.h"
#include "GroupPage.h"
#include "StagingPage.h"
#include "TitlePage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CLobbyWizard * Wizard;
#define THINK_TIMER 100
/////////////////////////////////////////////////////////////////////////////
// CLobbyWizard
IMPLEMENT_DYNAMIC(CLobbyWizard, CPropertySheet)
CLobbyWizard::CLobbyWizard(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
//PEERSTART
// Initialize our peer pointer to NULL.
///////////////////////////////////////
m_peer = NULL;
//PEERSTOP
}
CLobbyWizard::CLobbyWizard(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
//PEERSTART
// Initialize our peer pointer to NULL.
///////////////////////////////////////
m_peer = NULL;
//PEERSTOP
}
CLobbyWizard::~CLobbyWizard()
{
}
BEGIN_MESSAGE_MAP(CLobbyWizard, CPropertySheet)
//{{AFX_MSG_MAP(CLobbyWizard)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLobbyWizard message handlers
// Init the wizard.
///////////////////
BOOL CLobbyWizard::OnInitDialog()
{
BOOL bResult = CPropertySheet::OnInitDialog();
// Get the "next" button wnd.
/////////////////////////////
m_nextButtonWnd = ::FindWindowEx(this->m_hWnd, NULL, "Button", "&Next >");
// Rename "Cancel" to "Quit".
/////////////////////////////
HWND hWnd = ::FindWindowEx(this->m_hWnd, NULL, "Button", "Cancel");
if(hWnd)
::SetWindowText(hWnd, "&Quit");
// Hide the "Help" button.
//////////////////////////
hWnd = ::FindWindowEx(this->m_hWnd, NULL, "Button", "Help");
if(hWnd)
::ShowWindow(hWnd, SW_HIDE);
// Load icons.
//////////////
m_greenSmileyIcon = AfxGetApp()->LoadIcon(IDI_GREEN_SMILEY);
m_yellowSmileyIcon = AfxGetApp()->LoadIcon(IDI_YELLOW_SMILEY);
m_redSmileyIcon = AfxGetApp()->LoadIcon(IDI_RED_SMILEY);
m_stagingRoomIcon = AfxGetApp()->LoadIcon(IDI_STAGING_ROOM);
m_runningGameIcon = AfxGetApp()->LoadIcon(IDI_RUNNING_GAME);
if(!m_greenSmileyIcon || !m_yellowSmileyIcon || !m_redSmileyIcon || !m_stagingRoomIcon || !m_runningGameIcon)
return FALSE;
// Create the image list.
/////////////////////////
if(!m_imageList.Create(16, 16, ILC_COLOR, 5, 5))
return FALSE;
m_greenSmileyIndex = m_imageList.Add(m_greenSmileyIcon);
m_yellowSmileyIndex = m_imageList.Add(m_yellowSmileyIcon);
m_redSmileyIndex = m_imageList.Add(m_redSmileyIcon);
m_stagingRoomIndex = m_imageList.Add(m_stagingRoomIcon);
m_runningGameIndex = m_imageList.Add(m_runningGameIcon);
if((m_yellowSmileyIndex == -1) || (m_redSmileyIndex == -1) || (m_greenSmileyIndex == -1) || (m_runningGameIndex == -1) || (m_stagingRoomIndex == -1))
return FALSE;
//PEERSTART
// We're not hosting.
/////////////////////
m_hosting = FALSE;
// Set the timer for every 10 seconds.
//////////////////////////////////////
SetTimer(THINK_TIMER, 10, NULL);
//PEERSTOP
return bResult;
}
// Think every 10ms.
////////////////////
void CLobbyWizard::OnTimer(UINT nIDEvent)
{
if(nIDEvent == THINK_TIMER)
{
//PEERSTART
// Let peer think.
//////////////////
if(m_peer)
peerThink(m_peer);
//PEERSTOP
}
CPropertySheet::OnTimer(nIDEvent);
}
// Show the hourglass.
//////////////////////
void CLobbyWizard::StartHourglass()
{
// Load the hourglass.
//////////////////////
HCURSOR hourglass = LoadCursor(NULL, IDC_WAIT);
if(!hourglass)
return;
// Set the cursor.
//////////////////
m_lastCursor = SetCursor(hourglass);
}
// Back to normal pointer.
//////////////////////////
void CLobbyWizard::StopHourglass()
{
// Reset the old cursor.
////////////////////////
SetCursor(m_lastCursor);
}
// Catch [Enter] when pressed in a chat message box.
////////////////////////////////////////////////////
BOOL CLobbyWizard::PreTranslateMessage(MSG* pMsg)
{
// Check for enter.
///////////////////
if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == 0x0d))
{
// Check what page we're on.
/////////////////////////////
int page = GetActiveIndex();
CWnd * focus;
if(page == TITLE_PAGE)
{
focus = TitlePage->GetFocus();
if(focus->m_hWnd == TitlePage->GetDlgItem(IDC_MESSAGE)->m_hWnd)
{
TitlePage->SendMessage();
return TRUE;
}
}
else if(page == GROUP_PAGE)
{
focus = GroupPage->GetFocus();
if(focus->m_hWnd == GroupPage->GetDlgItem(IDC_MESSAGE)->m_hWnd)
{
GroupPage->SendMessage();
return TRUE;
}
}
else if(page == STAGING_PAGE)
{
focus = StagingPage->GetFocus();
if(focus->m_hWnd == StagingPage->GetDlgItem(IDC_MESSAGE)->m_hWnd)
{
StagingPage->SendMessage();
return TRUE;
}
}
}
return CPropertySheet::PreTranslateMessage(pMsg);
}

Some files were not shown because too many files have changed in this diff Show more