Annotation of libwww/Library/src/HTNet.c, revision 2.69
2.23 frystyk 1: /* HTNet.c
2: ** ASYNCRONOUS SOCKET MANAGEMENT
2.1 frystyk 3: **
2.10 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.4 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.69 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.68 1996/06/03 19:25:24 eric Exp $
2.4 frystyk 7: **
8: ** This is the implementation of the internal library multithreading
2.1 frystyk 9: ** functions. This includes an interrupt handler and a event loop.
10: **
11: ** History:
2.14 frystyk 12: ** 12 June 94 Written by Henrik Frystyk, frystyk@w3.org
2.17 frystyk 13: ** 31 May 95 Charlie Brooks cbrooks@osf.org
14: **
2.1 frystyk 15: */
16:
2.9 frystyk 17: /* Implemention dependent include files */
2.52 frystyk 18: #include "sysdep.h"
2.9 frystyk 19:
2.1 frystyk 20: /* Library include files */
2.59 frystyk 21: #include "WWWUtil.h"
2.16 frystyk 22: #include "HTProt.h"
2.1 frystyk 23: #include "HTError.h"
2.25 frystyk 24: #include "HTAlert.h"
2.37 frystyk 25: #include "HTParse.h"
2.59 frystyk 26: #include "HTTrans.h"
2.23 frystyk 27: #include "HTReqMan.h"
2.65 frystyk 28: #include "HTEvent.h"
2.23 frystyk 29: #include "HTStream.h"
2.24 frystyk 30: #include "HTNetMan.h" /* Implemented here */
2.1 frystyk 31:
2.23 frystyk 32: #ifndef HT_MAX_SOCKETS
33: #define HT_MAX_SOCKETS 6
34: #endif
35:
2.33 frystyk 36: typedef struct _NetCall {
2.30 frystyk 37: HTNetCallback * cbf;
2.60 frystyk 38: void * param; /* Local context */
2.23 frystyk 39: int status; /* Status associated with this callback */
2.33 frystyk 40: } NetCall;
2.23 frystyk 41:
42: struct _HTStream {
2.52 frystyk 43: const HTStreamClass * isa;
2.23 frystyk 44: /* ... */
45: };
46:
47: PRIVATE int HTMaxActive = HT_MAX_SOCKETS; /* Max active requests */
2.33 frystyk 48: PRIVATE HTList *HTBefore = NULL; /* List of call back functions */
49: PRIVATE HTList *HTAfter = NULL; /* List of call back functions */
2.24 frystyk 50:
2.23 frystyk 51: PRIVATE HTList *HTNetActive = NULL; /* List of active requests */
52: PRIVATE HTList *HTNetPending = NULL; /* List of pending requests */
2.24 frystyk 53: PRIVATE HTList *HTNetPersistent = NULL; /* List of persistent connections */
2.1 frystyk 54:
55: /* ------------------------------------------------------------------------- */
56:
2.23 frystyk 57: /*
58: ** Set the max number of simultanous sockets. Default is HT_MAX_SOCKETS
2.1 frystyk 59: */
2.23 frystyk 60: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
61: {
62: if (newmax > 0) {
63: HTMaxActive = newmax;
64: return YES;
65: }
66: return NO;
67: }
68:
69: PUBLIC int HTNet_maxSocket (void)
2.1 frystyk 70: {
2.23 frystyk 71: return HTMaxActive;
72: }
73:
74: /* ------------------------------------------------------------------------- */
2.33 frystyk 75: /* Call Back Functions */
2.23 frystyk 76: /* ------------------------------------------------------------------------- */
77:
2.33 frystyk 78: /* HTNetCall_add
79: ** -------------
80: ** Register a call back function that is to be called on every request.
81: ** Several call back functions can be registered
2.23 frystyk 82: ** in which case all of them are called in the order of which they
83: ** were registered.
84: **
85: ** The status signifies which call back function to call depending of the
86: ** result of the request. This can be
87: **
88: ** HT_ERROR An error occured
89: ** HT_LOADED The document was loaded
90: ** HT_NO_DATA OK, but no data
2.33 frystyk 91: ** HT_REDIRECT If we received a redirection
2.23 frystyk 92: ** HT_RETRY Retry request after at a later time
93: ** HT_ALL All of above
94: */
2.60 frystyk 95: PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback * cbf,
96: void * param, int status)
2.23 frystyk 97: {
2.58 hallam 98: if (CORE_TRACE)
2.60 frystyk 99: HTTrace("Call Add.... HTNetCallback %p with context %p\n",
100: (void *) cbf, param);
2.33 frystyk 101: if (list && cbf) {
2.49 frystyk 102: NetCall *me;
103: if ((me = (NetCall *) HT_CALLOC(1, sizeof(NetCall))) == NULL)
104: HT_OUTOFMEM("HTNetCall_add");
2.33 frystyk 105: me->cbf = cbf;
2.60 frystyk 106: me->param = param;
2.33 frystyk 107: me->status = status;
108: return HTList_addObject(list, (void *) me);
2.23 frystyk 109: }
110: return NO;
111: }
112:
2.33 frystyk 113: /* HTNetCall_delete
114: ** ----------------
115: ** Unregister a call back function from a list
2.23 frystyk 116: */
2.33 frystyk 117: PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
2.23 frystyk 118: {
2.58 hallam 119: if (CORE_TRACE)
2.50 eric 120: HTTrace("Call delete HTNetCallback %p\n", (void *) cbf);
2.33 frystyk 121: if (list && cbf) {
122: HTList *cur = list;
123: NetCall *pres;
124: while ((pres = (NetCall *) HTList_nextObject(cur))) {
2.23 frystyk 125: if (pres->cbf == cbf) {
2.33 frystyk 126: HTList_removeObject(list, (void *) pres);
2.49 frystyk 127: HT_FREE(pres);
2.23 frystyk 128: return YES;
129: }
130: }
131: }
132: return NO;
133: }
2.1 frystyk 134:
2.33 frystyk 135: /* HTNetCall_deleteAll
2.23 frystyk 136: ** -------------------
137: ** Unregisters all call back functions
138: */
2.33 frystyk 139: PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
2.23 frystyk 140: {
2.58 hallam 141: if (CORE_TRACE)
2.50 eric 142: HTTrace("Call delete All callback functions\n");
2.33 frystyk 143: if (list) {
144: HTList *cur = list;
145: NetCall *pres;
146: while ((pres = (NetCall *) HTList_nextObject(cur))) {
147: HTList_removeObject(list, (void *) pres);
2.49 frystyk 148: HT_FREE(pres);
2.23 frystyk 149: }
2.33 frystyk 150: HTList_delete(list);
2.23 frystyk 151: return YES;
152: }
153: return NO;
154: }
155:
2.33 frystyk 156: /* HTNetCall_execute
157: ** -----------------
2.23 frystyk 158: ** Call all the call back functions registered in the list IF not the
159: ** status is HT_IGNORE.
160: ** The callback functions are called in the order of which they
161: ** were registered. At the moment an application callback function is
162: ** called, it can free the request object - it is no longer used by the
163: ** Library.
2.33 frystyk 164: ** Returns what the last callback function returns
2.23 frystyk 165: */
2.33 frystyk 166: PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
2.23 frystyk 167: {
2.33 frystyk 168: int ret = HT_OK;
169: if (list && request && status != HT_IGNORE) {
170: int cnt = HTList_count(list);
2.23 frystyk 171: while (--cnt >= 0) {
2.33 frystyk 172: NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
2.23 frystyk 173: if (pres && (pres->status == status || pres->status == HT_ALL)) {
2.58 hallam 174: if (CORE_TRACE)
2.50 eric 175: HTTrace("Net callback %p (request=%p, status=%d)\n",
2.23 frystyk 176: (void *) pres->cbf, request, status);
2.60 frystyk 177: if ((ret=(*(pres->cbf))(request, pres->param,status)) != HT_OK)
178: break;
2.23 frystyk 179: }
180: }
2.1 frystyk 181: }
2.33 frystyk 182: return ret;
183: }
184:
185: /*
186: ** Global set of callback functions BEFORE the request is issued
187: ** list can be NULL
188: */
189: PUBLIC BOOL HTNet_setBefore (HTList *list)
190: {
2.57 eric 191: /* if (HTBefore) HTNetCall_deleteAll(HTBefore); */
2.33 frystyk 192: HTBefore = list;
193: return YES;
194: }
195:
196: PUBLIC HTList * HTNet_before (void)
197: {
198: return HTBefore;
199: }
200:
201: PUBLIC int HTNet_callBefore (HTRequest *request, int status)
202: {
2.58 hallam 203: int ret;
204: BOOL override = NO;
205: HTList * befores;
206:
207: if ((befores = HTRequest_before(request, &override))) {
208: if ((ret = HTNetCall_execute(befores, request, status)) != HT_OK)
209: return ret;
210: }
211: if (override)
212: return HT_OK;
2.33 frystyk 213: return HTNetCall_execute(HTBefore, request, status);
214: }
215:
2.60 frystyk 216: PUBLIC BOOL HTNetCall_addBefore (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 217: {
218: if (!HTBefore) HTBefore = HTList_new();
2.60 frystyk 219: return HTNetCall_add(HTBefore, cbf, param, status);
2.33 frystyk 220: }
221:
222: /*
223: ** Global set of callback functions AFTER the request is issued
224: ** list can be NULL
225: */
226: PUBLIC BOOL HTNet_setAfter (HTList *list)
227: {
2.57 eric 228: /* if (HTAfter) HTNetCall_deleteAll(HTAfter); */
2.33 frystyk 229: HTAfter = list;
230: return YES;
231: }
232:
233: PUBLIC HTList * HTNet_after (void)
234: {
235: return HTAfter;
236: }
237:
238: PUBLIC int HTNet_callAfter (HTRequest *request, int status)
239: {
2.58 hallam 240: int ret;
241: BOOL override = NO;
242: HTList * afters;
243:
244: if ((afters = HTRequest_after(request, &override))) {
245: if ((ret = HTNetCall_execute(afters, request, status)) != HT_OK)
246: return ret;
247: }
248: if (override)
249: return HT_OK;
2.33 frystyk 250: return HTNetCall_execute(HTAfter, request, status);
251: }
252:
2.60 frystyk 253: PUBLIC BOOL HTNetCall_addAfter (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 254: {
255: if (!HTAfter) HTAfter = HTList_new();
2.60 frystyk 256: return HTNetCall_add(HTAfter, cbf, param, status);
2.1 frystyk 257: }
258:
2.23 frystyk 259: /* ------------------------------------------------------------------------- */
260: /* Request Queue */
261: /* ------------------------------------------------------------------------- */
2.1 frystyk 262:
2.23 frystyk 263: /* HTNet_activeQueue
264: ** -----------------
265: ** Returns the list of active requests that are currently having an open
266: ** connection.
267: ** Returns list of HTNet objects or NULL if error
2.1 frystyk 268: */
2.23 frystyk 269: PUBLIC HTList *HTNet_activeQueue (void)
270: {
271: return HTNetActive;
272: }
2.17 frystyk 273:
2.40 frystyk 274: /* HTNet_idle
275: ** ----------
276: ** Returns whether there are active requests
2.28 frystyk 277: */
2.29 frystyk 278: PUBLIC BOOL HTNet_idle (void)
2.28 frystyk 279: {
2.29 frystyk 280: return HTList_isEmpty(HTNetActive);
2.28 frystyk 281: }
282:
2.40 frystyk 283: /* HTNet_empty
284: ** -----------
285: ** Returns whether there are requests registered or not
286: */
287: PUBLIC BOOL HTNet_isEmpty (void)
288: {
289: return (HTList_isEmpty(HTNetActive) && HTList_isEmpty(HTNetPersistent) &&
290: HTList_isEmpty(HTNetPending));
291: }
292:
2.23 frystyk 293: /* HTNet_pendingQueue
294: ** ------------------
295: ** Returns the list of pending requests that are waiting to become active
296: ** Returns list of HTNet objects or NULL if error
297: */
298: PUBLIC HTList *HTNet_pendingQueue (void)
2.1 frystyk 299: {
2.23 frystyk 300: return HTNetPending;
2.1 frystyk 301: }
302:
2.23 frystyk 303: /* ------------------------------------------------------------------------- */
304: /* Creation and deletion methods */
305: /* ------------------------------------------------------------------------- */
306:
2.27 frystyk 307: /* HTNet_duplicate
308: ** ---------------
309: ** Creates a new HTNet object as a duplicate of the same request.
310: ** Returns YES if OK, else NO
311: ** BUG: We do not check if we have a socket free!
312: */
2.43 frystyk 313: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27 frystyk 314: {
2.43 frystyk 315: HTNet * me;
2.54 eric 316: if (!src) return 0;
2.49 frystyk 317: if ((me = (HTNet *) HT_MALLOC(sizeof(HTNet))) == NULL)
318: HT_OUTOFMEM("HTNet_dup");
2.44 frystyk 319: memcpy((void *) me, src, sizeof(HTNet));
2.43 frystyk 320: return me;
2.27 frystyk 321: }
322:
2.30 frystyk 323: /* HTNet_priority
324: ** --------------
325: ** Get the current priority of the Net object
326: */
327: PUBLIC HTPriority HTNet_priority (HTNet * net)
328: {
2.51 frystyk 329: return (net ? net->priority : HT_PRIORITY_INV);
2.30 frystyk 330: }
331:
332: /* HTNet_setPriority
333: ** -----------------
334: ** Set the current priority of the Net object
335: ** This will change the priority next time the thread is blocked
336: */
337: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
338: {
339: if (net) {
340: net->priority = priority;
341: return YES;
342: }
343: return NO;
344: }
345:
2.36 frystyk 346: /* create_object
347: ** -------------
348: ** Creates an HTNet object
349: */
2.69 ! frystyk 350: PRIVATE HTNet * create_object (void)
2.36 frystyk 351: {
352: HTNet * me;
2.49 frystyk 353: if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
354: HT_OUTOFMEM("HTNet_new");
2.37 frystyk 355: me->tcpstate = TCP_BEGIN;
2.47 frystyk 356: if (!HTNetActive) HTNetActive = HTList_new();
2.36 frystyk 357: return me;
358: }
359:
2.37 frystyk 360: /* HTNet_new
361: ** ---------
362: ** This function creates a new HTNet object and assigns the socket number
363: ** to it. This is intended to be used when you are going to listen on a
364: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
365: ** call any of the callback functions.
366: ** Returns new object or NULL on error
367: */
2.69 ! frystyk 368: PUBLIC HTNet * HTNet_new (SOCKET sockfd, HTRequest * request)
2.37 frystyk 369: {
2.69 ! frystyk 370: if (sockfd != INVSOC) {
! 371: HTNet * me;
! 372: if ((me = create_object()) == NULL) return NULL;
! 373: if (CORE_TRACE)
! 374: HTTrace("HTNet_new... Create empty Net object %p\n", me);
! 375: me->preemptive = HTRequest_preemptive(request);
! 376: me->priority = HTRequest_priority(request);
! 377: me->sockfd = sockfd;
! 378: me->request = request;
! 379: HTRequest_setNet(request, me);
! 380: return me;
! 381: }
! 382: if (CORE_TRACE) HTTrace("HTNet_new... Can't create empty Net object!\n");
! 383: return NULL;
2.37 frystyk 384: }
385:
2.67 frystyk 386: /* HTNet_newServer
387: ** ---------------
388: ** Create a new HTNet object as a new request to be handled. If we have
389: ** more than HTMaxActive connections already then return NO.
390: ** Returns YES if OK, else NO
2.37 frystyk 391: */
2.69 ! frystyk 392: PUBLIC BOOL HTNet_newServer (HTRequest * request, HTNet * net, char * access)
2.37 frystyk 393: {
394: HTProtocol * protocol;
2.67 frystyk 395: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.37 frystyk 396: if (!request) return NO;
397:
398: /* Find a protocol object for this access scheme */
2.46 frystyk 399: protocol = HTProtocol_find(request, access);
2.67 frystyk 400:
401: /* added - JTD:5/28/96 */
402: /* Find a transport object for this protocol */
403: tp = HTTransport_find(request, HTProtocol_transport(protocol));
404: if (tp == NULL) {
405: if (CORE_TRACE) HTTrace("HTNet....... NO TRANSPORT OBJECT\n");
406: return NO;
407: }
408: /* end of additions - JTD:5/28/96 */
409:
2.69 ! frystyk 410: /* Fill out the net object and bind it to the request object */
! 411: net->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
! 412: net->protocol = protocol;
! 413: net->transport = tp; /* added - JTD:5/28/96 */
! 414: net->priority = HTRequest_priority(request);
! 415: net->request = request;
! 416: HTRequest_setNet(request, net);
! 417: if (!(net->cbf = HTProtocol_server(protocol))) {
2.67 frystyk 418: if (CORE_TRACE) HTTrace("HTNet_new... NO CALL BACK FUNCTION!\n");
419: return NO;
2.37 frystyk 420: }
421: request->retrys++;
422:
423: /* Start the server request */
2.69 ! frystyk 424: HTList_addObject(HTNetActive, (void *) net);
2.58 hallam 425: if (CORE_TRACE)
2.69 ! frystyk 426: HTTrace("HTNet_new... starting SERVER request %p with net object %p\n", request, net);
! 427: (*(net->cbf))(net->sockfd, request, FD_NONE);
2.37 frystyk 428: return YES;
429: }
2.36 frystyk 430:
2.30 frystyk 431: /* HTNet_new
432: ** ---------
2.23 frystyk 433: ** Create a new HTNet object as a new request to be handled. If we have
434: ** more than HTMaxActive connections already then put this into the
435: ** pending queue, else start the request by calling the call back
436: ** function registered with this access method.
437: ** Returns YES if OK, else NO
438: */
2.37 frystyk 439: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 440: {
2.33 frystyk 441: int status;
2.59 frystyk 442: HTNet * me = NULL;
443: HTProtocol * protocol = NULL;
444: HTTransport * tp = NULL;
2.37 frystyk 445: char * physical = NULL;
2.27 frystyk 446: if (!request) return NO;
2.33 frystyk 447: /*
448: ** First we do all the "BEFORE" callbacks in order to see if we are to
449: ** continue with this request or not. If we receive a callback status
450: ** that is NOT HT_OK then jump directly to the after callbacks and return
451: */
2.58 hallam 452: if ((status = HTNet_callBefore(request, HT_OK)) != HT_OK) {
453: HTNet_callAfter(request, status);
2.33 frystyk 454: return YES;
455: }
456:
2.36 frystyk 457: /*
458: ** If no translation was provided by the application then use the anchor
459: ** address directly
460: */
2.33 frystyk 461: if (!(physical = HTAnchor_physical(request->anchor)) || !*physical) {
2.36 frystyk 462: char * addr = HTAnchor_address((HTAnchor *) request->anchor);
2.58 hallam 463: if (CORE_TRACE) HTTrace("HTNet New... Using default address\n");
2.36 frystyk 464: HTAnchor_setPhysical(request->anchor, addr);
2.37 frystyk 465: physical = HTAnchor_physical(request->anchor);
2.49 frystyk 466: HT_FREE(addr);
2.33 frystyk 467: }
468:
2.37 frystyk 469: /* Find a protocol object for this access scheme */
470: {
471: char * access = HTParse(physical, "", PARSE_ACCESS);
472: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.58 hallam 473: if (CORE_TRACE) HTTrace("HTNet_new... NO PROTOCOL OBJECT\n");
2.49 frystyk 474: HT_FREE(access);
2.37 frystyk 475: return NO;
476: }
2.49 frystyk 477: HT_FREE(access);
2.37 frystyk 478: }
2.59 frystyk 479:
480: /* Find a transport object for this protocol */
481: tp = HTTransport_find(request, HTProtocol_transport(protocol));
482: if (tp == NULL) {
2.60 frystyk 483: if (CORE_TRACE) HTTrace("HTNet....... NO TRANSPORT OBJECT\n");
2.59 frystyk 484: return NO;
485: }
486:
2.23 frystyk 487: /* Create new net object and bind it to the request object */
2.69 ! frystyk 488: if ((me = create_object()) == NULL) return NO;
2.45 frystyk 489: me->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
2.69 ! frystyk 490: me->priority = HTRequest_priority(request);
2.23 frystyk 491: me->sockfd = INVSOC;
2.59 frystyk 492: me->protocol = protocol;
493: me->transport = tp;
2.69 ! frystyk 494: me->request = request;
! 495: HTRequest_setNet(request, me);
2.37 frystyk 496: if (!(me->cbf = HTProtocol_client(protocol))) {
2.58 hallam 497: if (CORE_TRACE) HTTrace("HTNet_new... NO CALL BACK FUNCTION!\n");
2.49 frystyk 498: HT_FREE(me);
2.23 frystyk 499: return NO;
500: }
2.25 frystyk 501: request->retrys++;
2.23 frystyk 502:
503: /*
504: ** Check if we can start the request, else put it into pending queue
505: ** If so then call the call back function associated with the anchor.
506: ** We use the INVSOC as we don't have a valid socket yet!
507: */
508: if (HTList_count(HTNetActive) < HTMaxActive) {
509: HTList_addObject(HTNetActive, (void *) me);
2.58 hallam 510: if (CORE_TRACE)
2.50 eric 511: HTTrace("HTNet_new... starting request %p (retry=%d) with net object %p\n",
2.43 frystyk 512: request, request->retrys, me);
2.25 frystyk 513: (*(me->cbf))(me->sockfd, request, FD_NONE);
2.23 frystyk 514: } else {
2.35 frystyk 515: HTAlertCallback *cbf = HTAlert_find(HT_PROG_WAIT);
2.23 frystyk 516: if (!HTNetPending) HTNetPending = HTList_new();
2.58 hallam 517: if (CORE_TRACE)
2.50 eric 518: HTTrace("HTNet_new... request %p registered as pending\n",
2.25 frystyk 519: request);
2.35 frystyk 520: if (cbf) (*cbf)(request, HT_PROG_WAIT, HT_MSG_NULL, NULL, NULL, NULL);
2.25 frystyk 521: HTList_addObject(HTNetPending, (void *) me);
2.23 frystyk 522: }
2.36 frystyk 523: return YES;
524: }
525:
2.23 frystyk 526: /* delete_object
527: ** -------------
528: ** Deletes an HTNet object
2.40 frystyk 529: ** Return YES if OK, else NO
2.15 frystyk 530: */
2.23 frystyk 531: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15 frystyk 532: {
2.58 hallam 533: if (CORE_TRACE)
2.50 eric 534: HTTrace("HTNet_delete Remove net object %p\n", net);
2.23 frystyk 535: if (net) {
536:
537: /* Free stream with data FROM network to application */
2.59 frystyk 538: #if 0
2.23 frystyk 539: if (net->target) {
540: if (status == HT_INTERRUPTED)
541: (*net->target->isa->abort)(net->target, NULL);
542: else
543: (*net->target->isa->_free)(net->target);
2.48 frystyk 544: net->target = NULL;
2.23 frystyk 545: }
2.59 frystyk 546: #endif
2.23 frystyk 547:
548: /* Close socket */
2.62 eric 549: if (net->channel) {
2.64 eric 550: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
2.68 eric 551: HTChannel_delete(net->channel, status);
2.59 frystyk 552: if (HTHost_channel(net->host) == NULL) {
553: if (CORE_TRACE)
554: HTTrace("HTNet_delete closing %d\n", net->sockfd);
2.24 frystyk 555: } else {
2.59 frystyk 556: if (CORE_TRACE)
557: HTTrace("HTNet_delete keeping %d\n", net->sockfd);
2.25 frystyk 558: /* Here we should probably use a low priority */
2.64 eric 559: HTEvent_register(net->sockfd, 0, (SockOps) FD_READ,
2.59 frystyk 560: HTHost_catchClose, net->priority);
2.24 frystyk 561: }
2.62 eric 562: HTChannel_downSemaphore(net->channel);
2.63 eric 563: net->channel = NULL;
2.23 frystyk 564: }
2.69 ! frystyk 565: HTRequest_setNet(net->request, NULL); /* Break link to request */
2.49 frystyk 566: HT_FREE(net);
2.23 frystyk 567: return status ? NO : YES;
568: }
569: return NO;
570: }
571:
572: /* HTNet_delete
573: ** ------------
574: ** Deletes the HTNet object from the list of active requests and calls
575: ** any registered call back functions IF not the status is HT_IGNORE.
576: ** This is used if we have internal requests that the app doesn't know
577: ** about. We also see if we have pending requests that can be started
578: ** up now when we have a socket free.
579: ** The callback functions are called in the reverse order of which they
580: ** were registered (last one first)
2.40 frystyk 581: ** Return YES if OK, else NO
2.23 frystyk 582: */
583: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
584: {
2.58 hallam 585: if (CORE_TRACE)
2.50 eric 586: HTTrace("HTNetDelete. Object and call callback functions\n");
2.23 frystyk 587: if (HTNetActive && net) {
2.36 frystyk 588: SOCKET cs = net->sockfd; /* Current sockfd */
2.23 frystyk 589:
590: /* Remove object and call callback functions */
591: HTRequest *request = net->request;
2.42 frystyk 592: if (HTList_removeObject(HTNetActive, (void *) net) != YES)
2.58 hallam 593: if (CORE_TRACE)
2.50 eric 594: HTTrace("HTNetDelete. %p not registered!\n", net);
2.23 frystyk 595: delete_object(net, status);
2.61 eric 596: HTNet_callAfter(request, status);
2.23 frystyk 597:
2.25 frystyk 598: /*
599: ** See first if we have a persistent request queued up for this socket
600: ** If not then see if there is a pending request
601: */
602: if (HTNetPersistent) {
603: HTList *cur = HTNetPersistent;
604: HTNet *next;
605: while ((next = (HTNet *) HTList_nextObject(cur))) {
606: if (next->sockfd == cs) {
2.58 hallam 607: if (CORE_TRACE)
2.50 eric 608: HTTrace("HTNet delete Launch request %p on WARM socket %d (net object %p)\n",
2.39 frystyk 609: next->request, next->sockfd, next);
2.28 frystyk 610: HTList_addObject(HTNetActive, (void *) next);
611: HTList_removeObject(HTNetPersistent, (void *) next);
2.41 frystyk 612: (*(next->cbf))(next->sockfd, next->request, FD_WRITE);
2.25 frystyk 613: break;
614: }
615: }
616: } else if (HTList_count(HTNetActive) < HTMaxActive &&
617: HTList_count(HTNetPending)) {
2.23 frystyk 618: HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
619: if (next) {
620: HTList_addObject(HTNetActive, (void *) next);
2.58 hallam 621: if (CORE_TRACE)
2.50 eric 622: HTTrace("HTNet delete launch PENDING request %p\n",
2.23 frystyk 623: next->request);
624: (*(next->cbf))(INVSOC, next->request, FD_NONE);
625: }
626: }
627: return YES;
628: }
629: return NO;
630: }
631:
632: /* HTNet_deleteAll
633: ** ---------------
634: ** Deletes all HTNet object that might either be active or pending
2.25 frystyk 635: ** We DO NOT call the call back functions - A crude way of saying goodbye!
2.23 frystyk 636: */
637: PUBLIC BOOL HTNet_deleteAll (void)
638: {
2.58 hallam 639: if (CORE_TRACE)
2.50 eric 640: HTTrace("HTNetDelete. Remove all Net objects, NO callback\n");
2.25 frystyk 641: if (HTNetPersistent) {
642: HTList *cur = HTNetPersistent;
643: HTNet *pres;
644: while ((pres = (HTNet *) HTList_nextObject(cur))) {
645: pres->sockfd = INVSOC; /* Don't close it more than once */
646: delete_object(pres, HT_INTERRUPTED);
647: }
648: HTList_delete(HTNetPersistent);
649: HTNetPersistent = NULL;
650: }
2.23 frystyk 651: if (HTNetPending) {
652: HTList *cur = HTNetPending;
653: HTNet *pres;
654: while ((pres = (HTNet *) HTList_nextObject(cur)))
655: delete_object(pres, HT_INTERRUPTED);
656: HTList_delete(HTNetPending);
657: HTNetPending = NULL;
658: }
659: if (HTNetActive) {
660: HTList *cur = HTNetActive;
661: HTNet *pres;
662: while ((pres = (HTNet *) HTList_nextObject(cur)))
663: delete_object(pres, HT_INTERRUPTED);
664: HTList_delete(HTNetActive);
665: HTNetActive = NULL;
666: }
667: return NO;
2.15 frystyk 668: }
669:
2.25 frystyk 670: /* HTNet_wait
671: ** ----------
672: ** Let a net object wait for a persistent socket. It will be launched
673: ** from the HTNet_delete() function
2.40 frystyk 674: ** Return YES if OK, else NO
2.25 frystyk 675: */
676: PUBLIC BOOL HTNet_wait (HTNet *net)
677: {
678: if (net) {
2.58 hallam 679: if (CORE_TRACE)
2.50 eric 680: HTTrace("HTNet_wait.. request %p is waiting for presistent socket %d\n",
2.40 frystyk 681: net->request, net->sockfd);
682:
683: /* Take it out of the active queue and add it to persistent queue */
684: if (HTList_removeObject(HTNetActive, (void *) net) != YES) {
2.58 hallam 685: if (CORE_TRACE) HTTrace("HTNet_wait.. not registered!\n");
2.40 frystyk 686: return NO;
687: }
2.25 frystyk 688: if (!HTNetPersistent) HTNetPersistent = HTList_new();
2.40 frystyk 689: return HTList_addObject(HTNetPersistent, (void *) net);
2.25 frystyk 690: }
691: return NO;
692: }
693:
2.23 frystyk 694: /* ------------------------------------------------------------------------- */
695: /* Killing requests */
696: /* ------------------------------------------------------------------------- */
697:
698: /* HTNet_kill
699: ** ----------
700: ** Kill the request by calling the call back function with a request for
701: ** closing the connection. Does not remove the object. This is done by
702: ** HTNet_delete() function which is called by the load routine.
703: ** Returns OK if success, NO on error
704: */
705: PUBLIC BOOL HTNet_kill (HTNet * me)
706: {
707: if (HTNetActive && me) {
2.25 frystyk 708: HTList *cur = HTNetActive;
2.23 frystyk 709: HTNet *pres;
2.25 frystyk 710: while ((pres = (HTNet *) HTList_nextObject(cur))) {
2.23 frystyk 711: if (pres == me) {
2.25 frystyk 712: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 713: return YES;
714: }
715: }
716: }
2.58 hallam 717: if (CORE_TRACE)
2.50 eric 718: HTTrace("HTNet_kill.. object %p is not registered\n", me);
2.23 frystyk 719: return NO;
720: }
721:
722: /* HTNet_killAll
723: ** -------------
724: ** Kills all registered (active+pending) requests by calling the call
725: ** back function with a request for closing the connection. We do not
726: ** remove the HTNet object as it is done by HTNet_delete().
727: ** Returns OK if success, NO on error
728: */
729: PUBLIC BOOL HTNet_killAll (void)
730: {
731: HTNet *pres;
2.58 hallam 732: if (CORE_TRACE)
2.50 eric 733: HTTrace("HTNet_kill.. ALL registered requests!!!\n");
2.23 frystyk 734:
2.25 frystyk 735: /* We start off in persistent queue so we avoid racing */
736: if (HTNetPersistent) {
737: while ((pres = (HTNet *) HTList_lastObject(HTNetPersistent)) != NULL) {
738: pres->sockfd = INVSOC;
739: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
740: HTList_removeObject(HTNetPersistent, pres);
741: }
742: }
2.23 frystyk 743: if (HTNetPending) {
744: while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
2.25 frystyk 745: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 746: HTList_removeObject(HTNetPending, pres);
747: }
748: }
749: if (HTNetActive) {
750: while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
2.25 frystyk 751: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 752: }
753: return YES;
754: }
2.38 frystyk 755:
756: /* ------------------------------------------------------------------------- */
2.59 frystyk 757: /* Connection Specifics */
758: /* ------------------------------------------------------------------------- */
759:
760: /* HTNet_Persistent
761: ** ----------------
762: ** Check whether the net object handles persistent connections
763: ** If we have a DNS entry then check that as well.
764: */
765: PUBLIC BOOL HTNet_persistent (HTNet * net)
766: {
767: return (net && HTHost_isPersistent(net->host));
768: }
769:
770: /* HTNet_persistent
771: ** ----------------
772: ** Set the net object to handle persistent connections
773: ** If we also have a DNS entry then update that as well
774: */
775: PUBLIC BOOL HTNet_setPersistent (HTNet * net, BOOL persistent)
776: {
777: if (net) {
2.60 frystyk 778: if (CORE_TRACE) HTTrace("Net......... Persistent connection set %s\n",
2.59 frystyk 779: persistent ? "ON" : "OFF");
780: if (persistent)
781: HTHost_setChannel(net->host, net->channel);
782: else
783: HTHost_clearChannel(net->host);
784: }
785: return NO;
786: }
787:
788: /* ------------------------------------------------------------------------- */
2.38 frystyk 789: /* Data Access Methods */
790: /* ------------------------------------------------------------------------- */
2.66 frystyk 791:
792: /*
793: ** Context pointer to be used in context call back function
794: */
795: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
796: {
797: if (net) {
798: net->context = context;
799: return YES;
800: }
801: return NO;
802: }
803:
804: PUBLIC void * HTNet_context (HTNet * net)
805: {
806: return net ? net->context : NULL;
807: }
2.38 frystyk 808:
809: /*
2.60 frystyk 810: ** Get and set the socket number
811: */
812: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
813: {
814: if (net) {
815: net->sockfd = sockfd;
816: return YES;
817: }
818: return NO;
819: }
820:
821: PUBLIC SOCKET HTNet_socket (HTNet * net)
822: {
823: return (net ? net->sockfd : INVSOC);
2.69 ! frystyk 824: }
! 825:
! 826: /*
! 827: ** Get and set the HTRequest object
! 828: */
! 829: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
! 830: {
! 831: if (net && request) {
! 832: net->request = request;
! 833: return YES;
! 834: }
! 835: return NO;
! 836: }
! 837:
! 838: PUBLIC HTRequest * HTNet_request (HTNet * net)
! 839: {
! 840: return (net ? net->request : NULL);
2.60 frystyk 841: }
842:
843: /*
2.59 frystyk 844: ** Get and set the HTTransport object
2.38 frystyk 845: */
2.59 frystyk 846: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
2.38 frystyk 847: {
2.59 frystyk 848: if (net && tp) {
849: net->transport = tp;
2.38 frystyk 850: return YES;
851: }
852: return NO;
853: }
854:
2.59 frystyk 855: PUBLIC HTTransport * HTNet_transport (HTNet * net)
2.38 frystyk 856: {
2.59 frystyk 857: return (net ? net->transport : NULL);
2.38 frystyk 858: }
859:
2.55 frystyk 860: /*
2.59 frystyk 861: ** Get and set the HTChannel object
2.55 frystyk 862: */
2.59 frystyk 863: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 864: {
2.59 frystyk 865: if (net && channel) {
866: net->channel = channel;
2.55 frystyk 867: return YES;
868: }
869: return NO;
870: }
871:
2.59 frystyk 872: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 873: {
2.59 frystyk 874: return (net ? net->channel : NULL);
875: }
876:
877: /*
878: ** Get and set the HTHost object
879: */
880: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
881: {
882: if (net && host) {
883: net->host = host;
884: return YES;
885: }
886: return NO;
887: }
888:
889: PUBLIC HTHost * HTNet_host (HTNet * net)
890: {
891: return (net ? net->host : NULL);
892: }
893:
894: /*
895: ** Get and set the HTdns object
896: */
897: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
898: {
899: if (net && dns) {
900: net->dns = dns;
901: return YES;
902: }
903: return NO;
904: }
905:
906: PUBLIC HTdns * HTNet_dns (HTNet * net)
907: {
908: return (net ? net->dns : NULL);
909: }
910:
911:
912: /*
913: ** Create the input stream and bind it to the channel
914: ** Please read the description in the HTIOStream module for the parameters
915: */
916: PUBLIC HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
917: void * param, int mode)
918: {
919: if (net && net->channel && net->transport) {
920: HTTransport * tp = net->transport;
921: HTChannel * ch = net->channel;
922: net->input = (*tp->input_new)(net, ch, target, param, mode);
923: HTChannel_setInput(ch, net->input, tp->mode);
924: return net->input;
925: }
2.60 frystyk 926: if (CORE_TRACE) HTTrace("Net......... Can't create input stream\n");
2.59 frystyk 927: return NULL;
928: }
929:
930: /*
931: ** Create the output stream and bind it to the channel
932: ** Please read the description in the HTIOStream module on the parameters
933: */
934: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * net, void * param, int mode)
935: {
936: if (net && net->request && net->channel && net->transport) {
937: HTTransport * tp = net->transport;
938: HTChannel * ch = net->channel;
939: HTOutputStream * output = (*tp->output_new)(net, ch, param, mode);
940: HTChannel_setOutput(ch, output, tp->mode);
941: return output;
942: }
2.60 frystyk 943: if (CORE_TRACE) HTTrace("Net......... Can't create output stream\n");
2.59 frystyk 944: return NULL;
2.55 frystyk 945: }
Webmaster