Beispiel #1
0
HashTable TableNew(int elemSize, int nBuckets,
                   TableHashFn hashFn, TableCompareFn compFn,
                   TableElementFreeFn freeFn)
{
	HashTable table;
	int i;

	if(!hashFn)
		gspyi.error("TableNew: hashFn is NULL.");
	if(!compFn)
		gspyi.error("TableNew: compFn is NULL.");
	if(elemSize <= 0)
		gspyi.error("TableNew: bad elemSize.");
	if(nBuckets <= 0)
		gspyi.error("TableNew: bad nBuckets.");

	table = (HashTable)malloc(sizeof(struct HashImplementation));
	if(!table)
		gspyi.error("TableNew: table is NULL.");

	table->buckets = (DArray *)malloc(nBuckets * sizeof(DArray));
	if(!table->buckets)
		gspyi.error("TableNew: table->buckets is NULL.");
	for (i = 0; i < nBuckets; i++) //ArrayNew will assert if allocation fails
		table->buckets[i] = ArrayNew(elemSize, 0, freeFn);
	table->nbuckets = nBuckets;
	table->freefn = freeFn;
	table->compfn = compFn;
	table->hashfn = hashFn;

	return table;
}
Beispiel #2
0
GPIPeer *
gpiAddPeer(
  GPConnection * connection,
  int profileid,
  GPIBool initiate
)
{
	GPIPeer * peer;
	GPIConnection * iconnection = (GPIConnection*)*connection;

	// Create a new peer.
	/////////////////////
	peer = (GPIPeer *)gsimalloc(sizeof(GPIPeer));
	if(peer == NULL)
		return NULL;
	memset(peer, 0, sizeof(GPIPeer));
	peer->state = GPI_PEER_NOT_CONNECTED;
	peer->initiated = initiate;
	//peer->sock = INVALID_SOCKET;
	peer->profile = profileid;
	peer->timeout = (time(NULL) + GPI_PEER_TIMEOUT);
	peer->pnext = iconnection->peerList;
	peer->messages = ArrayNew(sizeof(GPIMessage), 0, gpiFreeMessage);
	iconnection->peerList = peer;
	peer->peerOpQueue.first = NULL;
	peer->peerOpQueue.last = NULL;
	peer->peerOpQueue.opList = NULL;
	return peer;
}
Beispiel #3
0
Assembler* AsmNew() {
  Assembler *a=ObjNew(Assembler, 1);
  a->codes = ArrayNew(10);
  a->symTable = HashTableNew(127);
  a->opTable = OpTableNew();
  return a;
}
Beispiel #4
0
int Cache_Init (/*in*/ tApp * a)

    {
    epaTHX_
    pProviders  = newHV () ;
    pCacheItems = newHV () ;

    ArrayNew (a, &pCachesToRelease, 16, sizeof (tCacheItem *)) ;

    /* lprintf (a, "XXXXX Cache_Init [%d/%d] pProviders=%x pCacheItems=%x pCachesToRelease=%x", _getpid(), GetCurrentThreadId(), pProviders, pCacheItems, pCachesToRelease) ; */
    
    return ok ;
    }
Beispiel #5
0
int Cache_AddDependency (/*in*/ req *       r,
                         /*in*/ tCacheItem *    pItem,
                         /*in*/ tCacheItem *    pDependsOn)

    {
    int n ;
    
    if (!pItem -> pDependsOn)
        ArrayNew (r -> pApp, &pItem -> pDependsOn, 2, sizeof (tCacheItem *)) ;

    n = ArrayAdd (r -> pApp, &pItem -> pDependsOn, 1) ;
    pItem -> pDependsOn[n] = pDependsOn ;


    if (!pDependsOn -> pNeededFor)
        ArrayNew (r -> pApp, &pDependsOn -> pNeededFor, 2, sizeof (tCacheItem *)) ;

    n = ArrayAdd (r -> pApp, &pDependsOn -> pNeededFor, 1) ;
    pDependsOn -> pNeededFor[n] = pItem ;

    return ok ;
    }
