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

2.23      frystyk     1: /*                                                                  HTNet.c
2.79      frystyk     2: **     HTNet Class
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.99    ! frystyk     6: **     @(#) $Id: HTNet.c,v 2.98 1998/12/15 05:34:28 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.93      frystyk    18: #include "wwwsys.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.81      frystyk    31: #include "HTHstMan.h"
                     32: #include "HTIOStream.h"
2.24      frystyk    33: #include "HTNetMan.h"                                   /* Implemented here */
2.1       frystyk    34: 
2.23      frystyk    35: #ifndef HT_MAX_SOCKETS
2.93      frystyk    36: #define HT_MAX_SOCKETS 25
2.23      frystyk    37: #endif
                     38: 
2.91      frystyk    39: #define HASH_SIZE      599
2.74      frystyk    40: 
2.79      frystyk    41: typedef struct _BeforeFilter {
                     42:     HTNetBefore *      before;                           /* Filter function */
                     43:     char *             tmplate;     /* URL template for when to call filter */
                     44:     int                        order;                   /* Relative execution order */
2.60      frystyk    45:     void *             param;                              /* Local context */
2.79      frystyk    46: } BeforeFilter;
                     47: 
                     48: typedef struct _AfterFilter {
                     49:     HTNetAfter *       after;                            /* Filter function */
                     50:     char *             tmplate;     /* URL template for when to call filter */
                     51:     int                        order;                   /* Relative execution order */
                     52:     void *             param;                              /* Local context */
                     53:     int                        status;    /* Status of load for when to call filter */
                     54: } AfterFilter;
2.23      frystyk    55: 
                     56: struct _HTStream {
2.52      frystyk    57:     const HTStreamClass *      isa;
2.23      frystyk    58:     /* ... */
                     59: };
                     60: 
2.81      frystyk    61: struct _HTInputStream {
                     62:     const HTInputStreamClass * isa;
                     63:     /* ... */
                     64: };
                     65: 
2.99    ! frystyk    66: typedef struct _HTFilterEvent {
        !            67:     HTRequest *                request;
        !            68:     int                        status;
        !            69:     HTTimer *          timer;
        !            70: } HTFilterEvent;
        !            71: 
2.79      frystyk    72: PRIVATE HTList * HTBefore = NULL;          /* List of global BEFORE filters */
                     73: PRIVATE HTList * HTAfter = NULL;            /* List of global AFTER filters */
2.24      frystyk    74: 
2.74      frystyk    75: PRIVATE int MaxActive = HT_MAX_SOCKETS;              /* Max active requests */
                     76: PRIVATE int Active = 0;                                      /* Counts open sockets */
                     77: PRIVATE int Persistent = 0;                    /* Counts persistent sockets */
2.1       frystyk    78: 
2.74      frystyk    79: PRIVATE HTList ** NetTable = NULL;                   /* List of net objects */
                     80: PRIVATE int HTNetCount = 0;                   /* Counting elements in table */
2.23      frystyk    81: 
                     82: /* ------------------------------------------------------------------------- */
2.79      frystyk    83: /*                GENERIC BEFORE and AFTER filter Management                */
2.23      frystyk    84: /* ------------------------------------------------------------------------- */
                     85: 
2.79      frystyk    86: PRIVATE int HTBeforeOrder (const void * a, const void * b)
                     87: {
                     88:     return ((BeforeFilter *) b)->order - ((BeforeFilter *) a)->order;
                     89: }
                     90: 
                     91: PRIVATE int HTAfterOrder (const void * a, const void * b)
                     92: {
                     93:     return ((AfterFilter *) b)->order - ((AfterFilter *) a)->order;
                     94: }
                     95: 
