Annotation of libwww/Library/src/HTSocket.c, revision 2.15

2.1       frystyk     1: /*                                                                  HTSocket.c
                      2: **     MANAGES READ AND WRITE TO AND FROM THE NETWORK
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **
                      8: ** HISTORY:
                      9: **     6 June 95  HFN  Spawned off from HTFormat
                     10: */
                     11: 
                     12: /* Library Include files */
                     13: #include "tcp.h"
                     14: #include "HTUtils.h"
                     15: #include "HTString.h"
2.7       frystyk    16: #include "HTReqMan.h"
2.4       frystyk    17: #include "HTProt.h"
2.1       frystyk    18: #include "HTTCP.h"
                     19: #include "HTStream.h"
2.6       frystyk    20: #include "HTAlert.h"
2.1       frystyk    21: #include "HTFormat.h"
2.8       frystyk    22: #include "HTNetMan.h"
2.1       frystyk    23: #include "HTError.h"
                     24: #include "HTSocket.h"                                   /* Implemented here */
                     25: 
2.2       frystyk    26: struct _HTInputSocket {
2.7       frystyk    27:     char       buffer[INPUT_BUFFER_SIZE];
                     28:     char *     write;                                  /* Last byte written */
                     29:     char *     read;                                      /* Last byte read */
                     30:     SOCKFD     sockfd;
2.2       frystyk    31: };
                     32: 
2.1       frystyk    33: struct _HTStream {
                     34:     CONST HTStreamClass *      isa;
                     35: };
                     36: 
                     37: /* ------------------------------------------------------------------------- */
                     38: /*                             SOCKET INPUT BUFFERING                       */
                     39: /* ------------------------------------------------------------------------- */
                     40: /*                     
                     41: **     This code is used because one cannot in general open a
                     42: **     file descriptor for a socket.
                     43: **
                     44: **     The input file is read using the macro which can read from
                     45: **     a socket or a file, but this should not be used for files
                     46: **     as fopen() etc is more portable of course.
                     47: **
                     48: **     The input buffer size, if large will give greater efficiency and
                     49: **     release the server faster, and if small will save space on PCs etc.
                     50: */
                     51: 
                     52: 
                     53: /*     Set up the buffering
                     54: **
                     55: **     These routines are public because they are in fact needed by
                     56: **     many parsers, and on PCs and Macs we should not duplicate
                     57: **     the static buffer area.
                     58: */
2.12      frystyk    59: PUBLIC HTInputSocket * HTInputSocket_new (SOCKFD file_number)
2.1       frystyk    60: {
                     61:     HTInputSocket *isoc = (HTInputSocket *)calloc(1, sizeof(*isoc));
                     62:     if (!isoc) outofmem(__FILE__, "HTInputSocket_new");
2.7       frystyk    63:     isoc->sockfd = file_number;
                     64:     isoc->write = isoc->read = isoc->buffer;
2.1       frystyk    65:     return isoc;
                     66: }
                     67: 
2.12      frystyk    68: PUBLIC void HTInputSocket_free (HTInputSocket * me)
                     69: {
                     70:     if (me) free(me);
                     71: }
                     72: 
                     73: /* ------------------------------------------------------------------------- */
                     74: 
2.15    ! frystyk    75: #if 0
        !            76: 
2.1       frystyk    77: /* This should return HT_INTERRUPTED if interrupted BUT the connection
                     78:    MUST not be closed */ 