Beispiel #6
0
GPResult gpiCheckNpStatus(
  GPConnection * connection
)
{
	int ret = 0;
	int status = SCE_NP_MANAGER_STATUS_OFFLINE;
    SceNpId npId;
	GPIConnection * iconnection = (GPIConnection*)*connection;

	// Get NP status
	////////////////
	ret = sceNpManagerGetStatus(&status);
	if (ret < 0) 
	{
		gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
			"gpiCheckNpStatus: sceNpGetStatus() failed. ret = 0x%x\n", ret);	
	}
	gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
		"gpiCheckNpStatus: sceNpGetStatus - status = %d\n", status);	


	// If NP status != online after the timeout period, stop syncing 
	////////////////////////////////////////////////////////////////
	if (status != SCE_NP_MANAGER_STATUS_ONLINE && (current_time() - iconnection->loginTime > GPI_NP_STATUS_TIMEOUT))
	{
		gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
			"gpiCheckNpStatus: NP Status not online - timed out\n");	
		
		// Flag to stop the sync process
		////////////////////////////////
		iconnection->npPerformBuddySync = gsi_false;
        iconnection->npPerformBlockSync = gsi_false;

		return GP_MISC_ERROR;
	}

	// Once status is online, finish NP init
	////////////////////////////////////////
	if (status == SCE_NP_MANAGER_STATUS_ONLINE)
	{
		iconnection->loginTime = current_time();

        // Note - we ignore error messages here - if something fails we really don't care
		/////////////////////////////////////////////////////////////////////////////////
        if (!iconnection->npBasicGameInitialized)
        {
		    ret = sceNpBasicInit(); //obsolete?
		    if (ret < 0) 
		    {
			    gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
				    "gpiCheckNpStatus: sceNpBasicInit() failed. ret = 0x%x\n", ret);	
		    }

		    ret = sceNpBasicRegisterHandler(&gpi_communication_id, gpiNpBasicCallback, NULL);
		    if (ret < 0) 
		    {
			    gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
				    "gpiCheckNpStatus: sceNpBasicRegisterHandler() failed. ret = 0x%x\n", ret);
		    }
        }

        ret = sceNpLookupInit();
        if (ret == SCE_NP_COMMUNITY_ERROR_ALREADY_INITIALIZED)
        {
            // If already initialized - DO NOT terminate after GP destroy (game might need it)
            //////////////////////////////////////////////////////////////////////////////////
            iconnection->npLookupGameInitialized = gsi_true;
        }
        else if (ret < 0) 
        {
            gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
                "gpiCheckNpStatus: sceNpLookupInit() failed. ret = 0x%x\n", ret);    
            iconnection->npLookupGameInitialized = gsi_true;
        }
        else
            iconnection->npLookupGameInitialized = gsi_false;

        // Regardless of game, create a title context id for GP to use for lookups
        ///////////////////////////////////////////////////////////////////////////
        ret = sceNpManagerGetNpId(&npId);
        if (ret < 0) 
        {
            gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
                "gpiCheckNpStatus: sceNpManagerGetNpId() failed. ret = 0x%x\n", ret);  
        }

        ret = sceNpLookupCreateTitleCtx(&gpi_communication_id, &npId);
        if (ret < 0) 
        {
            gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError,
                "gpiCheckNpStatus: sceNpLookupCreateTitleCtx() failed. ret = 0x%x\n", ret);  
        }

        iconnection->npLookupTitleCtxId = ret;

		// Mark status retrieval completed
		//////////////////////////////////
		iconnection->npStatusRetrieved = gsi_true;
        gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment,
            "gpiCheckNpStatus: NP is now initialized with status.\n");	

        iconnection->npTransactionList = ArrayNew(sizeof(npIdLookupTrans), 1, gpiNpTransactionListFree);
        if (!iconnection->npTransactionList)
            Error(connection, GP_MEMORY_ERROR, "Out of memory.");
	}

	return GP_NO_ERROR;
}
Beispiel #7
0
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// UDP Layer must be initialized
// Message handlers are added using this function
// The initial message and header of a message handler cannot be empty
// However, they can be the same.
// User data can be useful for keeping track of Message Handler 
GSUdpErrorCode gsUdpEngineAddMsgHandler(char theInitMsg[GS_UDP_MSG_HEADER_LEN], char theHeader[GS_UDP_MSG_HEADER_LEN], 
									    gsUdpErrorCallback theMsgHandlerError, 
									    gsUdpConnConnectedCallback theMsgHandlerConnected, 
									    gsUdpConnClosedCallback theMsgHandlerClosed, 
									    gsUdpConnPingCallback theMsgHandlerPing,
										gsUdpConnReceivedDataCallback theMsgHandlerRecv,
										void *theUserData)
{
	GSUdpEngineObject *aUdp = gsUdpEngineGetEngine();
	GSUdpMsgHandler aMsgHandler;
	GS_ASSERT(aUdp->mInitialized);
	GS_ASSERT(theInitMsg || theInitMsg[0]);
	GS_ASSERT(theHeader || theHeader[0]);
	if (!aUdp->mInitialized)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug,
			"[Udp Engine] Engine not initialized\n");
		return GS_UDP_NETWORK_ERROR;
	}
	
	// setup a message handler that the UDP engine will use to pass connection attempts to
	
	//check for valid input
	if (!theInitMsg[0])
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug,
			"[Udp Engine] Invalid init message\n");
		return GS_UDP_PARAMETER_ERROR;
	}

	if (!theHeader[0])
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug,
			"[Udp Engine] Invalid header\n");
		return GS_UDP_PARAMETER_ERROR;
	}

	// This check is not necessary.  Some SDKs may not use all callbacks
	/*if (!theMsgHandlerError || !theMsgHandlerConnected || !theMsgHandlerClosed 
		|| !theMsgHandlerPing || !theMsgHandlerRecv)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug,
			"[Udp Engine] Invalid callback(s)");
		return GS_UDP_PARAMETER_ERROR;
	}
	*/
	aMsgHandler.mClosed = theMsgHandlerClosed;
	aMsgHandler.mConnected = theMsgHandlerConnected;
	aMsgHandler.mPingReply = theMsgHandlerPing;
	aMsgHandler.mReceived = theMsgHandlerRecv;
	
	aMsgHandler.mNetworkError = theMsgHandlerError;

	memcpy(aMsgHandler.mInitialMsg, theInitMsg, GS_UDP_MSG_HEADER_LEN);
	memcpy(aMsgHandler.mHeader, theHeader, GS_UDP_MSG_HEADER_LEN);
		
	aMsgHandler.mPendingConnections = ArrayNew(sizeof(GSUdpRemotePeer *), 1, NULL);
	if (aMsgHandler.mPendingConnections == NULL)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Memory, GSIDebugLevel_HotError, 
			"[Udp Engine] No more memory!!!\n");
		return GS_UDP_NO_MEMORY;
	}
	aMsgHandler.mUserData = theUserData;
	ArrayAppend(aUdp->mMsgHandlers, &aMsgHandler);
	
	return GS_UDP_NO_ERROR;
}
Beispiel #8
0
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Initializes the UDP layer
// A specific port can be used if needed.
// An app must register their callbacks here.
// An App must also call this before starting SDKs since they might start 
// the UDP layer without the app having a chance to register its callbacks.
// Any message handler can get the port the UDP layer is using if it did not
// initialize the UDP Layer.
// Use of the UDP Layer requires it to be initialized as is the case with most 
// functions below.
GSUdpErrorCode gsUdpEngineInitialize(unsigned short thePort, int theIncomingBufSize, 
									 int theOutgoingBufSize, gsUdpErrorCallback theAppNetworkError, 
									 gsUdpConnConnectedCallback theAppConnected,
									 gsUdpConnClosedCallback theAppClosed,
									 gsUdpConnPingCallback theAppPing,
									 gsUdpConnReceivedDataCallback theAppReceive,
									 gsUdpUnknownMsgCallback theAppUnownMsg,
									 gsUdpAppConnectAttemptCallback theAppConnectAttempt,
									 void *theAppUserData)
{
	int incomingBufferSize,
		outgoingBufferSize;
	char anAddr[GS_IP_ADDR_AND_PORT];
	GT2Result aGt2Result;
	// Grab the single instance of the UDP Communication Engine
	GSUdpEngineObject *aUdp = gsUdpEngineGetEngine();
	
	// Setup our gt2 buffer sizes for reliable messages
	
	incomingBufferSize = theIncomingBufSize != 0 ? theIncomingBufSize : GS_UDP_DEFAULT_IN_BUFFSIZE;
	outgoingBufferSize = theOutgoingBufSize != 0 ? theOutgoingBufSize : GS_UDP_DEFAULT_OUT_BUFFSIZE;

	// Setup our internal socket that will be shared among more than one application
	aUdp->mAppNetworkError = theAppNetworkError;
	aUdp->mAppUnknownMessage = theAppUnownMsg;
	aUdp->mAppConnected = theAppConnected;
	aUdp->mAppClosed = theAppClosed;
	aUdp->mAppPingReply = theAppPing;
	aUdp->mAppRecvData = theAppReceive;
	aUdp->mAppConnAttempt = theAppConnectAttempt;

	// Any port can be used 
	gt2AddressToString(0, thePort, anAddr);
	aGt2Result = gt2CreateSocket(&aUdp->mSocket, anAddr,  outgoingBufferSize, incomingBufferSize, 
		gsUdpSocketError);
	if (aGt2Result != GT2Success)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_WarmError, 
			"[Udp Engine] error creating gt2 socket, error code: %d\n", aGt2Result);
		return GS_UDP_NETWORK_ERROR;
	}	
	// We'll need to keep track of connections with an array of GPconnection to address mapping
	aUdp->mRemotePeers = ArrayNew(sizeof(GSUdpRemotePeer), 1, NULL);
	if (aUdp->mRemotePeers == NULL)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Memory, GSIDebugLevel_HotError, 
			"[Udp Engine] No more memory!!!\n");
		return GS_UDP_NO_MEMORY;
	}

	aUdp->mMsgHandlers = ArrayNew(sizeof(GSUdpMsgHandler), 1, gsUdpMsgHandlerFree);
	if (aUdp->mMsgHandlers == NULL)
	{
		gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Memory, GSIDebugLevel_HotError, 
			"[Udp Engine] No more memory!!!\n");
		return GS_UDP_NO_MEMORY;
	}
		
	// Used by the manager to receive messages from backend services or other clients
	// that may not be using gt2
	gt2SetUnrecognizedMessageCallback(aUdp->mSocket, gsUdpUnrecognizedMsgCB);
	
	// Automatically start listening for all SDKS and the game if game uses UDP Engine
	gt2Listen(aUdp->mSocket, gsUdpConnAttemptCB);
	aUdp->mLocalAddr = gt2GetLocalIP(aUdp->mSocket);
	aUdp->mLocalPort = gt2GetLocalPort(aUdp->mSocket);
	aUdp->mAppPendingConnections = 0;
	aUdp->mInitialized = gsi_true;
	if (theAppUserData)
	{
		aUdp->mAppUserData = theAppUserData;
	}
	else
		aUdp->mAppUserData = NULL;
	return GS_UDP_NO_ERROR;
}
Beispiel #9
0
GPResult
gpiProcessRecvBuddyList(
  GPConnection * connection,
  const char * input
)
{
    int i=0, j=0;
    int num = 0;
    int index = 0;
    char c;
    char *str = NULL;
    char buffer[512];
    GPIProfile * profile;
    GPProfile profileid;
    GPIConnection * iconnection = (GPIConnection*)*connection;

    // Check for an error.
    //////////////////////
    if(gpiCheckForError(connection, input, GPITrue))
        return GP_SERVER_ERROR;

    // Process Buddy List Retrieval msg - Format like:
    /* ===============================================
       \bdy\<num in list>\list\<block list - comma delimited>\final\
       =============================================== */

    if(!gpiValueForKeyWithIndex(input, "\\bdy\\", &index, buffer, sizeof(buffer)))
        CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
    num = atoi(buffer);

    // Check to make sure list is there 
    ///////////////////////////////////
    str = strstr(input, "\\list\\");
    if (str == NULL)
        CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");

    // Then increment index to get ready for parsing
    ////////////////////////////////////////////////
    str += 6;
    index += 6;

    for (i=0; i < num; i++)
    {     
        if (i==0)
        {
            // Manually grab first profile in list - comma delimiter
            ////////////////////////////////////////////////////////
            for(j=0 ; (j < sizeof(buffer)) && ((c = str[j]) != '\0') && (c != ',') ; j++)
            {
                buffer[j] = c;
            }
            buffer[j] = '\0';
            index += j;
        }
        else
        {
            if(!gpiValueForKeyWithIndex(input, ",", &index, buffer, sizeof(buffer)))
                CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
        }

        profileid = atoi(buffer);

        // Get the profile, adding if needed.
        /////////////////////////////////////
        profile = gpiProfileListAdd(connection, profileid);
        if(!profile)
            Error(connection, GP_MEMORY_ERROR, "Out of memory.");

        // Mark as offline buddy for now until we get the real status
        /////////////////////////////////////////////////////////////
#ifdef GP_NEW_STATUS_INFO
        // Use new status info as placeholder
        profile->buddyStatusInfo = (GPIBuddyStatusInfo *)gsimalloc(sizeof(GPIBuddyStatusInfo));
        if(!profile->buddyStatusInfo)
            Error(connection, GP_MEMORY_ERROR, "Out of memory.");
        memset(profile->buddyStatusInfo, 0, sizeof(GPIBuddyStatusInfo));

        profile->buddyStatusInfo->extendedInfoKeys = ArrayNew(sizeof(GPIKey), GPI_INITIAL_NUM_KEYS, gpiStatusInfoKeyFree);
        if (!profile->buddyStatusInfo->extendedInfoKeys)
            Error(connection, GP_MEMORY_ERROR, "Out of memory.");

        profile->buddyStatusInfo->buddyIndex = iconnection->profileList.numBuddies++;
        profile->buddyStatusInfo->statusState = GP_OFFLINE; 
#else
        // Use buddy status as placeholder
        profile->buddyStatus = (GPIBuddyStatus *)gsimalloc(sizeof(GPIBuddyStatus));
        if(!profile->buddyStatus)
            Error(connection, GP_MEMORY_ERROR, "Out of memory.");
        memset(profile->buddyStatus, 0, sizeof(GPIBuddyStatus));
        profile->buddyStatus->buddyIndex = iconnection->profileList.numBuddies++;
        profile->buddyStatus->status = GP_OFFLINE; 
#endif
    }

    return GP_NO_ERROR;
}
Beispiel #10
0
GPResult gpiProcessRecvBuddyStatusInfo(GPConnection *connection, const char *input)
{
	char buffer[1024];
	int profileid;
	time_t date;
	GPICallback callback;
	GPIProfile * profile;
	GPIBuddyStatusInfo * buddyStatusInfo;
	GPIConnection * iconnection = (GPIConnection*)*connection;

	// This is what the message should look like.  Its broken up for easy viewing.
	//
	// "\bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\"
	// "\qport\\hport\\sessflags\\rstatus\\gameType\"
	// "\gameVnt\\gameMn\\product\\qmodeflags\"
	////////////////////////////////
	date = time(NULL);
	// Get the buddy's profile
	////////////////////////////////
	if(!gpiValueForKey(input, "\\profile\\", buffer, sizeof(buffer)))
		CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	profileid = atoi(buffer);

	// Get the profile from the SDK's list, adding it if needed.
	/////////////////////////////////////
	profile = gpiProfileListAdd(connection, profileid);
	if(!profile)
		Error(connection, GP_MEMORY_ERROR, "Out of memory.");

    // Make sure profile wasn't blocked prior to getting the status update
    //////////////////////////////////////////////////////////////////////
    if (!profile->blocked)
    {
	    // This is a buddy.
	    ///////////////////
	    if(!profile->buddyStatusInfo)
	    {
		    profile->buddyStatusInfo = (GPIBuddyStatusInfo *)gsimalloc(sizeof(GPIBuddyStatusInfo));
		    if(!profile->buddyStatusInfo)
			    Error(connection, GP_MEMORY_ERROR, "Out of memory.");
		    memset(profile->buddyStatusInfo, 0, sizeof(GPIBuddyStatusInfo));
		    if (profile->buddyStatus)
		    {
			    profile->buddyStatusInfo->buddyIndex = profile->buddyStatus->buddyIndex;
			    gpiRemoveBuddyStatus(profile->buddyStatus);
			    profile->buddyStatus = NULL;
		    }
		    else
			    profile->buddyStatusInfo->buddyIndex = iconnection->profileList.numBuddies++;
		    profile->buddyStatusInfo->extendedInfoKeys = ArrayNew(sizeof(GPIKey), GPI_INITIAL_NUM_KEYS, gpiStatusInfoKeyFree);
		    if (!profile->buddyStatusInfo->extendedInfoKeys)
			    Error(connection, GP_MEMORY_ERROR, "Out of memory.");
	    }

	    // extract the buddy status information and 
	    // fill in appropriate information.
	    /////////////////////////////////////////////
	    buddyStatusInfo = profile->buddyStatusInfo;
    	
	    if (!gpiValueForKey(input, "\\state\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->statusState = (GPEnum)atoi(buffer);

	    if (!gpiValueForKey(input, "\\bip\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->buddyIp = htonl((unsigned int)atoi(buffer));
    	
	    if (!gpiValueForKey(input, "\\bport\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->buddyPort = (unsigned short)atoi(buffer);
    	
	    if (!gpiValueForKey(input, "\\hostip\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->hostIp = htonl((unsigned int)atoi(buffer));

	    if (!gpiValueForKey(input, "\\hprivip\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->hostPrivateIp = htonl((unsigned int)atoi(buffer));

	    if (!gpiValueForKey(input, "\\qport\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->queryPort = (unsigned short)atoi(buffer);

	    if (!gpiValueForKey(input, "\\hport\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->hostPort = (unsigned short)atoi(buffer);
    	
	    if (!gpiValueForKey(input, "\\sessflags\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->sessionFlags = (unsigned int)atoi(buffer);

	    freeclear(buddyStatusInfo->richStatus);
	    if (!gpiValueForKey(input, "\\rstatus\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->richStatus = goastrdup(buffer);
    	
	    freeclear(buddyStatusInfo->gameType);
	    if (!gpiValueForKey(input, "\\gameType\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->gameType = goastrdup(buffer);

	    freeclear(buddyStatusInfo->gameVariant);
	    if (!gpiValueForKey(input, "\\gameVnt\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->gameVariant = goastrdup(buffer);

	    freeclear(buddyStatusInfo->gameMapName);
	    if (!gpiValueForKey(input, "\\gameMn\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->gameMapName = goastrdup(buffer);

	    if (!gpiValueForKey(input, "\\product\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->productId = (int)atoi(buffer);

	    if (!gpiValueForKey(input, "\\qmodeflags\\", buffer, sizeof(buffer)))
		    CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server.");
	    buddyStatusInfo->quietModeFlags = (GPEnum)atoi(buffer);
    	
	    callback = iconnection->callbacks[GPI_RECV_BUDDY_STATUS];
	    if (callback.callback != NULL)
	    {
		    GPRecvBuddyStatusArg *anArg;
		    anArg = (GPRecvBuddyStatusArg *)gsimalloc(sizeof(GPRecvBuddyStatusArg));
		    if (anArg == NULL)
			    Error(connection, GP_MEMORY_ERROR, "Out of memory.");

		    anArg->date = (unsigned int)date;
		    anArg->index = buddyStatusInfo->buddyIndex;
		    anArg->profile = profileid;

		    CHECK_RESULT(gpiAddCallback(connection, callback, anArg, NULL, 0));
	    }
    }
	return GP_NO_ERROR;
	
}