2.80      frystyk    96: PRIVATE int check_order (HTFilterOrder order)
2.79      frystyk    97: {
                     98:     return (order<HT_FILTER_FIRST) ? HT_FILTER_FIRST :
                     99:        (order>HT_FILTER_LAST) ? HT_FILTER_LAST : order;
                    100: }
                    101: 
                    102: /*
                    103: **     Register a BEFORE filter in the list provided by the caller.
                    104: **     Several filters can be registered in which case they are called
                    105: **     with the filter ordering in mind.
                    106: */
                    107: PUBLIC BOOL HTNetCall_addBefore (HTList * list, HTNetBefore * before,
                    108:                                 const char * tmplate, void * param, 
2.80      frystyk   109:                                 HTFilterOrder order)
2.79      frystyk   110: {
                    111:     if (list && before) {
                    112:        BeforeFilter * me;
                    113:        if ((me = (BeforeFilter *) HT_CALLOC(1, sizeof(BeforeFilter)))==NULL)
                    114:            HT_OUTOFMEM("HTNetCall_addBefore");
                    115:        me->before = before;
                    116:        if (tmplate) StrAllocCopy(me->tmplate, tmplate);
                    117:        me->order = check_order(order);
                    118:        me->param = param;
                    119:        if (CORE_TRACE)
                    120:            HTTrace("Net Before.. Add %p with order %d tmplate `%s\' context %p\n",
                    121:                    before, me->order, tmplate ? tmplate : "<null>", param);
                    122:        return (HTList_addObject(list, me) &&
                    123:                HTList_insertionSort(list, HTBeforeOrder));
                    124:     }
                    125:     return NO;
                    126: }
                    127: 
                    128: /*
                    129: **     Unregister all instances of a BEFORE filter from a list.
                    130: */
                    131: PUBLIC BOOL HTNetCall_deleteBefore (HTList * list, HTNetBefore * before)
                    132: {
                    133:     if (CORE_TRACE) HTTrace("Net Before.. Delete %p\n", before);
                    134:     if (list && before) {
                    135:        HTList * cur = list;
                    136:        BeforeFilter * pres;
2.94      frystyk   137:        while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
2.79      frystyk   138:            if (pres->before == before) {
                    139:                HTList_removeObject(list, (void *) pres);
                    140:                HT_FREE(pres->tmplate);
                    141:                HT_FREE(pres);
                    142:                cur = list;
                    143:            }
                    144:        }
                    145:     }
                    146:     return NO;
                    147: }
                    148: 
                    149: /*
                    150: **     Deletes all BEFORE filters in list
                    151: */
                    152: PUBLIC BOOL HTNetCall_deleteBeforeAll (HTList * list)
                    153: {
                    154:     if (CORE_TRACE) HTTrace("Net Before. Delete All filters\n");
                    155:     if (list) {
                    156:        HTList * cur = list;
                    157:        BeforeFilter * pres;
                    158:        while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
                    159:            HT_FREE(pres->tmplate);
                    160:            HT_FREE(pres);
                    161:        }
                    162:        HTList_delete(list);
                    163:        return YES;
                    164:     }
                    165:     return NO;
                    166: }
                    167: 
                    168: /*
                    169: **     Call all the BEFORE filters in the order specified at registration
                    170: **     time. We also check for any template and whether it matches or not. 
                    171: **     If a filter returns other than HT_OK then stop and return immediately.
                    172: **     Otherwise return what the last filter returns.
2.23      frystyk   173: */
2.79      frystyk   174: PUBLIC int HTNetCall_executeBefore (HTList * list, HTRequest * request)
2.23      frystyk   175: {
2.79      frystyk   176:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    177:     char * url = HTAnchor_physical(anchor);
                    178:     char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
                    179:     int ret = HT_OK;
                    180:     int mode = 0;    
                    181:     if (list && request && addr) {
                    182:        BeforeFilter * pres;    
                    183:        while ((pres = (BeforeFilter *) HTList_nextObject(list))) {
                    184:            if (!pres->tmplate ||
                    185:                (pres->tmplate && HTStrMatch(pres->tmplate, addr))) {
                    186:                if (CORE_TRACE) HTTrace("Net Before.. calling %p (request %p, context %p)\n",
                    187:                                        pres->before,
                    188:                                        request, pres->param);
                    189:                ret = (*pres->before)(request, pres->param, mode);
                    190:                if (ret != HT_OK) break;
2.88      frystyk   191: 
                    192:                /*
                    193:                **  Update the address to match against if the filter changed
                    194:                **  the physical address.
                    195:                */
                    196:                if ((url = HTAnchor_physical(anchor))) addr = url;
2.79      frystyk   197:            }
                    198:        }
                    199:     }
                    200:     if (!url) HT_FREE(addr);
                    201:     return ret;
                    202: }
                    203: 
                    204: /*
                    205: **     Register a AFTER filter in the list provided by the caller.
                    206: **     Several filters can be registered in which case they are called
                    207: **     with the filter ordering in mind.
                    208: */
                    209: PUBLIC BOOL HTNetCall_addAfter (HTList * list, HTNetAfter * after,
                    210:                                const char * tmplate, void * param,
2.80      frystyk   211:                                int status, HTFilterOrder order)
2.79      frystyk   212: {
                    213:     if (list && after) {
                    214:        AfterFilter * me;
                    215:        if ((me = (AfterFilter *) HT_CALLOC(1, sizeof(AfterFilter)))==NULL)
                    216:            HT_OUTOFMEM("HTNetCall_addAfter");
                    217:        me->after = after;
                    218:        if (tmplate) StrAllocCopy(me->tmplate, tmplate);
                    219:        me->order = check_order(order);
2.60      frystyk   220:        me->param = param;
2.33      frystyk   221:        me->status = status;
2.79      frystyk   222:        if (CORE_TRACE)
                    223:            HTTrace("Net After... Add %p with order %d tmplate `%s\' code %d context %p\n",
                    224:                    after, me->order, tmplate ? tmplate : "<null>", status, param);
                    225:        return (HTList_addObject(list, me) &&
                    226:                HTList_insertionSort(list, HTAfterOrder));
                    227:     }
                    228:     return NO;
                    229: }
                    230: 
                    231: /*
                    232: **     Unregister all instances of an AFTER filter from a list.
                    233: */
                    234: PUBLIC BOOL HTNetCall_deleteAfter (HTList * list, HTNetAfter * after)
                    235: {
                    236:     if (CORE_TRACE) HTTrace("Net After... Delete %p\n", after);
                    237:     if (list && after) {
                    238:        HTList * cur = list;
                    239:        AfterFilter * pres;
                    240:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    241:            if (pres->after == after) {
                    242:                HTList_removeObject(list, (void *) pres);
                    243:                HT_FREE(pres->tmplate);
                    244:                HT_FREE(pres);
                    245:                cur = list;
                    246:            }
                    247:        }
2.23      frystyk   248:     }
                    249:     return NO;
                    250: }
                    251: 
2.79      frystyk   252: /*
                    253: **     Unregister all filters registered for a given status.
2.23      frystyk   254: */
2.79      frystyk   255: PUBLIC BOOL HTNetCall_deleteAfterStatus (HTList * list, int status)
2.23      frystyk   256: {
2.79      frystyk   257:     if (CORE_TRACE) HTTrace("Net After... Delete all with status %d\n",status);
                    258:     if (list) {
                    259:        HTList * cur = list;
                    260:        AfterFilter * pres;
                    261:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    262:            if (pres->status == status) {
2.33      frystyk   263:                HTList_removeObject(list, (void *) pres);
2.79      frystyk   264:                HT_FREE(pres->tmplate);
2.49      frystyk   265:                HT_FREE(pres);
2.79      frystyk   266:                cur = list;
2.23      frystyk   267:            }
                    268:        }
2.79      frystyk   269:        return YES;
2.23      frystyk   270:     }
                    271:     return NO;
                    272: }
2.1       frystyk   273: 
2.79      frystyk   274: /*
                    275: **     Deletes all AFTER filters in list
2.23      frystyk   276: */
2.79      frystyk   277: PUBLIC BOOL HTNetCall_deleteAfterAll (HTList * list)
2.23      frystyk   278: {
2.79      frystyk   279:     if (CORE_TRACE) HTTrace("Net After. Delete All filters\n");
2.33      frystyk   280:     if (list) {
2.79      frystyk   281:        HTList * cur = list;
                    282:        AfterFilter * pres;
                    283:        while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
                    284:            HT_FREE(pres->tmplate);
2.49      frystyk   285:            HT_FREE(pres);
2.23      frystyk   286:        }
2.33      frystyk   287:        HTList_delete(list);
2.23      frystyk   288:        return YES;
                    289:     }
                    290:     return NO;
                    291: }
                    292: 
2.79      frystyk   293: /*
                    294: **     Call all the AFTER filters in the order specified at registration
                    295: **     time and if it has the right status code and it's not HT_IGNORE.
                    296: **     We also check for any template and whether it matches or not.
                    297: **     If a filter returns other than HT_OK then stop and return immediately.
                    298: **     Otherwise return what the last filter returns.
2.23      frystyk   299: */
2.79      frystyk   300: PUBLIC int HTNetCall_executeAfter (HTList * list, HTRequest * request,
                    301:                                   int status)
2.23      frystyk   302: {
2.33      frystyk   303:     int ret = HT_OK;
2.79      frystyk   304:     if (status != HT_IGNORE) {
                    305:        HTParentAnchor * anchor = HTRequest_anchor(request);
                    306:        char * url = HTAnchor_physical(anchor);
                    307:        char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
                    308:        HTResponse * response = HTRequest_response(request);
                    309:        if (list && request && addr) {
                    310:            AfterFilter * pres;
                    311:            while ((pres = (AfterFilter *) HTList_nextObject(list))) {
                    312:                if ((pres->status == status || pres->status == HT_ALL) &&
                    313:                    (!pres->tmplate ||
                    314:                     (pres->tmplate && HTStrMatch(pres->tmplate, addr)))) {
                    315:                    if (CORE_TRACE)
                    316:                        HTTrace("Net After... calling %p (request %p, response %p, status %d, context %p)\n",
                    317:                                pres->after, request, response,
                    318:                                status, pres->param);
                    319:                    ret = (*pres->after)(request, response, pres->param, status);
                    320:                    if (ret != HT_OK) break;
2.88      frystyk   321: 
                    322:                    /*
                    323:                    **  Update the address to match against if the filter changed
                    324:                    **  the physical address.
                    325:                    */
                    326:                    if ((url = HTAnchor_physical(anchor))) addr = url;
2.79      frystyk   327:                }
2.23      frystyk   328:            }
                    329:        }
2.79      frystyk   330:        if (!url) HT_FREE(addr);
2.1       frystyk   331:     }
2.33      frystyk   332:     return ret;
                    333: }
                    334: 
