Annotation of Amaya/amaya/AHTBridge.c, revision 1.74

1.9       cvs         1: /*
                      2:  *
                      3:  *  (c) COPYRIGHT MIT and INRIA, 1996.
                      4:  *  Please first read the full copyright statement in file COPYRIGHT.
                      5:  *
                      6:  */
                      7:  
1.14      cvs         8: /*
                      9:  * AHTBridge.c : This module implements the callback setup and
                     10:  * handlers between the Xt, libwww, and Amaya procedures. It's responsible
                     11:  * for assigning, modifying, and supressing Xt events to the active
                     12:  * requests.
                     13:  *
                     14:  * Author: J Kahan
1.67      cvs        15:  *         J. K./R. Guetari. Windows NT/95 routines
1.14      cvs        16:  *
                     17:  */
1.68      cvs        18: #ifdef _GTK
                     19: #include <glib.h>
                     20: #endif /* _GTK */
                     21: 
1.16      cvs        22: #define THOT_EXPORT extern
1.4       cvs        23: #include "amaya.h"
1.10      cvs        24: #include "AHTBridge_f.h"
                     25: #include "AHTFWrite_f.h"
                     26: #include "query_f.h"
                     27: #include "answer_f.h"
1.64      cvs        28: #include "HTEvtLst.h"
1.4       cvs        29: 
1.58      cvs        30: #if 0
                     31: #define DEBUG_LIBWWW
                     32: #define THD_TRACE 1
                     33: #endif
                     34: 
1.22      cvs        35: #ifndef _WINDOWS
1.4       cvs        36: /* Amaya's X appcontext */
1.16      cvs        37: extern ThotAppContext app_cont;
1.68      cvs        38: #ifndef _GTK
1.4       cvs        39: 
1.32      cvs        40: /* Private functions */
1.4       cvs        41: #ifdef __STDC__
1.58      cvs        42: static void         RequestRegisterReadXtevent (SOCKET);
                     43: static void         RequestKillReadXtevent (SOCKET);
                     44: static void         RequestRegisterWriteXtevent ( SOCKET);
                     45: static void         RequestKillWriteXtevent (SOCKET);
                     46: static void         RequestRegisterExceptXtevent ( SOCKET);
                     47: static void         RequestKillExceptXtevent (SOCKET);
1.27      cvs        48: #else /* __STDC__ */
1.18      cvs        49: static void         RequesAddReadXtevent ();
1.7       cvs        50: static void         RequestKillReadXtevent ();
1.18      cvs        51: static void         RequesAddWriteXtevent ();
1.7       cvs        52: static void         RequestKillWriteXtevent ();
1.18      cvs        53: static void         RequestRegisterExceptXtevent ();
1.7       cvs        54: static void         RequestKillExceptXtevent ();
1.27      cvs        55: #endif /* __STDC__ */
1.58      cvs        56: 
1.68      cvs        57: #endif /* _GTK */
1.59      cvs        58: #endif /* !_WINDOWS */
1.24      cvs        59: 
1.68      cvs        60: #ifdef _GTK
                     61: #define WWW_HIGH_PRIORITY (G_PRIORITY_HIGH_IDLE + 50)
                     62: #define WWW_LOW_PRIORITY G_PRIORITY_LOW
                     63: #define WWW_SCALE_PRIORITY(p) ((WWW_HIGH_PRIORITY - WWW_LOW_PRIORITY) * p \
                     64:                           / HT_PRIORITY_MAX + WWW_LOW_PRIORITY)
                     65:      
                     66: #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
                     67: #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
                     68: #define EXCEPTION_CONDITION (G_IO_PRI)
                     69:      
                     70:  typedef struct _SockEventInfo SockEventInfo;
                     71:  struct _SockEventInfo {
                     72:    SOCKET s;
                     73:    HTEventType type;
                     74:    HTEvent *event;
                     75:    guint io_tag;
                     76:    guint timer_tag;
                     77:  };
                     78:  
                     79:  typedef struct _SockInfo SockInfo;
                     80:  struct _SockInfo {
                     81:    SOCKET s;
                     82:    GIOChannel *io;
                     83:    SockEventInfo ev[HTEvent_TYPES];
                     84:  };
                     85:  
                     86:  static GHashTable *sockhash = NULL;
                     87:  
                     88:  
                     89:  static SockInfo *
                     90:  get_sock_info(SOCKET s, gboolean create)
                     91:  {
                     92:    SockInfo *info;
                     93:  
                     94:    if (!sockhash)
                     95:      sockhash = g_hash_table_new(g_direct_hash, g_direct_equal);
                     96:  
                     97:    info = g_hash_table_lookup(sockhash, GINT_TO_POINTER(s));
                     98:    if (!info && create) {
                     99:      info = g_new0(SockInfo, 1);
                    100:      info->s = s;
                    101:      info->io = g_io_channel_unix_new(s);
                    102:      info->ev[0].s = info->ev[1].s = info->ev[2].s = s;
                    103:      info->ev[0].type = HTEvent_READ;
                    104:      info->ev[1].type = HTEvent_WRITE;
                    105:      info->ev[2].type = HTEvent_OOB;
                    106:      g_hash_table_insert(sockhash, GINT_TO_POINTER(s), info);
                    107:    }
                    108:    return info;
                    109:  }
                    110:  
                    111:  static gboolean glibwww_timeout_func (gpointer data);
                    112:  static gboolean glibwww_io_func(GIOChannel *source, GIOCondition condition,
                    113:                                  gpointer data);
                    114: #endif /* _GTK */
                    115: 
