~mimose/+junk/hplip-3.16.11

« back to all changes in this revision

Viewing changes to scan/sane/http.c

  • Committer: guoyalong
  • Date: 2017-09-20 10:13:05 UTC
  • Revision ID: guoyalong@kylinos.cn-20170920101305-82zaolzpv1qghz29
Modified debian/control & debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************\
 
2
  http.c - HTTP/1.1 feeder and consumer
 
3
 
 
4
  (c) 2008 Copyright HP Development Company, LP
 
5
 
 
6
  Permission is hereby granted, free of charge, to any person obtaining a copy 
 
7
  of this software and associated documentation files (the "Software"), to deal 
 
8
  in the Software without restriction, including without limitation the rights 
 
9
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
 
10
  of the Software, and to permit persons to whom the Software is furnished to do 
 
11
  so, subject to the following conditions:
 
12
 
 
13
  The above copyright notice and this permission notice shall be included in all
 
14
  copies or substantial portions of the Software.
 
15
 
 
16
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 
17
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
 
18
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 
19
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 
20
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 
21
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
  In order to support state-less connections, each HTTP/1.1 connection or session 
 
24
  must start with http_open and end with http_close. 
 
25
 
 
26
  Author: Naga Samrat Chowdary, Narla
 
27
  Contributing Author: Sarbeswar Meher
 
28
\************************************************************************************/
 
29
 
 
30
#ifndef _GNU_SOURCE
 
31
#define _GNU_SOURCE
 
32
#endif
 
33
 
 
34
#include <stdio.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
#include <syslog.h>
 
38
#include <ctype.h>
 
39
#include "hpmud.h"
 
40
#include "http.h"
 
41
 
 
42
//#define HTTP_DEBUG
 
43
 
 
44
#define _STRINGIZE(x) #x
 
45
#define STRINGIZE(x) _STRINGIZE(x)
 
46
 
 
47
#define BUG(args...) syslog(LOG_ERR, __FILE__ " " STRINGIZE(__LINE__) ": " args)
 
48
 
 
49
#ifdef HTTP_DEBUG
 
50
   #define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
 
51
   #define DBG_DUMP(data, size) sysdump((data), (size))
 
52
   #define DBG_SZ(args...) syslog(LOG_INFO, args)
 
53
#else
 
54
   #define DBG(args...)
 
55
   #define DBG_DUMP(data, size)
 
56
   #define DBG_SZ(args...)
 
57
#endif
 
58
 
 
59
#define EXCEPTION_TIMEOUT 45 /* seconds */
 
60
 
 
61
enum HTTP_STATE
 
62
{
 
63
   HS_ACTIVE = 1,
 
64
   HS_EOF,
 
65
};
 
66
 
 
67
struct stream_buffer
 
68
{
 
69
   char buf[4096];
 
70
   int index;
 
71
   int cnt;   
 
72
};
 
73
 
 
74
struct http_session
 
75
{
 
76
   enum HTTP_STATE state;
 
77
   int http_status;
 
78
   int footer;         /* current footer */
 
79
   int total;
 
80
   HPMUD_DEVICE dd;  /* hpiod device descriptor */
 
81
   HPMUD_CHANNEL cd;  /* hpiod soap channel descriptor */
 
82
   struct stream_buffer s;
 
83
};
 
84
 
 
85
 
 
86
/* Copy stream data to data buffer and then clear stream. */
 
87
int __attribute__ ((visibility ("hidden"))) clear_stream(HTTP_HANDLE handle, void *data, int max_size, int *bytes_read)
 
88
{
 
89
 
 
90
   DBG("clear_stream entry...\n");
 
91
   struct http_session *ps = (struct http_session *)handle;
 
92
   int len=0, stat=1;
 
93
 
 
94
   if (ps->s.cnt > 0 && ps->s.cnt <= max_size )
 
95
   {
 
96
         len = ps->s.cnt;
 
97
         DBG("Clearing (%d) bytes from the stream\n", len);
 
98
         memcpy(data, &ps->s.buf[ps->s.index], len);
 
99
         ps->s.index = ps->s.cnt = 0;       /* stream is empty reset */
 
100
         stat = 0;
 
101
   }
 
102
 
 
103
   *bytes_read = len;
 
104
 
 
105
   DBG("clear_stream returning with (stat = %d, bytes_read = %d)...\n", stat, *bytes_read);
 
106
   return stat;
 
107
 
 
108
}
 