2.79      frystyk   335: /* ------------------------------------------------------------------------- */
                    336: /*                GLOBAL BEFORE and AFTER filter Management                 */
                    337: /* ------------------------------------------------------------------------- */
                    338: 
2.33      frystyk   339: /*
                    340: **     Global set of callback functions BEFORE the request is issued
                    341: **     list can be NULL
                    342: */
                    343: PUBLIC BOOL HTNet_setBefore (HTList *list)
                    344: {
                    345:     HTBefore = list;
                    346:     return YES;
                    347: }
                    348: 
                    349: PUBLIC HTList * HTNet_before (void)
                    350: {
                    351:     return HTBefore;
                    352: }
                    353: 
2.79      frystyk   354: PUBLIC BOOL HTNet_addBefore (HTNetBefore * before, const char * tmplate,
2.80      frystyk   355:                             void * param, HTFilterOrder order)
2.33      frystyk   356: {
2.79      frystyk   357:     if (!HTBefore) HTBefore = HTList_new();
                    358:     return HTNetCall_addBefore(HTBefore, before, tmplate, param, order);
2.33      frystyk   359: }
                    360: 
2.79      frystyk   361: PUBLIC BOOL HTNet_deleteBefore (HTNetBefore * cbf)
2.33      frystyk   362: {
2.79      frystyk   363:     return HTNetCall_deleteBefore(HTBefore, cbf);
2.33      frystyk   364: }
                    365: 
2.79      frystyk   366: /*
                    367: **  Call both the local and the global BEFORE filters (if any)
                    368: */
                    369: PUBLIC int HTNet_executeBeforeAll (HTRequest * request)
2.73      frystyk   370: {
2.79      frystyk   371:     int ret;
                    372:     BOOL override = NO;
                    373:     HTList * befores;
                    374:     if ((befores = HTRequest_before(request, &override))) {
                    375:        if ((ret = HTNetCall_executeBefore(befores, request)) != HT_OK)
                    376:            return ret;
                    377:     }
                    378:     return override ? HT_OK : HTNetCall_executeBefore(HTBefore, request);
2.73      frystyk   379: }
                    380: 
2.33      frystyk   381: /*
                    382: **     Global set of callback functions AFTER the request is issued
                    383: **     list can be NULL
                    384: */
                    385: PUBLIC BOOL HTNet_setAfter (HTList *list)
                    386: {
                    387:     HTAfter = list;
                    388:     return YES;
                    389: }
                    390: 
                    391: PUBLIC HTList * HTNet_after (void)
                    392: {
                    393:     return HTAfter;
                    394: }
                    395: 
2.79      frystyk   396: PUBLIC BOOL HTNet_addAfter (HTNetAfter * after, const char * tmplate,
2.80      frystyk   397:                            void * param, int status, HTFilterOrder order)
2.33      frystyk   398: {
2.79      frystyk   399:     if (!HTAfter) HTAfter = HTList_new();
                    400:     return HTNetCall_addAfter(HTAfter, after, tmplate, param, status, order);
                    401: }
2.58      hallam    402: 
2.79      frystyk   403: PUBLIC BOOL HTNet_deleteAfter (HTNetAfter * cbf)
                    404: {
                    405:     return HTNetCall_deleteAfter(HTAfter, cbf);
2.33      frystyk   406: }
                    407: 
2.79      frystyk   408: PUBLIC BOOL HTNet_deleteAfterStatus (int status)
2.33      frystyk   409: {
2.79      frystyk   410:     return HTNetCall_deleteAfterStatus(HTAfter, status);
2.73      frystyk   411: }
                    412: 
2.79      frystyk   413: /*
                    414: **  Call both the local and the global AFTER filters (if any)
                    415: */
                    416: PUBLIC int HTNet_executeAfterAll (HTRequest * request, int status)
2.73      frystyk   417: {
2.79      frystyk   418:     int ret;
                    419:     BOOL override = NO;
                    420:     HTList * afters;
                    421:     if ((afters = HTRequest_after(request, &override))) {
                    422:        if ((ret = HTNetCall_executeAfter(afters, request, status)) != HT_OK)
                    423:            return ret;
                    424:     }
                    425:     return override ? HT_OK : HTNetCall_executeAfter(HTAfter, request, status);
2.1       frystyk   426: }
                    427: 
2.23      frystyk   428: /* ------------------------------------------------------------------------- */
2.74      frystyk   429: /*                           Socket Management                              */
2.23      frystyk   430: /* ------------------------------------------------------------------------- */
2.1       frystyk   431: 
2.74      frystyk   432: PUBLIC int HTNet_maxSocket (void)
                    433: {
                    434:     return MaxActive;
                    435: }
                    436: 
                    437: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
                    438: {
                    439:     if (newmax > 0) {
                    440:        MaxActive = newmax;
                    441:        return YES;
                    442:     }
                    443:     return NO;
                    444: }
                    445: 
                    446: PUBLIC void HTNet_increaseSocket (void)
                    447: {
                    448:     Active++;
2.87      frystyk   449:     if (CORE_TRACE)
                    450:        HTTrace("Net Manager. Increasing active sockets to %d, %d persistent sockets\n",
                    451:                Active, Persistent);
2.74      frystyk   452: }
                    453: 
                    454: PUBLIC void HTNet_decreaseSocket (void)
                    455: {
                    456:     if (--Active < 0) Active = 0;
2.87      frystyk   457:     if (CORE_TRACE)
                    458:        HTTrace("Net Manager. Decreasing active sockets to %d, %d persistent sockets\n",
                    459:                Active, Persistent);
2.74      frystyk   460: }
                    461: 
                    462: PUBLIC int HTNet_availableSockets (void)
                    463: {
                    464:     int available = MaxActive - Active;
                    465:     return available > 0 ? available : 0;
                    466: }
                    467: 
                    468: PUBLIC void HTNet_increasePersistentSocket (void)
                    469: {
                    470:     Persistent++;
2.87      frystyk   471:     if (CORE_TRACE)
                    472:        HTTrace("Net Manager. %d active sockets, increasing persistent sockets to %d\n",
                    473:                Active, Persistent);
2.74      frystyk   474: }
                    475: 
                    476: PUBLIC void HTNet_decreasePersistentSocket (void)
2.23      frystyk   477: {
2.74      frystyk   478:     if (--Persistent < 0) Persistent = 0;
2.87      frystyk   479:     if (CORE_TRACE)
                    480:        HTTrace("Net Manager. %d active sockets, decreasing persistent sockets to %d\n",
                    481:                Active, Persistent);
2.23      frystyk   482: }
2.17      frystyk   483: 
2.74      frystyk   484: PUBLIC int HTNet_availablePersistentSockets (void)
2.28      frystyk   485: {
2.74      frystyk   486:     int available = MaxActive - 2 - Persistent;
                    487:     return available > 0 ? available : 0;
2.28      frystyk   488: }
                    489: 
