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

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

Webmaster