1.32      cvs       116: /* Private variables */
1.4       cvs       117: 
                    118: /*
1.58      cvs       119:  * this set of HTEventType map our WinSock "socket event HTEventType" into 
1.4       cvs       120:  * our read and write sets. Note that under the canonical Unix model,
                    121:  * a non-blocking socket passed to an accept() call will appear as readable, 
                    122:  * whilst a non-blocking call to connect() will appear as writeable. In add.
                    123:  * if the connection has been closed, the socket will appear readable under
                    124:  * BSD Unix semantics 
                    125:  */
1.32      cvs       126: 
1.68      cvs       127: #ifndef _GTK
1.58      cvs       128: static const HTEventType ReadBits = HTEvent_READ | HTEvent_ACCEPT | HTEvent_CLOSE;
                    129: static const HTEventType WriteBits = HTEvent_WRITE | HTEvent_CONNECT;
                    130: static const HTEventType ExceptBits = HTEvent_OOB;
                    131: 
                    132: typedef struct sStatus {
                    133:   XtInputId read;             /* the different XtId's */
                    134:   XtInputId write;
                    135:   XtInputId except;
                    136: } SocketStatus;
1.4       cvs       137: 
1.38      cvs       138: #define SOCK_TABLE_SIZE 67
                    139: #define HASH(s) ((s) % SOCK_TABLE_SIZE)
1.58      cvs       140: static SocketStatus persSockets[SOCK_TABLE_SIZE];
1.68      cvs       141: #endif /* _GTK */
1.4       cvs       142: 
1.10      cvs       143: /*--------------------------------------------------------------------
                    144:   AHTCallback_bridge
1.11      cvs       145:   this function acts as a bridge between Xt and libwww. From the Xt
                    146:   point of view, this function is the callback handler whenever there's
                    147:   any activity on the sockets associated with the active requests. From
                    148:   the libwww point of view, this is the function that takes the initiative
                    149:   to invoke the callback function associated with an active request,
                    150:   whenever there's an activity in the socket associated to it.
                    151:   In this latter  aspect, this function is similar to the library's
                    152:   own __DoCallback()  function.
                    153:   Upon activation, the function looks up the request associated with the
                    154:   active socket and then looks up the cbf associated with that request.
                    155:   Upon completion of the execution of the request's cbf, it verifies
                    156:   the state of the request and, if it's an asynchronous request, deletes
                    157:   the memory allocated to it.
1.10      cvs       158:   -------------------------------------------------------------------*/
1.37      cvs       159: #ifndef _WINDOWS
1.68      cvs       160: #ifndef _GTK
1.4       cvs       161: #ifdef __STDC__
1.12      cvs       162: void *AHTCallback_bridge (caddr_t cd, int *s, XtInputId * id)
1.26      cvs       163: #else  /* __STDC__ */
1.12      cvs       164: void *AHTCallback_bridge (cd, s, id)
1.7       cvs       165: caddr_t             cd;
                    166: int                *s;
                    167: XtInputId          *id;
1.4       cvs       168: #endif /* __STDC__ */
                    169: {
1.11      cvs       170:    int                 status;  /* the status result of the libwwww call */
1.58      cvs       171:    HTEventType         type  = HTEvent_ALL;    
1.38      cvs       172:    int                 v;
1.40      cvs       173:    int                        socket = *s;
1.58      cvs       174:    ms_t                now = HTGetTimeInMillis();
                    175:    
                    176:    v = HASH (socket);
1.4       cvs       177: 
1.58      cvs       178:    /* convert the FD into an HTEventType which will allow us to find the
                    179:       request associated with the socket */
1.47      cvs       180: 
1.58      cvs       181:    /* I could send some other data here, like the event itself, right */
                    182:    switch ((XtInputId) cd) 
1.47      cvs       183:      {
1.58      cvs       184:      case XtInputReadMask:
                    185:        type = HTEvent_READ;
                    186:        break;
                    187:      case XtInputWriteMask:
                    188:        type = HTEvent_WRITE;
                    189:        break;
                    190:      case XtInputExceptMask:
                    191:        type = HTEvent_OOB;
                    192:        break;
                    193:      default:
                    194:        type = HTEvent_ALL; 
                    195:        break;
                    196:      } /* switch */
1.47      cvs       197:    
1.32      cvs       198:    /* Invokes the callback associated to the requests */
                    199:    
1.66      cvs       200:    /**   CanDoStop_set (FALSE); **/
1.58      cvs       201:    if ((status = HTEventList_dispatch (socket, type, now)) != HT_OK)
                    202:      {
1.36      cvs       203: #ifdef DEBUG_LIBWWW
1.58      cvs       204:      HTTrace ("Callback.... returned a value != HT_OK");
1.36      cvs       205: #endif
1.58      cvs       206:      }
1.41      cvs       207: 
1.66      cvs       208:    /***   CanDoStop_set (TRUE); **/
1.38      cvs       209: 
1.7       cvs       210:    return (0);
1.4       cvs       211: }
1.68      cvs       212: #endif /* _GTK */
1.37      cvs       213: #endif /* !_WINDOWS */
1.41      cvs       214: 
                    215: /*--------------------------------------------------------------------
                    216:   ProcessTerminateRequest
                    217:   This function is called whenever a request has ended. If the requested
                    218:   ended normally, the function will call any callback associated to the
                    219:   request. Otherwise, it will just mark the request as over.
                    220:   -------------------------------------------------------------------*/
                    221: #ifdef __STDC__
