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