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

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

Webmaster