1.56      cvs       222: void  ProcessTerminateRequest (HTRequest * request, HTResponse * response, void *param, int status)
1.41      cvs       223: #else
1.56      cvs       224: void ProcessTerminateRequest (request, response, param, status)
1.58      cvs       225: HTRequest *request;
                    226: HTResponse *response;
                    227: void *param;
                    228: int status;
1.41      cvs       229: #endif
                    230: {   
1.58      cvs       231:   AHTReqContext *me = HTRequest_context (request);
1.56      cvs       232: 
1.58      cvs       233:   /* choose a correct treatment in function of the request's
1.41      cvs       234:      being associated with an error, with an interruption, or with a
                    235:      succesful completion */
1.64      cvs       236: 
                    237: #ifdef DEBUG_LIBWWW  
                    238:   if (THD_TRACE)
                    239:     fprintf (stderr,"ProcessTerminateRequest: processing req %p, url %s, status %d\n", me, me->urlName, me->reqStatus);  
                    240: #endif /* DEBUG_LIBWWW */
1.41      cvs       241:   if (me->reqStatus == HT_END)
                    242:     {
1.58      cvs       243:       if (AmayaIsAlive ()  && me->terminate_cbf)
1.73      cvs       244:        (*me->terminate_cbf) (me->docid, 0, me->urlName, me->outputfile, &(me->http_headers), me->context_tcbf);
1.58      cvs       245: 
1.41      cvs       246:     }
1.42      cvs       247:   else if (me->reqStatus == HT_ABORT)
1.41      cvs       248:     /* either the application ended or the user pressed the stop 
                    249:        button. We erase the incoming file, if it exists */
                    250:     {
1.52      cvs       251:       if (AmayaIsAlive () && me->terminate_cbf)
1.73      cvs       252:        (*me->terminate_cbf) (me->docid, -1, me->urlName, me->outputfile, &(me->http_headers), me->context_tcbf);
1.72      cvs       253:       if (me->outputfile && me->outputfile[0] != WC_EOS)
1.41      cvs       254:        {
1.70      cvs       255:          TtaFileUnlink (me->outputfile);
1.72      cvs       256:          me->outputfile[0] = WC_EOS; 
1.70      cvs       257:        } 
1.41      cvs       258:     }
                    259:   else if (me->reqStatus == HT_ERR)
                    260:     {
                    261:       /* there was an error */
1.58      cvs       262:       if (AmayaIsAlive && me->terminate_cbf)
1.73      cvs       263:        (*me->terminate_cbf) (me->docid, -1, me->urlName, me->outputfile, &(me->http_headers), me->context_tcbf);
1.41      cvs       264:       
1.71      cvs       265:       if (me->outputfile && me->outputfile[0] != WC_EOS)
1.41      cvs       266:        {
1.70      cvs       267:          TtaFileUnlink (me->outputfile);
1.71      cvs       268:          me->outputfile[0] = WC_EOS;
1.41      cvs       269:        }
                    270:     }
1.58      cvs       271: 
1.41      cvs       272:    /* we erase the context if we're dealing with an asynchronous request */
1.61      cvs       273:   if ((me->mode & AMAYA_ASYNC)
                    274:       || (me->mode & AMAYA_IASYNC))
1.58      cvs       275:     {
1.63      cvs       276:       Document doc = me->docid;
1.58      cvs       277:       me->reqStatus = HT_END;
                    278:       /*** @@@ do we need this? yes!! **/
                    279:       AHTLoadTerminate_handler (request, response, param, status);
                    280:       AHTReqContext_delete (me);
1.63      cvs       281:       AHTPrintPendingRequestStatus (doc, YES);
1.58      cvs       282:     }
                    283: }
1.4       cvs       284: 
1.32      cvs       285: #ifdef _WINDOWS
1.29      cvs       286: /*----------------------------------------------------------------
1.32      cvs       287:   WIN_Activate_Request
1.29      cvs       288:   when there are more open requests than available sockets, the 
                    289:   requests are put in a "pending state." When a socket becomes
                    290:   available, libwww associates it with a pending request and then
                    291:   calls this callback function. This function is responsible for
                    292:   opening the temporary file where the GET and POST  results
                    293:   will be stored. The function is also responsible for 
                    294:   registering the socket with the Xt event loop.
                    295:   Consult the libwww manual for more details on the signature
                    296:   of this function.
                    297:   ----------------------------------------------------------------*/
                    298: #ifdef __STDC__
1.32      cvs       299: int                 WIN_Activate_Request (HTRequest * request, HTAlertOpcode op, int msgnum, const char *dfault, void *input, HTAlertPar * reply)
1.29      cvs       300: #else
1.32      cvs       301: int                 WIN_Activate_Request (request, op, msgnum, dfault, input, reply)
1.29      cvs       302: HTRequest          *request;
                    303: HTAlertOpcode       op;
                    304: int                 msgnum;
                    305: const char         *dfault;
                    306: void               *input;
                    307: HTAlertPar         *reply;
                    308: 
                    309: #endif /* __STDC__ */
                    310: {
                    311:    AHTReqContext      *me = HTRequest_context (request);
                    312: 
1.58      cvs       313:    if (me->reqStatus == HT_NEW) 
                    314:      {
                    315:        if (!(me->output)
                    316:           && (me->output != stdout) 
                    317:           && me->outputfile
1.70      cvs       318:           &&  (me->output = ufopen (me->outputfile, TEXT("wb"))) == NULL) {
1.58      cvs       319:         /* the request is associated with a file */
1.72      cvs       320:         me->outputfile[0] = WC_EOS;    /* file could not be opened */
1.70      cvs       321:         TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE), me->outputfile);
1.58      cvs       322:         me->reqStatus = HT_ERR;
                    323: 
                    324:         if (me->error_html)
                    325:           DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR; /* so we can show the error message */
                    326:        } 
                    327:        else
                    328:         {
                    329: #ifdef DEBUG_LIBWWW
                    330:           if (THD_TRACE)
                    331:             fprintf (stderr, "WIN_Activate_Request: Activating pending %s. "
                    332:                      "Open fd %d\n", me->urlName, (int) me->output);
                    333: #endif /* DEBUG_LIBWWW */
                    334:           HTRequest_setOutputStream (me->request, AHTFWriter_new (me->request, me->output, YES));    
                    335:           /*change the status of the request */
                    336:           me->reqStatus = HT_WAITING;
                    337:         }
                    338:      } 
                    339:    else if (me->reqStatus == HT_WAITING)
                    340:      {
                    341:        /*change the status of the request */
                    342:        rewind (me->output);
                    343:        if (HTRequest_outputStream (me->request) == NULL)
                    344:         HTRequest_setOutputStream (me->request, AHTFWriter_new (me->request, me->output, YES));
                    345:      } 