109
 
 
110
 
 
111
/* Read data into stream buffer. Return specified "size" or less. Unused data is left in the stream. */
 
112
static int read_stream(struct http_session *ps, char *data, int size, int sec_timeout, int *bytes_read)
 
113
{
 
114
   int len, stat=1;
 
115
   int tmo=sec_timeout;        /* initial timeout */
 
116
   int max=sizeof(ps->s.buf);
 
117
   enum HPMUD_RESULT ret;
 
118
   int retry = 3;
 
119
 
 
120
   //DBG("read_stream() ps=%p data=%p size=%d timeout=%d s.index=%d s.cnt=%d\n", ps, data, size, sec_timeout, ps->s.index, ps->s.cnt);
 
121
 
 
122
   *bytes_read = 0;
 
123
 
 
124
   /* Return any data in the stream first. */
 
125
   if (ps->s.cnt)
 
126
   {
 
127
      if (ps->s.cnt > size)
 
128
      {
 
129
         /* Return part of stream buffer. */
 
130
         len = size;
 
131
         memcpy(data, &ps->s.buf[ps->s.index], len);
 
132
         ps->s.index += len;
 
133
         ps->s.cnt -= len;
 
134
      }
 
135
      else
 
136
      {
 
137
         /* Return all of rbuf. */
 
138
         len = ps->s.cnt;
 
139
         memcpy(data, &ps->s.buf[ps->s.index], len);
 
140
         ps->s.index = ps->s.cnt = 0;       /* stream is empty reset */
 
141
      }
 
142
      *bytes_read = len;
 
143
      //DBG("-read_stream() bytes_read=%d s.index=%d s.cnt=%d\n", len, ps->s.index, ps->s.cnt);
 
144
      return 0;
 
145
   }
 
146
 
 
147
   /* Stream is empty read more data from device. */
 
148
   ret = hpmud_read_channel(ps->dd, ps->cd, &ps->s.buf[ps->s.index], max-(ps->s.index + ps->s.cnt), tmo, &len);
 
149
   while ( (ret == HPMUD_R_IO_TIMEOUT || ret == HPMUD_R_IO_ERROR) && retry--)
 
150
   {
 
151
      usleep(100000); //Pause for 0.1 sec. Sometimes devices like scanjet 3500 take some time to prepare data.
 
152
      ret = hpmud_read_channel(ps->dd, ps->cd, &ps->s.buf[ps->s.index], max-(ps->s.index + ps->s.cnt), tmo, &len);
 
153
      DBG("hpmud_read_channel failed retrying (%d) more times)\n", retry);
 
154
   }
 
155
   if (ret != HPMUD_R_OK)
 
156
   {
 
157
      BUG("read_stream error stat=%d\n", ret);
 
158
      goto bugout;
 
159
   }
 
160
   if (len==0)
 
161
   {
 
162
      BUG("read_stream error len=0\n");   /* shouldn't happen, but it does with jetdirect */
 
163
      goto bugout;
 
164
   }
 
165
 
 
166
   DBG("read_channel len=%d\n", len);
 
167
   ps->s.cnt += len;
 
168
 
 
169
   if (ps->s.cnt > size)
 
170
   {
 
171
      /* Return part of stream buffer. */
 
172
      len = size;
 
173
      memcpy(data, &ps->s.buf[ps->s.index], len);
 
174
      ps->s.index += len;
 
175
      ps->s.cnt -= len;
 
176
   }
 
177
   else
 
178
   {
 
179
      /* Return all of rbuf. */
 
180
      len = ps->s.cnt;
 
181
      memcpy(data, &ps->s.buf[ps->s.index], len);
 
182
      ps->s.index = ps->s.cnt = 0;       /* stream is empty reset */
 
183
   }
 
184
 
 
185
   *bytes_read = len;
 
186
   stat = 0;
 
187
 
 
188
bugout:
 
189
   DBG("-read_stream() bytes_read=%d s.index=%d s.cnt=%d stat=%d\n", len, ps->s.index, ps->s.cnt, stat);
 
190
   return stat;
 
191
}
 
192
 
 
193
static int read_char(struct http_session *ps, int sec_timeout)
 
194
{
 
195
   unsigned char ch;
 
196
   int len;
 
197
   if (read_stream(ps, (char *)&ch, 1, sec_timeout, &len))
 
198
      return -1;
 
199
   else
 
200
      return ch;  
 
201
}
 
