Annotation of libwww/Library/src/HTChannl.c, revision 2.12.2.3
2.1 frystyk 1: /* HTChannl.c
2: ** CONTAINS STREAMS FOR READING AND WRITING TO AND FROM A TRANSPORT
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.12.2.3! eric 6: ** @(#) $Id: HTChannl.c,v 2.12.2.2 1996/11/02 19:26:20 eric Exp $
2.1 frystyk 7: **
8: **
9: ** HISTORY:
10: ** April 96 HFN Written
11: */
12:
13: /* Library Include files */
14: #include "sysdep.h"
15: #include "WWWUtil.h"
16: #include "HTAlert.h"
2.10 frystyk 17: #include "HTHost.h"
2.1 frystyk 18: #include "HTError.h"
19: #include "HTChannl.h" /* Implemented here */
20:
21: #define HASH_SIZE 67
22: #define HASH(s) ((s) % HASH_SIZE)
23:
24: struct _HTChannel {
25: SOCKET sockfd; /* Socket */
26: FILE * fp;
27: HTInputStream * input; /* Input stream */
28: HTOutputStream * output; /* Output stream */
29: BOOL active; /* Active or passive channel */
30: int semaphore; /* On channel use */
2.10 frystyk 31: HTHost * host; /* Zombie connections */
2.1 frystyk 32: };
33:
34: struct _HTInputStream {
35: const HTInputStreamClass * isa;
36: };
37:
38: struct _HTOutputStream {
39: const HTOutputStreamClass * isa;
40: };
41:
42: PRIVATE HTList ** channels = NULL; /* List of channels */
43:
44: /* ------------------------------------------------------------------------- */
45:
46: PRIVATE void free_channel (HTChannel * ch)
47: {
48: if (ch) {
49:
50: /* Close the input and output stream */
2.11 frystyk 51: if (ch->input) {
52: (*ch->input->isa->close)(ch->input);
53: ch->input = NULL;
54: }
55: if (ch->output) {
56: (*ch->output->isa->close)(ch->output);
57: ch->output = NULL;
58: }
2.1 frystyk 59:
60: /* Close the socket */
61: if (ch->sockfd != INVSOC) {
62: NETCLOSE(ch->sockfd);
2.12.2.1 eric 63: /* HTEvent_unregister(ch->sockfd, all options); */
2.10 frystyk 64: HTNet_decreaseSocket();
2.1 frystyk 65: if (PROT_TRACE)
66: HTTrace("Channel..... Deleted %p, socket %d\n", ch,ch->sockfd);
67: }
2.12.2.2 eric 68: ch->sockfd = INVSOC;
2.1 frystyk 69:
70: /* Close the file */
71: if (ch->fp) {
72: fclose(ch->fp);
73: if (PROT_TRACE)
74: HTTrace("Channel..... Deleted %p, file %p\n", ch, ch->fp);
75: }
76: HT_FREE(ch);
77: }
78: }
79:
80: /*
81: ** A channel is uniquely identified by a socket.
82: ** Note that we don't create the input and output stream - they are
2.10 frystyk 83: ** created later.
2.1 frystyk 84: **
85: ** We only keep a hash on sockfd's as we don't have to look for channels
86: ** for ANSI file descriptors.
87: */
2.12.2.1 eric 88: PUBLIC HTChannel * HTChannel_new (SOCKET sockfd, BOOL active)
2.1 frystyk 89: {
2.12.2.1 eric 90: HTList * list = NULL;
91: HTChannel * ch = NULL;
92: int hash = sockfd < 0 ? 0 : HASH(sockfd);
93: if (PROT_TRACE) HTTrace("Channel..... Hash value is %d\n", hash);
94: if (!channels) {
95: if (!(channels = (HTList **) HT_CALLOC(HASH_SIZE,sizeof(HTList*))))
96: HT_OUTOFMEM("HTChannel_new");
2.1 frystyk 97: }
2.12.2.1 eric 98: if (!channels[hash]) channels[hash] = HTList_new();
99: list = channels[hash];
100: if ((ch = (HTChannel *) HT_CALLOC(1, sizeof(HTChannel))) == NULL)
101: HT_OUTOFMEM("HTChannel_new");
102: ch->sockfd = sockfd;
103: ch->active = active;
104: ch->semaphore = 1;
105: HTList_addObject(list, (void *) ch);
106:
107: if (PROT_TRACE) HTTrace("Channel..... Added %p to list %p\n", ch,list);
108: return ch;
2.1 frystyk 109: }
110:
111: /*
112: ** Look for a channel object if we for some reason should have lost it
113: ** Returns NULL if nothing found
114: */
115: PUBLIC HTChannel * HTChannel_find (SOCKET sockfd)
116: {
117: if (channels && sockfd != INVSOC) {
118: int hash = HASH(sockfd);
119: HTList * list = channels[hash];
120: if (list) {
121: HTChannel * ch = NULL;
122: while ((ch = (HTChannel *) HTList_nextObject(list)))
123: if (ch->sockfd == sockfd) return ch;
124: }
125: }
126: return NULL;
127: }
128:
129: /*
130: ** When deleting a channel we first look at if there are no more requests
131: ** using the channel (the semaphore is <= 0). Then, if the socket supports
132: ** persistent connections then we register the channel in the Host cache
133: ** and wait until the other end closes it or we get a time out on our side
134: */
2.6 eric 135: PUBLIC BOOL HTChannel_delete (HTChannel * channel, int status)
2.1 frystyk 136: {
137: if (channel) {
2.2 frystyk 138: if (PROT_TRACE) HTTrace("Channel..... Delete %p with semaphore %d\n",
2.1 frystyk 139: channel, channel->semaphore);
140: /*
141: ** We call the free methods on both the input stream and the output
142: ** stream so that we can free up the stream pipes. However, note that
143: ** this doesn't mean that we close the input stream and output stream
144: ** them selves - only the generic streams
145: */
2.12 frystyk 146: if (status != HT_IGNORE) {
2.12.2.3! eric 147: if (channel->input) {
2.12 frystyk 148: if (status == HT_INTERRUPTED)
149: (*channel->input->isa->abort)(channel->input, NULL);
150: else
151: (*channel->input->isa->_free)(channel->input);
2.12.2.3! eric 152: channel->input = NULL;
! 153: }
! 154: if (channel->output) {
2.12 frystyk 155: if (status == HT_INTERRUPTED)
156: (*channel->output->isa->abort)(channel->output, NULL);
157: else
158: (*channel->output->isa->_free)(channel->output);
2.12.2.3! eric 159: channel->output = NULL;
! 160: }
2.12 frystyk 161: }
2.1 frystyk 162:
163: /*
164: ** Check whether this channel is used by other objects or we can
165: ** delete it and free memory.
166: */
2.12.2.2 eric 167: if (channel->semaphore <= 0 && channels && channel->sockfd != INVSOC) {
2.1 frystyk 168: int hash = HASH(channel->sockfd);
169: HTList * list = channels[hash];
170: if (list) {
171: HTList_removeObject(list, (void *) channel);
172: free_channel(channel);
173: return YES;
174: }
2.8 frystyk 175: } else
176: HTChannel_downSemaphore(channel);
2.1 frystyk 177: }
178: return NO;
179: }
180:
181: /* HTChannel_deleteAll
182: ** -------------------
183: ** Destroys all channels. This is called by HTLibTerminate(0
184: */
2.9 frystyk 185: PUBLIC BOOL HTChannel_deleteAll (void)
2.1 frystyk 186: {
187: if (channels) {
188: HTList * cur;
189: int cnt;
190: for (cnt=0; cnt<HASH_SIZE; cnt++) {
191: if ((cur = channels[cnt])) {
192: HTChannel * pres;
193: while ((pres = (HTChannel *) HTList_nextObject(cur)) != NULL)
194: free_channel(pres);
195: }
196: HTList_delete(channels[cnt]);
197: }
198: HT_FREE(channels);
199: }
200: return YES;
201: }
202:
203: /*
2.10 frystyk 204: ** Return the socket associated with this channel
2.1 frystyk 205: */
2.10 frystyk 206: PUBLIC SOCKET HTChannel_socket (HTChannel * channel)
2.1 frystyk 207: {
2.10 frystyk 208: return channel ? channel->sockfd : INVSOC;
2.1 frystyk 209: }
210:
2.12.2.1 eric 211: PUBLIC void HTChannel_setSocket (HTChannel * channel, SOCKET socket)
212: {
213: if (channel)
214: channel->sockfd = socket;
215: }
216:
2.10 frystyk 217: /*
218: ** Return the file descriptor associated with this channel
219: */
220: PUBLIC FILE * HTChannel_file (HTChannel * channel)
2.1 frystyk 221: {
2.10 frystyk 222: return channel ? channel->fp : NULL;
2.1 frystyk 223: }
224:
225: /*
2.10 frystyk 226: ** We keep the associated Host object in case we have a
227: ** sleeping connection.
2.1 frystyk 228: */
2.10 frystyk 229: PUBLIC BOOL HTChannel_setHost (HTChannel * ch, HTHost * host)
2.1 frystyk 230: {
2.12.2.1 eric 231: if (ch) {
2.10 frystyk 232: ch->host = host;
233: return YES;
234: }
235: return NO;
2.4 frystyk 236: }
237:
2.10 frystyk 238: PUBLIC HTHost * HTChannel_host (HTChannel * ch)
2.4 frystyk 239: {
2.10 frystyk 240: return (ch ? ch->host : NULL);
2.1 frystyk 241: }
242:
243: /*
244: ** Increase the semaphore for this channel
245: */
246: PUBLIC void HTChannel_upSemaphore (HTChannel * channel)
247: {
248: if (channel) {
249: channel->semaphore++;
250: if (PROT_TRACE)
251: HTTrace("Channel..... Semaphore increased to %d for channel %p\n",
252: channel->semaphore, channel);
253: }
254: }
255:
256: /*
257: ** Decrease the semaphore for this channel
258: */
259: PUBLIC void HTChannel_downSemaphore (HTChannel * channel)
260: {
261: if (channel) {
262: channel->semaphore--;
263: if (channel->semaphore <= 0) channel->semaphore = 0;
264: if (PROT_TRACE)
265: HTTrace("Channel..... Semaphore decreased to %d for channel %p\n",
2.7 frystyk 266: channel->semaphore, channel);
267: }
268: }
269:
270: /*
271: ** Explicitly set the semaphore for this channel
272: */
273: PUBLIC void HTChannel_setSemaphore (HTChannel * channel, int semaphore)
274: {
275: if (channel) {
276: channel->semaphore = semaphore;
277: if (channel->semaphore <= 0) channel->semaphore = 0;
278: if (PROT_TRACE)
279: HTTrace("Channel..... Semaphore set to %d for channel %p\n",
2.1 frystyk 280: channel->semaphore, channel);
281: }
282: }
283:
284: /*
285: ** Create the input stream and bind it to the channel
286: ** Please read the description in the HTIOStream module on the parameters
287: */
2.10 frystyk 288: PUBLIC BOOL HTChannel_setInput (HTChannel * ch, HTInputStream * input)
2.1 frystyk 289: {
290: if (ch) {
291: ch->input = input;
292: return YES;
293: }
294: return NO;
295: }
296:
297: PUBLIC HTInputStream * HTChannel_input (HTChannel * ch)
298: {
299: return ch ? ch->input : NULL;
300: }
301:
302: /*
303: ** Create the output stream and bind it to the channel
304: ** Please read the description in the HTIOStream module on the parameters
305: */
2.10 frystyk 306: PUBLIC BOOL HTChannel_setOutput (HTChannel * ch, HTOutputStream * output)
2.1 frystyk 307: {
308: if (ch) {
309: ch->output = output;
310: return YES;
311: }
312: return NO;
313: }
314:
315: PUBLIC HTOutputStream * HTChannel_output (HTChannel * ch)
316: {
317: return ch ? ch->output : NULL;
318: }
319:
Webmaster