1.32      cvs       346:    else {
1.36      cvs       347:      me->reqStatus = HT_ERR;
1.32      cvs       348:    }
                    349:    
1.36      cvs       350:    return ((me->reqStatus != HT_ERR) ? HT_OK : HT_ERROR);
1.32      cvs       351: }
                    352: 
1.60      cvs       353: #endif /* WINDOWS but should be an else */
                    354: /* #else  */ /* _WINDOWS */
                    355: 
                    356: #ifndef _WINDOWS
1.68      cvs       357: #ifndef _GTK
1.32      cvs       358: 
1.11      cvs       359: /*----------------------------------------------------------------------
                    360:   AHTEvent_register
                    361:   callback called by libwww whenever a socket is open and associated
                    362:   to a request. It sets the pertinent Xt events so that the Xt Event
                    363:   loops gets an interruption whenever there's action of the socket. 
                    364:   In addition, it registers the request with libwww.
                    365:   ----------------------------------------------------------------------*/
1.4       cvs       366: #ifdef __STDC__
1.58      cvs       367: int AHTEvent_register (SOCKET sock, HTEventType type, HTEvent *event)
1.4       cvs       368: #else
1.58      cvs       369: int AHTEvent_register (sock, type, event)
                    370: SOCKET sock;
                    371: HTEventType type;
                    372: HTEvent *event;
1.7       cvs       373: #endif /* __STDC__ */
1.4       cvs       374: {
1.58      cvs       375:   int  status;
1.7       cvs       376: 
1.40      cvs       377:   if (sock == INVSOC)
                    378:     {
1.36      cvs       379: #ifdef DEBUG_LIBWWW
1.58      cvs       380:       fprintf(stderr, "AHTEvent_register: sock = INVSOC\n");
1.37      cvs       381: #endif /* DEBUG_LIBWWW */
1.58      cvs       382:       return (0);
                    383:     }
1.43      cvs       384: 
1.33      cvs       385: #ifndef _WINDOWS
1.58      cvs       386:        /* need something special for HTEvent_CLOSE */
                    387:   if (type & ReadBits)
                    388:     RequestRegisterReadXtevent (sock);
                    389:   
                    390:   if (type & WriteBits)
                    391:     RequestRegisterWriteXtevent (sock);
                    392:   
                    393:   if (type & ExceptBits)
                    394:     RequestRegisterExceptXtevent (sock);
1.33      cvs       395: #endif  /* !_WINDOWS */
1.58      cvs       396:   
1.51      cvs       397: #ifdef _WINDOWS   
1.50      cvs       398:   /* under windows, libwww requires an explicit FD_CLOSE registration 
1.58      cvs       399:      to detect HTTP responses not having a Content-Length header */
                    400:   status = HTEventList_register (sock, type | HTEvent_CLOSE , event);
1.50      cvs       401: #else
1.58      cvs       402:   status = HTEventList_register (sock, type, event);
1.51      cvs       403: #endif /* _WINDOWS */
1.58      cvs       404:   
                    405:   return (status);
                    406: }
1.68      cvs       407: #endif /* _GTK */
                    408: #endif /* _WINDOWS */
1.50      cvs       409: 
1.68      cvs       410: #ifdef _GTK
                    411: /*----------------------------------------------------------------------
                    412:   AHTEvent_register FOR GTK
                    413:   callback called by libwww whenever a socket is open and associated
                    414:   to a request. It sets the pertinent Xt events so that the Xt Event
                    415:   loops gets an interruption whenever there's action of the socket. 
                    416:   In addition, it registers the request with libwww.
                    417:   ----------------------------------------------------------------------*/
                    418: int AHTEvent_register (SOCKET s, HTEventType type, HTEvent *event)
                    419:  {
                    420:    SockInfo *info;
                    421:    gint priority = G_PRIORITY_DEFAULT;
                    422:    GIOCondition condition;
                    423:  
                    424:    if (s == INVSOC || HTEvent_INDEX(type) >= HTEvent_TYPES)
                    425:      return 0;
                    426:  
                    427:    info = get_sock_info(s, TRUE);
                    428:    info->ev[HTEvent_INDEX(type)].event = event;
                    429:  
                    430:    switch (HTEvent_INDEX(type)) {
                    431:    case HTEvent_INDEX(HTEvent_READ):
                    432:      condition = READ_CONDITION;      break;
                    433:    case HTEvent_INDEX(HTEvent_WRITE):
                    434:      condition = WRITE_CONDITION;     break;
                    435:    case HTEvent_INDEX(HTEvent_OOB):
                    436:      condition = EXCEPTION_CONDITION; break;
                    437:    }
                    438:    if (event->priority != HT_PRIORITY_OFF)
                    439:      priority = WWW_SCALE_PRIORITY(event->priority);
                    440:  
                    441:    info->ev[HTEvent_INDEX(type)].io_tag =
                    442:      g_io_add_watch_full(info->io, priority, condition, glibwww_io_func,
                    443:                           &info->ev[HTEvent_INDEX(type)], NULL);
                    444:  
                    445:    if (event->millis >= 0)
                    446:      info->ev[HTEvent_INDEX(type)].timer_tag =
                    447:        g_timeout_add_full(priority, event->millis, glibwww_timeout_func,
                    448:                           &info->ev[HTEvent_INDEX(type)], NULL);
                    449:  
                    450:    return HT_OK;
                    451:  }
                    452: #endif /* _GTK */