202
 
 
203
/* Read a line of data. Line length is not known. */
 
204
static int read_line(struct http_session *ps, char *line, int line_size, int sec_timeout, int *bytes_read)
 
205
{
 
206
   int total=0, stat=1;
 
207
   int ch, cr=0, lf=0;
 
208
   int tmo=sec_timeout;        /* initial timeout */
 
209
 
 
210
   *bytes_read = 0;
 
211
 
 
212
   while (total < (line_size-1))
 
213
   {
 
214
      ch = read_char(ps, tmo);
 
215
      line[total++]=ch;
 
216
 
 
217
      if (ch == '\r')
 
218
         cr=1;
 
219
      else if (ch == '\n' && cr)
 
220
         break;   /* done, found CRLF */
 
221
      else if (ch == '\n' && lf)
 
222
         break;   /* done, found LFLF (for kiwi "501 Not Implemented") */
 
223
      else if (ch == '\n')
 
224
         lf=1;
 
225
      else if (ch == -1)
 
226
         goto bugout;  /* error */
 
227
      else
 
228
      {
 
229
        cr=0;
 
230
        lf=0;
 
231
      }
 
232
      tmo=3;  /* changed 1 to 3 for 1200dpi uncompressed, DES 8/20/08. */ 
 
233
   }
 
234
   stat = 0;
 
235
 
 
236
bugout:
 
237
   line[total]=0;
 
238
   *bytes_read=total;   /* length does not include null termination */
 
239
   DBG("read_line len=%d index=%d cnt=%d\n", total, ps->s.index, ps->s.cnt);
 
240
   return stat;
 
241
}
 
242
 
 
243
/* Http_open must be called for each HTTP/1.1 connection or session. */
 
244
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_open(HPMUD_DEVICE dd, const char *channel, HTTP_HANDLE *handle)
 
245
{
 
246
   struct http_session *ps;
 
247
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
248
   
 
249
   DBG("http_open() dd=%d channel=%s handle=%p\n", dd, channel, handle);
 
250
 
 
251
   *handle = NULL;
 
252
 
 
253
   if ((ps = malloc(sizeof(struct http_session))) == NULL)
 
254
   {
 
255
      BUG("malloc failed: %m\n");
 
256
      return HTTP_R_MALLOC_ERROR;
 
257
   }
 
258
   memset(ps, 0, sizeof(struct http_session));
 
259
 
 
260
   ps->dd = dd;
 
261
   if (hpmud_open_channel(ps->dd, channel, &ps->cd) != HPMUD_R_OK)
 
262
   {
 
263
      BUG("unable to open %s channel\n", channel);
 
264
      goto bugout;
 
265
   }
 
266
 
 
267
   ps->state = HS_ACTIVE;
 
268
   *handle = ps;
 
269
   stat = HTTP_R_OK;
 
270
 
 
271
bugout:
 
272
   if (stat != HTTP_R_OK)
 
273
      free(ps);
 
274
   return stat;
 
275
}
 
276
 
 
277
/* Http_close must be called after the HTTP/1.1 connection closes. */
 
278
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_close(HTTP_HANDLE handle)
 
279
{
 
280
   struct http_session *ps = (struct http_session *)handle;
 
281
 
 
282
   if(ps)
 
283
   {
 
284
       DBG("http_close() handle=%p\n", handle);
 
285
       if (ps->cd > 0)
 
286
          hpmud_close_channel(ps->dd, ps->cd);
 
287
       free(ps);
 
288
   }
 
289
   return HTTP_R_OK;
 
290
}
 
291
 
 
292
/* Read HTTP/1.1 header. Blocks until header is read or timeout. */
 
293
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_read_header(HTTP_HANDLE handle, void *data, int max_size, int sec_timeout, int *bytes_read)
 
