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

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

Webmaster