1.34      cvs       453: 
1.68      cvs       454: #ifndef _GTK
1.34      cvs       455: /*----------------------------------------------------------------------
                    456:   AHTEvent_unregister
                    457:   callback called by libwww each time a request is unregistered. This
                    458:   function takes care of unregistering the pertinent Xt events
                    459:   associated with the request's socket. In addition, it unregisters
                    460:   the request from libwww.
                    461:   ----------------------------------------------------------------------*/
                    462: #ifdef __STDC__
1.58      cvs       463: int AHTEvent_unregister (SOCKET sock, HTEventType type)
1.34      cvs       464: #else
1.58      cvs       465: int AHTEvent_unregister (sock, type)
1.34      cvs       466: SOCKET              sock;
1.58      cvs       467: HTEventType         type;
1.34      cvs       468: 
                    469: #endif /* __STDC__ */
                    470: {
1.58      cvs       471:   int    status;
1.38      cvs       472: 
                    473: #ifndef _WINDOWS   
1.58      cvs       474:    /* remove the Xt event hooks */
                    475:    if (type & ReadBits) 
                    476:      RequestKillReadXtevent (sock);
                    477:    
                    478:    if (type & WriteBits)
                    479:      RequestKillWriteXtevent (sock);
                    480:    
                    481:    if (type & ExceptBits) 
                    482:      RequestKillExceptXtevent (sock);
1.36      cvs       483: #endif /* !_WINDOWS */
1.35      cvs       484: 
1.58      cvs       485:    /* @@@ if this is the default for windows, no need to have AHTEvent_..
                    486:       in windows!! */
1.35      cvs       487: 
1.58      cvs       488:    /* call libwww's default routine */
                    489:    status = HTEventList_unregister (sock, type);
                    490:    
1.7       cvs       491:    return (status);
1.4       cvs       492: }
1.68      cvs       493: #endif /* _GTK */
                    494: 
                    495: #ifdef _GTK
                    496: /*----------------------------------------------------------------------
                    497:   AHTEvent_unregister FOR GTK
                    498:   callback called by libwww each time a request is unregistered. This
                    499:   function takes care of unregistering the pertinent Xt events
                    500:   associated with the request's socket. In addition, it unregisters
                    501:   the request from libwww.
                    502:   ----------------------------------------------------------------------*/
                    503: int AHTEvent_unregister (SOCKET s, HTEventType type)
                    504:  {
                    505:    SockInfo *info = get_sock_info(s, FALSE);
                    506:  
                    507:    if (info) {
                    508:      if (info->ev[HTEvent_INDEX(type)].io_tag)
                    509:        g_source_remove(info->ev[HTEvent_INDEX(type)].io_tag);
                    510:      if (info->ev[HTEvent_INDEX(type)].timer_tag)
                    511:        g_source_remove(info->ev[HTEvent_INDEX(type)].timer_tag);
                    512:  
                    513:      info->ev[HTEvent_INDEX(type)].event = NULL;
                    514:      info->ev[HTEvent_INDEX(type)].io_tag = 0;
                    515:      info->ev[HTEvent_INDEX(type)].timer_tag = 0;
                    516:  
                    517:      /* clean up sock hash if needed */
                    518:      if (info->ev[0].event == NULL &&
                    519:          info->ev[1].event == NULL &&
                    520:          info->ev[2].event == NULL) {
                    521:        g_hash_table_remove(sockhash, GINT_TO_POINTER(s));
                    522:        g_io_channel_unref(info->io);
                    523:        g_free(info);
                    524:      }
                    525:      
                    526:      return HT_OK;
                    527:    }
                    528:    return HT_ERROR;
                    529:  }
                    530: static gboolean
                    531: glibwww_timeout_func (gpointer data)
                    532:  {
                    533:    SockEventInfo *info = (SockEventInfo *)data;
                    534:    HTEvent *event = info->event;
                    535:  
                    536:    (* event->cbf) (info->s, event->param, HTEvent_TIMEOUT);
                    537:    return TRUE;
                    538:  }
                    539:  
                    540: static gboolean
                    541: glibwww_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
                    542:  {
                    543:    SockEventInfo *info = (SockEventInfo *)data;
                    544:    HTEvent *event = info->event;
                    545:  
                    546:    if (info->timer_tag)
                    547:        g_source_remove(info->timer_tag);
                    548:    if (info->event->millis >= 0) {
                    549:      gint priority = G_PRIORITY_DEFAULT;
                    550:  
                    551:      if (event->priority != HT_PRIORITY_OFF)
                    552:        priority = WWW_SCALE_PRIORITY(event->priority);
                    553:      info->timer_tag =
                    554:        g_timeout_add_full(priority, info->event->millis, glibwww_timeout_func,
                    555:                           info, NULL);
                    556:    }
                    557:  
                    558:    (* event->cbf) (info->s, event->param, info->type);
                    559:    return TRUE;
                    560:  }
                    561: 
                    562: #endif /* _GTK */
