Beispiel #1
0
/*-----------------------------------------------------------------------
 Return the address of the given element of the table.
 If the table isn't that big, grow.
 Start all elements with 0.
 Returns NULL on failure.
-----------------------------------------------------------------------*/
void *dynatab_subscript_grow(dynatab_t *tab, int subscript)
{
	assert(tab != NULL);
	if (subscript < 0)
		return NULL;
	if (subscript >= tab->n_alloced) {
		void *newbuf;
		int new_n_alloced = tab->n_alloced + 16;
		if (new_n_alloced < subscript + 1)
			new_n_alloced = subscript + 16;

		if (tab->buf) 
			newbuf = dp_REALLOC(tab->buf, new_n_alloced * tab->unit);
		else
			newbuf = dp_MALLOC(new_n_alloced * tab->unit);
		if (!newbuf) return NULL;
		tab->buf = newbuf;
		/*  tab[n_alloced...new_n_alloced] = 0; */
		/*  memset(dynatab_subscript(tab, tab->n_alloced), 0, new area)); */
		memset((char *)tab->buf + (tab->n_alloced * tab->unit), 0,
			(new_n_alloced - tab->n_alloced) * tab->unit);
		tab->n_alloced = new_n_alloced;
	}
	if (tab->n_alloced < subscript + 1) {
		/*  BUG: Should have enough allocated by now. */
		return NULL;
	}
	if (tab->n_used < subscript + 1)
		tab->n_used = subscript + 1;

	return ((char *)tab->buf) + (subscript * tab->unit);
}
Beispiel #2
0
/*-----------------------------------------------------------------------
 Inserts a record into the table before the nth record.
 Grows the table.
 Returns NULL on failure.
-----------------------------------------------------------------------*/
void *dynatab_subscript_insert(dynatab_t *tab, int n)
{
	void *p;

	assert(tab != NULL);
	if (n < 0)
		return NULL;
	if (n > tab->n_used)
		return NULL;

	if (tab->n_used >= tab->n_alloced) {
		void *newbuf;
		int new_n_alloced = tab->n_alloced + 16;
		if (new_n_alloced < tab->n_used + 1)
			new_n_alloced = tab->n_used + 16;

		if (tab->buf) 
			newbuf = dp_REALLOC(tab->buf, new_n_alloced * tab->unit);
		else
			newbuf = dp_MALLOC(new_n_alloced * tab->unit);
		if (!newbuf) return NULL;
		tab->buf = newbuf;
		/*  tab[n_alloced...new_n_alloced] = 0; */
		/*  memset(dynatab_subscript(tab, tab->n_alloced), 0, new area)); */
		memset((char *)tab->buf + (tab->n_alloced * tab->unit), 0,
			(new_n_alloced - tab->n_alloced) * tab->unit);
		tab->n_alloced = new_n_alloced;
	}
	if (tab->n_alloced < tab->n_used + 1) {
		/*  BUG: Should have enough allocated by now. */
		return NULL;
	}

	/* Make pointer to new record */
	p = ((char *)tab->buf) + (n * tab->unit);

	/* If needed, move elements up to make space */
	if (n < tab->n_used) {
		void* dest = ((char *)p) + tab->unit;
		size_t count = (tab->n_used - n) * tab->unit;
		memmove(dest, p, count);
	}

	tab->n_used = tab->n_used + 1;

	/* Zero out new record */
	memset(p, 0, tab->unit);

	return ((char *)p);
}
Beispiel #3
0
/*--------------------------------------------------------------------------
 Process a network message generated by this module on another computer.

 Note: player deletion should be noticed by some other handler, and
 should cause a call to pv_deletePlayer().

 Large variables will be handled as follows:
 The buffer is broken into pieces.
 The first piece is sent with tag pv_PLAYERDATA_INITIAL_PACKET_ID
 and has a header structure describing the length, owner, and key of the
 incoming variables.
 Subsequent pieces are sent with tag pv_PLAYERDATA_BODY_PACKET_ID,
 and lack headers.

 When a first piece comes in, it goes into a holding area for that source;
 When middle or last pieces come in, they are appended to the holding area;
 When a last piece comes in, the holding area is copied to the real variable
 area, and the user code is informed.

 On success,
	if not the final packet,
		Returns dp_RES_EMPTY.
	else,
		Returns dp_RES_OK, and places a tagged dp_user_playerData_packet_t
		in buffer.
--------------------------------------------------------------------------*/
dp_result_t pv_handlePacket(pv_t *pv, size_t len, void *buf)
{
	dp_packetType_t *tag = (dp_packetType_t *)buf;
	pv_peer_t *peer;
	pv_var_t *pvar;
	dp_result_t err;
	dpid_t id;

#ifdef DPRINTBUFS
	DPRINT(("pv_handlePacket(pv, %d, ", len));
	dprint_buf(buf, len);
#endif
	if (!pv)
		return dp_RES_BUG;

	if (*tag == pv_PLAYERDATA_INITIAL_PACKET_ID) {
		pv_playerData_initial_packet_t *body = (pv_playerData_initial_packet_t *)((char *)buf + sizeof(dp_packetType_t));
		void *payload = ((char *)body) + sizeof(pv_playerData_initial_packet_t);
		size_t datalen = len - sizeof(dp_packetType_t) - sizeof(pv_playerData_initial_packet_t);

		if (datalen < 1 || datalen > pv_PLAYERDATA_INITIAL_MAXLEN)
			return dp_RES_BUG;
		/* call dpSwapPvUpdateInitial to byte swap body */
		dpSwapPvUpdateInitial(body);
		id = body->id;

		/* Locate the sender's holding area and check for sanity. */
		peer = (pv_peer_t *)assoctab_subscript(pv->peers, id);
		if (!peer) {
			/* No peer yet.  Create one.  Hope we can trust id. */
			peer = pv_addPlayer(pv, id);
			if (!peer) {
				DPRINT(("pv_handlePacket: pv_addPlayer returns NULL\n"));
				return dp_RES_NOMEM;
			}
		}
		pvar = &peer->incoming;
		if (peer->allocated < body->len) {
			void *p = dp_REALLOC(pvar->buf, body->len);
			if (!p) return dp_RES_NOMEM;
			pvar->buf = p;
			peer->allocated = body->len;
		}
		/* Clear the holding area & copy this in. */
		pvar->key = body->key;
		pvar->flags = body->flags;
		pvar->len = body->len;
		pvar->crc = body->crc;
		memcpy(pvar->type, body->type, sizeof(pvar->type));
		memcpy(pvar->buf, payload, datalen);
		pvar->offset = datalen;
		DPRINT(("pv_handlePacket: after 1st packet, offset is %d, len is %d\n", pvar->offset, pvar->len));

	} else if (*tag == pv_PLAYERDATA_BODY_PACKET_ID) {
		pv_playerData_body_packet_t *body = (pv_playerData_body_packet_t *)((char *)buf + sizeof(dp_packetType_t));
		void *payload = ((char *)body) + sizeof(pv_playerData_body_packet_t);
		size_t datalen = len - sizeof(dp_packetType_t) - sizeof(pv_playerData_body_packet_t);

		if (datalen < 1 || datalen > pv_PLAYERDATA_BODY_MAXLEN) {
			DPRINT(("pv_handlePacket: datalen\n"));
			return dp_RES_BUG;
		}
		/* call dpSwapPvUpdate to byte swap body */
		dpSwapPvUpdate(body);
		id = body->id;
		/* Locate the sender's holding area and check for sanity. */
		peer = (pv_peer_t *)assoctab_subscript(pv->peers, id);
		if (!peer) {
			DPRINT(("pv_handlePacket: no variables for player %d\n", id));
			return dp_RES_BAD;
		}
		pvar = &peer->incoming;
		if (peer->allocated < pvar->offset + datalen) {
			DPRINT(("pv_handlePacket: allocated %d need %d + %d\n", peer->allocated, pvar->offset, datalen));
			return dp_RES_BUG;
		}

		/* Append to holding area. */
		memcpy((char *)pvar->buf + pvar->offset, payload, datalen);
		pvar->offset += datalen;
		DPRINT(("pv_handlePacket: after: id %d, key %d, offset %d, len %d\n", id, pvar->key, pvar->offset, pvar->len));

	} else
		return dp_RES_EMPTY;	/* no error - but no pv packet recognized */

	if (pvar->offset == pvar->len) {
		/* The variable has arrived! Obey the value change it carries.
		 * Don't echo to other machines!
		 */
		long newcrc = dp_crc32((unsigned char *)pvar->buf, pvar->len);
		DPRINT(("pv_handlePacket: got crc %x\n", newcrc));
		if (newcrc != pvar->crc) {
			DPRINT(("pv_handlePacket: bad crc %x, expected %x!\n", newcrc, pvar->crc));
			return dp_RES_BAD;
		}

		err = pv_set(pv, id, pvar->key, pvar->len, pvar->buf, dp_PLAYERDATA_FLAG_NOFLOOD);
		DPRINT(("pv_handlePacket: called pv_set; returning err %d\n", err));
		if (err == dp_RES_OK) {
			dp_user_playerData_packet_t *body = (dp_user_playerData_packet_t *)((char *)buf + sizeof(dp_packetType_t));
			/* Notify local players - overwrite buffer with user packet. */
			*tag = dp_USER_PLAYERDATA_PACKET_ID;
			body->len = pvar->len;
			body->id = id;
			body->key = pvar->key;
			body->data = pvar->buf;
			return dp_RES_OK;
		}
		return err;
	}
	return dp_RES_EMPTY;
}