2.74      frystyk   490: /*
                    491: **     Returns whether there are any Net objects pending or active
2.40      frystyk   492: */
2.74      frystyk   493: PUBLIC BOOL HTNet_isIdle (void)
2.40      frystyk   494: {
2.74      frystyk   495:     return (HTNetCount > 0);
2.40      frystyk   496: }
                    497: 
2.74      frystyk   498: PUBLIC BOOL HTNet_isEmpty (void)
2.1       frystyk   499: {
2.74      frystyk   500:     return (HTNetCount <= 0);
2.1       frystyk   501: }
                    502: 
2.81      frystyk   503: PUBLIC int HTNet_count (void)
                    504: {
                    505:     return HTNetCount;
                    506: }
                    507: 
2.23      frystyk   508: /* ------------------------------------------------------------------------- */
                    509: /*                       Creation and deletion methods                      */
                    510: /* ------------------------------------------------------------------------- */
                    511: 
2.99    ! frystyk   512: PRIVATE int AfterFilterEvent (HTTimer * timer, void * param, HTEventType type)
        !           513: {
        !           514:     HTFilterEvent * fe = (HTFilterEvent *) param;
        !           515:     if (fe) {
        !           516:        HTRequest * request = fe->request;
        !           517:        int status = fe->status;
        !           518:        if (timer != fe->timer)
        !           519:            HTDebugBreak(__FILE__, __LINE__, "Net timer. %p not in sync\n", timer);
        !           520:        if (CORE_TRACE) 
        !           521:            HTTrace("HTNet....... Continuing calling AFTER filters %p with timer %p\n",
        !           522:                    fe, timer);
        !           523: 
        !           524:        /* Delete the event context */
        !           525:        HT_FREE(fe);
        !           526: 
        !           527:        /* Now call the remaining AFTER filters */
        !           528:        return HTNet_executeAfterAll(request, status);
        !           529:     }
        !           530:     return HT_ERROR;
        !           531: }
        !           532: 
        !           533: PRIVATE BOOL createAfterFilterEvent (HTRequest * request, int status)
        !           534: {
        !           535:     HTFilterEvent * me = NULL;
        !           536:     if ((me = (HTFilterEvent *) HT_CALLOC(1, sizeof(HTFilterEvent))) == NULL)
        !           537:         HT_OUTOFMEM("createAfterFilterEvent");
        !           538:     me->request = request;
        !           539:     me->status = status;
        !           540:     me->timer = HTTimer_new(NULL, AfterFilterEvent, me, 1, YES, NO);
        !           541:     return YES;
        !           542: }
        !           543: 
2.74      frystyk   544: PRIVATE HTNet * create_object (void)
                    545: {
                    546:     static int net_hash = 0;
                    547:     HTNet * me = NULL;
                    548: 
                    549:     /* Create new object */
                    550:     if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
                    551:         HT_OUTOFMEM("HTNet_new");
                    552:     me->hash = net_hash++ % HASH_SIZE;
                    553: 
                    554:     /* Insert into hash table */
                    555:     if (!NetTable) {
                    556:        if ((NetTable = (HTList **) HT_CALLOC(HASH_SIZE, sizeof(HTList *))) == NULL)
                    557:            HT_OUTOFMEM("create_object");
                    558:     }
                    559:     if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new();
                    560:     HTList_addObject(NetTable[me->hash], (void *) me);
                    561:     HTNetCount++;
                    562:     if (CORE_TRACE)
                    563:        HTTrace("Net Object.. %p created with hash %d\n",me, me->hash);
                    564:     return me;
                    565: }
                    566: 
2.27      frystyk   567: /*     HTNet_duplicate
                    568: **     ---------------
                    569: **     Creates a new HTNet object as a duplicate of the same request.
                    570: **     Returns YES if OK, else NO
                    571: **     BUG: We do not check if we have a socket free!
                    572: */
2.43      frystyk   573: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27      frystyk   574: {
2.74      frystyk   575:     if (src) {
                    576:         HTNet * me;
2.75      frystyk   577:        int hash;
2.74      frystyk   578:        if ((me = create_object()) == NULL) return NULL;
2.75      frystyk   579:        hash = me->hash;
2.74      frystyk   580:        if (CORE_TRACE) HTTrace("Net Object.. Duplicated %p\n", src);
                    581:         memcpy((void *) me, src, sizeof(HTNet));
2.75      frystyk   582:        me->hash = hash;                        /* Carry over hash entry */
2.74      frystyk   583:        return me;
                    584:     }
                    585:     return NULL;
2.27      frystyk   586: }
                    587: 
2.81      frystyk   588: PUBLIC BOOL HTNet_execute (HTNet * net, HTEventType type)
                    589: {
                    590:     if (net && net->event.cbf && net->request) {
                    591:        if (CORE_TRACE)
2.82      frystyk   592:            HTTrace("Net Object.. %p calling %p with event type %d and context %p\n",
                    593:                    net, net->event.cbf, type, net->event.param);
                    594:        (*(net->event.cbf))(HTNet_socket(net), net->event.param, type);
2.81      frystyk   595:        return YES;
                    596:     }
                    597:     return NO;
                    598: }
                    599: 
2.74      frystyk   600: /*
                    601: **     Start a Net obejct by calling the protocol module.
2.30      frystyk   602: */
2.74      frystyk   603: PUBLIC BOOL HTNet_start (HTNet * net)
2.30      frystyk   604: {
2.81      frystyk   605:     if (net && net->event.cbf && net->request) {
2.74      frystyk   606:        if (CORE_TRACE) HTTrace("Net Object.. Launching %p\n", net);
2.81      frystyk   607:        (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_BEGIN);
2.30      frystyk   608:        return YES;
                    609:     }
                    610:     return NO;
                    611: }
                    612: 
2.37      frystyk   613: /*     HTNet_new
                    614: **     ---------
                    615: **     This function creates a new HTNet object and assigns the socket number
                    616: **     to it. This is intended to be used when you are going to listen on a 
                    617: **     socket using the HTDoListen() function in HTTCP.c. The function do NOT
                    618: **     call any of the callback functions.
                    619: **     Returns new object or NULL on error
                    620: */
2.81      frystyk   621: PUBLIC HTNet * HTNet_new (HTRequest * request)
2.37      frystyk   622: {
2.81      frystyk   623:     HTNet * me;
                    624:     if ((me = create_object()) == NULL) return NULL;
                    625:     me->preemptive = HTRequest_preemptive(request);
                    626:     HTNet_setEventPriority(me, HTRequest_priority(request));
                    627:     me->request = request;
                    628:     HTRequest_setNet(request, me);
                    629:     return me;
2.37      frystyk   630: }
                    631: 
