/******************************************************************** Insert an item into the queue. *********************************************************************/ void pq_insert(struct pqueue *q, pq_data_t datum, int datum_priority) { int i; fc_assert_ret(NULL != q); /* allocate more memory if necessary */ if (q->size >= q->avail) { int newsize = q->size + q->step; q->cells = fc_realloc(q->cells, sizeof(pq_data_t) * newsize); q->priorities = fc_realloc(q->priorities, sizeof(int) * newsize); q->avail = newsize; } /* insert item */ i = q->size++; while (i > 1 && q->priorities[i / 2] < datum_priority) { q->cells[i] = q->cells[i / 2]; q->priorities[i] = q->priorities[i / 2]; i /= 2; } q->cells[i] = datum; q->priorities[i] = datum_priority; }
/************************************************************************** Set one auth option. **************************************************************************/ static bool set_auth_option(struct auth_option *target, const char *value, enum auth_option_source source) { if (value != NULL && !strcmp(target->name, "port")) { /* Port value must be all numeric. */ int i; for (i = 0; value[i] != '\0'; i++) { if (value[i] < '0' || value[i] > '9') { freelog(LOG_ERROR, _("Illegal value for auth port: \"%s\""), value); return FALSE; } } } if (value == NULL) { if (target->value != NULL) { free(target->value); } target->value = NULL; } else { target->value = fc_realloc(target->value, strlen(value) + 1); memcpy(target->value, value, strlen(value) + 1); } target->source = source; return TRUE; }
/************************************************************************** Initialize ai traits for player **************************************************************************/ void ai_traits_init(struct player *pplayer) { enum trait tr; pplayer->ai_common.traits = fc_realloc(pplayer->ai_common.traits, sizeof(struct ai_trait) * TRAIT_COUNT); for (tr = trait_begin(); tr != trait_end(); tr = trait_next(tr)) { pplayer->ai_common.traits[tr].mod = 0; } }
/************************************************************************** ... **************************************************************************/ static bool buffer_ensure_free_extra_space(struct socket_packet_buffer *buf, int extra_space) { /* room for more? */ if (buf->nsize - buf->ndata < extra_space) { buf->nsize = buf->ndata + extra_space; /* added this check so we don't gobble up too much mem */ if (buf->nsize > MAX_LEN_BUFFER) { return FALSE; } buf->data = (unsigned char *) fc_realloc(buf->data, buf->nsize); } return TRUE; }
/********************************************************************** Check that astr has enough size to hold n, and realloc to a bigger size if necessary. Here n must be big enough to include the trailing ascii-null if required. The requested n is stored in astr->n. The actual amount allocated may be larger than n, and is stored in astr->n_alloc. ***********************************************************************/ void astr_minsize(struct astring *astr, size_t n) { int n1; bool was_null = (astr->n == 0); assert(astr != NULL); astr->n = n; if (n <= astr->n_alloc) { return; } /* allocated more if this is only a small increase on before: */ n1 = (3*(astr->n_alloc+10)) / 2; astr->n_alloc = (n > n1) ? n : n1; astr->str = (char *)fc_realloc(astr->str, astr->n_alloc); if (was_null) { astr_clear(astr); } }
/*************************************************************************** Resize a dynamic bitvector. Create it if needed. ***************************************************************************/ void dbv_resize(struct dbv *pdbv, int bits) { fc_assert_ret(bits > 0 && bits < MAX_DBV_LENGTH); if (pdbv->vec == NULL) { /* Initialise a new dbv. */ dbv_init(pdbv, bits); } else { /* Resize an existing dbv. */ fc_assert_ret(pdbv->bits != 0); if (bits != pdbv->bits) { pdbv->bits = bits; pdbv->vec = fc_realloc(pdbv->vec, _BV_BYTES(pdbv->bits) * sizeof(*pdbv->vec)); } dbv_clr_all(pdbv); } }
/************************************************************************** ... **************************************************************************/ SDL_String16 * copy_chars_to_string16(SDL_String16 *pString, const char *pCharString) { size_t n; fc_assert_ret_val(pString != NULL, NULL); fc_assert_ret_val(pCharString != NULL, NULL); n = (strlen(pCharString) + 1) * 2; if (n > pString->n_alloc) { /* allocated more if this is only a small increase on before: */ size_t n1 = (3 * pString->n_alloc) / 2; pString->n_alloc = (n > n1) ? n : n1; pString->text = fc_realloc(pString->text, pString->n_alloc); } convertcopy_to_utf16(pString->text, pString->n_alloc, pCharString); return pString; }
/************************************************************************** presult indicates if there is more packets in the cache. We return result instead of just testing if the returning package is NULL as we sometimes return a NULL packet even if everything is OK (receive_packet_goto_route). **************************************************************************/ void *get_packet_from_connection(struct connection *pc, enum packet_type *ptype, bool * presult) { int len_read; int whole_packet_len; struct { enum packet_type type; int itype; } utype; struct data_in din; #ifdef USE_COMPRESSION bool compressed_packet = FALSE; int header_size = 0; #endif *presult = FALSE; if (!pc->used) { return NULL; /* connection was closed, stop reading */ } if (pc->buffer->ndata < 3) { return NULL; /* length and type not read */ } dio_input_init(&din, pc->buffer->data, pc->buffer->ndata); dio_get_uint16(&din, &len_read); /* The non-compressed case */ whole_packet_len = len_read; #ifdef USE_COMPRESSION if (len_read == JUMBO_SIZE) { compressed_packet = TRUE; header_size = 6; if (dio_input_remaining(&din) >= 4) { dio_get_uint32(&din, &whole_packet_len); log_compress("COMPRESS: got a jumbo packet of size %d", whole_packet_len); } else { /* to return NULL below */ whole_packet_len = 6; } } else if (len_read >= COMPRESSION_BORDER) { compressed_packet = TRUE; header_size = 2; whole_packet_len = len_read - COMPRESSION_BORDER; log_compress("COMPRESS: got a normal packet of size %d", whole_packet_len); } #endif if ((unsigned)whole_packet_len > pc->buffer->ndata) { return NULL; /* not all data has been read */ } #ifdef USE_COMPRESSION if (compressed_packet) { uLong compressed_size = whole_packet_len - header_size; /* * We don't know the decompressed size. We assume a bad case * here: an expansion by an factor of 100. */ unsigned long int decompressed_size = 100 * compressed_size; void *decompressed = fc_malloc(decompressed_size); int error; struct socket_packet_buffer *buffer = pc->buffer; error = uncompress(decompressed, &decompressed_size, ADD_TO_POINTER(buffer->data, header_size), compressed_size); if (error != Z_OK) { log_verbose("Uncompressing of the packet stream failed. " "The connection will be closed now."); connection_close(pc, _("decoding error")); return NULL; } buffer->ndata -= whole_packet_len; /* * Remove the packet with the compressed data and shift all the * remaining data to the front. */ memmove(buffer->data, buffer->data + whole_packet_len, buffer->ndata); if (buffer->ndata + decompressed_size > buffer->nsize) { buffer->nsize += decompressed_size; buffer->data = fc_realloc(buffer->data, buffer->nsize); } /* * Make place for the uncompressed data by moving the remaining * data. */ memmove(buffer->data + decompressed_size, buffer->data, buffer->ndata); /* * Copy the uncompressed data. */ memcpy(buffer->data, decompressed, decompressed_size); free(decompressed); buffer->ndata += decompressed_size; log_compress("COMPRESS: decompressed %ld into %ld", compressed_size, decompressed_size); return get_packet_from_connection(pc, ptype, presult); } #endif /* * At this point the packet is a plain uncompressed one. These have * to have to be at least 3 bytes in size. */ if (whole_packet_len < 3) { log_verbose("The packet stream is corrupt. The connection " "will be closed now."); connection_close(pc, _("decoding error")); return NULL; } dio_get_uint8(&din, &utype.itype); utype.type = utype.itype; log_packet("got packet type=(%s)%d len=%d from %s", packet_name(utype.type), utype.itype, whole_packet_len, is_server() ? pc->username : "******"); *ptype = utype.type; *presult = TRUE; if (pc->incoming_packet_notify) { pc->incoming_packet_notify(pc, utype.type, whole_packet_len); } #if PACKET_SIZE_STATISTICS { static struct { int counter; int size; } packets_stats[PACKET_LAST]; static int packet_counter = 0; int packet_type = utype.itype; int size = whole_packet_len; if (!packet_counter) { int i; for (i = 0; i < PACKET_LAST; i++) { packets_stats[i].counter = 0; packets_stats[i].size = 0; } } packets_stats[packet_type].counter++; packets_stats[packet_type].size += size; packet_counter++; if (packet_counter % 100 == 0) { int i, sum = 0; log_test("Received packets:"); for (i = 0; i < PACKET_LAST; i++) { if (packets_stats[i].counter == 0) continue; sum += packets_stats[i].size; log_test(" [%-25.25s %3d]: %6d packets; %8d bytes total; " "%5d bytes/packet average", packet_name(i), i, packets_stats[i].counter, packets_stats[i].size, packets_stats[i].size / packets_stats[i].counter); } log_test("received %d bytes in %d packets;average size " "per packet %d bytes", sum, packet_counter, sum / packet_counter); } } #endif return get_packet_from_connection_helper(pc, utype.type); }