Home | History | Annotate | Download | only in libvncserver
      1 /*
      2  * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
      3  * Copyright (C) 2003 Sun Microsystems, Inc.
      4  *
      5  * This is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This software is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this software; if not, write to the Free Software
     17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
     18  * USA.
     19  */
     20 
     21 #include "zrleoutstream.h"
     22 #include <stdlib.h>
     23 
     24 #define ZRLE_IN_BUFFER_SIZE  16384
     25 #define ZRLE_OUT_BUFFER_SIZE 1024
     26 #undef  ZRLE_DEBUG
     27 
     28 static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size)
     29 {
     30   buffer->ptr = buffer->start = malloc(size);
     31   if (buffer->start == NULL) {
     32     buffer->end = NULL;
     33     return FALSE;
     34   }
     35 
     36   buffer->end = buffer->start + size;
     37 
     38   return TRUE;
     39 }
     40 
     41 static void zrleBufferFree(zrleBuffer *buffer)
     42 {
     43   if (buffer->start)
     44     free(buffer->start);
     45   buffer->start = buffer->ptr = buffer->end = NULL;
     46 }
     47 
     48 static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size)
     49 {
     50   int offset;
     51 
     52   size  += buffer->end - buffer->start;
     53   offset = ZRLE_BUFFER_LENGTH (buffer);
     54 
     55   buffer->start = realloc(buffer->start, size);
     56   if (!buffer->start) {
     57     return FALSE;
     58   }
     59 
     60   buffer->end = buffer->start + size;
     61   buffer->ptr = buffer->start + offset;
     62 
     63   return TRUE;
     64 }
     65 
     66 zrleOutStream *zrleOutStreamNew(void)
     67 {
     68   zrleOutStream *os;
     69 
     70   os = malloc(sizeof(zrleOutStream));
     71   if (os == NULL)
     72     return NULL;
     73 
     74   if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) {
     75     free(os);
     76     return NULL;
     77   }
     78 
     79   if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) {
     80     zrleBufferFree(&os->in);
     81     free(os);
     82     return NULL;
     83   }
     84 
     85   os->zs.zalloc = Z_NULL;
     86   os->zs.zfree  = Z_NULL;
     87   os->zs.opaque = Z_NULL;
     88   if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
     89     zrleBufferFree(&os->in);
     90     free(os);
     91     return NULL;
     92   }
     93 
     94   return os;
     95 }
     96 
     97 void zrleOutStreamFree (zrleOutStream *os)
     98 {
     99   deflateEnd(&os->zs);
    100   zrleBufferFree(&os->in);
    101   zrleBufferFree(&os->out);
    102   free(os);
    103 }
    104 
    105 rfbBool zrleOutStreamFlush(zrleOutStream *os)
    106 {
    107   os->zs.next_in = os->in.start;
    108   os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
    109 
    110 #ifdef ZRLE_DEBUG
    111   rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in);
    112 #endif
    113 
    114   while (os->zs.avail_in != 0) {
    115     do {
    116       int ret;
    117 
    118       if (os->out.ptr >= os->out.end &&
    119 	  !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
    120 	rfbLog("zrleOutStreamFlush: failed to grow output buffer\n");
    121 	return FALSE;
    122       }
    123 
    124       os->zs.next_out = os->out.ptr;
    125       os->zs.avail_out = os->out.end - os->out.ptr;
    126 
    127 #ifdef ZRLE_DEBUG
    128       rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n",
    129 	     os->zs.avail_in, os->zs.avail_out);
    130 #endif
    131 
    132       if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
    133 	rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
    134 	return FALSE;
    135       }
    136 
    137 #ifdef ZRLE_DEBUG
    138       rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n",
    139 	     os->zs.next_out - os->out.ptr);
    140 #endif
    141 
    142       os->out.ptr = os->zs.next_out;
    143     } while (os->zs.avail_out == 0);
    144   }
    145 
    146   os->in.ptr = os->in.start;
    147 
    148   return TRUE;
    149 }
    150 
    151 static int zrleOutStreamOverrun(zrleOutStream *os,
    152 				int            size)
    153 {
    154 #ifdef ZRLE_DEBUG
    155   rfbLog("zrleOutStreamOverrun\n");
    156 #endif
    157 
    158   while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) {
    159     os->zs.next_in = os->in.start;
    160     os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
    161 
    162     do {
    163       int ret;
    164 
    165       if (os->out.ptr >= os->out.end &&
    166 	  !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
    167 	rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n");
    168 	return FALSE;
    169       }
    170 
    171       os->zs.next_out = os->out.ptr;
    172       os->zs.avail_out = os->out.end - os->out.ptr;
    173 
    174 #ifdef ZRLE_DEBUG
    175       rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n",
    176 	     os->zs.avail_in, os->zs.avail_out);
    177 #endif
    178 
    179       if ((ret = deflate(&os->zs, 0)) != Z_OK) {
    180 	rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret);
    181 	return 0;
    182       }
    183 
    184 #ifdef ZRLE_DEBUG
    185       rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n",
    186 	     os->zs.next_out - os->out.ptr);
    187 #endif
    188 
    189       os->out.ptr = os->zs.next_out;
    190     } while (os->zs.avail_out == 0);
    191 
    192     /* output buffer not full */
    193 
    194     if (os->zs.avail_in == 0) {
    195       os->in.ptr = os->in.start;
    196     } else {
    197       /* but didn't consume all the data?  try shifting what's left to the
    198        * start of the buffer.
    199        */
    200       rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n");
    201       memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in);
    202       os->in.ptr -= os->zs.next_in - os->in.start;
    203     }
    204   }
    205 
    206   if (size > os->in.end - os->in.ptr)
    207     size = os->in.end - os->in.ptr;
    208 
    209   return size;
    210 }
    211 
    212 static int zrleOutStreamCheck(zrleOutStream *os, int size)
    213 {
    214   if (os->in.ptr + size > os->in.end) {
    215     return zrleOutStreamOverrun(os, size);
    216   }
    217   return size;
    218 }
    219 
    220 void zrleOutStreamWriteBytes(zrleOutStream *os,
    221 			     const zrle_U8 *data,
    222 			     int            length)
    223 {
    224   const zrle_U8* dataEnd = data + length;
    225   while (data < dataEnd) {
    226     int n = zrleOutStreamCheck(os, dataEnd - data);
    227     memcpy(os->in.ptr, data, n);
    228     os->in.ptr += n;
    229     data += n;
    230   }
    231 }
    232 
    233 void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u)
    234 {
    235   zrleOutStreamCheck(os, 1);
    236   *os->in.ptr++ = u;
    237 }
    238 
    239 void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u)
    240 {
    241   zrleOutStreamCheck(os, 1);
    242   *os->in.ptr++ = u;
    243 }
    244 
    245 void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u)
    246 {
    247   zrleOutStreamCheck(os, 2);
    248   *os->in.ptr++ = ((zrle_U8*)&u)[0];
    249   *os->in.ptr++ = ((zrle_U8*)&u)[1];
    250 }
    251 
    252 void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u)
    253 {
    254   zrleOutStreamCheck(os, 4);
    255   *os->in.ptr++ = ((zrle_U8*)&u)[0];
    256   *os->in.ptr++ = ((zrle_U8*)&u)[1];
    257   *os->in.ptr++ = ((zrle_U8*)&u)[2];
    258   *os->in.ptr++ = ((zrle_U8*)&u)[3];
    259 }
    260 
    261 void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u)
    262 {
    263   zrleOutStreamCheck(os, 3);
    264   *os->in.ptr++ = ((zrle_U8*)&u)[0];
    265   *os->in.ptr++ = ((zrle_U8*)&u)[1];
    266   *os->in.ptr++ = ((zrle_U8*)&u)[2];
    267 }
    268 
    269 void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u)
    270 {
    271   zrleOutStreamCheck(os, 3);
    272   *os->in.ptr++ = ((zrle_U8*)&u)[1];
    273   *os->in.ptr++ = ((zrle_U8*)&u)[2];
    274   *os->in.ptr++ = ((zrle_U8*)&u)[3];
    275 }
    276