1.35      cvs       563: 
                    564: #ifndef _WINDOWS
1.4       cvs       565: 
1.58      cvs       566: /* Private functions */
                    567: 
1.11      cvs       568: /*----------------------------------------------------------------------
                    569:   RequestKillAllXtevents
                    570:   front-end for kill all Xt events associated with the request pointed
                    571:   to by "me".
                    572:   ----------------------------------------------------------------------*/
1.4       cvs       573: #ifdef __STDC__
1.7       cvs       574: void                RequestKillAllXtevents (AHTReqContext * me)
1.4       cvs       575: #else
1.7       cvs       576: void                RequestKillAllXtevents (me)
                    577: AHTReqContext      *me;
                    578: #endif /* __STDC__ */
1.4       cvs       579: {
1.68      cvs       580: #ifndef _GTK
1.58      cvs       581:   int sock = INVSOC;
                    582: 
                    583:   return;
                    584: 
                    585:   /* @@@ what to do with this one? @@@ */
                    586:   if (me->read_sock != INVSOC)
                    587:     sock = me->read_sock;
                    588:   else
                    589:     if (me->write_sock != INVSOC)
                    590:           sock = me->write_sock;
                    591:   else
                    592:     if (me->except_sock != INVSOC)
                    593:           sock = me->except_sock;
                    594: 
                    595: #ifdef DEBUG_LIBWWW
1.7       cvs       596:    if (THD_TRACE)
1.58      cvs       597:       fprintf (stderr, "RequestKillAllXtEvents: Clearing XtInputs\n");
                    598: #endif /* DEBUG_LIBWWW */
1.4       cvs       599: 
1.58      cvs       600: 
                    601:    RequestKillReadXtevent (sock);
                    602:    RequestKillWriteXtevent (sock);
                    603:    RequestKillExceptXtevent (sock);
1.68      cvs       604: #endif /* _GTK */
1.4       cvs       605: }
                    606: 
1.68      cvs       607: #ifndef _GTK
1.11      cvs       608: /*----------------------------------------------------------------------
1.18      cvs       609:   RequestRegisterReadXtevent
                    610:   Registers with Xt the read events associated with socket sock
                    611:   ----------------------------------------------------------------------*/
                    612: #ifdef __STDC__
1.58      cvs       613: static void         RequestRegisterReadXtevent (SOCKET sock)
1.18      cvs       614: #else
1.58      cvs       615: static void         RequestRegisterReadXtevent (sock)
1.18      cvs       616: SOCKET sock;
                    617: #endif /* __STDC__ */
                    618: {
1.58      cvs       619:   int v;
                    620: 
                    621:   v = HASH (sock);
                    622: 
                    623:   if (!persSockets[v].read)
1.18      cvs       624:     {
1.58      cvs       625:       persSockets[v].read  =
                    626:        XtAppAddInput (app_cont,
                    627:                       sock,
                    628:                       (XtPointer) XtInputReadMask,
                    629:                       (XtInputCallbackProc) AHTCallback_bridge,
                    630:                       (XtPointer) XtInputReadMask);
                    631:       
                    632: #ifdef DEBUG_LIBWWW
1.18      cvs       633:       if (THD_TRACE)
1.58      cvs       634:        fprintf (stderr, "RegisterReadXtEvent: adding XtInput %lu Socket %d\n",
                    635:                 persSockets[v].read, sock);
                    636: #endif /* DEBUG_LIBWWW */
1.18      cvs       637:     }
                    638: 
                    639: }
                    640: 
                    641: /*----------------------------------------------------------------------
1.11      cvs       642:   RequestKillReadXtevent
                    643:   kills any read Xt event associated with the request pointed to by "me".
                    644:   ----------------------------------------------------------------------*/
1.4       cvs       645: #ifdef __STDC__
1.58      cvs       646: static void         RequestKillReadXtevent (SOCKET sock)
1.4       cvs       647: #else
1.58      cvs       648: static void         RequestKillReadXtevent (sock)
                    649: SOCKET              sock;
1.7       cvs       650: #endif /* __STDC__ */
1.4       cvs       651: {
1.58      cvs       652:   int v;
                    653: 
                    654:   v = HASH (sock);
                    655: 
                    656:   if (persSockets[v].read)
                    657:     {
                    658: #ifdef DEBUG_LIBWWW
                    659:       if (THD_TRACE)
                    660:        fprintf (stderr, "UnregisterReadXtEvent: Clearing XtInput %lu\n",
                    661:                 persSockets[v].read);
                    662: #endif /* DEBUG_LIBWWW */
                    663:       XtRemoveInput (persSockets[v].read);
                    664:       persSockets[v].read = (XtInputId) NULL;
                    665:     }
1.18      cvs       666: }
                    667: 
                    668: /*----------------------------------------------------------------------
                    669:   RequestRegisterWriteXtevent
                    670:   Registers with Xt the write events associated with socket sock
                    671:   ----------------------------------------------------------------------*/
                    672: #ifdef __STDC__
