~ubuntu-branches/ubuntu/wily/trafficserver/wily

« back to all changes in this revision

Viewing changes to example/gzip-transform/gzip.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2012-12-17 22:28:16 UTC
  • mfrom: (5.1.8 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20121217222816-7xwjsx5k76zkb63d
Tags: 3.2.0-1ubuntu1
* Revert FreeBSD strerror_r() fixes that give errors with glibc 2.16.
* Apply patch from Konstantinos Margaritis to define barriers on ARM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** @file
2
 
 
3
 
  Transforms content using gzip
4
 
 
5
 
  @section license License
6
 
 
7
 
  Licensed to the Apache Software Foundation (ASF) under one
8
 
  or more contributor license agreements.  See the NOTICE file
9
 
  distributed with this work for additional information
10
 
  regarding copyright ownership.  The ASF licenses this file
11
 
  to you under the Apache License, Version 2.0 (the
12
 
  "License"); you may not use this file except in compliance
13
 
  with the License.  You may obtain a copy of the License at
14
 
 
15
 
      http://www.apache.org/licenses/LICENSE-2.0
16
 
 
17
 
  Unless required by applicable law or agreed to in writing, software
18
 
  distributed under the License is distributed on an "AS IS" BASIS,
19
 
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 
  See the License for the specific language governing permissions and
21
 
  limitations under the License.
22
 
 */
23
 
 
24
 
#include <limits.h>
25
 
#include <stdio.h>
26
 
#include <errno.h>
27
 
#include <fcntl.h>
28
 
#include <sys/file.h>
29
 
#include <sys/types.h>
30
 
#include <stdlib.h>
31
 
#include <string.h>
32
 
#include <zlib.h>
33
 
#include <assert.h>
34
 
#include <ts/ts.h>
35
 
 
36
 
#define DICT_PATH_MAX 512
37
 
#define DICT_ENTRY_MAX 2048
38
 
 
39
 
typedef struct
40
 
{
41
 
  TSHttpTxn txn;
42
 
  TSVIO output_vio;
43
 
  TSIOBuffer output_buffer;
44
 
  TSIOBufferReader output_reader;
45
 
  int output_length;
46
 
  z_stream zstrm;
47
 
  uLong crc;
48
 
  int state;
49
 
} GzipData;
50
 
 
51
 
 
52
 
char preload_file[1024];
53
 
uLong dictId;
54
 
int preload = 0;
55
 
char dictionary[800000];
56
 
 
57
 
void
58
 
load_dictionary(char *dict, uLong * adler)
59
 
{
60
 
  FILE *fp;
61
 
  int i = 0;
62
 
 
63
 
  fp = fopen(preload_file, "r");
64
 
  if (!fp) {
65
 
    TSError("gzip-transform: ERROR: Unable to open dict file %s\n", preload_file);
66
 
    exit(0);
67
 
  }
68
 
 
69
 
  /* dict = (char *) calloc(8000,sizeof(char)); */
70
 
 
71
 
  i = 0;
72
 
  while (!feof(fp)) {
73
 
    if (fscanf(fp, "%s\n", dict + i) == 1) {
74
 
      i = strlen(dict);
75
 
      strcat(dict + i, " ");
76
 
      i++;
77
 
    }
78
 
  }
79
 
  dict[i - 1] = '\0';
80
 
 
81
 
  /* TODO get the adler compute right */
82
 
  *adler = adler32(*adler, (const Byte *) dict, sizeof(dict));
83
 
}
84
 
 
85
 
static voidpf
86
 
gzip_alloc(voidpf opaque, uInt items, uInt size)
87
 
{
88
 
  return (voidpf) TSmalloc(items * size);
89
 
}
90
 
 
91
 
 
92
 
static void
93
 
gzip_free(voidpf opaque, voidpf address)
94
 
{
95
 
  TSfree(address);
96
 
}
97
 
 
98
 
 
99
 
static GzipData *
100
 
gzip_data_alloc()
101
 
{
102
 
  GzipData *data;
103
 
  int err;
104
 
 
105
 
  data = (GzipData *) TSmalloc(sizeof(GzipData));
106
 
  data->output_vio = NULL;
107
 
  data->output_buffer = NULL;
108
 
  data->output_reader = NULL;
109
 
  data->output_length = 0;
110
 
  data->state = 0;
111
 
  data->crc = crc32(0L, Z_NULL, 0);
112
 
 
113
 
  data->zstrm.next_in = Z_NULL;
114
 
  data->zstrm.avail_in = 0;
115
 
  data->zstrm.total_in = 0;
116
 
  data->zstrm.next_out = Z_NULL;
117
 
  data->zstrm.avail_out = 0;
118
 
  data->zstrm.total_out = 0;
119
 
  data->zstrm.zalloc = gzip_alloc;
120
 
  data->zstrm.zfree = gzip_free;
121
 
  data->zstrm.opaque = (voidpf) 0;
122
 
  data->zstrm.data_type = Z_ASCII;
123
 
 
124
 
  err = deflateInit(&data->zstrm, Z_BEST_COMPRESSION);
125
 
 
126
 
  if (err != Z_OK) {
127
 
    TSError("gzip-transform: ERROR: deflateInit (%d)!", err);
128
 
    exit(1);
129
 
  }
130
 
 
131
 
  if (preload) {
132
 
    assert(&data->zstrm);
133
 
    err = deflateSetDictionary(&data->zstrm, (const Bytef *) dictionary, strlen(dictionary));
134
 
    if (err != Z_OK) {
135
 
      TSError("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
136
 
    }
137
 
  }
138
 
 
139
 
  return data;
140
 
}
141
 
 
142
 
 
143
 
static void
144
 
gzip_data_destroy(GzipData * data)
145
 
{
146
 
  int err;
147
 
 
148
 
  if (data) {
149
 
    err = deflateEnd(&data->zstrm);
150
 
    if (err != Z_OK) {
151
 
      TSError("gzip-transform: ERROR: deflateEnd (%d)!", err);
152
 
    }
153
 
 
154
 
    if (data->output_buffer)
155
 
      TSIOBufferDestroy(data->output_buffer);
156
 
    TSfree(data);
157
 
  }
158
 
}
159
 
 
160
 
 
161
 
static void
162
 
gzip_transform_init(TSCont contp, GzipData * data)
163
 
{
164
 
  TSVConn output_conn;
165
 
  TSMBuffer bufp;
166
 
  TSMLoc hdr_loc;
167
 
  TSMLoc ce_loc;               /* for the content encoding mime field */
168
 
 
169
 
  data->state = 1;
170
 
 
171
 
  /*
172
 
   * Mark the output data as having gzip content encoding
173
 
   */
174
 
  TSHttpTxnTransformRespGet(data->txn, &bufp, &hdr_loc);
175
 
  TSMimeHdrFieldCreate(bufp, hdr_loc, &ce_loc); /* Probably should check for errors */
176
 
  TSMimeHdrFieldNameSet(bufp, hdr_loc, ce_loc, "Content-Encoding", -1);
177
 
  TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, ce_loc, -1, "deflate", -1);
178
 
  TSMimeHdrFieldAppend(bufp, hdr_loc, ce_loc);
179
 
  TSHandleMLocRelease(bufp, hdr_loc, ce_loc);
180
 
  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
181
 
 
182
 
 
183
 
  /* Get the output connection where we'll write data to. */
184
 
  output_conn = TSTransformOutputVConnGet(contp);
185
 
 
186
 
  data->output_buffer = TSIOBufferCreate();
187
 
  data->output_reader = TSIOBufferReaderAlloc(data->output_buffer);
188
 
  data->output_vio = TSVConnWrite(output_conn, contp, data->output_reader, INT64_MAX);
189
 
}
190
 
 
191
 
 
192
 
static void
193
 
gzip_transform_one(GzipData * data, TSIOBufferReader input_reader, int amount)
194
 
{
195
 
  TSIOBufferBlock blkp;
196
 
  const char *ibuf;
197
 
  char *obuf;
198
 
  int64_t ilength, olength;
199
 
  int err;
200
 
 
201
 
  while (amount > 0) {
202
 
    blkp = TSIOBufferReaderStart(input_reader);
203
 
    ibuf = TSIOBufferBlockReadStart(blkp, input_reader, &ilength);
204
 
 
205
 
    if (ilength > amount) {
206
 
      ilength = amount;
207
 
    }
208
 
 
209
 
    data->zstrm.next_in = (unsigned char *) ibuf;
210
 
    data->zstrm.avail_in = ilength;
211
 
 
212
 
    while (data->zstrm.avail_in > 0) {
213
 
      blkp = TSIOBufferStart(data->output_buffer);
214
 
 
215
 
      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
216
 
 
217
 
      data->zstrm.next_out = (unsigned char *) obuf;
218
 
      data->zstrm.avail_out = olength;
219
 
 
220
 
      /* Encode */
221
 
      err = deflate(&data->zstrm, Z_NO_FLUSH);
222
 
 
223
 
      if (olength > data->zstrm.avail_out) {
224
 
        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
225
 
        data->output_length += (olength - data->zstrm.avail_out);
226
 
      }
227
 
 
228
 
      if (data->zstrm.avail_out > 0) {
229
 
        if (data->zstrm.avail_in != 0) {
230
 
          TSError("gzip-transform: ERROR: avail_in is (%d): should be 0", data->zstrm.avail_in);
231
 
        }
232
 
      }
233
 
    }
234
 
 
235
 
    /* compute CRC for error checking at client */
236
 
    data->crc = crc32(data->crc, (unsigned char *) ibuf, ilength);
237
 
 
238
 
    TSIOBufferReaderConsume(input_reader, ilength);
239
 
    amount -= ilength;
240
 
  }
241
 
}
242
 
 
243
 
 
244
 
static void
245
 
gzip_transform_finish(GzipData * data)
246
 
{
247
 
  if (data->state == 1) {
248
 
    TSIOBufferBlock blkp;
249
 
    char *obuf;
250
 
    int64_t olength;
251
 
    int err;
252
 
 
253
 
    data->state = 2;
254
 
 
255
 
    for (;;) {
256
 
      blkp = TSIOBufferStart(data->output_buffer);
257
 
 
258
 
      obuf = TSIOBufferBlockWriteStart(blkp, &olength);
259
 
      data->zstrm.next_out = (unsigned char *) obuf;
260
 
      data->zstrm.avail_out = olength;
261
 
 
262
 
      /* Encode remaining data */
263
 
      err = deflate(&data->zstrm, Z_FINISH);
264
 
 
265
 
      if (olength > data->zstrm.avail_out) {
266
 
        TSIOBufferProduce(data->output_buffer, olength - data->zstrm.avail_out);
267
 
        data->output_length += (olength - data->zstrm.avail_out);
268
 
      }
269
 
 
270
 
      if (err == Z_OK) {        /* some more data to encode */
271
 
        continue;
272
 
      }
273
 
      /* done! */
274
 
      if (err != Z_STREAM_END) {
275
 
        TSDebug("gzip-transform", "deflate should report Z_STREAM_END\n");
276
 
      }
277
 
      break;
278
 
    }
279
 
 
280
 
    if (data->output_length != (data->zstrm.total_out)) {
281
 
      TSError("gzip-transform: ERROR: output lengths don't match (%d, %ld)", data->output_length,
282
 
               data->zstrm.total_out);
283
 
    }
284
 
 
285
 
    /* compute/append crc to end of stream */
286
 
 
287
 
    /*
288
 
       blkp = TSIOBufferStart (data->output_buffer);
289
 
 
290
 
       tmp = data->crc;
291
 
       buf[0] = tmp & 0xff; tmp >>= 8;
292
 
       buf[1] = tmp & 0xff; tmp >>= 8;
293
 
       buf[2] = tmp & 0xff; tmp >>= 8;
294
 
       buf[3] = tmp & 0xff;
295
 
 
296
 
       tmp = data->zstrm.total_in;
297
 
       buf[4] = tmp & 0xff; tmp >>= 8;
298
 
       buf[5] = tmp & 0xff; tmp >>= 8;
299
 
       buf[6] = tmp & 0xff; tmp >>= 8;
300
 
       buf[7] = tmp & 0xff;
301
 
 
302
 
       p = buf;
303
 
       length = 8;
304
 
 
305
 
       while (length > 0) {
306
 
       obuf = TSIOBufferBlockWriteStart (blkp, &olength);
307
 
       if (olength > length) {
308
 
       olength = length;
309
 
       }
310
 
 
311
 
       memcpy (obuf, p, olength);
312
 
       p += olength;
313
 
       length -= olength;
314
 
 
315
 
       TSIOBufferProduce (data->output_buffer, olength);
316
 
       }
317
 
 
318
 
       data->output_length += 8;
319
 
     */
320
 
  }
321
 
}
322
 
 
323
 
 
324
 
static void
325
 
gzip_transform_do(TSCont contp)
326
 
{
327
 
  TSVIO write_vio;
328
 
  GzipData *data;
329
 
  int towrite;
330
 
  int avail;
331
 
  int length;
332
 
 
333
 
  /* Get our data structure for this operation. The private data
334
 
     structure contains the output vio and output buffer. If the
335
 
     private data structure pointer is NULL, then we'll create it
336
 
     and initialize its internals. */
337
 
  data = TSContDataGet(contp);
338
 
  if (data->state == 0) {
339
 
    gzip_transform_init(contp, data);
340
 
  }
341
 
 
342
 
  /* Get the write vio for the write operation that was performed on
343
 
     ourself. This vio contains the buffer that we are to read from
344
 
     as well as the continuation we are to call when the buffer is
345
 
     empty. */
346
 
  write_vio = TSVConnWriteVIOGet(contp);
347
 
 
348
 
  length = data->output_length;
349
 
 
350
 
  /* We also check to see if the write vio's buffer is non-NULL. A
351
 
     NULL buffer indicates that the write operation has been
352
 
     shutdown and that the continuation does not want us to send any
353
 
     more WRITE_READY or WRITE_COMPLETE events. For this simplistic
354
 
     transformation that means we're done. In a more complex
355
 
     transformation we might have to finish writing the transformed
356
 
     data to our output connection. */
357
 
  if (!TSVIOBufferGet(write_vio)) {
358
 
    gzip_transform_finish(data);
359
 
 
360
 
    TSVIONBytesSet(data->output_vio, data->output_length);
361
 
    TSDebug("gzip-transform", "Compressed size %d (bytes)", data->output_length);
362
 
 
363
 
    if (data->output_length > length) {
364
 
      TSVIOReenable(data->output_vio);
365
 
    }
366
 
    return;
367
 
  }
368
 
 
369
 
  /* Determine how much data we have left to read. For this gzip
370
 
     transform plugin this is also the amount of data we have left
371
 
     to write to the output connection. */
372
 
  towrite = TSVIONTodoGet(write_vio);
373
 
  if (towrite > 0) {
374
 
    /* The amount of data left to read needs to be truncated by
375
 
       the amount of data actually in the read buffer. */
376
 
    avail = TSIOBufferReaderAvail(TSVIOReaderGet(write_vio));
377
 
    if (towrite > avail) {
378
 
      towrite = avail;
379
 
    }
380
 
 
381
 
    if (towrite > 0) {
382
 
      gzip_transform_one(data, TSVIOReaderGet(write_vio), towrite);
383
 
 
384
 
      /* Modify the write vio to reflect how much data we've
385
 
         completed. */
386
 
      TSVIONDoneSet(write_vio, TSVIONDoneGet(write_vio) + towrite);
387
 
    }
388
 
  }
389
 
 
390
 
  /* Now we check the write vio to see if there is data left to
391
 
     read. */
392
 
  if (TSVIONTodoGet(write_vio) > 0) {
393
 
    if (towrite > 0) {
394
 
      /* If we output some data then we reenable the output
395
 
         connection by reenabling the output vio. This will wakeup
396
 
         the output connection and allow it to consume data from the
397
 
         output buffer. */
398
 
      if (data->output_length > length) {
399
 
        TSVIOReenable(data->output_vio);
400
 
      }
401
 
 
402
 
      /* Call back the write vio continuation to let it know that we
403
 
         are ready for more data. */
404
 
      TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_READY, write_vio);
405
 
    }
406
 
  } else {
407
 
    /* If there is no data left to read, then we modify the output
408
 
       vio to reflect how much data the output connection should
409
 
       expect. This allows the output connection to know when it
410
 
       is done reading. We then reenable the output connection so
411
 
       that it can consume the data we just gave it. */
412
 
    gzip_transform_finish(data);
413
 
 
414
 
    TSVIONBytesSet(data->output_vio, data->output_length);
415
 
    TSDebug("gzip-transform", "Compressed size %d (bytes)", data->output_length);
416
 
 
417
 
    if (data->output_length > length) {
418
 
      TSVIOReenable(data->output_vio);
419
 
    }
420
 
 
421
 
    /* Call back the write vio continuation to let it know that we
422
 
       have completed the write operation. */
423
 
    TSContCall(TSVIOContGet(write_vio), TS_EVENT_VCONN_WRITE_COMPLETE, write_vio);
424
 
  }
425
 
}
426
 
 
427
 
 
428
 
