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