1.58      cvs       673: static void         RequestRegisterWriteXtevent (SOCKET sock)
1.18      cvs       674: #else
1.58      cvs       675: static void         RequestRegisterWriteXtevent (sock)
1.18      cvs       676: SOCKET              sock;
                    677: 
                    678: #endif /* __STDC__ */
                    679: {
1.58      cvs       680:   int v;
                    681:   v = HASH (sock);
1.18      cvs       682: 
1.58      cvs       683:   if (!persSockets[v].write)
                    684:     {   
                    685:       persSockets[v].write =
                    686:        XtAppAddInput (app_cont,
                    687:                       sock,
1.18      cvs       688:                   (XtPointer) XtInputWriteMask,
                    689:                   (XtInputCallbackProc) AHTCallback_bridge,
                    690:                   (XtPointer) XtInputWriteMask);
1.58      cvs       691: #ifdef DEBUG_LIBWWW   
1.18      cvs       692:   if (THD_TRACE)
1.58      cvs       693:     fprintf (stderr, "RegisterWriteXtEvent: Adding XtInput %lu Socket %d\n",
                    694:             persSockets[v].write, sock);
                    695: #endif /* DEBUG_LIBWWW */
                    696:   
                    697:     }
1.4       cvs       698: }
                    699: 
1.11      cvs       700: /*----------------------------------------------------------------------
                    701:   RequestKillWriteXtevent
                    702:   kills any write Xt event associated with the request pointed to
                    703:   by "me".
                    704:   ----------------------------------------------------------------------*/
1.4       cvs       705: #ifdef __STDC__
1.58      cvs       706: static void         RequestKillWriteXtevent (SOCKET sock)
1.4       cvs       707: #else
1.58      cvs       708: static void         RequestKillWriteXtevent (sock)
                    709: SOCKET sock;
1.7       cvs       710: #endif /* __STDC__ */
1.4       cvs       711: {
1.58      cvs       712:   int v;
                    713: 
                    714:   v = HASH (sock);
                    715: 
                    716:   if (persSockets[v].write)
                    717:     {
                    718: #ifdef DEBUG_LIBWWW   
                    719:       if (THD_TRACE)
                    720:        fprintf (stderr, "UnRegisterWriteXtEvent: Clearing Write XtInputs "
                    721:                 "%lu\n",
                    722:                 persSockets[v].write);
                    723: #endif /* DEBUG_LIBWWW */
                    724:       XtRemoveInput (persSockets[v].write);
                    725:       persSockets[v].write =  (XtInputId) NULL;
                    726:     }
1.18      cvs       727: }
                    728: 
                    729: /*----------------------------------------------------------------------
                    730:   RequestRegisterExceptXtevent
                    731:   Registers with Xt the except events associated with socket sock
                    732:   ----------------------------------------------------------------------*/
                    733: #ifdef __STDC__
1.58      cvs       734: static void         RequestRegisterExceptXtevent (SOCKET sock)
1.18      cvs       735: #else
1.58      cvs       736: static void         RequestRegisterExceptXtevent (sock)
1.18      cvs       737: SOCKET              sock;
                    738: 
                    739: #endif /* __STDC__ */
                    740: {
1.58      cvs       741:   int v;
                    742: 
                    743:   v = HASH (sock);
                    744: 
                    745:    if (!persSockets[v].except)
1.18      cvs       746:      {
1.58      cvs       747:    
                    748:        persSockets[v].except =
                    749:         XtAppAddInput (app_cont,
                    750:                        sock,
                    751:                        (XtPointer) XtInputExceptMask,
                    752:                        (XtInputCallbackProc) AHTCallback_bridge,
                    753:                        (XtPointer) XtInputExceptMask);
                    754: #ifdef DEBUG_LIBWWW      
                    755:    if (THD_TRACE)
                    756:      fprintf (stderr, "RegisterExceptXtEvent: adding XtInput %lu Socket %d\n",
                    757:              persSockets[v].except, sock);
                    758: #endif /* DEBUG_LIBWWW */
1.18      cvs       759:      }
1.4       cvs       760: }
                    761: 
1.11      cvs       762: /*----------------------------------------------------------------------
                    763:   RequestKillExceptXtevent
                    764:   kills any exception Xt event associated with the request pointed to
                    765:   by "me".
                    766:   ----------------------------------------------------------------------*/
1.4       cvs       767: #ifdef __STDC__
1.58      cvs       768: static void         RequestKillExceptXtevent (SOCKET sock)
1.4       cvs       769: #else
1.58      cvs       770: static void         RequestKillExceptXtevent (sock)
                    771: SOCKET sock;