static int
429
 
gzip_transform(TSCont contp, TSEvent event, void *edata)
430
 
{
431
 
  /* Check to see if the transformation has been closed by a call to
432
 
     TSVConnClose. */
433
 
  if (TSVConnClosedGet(contp)) {
434
 
    gzip_data_destroy(TSContDataGet(contp));
435
 
    TSContDestroy(contp);
436
 
    return 0;
437
 
  } else {
438
 
    switch (event) {
439
 
    case TS_EVENT_ERROR:
440
 
      {
441
 
        TSVIO write_vio;
442
 
 
443
 
        /* Get the write vio for the write operation that was
444
 
           performed on ourself. This vio contains the continuation of
445
 
           our parent transformation. */
446
 
        write_vio = TSVConnWriteVIOGet(contp);
447
 
 
448
 
        /* Call back the write vio continuation to let it know that we
449
 
           have completed the write operation. */
450
 
        TSContCall(TSVIOContGet(write_vio), TS_EVENT_ERROR, write_vio);
451
 
      }
452
 
      break;
453
 
    case TS_EVENT_VCONN_WRITE_COMPLETE:
454
 
      /* When our output connection says that it has finished
455
 
         reading all the data we've written to it then we should
456
 
         shutdown the write portion of its connection to
457
 
         indicate that we don't want to hear about it anymore. */
458
 
      TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
459
 
      break;
460
 
    case TS_EVENT_VCONN_WRITE_READY:
461
 
    default:
462
 
      /* If we get a WRITE_READY event or any other type of
463
 
         event (sent, perhaps, because we were reenabled) then
464
 
         we'll attempt to transform more data. */
465
 
      gzip_transform_do(contp);
466
 
      break;
467
 
    }
468
 
  }
469
 
 
470
 
  return 0;
471
 
}
472
 
 
473
 
 
474
 