294
{
 
295
   struct http_session *ps = (struct http_session *)handle;
 
296
   int len, total; 
 
297
   int tmo=sec_timeout;   /* set initial timeout */
 
298
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
299
 
 
300
   DBG("http_read_header() handle=%p data=%p size=%d sectime=%d\n", handle, data, max_size, sec_timeout);
 
301
 
 
302
   *bytes_read = 0;
 
303
 
 
304
   /* Read initial HTTP/1.1 header status line. */
 
305
    while(1)
 
306
    {
 
307
       if (read_line(ps, data, max_size, tmo, &len))
 
308
          goto bugout;
 
309
        if( !strncmp(data, "HTTP/1.1", 8)) 
 
310
            break;
 
311
        else
 
312
        {
 
313
            DBG("HTTP Header not found. Searching header in next line (%d)\n", len); 
 
314
        }           
 
315
    }
 
316
   ps->http_status = strtol(data+9, NULL, 10);
 
317
   *bytes_read = total = len;
 
318
 
 
319
   /* Check for good status, ignore 400 (no job id found for JobCancelRequest) */                    
 
320
   if (!((ps->http_status >= 200 && ps->http_status < 300) || ps->http_status == 400))
 
321
   {
 
322
      BUG("invalid http_status=%d\n", ps->http_status);
 
323
 
 
324
      /* Dump any outstanding payload here. */
 
325
      while (!read_stream(ps, data + total, max_size, 1, &len))
 
326
      {
 
327
         total = (total+len) % max_size;
 
328
         BUG("dumping len=%d\n", len);
 
329
      }
 
330
      goto bugout;                
 
331
   }
 
332
 
 
333
   /* Read rest of header. Look for blank line. */
 
334
   *bytes_read = total = len;
 
335
   while (len > 2)
 
336
   {
 
337
      if (read_line(ps, data+total, max_size-total, tmo, &len))
 
338
         goto bugout;
 
339
      total += len;
 
340
     *bytes_read += len;
 
341
        DBG("http_read_header data=%s len=%d total=%d\n", (char*)data+total, len, total);
 
342
   }
 
343
   stat = HTTP_R_OK;
 
344
 
 
345
   DBG("-http_read_header() handle=%p data=%p bytes_read=%d size=%d status=%d\n", handle, data, *bytes_read, max_size, stat);
 
346
 
 
347
bugout:
 
348
   return stat;
 
349
};
 
350
 
 
351
/* Reads data from HTTP/1.1 chunked data stream until EOF. Returns max_size or less. */
 
352
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_read_payload(HTTP_HANDLE handle, void *data, int max_size, int sec_timeout, int *bytes_read)
 
353
{
 
354
   struct http_session *ps = (struct http_session *)handle;
 
355
   char line[128];
 
356
   int len; 
 
357
   int tmo=sec_timeout;   /* set initial timeout */
 
358
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
359
 
 
360
   DBG("http_read_payload() handle=%p data=%p size=%d sectime=%d\n", handle, data, max_size, sec_timeout);
 
361
 
 
362
   *bytes_read = 0;
 
363
 
 
364
   if (ps->state == HS_EOF)
 
365
   {
 
366
      stat = HTTP_R_EOF;
 
367
   }
 
368
   else
 
369
   {
 
370
      if (ps->footer)
 
371
      {
 
372
         /* Footer is not complete. Continue reading payload. */
 
373
         if (read_stream(ps, data, ps->footer < max_size ? ps->footer : max_size, tmo, &len))
 
374
            goto bugout;
 
375
 
 
376
         ps->total += len;
 
377
         ps->footer -= len;
 
378
         *bytes_read = len;
 
379
 
 
380
         if (ps->footer == 0)
 
381
            if (read_line(ps, line, sizeof(line), tmo, &len))   /* footer is complete, eat CRLF */
 
382
               goto bugout;
 
383
 
 
384
         stat = HTTP_R_OK;
 
385
      }
 
386
      else
 
387
      {
 
388
         /* Read new footer. */
 
389
         if (read_line(ps, line, sizeof(line), tmo, &len))
 
390
            goto bugout;
 
391
         ps->footer = strtol(line, NULL, 16);
 
392
 
 
393
         /* Check for zero footer. */
 
394
         if (ps->footer == 0)
 
395
         {
 
396
            /* Done eat blank line. */
 
397
            read_line(ps, line, sizeof(line), 1, &len);
 
398
            ps->state = HS_EOF;
 
399
            stat = HTTP_R_EOF;
 
400
         }
 
401
         else
 
402
         {
 
403
            /* Got a valid footer, continue reading payload. */
 
404
            if (read_stream(ps, data, ps->footer < max_size ? ps->footer : max_size, tmo, &len))
 
405
               goto bugout;
 
406
 
 
407
            ps->total += len;
 
408
            ps->footer -= len;
 
409
            *bytes_read = len;
 
410
 
 
411
            if (ps->footer == 0)
 
412
               if (read_line(ps, line, sizeof(line), tmo, &len))   /* footer is complete, eat CRLF */
 
413
                  goto bugout;
 
414
 
 
415
            stat = HTTP_R_OK;
 
416
         }
 
417
      }
 
418
   }  /* if (ps->state == HS_EOF) */
 
419
 
 
420
   DBG("-http_read_payload() handle=%p data=%p bytes_read=%d size=%d status=%d\n", handle, data, *bytes_read, max_size, stat);
 
421
 
 
422
bugout:
 
423
   return stat;
 
424
};
 
