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

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:     HTParentAnchor *anchor = HTRequest_anchor(request);
                     80: 
                     81:     /* Generate the HTTP/1.0 ResponseLine */
                     82:     if (request->error_stack) {
                     83: 
                     84:        /* @@@ WRITE A SMALL HTError_response() function */
                     85:        sprintf(linebuf, "HTTP/1.0 404 Not Found%c%c", CR, LF);
                     86:        
                     87:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     88:     } else {
                     89:        sprintf(linebuf, "HTTP/1.0 200 OK%c%c", CR, LF);
                     90:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     91: 
                     92:        /* Response Headers */
                     93:        if (request->ResponseMask & HT_S_SERVER) {
                     94:            sprintf(linebuf, "Server: %s/%s %s/%s%c%c",
                     95:                    HTLib_appName(), HTLib_appVersion(),
                     96:                    HTLib_name(), HTLib_version(), CR, LF);
                     97:            PUTBLOCK(linebuf, (int) strlen(linebuf));
                     98:        }
                     99:     }
                    100: }
                    101: 
                    102: PRIVATE int HTTPResponse_put_block (HTStream * me, CONST char * b, int l)
                    103: {
                    104:     if (!me->target) {
                    105:        return HT_WOULD_BLOCK;
                    106:     } else if (me->transparent)
                    107:        return b ? PUTBLOCK(b, l) : HT_OK;
                    108:     else {
                    109:        HTTPMakeResponse(me, me->request);                /* Generate header */
                    110:        me->transparent = YES;
                    111:        return b ? PUTBLOCK(b, l) : HT_OK;
                    112:     }
                    113: }
                    114: 
                    115: PRIVATE int HTTPResponse_put_character (HTStream * me, char c)
                    116: {
                    117:     return HTTPResponse_put_block(me, &c, 1);
                    118: }
                    119: 
                    120: PRIVATE int HTTPResponse_put_string (HTStream * me, CONST char * s)
                    121: {
                    122:     return HTTPResponse_put_block(me, s, strlen(s));
                    123: }
                    124: 
                    125: /*
                    126: **     Flushes data but doesn't free stream object
                    127: */
                    128: PRIVATE int HTTPResponse_flush (HTStream * me)
                    129: {
                    130:     int status = HTTPResponse_put_block(me, NULL, 0);
                    131:     return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
                    132: }
                    133: 
                    134: /*
                    135: **     Flushes data and frees stream object
                    136: */
                    137: PRIVATE int HTTPResponse_free (HTStream * me)
                    138: {
                    139:     int status = HTTPResponse_flush(me);
                    140:     if (status != HT_WOULD_BLOCK) {
                    141:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    142:            return HT_WOULD_BLOCK;
2.2     ! frystyk   143:        Cleanup(me);
2.1       frystyk   144:     }
                    145:     return status;
                    146: }
                    147: 
                    148: PRIVATE int HTTPResponse_abort (HTStream * me, HTList * e)
                    149: {
                    150:     if (me->target) (*me->target->isa->abort)(me->target, e);
2.2     ! frystyk   151:     Cleanup(me);
2.1       frystyk   152:     if (PROT_TRACE) TTYPrint(TDEST, "HTTPResponse ABORTING...\n");
                    153:     return HT_ERROR;
                    154: }
                    155: 
                    156: /*     HTTPResponse Stream
                    157: **     -----------------
                    158: */
                    159: PRIVATE CONST HTStreamClass HTTPResponseClass =
                    160: {              
                    161:     "HTTPResponse",
                    162:     HTTPResponse_flush,
                    163:     HTTPResponse_free,
                    164:     HTTPResponse_abort,
                    165:     HTTPResponse_put_character,
                    166:     HTTPResponse_put_string,
                    167:     HTTPResponse_put_block
                    168: };
                    169: 
                    170: PUBLIC HTStream * HTTPResponse_new (HTRequest *        request, HTStream * target)
                    171: {
                    172:     HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
                    173:     if (!me) outofmem(__FILE__, "HTTPResponse_new");
                    174:     me->isa = &HTTPResponseClass;
                    175:     me->target = target;
                    176:     me->request = request;
                    177:     me->transparent = NO;
                    178:     return HTMIMERequest_new(request, me);
                    179: }

Webmaster