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

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

Webmaster