Annotation of libwww/Library/src/HTTPRes.c, revision 2.2.2.1
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