2.67      frystyk   632: /*      HTNet_newServer
                    633: **      ---------------
                    634: **      Create a new HTNet object as a new request to be handled. If we have
2.74      frystyk   635: **      more than MaxActive connections already then return NO.
2.67      frystyk   636: **      Returns YES if OK, else NO
2.37      frystyk   637: */
2.98      frystyk   638: PUBLIC BOOL HTNet_newServer (HTRequest * request)
2.37      frystyk   639: {
2.98      frystyk   640:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    641:     HTNet * me = NULL;
2.37      frystyk   642:     HTProtocol * protocol;
2.67      frystyk   643:     HTTransport * tp = NULL;           /* added JTD:5/28/96 */
2.98      frystyk   644:     char * physical = NULL;
                    645:     int status;
2.81      frystyk   646:     HTProtCallback * cbf;
2.98      frystyk   647: 
2.37      frystyk   648:     if (!request) return NO;
                    649: 
2.98      frystyk   650:     /*
                    651:     ** First we do all the "BEFORE" callbacks in order to see if we are to
                    652:     ** continue with this request or not. If we receive a callback status
                    653:     ** that is NOT HT_OK then jump directly to the after callbacks and return
                    654:     */
                    655:     if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99    ! frystyk   656: 
        !           657:        /*
        !           658:        **  If in non-blocking mode then return here and call AFTER
        !           659:        **  filters from a timer event handler. As Olga Antropova
        !           660:        **  points out, otherwise, the stack can grow if new requests
        !           661:        **  are started directly from the after filters 
        !           662:        */
        !           663:        if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
        !           664:            createAfterFilterEvent(request, status);
        !           665:        else
        !           666:            HTNet_executeAfterAll(request, status);
2.98      frystyk   667:        return YES;
                    668:     }
                    669: 
                    670:     /*
                    671:     ** If no translation was provided by the filters then use the anchor
                    672:     ** address directly
                    673:     */
                    674:     if (!(physical = HTAnchor_physical(anchor))) {
                    675:        char * addr = HTAnchor_address((HTAnchor *) anchor);
                    676:        if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
                    677:        HTAnchor_setPhysical(anchor, addr);
                    678:        physical = HTAnchor_physical(anchor);
                    679:        HT_FREE(addr);
                    680:     }
                    681: 
2.37      frystyk   682:     /* Find a protocol object for this access scheme */
2.98      frystyk   683:     {
                    684:        char * access = HTParse(physical, "", PARSE_ACCESS);      
                    685:        if ((protocol = HTProtocol_find(request, access)) == NULL) {
                    686:            if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n", access);
                    687:            HT_FREE(access);
                    688:            return NO;
                    689:        }
                    690:        if (!(cbf = HTProtocol_server(protocol))) {
                    691:            if (CORE_TRACE) HTTrace("Net Object.. NO SERVER HANDLER for URI scheme `%s\'\n", access);
                    692:            HT_FREE(access);
                    693:            HT_FREE(me);
                    694:            return NO;
                    695:        }
                    696:        HT_FREE(access);
                    697:     }
2.67      frystyk   698: 
                    699:     /* Find a transport object for this protocol */
2.98      frystyk   700:     if ((tp = HTTransport_find(request, HTProtocol_transport(protocol))) == NULL) {
                    701:         if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT found for protocol `%s\'\n", HTProtocol_name(protocol));
2.67      frystyk   702:         return NO;
                    703:     }
                    704: 
2.98      frystyk   705:     /* Create new net object and bind to request object */
                    706:     if ((me = create_object()) == NULL) return NO;
                    707:     me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
                    708:     HTNet_setEventPriority(me, HTRequest_priority(request));
                    709:     me->protocol = protocol;
                    710:     me->transport = tp;                /* added - JTD:5/28/96 */
                    711:     me->request = request;
                    712:     HTRequest_setNet(request, me);
2.37      frystyk   713: 
                    714:     /* Start the server request */
2.58      hallam    715:     if (CORE_TRACE)
2.98      frystyk   716:         HTTrace("Net Object.. starting SERVER request %p and net object %p\n", request, me);
                    717:     (*(cbf))(INVSOC, request);
2.37      frystyk   718:     return YES;
                    719: }
2.36      frystyk   720: 
2.30      frystyk   721: /*     HTNet_new
                    722: **     ---------
2.23      frystyk   723: **     Create a new HTNet object as a new request to be handled. If we have
2.74      frystyk   724: **     more than MaxActive connections already then put this into the
2.23      frystyk   725: **     pending queue, else start the request by calling the call back
                    726: **     function registered with this access method. 
                    727: **     Returns YES if OK, else NO
                    728: */
2.37      frystyk   729: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23      frystyk   730: {
2.74      frystyk   731:     HTParentAnchor * anchor = HTRequest_anchor(request);
2.59      frystyk   732:     HTNet * me = NULL;
                    733:     HTProtocol * protocol = NULL;
                    734:     HTTransport * tp = NULL;
2.37      frystyk   735:     char * physical = NULL;
2.74      frystyk   736:     int status;
2.81      frystyk   737:     HTProtCallback * cbf;
                    738: 
2.27      frystyk   739:     if (!request) return NO;
2.98      frystyk   740: 
2.33      frystyk   741:     /*
                    742:     ** First we do all the "BEFORE" callbacks in order to see if we are to
                    743:     ** continue with this request or not. If we receive a callback status
                    744:     ** that is NOT HT_OK then jump directly to the after callbacks and return
                    745:     */
2.79      frystyk   746:     if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99    ! frystyk   747: 
        !           748:        /*
        !           749:        **  If in non-blocking mode then return here and call AFTER
        !           750:        **  filters from a timer event handler. As Olga Antropova
        !           751:        **  points out, otherwise, the stack can grow if new requests
        !           752:        **  are started directly from the after filters 
        !           753:        */
        !           754:        if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
        !           755:            createAfterFilterEvent(request, status);
        !           756:        else
        !           757:            HTNet_executeAfterAll(request, status);
2.33      frystyk   758:        return YES;
                    759:     }
                    760: 
2.36      frystyk   761:     /*
2.79      frystyk   762:     ** If no translation was provided by the filters then use the anchor
2.36      frystyk   763:     ** address directly
                    764:     */
2.74      frystyk   765:     if (!(physical = HTAnchor_physical(anchor))) {
                    766:        char * addr = HTAnchor_address((HTAnchor *) anchor);
                    767:        if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
                    768:        HTAnchor_setPhysical(anchor, addr);
                    769:        physical = HTAnchor_physical(anchor);
2.49      frystyk   770:        HT_FREE(addr);
2.33      frystyk   771:     }
                    772: 
2.37      frystyk   773:     /* Find a protocol object for this access scheme */
                    774:     {
2.81      frystyk   775:        char * proxy = HTRequest_proxy(request);
                    776:        char * access = HTParse(proxy ? proxy : physical, "", PARSE_ACCESS);      
2.37      frystyk   777:        if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.98      frystyk   778:            if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n", access);
2.49      frystyk   779:            HT_FREE(access);
2.37      frystyk   780:            return NO;
                    781:        }
2.98      frystyk   782:        if (!(cbf = HTProtocol_client(protocol))) {
                    783:            if (CORE_TRACE) HTTrace("Net Object.. NO CLIENT HANDLER for URI scheme `%s\'\n", access);
                    784:            HT_FREE(access);
                    785:            HT_FREE(me);
                    786:            return NO;
                    787:        }
