Annotation of libwww/Library/src/HTChannl.c, revision 2.12.2.1
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.1! eric 6: ** @(#) $Id: HTChannl.c,v 2.12 1996/08/24 18:09:48 frystyk 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: }
68:
69: /* Close the file */
70: if (ch->fp) {
71: fclose(ch->fp);
72: if (PROT_TRACE)
73: HTTrace("Channel..... Deleted %p, file %p\n", ch, ch->fp);
74: }
75: HT_FREE(ch);
76: }
77: }
78:
79: /*
80: ** A channel is uniquely identified by a socket.
81: ** Note that we don't create the input and output stream - they are
2.10 frystyk 82: ** created later.
2.1 frystyk 83: **
84: ** We only keep a hash on sockfd's as we don't have to look for channels
85: ** for ANSI file descriptors.
86: */
2.12.2.1! eric 87: PUBLIC HTChannel * HTChannel_new (SOCKET sockfd, BOOL active)
2.1 frystyk 88: {
2.12.2.1! eric 89: HTList * list = NULL;
! 90: HTChannel * ch = NULL;
! 91: int hash = sockfd < 0 ? 0 : HASH(sockfd);
! 92: if (PROT_TRACE) HTTrace("Channel..... Hash value is %d\n", hash);
! 93: if (!channels) {
! 94: if (!(channels = (HTList **) HT_CALLOC(HASH_SIZE,sizeof(HTList*))))
! 95: HT_OUTOFMEM("HTChannel_new");
2.1 frystyk 96: }
2.12.2.1! eric 97: if (!channels[hash]) channels[hash] = HTList_new();
! 98: list = channels[hash];
! 99: if ((ch = (HTChannel *) HT_CALLOC(1, sizeof(HTChannel))) == NULL)
! 100: HT_OUTOFMEM("HTChannel_new");
! 101: ch->sockfd = sockfd;
! 102: ch->active = active;
! 103: ch->semaphore = 1;
! 104: HTList_addObject(list, (void *) ch);
! 105:
! 106: if (PROT_TRACE) HTTrace("Channel..... Added %p to list %p\n", ch,list);
! 107: return ch;
2.1 frystyk 108: }
109:
110: /*
111: ** Look for a channel object if we for some reason should have lost it
112: ** Returns NULL if nothing found
113: */
114: PUBLIC HTChannel * HTChannel_find (SOCKET sockfd)
115: {
116: if (channels && sockfd != INVSOC) {
117: int hash = HASH(sockfd);
118: HTList * list = channels[hash];
119: if (list) {
120: HTChannel * ch = NULL;
121: while ((ch = (HTChannel *) HTList_nextObject(list)))
122: if (ch->sockfd == sockfd) return ch;
123: }
124: }
125: return NULL;
126: }
127:
128: /*
129: ** When deleting a channel we first look at if there are no more requests
130: ** using the channel (the semaphore is <= 0). Then, if the socket supports
131: ** persistent connections then we register the channel in the Host cache
132: ** and wait until the other end closes it or we get a time out on our side
133: */
2.6 eric 134: PUBLIC BOOL HTChannel_delete (HTChannel * channel, int status)
2.1 frystyk 135: {
136: if (channel) {
2.2 frystyk 137: if (PROT_TRACE) HTTrace("Channel..... Delete %p with semaphore %d\n",
2.1 frystyk 138: channel, channel->semaphore);
139: /*
140: ** We call the free methods on both the input stream and the output
141: ** stream so that we can free up the stream pipes. However, note that
142: ** this doesn't mean that we close the input stream and output stream
143: ** them selves - only the generic streams
144: */
2.12 frystyk 145: if (status != HT_IGNORE) {
146: if (channel->input)
147: if (status == HT_INTERRUPTED)
148: (*channel->input->isa->abort)(channel->input, NULL);
149: else
150: (*channel->input->isa->_free)(channel->input);
151: if (channel->output)
152: if (status == HT_INTERRUPTED)
153: (*channel->output->isa->abort)(channel->output, NULL);
154: else
155: (*channel->output->isa->_free)(channel->output);
156: }
2.1 frystyk 157:
158: /*
159: ** Check whether this channel is used by other objects or we can
160: ** delete it and free memory.
161: */
162: if (channel->semaphore <= 0 && channels) {
163: int hash = HASH(channel->sockfd);
164: HTList * list = channels[hash];
165: if (list) {
166: HTList_removeObject(list, (void *) channel);
167: free_channel(channel);
168: return YES;
169: }
2.8 frystyk 170: } else
171: HTChannel_downSemaphore(channel);
2.1 frystyk 172: }
173: return NO;
174: }
175:
176: /* HTChannel_deleteAll
177: ** -------------------
178: ** Destroys all channels. This is called by HTLibTerminate(0
179: */
2.9 frystyk 180: PUBLIC BOOL HTChannel_deleteAll (void)
2.1 frystyk 181: {
182: if (channels) {
183: HTList * cur;
184: int cnt;
185: for (cnt=0; cnt<HASH_SIZE; cnt++) {
186: if ((cur = channels[cnt])) {
187: HTChannel * pres;
188: while ((pres = (HTChannel *) HTList_nextObject(cur)) != NULL)
189: free_channel(pres);
190: }
191: HTList_delete(channels[cnt]);
192: }
193: HT_FREE(channels);
194: }
195: return YES;
196: }
197:
198: /*
2.10 frystyk 199: ** Return the socket associated with this channel
2.1 frystyk 200: */
2.10 frystyk 201: PUBLIC SOCKET HTChannel_socket (HTChannel * channel)
2.1 frystyk 202: {
2.10 frystyk 203: return channel ? channel->sockfd : INVSOC;
2.1 frystyk 204: }
205:
2.12.2.1! eric 206: PUBLIC void HTChannel_setSocket (HTChannel * channel, SOCKET socket)
! 207: {
! 208: if (channel)
! 209: channel->sockfd = socket;
! 210: }
! 211:
2.10 frystyk 212: /*
213: ** Return the file descriptor associated with this channel
214: */
215: PUBLIC FILE * HTChannel_file (HTChannel * channel)
2.1 frystyk 216: {
2.10 frystyk 217: return channel ? channel->fp : NULL;
2.1 frystyk 218: }
219:
220: /*
2.10 frystyk 221: ** We keep the associated Host object in case we have a
222: ** sleeping connection.
2.1 frystyk 223: */
2.10 frystyk 224: PUBLIC BOOL HTChannel_setHost (HTChannel * ch, HTHost * host)
2.1 frystyk 225: {
2.12.2.1! eric 226: if (ch) {
2.10 frystyk 227: ch->host = host;
228: return YES;
229: }
230: return NO;
2.4 frystyk 231: }
232:
2.10 frystyk 233: PUBLIC HTHost * HTChannel_host (HTChannel * ch)
2.4 frystyk 234: {
2.10 frystyk 235: return (ch ? ch->host : NULL);
2.1 frystyk 236: }
237:
238: /*
239: ** Increase the semaphore for this channel
240: */
241: PUBLIC void HTChannel_upSemaphore (HTChannel * channel)
242: {
243: if (channel) {
244: channel->semaphore++;
245: if (PROT_TRACE)
246: HTTrace("Channel..... Semaphore increased to %d for channel %p\n",
247: channel->semaphore, channel);
248: }
249: }
250:
251: /*
252: ** Decrease the semaphore for this channel
253: */
254: PUBLIC void HTChannel_downSemaphore (HTChannel * channel)
255: {
256: if (channel) {
257: channel->semaphore--;
258: if (channel->semaphore <= 0) channel->semaphore = 0;
259: if (PROT_TRACE)
260: HTTrace("Channel..... Semaphore decreased to %d for channel %p\n",
2.7 frystyk 261: channel->semaphore, channel);
262: }
263: }
264:
265: /*
266: ** Explicitly set the semaphore for this channel
267: */
268: PUBLIC void HTChannel_setSemaphore (HTChannel * channel, int semaphore)
269: {
270: if (channel) {
271: channel->semaphore = semaphore;
272: if (channel->semaphore <= 0) channel->semaphore = 0;
273: if (PROT_TRACE)
274: HTTrace("Channel..... Semaphore set to %d for channel %p\n",
2.1 frystyk 275: channel->semaphore, channel);
276: }
277: }
278:
279: /*
280: ** Create the input stream and bind it to the channel
281: ** Please read the description in the HTIOStream module on the parameters
282: */
2.10 frystyk 283: PUBLIC BOOL HTChannel_setInput (HTChannel * ch, HTInputStream * input)
2.1 frystyk 284: {
285: if (ch) {
286: ch->input = input;
287: return YES;
288: }
289: return NO;
290: }
291:
292: PUBLIC HTInputStream * HTChannel_input (HTChannel * ch)
293: {
294: return ch ? ch->input : NULL;
295: }
296:
297: /*
298: ** Create the output stream and bind it to the channel
299: ** Please read the description in the HTIOStream module on the parameters
300: */
2.10 frystyk 301: PUBLIC BOOL HTChannel_setOutput (HTChannel * ch, HTOutputStream * output)
2.1 frystyk 302: {
303: if (ch) {
304: ch->output = output;
305: return YES;
306: }
307: return NO;
308: }
309:
310: PUBLIC HTOutputStream * HTChannel_output (HTChannel * ch)
311: {
312: return ch ? ch->output : NULL;
313: }
314:
Webmaster