static int
475
 
gzip_transformable(TSHttpTxn txnp, int server)
476
 
{
477
 
  /* Server response header */
478
 
  TSMBuffer bufp;
479
 
  TSMLoc hdr_loc;
480
 
  TSMLoc field_loc;
481
 
 
482
 
  /* Client request header */
483
 
  TSMBuffer cbuf;
484
 
  TSMLoc chdr;
485
 
  TSMLoc cfield;
486
 
 
487
 
  const char *value;
488
 
  int nvalues;
489
 
  int i, deflate_flag;
490
 
 
491
 
  TSHttpTxnClientReqGet(txnp, &cbuf, &chdr);
492
 
 
493
 
  /* check if client accepts "deflate" */
494
 
 
495
 
  cfield = TSMimeHdrFieldFind(cbuf, chdr, TS_MIME_FIELD_ACCEPT_ENCODING, -1);
496
 
  if (TS_NULL_MLOC != cfield) {
497
 
    nvalues = TSMimeHdrFieldValuesCount(cbuf, chdr, cfield);
498
 
    value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, 0, NULL);
499
 
    deflate_flag = 0;
500
 
    i = 0;
501
 
    while (nvalues > 0) {
502
 
      if (value && (strncasecmp(value, "deflate", sizeof("deflate") - 1) == 0)) {
503
 
        deflate_flag = 1;
504
 
        break;
505
 
      }
506
 
      i++;
507
 
      value = TSMimeHdrFieldValueStringGet(cbuf, chdr, cfield, i, NULL);
508
 
      nvalues--;
509
 
    }
510
 
    if (!deflate_flag) {
511
 
      return -7;
512
 
    }
513
 
    TSHandleMLocRelease(cbuf, chdr, cfield);
514
 
    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
515
 
  } else {
516
 
    TSHandleMLocRelease(cbuf, chdr, cfield);
517
 
    TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
518
 
    return -6;
519
 
  }