2.49      frystyk   788:        HT_FREE(access);
2.37      frystyk   789:     }
2.59      frystyk   790: 
                    791:     /* Find a transport object for this protocol */
                    792:     tp = HTTransport_find(request, HTProtocol_transport(protocol));
                    793:     if (tp == NULL) {
2.98      frystyk   794:        if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT found for protocol `%s\'\n", HTProtocol_name(protocol));
2.59      frystyk   795:        return NO;
                    796:     }
                    797: 
2.23      frystyk   798:     /* Create new net object and bind it to the request object */
2.69      frystyk   799:     if ((me = create_object()) == NULL) return NO;
2.74      frystyk   800:     me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.81      frystyk   801: #if 0
2.69      frystyk   802:     me->priority = HTRequest_priority(request);
2.81      frystyk   803: #endif
                    804:     HTNet_setEventPriority(me, HTRequest_priority(request));
2.59      frystyk   805:     me->protocol = protocol;
                    806:     me->transport = tp;
2.69      frystyk   807:     me->request = request;
                    808:     HTRequest_setNet(request, me);
2.74      frystyk   809: 
                    810:     /* Increase the number of retrys for this download */
                    811:     HTRequest_addRetry(request);
2.23      frystyk   812: 
                    813:     /*
                    814:     ** Check if we can start the request, else put it into pending queue
                    815:     ** If so then call the call back function associated with the anchor.
                    816:     ** We use the INVSOC as we don't have a valid socket yet!
                    817:     */
2.74      frystyk   818:     if (CORE_TRACE)
                    819:         HTTrace("Net Object.. starting request %p (retry=%d) with net object %p\n",
                    820:                request, HTRequest_retrys(request), me);
2.81      frystyk   821:     (*(cbf))(INVSOC, request);
2.36      frystyk   822:     return YES;
                    823: }
                    824: 
2.23      frystyk   825: /*     delete_object
                    826: **     -------------
                    827: **     Deletes an HTNet object
2.40      frystyk   828: **     Return YES if OK, else NO
2.15      frystyk   829: */
2.81      frystyk   830: PRIVATE BOOL delete_object (HTNet * net)
2.15      frystyk   831: {
2.74      frystyk   832:     if (CORE_TRACE) HTTrace("Net Object.. Remove object %p\n", net);
2.23      frystyk   833:     if (net) {
                    834: 
                    835:        /* Close socket */
2.74      frystyk   836:        /*
                    837:        **  As we may have a socket available we check for whether
                    838:        **  we can start any pending requests. We do this by asking for
                    839:        **  pending Host objects. If none then use the current object
                    840:        */
2.81      frystyk   841: /*     (*net->input->isa->consumed)(net->input, net->header_length + net->bytes_read);
                    842:  */
2.74      frystyk   843: 
2.89      frystyk   844:         HTHost_launchPending(net->host);
                    845: 
                    846:         /*
2.74      frystyk   847:        **  Break the link to the request and free the Net object
                    848:        */
                    849:        HTRequest_setNet(net->request, NULL);
2.49      frystyk   850:        HT_FREE(net);
2.81      frystyk   851:        return YES;
                    852:     }
                    853:     return NO;
                    854: }
                    855: 
                    856: PRIVATE BOOL remove_net (HTNet * net)
                    857: {
                    858:     if (net && NetTable) {
                    859:        HTList * list = NetTable[net->hash];
                    860:        if (list) {
                    861:            HTList_removeObject(list, (void *) net);
                    862:            delete_object(net);
                    863:            HTNetCount--;
                    864:            return YES;
                    865:        }
2.23      frystyk   866:     }
                    867:     return NO;
                    868: }
                    869: 
2.74      frystyk   870: /*
                    871: **     Clears the contents of the Net object so that we can use it again.
                    872: */
                    873: PUBLIC BOOL HTNet_clear (HTNet * net)
                    874: {
                    875:     if (net) {
2.81      frystyk   876:        net->host->channel = NULL;
                    877:        net->readStream = NULL;
                    878:        net->bytesRead = 0;
2.95      frystyk   879:        net->headerBytesRead = 0;
2.81      frystyk   880:        net->bytesWritten = 0;
2.95      frystyk   881:        net->headerBytesWritten = 0;
2.74      frystyk   882:        return YES;
                    883:     }
                    884:     return NO;
                    885: }
                    886: 
2.23      frystyk   887: /*     HTNet_delete
                    888: **     ------------
                    889: **     Deletes the HTNet object from the list of active requests and calls
                    890: **     any registered call back functions IF not the status is HT_IGNORE.
                    891: **     This is used if we have internal requests that the app doesn't know
                    892: **     about. We also see if we have pending requests that can be started
                    893: **     up now when we have a socket free.
                    894: **     The callback functions are called in the reverse order of which they
                    895: **     were registered (last one first)
2.40      frystyk   896: **     Return YES if OK, else NO
2.23      frystyk   897: */
                    898: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
                    899: {
2.58      hallam    900:     if (CORE_TRACE) 
2.74      frystyk   901:        HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
                    902:     if (net) {
                    903:        HTRequest * request = net->request;
2.23      frystyk   904: 
2.25      frystyk   905:        /*
2.74      frystyk   906:        ** If we have a premature close then recover the request. Otherwise
                    907:        ** break the link to the Host object and continue deleting the net
                    908:        ** object
2.25      frystyk   909:        */
2.74      frystyk   910:        if (net->host) {
2.81      frystyk   911:            HTHost_unregister (net->host, net, HTEvent_READ);
                    912:            HTHost_unregister (net->host, net, HTEvent_WRITE);
2.74      frystyk   913:            if (status == HT_RECOVER_PIPE) {
                    914:                HTNet_clear(net);
2.58      hallam    915:                if (CORE_TRACE)
2.74      frystyk   916:                    HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
                    917:                            request, HTRequest_retrys(request), net);
                    918:                return YES;
2.81      frystyk   919:            }
2.97      frystyk   920:             HTHost_deleteNet(net->host, net, status);
2.92      frystyk   921:            if (HTHost_doRecover(net->host)) HTHost_recoverPipe(net->host);
2.89      frystyk   922:         }
2.74      frystyk   923: 
                    924:         /* Remove object from the table of Net Objects */
2.81      frystyk   925:        remove_net(net);
2.82      frystyk   926: 
2.74      frystyk   927:        /* Call AFTER filters */
2.79      frystyk   928:        HTNet_executeAfterAll(request, status);
2.74      frystyk   929:         return YES;
2.23      frystyk   930:     }
                    931:     return NO;
2.98      frystyk   932: }
                    933: 
                    934: PUBLIC BOOL HTNet_deleteDup (HTNet * dup)
                    935: {
                    936:     return dup ? remove_net(dup) : NO;
2.23      frystyk   937: }
                    938: 
                    939: /*     HTNet_deleteAll
                    940: **     ---------------
                    941: **     Deletes all HTNet object that might either be active or pending
2.74      frystyk   942: **     We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23      frystyk   943: */
                    944: PUBLIC BOOL HTNet_deleteAll (void)
                    945: {
2.58      hallam    946:     if (CORE_TRACE) 
2.74      frystyk   947:        HTTrace("Net Object.. Remove all Net objects, NO filters\n"); 
                    948:     if (NetTable) {
                    949:        HTList * cur = NULL;
                    950:         HTNet * pres = NULL;
                    951:        int cnt;
                    952:        for (cnt=0; cnt<HASH_SIZE; cnt++) {
                    953:            if ((cur = NetTable[cnt])) { 
                    954:                while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
2.81      frystyk   955:                    delete_object(pres);
2.74      frystyk   956:            }
                    957:            HTList_delete(NetTable[cnt]);
2.25      frystyk   958:        }
2.74      frystyk   959:        HT_FREE(NetTable);
                    960:        HTNetCount = 0;
                    961:        return YES;
2.25      frystyk   962:     }
                    963:     return NO;
2.97      frystyk   964: }
                    965: 
                    966: /*
                    967: **     When pipelining, it is not possible to kill a single request 
                    968: **     as we then loose track of where we are in the pipe. It is 
                    969: **     therefore necessary to kill the whole pipeline.
                    970: */
                    971: PUBLIC BOOL HTNet_killPipe (HTNet * net)
                    972: {
                    973:     return (net && net->host) ? HTHost_killPipe(net->host) : NO;
2.25      frystyk   974: }
                    975: 
2.23      frystyk   976: /*     HTNet_kill
                    977: **     ----------
                    978: **     Kill the request by calling the call back function with a request for 
                    979: **     closing the connection. Does not remove the object. This is done by
                    980: **     HTNet_delete() function which is called by the load routine.
                    981: **     Returns OK if success, NO on error
                    982: */
2.74      frystyk   983: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23      frystyk   984: {
2.81      frystyk   985:     if (net) {
2.94      frystyk   986:         HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);
                    987:         if (cbf) (*cbf)(net->request, HT_PROG_INTERRUPT, HT_MSG_NULL, NULL, NULL, NULL);
2.81      frystyk   988:        if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
                    989:        if (net->event.cbf) {
                    990:            (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_CLOSE);
                    991:            return YES;
                    992:        }
                    993:        return remove_net(net);
2.23      frystyk   994:     }
2.81      frystyk   995:     if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n");
2.23      frystyk   996:     return NO;
                    997: }
                    998: 
                    999: /*     HTNet_killAll
                   1000: **     -------------
2.74      frystyk  1001: **     Kills all registered net objects by calling the call
2.23      frystyk  1002: **     back function with a request for closing the connection. We do not
                   1003: **     remove the HTNet object as it is done by HTNet_delete().
                   1004: **     Returns OK if success, NO on error
                   1005: */
                   1006: PUBLIC BOOL HTNet_killAll (void)
                   1007: {
2.74      frystyk  1008:     if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n"); 
                   1009:     if (NetTable) {
                   1010:        HTList * cur = NULL;
                   1011:         HTNet * pres = NULL;
                   1012:        int cnt;
                   1013:        for (cnt=0; cnt<HASH_SIZE; cnt++) {
                   1014:            if ((cur = NetTable[cnt])) { 
2.75      frystyk  1015:                while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74      frystyk  1016:                    HTNet_kill(pres);
                   1017:            }
2.25      frystyk  1018:        }
2.74      frystyk  1019:        return YES;
2.25      frystyk  1020:     }
2.74      frystyk  1021:     if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
                   1022:     return NO;
2.23      frystyk  1023: }
2.38      frystyk  1024: 
                   1025: /* ------------------------------------------------------------------------- */
2.59      frystyk  1026: /*                         Connection Specifics                             */
                   1027: /* ------------------------------------------------------------------------- */
                   1028: 
2.74      frystyk  1029: /*     HTNet_priority
                   1030: **     --------------
                   1031: **     Get the current priority of the Net object
                   1032: */
                   1033: PUBLIC HTPriority HTNet_priority (HTNet * net)
                   1034: {
2.81      frystyk  1035:     return (net ? net->event.priority : HT_PRIORITY_INV);
2.74      frystyk  1036: }
                   1037: 
                   1038: /*     HTNet_setPriority
                   1039: **     -----------------
                   1040: **     Set the current priority of the Net object
                   1041: **     This will change the priority next time the thread is blocked
                   1042: */
                   1043: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
                   1044: {
                   1045:     if (net) {
2.81      frystyk  1046:        net->event.priority = priority;
2.74      frystyk  1047:        return YES;
                   1048:     }
                   1049:     return NO;
                   1050: }
                   1051: 
2.59      frystyk  1052: /*     HTNet_Persistent
                   1053: **     ----------------
                   1054: **     Check whether the net object handles persistent connections
                   1055: **     If we have a DNS entry then check that as well.
                   1056: */
                   1057: PUBLIC BOOL HTNet_persistent (HTNet * net)
                   1058: {
                   1059:     return (net && HTHost_isPersistent(net->host));
                   1060: }
                   1061: 
                   1062: /*     HTNet_persistent
                   1063: **     ----------------
                   1064: **     Set the net object to handle persistent connections
                   1065: **     If we also have a DNS entry then update that as well
                   1066: */
2.74      frystyk  1067: PUBLIC BOOL HTNet_setPersistent (HTNet *               net,
                   1068:                                 BOOL                   persistent,
                   1069:                                 HTTransportMode        mode)
2.59      frystyk  1070: {
                   1071:     if (net) {
2.81      frystyk  1072:        BOOL result = HTHost_setPersistent(net->host, persistent, mode);
2.74      frystyk  1073:        if (CORE_TRACE)
                   1074:            HTTrace("Net Object.. Persistent connection set %s %s\n",
                   1075:                    persistent ? "ON" : "OFF",
                   1076:                    result ? "succeeded" : "failed");
2.81      frystyk  1077:        return result;
2.59      frystyk  1078:     }
                   1079:     return NO;
                   1080: }
                   1081: 
2.66      frystyk  1082: /*
                   1083: **     Context pointer to be used in context call back function
                   1084: */
                   1085: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
                   1086: {
                   1087:     if (net) {
                   1088:        net->context = context;
                   1089:        return YES;
                   1090:     }
                   1091:     return NO;
                   1092: }
                   1093: 
                   1094: PUBLIC void * HTNet_context (HTNet * net)
                   1095: {
                   1096:     return net ? net->context : NULL;
                   1097: }
2.38      frystyk  1098: 
                   1099: /*
2.60      frystyk  1100: **  Get and set the socket number
                   1101: */
                   1102: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
                   1103: {
2.81      frystyk  1104:     if (net && net->host && net->host->channel) {
                   1105:        HTChannel_setSocket(net->host->channel, sockfd);
2.60      frystyk  1106:        return YES;
                   1107:     }
                   1108:     return NO;
                   1109: }
                   1110: 
                   1111: PUBLIC SOCKET HTNet_socket (HTNet * net)
                   1112: {
2.81      frystyk  1113:     return (net && net->host && net->host->channel ? HTChannel_socket(net->host->channel) : INVSOC);
2.69      frystyk  1114: }
                   1115: 
                   1116: /*
                   1117: **  Get and set the HTRequest object
                   1118: */
                   1119: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
                   1120: {
                   1121:     if (net && request) {
                   1122:        net->request = request;
                   1123:        return YES;
                   1124:     }
                   1125:     return NO;
                   1126: }
                   1127: 
                   1128: PUBLIC HTRequest * HTNet_request (HTNet * net)
                   1129: {
                   1130:     return (net ? net->request : NULL);
2.60      frystyk  1131: }
                   1132: 
                   1133: /*
2.59      frystyk  1134: **  Get and set the HTChannel object
2.55      frystyk  1135: */
2.59      frystyk  1136: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55      frystyk  1137: {
2.81      frystyk  1138:     return (net && channel) ? HTHost_setChannel(net->host, channel) : NO;
2.55      frystyk  1139: }
                   1140: 
2.59      frystyk  1141: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55      frystyk  1142: {
2.81      frystyk  1143:     return net ? HTHost_channel(net->host) : NULL;
2.59      frystyk  1144: }
                   1145: 
                   1146: /*
                   1147: **  Get and set the HTHost object
                   1148: */
                   1149: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
                   1150: {
                   1151:     if (net && host) {
                   1152:        net->host = host;
                   1153:        return YES;
                   1154:     }
                   1155:     return NO;
                   1156: }
                   1157: 
                   1158: PUBLIC HTHost * HTNet_host (HTNet * net)
                   1159: {
                   1160:     return (net ? net->host : NULL);
                   1161: }
                   1162: 
                   1163: /*
                   1164: **  Get and set the HTdns object
                   1165: */
                   1166: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
                   1167: {
                   1168:     if (net && dns) {
2.81      frystyk  1169:        net->host->dns = dns;
2.59      frystyk  1170:        return YES;
                   1171:     }
                   1172:     return NO;
                   1173: }
                   1174: 
                   1175: PUBLIC HTdns * HTNet_dns (HTNet * net)
                   1176: {
2.81      frystyk  1177:     return (net ? net->host->dns : NULL);
2.59      frystyk  1178: }
                   1179: 
2.81      frystyk  1180: PUBLIC BOOL HTNet_setProtocol (HTNet * net, HTProtocol * protocol)
                   1181: {
                   1182:     if (net && protocol) {
                   1183:        net->protocol = protocol;
                   1184:        return YES;
                   1185:     }
                   1186:     return NO;
                   1187: }
                   1188: 
                   1189: PUBLIC HTProtocol * HTNet_protocol (HTNet * net)
2.72      frystyk  1190: {
2.81      frystyk  1191:     return (net ? net->protocol : NULL);
2.72      frystyk  1192: }
2.59      frystyk  1193: 
2.86      frystyk  1194: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
                   1195: {
                   1196:     if (net && tp) {
                   1197:        net->transport = tp;
                   1198:        return YES;
                   1199:     }
                   1200:     return NO;
                   1201: }
                   1202: 
                   1203: PUBLIC HTTransport * HTNet_transport (HTNet * net)
                   1204: {
                   1205:     return (net ? net->transport : NULL);
                   1206: }
                   1207: 
                   1208: PUBLIC BOOL HTNet_preemptive (HTNet * net)
                   1209: {
                   1210:     return (net ? net->preemptive : NO);
                   1211: }
                   1212: 
2.59      frystyk  1213: /*
                   1214: **     Create the output stream and bind it to the channel
                   1215: **     Please read the description in the HTIOStream module on the parameters
                   1216: */
2.81      frystyk  1217: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * me, void * param, int mode)
2.59      frystyk  1218: {
2.81      frystyk  1219:     if (me && me->host && me->host->channel && me->transport) {
                   1220:        HTTransport * tp = me->transport;
                   1221:        HTChannel * ch = me->host->channel;
                   1222:        HTOutputStream * output = (*tp->output_new)(me->host, ch, param, mode);
2.74      frystyk  1223:        HTChannel_setOutput(ch, output);
2.59      frystyk  1224:        return output;
                   1225:     }
2.81      frystyk  1226:     if (CORE_TRACE) HTTrace("Host Object.. Can't create output stream\n");
2.59      frystyk  1227:     return NULL;
2.81      frystyk  1228: }
                   1229: 
2.87      frystyk  1230: PUBLIC HTEvent * HTNet_event (HTNet * net)
2.81      frystyk  1231: {
2.87      frystyk  1232:     return net ? &net->event : NULL;
                   1233: }
                   1234: 
                   1235: PUBLIC BOOL HTNet_setEventParam (HTNet * net, void * eventParam)
                   1236: {
2.81      frystyk  1237:     if (net) return HTEvent_setParam(&net->event, eventParam);
                   1238:     return NO;
                   1239: }
                   1240: 
2.87      frystyk  1241: PUBLIC void * HTNet_eventParam (HTNet * net)
2.81      frystyk  1242: {
2.87      frystyk  1243:     return net ? net->event.param : NULL;
2.81      frystyk  1244: }
                   1245: 
                   1246: PUBLIC BOOL HTNet_setEventCallback(HTNet * net, HTEventCallback * cbf)
                   1247: {
                   1248:     if (net) return HTEvent_setCallback(&net->event, cbf);
                   1249:     return NO;
                   1250: }
                   1251: 
                   1252: PUBLIC HTEventCallback * HTNet_eventCallback(HTNet * net)
                   1253: {
                   1254:     return net->event.cbf;
                   1255: }
                   1256: 
                   1257: PUBLIC BOOL HTNet_setEventPriority(HTNet * net, HTPriority priority)
                   1258: {
                   1259:     if (net) return HTEvent_setPriority(&net->event, priority);
                   1260:     return NO;
                   1261: }
                   1262: 
                   1263: PUBLIC HTPriority HTNet_eventPriority(HTNet * net)
                   1264: {
                   1265:     return net->event.priority;
                   1266: }
                   1267: 
                   1268: PUBLIC HTStream * HTNet_readStream(HTNet * net)
                   1269: {
                   1270:     if (!net) return NULL;
                   1271:     return net->readStream;
                   1272: }
                   1273: 
                   1274: PUBLIC BOOL HTNet_setReadStream (HTNet * net, HTStream * stream)
                   1275: {
                   1276:     if (net) {
                   1277:        net->readStream = stream;
                   1278:        return YES;
                   1279:     }
                   1280:     return NO;
2.96      frystyk  1281: }
                   1282: 
                   1283: /*
                   1284: **     Should we do raw byte count at the network or later?
                   1285: **     Normally it is later but in cases like FTP we need it
                   1286: **     in the raw form
                   1287: */
                   1288: PUBLIC BOOL HTNet_setRawBytesCount (HTNet * net, BOOL mode)
                   1289: {
                   1290:     if (net) {
                   1291:        net->countRawBytes = mode;
                   1292:        return YES;
                   1293:     }
                   1294:     return NO;
                   1295: }
                   1296: 
                   1297: PUBLIC BOOL HTNet_rawBytesCount (HTNet * net)
                   1298: {
                   1299:     return (net && net->countRawBytes);
2.55      frystyk  1300: }

Webmaster