Annotation of libwww/Library/src/HTTPRes.c, revision 2.3

2.1       frystyk     1: /*                                                                   HTTPRes.c
                      2: **     HTTP MESSAGES GENERATION
                      3: **
                      4: **     This module implements the output stream for HTTP used for sending
                      5: **     responces with or without a entity body. It is the server equivalent
                      6: **     to the HTTPReq module
                      7: **
                      8: ** History:
                      9: **     Dec 95 HFN      Written from scratch
                     10: */
                     11: 
                     12: /* Library Includes */
                     13: #include "tcp.h"
                     14: #include "HTUtils.h"
                     15: #include "HTString.h"
                     16: #include "HTWWWStr.h"
                     17: #include "HTAccess.h"
                     18: #include "HTWriter.h"
                     19: #include "HTEvntrg.h"
                     20: #include "HTNetMan.h"
                     21: #include "HTReqMan.h"
                     22: #include "HTMIMERq.h"
                     23: #include "HTTPUtil.h"
                     24: #include "HTTPRes.h"                                          /* Implements */
                     25: 
                     26: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
                     27: 
                     28: struct _HTStream {
                     29:     CONST HTStreamClass *      isa;
                     30:     HTStream *                 target;
                     31:     HTRequest *                        request;
                     32:     SOCKET                     sockfd;
                     33:     BOOL                       transparent;
                     34: };
                     35: 
                     36: /* ------------------------------------------------------------------------- */
                     37: /*                         HTTP Output Request Stream                       */
                     38: /* ------------------------------------------------------------------------- */
                     39: 
2.2       frystyk    40: /*     Cleanup
                     41: **     -------
                     42: **      Cleanup the source request
                     43: **      Returns YES on OK, else NO
                     44: */
                     45: PRIVATE BOOL Cleanup (HTStream * me)
                     46: {
                     47:     int status = 0;
                     48:     HTRequest * src_req = HTRequest_source(me->request);
                     49:     HTNet * src_net;
                     50:     if (!src_req || !src_req->net) return NO;
                     51:     src_net = src_req->net;
                     52: 
                     53:     if (PROT_TRACE) TTYPrint(TDEST, "HTTPResponse FREEING...\n");
                     54: 
                     55: #if 0
                     56:     /* Free stream with data TO network */
                     57:     if (!HTRequest_isDestination(src_req) && src_req->input_stream) {
                     58:        if (status == HT_INTERRUPTED)
                     59:            (*src_req->input_stream->isa->abort)(src_req->input_stream, NULL);
                     60:        else
                     61:            (*src_req->input_stream->isa->_free)(src_req->input_stream);
                     62:        src_req->input_stream = NULL;
                     63:     }
                     64: #endif
                     65:     /* Remove the request object and our own context object for http */
                     66:     src_net->target = NULL;
                     67:     if (status != HT_INTERRUPTED && HTDNS_socket(src_net->dns) == INVSOC)
                     68:        HTNet_delete(src_net, HT_IGNORE);
                     69:     return YES;
                     70: }
                     71: 
2.1       frystyk    72: /*     HTTPMakeResponse
                     73: **     ----------------
                     74: **     Makes a HTTP/1.0-1.1 response header.
                     75: */
                     76: PRIVATE void HTTPMakeResponse (HTStream * me, HTRequest * request)
                     77: {
                     78:     char linebuf[256];
                     79: 
                     80:     /* Generate the HTTP/1.0 ResponseLine */
                     81:     if (request->error_stack) {
                     82: 
                     83:        /* @@@ WRITE A SMALL HTError_response() function */
                     84:        sprintf(linebuf, "HTTP/1.0 404 Not Found%c%c", CR, LF);
                     85:        
                     86:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     87:     } else {
                     88:        sprintf(linebuf, "HTTP/1.0 200 OK%c%c", CR, LF);
                     89:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     90: 
                     91:        /* Response Headers */
                     92:        if (request->ResponseMask & HT_S_SERVER) {
                     93:            sprintf(linebuf, "Server: %s/%s %s/%s%c%c",
                     94:                    HTLib_appName(), HTLib_appVersion(),
                     95:                    HTLib_name(), HTLib_version(), CR, LF);
                     96:            PUTBLOCK(linebuf, (int) strlen(linebuf));
                     97:        }
                     98:     }
                     99: }
                    100: 
                    101: PRIVATE int HTTPResponse_put_block (HTStream * me, CONST char * b, int l)
                    102: {
                    103:     if (!me->target) {
                    104:        return HT_WOULD_BLOCK;
                    105:     } else if (me->transparent)
                    106:        return b ? PUTBLOCK(b, l) : HT_OK;
                    107:     else {
                    108:        HTTPMakeResponse(me, me->request);                /* Generate header */
                    109:        me->transparent = YES;
                    110:        return b ? PUTBLOCK(b, l) : HT_OK;
                    111:     }
                    112: }
                    113: 
                    114: PRIVATE int HTTPResponse_put_character (HTStream * me, char c)
                    115: {
                    116:     return HTTPResponse_put_block(me, &c, 1);
                    117: }
                    118: 
                    119: PRIVATE int HTTPResponse_put_string (HTStream * me, CONST char * s)
                    120: {
                    121:     return HTTPResponse_put_block(me, s, strlen(s));
                    122: }
                    123: 
                    124: /*
                    125: **     Flushes data but doesn't free stream object
                    126: */
                    127: PRIVATE int HTTPResponse_flush (HTStream * me)
                    128: {
                    129:     int status = HTTPResponse_put_block(me, NULL, 0);
                    130:     return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
                    131: }
                    132: 
                    133: /*
                    134: **     Flushes data and frees stream object
                    135: */
                    136: PRIVATE int HTTPResponse_free (HTStream * me)
                    137: {
                    138:     int status = HTTPResponse_flush(me);
                    139:     if (status != HT_WOULD_BLOCK) {
                    140:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    141:            return HT_WOULD_BLOCK;
2.2       frystyk   142:        Cleanup(me);
2.1       frystyk   143:     }
                    144:     return status;
                    145: }
                    146: 
                    147: PRIVATE int HTTPResponse_abort (HTStream * me, HTList * e)
                    148: {
                    149:     if (me->target) (*me->target->isa->abort)(me->target, e);
2.2       frystyk   150:     Cleanup(me);
2.1       frystyk   151:     if (PROT_TRACE) TTYPrint(TDEST, "HTTPResponse ABORTING...\n");
                    152:     return HT_ERROR;
                    153: }
                    154: 
                    155: /*     HTTPResponse Stream
                    156: **     -----------------
                    157: */
                    158: PRIVATE CONST HTStreamClass HTTPResponseClass =
                    159: {              
                    160:     "HTTPResponse",
                    161:     HTTPResponse_flush,
                    162:     HTTPResponse_free,
                    163:     HTTPResponse_abort,
                    164:     HTTPResponse_put_character,
                    165:     HTTPResponse_put_string,
                    166:     HTTPResponse_put_block
                    167: };
                    168: 
                    169: PUBLIC HTStream * HTTPResponse_new (HTRequest *        request, HTStream * target)
                    170: {
                    171:     HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
                    172:     if (!me) outofmem(__FILE__, "HTTPResponse_new");
                    173:     me->isa = &HTTPResponseClass;
                    174:     me->target = target;
                    175:     me->request = request;
                    176:     me->transparent = NO;
                    177:     return HTMIMERequest_new(request, me);
                    178: }

Webmaster