Example #1
0
/* When a new client comes online,
 * send it our SESSIONS table,
 * and when it sends us its MYSESSIONS table, put it in our MYSESSIONS table.
 * (If we're the master gameserver, dump it into the sessions table
 * instead.)
 */
void addClient(dp_t *dp, playerHdl_t src)
{
    dp_result_t err;
    dptab_table_t *target;

    target = masterServerHostname ? dp->mysessions: dp->sessions;

    DPRINT(("addClient: h:%x; sucking his MYSESSIONS into my table %s\n",
            src, key2a(target->key, target->keylen)));

    err = dptab_addPeer(dp->dt, src);
    if (err != dp_RES_OK) {
        DPRINT(("addClient: can't addPeer, err:%d\n", err));
        return;
    }

    /* Send our session table to the new client. */
    err = dptab_addSubscriber(dp->dt, dp->sessions, src);
    if (err != dp_RES_OK) {
        DPRINT(("addClient: can't addSubscriber, err:%d\n", err));
        return;
    }

    /* Accept the new client's mysessions table, dump it in to
     * the 'target' table (different for master and slave servers)
     */
    err = dptab_addPublisher(dp->dt, target,
                             dp->mysessions->key, dp->mysessions->keylen, src);
    if (err != dp_RES_OK) {
        DPRINT(("addClient: can't addPublisher, err:%d\n", err));
        return;
    }
}
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
/* Print out incoming variable adds or deletes. */
int dp_PASCAL print_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 err)
{
    dptab_table_t *sessions = (dptab_table_t *)context;

    printf("print_cb: src h:%x, dest h:%x, table %s, subkey %s, err %d\n",
           src, dest,
           key2a(table->key, table->keylen),
           key2a2(subkey, subkeylen),
           err);

    return TRUE;
}
Example #4
0
// test the key creation functions
void RegTreeCtrl::OnMenuTest()
{
    wxTreeItemId lId = GetSelection();
    TreeNode *pNode = (TreeNode *)GetItemData(lId);

    wxCHECK_RET( pNode != NULL, wxT("tree item without data?") );

    if ( pNode->IsRoot() )
    {
        wxLogError(wxT("Can't create a subkey under the root key."));
        return;
    }

    if ( !pNode->IsKey() )
    {
        wxLogError(wxT("Can't create a subkey under a value!"));
        return;
    }

    wxRegKey key1(pNode->Key(), wxT("key1"));
    if ( key1.Create() )
    {
        wxRegKey key2a(key1, wxT("key2a")), key2b(key1, wxT("key2b"));
        if ( key2a.Create() && key2b.Create() )
        {
            // put some values under the newly created keys
            key1.SetValue(wxT("first_term"), wxT("10"));
            key1.SetValue(wxT("second_term"), wxT("7"));
            key2a = wxT("this is the unnamed value");
            key2b.SetValue(wxT("sum"), 17);

            // refresh tree
            pNode->Refresh();
            wxLogStatus(wxT("Test keys successfully added."));
            return;
        }
    }

    wxLogError(wxT("Creation of test keys failed."));
}
Example #5
0
/*------------------------------------------------------------------------
 Start or stop monitoring the given object table for changes.
 Initially, and on any change to the given table, a dp_objectDelta_packet_t
 is generated and placed in a queue for retrieval with dpReceive.
 See anet.h for the definition of dp_objectDelta_packet_t.

 When called with monitor=TRUE, a burst of messages are generated giving 
 the initial contents of the table.
 When called with monitor=FALSE, no more messages of that sort will
 be generated, although there may still be some in the queue; you can
 call dpReceive until it returns empty to flush these out if desired.

 The key argument is a variable-length binary string that indicates
 what objects to start or stop monitoring.

 To start or stop monitoring sessions, use 
	keylen=1, key[0] = dp_KEY_SESSIONS
 To stop monitoring servers, use 
	keylen=1, key[0] = dp_KEY_SERVERPINGS,
 To start monitoring servers, use 
 	keylen=3;
	key[0] = dp_KEY_SERVERPINGS,
	key[1] = (char) dpGETSHORT_FIRSTBYTE(sessiontype);
	key[2] = (char) dpGETSHORT_SECONDBYTE(sessiontype);
 To monitor players, use
    char key[dp_MAX_KEYLEN+1];
	key[0] = dp_KEY_PLAYERS;
	dpGetSessionId(dp, &sess, &key[1], &keylen);
	keylen++;
 To request that latencies be included in player deltas for the current 
	session, use
	keylen = 1, key[0] = dp_KEY_PLAYER_LATENCIES;
	The latency in milliseconds will be placed in the latency field of
	the object delta packet.
	The frequency of latency measurements is influenced by the intervals
	set with dpSetPingIntervals.
	Deltas are synthesized locally and do not load the network.

 Note: keylen will be dp_MAX_KEYLEN+1 when requesting player deltas
 in IPX sessions!
------------------------------------------------------------------------*/
DP_API dp_result_t DP_APIX dpRequestObjectDeltas(
	dp_t *dp,
	int monitor,		/* TRUE to start, FALSE to stop */
	const char *key,
	int keylen)
{
	dp_result_t err;
	precondition(dp);
	precondition(key);
	precondition((keylen > 0) && (keylen <= dp_KEY_MAXLEN+1));

	DPRINT(("dpRequestObjectDeltas(,%d,%s)\n",
			monitor, key2a(key, keylen)));

	switch (key[0]) {
	case dp_KEY_SESSIONS:
		if (keylen != 1) {
			DPRINT(("dpRequestObjectDeltas: sessions: can't specify session type yet\n"));
			return dp_RES_BAD;
		}
		if (dp->monitor_object_sessions && monitor) 
			return dp_RES_ALREADY;
		/* Cause dp_sessions_cb to generate new messages */
		dp->monitor_object_sessions = monitor;
		if (monitor) {
			dptab_table_t *sesstab;
			int i;

			/* enumerate the existing sessions */
			/* If we're a standalone master, enum the mysessions table */
			if (bIAmStandaloneMaster(dp))
				sesstab = dp->mysessions;
			else
				sesstab = dp->sessions;
			DPRINT(("dpRequestObjectDeltas: table size %d\n", dptab_tableSize(sesstab)));
			for (i=0; i<dptab_tableSize(sesstab); i++) {
				char *s;
				dp_session_t sess;
				size_t len;
				char subkey[dptab_KEY_MAXLEN];
				int subkeylen;

				err = dptab_get_byindex(sesstab, i, (void **)&s, &len, subkey, &subkeylen);
				if (err != dp_RES_OK) {
					DPRINT(("dpRequestObjectDeltas: bug?\n"));
					dp_assertValid(dp);
					break;
				}
				/* Must unpack when retrieving records from dptab */
				dp_unpack_session(dp, subkey, subkeylen, s, len, &sess);
				err = dpSendObjectDelta(dp, dp_RES_CREATED, (dp_object_t *) &sess, sesstab, subkey, subkeylen);
				if (err != dp_RES_OK) {
					DPRINT(("dpRequestObjectDeltas: can't send object delta, err:%d\n", err));
				}
			}
		}
		return dp_RES_OK;
		break;

	case dp_KEY_SERVERPINGS:
		if (dp->monitor_object_servers && monitor) return dp_RES_ALREADY;
		/* Cause dpHandleServerPingResponsePacket to generate new messages */
		dp->monitor_object_servers = monitor;
		dp->serverping_interval = dp->dpio->clocksPerSec;
		dp->next_serverping = dp->now;
		dp->serverping_rx_count = 0;
		dp->serverping_rx_count_old = 0;
		if (monitor) {
			int i;

			if (keylen != 3) {
				DPRINT(("dpRequestObjectDeltas: must specify session type.\n"));
				return dp_RES_BAD;
			}
			dp->monitor_object_servers_sessType = dpMAKESHORT(key[1], key[2]);
			DPRINT(("dpRequestObjectDeltas: servers_sessType %d\n",dp->monitor_object_servers_sessType));
			
			/* enumerate the existing servers */
			for (i=0; i<dptab_tableSize(dp->serverpings); i++) {
				dp_serverInfo_t *server;
				size_t len;
				char subkey[dptab_KEY_MAXLEN];
				int subkeylen;

				err = dptab_get_byindex(dp->serverpings, i, (void **)&server, &len, subkey, &subkeylen);
				if (err != dp_RES_OK) {
					DPRINT(("dpRequestObjectDeltas: bug?\n"));
					dp_assertValid(dp);
					break;
				}
				err = dpSendObjectDelta(dp, dp_RES_CREATED, (dp_object_t *) server, dp->serverpings, subkey, subkeylen);
				if (err != dp_RES_OK) {
					DPRINT(("dpRequestObjectDeltas: can't send object delta, err:%d\n", err));
				}
			}
		}
		return dp_RES_OK;
		break;

	case dp_KEY_PLAYERS: 
		{
		dp_session_t sDesc;
		void *rplayers_context;
		dp_rplayers_enumEx_context_t rpecontext;
		size_t slen;
		dptab_table_t *rplayers;
		char pkey[3];
		int pkeylen;

		precondition(keylen == dp->dpio->myAdrLen + 3);
		pkeylen = 0;
		pkey[pkeylen++] = dp_KEY_PLAYERS;
		pkey[pkeylen++] = key[dp->dpio->myAdrLen+1];
		pkey[pkeylen++] = key[dp->dpio->myAdrLen+2];
		rplayers_context = NULL;
		if ((rplayers = dptab_getTable(dp->dt, pkey, pkeylen)))
			rplayers_context = dptab_getTableContext(rplayers, dp_rplayers_cb);
		if (!monitor) {
			/* caller no longer wants object delta messages for this table */
			if (!rplayers_context)
				return dp_RES_ALREADY;
			dptab_clearTableCallback(rplayers, dp_rplayers_cb);
			/* bug: should cancel subscription if remote */
			return dp_RES_OK;
		}
		/* caller wants to start getting object delta messages for this table */
		if (rplayers_context)
			return dp_RES_ALREADY;
		slen = sizeof(sDesc);
		err = dpGetSessionDescById(dp, key+1, &sDesc, &slen);
		if (err != dp_RES_OK) {
			DPRINT(("dpRequestObjectDeltas: dpGetSessionById returns %d\n", err));
			return err;
		}
		rpecontext.dp = dp;
		rpecontext.tab = rplayers;
		err = dpEnumPlayersEx(dp, &sDesc, dp_rplayers_enumEx_cb, &rpecontext, 0);
		if (err != dp_RES_OK) {
			DPRINT(("dpRequestObjectDeltas: dpEnumPlayers returns %d\n", err));
			return err;
		}
		rplayers = dptab_getTable(dp->dt, pkey, pkeylen);
		assert(rplayers);
		err = dptab_setTableCallback(rplayers, dp_rplayers_cb, dp);
		if (err != dp_RES_OK) {
			DPRINT(("dpRequestObjectDeltas: dptab_setTableCallback returns %d\n", err));
			return err;
		}
		return dp_RES_OK;
		}
		break;

	case dp_KEY_PLAYER_LATENCIES:
		if (keylen != 1) {
			DPRINT(("dpRequestObjectDeltas: player_latencies: bad keylen:%d != 1\n", keylen));
			return dp_RES_BAD;
		}
		dp->monitor_player_latencies = (monitor) ? TRUE : FALSE;
		return dp_RES_OK;
		break;
		
	case dp_KEY_SCORES:
		/* For the moment, only allow the default session type */
		if (keylen != 1) {
			DPRINT(("dpRequestObjectDeltas: scores: can't specify session type yet\n"));
			return dp_RES_BAD;
		}
		err = dpscore_client_subscribe(dp, dp->defaultSessionType);
		if (err != dp_RES_OK) {
			DPRINT(("dpRequestObjectDeltas: dpscore_client_subscribe returns err:%d\n", err));
			return dp_RES_BUG;
		}
		return dp_RES_OK;
		break; 
	default:
		;
	}

	DPRINT(("dpRequestObjectDeltas: unknown request\n"));
	return dp_RES_BAD;
}
Example #6
0
/*-------------------------------------------------------------------------
 This is called by the dptab_handlePacket when a new variable arrives or
 an old one is deleted.
 Note the time of the callback in the result block.
-------------------------------------------------------------------------*/
int dp_PASCAL
table_cb(
	dptab_t *dptab,			/* table owner */
	dptab_table_t *table,	/* table */
	playerHdl_t src,		/* */
	playerHdl_t dest,		/* */
	char *subkey,			/* key of variable */
	int subkeylen,			/* number of bytes in subkey */
	void *buf,				/* pointer to variable */
	size_t sent,
	size_t total,
	int seconds_left,
	void *context,			/* whatever we gave it */
	dp_result_t err)		/* operation completed upon variable */
{
	clock_t now = eclock();
	printf("Node %d: table_cb: type:%d  src h:%x  dest h:%x  table:%s  key:%s\n",
				results.thisHost, err, src, dest, key2a(table->key, table->keylen),
				key2a2(subkey, subkeylen));
	if (err == dp_RES_CREATED || err == dp_RES_CHANGED) {
		/*printf("table_cb: CREATED/CHANGED: src h:%x  dest h:%x  table:%s  key:%s\n",
				src, dest, key2a(table->key, table->keylen),
				key2a2(subkey, subkeylen));*/
		if ((dest == PLAYER_ME) && (sent == total)) {
			/* Got a variable */
			switch (subkey[0]) {
			case SUBKEY_SINGLE_SMALL:
				if(table->key[0] == 2) {
					results.gotSingleSmallTime = now;
					results.singleSmallTime = ((float)now - results.sentSingleSmallTime) / ECLOCKS_PER_SEC;
					/* Move this statement to right after last measurement taken */
					writeReport(logFile, &results);
				}
				break;
			case SUBKEY_SINGLE_LARGE:
				results.gotSingleLargeTime = now;
				break;
			case SUBKEY_MULTIPLE_SMALL:
				results.gotMultipleSmallTime = now;
				break;
			default:
				;
			}
			printf("Node %d: Got variable from h:%x; table %s, subkey %s; len %d\n",
				results.thisHost,
				src,
				key2a(table->key, table->keylen),
				key2a2(subkey, subkeylen),
				total);
		}
	} else if (err == dp_RES_CLOSED) {
		/*printf("table_cb: Deleted: src h:%x  dest h:%x\n", src, dest);*/
		if (dest == PLAYER_ME) {
			switch (subkey[0]) {
			case SUBKEY_SINGLE_SMALL:
				results.gotDeleteTime = now;
				results.deleteTime = ((float)now - results.sentDeleteTime) / ECLOCKS_PER_SEC;
				break;
			default:
				;
			}
			printf("Node %d: Got delete variable from h:%x; table %s, subkey %s\n",
				results.thisHost,
				src,
				key2a(table->key, table->keylen),
				key2a2(subkey, subkeylen));
		}
	}

	(void) dptab;
	(void) buf;
	(void) seconds_left;
	(void) context;
	return TRUE;
}