2.15    ! frystyk    79: PRIVATE int HTInputSocket_getCharacter ARGS1(HTInputSocket*, isoc)
2.1       frystyk    80: {
                     81:     int ch;
                     82:     do {
2.7       frystyk    83:        if (isoc->write >= isoc->read) {
                     84:            int status = NETREAD(isoc->sockfd, isoc->buffer,INPUT_BUFFER_SIZE);
2.1       frystyk    85:            if (status <= 0) {
                     86:                if (status == 0)
                     87:                    return EOF;
                     88:                if (PROT_TRACE)
2.14      frystyk    89:                    TTYPrint(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
2.1       frystyk    90:                return EOF;     /* -1 is returned by UCX at end of HTTP link */
                     91:            }
2.7       frystyk    92:            isoc->write = isoc->buffer;
                     93:            isoc->read = isoc->buffer + status;
2.1       frystyk    94:        }
2.7       frystyk    95:        ch = (unsigned char) *isoc->write++;
2.1       frystyk    96:     } while (ch == 13);                             /* Ignore ASCII carriage return */
                     97:     
                     98:     return FROMASCII(ch);
                     99: }
                    100: 
2.15    ! frystyk   101: PRIVATE char * HTInputSocket_getBlock ARGS2(HTInputSocket*,    isoc,
2.1       frystyk   102:                                           int *,               len)
                    103: {
2.7       frystyk   104:     if (isoc->write >= isoc->read) {
                    105:        int status = NETREAD(isoc->sockfd,
                    106:                             isoc->buffer,
2.1       frystyk   107:                             ((*len < INPUT_BUFFER_SIZE) ?
                    108:                              *len : INPUT_BUFFER_SIZE));
                    109:        if (status <= 0) {
2.7       frystyk   110:            isoc->read = isoc->buffer;
2.1       frystyk   111:            if (status < 0) {
                    112:                if (PROT_TRACE)
2.14      frystyk   113:                    TTYPrint(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
2.1       frystyk   114:            }
                    115:            *len = 0;
                    116:            return NULL;
                    117:        }
                    118:        else {
                    119:            *len = status;
2.7       frystyk   120:            return isoc->buffer;
2.1       frystyk   121:        }
                    122:     }
                    123:     else {
2.7       frystyk   124:        char * ret = isoc->write;
                    125:        *len = isoc->read - isoc->write;
                    126:        isoc->write = isoc->read;
2.1       frystyk   127:        return ret;
                    128:     }
                    129: }
                    130: 
                    131: 
                    132: PRIVATE int fill_in_buffer ARGS1(HTInputSocket *, isoc)
                    133: {
                    134:     if (isoc) {
                    135:        int status;
                    136: 
2.7       frystyk   137:        isoc->write = isoc->buffer;
                    138:        status = NETREAD(isoc->sockfd,
                    139:                         isoc->buffer,
2.1       frystyk   140:                         INPUT_BUFFER_SIZE);
                    141:        if (status <= 0) {
2.7       frystyk   142:            isoc->read = isoc->buffer;
2.1       frystyk   143:            if (status < 0) {
                    144:                if (PROT_TRACE)
2.14      frystyk   145:                    TTYPrint(TDEST, "Read Socket. READ ERROR %d\n", socerrno);
2.1       frystyk   146:            }
                    147:        }
                    148:        else 
2.7       frystyk   149:            isoc->read = isoc->buffer + status;
2.1       frystyk   150:        return status;
                    151:     }
                    152:     return -1;
                    153: }
                    154: 
                    155: 
                    156: PRIVATE void ascii_cat ARGS3(char **,  linep,
                    157:                             char *,    start,
                    158:                             char *,    end)
                    159: {
                    160:     if (linep && start && end && start <= end) {
                    161:        char *ptr;
                    162: 
                    163:        if (*linep) {
                    164:            int len = strlen(*linep);
                    165:            *linep = (char*)realloc(*linep, len + end-start + 1);
                    166:            ptr = *linep + len;
                    167:        }
                    168:        else {
                    169:            ptr = *linep = (char*)malloc(end-start + 1);
                    170:        }
                    171: 
                    172:        while (start < end) {
                    173:            *ptr = FROMASCII(*start);
                    174:            ptr++;
                    175:            start++;
                    176:        }
                    177:        *ptr = 0;
                    178:     }
                    179: }
                    180: 
                    181: 
                    182: PRIVATE char * get_some_line ARGS2(HTInputSocket *,    isoc,
                    183:                                   BOOL,                unfold)
                    184: {
                    185:     if (!isoc)
                    186:        return NULL;
                    187:     else {
                    188:        BOOL check_unfold = NO;
                    189:        int prev_cr = 0;
2.7       frystyk   190:        char *start = isoc->write;
                    191:        char *cur = isoc->write;
2.1       frystyk   192:        char * line = NULL;
                    193: 
                    194:        for(;;) {
                    195:            /*
                    196:            ** Get more if needed to complete line
                    197:            */
2.7       frystyk   198:            if (cur >= isoc->read) { /* Need more data */
2.1       frystyk   199:                ascii_cat(&line, start, cur);
                    200:                if (fill_in_buffer(isoc) <= 0)
                    201:                    return line;
2.7       frystyk   202:                start = cur = isoc->write;
2.1       frystyk   203:            } /* if need more data */
                    204: 
                    205:            /*
                    206:            ** Find a line feed if there is one
                    207:            */
2.7       frystyk   208:            for(; cur < isoc->read; cur++) {
2.1       frystyk   209:                char c = FROMASCII(*cur);
                    210:                if (!c) {
                    211:                    if (line) free(line);       /* Leak fixed AL 6 Feb 94 */
                    212:                    return NULL;        /* Panic! read a 0! */
                    213:                }
                    214:                if (check_unfold  &&  c != ' '  &&  c != '\t') {
2.7       frystyk   215:                    return line;  /* Note: didn't update isoc->write */
2.1       frystyk   216:                }
                    217:                else {
                    218:                    check_unfold = NO;
                    219:                }
                    220: 
                    221:                if (c=='\r') {
                    222:                    prev_cr = 1;
                    223:                }
                    224:                else {
                    225:                    if (c=='\n') {              /* Found a line feed */
                    226:                        ascii_cat(&line, start, cur-prev_cr);
2.7       frystyk   227:                        start = isoc->write = cur+1;
2.1       frystyk   228: 
                    229:                        if (line && (int) strlen(line) > 0 && unfold) {
                    230:                            check_unfold = YES;
                    231:                        }
                    232:                        else {
                    233:                            return line;
                    234:                        }
                    235:                    } /* if NL */
                    236:                    /* else just a regular character */
                    237:                    prev_cr = 0;
                    238:                } /* if not CR */
                    239:            } /* while characters in buffer remain */
                    240:        } /* until line read or end-of-file */
                    241:     } /* valid parameters to function */
                    242: }
                    243: 
                    244: /* The returned string must be freed by the caller */
2.15    ! frystyk   245: PRIVATE char * HTInputSocket_getLine ARGS1(HTInputSocket *, isoc)
2.1       frystyk   246: {
                    247:     return get_some_line(isoc, NO);
                    248: }
                    249: 
                    250: /* The returned string must be freed by the caller */
2.15    ! frystyk   251: PRIVATE char * HTInputSocket_getUnfoldedLine ARGS1(HTInputSocket *, isoc)
2.1       frystyk   252: {
                    253:     return get_some_line(isoc, YES);
                    254: }
                    255: 
2.15    ! frystyk   256: #endif
2.1       frystyk   257: 
                    258: /*     Push data from a socket down a stream
                    259: **     -------------------------------------
                    260: **
                    261: **   This routine is responsible for creating and PRESENTING any
                    262: **   graphic (or other) objects described by the file.
                    263: **
                    264: **   The file number given is assumed to be a TELNET stream ie containing
                    265: **   CRLF at the end of lines which need to be stripped to LF for unix
                    266: **   when the format is textual.
                    267: **
                    268: **   RETURNS the number of bytes transferred.
                    269: **
                    270: */
2.12      frystyk   271: PRIVATE int HTCopy ARGS2(
2.1       frystyk   272:        SOCKFD,                 file_number,
                    273:        HTStream*,              sink)
                    274: {
                    275:     HTStreamClass targetClass;    
                    276:     HTInputSocket * isoc;
                    277:     int cnt = 0;
                    278: 
                    279: /*     Push the data down the stream
                    280: **
                    281: */
                    282:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    283:     isoc = HTInputSocket_new(file_number);
                    284:     
                    285:     /* Push binary from socket down sink
                    286:     **
                    287:     **         This operation could be put into a main event loop
                    288:     */
                    289:     for(;;) {
                    290:        int status = NETREAD(
2.7       frystyk   291:                file_number, isoc->buffer, INPUT_BUFFER_SIZE);
2.1       frystyk   292:        if (status <= 0) {
                    293:            if (status == 0) break;
2.14      frystyk   294:            if (WWWTRACE) TTYPrint(TDEST,
2.1       frystyk   295:                "Socket Copy. Read error, read returns %d with errno=%d\n",
                    296:                status, socerrno);
2.15    ! frystyk   297:            break;
2.1       frystyk   298:        }
                    299: 
                    300: #ifdef NOT_ASCII
                    301:        {
                    302:            char * p;
2.7       frystyk   303:            for(p = isoc->buffer; p < isoc->buffer+status; p++) {
2.1       frystyk   304:                *p = FROMASCII(*p);
                    305:            }
                    306:        }
                    307: #endif
                    308: 
2.7       frystyk   309:        (*targetClass.put_block)(sink, isoc->buffer, status);
2.1       frystyk   310:        cnt += status;
                    311:     } /* next bufferload */
                    312: 
                    313:     HTInputSocket_free(isoc);
                    314: 
                    315:     return cnt;
                    316: }
                    317: 
2.13      frystyk   318: #if 0
2.1       frystyk   319: 
                    320: /*     Push data from a socket down a stream STRIPPING CR
                    321: **     --------------------------------------------------
                    322: **
                    323: **   This routine is responsible for creating and PRESENTING any
                    324: **   graphic (or other) objects described by the socket.
                    325: **
                    326: **   The file number given is assumed to be a TELNET stream ie containing
                    327: **   CRLF at the end of lines which need to be stripped to LF for unix
                    328: **   when the format is textual.
                    329: **     
                    330: **     Character handling is now of type int, Henrik, May 09-94
                    331: */
2.12      frystyk   332: PRIVATE void HTCopyNoCR ARGS2(
2.1       frystyk   333:        SOCKFD,                 file_number,
                    334:        HTStream*,              sink)
                    335: {
                    336:     HTStreamClass targetClass;
                    337:     HTInputSocket * isoc;   
                    338:     int ch;
                    339:     
                    340: /*     Push the data, ignoring CRLF, down the stream
                    341: **
                    342: */
                    343:     targetClass = *(sink->isa);        /* Copy pointers to procedures */
                    344: 
                    345: /*     Push text from telnet socket down sink
                    346: **
                    347: **     @@@@@ To push strings could be faster? (especially is we
                    348: **     cheat and don't ignore CR! :-}
                    349: */  
                    350:     isoc = HTInputSocket_new(file_number);
                    351:     while ((ch = HTInputSocket_getCharacter(isoc)) >= 0)
                    352:        (*targetClass.put_character)(sink, ch);
                    353:     HTInputSocket_free(isoc);
                    354: }
                    355: 
2.15    ! frystyk   356: #endif
2.1       frystyk   357: 
                    358: /*     Parse a socket given format and file number
                    359: **
                    360: **   This routine is responsible for creating and PRESENTING any
                    361: **   graphic (or other) objects described by the file.
                    362: **
                    363: **   The file number given is assumed to be a TELNET stream ie containing
                    364: **   CRLF at the end of lines which need to be stripped to LF for unix
                    365: **   when the format is textual.
                    366: **
                    367: **     Returns <0 on error, HT_LOADED on success.
                    368: */
                    369: 
                    370: /* The parameter to this function and HTParsefile should be HTRequest */
                    371: 
                    372: PUBLIC int HTParseSocket ARGS3(
                    373:        HTFormat,               rep_in,
                    374:        SOCKFD,                 file_number,
                    375:        HTRequest *,            request)
                    376: {
                    377:     HTStream * stream;
                    378:     HTStreamClass targetClass;    
                    379: 
                    380:     if (request->error_stack) {
2.14      frystyk   381:        if (WWWTRACE) TTYPrint(TDEST, "ParseSocket. Called whith non-empty error stack, so I return right away!\n");
2.1       frystyk   382:        return -1;
                    383:     }
                    384: 
                    385:     /* Set up stream stack */
                    386:     if ((stream = HTStreamStack(rep_in, request->output_format,
                    387:                                request->output_stream,
                    388:                                request, YES)) == NULL)
                    389:        return -1;
                    390:     
                    391: /*     Push the data, ignoring CRLF if necessary, down the stream
                    392: **
                    393: **
                    394: **   @@  Bug:  This decision ought to be made based on "encoding"
                    395: **   rather than on format.  @@@  When we handle encoding.
                    396: **   The current method smells anyway.
                    397: */
                    398:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
2.15    ! frystyk   399: #if 0
2.1       frystyk   400:     if (rep_in == WWW_BINARY || rep_in == WWW_UNKNOWN
                    401:        || (HTAnchor_encoding(request->anchor) != HTAtom_for("8bit") &&
                    402:            HTAnchor_encoding(request->anchor) != HTAtom_for("7bit"))
                    403:         || strstr(HTAtom_name(rep_in), "image/")
                    404:        || strstr(HTAtom_name(rep_in), "video/")) { /* @@@@@@ */
                    405:        HTCopy(file_number, stream);
                    406:     } else
                    407:         HTCopyNoCR(file_number, stream);
2.15    ! frystyk   408: #endif
        !           409:     HTCopy(file_number, stream);
2.1       frystyk   410:     (*targetClass._free)(stream);
                    411:     return HT_LOADED;
                    412: }
                    413: 
                    414: 
2.12      frystyk   415: #if 0
2.1       frystyk   416: /*     Parse a file given format and file pointer
                    417: **
                    418: **   This routine is responsible for creating and PRESENTING any
                    419: **   graphic (or other) objects described by the file.
                    420: **
                    421: **   The file number given is assumed to be a TELNET stream ie containing
                    422: **   CRLF at the end of lines which need to be stripped to \n for unix
                    423: **   when the format is textual.
                    424: **
                    425: */
2.2       frystyk   426: PRIVATE int HTParseFile ARGS3(
2.1       frystyk   427:        HTFormat,               rep_in,
                    428:        FILE *,                 fp,
                    429:        HTRequest *,            request)
                    430: {
                    431:     HTStream * stream;
                    432:     HTStreamClass targetClass;    
                    433: 
                    434:     if (request->error_stack) {
2.14      frystyk   435:        if (WWWTRACE) TTYPrint(TDEST, "ParseFile... Called whith non-empty error stack, so I return right away!\n");
2.1       frystyk   436:        return -1;
                    437:     }
                    438: 
                    439:     /* Set up stream stack */
                    440:     if ((stream = HTStreamStack(rep_in, request->output_format,
                    441:                                request->output_stream, request, YES)) == NULL)
                    442:        return -1;
                    443:     
                    444: /*     Push the data down the stream
                    445: **
                    446: **
                    447: **   @@  Bug:  This decision ought to be made based on "encoding"
                    448: **   rather than on content-type.  @@@  When we handle encoding.
                    449: **   The current method smells anyway.
                    450: */
                    451:     targetClass = *(stream->isa);      /* Copy pointers to procedures */
                    452:     HTFileCopy(fp, stream);
                    453:     (*targetClass._free)(stream);
                    454:     
                    455:     return HT_LOADED;
                    456: }
2.12      frystyk   457: #endif
2.1       frystyk   458: 
                    459: /* ------------------------------------------------------------------------- */
                    460: /*                     MULTI THREADED IMPLEMENTATIONS                       */
                    461: /* ------------------------------------------------------------------------- */
                    462: 
                    463: /*     Push data from a socket down a stream
                    464: **     -------------------------------------
                    465: **
                    466: **   This routine is responsible for creating and PRESENTING any
                    467: **   graphic (or other) objects described by the file. As this function
                    468: **   max reads a chunk of data on size INPUT_BUFFER_SIZE, it can be used
                    469: **   with both blocking or non-blocking sockets. It will always return to
                    470: **   the event loop, however if we are using blocking I/O then we get a full
                    471: **   buffer read, otherwise we get what's available.
                    472: **
                    473: ** Returns      HT_LOADED      if finished reading
2.3       frystyk   474: **             HT_OK           if OK, but more to read
2.1       frystyk   475: **             HT_ERROR        if error,
                    476: **                     HT_WOULD_BLOCK  if read would block
                    477: */
2.10      frystyk   478: PUBLIC int HTSocketRead (HTRequest * request, HTNet * net)
2.1       frystyk   479: {
2.7       frystyk   480:     HTInputSocket *isoc = net->isoc;
2.10      frystyk   481:     HTStream *target = net->target;
2.7       frystyk   482:     int b_read = isoc->read - isoc->buffer;
2.1       frystyk   483:     int status;
2.7       frystyk   484:     if (!isoc || isoc->sockfd==INVSOC) {
2.14      frystyk   485:        if (PROT_TRACE) TTYPrint(TDEST, "Read Socket. Bad argument\n");
2.1       frystyk   486:        return HT_ERROR;
                    487:     }
                    488: 
2.3       frystyk   489:     /* Read from socket if we got rid of all the data previously read */
2.4       frystyk   490:     do {
2.7       frystyk   491:        if (isoc->write >= isoc->read) {
                    492:            if ((b_read = NETREAD(isoc->sockfd, isoc->buffer,
2.4       frystyk   493:                                  INPUT_BUFFER_SIZE)) < 0) {
2.1       frystyk   494: #ifdef EAGAIN
2.4       frystyk   495:                if (socerrno==EAGAIN || socerrno==EWOULDBLOCK)      /* POSIX */
2.1       frystyk   496: #else
2.11      frystyk   497:                if (socerrno==EWOULDBLOCK)                            /* BSD */
                    498: #endif 
                    499:                {
                    500:                    if (PROT_TRACE)
2.14      frystyk   501:                        TTYPrint(TDEST, "Read Socket. WOULD BLOCK soc %d\n",
2.11      frystyk   502:                                isoc->sockfd);
                    503:                    HTEvent_Register(isoc->sockfd, request, (SockOps) FD_READ,
                    504:                                     net->cbf, net->priority);
                    505:                    return HT_WOULD_BLOCK;
                    506:                } else { /* We have a real error */
                    507:                    if (PROT_TRACE)
2.14      frystyk   508:                        TTYPrint(TDEST, "Read Socket. READ ERROR %d\n",
2.11      frystyk   509:                                socerrno);
                    510:                    return HT_ERROR;
                    511:                }
2.4       frystyk   512:            } else if (!b_read) {
2.3       frystyk   513:                if (PROT_TRACE)
2.14      frystyk   514:                    TTYPrint(TDEST, "Read Socket. Finished loading socket %d\n",
2.7       frystyk   515:                            isoc->sockfd);
2.6       frystyk   516:                HTProgress(request, HT_PROG_DONE, NULL);
2.7       frystyk   517:                HTEvent_UnRegister(isoc->sockfd, FD_READ);
2.4       frystyk   518:                return HT_LOADED;
2.1       frystyk   519:            }
                    520: 
2.4       frystyk   521:            /* Remember how much we have read from the input socket */
2.7       frystyk   522:            isoc->write = isoc->buffer;
                    523:            isoc->read = isoc->buffer + b_read;
2.1       frystyk   524: 
                    525: #ifdef NOT_ASCII
2.4       frystyk   526:            {
2.7       frystyk   527:                char *p = isoc->buffer;
                    528:                while (p < isoc->read) {
2.4       frystyk   529:                    *p = FROMASCII(*p);
                    530:                    p++;
                    531:                }
2.1       frystyk   532:            }
                    533: #endif
2.3       frystyk   534:            if (PROT_TRACE)
2.14      frystyk   535:                TTYPrint(TDEST, "Read Socket. %d bytes read from socket %d\n",
2.7       frystyk   536:                        b_read, isoc->sockfd);
2.8       frystyk   537:            net->bytes_read += b_read;
2.6       frystyk   538:            HTProgress(request, HT_PROG_READ, NULL);
2.4       frystyk   539:        }
                    540:        
                    541:        /* Now push the data down the stream */
2.7       frystyk   542:        if ((status = (*target->isa->put_block)(target, isoc->buffer,
2.4       frystyk   543:                                                b_read)) != HT_OK) {
                    544:            if (status==HT_WOULD_BLOCK) {
                    545:                if (PROT_TRACE)
2.14      frystyk   546:                    TTYPrint(TDEST, "Read Socket. Target WOULD BLOCK\n");
2.7       frystyk   547:                HTEvent_UnRegister(isoc->sockfd, FD_READ);
2.4       frystyk   548:                return HT_WOULD_BLOCK;
2.5       frystyk   549:            } else if (status>0) {            /* Stream specific return code */
                    550:                if (PROT_TRACE)
2.14      frystyk   551:                    TTYPrint(TDEST, "Read Socket. Target returns %d\n", status);
2.10      frystyk   552:                isoc->write = isoc->buffer + b_read;
2.5       frystyk   553:                return status;
                    554:            } else {                                 /* We have a real error */
2.4       frystyk   555:                if (PROT_TRACE)
2.14      frystyk   556:                    TTYPrint(TDEST, "Read Socket. Target ERROR\n");
2.4       frystyk   557:                return status;
                    558:            }
2.1       frystyk   559:        }
2.7       frystyk   560:        isoc->write = isoc->buffer + b_read;
                    561:     } while (net->preemtive);
2.10      frystyk   562:     HTEvent_Register(isoc->sockfd, request, (SockOps) FD_READ,
                    563:                     net->cbf, net->priority);
2.1       frystyk   564:     return HT_WOULD_BLOCK;
                    565: }
2.2       frystyk   566: 
                    567: 
                    568: 
                    569: /*     Push data from an ANSI file descriptor down a stream
                    570: **     ----------------------------------------------------
                    571: **
                    572: **   This routine is responsible for creating and PRESENTING any
                    573: **   graphic (or other) objects described by the file.
                    574: **
                    575: **   Bugs: When we can wait on a file then this should also check interrupts!
                    576: **
                    577: **   Returns    HT_LOADED      if finished reading
                    578: **             HT_ERROR        if error,
                    579: */
2.10      frystyk   580: PUBLIC int HTFileRead (HTRequest * request, HTNet * net, FILE * fp)
2.2       frystyk   581: {
2.10      frystyk   582:     HTInputSocket *isoc = net->isoc;
                    583:     HTStream *target = net->target;
2.2       frystyk   584:     int b_read;
                    585:     int status;
                    586:     if (!fp) {
2.14      frystyk   587:        if (PROT_TRACE) TTYPrint(TDEST, "Read File... Bad argument\n");
2.2       frystyk   588:        return HT_ERROR;
                    589:     }
                    590: 
                    591:     while(1) {
2.7       frystyk   592:        if ((b_read = fread(isoc->buffer, 1, INPUT_BUFFER_SIZE, fp))==0){
2.2       frystyk   593:            if (ferror(fp)) {
                    594:                if (PROT_TRACE)
2.14      frystyk   595:                    TTYPrint(TDEST, "Read File... READ ERROR\n");
2.2       frystyk   596:            } else
                    597:                return HT_LOADED;
                    598:        }
2.7       frystyk   599:        isoc->write = isoc->buffer;
                    600:        isoc->read = isoc->buffer + b_read;
2.2       frystyk   601:        if (PROT_TRACE)
2.14      frystyk   602:            TTYPrint(TDEST, "Read File... %d bytes read from file %p\n",
2.2       frystyk   603:                    b_read, fp);
                    604: 
                    605:        /* Now push the data down the stream (we use blocking I/O) */
2.7       frystyk   606:        if ((status = (*target->isa->put_block)(target, isoc->buffer,
2.2       frystyk   607:                                                b_read)) != HT_OK) {
                    608:            if (PROT_TRACE)
2.14      frystyk   609:                TTYPrint(TDEST, "Read File... Target ERROR\n");
2.2       frystyk   610:            return status;
                    611:        }
2.7       frystyk   612:        isoc->write = isoc->buffer + b_read;
2.2       frystyk   613:     }
                    614: }
                    615: 
                    616: 

Webmaster