HTNet.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:21k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /*      HTNet.c
  2. ** ASYNCRONOUS SOCKET MANAGEMENT
  3. **
  4. ** (c) COPYRIGHT MIT 1995.
  5. ** Please first read the full copyright statement in the file COPYRIGH.
  6. **
  7. ** This is the implementation of the internal library multithreading
  8. ** functions. This includes an interrupt handler and a event loop.
  9. **
  10. ** History:
  11. **   12 June 94 Written by Henrik Frystyk, frystyk@w3.org
  12. **      31 May  95      Charlie Brooks cbrooks@osf.org
  13. **
  14. */
  15. /* Implemention dependent include files */
  16. #include "tcp.h"
  17. /* Library include files */
  18. #include "HTUtils.h"
  19. #include "HTProt.h"
  20. #include "HTError.h"
  21. #include "HTAlert.h"
  22. #include "HTParse.h"
  23. #include "HTReqMan.h"
  24. #include "HTEvntrg.h"
  25. #include "HTStream.h"
  26. #include "HTNetMan.h"  /* Implemented here */
  27. #ifdef WIN32
  28. #include <io.h>
  29. #endif
  30. #ifndef HT_MAX_SOCKETS
  31. #define HT_MAX_SOCKETS 6
  32. #endif
  33. typedef struct _NetCall {
  34.     HTNetCallback * cbf;
  35.     int  status;      /* Status associated with this callback */
  36. } NetCall;
  37. struct _HTStream {
  38.     CONST HTStreamClass * isa;
  39.     /* ... */
  40. };
  41. PRIVATE int  HTMaxActive = HT_MAX_SOCKETS;         /* Max active requests */
  42. PRIVATE HTList *HTBefore = NULL;       /* List of call back functions */
  43. PRIVATE HTList *HTAfter = NULL;              /* List of call back functions */
  44. PRIVATE HTList *HTNetActive = NULL;               /* List of active requests */
  45. PRIVATE HTList *HTNetPending = NULL;  /* List of pending requests */
  46. PRIVATE HTList *HTNetPersistent = NULL;    /* List of persistent connections */
  47. /* ------------------------------------------------------------------------- */
  48. /*
  49. ** Set the max number of simultanous sockets. Default is HT_MAX_SOCKETS
  50. */
  51. PUBLIC BOOL HTNet_setMaxSocket (int newmax)
  52. {
  53.     if (newmax > 0) {
  54. HTMaxActive = newmax;
  55. return YES;
  56.     }
  57.     return NO;
  58. }
  59. PUBLIC int HTNet_maxSocket (void)
  60. {
  61.     return HTMaxActive;
  62. }
  63. /* ------------------------------------------------------------------------- */
  64. /*    Call Back Functions      */
  65. /* ------------------------------------------------------------------------- */
  66. /* HTNetCall_add
  67. ** -------------
  68. ** Register a call back function that is to be called on every request.
  69. ** Several call back functions can be registered
  70. ** in which case all of them are called in the order of which they
  71. ** were registered.
  72. **
  73. ** The status signifies which call back function to call depending of the 
  74. ** result of the request. This can be
  75. **
  76. ** HT_ERROR An error occured
  77. ** HT_LOADED The document was loaded
  78. ** HT_NO_DATA OK, but no data
  79. ** HT_REDIRECT If we received a redirection
  80. ** HT_RETRY Retry request after at a later time
  81. ** HT_ALL All of above
  82. */
  83. PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback *cbf, int status)
  84. {
  85.     if (WWWTRACE) 
  86. TTYPrint(TDEST, "Call Add.... HTNetCallback %pn", (void *) cbf);
  87.     if (list && cbf) {
  88. NetCall *me;
  89. if ((me = (NetCall  *) HT_CALLOC(1, sizeof(NetCall))) == NULL)
  90.     HT_OUTOFMEM("HTNetCall_add");
  91. me->cbf = cbf;
  92. me->status = status;
  93. return HTList_addObject(list, (void *) me);
  94.     }
  95.     return NO;
  96. }
  97. /* HTNetCall_delete
  98. ** ----------------
  99. ** Unregister a call back function from a list
  100. */
  101. PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
  102. {
  103.     if (WWWTRACE) 
  104. TTYPrint(TDEST, "Call delete HTNetCallback %pn", (void *) cbf);
  105.     if (list && cbf) {
  106. HTList *cur = list;
  107. NetCall *pres;
  108. while ((pres = (NetCall *) HTList_nextObject(cur))) {
  109.     if (pres->cbf == cbf) {
  110. HTList_removeObject(list, (void *) pres);
  111. HT_FREE(pres);
  112. return YES;
  113.     }
  114. }
  115.     }
  116.     return NO;
  117. }
  118. /* HTNetCall_deleteAll
  119. ** -------------------
  120. ** Unregisters all call back functions
  121. */
  122. PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
  123. {
  124.     if (WWWTRACE) 
  125. TTYPrint(TDEST, "Call delete All callback functionsn");
  126.     if (list) {
  127. HTList *cur = list;
  128. NetCall *pres;
  129. while ((pres = (NetCall *) HTList_nextObject(cur))) {
  130.     HTList_removeObject(list, (void *) pres);
  131.     HT_FREE(pres);
  132. }
  133. HTList_delete(list);
  134. return YES;
  135.     }
  136.     return NO;
  137. }
  138. /* HTNetCall_execute
  139. ** -----------------
  140. ** Call all the call back functions registered in the list IF not the 
  141. ** status is HT_IGNORE.
  142. ** The callback functions are called in the order of which they
  143. ** were registered. At the moment an application callback function is
  144. ** called, it can free the request object - it is no longer used by the
  145. ** Library.
  146. ** Returns what the last callback function returns
  147. */
  148. PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
  149. {
  150.     int ret = HT_OK;
  151.     if (list && request && status != HT_IGNORE) {
  152. int cnt = HTList_count(list);
  153. while (--cnt >= 0) {
  154.     NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
  155.     if (pres && (pres->status == status || pres->status == HT_ALL)) {
  156. if (WWWTRACE)
  157.     TTYPrint(TDEST,"Net callback %p (request=%p, status=%d)n",
  158.     (void *) pres->cbf, request, status);
  159. if ((ret = (*(pres->cbf))(request, status)) != HT_OK) break;
  160.     }
  161. }
  162.     }
  163.     return ret;
  164. }
  165. /*
  166. ** Global set of callback functions BEFORE the request is issued
  167. ** list can be NULL
  168. */
  169. PUBLIC BOOL HTNet_setBefore (HTList *list)
  170. {
  171.     if (HTBefore) HTNetCall_deleteAll(HTBefore);
  172.     HTBefore = list;
  173.     return YES;
  174. }
  175. PUBLIC HTList * HTNet_before (void)
  176. {
  177.     return HTBefore;
  178. }
  179. PUBLIC int HTNet_callBefore (HTRequest *request, int status)
  180. {
  181.     return HTNetCall_execute(HTBefore, request, status);
  182. }
  183. PUBLIC BOOL HTNetCall_addBefore (HTNetCallback *cbf, int status)
  184. {
  185.     if (!HTBefore) HTBefore = HTList_new();
  186.     return HTNetCall_add(HTBefore, cbf, status);
  187. }
  188. /*
  189. ** Global set of callback functions AFTER the request is issued
  190. ** list can be NULL
  191. */
  192. PUBLIC BOOL HTNet_setAfter (HTList *list)
  193. {
  194.     if (HTAfter) HTNetCall_deleteAll(HTAfter);
  195.     HTAfter = list;
  196.     return YES;
  197. }
  198. PUBLIC HTList * HTNet_after (void)
  199. {
  200.     return HTAfter;
  201. }
  202. PUBLIC int HTNet_callAfter (HTRequest *request, int status)
  203. {
  204.     return HTNetCall_execute(HTAfter, request, status);
  205. }
  206. PUBLIC BOOL HTNetCall_addAfter (HTNetCallback *cbf, int status)
  207. {
  208.     if (!HTAfter) HTAfter = HTList_new();
  209.     return HTNetCall_add(HTAfter, cbf, status);
  210. }
  211. /* ------------------------------------------------------------------------- */
  212. /*    Request Queue      */
  213. /* ------------------------------------------------------------------------- */
  214. /* HTNet_activeQueue
  215. ** -----------------
  216. ** Returns the list of active requests that are currently having an open
  217. ** connection.
  218. ** Returns list of HTNet objects or NULL if error
  219. */
  220. PUBLIC HTList *HTNet_activeQueue (void)
  221. {
  222.     return HTNetActive;
  223. }
  224. /* HTNet_idle
  225. ** ----------
  226. ** Returns whether there are active requests
  227. */
  228. PUBLIC BOOL HTNet_idle (void)
  229. {
  230.     return HTList_isEmpty(HTNetActive);
  231. }
  232. /* HTNet_empty
  233. ** -----------
  234. ** Returns whether there are requests registered or not
  235. */
  236. PUBLIC BOOL HTNet_isEmpty (void)
  237. {
  238.     return (HTList_isEmpty(HTNetActive) && HTList_isEmpty(HTNetPersistent) &&
  239.     HTList_isEmpty(HTNetPending));
  240. }
  241. /* HTNet_pendingQueue
  242. ** ------------------
  243. ** Returns the list of pending requests that are waiting to become active
  244. ** Returns list of HTNet objects or NULL if error
  245. */
  246. PUBLIC HTList *HTNet_pendingQueue (void)
  247. {
  248.     return HTNetPending;
  249. }
  250. /* ------------------------------------------------------------------------- */
  251. /*   Creation and deletion methods        */
  252. /* ------------------------------------------------------------------------- */
  253. /* HTNet_duplicate
  254. ** ---------------
  255. ** Creates a new HTNet object as a duplicate of the same request.
  256. ** Returns YES if OK, else NO
  257. ** BUG: We do not check if we have a socket free!
  258. */
  259. PUBLIC HTNet * HTNet_dup (HTNet * src)
  260. {
  261.     HTNet * me;
  262.     if (!src) return NO;
  263.     if ((me = (HTNet *) HT_MALLOC(sizeof(HTNet))) == NULL)
  264. HT_OUTOFMEM("HTNet_dup");
  265.     memcpy((void *) me, src, sizeof(HTNet));
  266.     return me;
  267. }
  268. /* HTNet_priority
  269. ** --------------
  270. ** Get the current priority of the Net object
  271. */
  272. PUBLIC HTPriority HTNet_priority (HTNet * net)
  273. {
  274.     return (net ? net->priority : -1);
  275. }
  276. /* HTNet_setPriority
  277. ** -----------------
  278. ** Set the current priority of the Net object
  279. ** This will change the priority next time the thread is blocked
  280. */
  281. PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
  282. {
  283.     if (net) {
  284. net->priority = priority;
  285. return YES;
  286.     }
  287.     return NO;
  288. }
  289. /* create_object
  290. ** -------------
  291. ** Creates an HTNet object
  292. */
  293. PRIVATE HTNet * create_object (HTRequest * request)
  294. {
  295.     HTNet * me;
  296.     if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
  297.         HT_OUTOFMEM("HTNet_new");
  298.     me->request = request;
  299.     request->net = me;
  300.     me->tcpstate = TCP_BEGIN;
  301.     if (!HTNetActive) HTNetActive = HTList_new();
  302.     return me;
  303. }
  304. /* HTNet_new
  305. ** ---------
  306. ** This function creates a new HTNet object and assigns the socket number
  307. ** to it. This is intended to be used when you are going to listen on a 
  308. ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
  309. ** call any of the callback functions.
  310. ** Returns new object or NULL on error
  311. */
  312. PUBLIC HTNet * HTNet_new (HTRequest * request, SOCKET sockfd)
  313. {
  314.     HTNet * me;
  315.     if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... Create empty Net objectn");
  316.     if (!request || sockfd==INVSOC) return NULL;
  317.     if ((me = create_object(request)) == NULL) return NULL;
  318.     me->preemptive = request->preemptive;
  319.     me->priority = request->priority;
  320.     me->sockfd = sockfd;
  321.     return me;
  322. }
  323. /* HTNet_newServer
  324. ** ---------------
  325. ** Create a new HTNet object as a new request to be handled. If we have
  326. ** more than HTMaxActive connections already then return NO.
  327. ** Returns YES if OK, else NO
  328. */
  329. PUBLIC BOOL HTNet_newServer (HTRequest * request, SOCKET sockfd, char * access)
  330. {
  331.     HTNet * me;
  332.     HTProtocol * protocol;
  333.     if (!request) return NO;
  334.     /* Check if we can start the request, else return immediately */
  335.     if (HTList_count(HTNetActive) > HTMaxActive) {
  336. if (PROT_TRACE) TTYPrint(TDEST, "HTNet new... NO SOCKET AVAILABLEn");
  337. HTNetCall_execute(HTAfter, request, HT_RETRY);
  338. return YES;
  339.     }
  340.     /* Find a protocol object for this access scheme */
  341.     protocol = HTProtocol_find(request, access);
  342.     /* Create new net object and bind it to the request object */
  343.     if ((me = create_object(request)) == NULL) return NO;
  344.     me->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
  345.     me->priority = request->priority;
  346.     me->sockfd = sockfd;
  347.     if (!(me->cbf = HTProtocol_server(protocol))) {
  348. if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... NO CALL BACK FUNCTION!n");
  349. HT_FREE(me);
  350. return NO;
  351.     }
  352.     request->retrys++;
  353.     /* Start the server request */
  354.     HTList_addObject(HTNetActive, (void *) me);
  355.     if (WWWTRACE)
  356. TTYPrint(TDEST, "HTNet_new... starting SERVER request %p with net object %pn", request, me);
  357.     (*(me->cbf))(me->sockfd, request, FD_NONE);
  358.     return YES;
  359. }
  360. /* HTNet_new
  361. ** ---------
  362. ** Create a new HTNet object as a new request to be handled. If we have
  363. ** more than HTMaxActive connections already then put this into the
  364. ** pending queue, else start the request by calling the call back
  365. ** function registered with this access method. 
  366. ** Returns YES if OK, else NO
  367. */
  368. PUBLIC BOOL HTNet_newClient (HTRequest * request)
  369. {
  370.     int status;
  371.     HTNet * me;
  372.     HTProtocol * protocol;
  373.     char * physical = NULL;
  374.     if (!request) return NO;
  375.     /*
  376.     ** First we do all the "BEFORE" callbacks in order to see if we are to
  377.     ** continue with this request or not. If we receive a callback status
  378.     ** that is NOT HT_OK then jump directly to the after callbacks and return
  379.     */
  380.     if ((status = HTNetCall_execute(HTBefore, request, HT_OK)) != HT_OK) {
  381. HTNetCall_execute(HTAfter, request, status);
  382. return YES;
  383.     }
  384.     /*
  385.     ** If no translation was provided by the application then use the anchor
  386.     ** address directly
  387.     */
  388.     if (!(physical = HTAnchor_physical(request->anchor)) || !*physical) {
  389. char * addr = HTAnchor_address((HTAnchor *) request->anchor);
  390. if (WWWTRACE) TTYPrint(TDEST, "HTNet New... Using default addressn");
  391. HTAnchor_setPhysical(request->anchor, addr);
  392. physical = HTAnchor_physical(request->anchor);
  393. HT_FREE(addr);
  394.     }
  395.     /* Find a protocol object for this access scheme */
  396.     {
  397. char * access = HTParse(physical, "", PARSE_ACCESS);
  398. if ((protocol = HTProtocol_find(request, access)) == NULL) {
  399.     if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... NO PROTOCOL OBJECTn");
  400.     HT_FREE(access);
  401.     return NO;
  402. }
  403. HT_FREE(access);
  404.     }
  405.     /* Create new net object and bind it to the request object */
  406.     if ((me = create_object(request)) == NULL) return NO;
  407.     me->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
  408.     me->priority = request->priority;
  409.     me->sockfd = INVSOC;
  410.     if (!(me->cbf = HTProtocol_client(protocol))) {
  411. if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... NO CALL BACK FUNCTION!n");
  412. HT_FREE(me);
  413. return NO;
  414.     }
  415.     request->retrys++;
  416.     /*
  417.     ** Check if we can start the request, else put it into pending queue
  418.     ** If so then call the call back function associated with the anchor.
  419.     ** We use the INVSOC as we don't have a valid socket yet!
  420.     */
  421.     if (HTList_count(HTNetActive) < HTMaxActive) {
  422. HTList_addObject(HTNetActive, (void *) me);
  423. if (WWWTRACE)
  424.     TTYPrint(TDEST, "HTNet_new... starting request %p (retry=%d) with net object %pn",
  425.     request, request->retrys, me);
  426. (*(me->cbf))(me->sockfd, request, FD_NONE);
  427.     } else {
  428. HTAlertCallback *cbf = HTAlert_find(HT_PROG_WAIT);
  429. if (!HTNetPending) HTNetPending = HTList_new();
  430. if (WWWTRACE)
  431.     TTYPrint(TDEST, "HTNet_new... request %p registered as pendingn",
  432.     request);
  433. if (cbf) (*cbf)(request, HT_PROG_WAIT, HT_MSG_NULL, NULL, NULL, NULL);
  434. HTList_addObject(HTNetPending, (void *) me);
  435.     }
  436.     return YES;
  437. }
  438. /* delete_object
  439. ** -------------
  440. ** Deletes an HTNet object
  441. ** Return YES if OK, else NO
  442. */
  443. PRIVATE BOOL delete_object (HTNet *net, int status)
  444. {
  445.     if (WWWTRACE)
  446. TTYPrint(TDEST, "HTNet_delete Remove net object %pn", net);
  447.     if (net) {
  448. int status = 0;
  449. /* Free stream with data FROM network to application */
  450. if (net->target) {
  451.     if (status == HT_INTERRUPTED)
  452. (*net->target->isa->abort)(net->target, NULL);
  453.     else
  454. (*net->target->isa->_free)(net->target);
  455.     net->target = NULL;
  456. }
  457. /* Close socket */
  458. if (net->sockfd != INVSOC) {
  459.     HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
  460.     if (HTDNS_socket(net->dns) == INVSOC) {
  461. if ((status = NETCLOSE(net->sockfd)) < 0)
  462.     HTRequest_addSystemError(net->request, ERR_FATAL,
  463.      socerrno, NO, "NETCLOSE");
  464. if (WWWTRACE)
  465.     TTYPrint(TDEST, "HTNet_delete closing %dn", net->sockfd);
  466.     } else {
  467. if (WWWTRACE)
  468.     TTYPrint(TDEST, "HTNet_delete keeping %dn", net->sockfd);
  469. HTDNS_clearActive(net->dns);
  470. /* Here we should probably use a low priority */
  471. HTEvent_Register(net->sockfd, net->request, (SockOps) FD_READ,
  472.  HTDNS_closeSocket, net->priority);
  473.     }
  474. }
  475. if (net->isoc)
  476.     HTInputSocket_free(net->isoc);
  477. if (net->request)
  478.     net->request->net = NULL;     /* Break link to request */
  479. HT_FREE(net);
  480. return status ? NO : YES;
  481.     }
  482.     return NO;
  483. }
  484. /* HTNet_delete
  485. ** ------------
  486. ** Deletes the HTNet object from the list of active requests and calls
  487. ** any registered call back functions IF not the status is HT_IGNORE.
  488. ** This is used if we have internal requests that the app doesn't know
  489. ** about. We also see if we have pending requests that can be started
  490. ** up now when we have a socket free.
  491. ** The callback functions are called in the reverse order of which they
  492. ** were registered (last one first)
  493. ** Return YES if OK, else NO
  494. */
  495. PUBLIC BOOL HTNet_delete (HTNet * net, int status)
  496. {
  497.     if (WWWTRACE) 
  498. TTYPrint(TDEST,"HTNetDelete. Object and call callback functionsn");
  499.     if (HTNetActive && net) {
  500. SOCKET cs = net->sockfd;    /* Current sockfd */
  501. /* Remove object and call callback functions */
  502. HTRequest *request = net->request;
  503. if (HTList_removeObject(HTNetActive, (void *) net) != YES)
  504.     if (WWWTRACE)
  505. TTYPrint(TDEST, "HTNetDelete. %p not registered!n", net);
  506.   delete_object(net, status);
  507. HTNetCall_execute(HTAfter, request, status);
  508. /*
  509. ** See first if we have a persistent request queued up for this socket
  510. ** If not then see if there is a pending request
  511. */
  512. if (HTNetPersistent) {
  513.     HTList *cur = HTNetPersistent;
  514.     HTNet *next;
  515.     while ((next = (HTNet *) HTList_nextObject(cur))) {
  516. if (next->sockfd == cs) {
  517.     if (WWWTRACE)
  518. TTYPrint(TDEST, "HTNet delete Launch request %p on WARM socket %d (net object %p)n",
  519.  next->request, next->sockfd, next);
  520.     HTList_addObject(HTNetActive, (void *) next);
  521.     HTList_removeObject(HTNetPersistent, (void *) next);
  522.     (*(next->cbf))(next->sockfd, next->request, FD_WRITE);
  523.     break;
  524. }
  525.     }
  526. } else if (HTList_count(HTNetActive) < HTMaxActive &&
  527.    HTList_count(HTNetPending)) {
  528.     HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
  529.     if (next) {
  530. HTList_addObject(HTNetActive, (void *) next);
  531. if (WWWTRACE)
  532.     TTYPrint(TDEST,"HTNet delete launch PENDING request %pn",
  533.     next->request);
  534. (*(next->cbf))(INVSOC, next->request, FD_NONE);
  535.     }
  536. }
  537. return YES;
  538.     }
  539.     return NO;
  540. }
  541. /* HTNet_deleteAll
  542. ** ---------------
  543. ** Deletes all HTNet object that might either be active or pending
  544. ** We DO NOT call the call back functions - A crude way of saying goodbye!
  545. */
  546. PUBLIC BOOL HTNet_deleteAll (void)
  547. {
  548.     if (WWWTRACE) 
  549. TTYPrint(TDEST, "HTNetDelete. Remove all Net objects, NO callbackn"); 
  550.     if (HTNetPersistent) {
  551. HTList *cur = HTNetPersistent;
  552. HTNet *pres;
  553. while ((pres = (HTNet *) HTList_nextObject(cur))) {
  554.     pres->sockfd = INVSOC;     /* Don't close it more than once */
  555.     delete_object(pres, HT_INTERRUPTED);
  556. }
  557. HTList_delete(HTNetPersistent);
  558. HTNetPersistent = NULL;
  559.     }
  560.     if (HTNetPending) {
  561. HTList *cur = HTNetPending;
  562. HTNet *pres;
  563. while ((pres = (HTNet *) HTList_nextObject(cur)))
  564.     delete_object(pres, HT_INTERRUPTED);
  565. HTList_delete(HTNetPending);
  566. HTNetPending = NULL;
  567.     }
  568.     if (HTNetActive) {
  569. HTList *cur = HTNetActive;
  570. HTNet *pres;
  571. while ((pres = (HTNet *) HTList_nextObject(cur)))
  572.     delete_object(pres, HT_INTERRUPTED);
  573. HTList_delete(HTNetActive);
  574. HTNetActive = NULL;
  575.     }
  576.     return NO;
  577. }
  578. /* HTNet_wait
  579. ** ----------
  580. ** Let a net object wait for a persistent socket. It will be launched
  581. ** from the HTNet_delete() function
  582. ** Return YES if OK, else NO
  583. */
  584. PUBLIC BOOL HTNet_wait (HTNet *net)
  585. {
  586.     if (net) {
  587. if (WWWTRACE)
  588.     TTYPrint(TDEST,"HTNet_wait.. request %p is waiting for presistent socket %dn",
  589.      net->request, net->sockfd);
  590. /* Take it out of the active queue and add it to persistent queue */
  591. if (HTList_removeObject(HTNetActive, (void *) net) != YES) {
  592.     if (WWWTRACE) TTYPrint(TDEST, "HTNet_wait.. not registered!n");
  593.     return NO;
  594. }
  595. if (!HTNetPersistent) HTNetPersistent = HTList_new();
  596. return HTList_addObject(HTNetPersistent, (void *) net);
  597.     }
  598.     return NO;
  599. }
  600. /* ------------------------------------------------------------------------- */
  601. /*         Killing requests        */
  602. /* ------------------------------------------------------------------------- */
  603. /* HTNet_kill
  604. ** ----------
  605. ** Kill the request by calling the call back function with a request for 
  606. ** closing the connection. Does not remove the object. This is done by
  607. ** HTNet_delete() function which is called by the load routine.
  608. ** Returns OK if success, NO on error
  609. */
  610. PUBLIC BOOL HTNet_kill (HTNet * me)
  611. {
  612.     if (HTNetActive && me) {
  613. HTList *cur = HTNetActive;
  614. HTNet *pres;
  615. while ((pres = (HTNet *) HTList_nextObject(cur))) {
  616.     if (pres == me) {
  617. (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
  618. return YES;
  619.     }
  620. }
  621.     }
  622.     if (WWWTRACE)
  623. TTYPrint(TDEST, "HTNet_kill.. object %p is not registeredn", me);
  624.     return NO;
  625. }
  626. /* HTNet_killAll
  627. ** -------------
  628. ** Kills all registered (active+pending) requests by calling the call
  629. ** back function with a request for closing the connection. We do not
  630. ** remove the HTNet object as it is done by HTNet_delete().
  631. ** Returns OK if success, NO on error
  632. */
  633. PUBLIC BOOL HTNet_killAll (void)
  634. {
  635.     HTNet *pres;
  636.     if (WWWTRACE)
  637. TTYPrint(TDEST, "HTNet_kill.. ALL registered requests!!!n");
  638.     /* We start off in persistent queue so we avoid racing */
  639.     if (HTNetPersistent) {
  640. while ((pres = (HTNet *) HTList_lastObject(HTNetPersistent)) != NULL) {
  641.     pres->sockfd = INVSOC;
  642.     (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
  643.     HTList_removeObject(HTNetPersistent, pres);
  644. }
  645.     }
  646.     if (HTNetPending) {
  647. while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
  648.     (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
  649.     HTList_removeObject(HTNetPending, pres);
  650. }
  651.     }
  652.     if (HTNetActive) {
  653. while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
  654.     (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
  655.     }
  656.     return YES;
  657. }
  658. /* ------------------------------------------------------------------------- */
  659. /*       Data Access Methods        */
  660. /* ------------------------------------------------------------------------- */
  661. /*
  662. **  Get and set the socket number
  663. */
  664. PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
  665. {
  666.     if (net) {
  667. net->sockfd = sockfd;
  668. return YES;
  669.     }
  670.     return NO;
  671. }
  672. PUBLIC SOCKET HTNet_socket (HTNet * net)
  673. {
  674.     return (net ? net->sockfd : INVSOC);
  675. }