520
 
 
521
 
  if (server) {
522
 
    TSHttpTxnServerRespGet(txnp, &bufp, &hdr_loc);
523
 
  } else {
524
 
    TSHttpTxnCachedRespGet(txnp, &bufp, &hdr_loc);
525
 
  }
526
 
 
527
 
  /* If there already exists a content encoding then we don't want
528
 
     to do anything. */
529
 
  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_ENCODING, -1);
530
 
  if (field_loc) {
531
 
    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
532
 
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
533
 
    return -3;
534
 
  }
535
 
  TSHandleMLocRelease(bufp, hdr_loc, field_loc);
536
 
 
537
 
  /* We only want to do gzip compression on documents that have a
538
 
     content type of "text/" or "application/x-javascript". */
539
 
 
540
 
  field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_CONTENT_TYPE, -1);
541
 
  if (!field_loc) {
542
 
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
543
 
    return -4;
544
 
  }
545
 
 
546
 
  value = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, NULL);
547
 
  if (value && (strncasecmp(value, "text/", sizeof("text/") - 1) == 0)) {
548
 
    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
549
 
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
550
 
    return 0;
551
 
  } else if (value && (strncasecmp(value, "application/x-javascript", (sizeof("application/x-javascript") - 1)) == 0)) {
552
 
    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
553
 
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
554
 
    return 0;
555
 
  } else {
556
 
    TSHandleMLocRelease(bufp, hdr_loc, field_loc);
557
 
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
558
 
    return -5;
559
 
  }
