123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- #include "MonoPosixHelper.h"
- #include <string.h>
- #include <stdlib.h>
- #include "../external/zlib/zlib.h"
- #include "vm/Exception.h"
- #define BUFFER_SIZE 4096
- #define ARGUMENT_ERROR -10
- #define IO_ERROR -11
- typedef int32_t (*read_write_func)(intptr_t buffer, int32_t length, intptr_t gchandle);
- struct ZStream
- {
- z_stream *stream;
- uint8_t *buffer;
- read_write_func func;
- void *gchandle;
- uint8_t compress;
- uint8_t eof;
- uint32_t total_in;
- };
- static int32_t write_to_managed(ZStream *stream)
- {
- int32_t n;
- z_stream *zs;
- zs = stream->stream;
- if (zs->avail_out != BUFFER_SIZE)
- {
- intptr_t buffer_ptr = reinterpret_cast<intptr_t>(stream->buffer);
- intptr_t gchandle_ptr = reinterpret_cast<intptr_t>(stream->gchandle);
- n = stream->func(buffer_ptr, BUFFER_SIZE - zs->avail_out, gchandle_ptr);
- zs->next_out = stream->buffer;
- zs->avail_out = BUFFER_SIZE;
- if (n < 0)
- return IO_ERROR;
- }
- return 0;
- }
- static int32_t flush_internal(ZStream *stream, bool is_final)
- {
- int32_t status;
- if (!stream->compress)
- return 0;
- if (!is_final && stream->stream->avail_in != 0)
- {
- status = deflate(stream->stream, Z_PARTIAL_FLUSH);
- if (status != Z_OK && status != Z_STREAM_END)
- return status;
- }
- return write_to_managed(stream);
- }
- static void *z_alloc(void *opaque, uint32_t nitems, uint32_t item_size)
- {
- return calloc(nitems, item_size);
- }
- static void z_free(void *opaque, void *ptr)
- {
- free(ptr);
- }
- intptr_t CreateZStream(int32_t compress, uint8_t gzip, Il2CppMethodPointer func_ptr, intptr_t gchandle)
- {
- z_stream *z;
- int32_t retval;
- ZStream *result;
- intptr_t result_ptr = 0;
- read_write_func func = (read_write_func)func_ptr;
- if (func == NULL)
- return result_ptr;
- #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
- // Older versions of zlib do not support raw deflate or gzip
- return NULL;
- #endif
- z = (z_stream*)calloc(1, sizeof(z_stream));
- if (compress)
- {
- retval = deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY);
- }
- else
- {
- retval = inflateInit2(z, gzip ? 31 : -15);
- }
- if (retval != Z_OK)
- {
- free(z);
- return result_ptr;
- }
- z->zalloc = z_alloc;
- z->zfree = z_free;
- result = (ZStream*)calloc(1, sizeof(ZStream));
- result->stream = z;
- result->func = func;
- result->gchandle = reinterpret_cast<void*>(gchandle);
- result->compress = compress;
- result->buffer = (uint8_t*)malloc(BUFFER_SIZE * sizeof(uint8_t));
- result->stream->next_out = result->buffer;
- result->stream->avail_out = BUFFER_SIZE;
- result->stream->total_in = 0;
- result_ptr = reinterpret_cast<intptr_t>(result);
- return result_ptr;
- }
- int32_t CloseZStream(intptr_t zstream)
- {
- int32_t status;
- int32_t flush_status;
- ZStream *stream = reinterpret_cast<ZStream*>(zstream);
- if (stream == NULL)
- return ARGUMENT_ERROR;
- status = 0;
- if (stream->compress)
- {
- if (stream->stream->total_in > 0)
- {
- do
- {
- status = deflate(stream->stream, Z_FINISH);
- flush_status = flush_internal(stream, true);
- }
- while (status == Z_OK); /* We want Z_STREAM_END or error here here */
- if (status == Z_STREAM_END)
- status = flush_status;
- }
- deflateEnd(stream->stream);
- }
- else
- {
- inflateEnd(stream->stream);
- }
- free(stream->buffer);
- free(stream->stream);
- memset(stream, 0, sizeof(ZStream));
- free(stream);
- return status;
- }
- int32_t Flush(intptr_t zstream)
- {
- ZStream *stream = (ZStream*)zstream;
- return flush_internal(stream, false);
- }
- int32_t ReadZStream(intptr_t zstream, intptr_t zbuffer, int32_t length)
- {
- int32_t n;
- int32_t status;
- z_stream *zs;
- ZStream *stream = (ZStream*)zstream;
- uint8_t *buffer = (uint8_t*)zbuffer;
- if (stream == NULL || buffer == NULL || length < 0)
- return ARGUMENT_ERROR;
- if (stream->eof)
- return 0;
- zs = stream->stream;
- zs->next_out = buffer;
- zs->avail_out = length;
- while (zs->avail_out > 0)
- {
- if (zs->avail_in == 0)
- {
- intptr_t buffer_ptr = reinterpret_cast<intptr_t>(stream->buffer);
- intptr_t gchandle_ptr = reinterpret_cast<intptr_t>(stream->gchandle);
- n = stream->func(buffer_ptr, BUFFER_SIZE, gchandle_ptr);
- if (n < 0)
- n = 0;
- // Even if avail_in reports zero, and we have no more data from the stream,
- // inflate may have more data to return. So we cannot break here and need to
- // keep calling inflate until it returns Z_STREAM_END.
- stream->total_in += n;
- zs->next_in = stream->buffer;
- zs->avail_in = n;
- }
- status = inflate(stream->stream, Z_SYNC_FLUSH);
- if (status == Z_STREAM_END)
- {
- stream->eof = 1;
- break;
- }
- else if (status == Z_BUF_ERROR && stream->total_in == zs->total_in)
- {
- if (zs->avail_in != 0)
- {
- stream->eof = 1;
- }
- break;
- }
- else if (status != Z_OK)
- {
- return status;
- }
- }
- return length - zs->avail_out;
- }
- int32_t WriteZStream(intptr_t zstream, intptr_t zbuffer, int32_t length)
- {
- int32_t n;
- int32_t status;
- z_stream *zs;
- ZStream *stream = (ZStream*)zstream;
- uint8_t *buffer = (uint8_t*)zbuffer;
- if (stream == NULL || buffer == NULL || length < 0)
- return ARGUMENT_ERROR;
- if (stream->eof)
- return IO_ERROR;
- zs = stream->stream;
- zs->next_in = buffer;
- zs->avail_in = length;
- while (zs->avail_in > 0)
- {
- if (zs->avail_out == 0)
- {
- zs->next_out = stream->buffer;
- zs->avail_out = BUFFER_SIZE;
- }
- status = deflate(stream->stream, Z_NO_FLUSH);
- if (status != Z_OK && status != Z_STREAM_END)
- return status;
- if (zs->avail_out == 0)
- {
- n = write_to_managed(stream);
- if (n < 0)
- return n;
- }
- }
- return length;
- }
- // The following methods are used by LinuxNetworkChange
- // Which the implementation for System.Net.NetworkInformation.NetworkChange on linux
- // These are here we throw a NotImplemented exception rather than getting an entry point not found
- // We could probably port this if we hard the time
- intptr_t CreateNLSocket()
- {
- IL2CPP_NOT_IMPLEMENTED(CreateNLSocket);
- NOT_SUPPORTED_IL2CPP(CreateNLSocket, Not implemented);
- return 0;
- }
- int32_t ReadEvents(intptr_t sock, intptr_t buffer, int32_t count, int32_t size)
- {
- IL2CPP_NOT_IMPLEMENTED(ReadEvents);
- NOT_SUPPORTED_IL2CPP(ReadEvents, Not implemented);
- return 0;
- }
- intptr_t CloseNLSocket(intptr_t sock)
- {
- IL2CPP_NOT_IMPLEMENTED(CloseNLSocket);
- NOT_SUPPORTED_IL2CPP(CloseNLSocket, Not implemented);
- return 0;
- }
|