1.7       cvs       772: #endif /* __STDC__ */
1.4       cvs       773: {
1.58      cvs       774:   int v;
                    775: 
                    776:   v = HASH (sock);
                    777:   if (persSockets[v].except)
                    778:     {
                    779: #ifdef DEBUG_LIBWWW   
                    780:       if (THD_TRACE)
                    781:        fprintf (stderr, "UnregisterExceptXtEvent: Clearing Except XtInputs "
                    782:                 "%lu\n", persSockets[v].except);
                    783: #endif /* DEBUG_LIBWWW */
                    784:       XtRemoveInput (persSockets[v].except);
                    785:       persSockets[v].except = (XtInputId) NULL;
                    786:     }
                    787: }
                    788: 
                    789: /*----------------------------------------------------------------------
                    790:   Xt Timer functions 
                    791:   ----------------------------------------------------------------------*/
                    792: 
                    793: struct _HTTimer {
                    794:     ms_t        millis;         /* Relative value in millis */
                    795:     ms_t        expires;        /* Absolute value in millis */
                    796:     BOOL        relative;
                    797:     BOOL        repetitive;
                    798:     void *      param;          /* Client supplied context */
                    799:     HTTimerCallback * cbf;
                    800: };
                    801: 
                    802: struct _AmayaTimer {
                    803:   HTTimer *libwww_timer;
                    804:   XtIntervalId xt_timer;
                    805: };
                    806: 
                    807: typedef struct _AmayaTimer AmayaTimer;
                    808: 
                    809: static HTList *Timers = NULL;
                    810: 
                    811: /*----------------------------------------------------------------------
                    812:   ----------------------------------------------------------------------*/
                    813: void *TimerCallback (XtPointer cdata, XtIntervalId *id)
                    814: {
                    815:   HTList *cur, *last;
                    816:   AmayaTimer *me;
                    817:   HTTimer *libwww_timer;
                    818: 
                    819:   if (!AmayaIsAlive () 
                    820:       || Timers == NULL)
                    821:     return (0);
                    822: 
                    823:   /* find the timer from the uid */
                    824:   last = cur = Timers;
                    825:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    826:     {
                    827:       if (me->xt_timer == *id)
                    828:        break;
                    829:       last = cur;
                    830:     }
                    831: 
                    832:   if (me)
                    833:     {
                    834:       libwww_timer = me->libwww_timer;
                    835:       /* remove the element from the list @@@ can be optimized later */
                    836:       HTList_quickRemoveElement(cur, last);
                    837:       TtaFreeMemory (me);
                    838:       HTTimer_dispatch (libwww_timer);
                    839:     }
                    840: 
                    841:   return (0);
                    842: }
                    843: 
                    844: /*----------------------------------------------------------------------
1.59      cvs       845:   KillAllTimers
1.58      cvs       846:   ----------------------------------------------------------------------*/
1.59      cvs       847: #ifdef __STDC__
                    848: void KillAllTimers (void)
                    849: #else
1.58      cvs       850: void KillAllTimers ()
1.59      cvs       851: #endif /* __STDC__ */
1.58      cvs       852: {
                    853:   /* @@@ maybe add something else to kill the Xt things */
                    854:   if (Timers)
                    855:     HTList_delete (Timers);
1.65      cvs       856:   Timers = NULL;
1.58      cvs       857: }
                    858: 
                    859: /*----------------------------------------------------------------------
1.59      cvs       860:  AMAYA_SetTimer
                    861:  ----------------------------------------------------------------------*/
                    862: #ifdef __STDC__
                    863: void AMAYA_SetTimer (HTTimer *libwww_timer)
                    864: #else
                    865: void AMAYA_SetTimer (libwww_timer)
                    866: HTTimer *libwww_timer;
                    867: #endif /* __STDC__ */
1.58      cvs       868: {
                    869:   HTList *cur, *last;
                    870:   AmayaTimer *me;
                    871: 
                    872:   if (!AmayaIsAlive 
                    873:       || libwww_timer == NULL
                    874:       || libwww_timer->expires == 0)
                    875:     return;
                    876: 
                    877:   if (Timers == NULL)
                    878:     Timers = HTList_new ();
                    879: 
                    880:   /* see if this timer existed already */
                    881:   last = cur = Timers;
                    882:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    883:     {
                    884:       if (me->libwww_timer == libwww_timer)
                    885:        break;
                    886:       last = cur;
                    887:     }
                    888: 
                    889:   if (me)
                    890:     {
                    891:     /* remove the old timer */
                    892:       if (me->xt_timer) 
                    893:        {
                    894:          XtRemoveTimeOut (me->xt_timer);
1.59      cvs       895:          me->xt_timer = (XtIntervalId) NULL;
1.58      cvs       896:        }
                    897:     }
                    898:   else
                    899:     {
                    900:       /* create a new element */
                    901:       me = TtaGetMemory (sizeof (AmayaTimer));
                    902:       /* and add it to the list */
                    903:       HTList_addObject(last, (void *) me);
                    904:       me->libwww_timer = libwww_timer;
                    905:     }
                    906: 
                    907:   /* add a new time out */
                    908:   me->xt_timer = XtAppAddTimeOut (app_cont,
                    909:                                 me->libwww_timer->millis,
                    910:                                 (XtTimerCallbackProc) TimerCallback,
                    911:                                 (XtPointer *) (void *) me);
                    912: 
                    913: }
                    914: 
                    915: /*----------------------------------------------------------------------
1.59      cvs       916:   AMAYA_DeleteTimer
1.58      cvs       917:   ----------------------------------------------------------------------*/
1.59      cvs       918: #ifdef __STDC__
                    919: void AMAYA_DeleteTimer (HTTimer *libwww_timer)
                    920: #else
                    921: void AMAYA_DeleteTimer (libwww_timer)
                    922: HTTimer *libwww_timer;
                    923: #endif /* __STDC__ */
1.58      cvs       924: {
                    925:   HTList *cur, *last;
                    926:   AmayaTimer *me;
                    927: 
1.59      cvs       928:   if (Timers == NULL || libwww_timer == NULL)
1.58      cvs       929:     return;
                    930: 
                    931:   /* find the id */
                    932:   last = cur = Timers;
                    933:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    934:     {
1.59      cvs       935:       if (me->libwww_timer == libwww_timer)
1.58      cvs       936:        break;
                    937:       last = cur;
                    938:     }
                    939: 
                    940:   if (me)
                    941:     {
                    942:       /* remove the Xt timer */
                    943:       XtRemoveTimeOut (me->xt_timer);
                    944:       /* and the element from the list */
1.65      cvs       945:       HTList_removeObject (Timers, me);
1.58      cvs       946:       TtaFreeMemory (me);
                    947:     }
1.31      cvs       948: }
1.68      cvs       949: #endif /* _GTK */
1.58      cvs       950: 
1.32      cvs       951: #endif /* !_WINDOWS */

Webmaster