static int common_close(SDL_RWops *rw) { PRINT("common_close\n"); if(rw) { ZData *z = ZDATA(rw); PRINT("T = %i\n", z->type); if(z->type == TYPE_DEFLATE) { deflate_flush(z); deflateEnd(z->stream); free(z->buffer_aux); } else { inflateEnd(z->stream); } free(z->buffer); free(z->stream); if(z->autoclose) { SDL_RWclose(z->wrapped); } free(z); SDL_FreeRW(rw); } return 0; }
static size_t deflate_write(SDL_RWops *rw, const void *ptr, size_t size, size_t maxnum) { ZData *z = ZDATA(rw); size_t totalsize = size * maxnum; size_t available; size_t remaining = totalsize; size_t offset = 0; while(remaining) { available = z->buffer_size - (z->buffer_ptr - z->buffer); size_t copysize = remaining > available ? available : remaining; PRINT("avail = %lu; copysize = %lu\n", available, copysize); if(available) { remaining -= copysize; memcpy(z->buffer_ptr, (uint8_t*)ptr + offset, copysize); printbuf(z->buffer_ptr, copysize); offset += copysize; z->buffer_ptr += copysize; z->pos += copysize; } else { deflate_flush(z); } } return maxnum; }
/** * Flush compression and send whatever we got so far. */ static void deflate_flush_send(txdrv_t *tx) { struct attr *attr = tx->opaque; /* * During deflate_flush(), we can fill the current buffer, then call * deflate_rotate_and_send() and finish the flush. But it is possible * that the whole send buffer does not get sent immediately. Therefore, * we need to recheck for attr->send_idx. */ if (deflate_flush(tx)) { if (-1 == attr->send_idx) { /* No write pending */ struct buffer *b = &attr->buf[attr->fill_idx]; if (b->rptr != b->wptr) /* Something to send */ deflate_rotate_and_send(tx); } } }
/** * Compress as much data as possible to the output buffer, sending data * as we go along. * * @return the amount of input bytes that were consumed ("added"), -1 on error. */ static int deflate_add(txdrv_t *tx, const void *data, int len) { struct attr *attr = tx->opaque; z_streamp outz = attr->outz; int added = 0; if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) given %u bytes (buffer #%d, nagle %s, " "unflushed %zu) [%c%c]%s", G_STRFUNC, gnet_host_to_string(&tx->host), len, attr->fill_idx, (attr->flags & DF_NAGLE) ? "on" : "off", attr->unflushed, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-', (tx->flags & TX_ERROR) ? " ERROR" : ""); } /* * If an error was already reported, the whole deflate stream is dead * and we cannot accept any more data. */ if G_UNLIKELY(tx->flags & TX_ERROR) return -1; while (added < len) { struct buffer *b = &attr->buf[attr->fill_idx]; /* Buffer we fill */ int ret; int old_added = added; bool flush_started = (attr->flags & DF_FLUSH) ? TRUE : FALSE; int old_avail; const char *in, *old_in; /* * Prepare call to deflate(). */ outz->next_out = cast_to_pointer(b->wptr); outz->avail_out = old_avail = b->end - b->wptr; in = data; old_in = &in[added]; outz->next_in = deconstify_pointer(old_in); outz->avail_in = len - added; g_assert(outz->avail_out > 0); g_assert(outz->avail_in > 0); /* * Compress data. * * If we previously started to flush, continue the operation, now * that we have more room available for the output. */ ret = deflate(outz, flush_started ? Z_SYNC_FLUSH : 0); if (Z_OK != ret) { attr->flags |= DF_SHUTDOWN; (*attr->cb->shutdown)(tx->owner, "Compression failed: %s", zlib_strerror(ret)); return -1; } /* * Update the parameters. */ b->wptr = cast_to_pointer(outz->next_out); added = ptr_diff(outz->next_in, in); g_assert(added >= old_added); attr->unflushed += added - old_added; attr->flushed += old_avail - outz->avail_out; if (NULL != attr->cb->add_tx_deflated) attr->cb->add_tx_deflated(tx->owner, old_avail - outz->avail_out); if (attr->gzip.enabled) { size_t r; r = ptr_diff(outz->next_in, old_in); attr->gzip.size += r; attr->gzip.crc = crc32(attr->gzip.crc, cast_to_constpointer(old_in), r); } if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) deflated %d bytes into %d " "(buffer #%d, nagle %s, flushed %zu, unflushed %zu) [%c%c]", G_STRFUNC, gnet_host_to_string(&tx->host), added, old_avail - outz->avail_out, attr->fill_idx, (attr->flags & DF_NAGLE) ? "on" : "off", attr->flushed, attr->unflushed, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-'); } /* * If we filled the output buffer, check whether we have a pending * send buffer. If we do, we cannot process more data. Otherwise * send it now and continue. */ if (0 == outz->avail_out) { if (attr->send_idx >= 0) { deflate_set_flowc(tx, TRUE); /* Enter flow control */ return added; } deflate_rotate_and_send(tx); /* Can set TX_ERROR */ if (tx->flags & TX_ERROR) return -1; } /* * If we were flushing and we consumed all the input, then * the flush is done and we're starting normal compression again. * * This must be done after we made sure that we had enough output * space avaialable. */ if (flush_started && 0 == outz->avail_in) deflate_flushed(tx); } g_assert(0 == outz->avail_in); /* * Start Nagle if not already on. */ if (attr->flags & DF_NAGLE) deflate_nagle_delay(tx); else deflate_nagle_start(tx); /* * We're going to ask for a flush if not already started yet and the * amount of bytes we have written since the last flush is greater * than attr->buffer_flush. */ if (attr->unflushed > attr->buffer_flush) { if (!deflate_flush(tx)) return -1; } return added; }