Annotation of libwww/Library/src/HTSocket.c, revision 2.34
2.1 frystyk 1: /* HTSocket.c
2.29 frystyk 2: ** LOAD A SOCKET
2.1 frystyk 3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.34 ! frystyk 6: ** @(#) $Id: HTSocket.c,v 2.33 1998/12/15 05:34:28 frystyk Exp $
2.1 frystyk 7: **
8: **
9: ** HISTORY:
2.29 frystyk 10: ** 6 June 95 HFN Written
2.1 frystyk 11: */
12:
13: /* Library Include files */
2.32 frystyk 14: #include "wwwsys.h"
2.30 frystyk 15: #include "WWWUtil.h"
16: #include "WWWCore.h"
17: #include "WWWTrans.h"
2.8 frystyk 18: #include "HTNetMan.h"
2.1 frystyk 19: #include "HTSocket.h" /* Implemented here */
20:
2.33 frystyk 21: #ifndef RAW_PORT
22: #define RAW_PORT 1024
23: #endif
24:
25: /* Final states have negative value */
26: typedef enum _RAWState {
27: RAW_ERROR = -2,
28: RAW_OK = -1,
29: RAW_BEGIN = 0,
30: RAW_NEED_STREAM,
31: RAW_READ
32: } RawState;
33:
34: /* This is the context structure for the this module */
35: typedef struct _raw_info {
36: RawState state; /* Current State of the connection */
37: HTNet * listen;
38: HTNet * accepted;
39: HTRequest * request;
40: } raw_info;
41:
2.1 frystyk 42: struct _HTStream {
2.25 frystyk 43: const HTStreamClass * isa;
2.1 frystyk 44: };
45:
2.30 frystyk 46: struct _HTInputStream {
47: const HTInputStreamClass * isa;
48: };
49:
2.1 frystyk 50: /* ------------------------------------------------------------------------- */
2.27 frystyk 51:
2.33 frystyk 52: PRIVATE int RawCleanup (HTRequest * request, int status)
53: {
54: HTNet * listen = HTRequest_net(request);
55: raw_info * raw = (raw_info *) HTNet_context(listen);
56:
2.34 ! frystyk 57: HTTRACE(PROT_TRACE, "Raw clean... Called with status %d, net %p\n" _ status _ raw->accepted);
2.33 frystyk 58:
59: if (status == HT_INTERRUPTED) {
60: HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);
61: if (cbf) (*cbf)(request, HT_PROG_INTERRUPT,
62: HT_MSG_NULL, NULL, NULL, NULL);
63: } else if (status == HT_TIMEOUT) {
64: HTAlertCallback * cbf = HTAlert_find(HT_PROG_TIMEOUT);
65: if (cbf) (*cbf)(request, HT_PROG_TIMEOUT,
66: HT_MSG_NULL, NULL, NULL, NULL);
67: }
68:
69: /* Delete both of the Net objects */
70: if (raw->accepted) {
71: HTNet_deleteDup(listen);
72: HTNet_delete(raw->accepted, status);
73: } else {
74: HTNet_delete(listen, HT_ERROR);
75: }
76:
77: HT_FREE(raw);
78: return YES;
79: }
80:
2.17 frystyk 81: /* HTLoadSocket
82: ** ------------
83: ** Given an open socket, this routine loads what ever is on the socket
84: **
85: ** On entry,
86: ** request This is the request structure
87: ** On Exit
88: ** returns HT_ERROR Error has occured in call back
89: ** HT_OK Call back was OK
90: */
2.31 frystyk 91: PRIVATE int SocketEvent (SOCKET soc, void * pVoid, HTEventType type);
92:
93: PUBLIC int HTLoadSocket (SOCKET soc, HTRequest * request)
2.17 frystyk 94: {
2.33 frystyk 95: raw_info * raw; /* Specific protocol information */
2.30 frystyk 96: HTNet * net = HTRequest_net(request);
2.34 ! frystyk 97: HTTRACE(PROT_TRACE, "Load socket. Setting up socket for accept\n");
2.33 frystyk 98: if ((raw = (raw_info *) HT_CALLOC(1, sizeof(raw_info))) == NULL)
99: HT_OUTOFMEM("HTLoadSocket");
100: raw->state = RAW_BEGIN;
101: raw->listen = net;
102: raw->request = request;
103: HTNet_setContext(net, raw);
2.31 frystyk 104: HTNet_setEventCallback(net, SocketEvent);
2.33 frystyk 105: HTNet_setEventParam(net, raw);
2.31 frystyk 106:
2.33 frystyk 107: /* Get it started - ops is ignored */
108: return SocketEvent(soc, raw, HTEvent_BEGIN);
2.31 frystyk 109: }
110:
111: PRIVATE int SocketEvent (SOCKET soc, void * pVoid, HTEventType type)
112: {
2.33 frystyk 113: raw_info * raw = (raw_info *)pVoid;
114: int status = HT_ERROR;
115: HTNet * listen = raw->listen;
116: HTRequest * request = HTNet_request(listen);
117: HTParentAnchor * anchor = HTRequest_anchor(request);
118: HTHost * host = HTNet_host(listen);
119:
120: /*
121: ** Check whether we have been interrupted or timed out
122: */
123: if (type == HTEvent_BEGIN) {
124: raw->state = RAW_BEGIN;
125: } else if (type == HTEvent_CLOSE) { /* Interrupted */
126: RawCleanup(request, HT_INTERRUPTED);
127: return HT_OK;
128: } else if (type == HTEvent_TIMEOUT) {
129: HTRequest_addError(request, ERR_FATAL, NO, HTERR_TIME_OUT,
130: NULL, 0, "HTLoadSocket");
131: RawCleanup(request, HT_TIMEOUT);
132: return HT_OK;
133: } else if (type == HTEvent_END) {
134: RawCleanup(request, HT_OK);
2.17 frystyk 135: return HT_OK;
136: }
2.33 frystyk 137:
138: /* Now jump into the state machine */
139: while (1) {
140: switch(raw->state) {
141: case RAW_BEGIN:
142: status = HTHost_accept(host, listen, &raw->accepted, HTAnchor_physical(anchor), RAW_PORT);
143: host = HTNet_host(listen);
144: if (status == HT_OK) {
145: raw->state = RAW_NEED_STREAM;
146: } else if (status == HT_WOULD_BLOCK || status == HT_PENDING) {
147: return HT_OK;
148: } else
149: raw->state = RAW_ERROR; /* Error or interrupt */
150: break;
151:
152: case RAW_NEED_STREAM:
153: {
154: /*
155: ** Create the stream pipe FROM the channel to the application.
156: ** The target for the input stream pipe is set up using the
157: ** stream stack.
158: */
159: HTStream * in_stream =
160: HTStreamStack(WWW_RAW,
161: HTRequest_outputFormat(request),
162: HTRequest_outputStream(request),
163: request, YES);
164: HTNet_setReadStream(raw->accepted, in_stream);
165: HTRequest_setOutputConnected(request, YES);
166:
167: raw->state = RAW_READ;
168: break;
169: }
170:
171: case RAW_READ:
172: status = HTHost_read(host, raw->accepted);
173: if (status == HT_WOULD_BLOCK)
174: return HT_OK;
175: else if (status==HT_CLOSED)
176: raw->state = RAW_OK;
177: else
178: raw->state = RAW_ERROR;
179: break;
180:
181: case RAW_OK:
182: RawCleanup(request, HT_OK);
183: return HT_OK;
184: break;
185:
186: case RAW_ERROR:
187: RawCleanup(request, HT_ERROR);
188: return HT_OK;
189: break;
190:
191: default:
2.34 ! frystyk 192: HTDEBUGBREAK("Bad raw state %d\n" _ raw->state);
2.33 frystyk 193: }
2.17 frystyk 194: }
195: return HT_OK;
196: }
2.27 frystyk 197:
Webmaster