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

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

Webmaster