openmohaa/code/gamespy/GP/gp.c

4319 lines
110 KiB
C
Raw Normal View History

2023-02-04 21:00:01 +01:00
/*
gp.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"
//FUNCTIONS
///////////
GPResult gpInitialize(
GPConnection * connection,
int productID,
int namespaceID,
int partnerID
)
{
// Check if the backend is available.
/////////////////////////////////////
if(__GSIACResult != GSIACAvailable)
return GP_PARAMETER_ERROR;
// Error check.
///////////////
if(connection == NULL)
return GP_PARAMETER_ERROR;
return gpiInitialize(connection, productID, namespaceID, partnerID);
}
void gpDestroy(
GPConnection * connection
)
{
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return;
gpiDestroy(connection);
}
GPResult gpEnable(
GPConnection * connection,
GPEnum state
)
{
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
return gpiEnable(connection, state);
}
GPResult gpDisable(
GPConnection * connection,
GPEnum state
)
{
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
return gpiDisable(connection, state);
}
GPResult gpProcess(
GPConnection * connection
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
return gpiProcess(connection, 0);
}
GPResult gpSetCallback(
GPConnection * connection,
GPEnum func,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
int index;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Find which callback.
///////////////////////
index = func;
if((index < 0) || (index >= GPI_NUM_CALLBACKS))
Error(connection, GP_PARAMETER_ERROR, "Invalid func.");
// Set the info.
////////////////
iconnection->callbacks[index].callback = callback;
iconnection->callbacks[index].param = param;
return GP_NO_ERROR;
}
GPResult gpConnectA(
GPConnection * connection,
const char nick[GP_NICK_LEN],
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((nick == NULL) || (nick[0] == '\0'))
return GP_PARAMETER_ERROR;
if((email == NULL) || (email[0] == '\0'))
return GP_PARAMETER_ERROR;
if((password == NULL) || (password[0] == '\0'))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPConnectResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do it.
/////////
return gpiConnect(connection, nick, "", email, password, "", "", NULL, firewall, GPIFalse, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpConnectW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
const unsigned short email[GP_EMAIL_LEN],
const unsigned short password[GP_PASSWORD_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
char email_A[GP_EMAIL_LEN];
char password_A[GP_PASSWORD_LEN];
UCS2ToAsciiString(nick, nick_A);
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(password, password_A);
return gpConnectA(connection, nick_A, email_A, password_A, firewall, blocking, callback, param);
}
#endif
GPResult gpConnectNewUserA(
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 firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((nick == NULL) || (nick[0] == '\0'))
return GP_PARAMETER_ERROR;
if(uniquenick == NULL)
uniquenick = "";
if((email == NULL) || (email[0] == '\0'))
return GP_PARAMETER_ERROR;
if((password == NULL) || (password[0] == '\0'))
return GP_PARAMETER_ERROR;
if(cdkey && (cdkey[0] == '\0'))
cdkey = NULL;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the nick.
////////////////////////////////
if(strlen(nick) >= GP_NICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Nick too long.");
// Check the length of the uniquenick.
//////////////////////////////////////
if(strlen(uniquenick) >= GP_UNIQUENICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Uniquenick too long.");
// Check the length of the email.
/////////////////////////////////
if(strlen(email) >= GP_EMAIL_LEN)
Error(connection, GP_PARAMETER_ERROR, "Email too long.");
// Check the length of the password.
////////////////////////////////////
if(strlen(password) >= GP_PASSWORD_LEN)
Error(connection, GP_PARAMETER_ERROR, "Password too long.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPConnectResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do it.
/////////
return gpiConnect(connection, nick, uniquenick, email, password, "", "", cdkey, firewall, GPITrue, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpConnectNewUserW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const unsigned short email[GP_EMAIL_LEN],
const unsigned short password[GP_PASSWORD_LEN],
const unsigned short cdkey[GP_CDKEY_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
char uniquenick_A[GP_UNIQUENICK_LEN];
char email_A[GP_NICK_LEN];
char password_A[GP_NICK_LEN];
char cdkey_A[GP_CDKEY_LEN];
UCS2ToAsciiString(nick, nick_A);
UCS2ToAsciiString(uniquenick, uniquenick_A);
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(password, password_A);
UCS2ToAsciiString(cdkey, cdkey_A);
return gpConnectNewUserA(connection, nick_A, uniquenick_A, email_A, password_A, cdkey_A, firewall, blocking, callback, param);
}
#endif
GPResult gpConnectUniqueNickA(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const char password[GP_PASSWORD_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((uniquenick == NULL) || (uniquenick[0] == '\0'))
return GP_PARAMETER_ERROR;
if((password == NULL) || (password[0] == '\0'))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPConnectResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do it.
/////////
return gpiConnect(connection, "", uniquenick, "", password, "", "", NULL, firewall, GPIFalse, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpConnectUniqueNickW(
GPConnection * connection,
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const unsigned short password[GP_PASSWORD_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char uniquenick_A[GP_UNIQUENICK_LEN];
char password_A[GP_NICK_LEN];
UCS2ToAsciiString(uniquenick, uniquenick_A);
UCS2ToAsciiString(password, password_A);
return gpConnectUniqueNickA(connection, uniquenick_A, password_A, firewall, blocking, callback, param);
}
#endif
GPResult gpConnectPreAuthenticatedA
(
GPConnection * connection,
const char authtoken[GP_AUTHTOKEN_LEN],
const char partnerchallenge[GP_PARTNERCHALLENGE_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((authtoken == NULL) || (authtoken[0] == '\0'))
return GP_PARAMETER_ERROR;
if((partnerchallenge == NULL) || (partnerchallenge[0] == '\0'))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPConnectResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do it.
/////////
return gpiConnect(connection, "", "", "", "", authtoken, partnerchallenge, NULL, firewall, GPIFalse, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpConnectPreAuthenticatedW
(
GPConnection * connection,
const unsigned short authtoken[GP_AUTHTOKEN_LEN],
const unsigned short partnerchallenge[GP_PARTNERCHALLENGE_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char authtoken_A[GP_AUTHTOKEN_LEN];
char partnerchallenge_A[GP_PARTNERCHALLENGE_LEN];
UCS2ToAsciiString(authtoken, authtoken_A);
UCS2ToAsciiString(partnerchallenge, partnerchallenge_A);
return gpConnectPreAuthenticatedA(connection, authtoken_A, partnerchallenge_A, firewall, blocking, callback, param);
}
#endif
void gpDisconnect(
GPConnection * connection
)
{
GPIConnection * iconnection;
int oldState;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return;
// Make a note of connection state prior to reset
/////////////////////////////////////////////////
oldState = iconnection->connectState;
gpiDisconnect(connection, GPITrue);
//Added by Saad Nader
//08-28-2004; fix for memory leaks after being disconnected abruptly
////////////////////////////////////////////////
gpiReset(connection);
// If we were connected prior, set to disconnected to save off info cache
//////////////////////////////////////////////////////////////////////////
if (oldState == GPI_CONNECTED)
iconnection->connectState = GPI_DISCONNECTED;
}
GPResult gpIsConnected
(
GPConnection * connection,
GPEnum * connected
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Set the flag.
////////////////
if(iconnection->connectState == GPI_CONNECTED)
*connected = GP_CONNECTED;
else
*connected = GP_NOT_CONNECTED;
return GP_NO_ERROR;
}
GPResult gpCheckUserA(
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
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the nick.
////////////////////////////////
if(strlen(nick) >= GP_NICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Nick too long.");
// Check the length of the email.
/////////////////////////////////
if(strlen(email) >= GP_EMAIL_LEN)
Error(connection, GP_PARAMETER_ERROR, "Email too long.");
// Check the length of the password.
////////////////////////////////////
if(password && (strlen(password) >= GP_PASSWORD_LEN))
Error(connection, GP_PARAMETER_ERROR, "Password too long.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPCheckResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do the check.
////////////////
return gpiCheckUser(connection, nick, email, password, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpCheckUserW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
const unsigned short email[GP_EMAIL_LEN],
const unsigned short password[GP_PASSWORD_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
char email_A[GP_NICK_LEN];
char password_A[GP_NICK_LEN];
UCS2ToAsciiString(nick, nick_A);
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(password, password_A);
return gpCheckUserA(connection, nick_A, email_A, password_A, blocking, callback, param);
}
#endif
GPResult gpNewUserA(
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
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((nick == NULL) || (nick[0] == '\0'))
return GP_PARAMETER_ERROR;
if(uniquenick == NULL)
uniquenick = "";
if((email == NULL) || (email[0] == '\0'))
return GP_PARAMETER_ERROR;
if((password == NULL) || (password[0] == '\0'))
return GP_PARAMETER_ERROR;
if(cdkey && (cdkey[0] == '\0'))
cdkey = NULL;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the nick.
////////////////////////////////
if(strlen(nick) >= GP_NICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Nick too long.");
// Check the length of the uniquenick.
//////////////////////////////////////
if(strlen(uniquenick) >= GP_UNIQUENICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Uniquenick too long.");
// Check the length of the email.
/////////////////////////////////
if(strlen(email) >= GP_EMAIL_LEN)
Error(connection, GP_PARAMETER_ERROR, "Email too long.");
// Check the length of the password.
////////////////////////////////////
if(strlen(password) >= GP_PASSWORD_LEN)
Error(connection, GP_PARAMETER_ERROR, "Password too long.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPNewUserResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Creat the new user.
//////////////////////
return gpiNewUser(connection, nick, uniquenick, email, password, cdkey, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpNewUserW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const unsigned short email[GP_EMAIL_LEN],
const unsigned short password[GP_PASSWORD_LEN],
const unsigned short cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
char uniquenick_A[GP_UNIQUENICK_LEN];
char email_A[GP_EMAIL_LEN];
char password_A[GP_PASSWORD_LEN];
char cdkey_A[GP_CDKEY_LEN];
UCS2ToAsciiString(nick, nick_A);
UCS2ToAsciiString(uniquenick, uniquenick_A);
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(password, password_A);
UCS2ToAsciiString(cdkey, cdkey_A);
return gpNewUserA(connection, nick_A, uniquenick_A, email_A, password_A, cdkey_A, blocking, callback, param);
}
#endif
GPResult gpSuggestUniqueNickA(
GPConnection * connection,
const char desirednick[GP_NICK_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the desirednick.
///////////////////////////////////////
if(strlen(desirednick) >= GP_UNIQUENICK_LEN)
Error(connection, GP_PARAMETER_ERROR, "Desirednick too long.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPSuggestUniqueNickResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Creat the new user.
//////////////////////
return gpiSuggestUniqueNick(connection, desirednick, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpSuggestUniqueNickW(
GPConnection * connection,
const unsigned short desirednick[GP_NICK_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char desirednick_A[GP_UNIQUENICK_LEN];
UCS2ToAsciiString(desirednick, desirednick_A);
return gpSuggestUniqueNickA(connection, desirednick_A, blocking, callback, param);
}
#endif
GPResult gpRegisterUniqueNickA(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((uniquenick == NULL) || (uniquenick[0] == '\0'))
return GP_PARAMETER_ERROR;
if(cdkey && (cdkey[0] == '\0'))
cdkey = NULL;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPRegisterUniqueNickResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiRegisterUniqueNick(connection, uniquenick, cdkey, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpRegisterUniqueNickW(
GPConnection * connection,
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const unsigned short cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char uniquenick_A[GP_UNIQUENICK_LEN];
char cdkey_A[GP_CDKEY_LEN];
UCS2ToAsciiString(uniquenick, uniquenick_A);
UCS2ToAsciiString(cdkey, cdkey_A);
return gpRegisterUniqueNickA(connection, uniquenick_A, cdkey_A, blocking, callback, param);
}
#endif
GPResult gpRegisterCdKeyA(
GPConnection * connection,
const char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
if((cdkey == NULL) || (cdkey[0] == '\0'))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPRegisterCdKeyResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiRegisterCdKey(connection, cdkey, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpRegisterCdKeyW(
GPConnection * connection,
const gsi_char cdkey[GP_CDKEY_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char cdkey_A[GP_CDKEY_LEN];
UCS2ToAsciiString(cdkey, cdkey_A);
return gpRegisterCdKeyA(connection, cdkey_A, blocking, callback, param);
}
#endif
GPResult gpGetErrorCode(
GPConnection * connection,
GPErrorCode * errorCode
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Error check.
///////////////
if(errorCode == NULL)
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
*errorCode = (GPErrorCode)0;
return GP_NO_ERROR;
}
// Set the code.
////////////////
*errorCode = iconnection->errorCode;
return GP_NO_ERROR;
}
GPResult gpGetErrorStringA(
GPConnection * connection,
char errorString[GP_ERROR_STRING_LEN]
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Error check.
///////////////
if(errorString == NULL)
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
errorString[0] = '\0';
return GP_NO_ERROR;
}
// Copy the error string.
/////////////////////////
strzcpy(errorString, iconnection->errorString, GP_ERROR_STRING_LEN);
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
GPResult gpGetErrorStringW(
GPConnection * connection,
unsigned short errorString[GP_ERROR_STRING_LEN]
)
{
char errorString_A[GP_ERROR_STRING_LEN];
GPResult result;
result = gpGetErrorStringA(connection, errorString_A);
AsciiToUCS2String(errorString_A, errorString);
return result;
}
#endif
GPResult gpNewProfileA(
GPConnection * connection,
const char nick[GP_NICK_LEN],
GPEnum replace,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check for no nick.
// PANTS|05.18.00
/////////////////////
if((nick == NULL) || (nick[0] == '\0'))
Error(connection, GP_PARAMETER_ERROR, "Invalid nick.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPNewProfileResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiNewProfile(connection, nick, replace, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpNewProfileW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
GPEnum replace,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
// Since we don't currently allow UNICODE nicknames, make sure the first byte is empty
// (We make this check as an early alert to devlopers that the parameter is invalid)
// (Even if it's bypassed, the server will still reject the name.)
int i = 0;
for (; (i < GP_NICK_LEN) && (nick[i] != 0); i++)
{
if ((nick[i] & 0xFF00) != 0)
return GP_PARAMETER_ERROR;
}
// Convert to ascii and call "A" version
UCS2ToAsciiString(nick, nick_A);
return gpNewProfileA(connection, nick_A, replace, blocking, callback, param);
}
#endif
GPResult gpDeleteProfile(
GPConnection * connection,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
GPDeleteProfileResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiDeleteProfile(connection, callback, param);
}
GPResult gpProfileFromID(
GPConnection * connection,
GPProfile * profile,
int id
)
{
GSI_UNUSED(connection);
// Set the profile.
// This function is depreciated & may be removed from future versions.
//////////////////////////////////////////////////////////////////////
*profile = id;
return GP_NO_ERROR;
}
// gpIDFromProfile
//////////////////
GPResult gpIDFromProfile(
GPConnection * connection,
GPProfile profile,
int * id
)
{
GSI_UNUSED(connection);
// ID is the same as GPProfile
// This function is depreciated & may be removed from future versions.
//////////////////////////////////////////////////////////////////////
*id = profile;
return GP_NO_ERROR;
}
// gpUserIDFromProfile
//////////////////
GPResult gpUserIDFromProfile(
GPConnection * connection,
GPProfile profile,
int * userid
)
{
GPIConnection * iconnection;
GPIProfile * pProfile;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
*userid = 0;
return GP_NO_ERROR;
}
// Get the profile object.
//////////////////////////
if(!gpiGetProfile(connection, profile, &pProfile))
Error(connection, GP_PARAMETER_ERROR, "Invalid profile.");
// Set the id.
//////////////
*userid = pProfile->userId;
return GP_NO_ERROR;
}
GPResult gpProfileSearchA(
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,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPProfileSearchResponseArg arg;
memset(&arg, 0, sizeof(arg));
arg.more = GP_DONE;
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do the search.
/////////////////
return gpiProfileSearch(connection, nick, uniquenick, email, firstname, lastname, icquin, 0, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpProfileSearchW(
GPConnection * connection,
const unsigned short nick[GP_NICK_LEN],
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const unsigned short email[GP_EMAIL_LEN],
const unsigned short firstname[GP_FIRSTNAME_LEN],
const unsigned short lastname[GP_LASTNAME_LEN],
int icquin,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char nick_A[GP_NICK_LEN];
char uniquenick_A[GP_UNIQUENICK_LEN];
char email_A[GP_NICK_LEN];
char firstname_A[GP_NICK_LEN];
char lastname_A[GP_NICK_LEN];
UCS2ToAsciiString(nick, nick_A); // nicknames are ascii
UCS2ToAsciiString(uniquenick, uniquenick_A);
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(firstname, firstname_A);
UCS2ToAsciiString(lastname, lastname_A);
return gpProfileSearchA(connection, nick_A, uniquenick_A, email_A, firstname_A, lastname_A, icquin, blocking, callback, param);
}
#endif
GPResult gpProfileSearchUniquenickA(
GPConnection * connection,
const char uniquenick[GP_UNIQUENICK_LEN],
const int namespaceIDs[GP_MAX_NAMESPACEIDS],
int numNamespaces,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL) || (namespaceIDs == NULL) || (numNamespaces < 1))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPProfileSearchResponseArg arg;
memset(&arg, 0, sizeof(arg));
arg.more = GP_DONE;
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do the search.
/////////////////
return gpiProfileSearchUniquenick(connection, uniquenick, namespaceIDs, numNamespaces, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpProfileSearchUniquenickW(
GPConnection * connection,
const unsigned short uniquenick[GP_UNIQUENICK_LEN],
const int namespaceIDs[GP_MAX_NAMESPACEIDS],
int numNamespaces,
GPEnum blocking,
GPCallback callback,
void * param
)
{
char uniquenick_A[GP_UNIQUENICK_LEN];
UCS2ToAsciiString(uniquenick, uniquenick_A);
return gpProfileSearchUniquenickA(connection, uniquenick_A, namespaceIDs, numNamespaces, blocking, callback, param);
}
#endif
GPResult gpGetInfo(
GPConnection * connection,
GPProfile profile,
GPEnum checkCache,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL) || (profile == 0))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPGetInfoResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiGetInfo(connection, profile, checkCache, blocking, callback, param);
}
GPResult gpGetInfoNoWait(
GPConnection * connection,
GPProfile profile,
GPGetInfoResponseArg * arg
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL) || (profile == 0) || (arg == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
{
memset(arg, 0, sizeof(arg));
return GP_NO_ERROR;
}
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiGetInfoNoWait(connection, profile, arg);
}
GPResult gpSetInfoi(
GPConnection * connection,
GPEnum info,
int value
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiSetInfoi(connection, info, value);
}
GPResult gpSetInfosA(
GPConnection * connection,
GPEnum info,
const char * value
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiSetInfos(connection, info, value);
}
#ifdef GSI_UNICODE
GPResult gpSetInfosW(
GPConnection * connection,
GPEnum info,
const unsigned short* value
)
{
char* value_A = UCS2ToUTF8StringAlloc(value);
GPResult result = gpSetInfosA(connection, info, value_A);
gsifree(value_A);
return result;
}
#endif
GPResult gpSetInfod(
GPConnection * connection,
GPEnum info,
int day,
int month,
int year
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiSetInfod(connection, info, day, month, year);
}
GPResult gpSetInfoMask(
GPConnection * connection,
GPEnum mask
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiSetInfoMask(connection, mask);
}
GPResult gpSendBuddyRequestA(
GPConnection * connection,
GPProfile profile,
const char reason[GP_REASON_LEN]
)
{
GPIConnection * iconnection;
char reasonFixed[GP_REASON_LEN];
int i;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
if(reason == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid reason.");
// Replace backslashes in reason.
/////////////////////////////////
strzcpy(reasonFixed, reason, GP_REASON_LEN);
for(i = 0 ; reasonFixed[i] ; i++)
if(reasonFixed[i] == '\\')
reasonFixed[i] = '/';
// Send the request.
////////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\addbuddy\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\newprofileid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, profile);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\reason\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, reasonFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
GPResult gpSendBuddyRequestW(
GPConnection * connection,
GPProfile profile,
const unsigned short reason[GP_REASON_LEN]
)
{
char reason_A[GP_REASON_LEN];
UCS2ToUTF8String(reason, reason_A);
return gpSendBuddyRequestA(connection, profile, reason_A);
}
#endif
GPResult gpAuthBuddyRequest(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiAuthBuddyRequest(connection, profile);
}
GPResult gpDenyBuddyRequest(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
GPIProfile * pProfile;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for simulation mode.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Get the profile.
///////////////////
if(!gpiGetProfile(connection, profile, &pProfile))
return GP_NO_ERROR;
// freeclear the sig if no more requests.
////////////////////////////////////
pProfile->requestCount--;
if(!iconnection->infoCaching && (pProfile->requestCount <= 0))
{
freeclear(pProfile->authSig);
if(gpiCanFreeProfile(pProfile))
gpiRemoveProfile(connection, pProfile);
}
return GP_NO_ERROR;
}
GPResult gpGetNumBuddies(
GPConnection * connection,
int * numBuddies
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
*numBuddies = 0;
return GP_NO_ERROR;
}
// Set the number of buddies.
/////////////////////////////
*numBuddies = iconnection->profileList.numBuddies;
return GP_NO_ERROR;
}
#ifndef GP_NEW_STATUS_INFO
GPResult gpGetBuddyStatus(
GPConnection * connection,
int index,
GPBuddyStatus * status
)
{
GPIConnection * iconnection;
int num;
GPIProfile * profile;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
memset(status, 0, sizeof(GPBuddyStatus));
return GP_NO_ERROR;
}
// Check for a NULL status.
///////////////////////////
if(status == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid status.");
// Check the buddy index.
/////////////////////////
num = iconnection->profileList.numBuddies;
if((index < 0) || (index >= num))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
// Find the buddy with this index.
//////////////////////////////////
profile = gpiFindBuddy(connection, index);
if(!profile)
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
assert(profile->buddyStatus);
status->profile = (GPProfile)profile->profileId;
status->status = profile->buddyStatus->status;
#ifndef GSI_UNICODE
if(profile->buddyStatus->statusString)
strzcpy(status->statusString, profile->buddyStatus->statusString, GP_STATUS_STRING_LEN);
else
status->statusString[0] = '\0';
if(profile->buddyStatus->locationString)
strzcpy(status->locationString, profile->buddyStatus->locationString, GP_LOCATION_STRING_LEN);
else
status->locationString[0] = '\0';
#else
if(profile->buddyStatus->statusString)
UTF8ToUCS2String(profile->buddyStatus->statusString, status->statusString);
else
status->statusString[0] = '\0';
if(profile->buddyStatus->locationString)
UTF8ToUCS2String(profile->buddyStatus->locationString, status->locationString);
else
status->locationString[0] = '\0';
#endif
status->ip = profile->buddyStatus->ip;
status->port = profile->buddyStatus->port;
status->quietModeFlags = profile->buddyStatus->quietModeFlags;
return GP_NO_ERROR;
}
#endif
#ifdef GP_NEW_STATUS_INFO
GPResult gpGetBuddyStatusInfo(
GPConnection * connection,
int index,
GPBuddyStatusInfo * statusInfo
)
{
GPIConnection * iconnection;
int num;
GPIProfile * profile;
GPIBuddyStatus *buddyStatus;
GPIBuddyStatusInfo * buddyStatusInfo;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
memset(statusInfo, 0, sizeof(GPBuddyStatusInfo));
return GP_NO_ERROR;
}
// Check for a NULL status.
///////////////////////////
if(statusInfo == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid status.");
// Check the buddy index.
/////////////////////////
num = iconnection->profileList.numBuddies;
if((index < 0) || (index >= num))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
// Find the buddy with this index.
//////////////////////////////////
profile = gpiFindBuddy(connection, index);
if(!profile)
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
buddyStatus = profile->buddyStatus;
buddyStatusInfo = profile->buddyStatusInfo;
assert(buddyStatus || buddyStatusInfo);
statusInfo->profile = (GPProfile)profile->profileId;
if (buddyStatus)
{
statusInfo->statusState = buddyStatus->status;
#ifndef GSI_UNICODE
if(buddyStatus->statusString)
strzcpy(statusInfo->richStatus, buddyStatus->statusString, GP_RICH_STATUS_LEN);
else
statusInfo->richStatus[0] = '\0';
statusInfo->gameType[0] = '\0';
statusInfo->gameVariant[0] = '\0';
statusInfo->gameMapName[0] = '\0';
#else
if(buddyStatus->statusString)
UTF8ToUCS2String(buddyStatus->statusString, statusInfo->richStatus);
else
statusInfo->richStatus[0] = '\0';
statusInfo->gameType[0] = '\0';
statusInfo->gameVariant[0] = '\0';
statusInfo->gameMapName[0] = '\0';
#endif
statusInfo->buddyIp = buddyStatus->ip;
statusInfo->buddyPort = buddyStatus->port;
statusInfo->quietModeFlags = buddyStatus->quietModeFlags;
statusInfo->newStatusInfoFlag = GP_NEW_STATUS_INFO_NOT_SUPPORTED;
}
else if (buddyStatusInfo)
{
statusInfo->statusState = buddyStatusInfo->statusState;
statusInfo->buddyIp = buddyStatusInfo->buddyIp;
statusInfo->buddyPort = buddyStatusInfo->buddyPort;
statusInfo->hostIp = buddyStatusInfo->hostIp;
statusInfo->hostPrivateIp = buddyStatusInfo->hostPrivateIp;
statusInfo->queryPort = buddyStatusInfo->queryPort;
statusInfo->hostPort = buddyStatusInfo->hostPort;
statusInfo->sessionFlags = buddyStatusInfo->sessionFlags;
statusInfo->quietModeFlags = buddyStatusInfo->quietModeFlags;
statusInfo->newStatusInfoFlag = GP_NEW_STATUS_INFO_SUPPORTED;
#ifndef GSI_UNICODE
strzcpy(statusInfo->richStatus, buddyStatusInfo->richStatus, GP_RICH_STATUS_LEN);
strzcpy(statusInfo->gameType, buddyStatusInfo->gameType, GP_STATUS_BASIC_STR_LEN);
strzcpy(statusInfo->gameVariant, buddyStatusInfo->gameVariant, GP_STATUS_BASIC_STR_LEN);
strzcpy(statusInfo->gameMapName, buddyStatusInfo->gameMapName, GP_STATUS_BASIC_STR_LEN);
#else
UTF8ToUCS2String(buddyStatusInfo->richStatus, statusInfo->richStatus);
UTF8ToUCS2String(buddyStatusInfo->gameType, statusInfo->gameType);
UTF8ToUCS2String(buddyStatusInfo->gameVariant, statusInfo->gameVariant);
UTF8ToUCS2String(buddyStatusInfo->gameMapName, statusInfo->gameMapName);
#endif
}
return GP_NO_ERROR;
}
GPResult gpSetBuddyAddr(
GPConnection *connection,
int index,
unsigned int buddyIp,
unsigned short buddyPort
)
{
GPIConnection * iconnection;
int num;
GPIProfile * profile;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check the buddy index.
/////////////////////////
num = iconnection->profileList.numBuddies;
if((index < 0) || (index >= num))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
// Find the buddy with this index.
//////////////////////////////////
profile = gpiFindBuddy(connection, index);
if(!profile)
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
if (buddyIp == 0 || buddyPort == 0)
Error(connection, GP_PARAMETER_ERROR, "Invalid IP and port");
if (profile->buddyStatusInfo)
{
profile->buddyStatusInfo->buddyIp = buddyIp;
profile->buddyStatusInfo->buddyPort = buddyPort;
}
return GP_NO_ERROR;
}
#endif
GPResult gpGetBuddyIndex(
GPConnection * connection,
GPProfile profile,
int * index
)
{
GPIProfile * pProfile;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
*index = 0;
return GP_NO_ERROR;
}
// Get the index.
/////////////////
if(gpiGetProfile(connection, profile, &pProfile) && pProfile->buddyStatus)
*index = pProfile->buddyStatus->buddyIndex;
else if (gpiGetProfile(connection, profile, &pProfile) && pProfile->buddyStatusInfo)
*index = pProfile->buddyStatusInfo->buddyIndex;
else
*index = -1;
return GP_NO_ERROR;
}
int gpIsBuddy(
GPConnection * connection,
GPProfile profile
)
{
GPIProfile * pProfile;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return 0;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return 0;
// Get the index.
/////////////////
if(gpiGetProfile(connection, profile, &pProfile) && pProfile->buddyStatus)
return 1;
else if (gpiGetProfile(connection, profile, &pProfile) &&pProfile->buddyStatusInfo)
return 1;
return 0;
}
int gpIsBuddyConnectionOpen(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
GPIPeer *aPeer;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return 0;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return 0;
aPeer = gpiGetPeerByProfile(connection, profile);
if (aPeer == NULL || !gpiIsPeerConnected(aPeer))
return 0; // not connected
else
return 1; // connected
}
GPResult gpDeleteBuddy(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Delete the buddy.
////////////////////
CHECK_RESULT(gpiDeleteBuddy(connection, profile, GPITrue));
return GP_NO_ERROR;
}
GPResult gpAddToBlockedList(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Add em to the internal list - remove buddy status if already a buddy
///////////////////////////////////////////////////////////////////////
return gpiAddToBlockedList(connection, profile);
}
GPResult gpRemoveFromBlockedList(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Remove blocked association from internal list if it's there
//////////////////////////////////////////////////////////////
return gpiRemoveFromBlockedList(connection, profile);
}
GPResult gpGetNumBlocked(
GPConnection * connection,
int * numBlocked
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
*numBlocked = 0;
return GP_NO_ERROR;
}
// Set the number of blocked profiles
/////////////////////////////////////
*numBlocked = iconnection->profileList.numBlocked;
return GP_NO_ERROR;
}
GPResult gpGetBlockedProfile(
GPConnection * connection,
int index,
GPProfile * profile
)
{
GPIConnection * iconnection;
int num;
GPIProfile * pProfile;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for a NULL profile.
////////////////////////////
if(profile == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid profile container");
// Check the block index.
/////////////////////////
num = iconnection->profileList.numBlocked;
if((index < 0) || (index >= num))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
// Find the blocked profile with this index.
////////////////////////////////////////////
pProfile = gpiFindBlockedProfile(connection, index);
if(!pProfile)
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
*profile = (GPProfile)pProfile->profileId;
return GP_NO_ERROR;
}
gsi_bool gpIsBlocked(
GPConnection * connection,
GPProfile profile
)
{
GPIProfile * pProfile;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return gsi_false;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return gsi_false;
// Get the index.
/////////////////
if(gpiGetProfile(connection, profile, &pProfile) && pProfile->blocked)
return gsi_true;
return gsi_false;
}
#ifndef GP_NEW_STATUS_INFO
GPResult gpSetStatusA(
GPConnection * connection,
GPEnum status,
const char statusString[GP_STATUS_STRING_LEN],
const char locationString[GP_LOCATION_STRING_LEN]
)
{
char statusStringFixed[GP_STATUS_STRING_LEN];
char locationStringFixed[GP_LOCATION_STRING_LEN];
GPIConnection * iconnection;
int i;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
if(statusString == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid statusString.");
if(locationString == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid locationString.");
// Replace backslashes with slashes.
////////////////////////////////////
strzcpy(statusStringFixed, statusString, GP_STATUS_STRING_LEN);
for(i = 0 ; statusStringFixed[i] ; i++)
if(statusStringFixed[i] == '\\')
statusStringFixed[i] = '/';
strzcpy(locationStringFixed, locationString, GP_LOCATION_STRING_LEN);
for(i = 0 ; locationStringFixed[i] ; i++)
if(locationStringFixed[i] == '\\')
locationStringFixed[i] = '/';
// Don't send it if its the same as the previous.
/////////////////////////////////////////////////
if((status == iconnection->lastStatusState) &&
(strcmp(statusStringFixed, iconnection->lastStatusString) == 0) &&
(strcmp(locationStringFixed, iconnection->lastLocationString) == 0))
{
return GP_NO_ERROR;
}
// Copy off the new status.
///////////////////////////
iconnection->lastStatusState = status;
#ifndef GSI_UNICODE
strzcpy(iconnection->lastStatusString, statusStringFixed, GP_STATUS_STRING_LEN);
strzcpy(iconnection->lastLocationString, locationStringFixed, GP_LOCATION_STRING_LEN);
#else
UTF8ToUCS2StringLen(iconnection->lastStatusString, iconnection->lastStatusString_W, GP_STATUS_STRING_LEN);
UTF8ToUCS2StringLen(iconnection->lastStatusString, iconnection->lastLocationString_W, GP_LOCATION_STRING_LEN);
#endif
// Send the new status.
///////////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\status\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, status);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\statstring\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, statusStringFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\locstring\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, locationStringFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
GPResult gpSetStatusW(
GPConnection * connection,
GPEnum status,
const unsigned short statusString[GP_STATUS_STRING_LEN],
const unsigned short locationString[GP_LOCATION_STRING_LEN]
)
{
char statusString_A[GP_STATUS_STRING_LEN];
char locationString_A[GP_LOCATION_STRING_LEN];
UCS2ToUTF8String(statusString, statusString_A);
UCS2ToUTF8String(locationString, locationString_A);
return gpSetStatusA(connection, status, statusString_A, locationString_A);
}
#endif
#endif
#ifdef GP_NEW_STATUS_INFO
GPResult gpSetStatusInfoA(
GPConnection *connection,
GPEnum statusState,
unsigned int hostIp,
unsigned int hostPrivateIp,
unsigned short queryPort,
unsigned short hostPort,
unsigned int sessionFlags,
const char *richStatus,
int richStatusLen,
const char *gameType,
int gameTypeLen,
const char *gameVariant,
int gameVariantLen,
const char *gameMapName,
int gameMapNameLen
)
{
GPIConnection * iconnection;
#ifndef GSI_UNICODE
char gameTypeFixed[GP_STATUS_BASIC_STR_LEN];
char gameVariantFixed[GP_STATUS_BASIC_STR_LEN];
char gameMapNameFixed[GP_STATUS_BASIC_STR_LEN];
#else
char *gameTypeFixed;
char *gameVariantFixed;
char *gameMapNameFixed;
#endif
GS_ASSERT(connection != NULL);
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
GS_ASSERT(richStatus != NULL);
if (richStatus == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid richStatus.");
#ifndef GSI_UNICODE
GS_ASSERT(richStatusLen <= GP_RICH_STATUS_LEN);
GS_ASSERT(gameTypeLen <= GP_STATUS_BASIC_STR_LEN);
GS_ASSERT(gameVariantLen <= GP_STATUS_BASIC_STR_LEN);
GS_ASSERT(gameMapNameLen <= GP_STATUS_BASIC_STR_LEN);
if (gameType == NULL)
strncpy(gameTypeFixed, "", GP_STATUS_BASIC_STR_LEN);
else
strncpy(gameTypeFixed, gameType, GP_STATUS_BASIC_STR_LEN);
if (gameVariant == NULL)
strncpy(gameVariantFixed, "", GP_STATUS_BASIC_STR_LEN);
else
strncpy(gameVariantFixed, gameVariant, GP_STATUS_BASIC_STR_LEN);
if (gameMapName == NULL)
strncpy(gameMapNameFixed, "", GP_STATUS_BASIC_STR_LEN);
else
strncpy(gameMapNameFixed, gameMapName, GP_STATUS_BASIC_STR_LEN);
// Don't send it if its the same as the previous.
/////////////////////////////////////////////////
if((statusState == iconnection->lastStatusState) &&
(strcmp(richStatus, iconnection->richStatus) == 0) &&
(strcmp(gameTypeFixed, iconnection->gameType) == 0) &&
(strcmp(gameVariantFixed, iconnection->gameVariant) == 0) &&
(strcmp(gameMapNameFixed, iconnection->gameMapName) == 0) &&
(sessionFlags == iconnection->sessionFlags) &&
(hostIp == iconnection->hostIp) &&
(hostPrivateIp == iconnection->hostPrivateIp) &&
(queryPort == iconnection->queryPort) &&
(hostPort == iconnection->hostPort))
{
return GP_NO_ERROR;
}
#else
gameTypeFixed = goastrdup(gameType);
gameVariantFixed = goastrdup(gameVariant);
gameMapNameFixed = goastrdup(gameMapName);
#endif
iconnection->lastStatusState = statusState;
iconnection->hostIp = hostIp;
iconnection->hostPrivateIp = hostPrivateIp;
iconnection->queryPort = queryPort;
iconnection->hostPort = hostPort;
iconnection->sessionFlags = sessionFlags;
#ifndef GSI_UNICODE
strzcpy(iconnection->gameType, gameTypeFixed, GP_STATUS_BASIC_STR_LEN);
strzcpy(iconnection->gameVariant, gameVariantFixed, GP_STATUS_BASIC_STR_LEN);
strzcpy(iconnection->gameMapName, gameMapNameFixed, GP_STATUS_BASIC_STR_LEN);
strzcpy(iconnection->richStatus, richStatus, GP_RICH_STATUS_LEN);
#endif
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\statusinfo\\\\state\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, statusState);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\hostIp\\");
gpiAppendUIntToBuffer(connection, &iconnection->outputBuffer, ntohl(hostIp));
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\hprivIp\\");
gpiAppendUIntToBuffer(connection, &iconnection->outputBuffer, ntohl(hostPrivateIp));
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\qport\\");
gpiAppendUShortToBuffer(connection, &iconnection->outputBuffer, queryPort);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\hport\\");
gpiAppendUShortToBuffer(connection, &iconnection->outputBuffer, hostPort);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sessflags\\");
gpiAppendUIntToBuffer(connection, &iconnection->outputBuffer, sessionFlags);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\richStatus\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, richStatus);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\gameType\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, gameTypeFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\gameVariant\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, gameVariantFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\gameMapName\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, gameMapNameFixed);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
GSI_UNUSED(richStatusLen);
GSI_UNUSED(gameTypeLen);
GSI_UNUSED(gameVariantLen);
GSI_UNUSED(gameMapNameLen);
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
GPResult gpSetStatusInfoW(
GPConnection *connection,
GPEnum statusState,
unsigned int hostIp,
unsigned int hostPrivateIp,
unsigned short queryPort,
unsigned short hostPort,
unsigned int sessionFlags,
const unsigned short *richStatus,
int richStatusLen,
const unsigned short *gameType,
int gameTypeLen,
const unsigned short *gameVariant,
int gameVariantLen,
const unsigned short *gameMapName,
int gameMapNameLen
)
{
char *richStatus_A, *gameType_A, *gameVariant_A, *gameMapName_A;
GPResult aResult;
GPIConnection * iconnection;
GS_ASSERT(connection != NULL);
GS_ASSERT(richStatusLen <= GP_RICH_STATUS_LEN);
GS_ASSERT(gameTypeLen <= GP_STATUS_BASIC_STR_LEN);
GS_ASSERT(gameVariantLen <= GP_STATUS_BASIC_STR_LEN);
GS_ASSERT(gameMapNameLen <= GP_STATUS_BASIC_STR_LEN);
GS_ASSERT(richStatus != NULL);
if (connection != NULL && (*connection != NULL))
iconnection = (GPIConnection *)*connection;
else return GP_PARAMETER_ERROR;
if (richStatus == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid richStatus.");
if (richStatusLen <= GP_RICH_STATUS_LEN)
richStatus_A = UCS2ToUTF8StringAlloc(richStatus);
else
richStatus_A = UCS2ToUTF8StringAlloc((UCS2String)_T(""));
if (gameType && (gameTypeLen <= GP_STATUS_BASIC_STR_LEN))
gameType_A = UCS2ToUTF8StringAlloc(gameType);
else
gameType_A = UCS2ToUTF8StringAlloc((UCS2String)_T(""));
if (gameVariant && (gameVariantLen <= GP_STATUS_BASIC_STR_LEN))
gameVariant_A = UCS2ToUTF8StringAlloc(gameVariant);
else
gameVariant_A = UCS2ToUTF8StringAlloc((UCS2String)_T(""));
if (gameMapName && (gameMapNameLen <= GP_STATUS_BASIC_STR_LEN))
gameMapName_A = UCS2ToUTF8StringAlloc(gameMapName);
else
gameMapName_A = UCS2ToUTF8StringAlloc((UCS2String)_T(""));
if ((statusState == iconnection->lastStatusState) &&
(sessionFlags == iconnection->sessionFlags) &&
(hostIp == iconnection->hostIp) &&
(hostPrivateIp == iconnection->hostPrivateIp) &&
(queryPort == iconnection->queryPort) &&
(hostPort == iconnection->hostPort) &&
(_tcscmp(richStatus, iconnection->richStatus_W) == 0) &&
(_tcscmp(gameType, iconnection->gameType_W) == 0) &&
(_tcscmp(gameVariant, iconnection->gameVariant_W) == 0) &&
(_tcscmp(gameMapName, iconnection->gameMapName_W) == 0))
{
return GP_NO_ERROR;
}
_tcsncpy(iconnection->richStatus_W, richStatus, GP_RICH_STATUS_LEN);
_tcsncpy(iconnection->gameType_W, gameType, GP_STATUS_BASIC_STR_LEN);
_tcsncpy(iconnection->gameVariant_W, gameVariant, GP_STATUS_BASIC_STR_LEN);
_tcsncpy(iconnection->gameMapName_W, gameMapName, GP_STATUS_BASIC_STR_LEN);
aResult = gpSetStatusInfoA(connection, statusState, hostIp, hostPrivateIp, queryPort, hostPort,
sessionFlags, richStatus_A, (int)strlen(richStatus_A), gameType_A, (int)strlen(gameType_A),
gameVariant_A, (int)strlen(gameVariant_A), gameMapName_A, (int)strlen(gameMapName_A));
gsifree(richStatus_A);
gsifree(gameType_A);
gsifree(gameVariant_A);
gsifree(gameMapName_A);
return aResult;
}
#endif
GPResult gpAddStatusInfoKeyA(GPConnection *connection, const char *keyName, const char *keyValue)
{
GPIConnection * iconnection;
// Error check.
///////////////
if ((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if ( iconnection->simulation )
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if (iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiStatusInfoAddKey(connection, iconnection->extendedInfoKeys, keyName, keyValue);
}
#ifdef GSI_UNICODE
GPResult gpAddStatusInfoKeyW(GPConnection *connection, const unsigned short *keyName, const unsigned short *keyValue)
{
GPResult aResult;
char *keyName_A = UCS2ToUTF8StringAlloc(keyName);
char *keyValue_A = UCS2ToUTF8StringAlloc(keyValue);
aResult = gpAddStatusInfoKeyA(connection, keyName_A, keyValue_A);
gsifree(keyName_A);
gsifree(keyValue_A);
return aResult;
}
#endif
GPResult gpSetStatusInfoKeyA(GPConnection *connection, const char *keyName, const char *keyValue)
{
GPIConnection * iconnection;
// Error check.
///////////////
if ((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if ( iconnection->simulation )
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if (iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiStatusInfoSetKey(connection, iconnection->extendedInfoKeys, keyName, keyValue);
}
#ifdef GSI_UNICODE
GPResult gpSetStatusInfoKeyW(GPConnection *connection, const unsigned short *keyName, const unsigned short *keyValue)
{
GPResult aResult;
char *keyName_A = UCS2ToUTF8StringAlloc(keyName);
char *keyValue_A = UCS2ToUTF8StringAlloc(keyValue);
aResult = gpSetStatusInfoKeyA(connection, keyName_A, keyValue_A);
gsifree(keyName_A);
gsifree(keyValue_A);
return aResult;
}
#endif
GPResult gpDelStatusInfoKeyA(GPConnection *connection, const char *keyName)
{
GPIConnection * iconnection;
// Error check.
///////////////
if ((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if ( iconnection->simulation )
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if (iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiStatusInfoDelKey(connection, iconnection->extendedInfoKeys, keyName);
}
#ifdef GSI_UNICODE
GPResult gpDelStatusInfoKeyW(GPConnection *connection, const unsigned short *keyName)
{
GPResult aResult;
char *keyName_A = UCS2ToUTF8StringAlloc(keyName);
aResult = gpDelStatusInfoKeyA(connection, keyName_A);
gsifree(keyName_A);
return aResult;
}
#endif
GPResult gpGetStatusInfoKeyValA(GPConnection *connection, const char *keyName, char **keyValue)
{
GPIConnection * iconnection;
// Error check.
///////////////
if ((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if ( iconnection->simulation )
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if (iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
return gpiStatusInfoGetKey(connection, iconnection->extendedInfoKeys, keyName, keyValue);
}
#ifdef GSI_UNICODE
GPResult gpGetStatusInfoKeyValW(GPConnection *connection, const unsigned short *keyName, unsigned short **keyValue)
{
GPResult aResult;
char *keyValue_A;
char *keyName_A = UCS2ToUTF8StringAlloc(keyName);
aResult = gpGetStatusInfoKeyValA(connection, keyName_A, &keyValue_A);
*keyValue = UTF8ToUCS2StringAlloc(keyValue_A);
gsifree(keyName_A);
gsifree(keyValue_A);
return aResult;
}
#endif
GPResult gpGetBuddyStatusInfoKeys(GPConnection *connection, int index, GPCallback callback, void *userData)
{
GPIConnection *iconnection;
GPIProfile * pProfile;
GPResult aResult;
GPIPeerOp *aPeerOp;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
pProfile = gpiFindBuddy(connection, index);
if (!pProfile)
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
if (pProfile->buddyStatus)
CallbackError(connection, GP_PARAMETER_ERROR, GP_BM_EXT_INFO_NOT_SUPPORTED, "The profile does not support extended info keys.")
if (!pProfile->buddyStatusInfo && !pProfile->buddyStatus)
CallbackError(connection, GP_PARAMETER_ERROR, GP_BM_NOT_BUDDY, "The profile used to get extended info keys is not a buddy.")
if (pProfile->buddyStatusInfo && pProfile->buddyStatusInfo->statusState == GP_OFFLINE)
CallbackError(connection, GP_NETWORK_ERROR, GP_BM_BUDDY_OFFLINE, "The profile used to get extended info keys is offline.");
aPeerOp = (GPIPeerOp *)gsimalloc(sizeof(GPIPeerOp));
aPeerOp->callback = callback;
aPeerOp->next = NULL;
aPeerOp->state = GPI_PEER_OP_STATE_REQUESTED;
aPeerOp->type = GPI_BM_KEYS_REQUEST;
aPeerOp->userData = userData;
aPeerOp->timeout = current_time() + GPI_PEER_OP_TIMEOUT;
aResult = gpiSendBuddyMessage(connection, pProfile->profileId, GPI_BM_KEYS_REQUEST, "Keys?", GP_DONT_ROUTE, aPeerOp);
return aResult;
}
#endif
GPResult gpSendBuddyMessageA(
GPConnection * connection,
GPProfile profile,
const char * message
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
if(message == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid message.");
return gpiSendBuddyMessage(connection, profile, GPI_BM_MESSAGE, message, 0, NULL);
}
#ifdef GSI_UNICODE
GPResult gpSendBuddyMessageW(
GPConnection * connection,
GPProfile profile,
const unsigned short* message
)
{
char* message_A;
GPResult result;
assert(message != NULL);
message_A = UCS2ToUTF8StringAlloc(message); // convert to UTF8
result = gpSendBuddyMessageA(connection, profile, message_A); // send
gsifree(message_A); // free the converted string
return result;
}
#endif
GPResult gpSendBuddyUTMA(
GPConnection * connection,
GPProfile profile,
const char * message,
int sendOption
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
if(message == NULL)
Error(connection, GP_PARAMETER_ERROR, "Invalid message.");
return gpiSendBuddyMessage(connection, profile, GPI_BM_UTM, message, sendOption, NULL);
}
#ifdef GSI_UNICODE
GPResult gpSendBuddyUTMW(
GPConnection * connection,
GPProfile profile,
const unsigned short* message,
int sendOption
)
{
char* message_A;
GPResult result;
assert(message != NULL);
message_A = UCS2ToUTF8StringAlloc(message); // convert to UTF8
result = gpSendBuddyUTMA(connection, profile, message_A, sendOption); // send
gsifree(message_A); // free the converted string
return result;
}
#endif
GPResult gpIsValidEmailA(
GPConnection * connection,
const char email[GP_EMAIL_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the email.
/////////////////////////////////
if(strlen(email) >= GP_EMAIL_LEN)
Error(connection, GP_PARAMETER_ERROR, "Email too long.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPIsValidEmailResponseArg arg;
memset(&arg, 0, sizeof(arg));
#ifndef GSI_UNICODE
strzcpy(arg.email, email, GP_EMAIL_LEN);
#else
UTF8ToUCS2String(email, arg.email);
#endif
arg.isValid = GP_INVALID;
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do the validation.
/////////////////////
return gpiIsValidEmail(connection, email, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpIsValidEmailW(
GPConnection * connection,
const unsigned short email[GP_EMAIL_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char email_A[GP_EMAIL_LEN];
UCS2ToAsciiString(email, email_A);
return gpIsValidEmailA(connection, email_A, blocking,callback, param);
}
#endif
GPResult gpGetUserNicksA(
GPConnection * connection,
const char email[GP_EMAIL_LEN],
const char password[GP_PASSWORD_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Check the length of the email.
/////////////////////////////////
if(strlen(email) >= GP_EMAIL_LEN)
Error(connection, GP_PARAMETER_ERROR, "Email too long.");
// Check the length of the password.
////////////////////////////////////
if(strlen(password) >= GP_PASSWORD_LEN)
Error(connection, GP_PARAMETER_ERROR, "Password too long.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPGetUserNicksResponseArg arg;
memset(&arg, 0, sizeof(arg));
#ifndef GSI_UNICODE
strzcpy(arg.email, email, GP_EMAIL_LEN);
#else
AsciiToUCS2String(email, arg.email);
#endif
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Do the validation.
/////////////////////
return gpiGetUserNicks(connection, email, password, blocking, callback, param);
}
#ifdef GSI_UNICODE
GPResult gpGetUserNicksW(
GPConnection * connection,
const unsigned short email[GP_EMAIL_LEN],
const unsigned short password[GP_PASSWORD_LEN],
GPEnum blocking,
GPCallback callback,
void * param
)
{
char email_A[GP_EMAIL_LEN];
char password_A[GP_PASSWORD_LEN];
UCS2ToAsciiString(email, email_A);
UCS2ToAsciiString(password, password_A);
return gpGetUserNicksA(connection, email_A, password_A, blocking, callback, param);
}
#endif
GPResult gpSetInvitableGames(
GPConnection * connection,
int numProductIDs,
const int * productIDs
)
{
GPIConnection * iconnection;
int i;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Error check.
///////////////
if(numProductIDs < 0)
Error(connection, GP_PARAMETER_ERROR, "Invalid numProductIDs.");
if((numProductIDs > 0) && (productIDs == NULL))
Error(connection, GP_PARAMETER_ERROR, "Invalid productIDs.");
// Send the list.
/////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\inviteto\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\products\\");
for(i = 0 ; i < numProductIDs ; i++)
{
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, productIDs[i]);
if(i < (numProductIDs - 1))
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, ",");
}
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
GPResult gpFindPlayers(
GPConnection * connection,
int productID,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPFindPlayersResponseArg arg;
memset(&arg, 0, sizeof(arg));
arg.productID = productID;
arg.numMatches = 0;
arg.matches = NULL;
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Start the find.
//////////////////
return gpiFindPlayers(connection, productID, blocking, callback, param);
}
GPResult gpInvitePlayerA(
GPConnection * connection,
GPProfile profile,
int productID,
const char location[GP_LOCATION_STRING_LEN]
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Send the invite.
///////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\pinvite\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\profileid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, profile);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\productid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, productID);
if (location && location[0])
{
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\location\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, location);
}
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
GPResult gpInvitePlayerW(
GPConnection * connection,
GPProfile profile,
int productID,
const gsi_char location[GP_LOCATION_STRING_LEN]
)
{
char location_A[GP_LOCATION_STRING_LEN];
UCS2ToAsciiString(location, location_A);
return gpInvitePlayerA(connection, profile, productID, location_A);
}
#endif
GPResult gpGetReverseBuddies(
GPConnection * connection,
GPEnum blocking,
GPCallback callback,
void * param
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPGetReverseBuddiesResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Start the search.
////////////////////
return gpiOthersBuddy(connection, blocking, callback, param);
}
GPResult gpGetReversBuddiesList( GPConnection * connection,
GPProfile *targets, int numOfTargets,
GPEnum blocking,
GPCallback callback,
void * param)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for no callback.
/////////////////////////
if(callback == NULL)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
{
GPGetReverseBuddiesListResponseArg arg;
memset(&arg, 0, sizeof(arg));
callback(connection, &arg, param);
return GP_NO_ERROR;
}
// Start the search.
////////////////////
return gpiOthersBuddyList(connection, targets, numOfTargets, blocking, callback, param);
}
GPResult gpRevokeBuddyAuthorization(
GPConnection * connection,
GPProfile profile
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
return GP_NO_ERROR;
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Send the invite.
///////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\revoke\\");
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\profileid\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, profile);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
return GP_NO_ERROR;
}
GPResult gpGetLoginTicket(
GPConnection * connection,
char loginTicket[GP_LOGIN_TICKET_LEN]
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
memcpy(loginTicket, iconnection->loginTicket, GP_LOGIN_TICKET_LEN);
return GP_NO_ERROR;
}
GPResult gpSetQuietMode(
GPConnection * connection,
GPEnum flags
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Store the flags locally.
///////////////////////////
iconnection->quietModeFlags = flags;
// Check for a connection.
//////////////////////////
if(iconnection->connectState == GPI_CONNECTED)
{
// Send the flags.
//////////////////
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\quiet\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->quietModeFlags);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\");
gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey);
gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\");
}
return GP_NO_ERROR;
}
#ifndef NOFILE
void gpSetInfoCacheFilenameA(
const char * filename
)
{
gpiSetInfoCacheFilename(filename);
}
void gpSetInfoCacheFilenameW(
const unsigned short * filename
)
{
char* filename_A = UCS2ToUTF8StringAlloc(filename);
gpiSetInfoCacheFilename(filename_A);
gsifree(filename_A);
}
static GPResult gpiAddSendingFileA(
GPConnection * connection,
GPITransfer * transfer,
const char * path,
const char * name
)
{
GPIFile * file = NULL;
int size = 0;
gsi_time modTime = 0;
// Check for a bad path or name.
////////////////////////////////
if(!path && !name)
Error(connection, GP_PARAMETER_ERROR, "File missing path and name.");
if(path && !path[0])
Error(connection, GP_PARAMETER_ERROR, "Empty path.");
if(name && !name[0])
Error(connection, GP_PARAMETER_ERROR, "Empty name.");
// Check that the file exists and is readable.
//////////////////////////////////////////////
if(path)
{
FILE * fileVerify;
fileVerify = fopen(path, "r");
if(!fileVerify)
Error(connection, GP_PARAMETER_ERROR, "Can't find file.");
if(!gpiGetTransferFileInfo(fileVerify, &size, &modTime))
{
fclose(fileVerify);
Error(connection, GP_PARAMETER_ERROR, "Can't get info on file.");
}
fclose(fileVerify);
}
// Validate the name.
/////////////////////
if(name)
{
size_t len;
len = strlen(name);
if(strstr(name, "//") || strstr(name, "\\\\"))
Error(connection, GP_PARAMETER_ERROR, "Empty directory in filename.");
if(strstr(name, "./") || strstr(name, ".\\") || (name[len - 1] == '.'))
Error(connection, GP_PARAMETER_ERROR, "Directory level in filename.");
if((name[0] == '/') || (name[0] == '\\'))
Error(connection, GP_PARAMETER_ERROR, "Filename can't start with a slash.");
if(strcspn(name, ":*?\"<>|\n") != len)
Error(connection, GP_PARAMETER_ERROR, "Invalid character in filename.");
}
// The name is the path's title.
////////////////////////////////
else
{
const char * str;
// Find the end of the path.
////////////////////////////
name = strrchr(path, '/');
str = strrchr(path, '\\');
if(str > name)
name = str;
// Point the name at the title.
///////////////////////////////
if(name)
name++;
else
name = path;
}
// Add this to the list.
////////////////////////
file = gpiAddFileToTransfer(transfer, path, name);
if(!file)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
// Set the size and time.
/////////////////////////
file->size = size;
file->modTime = modTime;
// Update the total size.
/////////////////////////
transfer->totalSize += size;
return GP_NO_ERROR;
}
#ifdef GSI_UNICODE
static GPResult gpiAddSendingFileW(
GPConnection * connection,
GPITransfer * transfer,
const unsigned short * path,
const unsigned short * name
)
{
char* path_A = UCS2ToUTF8StringAlloc(path);
char* name_A = UCS2ToUTF8StringAlloc(name);
GPResult result = gpiAddSendingFileA(connection, transfer, path_A, name_A);
gsifree(path_A);
gsifree(name_A);
return result;
}
#endif
GPResult gpSendFilesA(
GPConnection * connection,
GPTransfer * transfer,
GPProfile profile,
const char * message,
gpSendFilesCallback callback,
void * param
)
{
GPIConnection * iconnection;
GPITransfer * pTransfer;
GPResult result;
const gsi_char * path;
const gsi_char * name;
int numFiles;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Check for simulation mode.
/////////////////////////////
if(iconnection->simulation)
Error(connection, GP_PARAMETER_ERROR, "Cannot send files in simulation mode.");
// Check for disconnected.
//////////////////////////
if(iconnection->connectState == GPI_DISCONNECTED)
Error(connection, GP_PARAMETER_ERROR, "The connection has already been disconnected.");
// Check other stuff.
/////////////////////
if(!callback)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
if(!iconnection->callbacks[GPI_TRANSFER_CALLBACK].callback)
Error(connection, GP_PARAMETER_ERROR, "No callback.");
// No message is an empty message.
//////////////////////////////////
if(!message)
message = "";
// Create the transfer object.
//////////////////////////////
CHECK_RESULT(gpiNewSenderTransfer(connection, &pTransfer, profile));
// Fill in the message.
///////////////////////
pTransfer->message = goastrdup(message);
if(!pTransfer->message)
{
gpiFreeTransfer(connection, pTransfer);
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
}
// Add all the files.
/////////////////////
numFiles = 0;
do
{
path = NULL;
name = NULL;
callback(connection, numFiles++, &path, &name, param);
if(path && !path[0])
path = NULL;
if(name && !name[0])
name = NULL;
if(name || path)
{
#ifndef GSI_UNICODE
result = gpiAddSendingFileA(connection, pTransfer, path, name);
#else
result = gpiAddSendingFileW(connection, pTransfer, path, name);
#endif
if(result != GP_NO_ERROR)
{
gpiFreeTransfer(connection, pTransfer);
return result;
}
}
}
while(name || path);
// Check that we got at least 1 file.
/////////////////////////////////////
if(!ArrayLength(pTransfer->files))
{
gpiFreeTransfer(connection, pTransfer);
Error(connection, GP_PARAMETER_ERROR, "No files to send.");
}
// Ping the receiver.
/////////////////////
result = gpiSendBuddyMessage(connection, profile, GPI_BM_PING, "1", 0, NULL);
if(result != GP_NO_ERROR)
{
gpiFreeTransfer(connection, pTransfer);
return result;
}
// Successful so far.
/////////////////////
if(transfer)
*transfer = pTransfer->localID;
return GP_NO_ERROR;
}
GPResult gpSendFilesW(
GPConnection * connection,
GPTransfer * transfer,
GPProfile profile,
const unsigned short* message,
gpSendFilesCallback callback,
void * param
)
{
char* message_A = NULL;
GPResult result;
if (message == NULL)
return gpSendFilesA(connection, transfer, profile, NULL, callback, param);
message_A = UCS2ToUTF8StringAlloc(message);
result = gpSendFilesA(connection, transfer, profile, message_A, callback, param);
gsifree(message_A);
return result;
}
GPResult gpAcceptTransferA(
GPConnection * connection,
GPTransfer transfer,
const char * message
)
{
GPITransfer * pTransfer;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Check that we have a directory set.
//////////////////////////////////////
if(!pTransfer->baseDirectory)
Error(connection, GP_PARAMETER_ERROR, "No transfer directory set.");
// Check if this transfer has been cancelled.
/////////////////////////////////////////////
if(pTransfer->state & GPITransferCancelled)
Error(connection, GP_PARAMETER_ERROR, "Transfer already cancelled.");
// Send a reply.
////////////////
CHECK_RESULT(gpiSendTransferReply(connection, &pTransfer->transferID, pTransfer->peer, GPI_ACCEPTED, message));
// We're now transferring.
//////////////////////////
pTransfer->state = GPITransferTransferring;
// Set the current file index to the first file.
////////////////////////////////////////////////
pTransfer->currentFile = 0;
return GP_NO_ERROR;
}
GPResult gpAcceptTransferW(
GPConnection * connection,
GPTransfer transfer,
const unsigned short * message
)
{
char* message_A = NULL;
GPResult result;
if (message == NULL)
return gpAcceptTransferA(connection, transfer, NULL);
message_A = UCS2ToUTF8StringAlloc(message);
result = gpAcceptTransferA(connection, transfer, message_A);
gsifree(message_A);
return result;
}
GPResult gpRejectTransferA(
GPConnection * connection,
GPTransfer transfer,
const char * message
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
return GP_NO_ERROR;
// Check if this transfer has been cancelled.
/////////////////////////////////////////////
if(pTransfer->state & GPITransferCancelled)
return GP_NO_ERROR;
// Send the reply.
//////////////////
gpiSendTransferReply(connection, &pTransfer->transferID, pTransfer->peer, GPI_REJECTED, message);
// Free the transfer.
/////////////////////
gpiFreeTransfer(connection, pTransfer);
return GP_NO_ERROR;
}
GPResult gpRejectTransferW(
GPConnection * connection,
GPTransfer transfer,
const unsigned short* message
)
{
char* message_A = NULL;
GPResult result;
if (message == NULL)
return gpRejectTransferA(connection, transfer, NULL);
message_A = UCS2ToUTF8StringAlloc(message);
result = gpRejectTransferA(connection, transfer, message_A);
gsifree(message_A);
return result;
}
GPResult gpFreeTransfer(
GPConnection * connection,
GPTransfer transfer
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
return GP_NO_ERROR;
// Check if this should be a reject.
////////////////////////////////////
if(!pTransfer->sender && (pTransfer->state == GPITransferWaiting))
return gpRejectTransfer(connection, transfer, NULL);
// Check for cancelling.
////////////////////////
if(pTransfer->state < GPITransferComplete)
gpiCancelTransfer(connection, pTransfer);
// Free the transfer.
/////////////////////
gpiFreeTransfer(connection, pTransfer);
return GP_NO_ERROR;
}
GPResult gpSetTransferData(
GPConnection * connection,
GPTransfer transfer,
void * userData
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Set the data.
////////////////
pTransfer->userData = userData;
return GP_NO_ERROR;
}
void * gpGetTransferData(
GPConnection * connection,
GPTransfer transfer
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
return NULL;
// Return the data.
///////////////////
return pTransfer->userData;
}
GPResult gpSetTransferDirectoryA(
GPConnection * connection,
GPTransfer transfer,
const char * directory
)
{
GPITransfer * pTransfer;
char lastChar;
if(!directory || !directory[0])
Error(connection, GP_PARAMETER_ERROR, "Invalid directory.");
lastChar = directory[strlen(directory) - 1];
if((lastChar != '\\') && (lastChar != '/'))
Error(connection, GP_PARAMETER_ERROR, "Invalid directory.");
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// This has to be set before transferring.
//////////////////////////////////////////
if(pTransfer->sender)
Error(connection, GP_PARAMETER_ERROR, "Sender has no transfer directory.");
if(pTransfer->state != GPITransferWaiting)
Error(connection, GP_PARAMETER_ERROR, "Can only set transfer directory before transferring.");
// Free any existing directory.
///////////////////////////////
if(pTransfer->baseDirectory)
gsifree(pTransfer->baseDirectory);
pTransfer->baseDirectory = NULL;
// Set the directory.
/////////////////////
pTransfer->baseDirectory = goastrdup(directory);
if(!pTransfer->baseDirectory)
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
return GP_NO_ERROR;
}
GPResult gpSetTransferDirectoryW(
GPConnection * connection,
GPTransfer transfer,
const unsigned short * directory
)
{
char* directory_A = UCS2ToUTF8StringAlloc(directory);
GPResult result = gpSetTransferDirectoryA(connection, transfer, directory_A);
gsifree(directory_A);
return result;
}
GPResult gpSetTransferThrottle(
GPConnection * connection,
GPTransfer transfer,
int throttle
)
{
GPITransfer * pTransfer;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
// Negative means no throttle.
//////////////////////////////
if(throttle < 0)
throttle = -1;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Store the throttle setting.
//////////////////////////////
pTransfer->throttle = throttle;
// Send the rate.
/////////////////
CHECK_RESULT(gpiPeerStartTransferMessage(connection, pTransfer->peer, GPI_BM_FILE_TRANSFER_THROTTLE, (GPITransferID_st)&pTransfer->transferID));
gpiSendOrBufferString(connection, pTransfer->peer, "\\rate\\");
gpiSendOrBufferInt(connection, pTransfer->peer, throttle);
gpiPeerFinishTransferMessage(connection, pTransfer->peer, NULL, 0);
// If we're the sender, call the callback.
//////////////////////////////////////////
if(pTransfer->sender)
{
GPTransferCallbackArg * arg;
// Call the callback.
/////////////////////
arg = (GPTransferCallbackArg *)gsimalloc(sizeof(GPTransferCallbackArg));
if(arg)
{
memset(arg, 0, sizeof(GPTransferCallbackArg));
arg->transfer = pTransfer->localID;
arg->type = GP_TRANSFER_THROTTLE;
arg->num = throttle;
gpiAddCallback(connection, iconnection->callbacks[GPI_TRANSFER_CALLBACK], arg, NULL, GPI_ADD_TRANSFER_CALLBACK);
}
}
return GP_NO_ERROR;
}
GPResult gpGetTransferThrottle(
GPConnection * connection,
GPTransfer transfer,
int * throttle
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the throttle.
////////////////////
*throttle = pTransfer->throttle;
return GP_NO_ERROR;
}
GPResult gpGetTransferProfile(
GPConnection * connection,
GPTransfer transfer,
GPProfile * profile
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the profile.
///////////////////
*profile = pTransfer->profile;
return GP_NO_ERROR;
}
GPResult gpGetTransferSide(
GPConnection * connection,
GPTransfer transfer,
GPEnum * side
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the side.
////////////////
if(pTransfer->sender)
*side = GP_TRANSFER_SENDER;
else
*side = GP_TRANSFER_RECEIVER;
return GP_NO_ERROR;
}
GPResult gpGetTransferSize(
GPConnection * connection,
GPTransfer transfer,
int * size
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the size.
////////////////
*size = pTransfer->totalSize;
return GP_NO_ERROR;
}
GPResult gpGetTransferProgress(
GPConnection * connection,
GPTransfer transfer,
int * progress
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the progress.
////////////////////
*progress = pTransfer->progress;
return GP_NO_ERROR;
}
GPResult gpGetNumFiles(
GPConnection * connection,
GPTransfer transfer,
int * num
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the progress.
////////////////////
*num = ArrayLength(pTransfer->files);
return GP_NO_ERROR;
}
GPResult gpGetCurrentFile(
GPConnection * connection,
GPTransfer transfer,
int * index
)
{
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the current file.
////////////////////////
*index = pTransfer->currentFile;
return GP_NO_ERROR;
}
GPResult gpSkipFile(
GPConnection * connection,
GPTransfer transfer,
int index
)
{
GPIFile * file;
GPITransfer * pTransfer;
GPTransferCallbackArg * arg;
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection*)*connection;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Are we already past this file?
/////////////////////////////////
if(index < pTransfer->currentFile)
return GP_NO_ERROR;
// Did we not get to this file yet?
///////////////////////////////////
if(pTransfer->currentFile != index)
{
// Mark it.
///////////
file->flags |= GPI_FILE_SKIP;
// If we're receiving, let the sender know we want to skip it.
//////////////////////////////////////////////////////////////
if(!pTransfer->sender)
gpiSkipFile(connection, pTransfer, index, GPI_SKIP_USER_SKIP);
return GP_NO_ERROR;
}
// If we're receiving, delete our temp file.
////////////////////////////////////////////
if(!pTransfer->sender && (index == pTransfer->currentFile) && file->file)
{
fclose(file->file);
file->file = NULL;
remove(file->path);
}
// Skip the current file.
/////////////////////////
gpiSkipCurrentFile(connection, pTransfer, GPI_SKIP_USER_SKIP);
// Call the callback.
/////////////////////
arg = (GPTransferCallbackArg *)gsimalloc(sizeof(GPTransferCallbackArg));
if(arg)
{
memset(arg, 0, sizeof(GPTransferCallbackArg));
arg->transfer = pTransfer->localID;
arg->index = index;
arg->type = GP_FILE_SKIP;
gpiAddCallback(connection, iconnection->callbacks[GPI_TRANSFER_CALLBACK], arg, NULL, GPI_ADD_TRANSFER_CALLBACK);
}
return GP_NO_ERROR;
}
GPResult gpGetFileName(
GPConnection * connection,
GPTransfer transfer,
int index,
gsi_char ** name
)
{
GPIFile * file;
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Get the name.
////////////////
#ifndef GSI_UNICODE
*name = file->name;
#else
*name = file->name_W;
#endif
return GP_NO_ERROR;
}
GPResult gpGetFilePath(
GPConnection * connection,
GPTransfer transfer,
int index,
gsi_char ** path
)
{
GPIFile * file;
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Get the path.
////////////////
#ifndef GSI_UNICODE
*path = file->path;
#else
*path = file->path_W;
#endif
return GP_NO_ERROR;
}
GPResult gpGetFileSize(
GPConnection * connection,
GPTransfer transfer,
int index,
int * size
)
{
GPIFile * file;
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Get the size.
////////////////
*size = file->size;
return GP_NO_ERROR;
}
GPResult gpGetFileProgress(
GPConnection * connection,
GPTransfer transfer,
int index,
int * progress
)
{
GPIFile * file;
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Get the progress.
////////////////////
*progress = file->progress;
return GP_NO_ERROR;
}
GPResult gpGetFileModificationTime(
GPConnection * connection,
GPTransfer transfer,
int index,
gsi_time * modTime
)
{
GPIFile * file;
GPITransfer * pTransfer;
// Get the transfer.
////////////////////
pTransfer = gpiFindTransferByLocalID(connection, transfer);
if(!pTransfer)
Error(connection, GP_PARAMETER_ERROR, "Invalid transfer.");
// Get the file.
////////////////
if((index < 0) || (index >= ArrayLength(pTransfer->files)))
Error(connection, GP_PARAMETER_ERROR, "Invalid index.");
file = (GPIFile *)ArrayNth(pTransfer->files, index);
// Get the modTime.
///////////////////
*modTime = file->modTime;
return GP_NO_ERROR;
}
GPResult gpGetNumTransfers(
GPConnection * connection,
int * num
)
{
GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for NULL.
//////////////////
if(num == NULL)
Error(connection, GP_PARAMETER_ERROR, "NULL pointer.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Set num.
///////////
*num = ArrayLength(iconnection->transfers);
return GP_NO_ERROR;
}
GPResult gpGetTransfer(
GPConnection * connection,
int index,
GPTransfer * transfer
)
{
GPIConnection * iconnection;
int localID;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return GP_PARAMETER_ERROR;
// Check for NULL.
//////////////////
if(transfer == NULL)
Error(connection, GP_PARAMETER_ERROR, "NULL pointer.");
// Get the connection object.
/////////////////////////////
iconnection = (GPIConnection *)*connection;
// Get the local ID.
////////////////////
localID = gpiGetTransferLocalIDByIndex(connection, index);
// Check if it was a bad index.
///////////////////////////////
if(localID == -1)
Error(connection, GP_PARAMETER_ERROR, "Index out of range.");
// Set the transfer they want.
//////////////////////////////
*transfer = localID;
return GP_NO_ERROR;
}
#endif
#ifdef _DEBUG
void gpProfilesReport(
GPConnection * connection,
void (* report)(const char * output)
)
{
//GPIConnection * iconnection;
// Error check.
///////////////
if((connection == NULL) || (*connection == NULL))
return;
// Get the connection object.
/////////////////////////////
//iconnection = (GPIConnection *)*connection;
gpiReport(connection, report);
}
#endif