Annotation of libwww/Library/src/HTNet.c, revision 2.59

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

Webmaster