425
 
 
426
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_read2(HTTP_HANDLE handle, void *data, int max_size, int tmo, int *bytes_read)
 
427
{
 
428
   struct http_session *ps = (struct http_session *)handle;
 
429
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
430
   int len = 0, ret;
 
431
   int retry = 5;
 
432
 
 
433
   while(retry--)
 
434
   {
 
435
       DBG("http_read2 entry.\n" );
 
436
       ret = hpmud_read_channel(ps->dd, ps->cd, (char *)data, max_size, tmo, bytes_read);
 
437
       if(*bytes_read > 0)
 
438
       {
 
439
           DBG("http_read2 successful. (%d bytes read). \n", *bytes_read);
 
440
           stat = HTTP_R_OK;
 
441
           return 0;
 
442
       }
 
443
       DBG("http_read2 failed. Retrying (%d) more times before exiting.\n", retry);
 
444
       usleep(100000);
 
445
   }
 
446
   DBG("http_read2 failed to read (bytes_read=%d)\n", *bytes_read);
 
447
   return stat;
 
448
}
 
449
/* Reads data from HTTP/1.1 chunked data stream until EOF. Returns max_size or less. */
 
450
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_read(HTTP_HANDLE handle, void *data, int max_size, int sec_timeout, int *bytes_read)
 
451
{
 
452
   struct http_session *ps = (struct http_session *)handle;
 
453
   char line[128] ={0,};
 
454
   int len = 0, ret;
 
455
   int tmo=sec_timeout;   /* set initial timeout */
 
456
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
457
   int total_payload_length=*bytes_read;
 
458
 
 
459
   DBG("http_read() handle=%p data=%p size=%d sectime=%d total_payload_length=%d\n", handle, data, max_size, sec_timeout, total_payload_length);
 
460
 
 
461
   ps->footer=total_payload_length;
 
462
 
 
463
   *bytes_read = 0;
 
464
 
 
465
      /* Read new footer. */
 
466
      if (ps->footer) //Payload length is known
 
467
      {
 
468
         while(ps->footer)
 
469
         {
 
470
              if (read_line(ps, line, sizeof(line), tmo, &len))
 
471
                       {
 
472
                                 *bytes_read = (ps->footer) * (-1) + 12;
 
473
                                    goto bugout; 
 
474
                           }
 
475
                     strcpy(data, line);
 
476
                     data=data+len;
 
477
                     ps->footer -= len;
 
478
            *bytes_read += len;
 
479
         }
 
480
      } 
 
481
      else
 
482
      {
 
483
         while(1)
 
484
         {
 
485
            ret = read_line (ps, line, sizeof(line), tmo, &len);
 
486
            *bytes_read += len;
 
487
            if(ret) //failed to read line 
 
488
                    {
 
489
                            ps->footer = 0;
 
490
                            break;
 
491
                    }
 
492
            strcpy(data, line);
 
493
            data = data + len;
 
494
            DBG("http_read len=%d datalen=%d data=%s\n", len, strlen((char*)data), (char*)data);
 
495
            //Check for the footer
 
496
            if (strncmp(data-7, ZERO_FOOTER, sizeof(ZERO_FOOTER)-1) == 0)
 
497
            {
 
498
               ps->footer = 0;
 
499
               break;
 
500
            }
 
501
         }//end while(1)
 
502
      }//end else
 
503
      stat = HTTP_R_OK;
 
504
      if(ps->footer == 0) stat=HTTP_R_EOF;
 
505
 
 
506
   DBG("-http_read() handle=%p data=%p bytes_read=%d size=%d status=%d\n", handle, data, *bytes_read, max_size, stat);
 
507
 
 
508
bugout:
 
509
   return stat;
 
510
};
 
511
 
 
512
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_read_size(HTTP_HANDLE handle, void *data, int max_size, int sec_timeout, int *bytes_read)
 
