Example #1
0
/*----------------------------------------------------------------------
 Callback to handle score reports from client.
----------------------------------------------------------------------*/
static int dp_PASCAL scores_cb(dptab_t *dptab, dptab_table_t *table, playerHdl_t src, playerHdl_t dest, char *subkey, int subkeylen, void *buf, size_t sent, size_t total, int seconds_left, void *context, dp_result_t status)
{
	dp_t *dp = (dp_t *)context;
	dp_result_t err;

	scorerep_buf_t sbuf;
	scorerep_t *srep;
	dp_uid_t uid;
	char sessid[dptab_KEY_MAXLEN];
	int sessidlen;
	dp_species_t sessType;

	if (!dp || !buf || (status != dp_RES_CREATED))
		return 0;
	DPRINT(("scores_cb: new score report; size %d\n", total));

	/* Look up uid of handle reporting score */
	uid = tserv_hdl2uid(dp->tserv, src);
	if (uid == dp_UID_NONE) {
		DPRINT(("scores_cb: can't map h:%x to uid\n", src));
		return 0;
	}
	/* Get id and type of session that uid most recently tried to join */
	err = dp_uid2sessid(dp, uid, sessid, &sessidlen, &sessType);
	if (err != dp_RES_OK) {
		DPRINT(("scores_cb: can't map uid:%d to session\n", uid));
		return 0;
	}

	/* Write out incoming score record to web message queue,
	 * preceded by header:
	 *	char sessid[8];		// inetadr + port + karma 
	 *	dp_karma_t sessType;
	 *	unsigned short bloblen;
	 */
	{
		char wmqbuf[1024];
		int wmqbuflen;

		memcpy(wmqbuf, sessid, sessidlen);
		wmqbuflen = sessidlen;
		wmqbuf[wmqbuflen++] = dpGETSHORT_FIRSTBYTE(sessType);
		wmqbuf[wmqbuflen++] = dpGETSHORT_SECONDBYTE(sessType);
		wmqbuf[wmqbuflen++] = dpGETSHORT_FIRSTBYTE(total);
		wmqbuf[wmqbuflen++] = dpGETSHORT_SECONDBYTE(total);
		assert(wmqbuflen + total < sizeof(wmqbuf));
		memcpy(wmqbuf + wmqbuflen, buf, total);
		wmqbuflen += total;

		err = wmq_put(wmq, time(NULL), wmq_RECORDTAG_SCORE, wmqbuf, wmqbuflen);
		if (err != dp_RES_OK)
			DPRINT(("scores_cb: wmq_put returns err:%d\n", err));
		assert(err == dp_RES_OK);
	}

	/* Delete the raw score report!  Causes another callback here, ignored. */
	dptab_delete(dptab, table, subkey, subkeylen);

	return 0;
}
Example #2
0
/*--------------------------------------------------------------------------
 Call this (from the player table callback dp_players_cb())
 whenever a player leaves the session.
 Sends a score record for the given player to the game server.
 If the player is ourselves, also sends scores for all other players.

 Return: dp_RES_BAD if score table doesn't exist or can't be created
         dp_RES_EMPTY if there are no score records found
         otherwise return status of dptab_addSubscriber(), dptab_set()
--------------------------------------------------------------------------*/
dp_result_t dpscore_client_playerLeaving(dp_t *dp, dpid_t id)
{
	dp_result_t err = dp_RES_OK;
	char subkey[dptab_KEY_MAXLEN];
	int subkeylen = 0;
	int flags;
	dpid_t firstId;
	scorerep_buf_t sbuf;

	precondition(dp);
	DPRINT(("dpscore_client_playerLeaving: id:%d\n", id));
	ASSERTMEM();
	
	if (!dp->myscoretab) {
		DPRINT(("dpscore_client_playerLeaving: no myscorestab\n"));
		return dp_RES_BUG;
	}

	if (dp->scorerep) {
		/* If (local player), set SELFEXIT to show we're leaving */
		/* We care because when local player leaves, we report on everyone */
		/* Use same code as dpEnumPlayers to detect local player */
		firstId = (dpid_t) (id & ~(dp_PLAYERS_PER_HOST-1));	
		flags = 0;
		if (firstId == dp->firstId)		
			flags = scorerep_FLAGS_SELFEXIT;
		
		/* Grab the appropriate score data and put it into a buffer */
		err = scorerep_toBuf(dp->scorerep, flags, id, &sbuf);
		ASSERTMEM();
		if (err != dp_RES_OK) {
			DPRINT(("dpscore_client_playerLeaving: can't convert to buf\n"));
			return dp_RES_BUG;
		}

		/* The score report key is the session id plus this player's dpid plus
		 * the id of the player who is leaving.
		 */
		assert(dp->sess_subkeylen + 4 <= dptab_KEY_MAXLEN);
		memcpy(subkey, dp->sess_subkey, dp->sess_subkeylen);
		ASSERTMEM();
		subkeylen = dp->sess_subkeylen;
		subkey[subkeylen++] = dpGETSHORT_FIRSTBYTE(dp->firstId);  /* KLUDGE */
		subkey[subkeylen++] = dpGETSHORT_SECONDBYTE(dp->firstId);
		subkey[subkeylen++] = dpGETSHORT_FIRSTBYTE(id);
		subkey[subkeylen++] = dpGETSHORT_SECONDBYTE(id);
		assert(subkeylen <= dptab_KEY_MAXLEN);
		err = dptab_set(dp->dt, dp->myscoretab, subkey, subkeylen, sbuf.buf, sbuf.len, 1, PLAYER_ME);
		ASSERTMEM();
		if (err != dp_RES_OK) {
			DPRINT(("dpscore_client_playerLeaving: dptab_set(MYSCORES.%s) returns err:%d\n", key2a(subkey, subkeylen), err));
			return err;
		}
	}
	return dp_RES_OK;
}
Example #3
0
/*--------------------------------------------------------------------------
 Call in dpDestroy *before dpFreeze* (and in dpCloseGameServer()) to clean up.
 Don't want to save old scores to disk... oughtta be a way to mark
 tables as 'volatile' in dptab_createTable().
--------------------------------------------------------------------------*/
dp_result_t dpscore_client_cleanup(dp_t *dp)
{
	char key[dptab_KEY_MAXLEN];

	DPRINT(("dpscore_client_cleanup: deleting myscores and scores tables\n"));
	/* Delete outgoing scores */
	key[0] = dp_KEY_MYSCORES;
	dptab_deleteTable(dp->dt, key, 1);
	dp->myscoretab = NULL;  /* clear our quick access pointer */
	ASSERTMEM();
	
	/* Delete incoming scores.  KLUDGE; only does one session type... */
	/* Watch out- the entry in the publishers table contains a pointer
	 * to this table.  Possible crash bug if a record comes in
	 * from the game server after table is deleted.  Not sure if deleteTable
	 * wipes out the publishers table entry...
	 */
	key[0] = dp_KEY_SCORES;
	key[1] = dpGETSHORT_FIRSTBYTE(dp->defaultSessionType);
	key[2] = dpGETSHORT_SECONDBYTE(dp->defaultSessionType);
	dptab_deleteTable(dp->dt, key, 3);
	ASSERTMEM();

	return dp_RES_OK;
}
Example #4
0
/*----------------------------------------------------------------------
 Gets latest version info from server's table.
----------------------------------------------------------------------*/
static dp_result_t			/* status */
getLatest(
	dp_t* dp,				/* (input) source of table of latest */
	dp_appParam_t *pApp)	/* (output) latest version info */
{
	dptab_table_t *ptApps;
	char key[dptab_KEY_MAXLEN];
	int keylen = 0;
	dp_result_t err;

	assert(dp != NULL);
	assert(pApp != NULL);

	/* Set up default values */
	pApp->latest.major = dp_VERS_UNKNOWN;
	pApp->latest.minor = dp_VERS_UNKNOWN;

	/* Get table of applications */
	keylen = 0;
	key[keylen++] = dp_KEY_APPLICATIONS;
	ptApps = dptab_getTable(dp->dt, key, keylen);

	/* If table present, find app info */
	if(ptApps != NULL) {
		dp_version_t ver;
		dp_version_t* pVer = &ver;
		size_t len;

		keylen = 0;
		key[keylen++] = (char) dpGETSHORT_FIRSTBYTE(pApp->sessionType);
		key[keylen++] = (char) dpGETSHORT_SECONDBYTE(pApp->sessionType);
		key[keylen++] = (char) dpGETSHORT_FIRSTBYTE(pApp->platform);
		key[keylen++] = (char) dpGETSHORT_SECONDBYTE(pApp->platform);
		key[keylen++] = (char) pApp->language;
		err = dptab_get_bykey(ptApps, key, keylen, &pVer, &len);
		if (err != dp_RES_OK) {
			DPRINT(("enumapp.getLatest: game not in table\n"));
			return err;
		}
		pApp->latest = *pVer;
	}

	return dp_RES_OK;
}
Example #5
0
/*------------------------------------------------------------------------
 Convert a player id (dpid_t) to a user id (dp_uid_t).
 Returns dp_UID_NONE on any error.
------------------------------------------------------------------------*/
DP_API dp_uid_t DP_APIX dpGetPlayerUid(dp_t *dp, dpid_t id)
{
	dp_result_t err;
	dp_playerId_t player;
	char *playerbuf;
	size_t len_used;
	size_t len;
	char subkey[dptab_KEY_MAXLEN];
	int subkeylen;

	precondition(dp != NULL);
	dp_assertValid(dp);
	if (!dp->players) return dp_UID_NONE;
	if (!dp->groups) return dp_UID_NONE;

	subkey[0] = (char) dpGETSHORT_FIRSTBYTE(id);
	subkey[1] = (char) dpGETSHORT_SECONDBYTE(id);
	subkeylen = 2;

	if (id >= dp->firstGId && id < dp->firstGId + dp_MAX_GROUPS) {
		DPRINT(("dpGetPlayerUid: player groups don't have UIDs\n"));
		return dp_UID_NONE;
	}

	err = dptab_get_bykey(dp->players, subkey, subkeylen, (void **)&playerbuf, &len);
	if (err != dp_RES_OK) {
		DPRINT(("dpGetPlayerUid: dptab_get_bykey(players, id:%d) returns err:%d\n", id, err));
		dp_assertValid(dp);
		return dp_UID_NONE;
	}
	len_used = dp_unpack_playerId(id, playerbuf, &player);
	if (len != len_used) {
		DPRINT(("dpGetPlayerUid: can't unpack player %d.\n", id));
		dp_assertValid(dp);
		return dp_UID_NONE;
	}

	if ((unsigned long)player.karma == dp_UID_NONE)
		return dp_UID_NONE;  /* Better not let UID get to 131072! FIXME */

	/* Kludge: only the lower 16 bits of uid available at moment */
	return (dp_uid_t)(0x10000 + (unsigned long)(player.karma));
}
Example #6
0
/*--------------------------------------------------------------------------
 Request that the server send us score data for the given session type.
 Call from dpRequestObjectDeltas().
--------------------------------------------------------------------------*/
dp_result_t dpscore_client_subscribe(dp_t *dp, dp_species_t sessType)
{
	dp_result_t err;
	dptab_table_t *tab;
	char key[dptab_KEY_MAXLEN];
	int keylen;
	ASSERTMEM();
	
	/* Create incoming scores table. */
	key[0] = dp_KEY_SCORES;
	key[1] = dpGETSHORT_FIRSTBYTE(sessType);
	key[2] = dpGETSHORT_SECONDBYTE(sessType);
	keylen = 3;
	err = dptab_createTable(dp->dt, &tab, key, keylen, 0, NULL, NULL, dpscores_cb, dp);
	ASSERTMEM();
	if (err != dp_RES_OK) {
		DPRINT(("dpscore_client_subscribe: can't create scores table, err:%d\n", err));
		return err;
	}
	/* Allow the game server to send us data on this table. */
	err = dptab_addPublisher(dp->dt, tab, key, keylen, dp->hGameServer);
	ASSERTMEM();
	if (err != dp_RES_OK) {
		DPRINT(("dpscore_client_subscribe: can't add hGameServer h:%x as publisher?, err:%d\n", dp->hGameServer, err));
		return err;
	}

	/* Request the game server to send us data on this table. 
	 * For now, ask for the whole table; later, we'll ask for just
	 * part of it (otherwise we'll drown in data).
	 */
	err = dptab_requestSubscription(dp->dt, key, keylen, dp->hGameServer, NULL, NULL);
	ASSERTMEM();
	if (err != dp_RES_OK) {
		DPRINT(("dpscore_client_subscribe: can't request scores from hGameServer h:%x, err:%d\n", dp->hGameServer, err));
		return err;
	}
	ASSERTMEM();

	return dp_RES_OK;
}
Example #7
0
/*----------------------------------------------------------------------
 Callback for remote enum players.  Only used if application requested
 object deltas for this session's players.
----------------------------------------------------------------------*/
void dp_PASCAL dp_rplayers_enumEx_cb(dpid_t id, char *name, long flags, void *context, dp_playerId_t *player)
{
	dp_rplayers_enumEx_context_t *r = (dp_rplayers_enumEx_context_t *)context;
	dp_result_t err;
	char subkey[2];
	int subkeylen;

	if (!r || !r->dp || !r->tab)
		return;
	if (player == NULL)
		return;

	/* Inform caller via local message, if desired */
	subkeylen = 0;
	subkey[subkeylen++] = (char) dpGETSHORT_FIRSTBYTE(player->id);
	subkey[subkeylen++] = (char) dpGETSHORT_SECONDBYTE(player->id);
	err = dpSendObjectDelta(r->dp, dp_RES_CREATED, (dp_object_t *) player, r->tab, subkey, subkeylen);
	if (err != dp_RES_OK) {
		DPRINT(("dp_rplayers_enumEx_cb: can't send object delta, err:%d\n", err));
		return;
	}

	return;
}
Example #8
0
int scorerep_test(void)
{
	dp_result_t err;
	dp_uid_t myUID;
	dpid_t myId;
	dp_uid_t hisUID;
	dpid_t hisId;
	scorerep_t *rep;
	scorerep_buf_t repbuf;
	scorerep_player_t *player;
	unsigned short bloblen;
	char blob[scorerep_MAX_BLOBLEN];

	/* create a rep */
	rep = scorerep_create();
	assert(rep);

	/* set my id and uid */
	myId = 1;
	myUID = (long) myId + 10000;
	err = scorerep_setSelf(rep, myId, myUID);
	assert(!err);
	assert(rep->id == myId);
	assert(rep->uid == myUID);
	
	/* fill my score report with a few blobs */
	for (hisId = myId; hisId < myId + 10; hisId++) {
		hisUID = (long) hisId + 10000;
		blob[0] = dpGETSHORT_FIRSTBYTE(hisId);
		blob[1] = dpGETSHORT_SECONDBYTE(hisId);
		blob[2] = dpGETLONG_FIRSTBYTE(hisUID);
		blob[3] = dpGETLONG_SECONDBYTE(hisUID);
		blob[4] = dpGETLONG_THIRDBYTE(hisUID);
		blob[5] = dpGETLONG_FOURTHBYTE(hisUID);
		bloblen = 6;
		err = scorerep_set(rep, hisId, hisUID, 0, blob, bloblen);
		assert(!err);
	}
	
	/* convert it to a buffer with everyone's scores */
	err = scorerep_toBuf(rep, scorerep_FLAGS_SELFEXIT, myId, &repbuf);
	assert(!err);
	
	/* destroy the rep */
	scorerep_destroy(rep);
	rep = NULL;

	/* create a new rep */
	rep = scorerep_create();
	assert(rep);

	/* set my id and uid */
	myId = 1;
	myUID = (long) myId + 10000;
	err = scorerep_setSelf(rep, myId, myUID);
	assert(!err);
	assert(rep->id == myId);
	assert(rep->uid == myUID);
	
	/* read the buffer into my report table */
	err = scorerep_fromBuf(rep, &repbuf);
	assert(!err);
	assert(rep->players);
	assert(rep->flags == scorerep_FLAGS_SELFEXIT);
	
	/* check that it contains what I put there and only that */
	assert(rep->players->n_used = 10);
	for (hisId = myId; hisId < myId + 10; hisId++) {
		player = (scorerep_player_t *)assoctab_subscript(rep->players, hisId);
		assert(player);
		hisUID = (long) hisId + 10000;
		assert(player->uid = hisUID);
		assert(player->bloblen == 6);
		assert(hisId == dpMAKESHORT(player->blob[0], player->blob[1]));
		assert(hisUID == dpMAKELONG(player->blob[2], player->blob[3], player->blob[4], player->blob[5]));
	}
	
	/* convert it to a buffer with only my and his scores */
	hisId = myId + 1;
	hisUID = (long) hisId + 10000;
	memset(&repbuf, 0, sizeof(repbuf));
	err = scorerep_toBuf(rep, 0, hisId, &repbuf);
	assert(!err);
	
	/* destroy the rep */
	scorerep_destroy(rep);
	rep = NULL;

	/* create a new rep */
	rep = scorerep_create();
	assert(rep);

	/* set my id and uid */
	myId = 1;
	myUID = (long) myId + 10000;
	err = scorerep_setSelf(rep, myId, myUID);
	assert(!err);
	assert(rep->id == myId);
	assert(rep->uid == myUID);

	/* read the buffer into my report table */
	err = scorerep_fromBuf(rep, &repbuf);
	assert(!err);
	assert(rep->players);
	assert(rep->flags == 0);

	/* check that it contains what I put there and only that */
	assert(rep->players->n_used = 2);
	player = (scorerep_player_t *)assoctab_subscript(rep->players, myId);
	assert(player);
	assert(player->uid = myUID);
	assert(player->bloblen == 6);
	assert(myId == dpMAKESHORT(player->blob[0], player->blob[1]));
	assert(myUID == dpMAKELONG(player->blob[2], player->blob[3], player->blob[4], player->blob[5]));

	hisId = myId + 1;
	hisUID = (long) hisId + 10000;
	player = (scorerep_player_t *)assoctab_subscript(rep->players, hisId);
	assert(player);
	assert(player->uid = hisUID);
	assert(player->bloblen == 6);
	assert(hisId == dpMAKESHORT(player->blob[0], player->blob[1]));
	assert(hisUID == dpMAKELONG(player->blob[2], player->blob[3], player->blob[4], player->blob[5]));

	/* destroy the rep */
	scorerep_destroy(rep);
	rep = NULL;
	
	return 0;
}