560
 
}
561
 
 
562
 
 
563
 
static void
564
 
gzip_transform_add(TSHttpTxn txnp, int server)
565
 
{
566
 
  TSVConn connp;
567
 
  GzipData *data;
568
 
 
569
 
  connp = TSTransformCreate(gzip_transform, txnp);
570
 
 
571
 
  data = gzip_data_alloc();
572
 
  data->txn = txnp;
573
 
  TSContDataSet(connp, data);
574
 
 
575
 
  TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
576
 
}
577
 
 
578
 
 
579
 
static int
580
 
transform_plugin(TSCont contp, TSEvent event, void *edata)
581
 
{
582
 
  TSHttpTxn txnp = (TSHttpTxn) edata;
583
 
  int reason;
584
 
 
585
 
  switch (event) {
586
 
  case TS_EVENT_HTTP_READ_RESPONSE_HDR:
587
 
    reason = gzip_transformable(txnp, 1);
588
 
    if (reason >= 0) {
589
 
      TSDebug("gzip-transform", "server content transformable");
590
 
      gzip_transform_add(txnp, 1);
591
 
    } else {
592
 
      TSDebug("gzip-transform", "server content NOT transformable [%d]", reason);
593
 
    }
594
 
 
595
 
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
596
 
    break;
597
 
 
598
 
  case TS_EVENT_HTTP_READ_CACHE_HDR:
599
 
 
600
 
    reason = gzip_transformable(txnp, 0);
601
 
    if (reason >= 0) {
602
 
      TSDebug("gzip-transform", "cached content transformable");
603
 
      gzip_transform_add(txnp, 1);
604
 
    } else {
605
 
      TSDebug("gzip-transform", "cached data:  forwarding unchanged (%d)", reason);
606
 
    }
607
 
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
608
 
    break;
609
 
 
610
 
  default:
611
 
    exit(1);
612
 
  }
613
 
 
614
 
  return 0;
615
 
}
616
 
 
617
 
 
618
 
void
619
 
TSPluginInit(int argc, const char *argv[])
620
 
{
621
 
  dictId = adler32(0L, Z_NULL, 0);
622
 
  if (argc == 2) {
623
 
    strcpy(preload_file, argv[1]);
624
 
    preload = 1;
625
 
    load_dictionary(dictionary, &dictId);
626
 
  }
627
 
 
628
 
  TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
629
 
  TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, TSContCreate(transform_plugin, NULL));
630
 
}
631