513
{
 
514
  struct http_session *ps = (struct http_session *)handle;
 
515
  enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
516
  int ch;
 
517
 
 
518
  if(ps && ps->state == HTTP_R_EOF) return HTTP_R_EOF;
 
519
  if(max_size == -1) 
 
520
  { 
 
521
    ps->state = HTTP_R_EOF; 
 
522
    return HTTP_R_EOF; 
 
523
  }
 
524
 
 
525
  DBG("http_read_size() handle=%p data=%p size=%d sectime=%d\n", handle, data, max_size, sec_timeout);
 
526
 
 
527
  *bytes_read=0;
 
528
  while(*bytes_read < max_size)
 
529
  {
 
530
    ch = read_char(ps, sec_timeout);
 
531
    if(ch == -1)
 
532
    {   
 
533
        DBG("http_read_size(): IO error after %d bytes.\n",*bytes_read);
 
534
        return HTTP_R_IO_ERROR;
 
535
    }
 
536
 
 
537
    *((char*)data + (*bytes_read)) = ch;
 
538
    *bytes_read = *bytes_read+1;
 
539
  }
 
540
 
 
541
  return stat = HTTP_R_OK;
 
542
}
 
543
 
 
544
/* Write data to HTTP/1.1 connection. Blocks until all data is written or timeout. Caller formats header, footer and payload. */
 
545
enum HTTP_RESULT __attribute__ ((visibility ("hidden"))) http_write(HTTP_HANDLE handle, void *data, int size, int sec_timeout)
 
546
{
 
547
   struct http_session *ps = (struct http_session *)handle;
 
548
   int len; 
 
549
   int tmo=sec_timeout;   /* set initial timeout */
 
550
   enum HTTP_RESULT stat = HTTP_R_IO_ERROR;
 
551
 
 
552
   DBG("http_write() handle=%p data=%p size=%d sectime=%d\n", handle, data, size, sec_timeout);
 
553
 
 
554
   if (hpmud_write_channel(ps->dd, ps->cd, data, size, tmo, &len) != HPMUD_R_OK)
 
555
   {
 
556
      BUG("unable to write channel data\n");
 
557
      goto bugout;
 
558
   }
 
559
 
 
560
   stat = HTTP_R_OK;
 
561
 
 
562
bugout:
 
563
   return stat;
 
564
}
 
565
 
 
566
void __attribute__ ((visibility ("hidden"))) http_unchunk_data(char *buffer)
 
567
{
 
568
  char *temp=buffer;
 
569
  char *p=buffer;
 
570
  int chunklen = 0;
 
571
 
 
572
  //Here buffer starts like "<?xml....". There is no chunklen, only buffer
 
573
  if (*p == '<')
 
574
  {
 
575
      while(*p)
 
576
      {
 
577
        if (!(*p == '\n' || *p == '\r' || *p =='\t'))
 
578
        {
 
579
         *temp = *p;
 
580
         temp++;
 
581
        }
 
582
        p++;
 
583
          }
 
584
          *temp = '\0';
 
585
          return;
 
586
  }
 
587
  /*Here buffer looks like "chunklen data chunklen data 0"
 
588
  e.g "FE3 <?xml....  8E8 ... 0"*/
 
589
  while(1)
 
590
  {
 
591
    while(*p != '\n' && *p != '\r') 
 
592
    {
 
593
         chunklen = chunklen << 4 ; //Multiply 16
 
594
         if ('0' <= *p &&  *p<='9')
 
595
           chunklen += *p - '0';
 
596
         else if ('A' <= *p && *p <= 'F')
 
597
            chunklen += 10  - 'A' + *p;
 
598
         else if ('a' <= *p && *p <= 'f')
 
599
            chunklen += 10 + *p - 'a';
 
600
         else
 
601
         {
 
602
            chunklen = chunklen >> 4;
 
603
                break;
 
604
         }
 
605
         p++;
 
606
    }//end while()
 
607
    if (chunklen == 0)
 
608
       break ;
 
609
    while(*p == '\n' || *p == '\r' || *p =='\t') p++;
 
610
    //copy the data till chunklen
 
611
    while(chunklen > 0)
 
612
    {
 
613
           if (!(*p == '\n' || *p == '\r' || *p =='\t'))
 
614
       {
 
615
        *temp = *p ;
 
616
        temp++;
 
617
       }
 
618
       p++;
 
619
       chunklen--;
 
620
    }
 
621
    while(*p == '\n' || *p == '\r' || *p =='\t') p++;
 
622
  }//end while(1)
 
623
  *temp = '\0';
 
624
}
 
625
 
 
626
 
 
627
 
 
628