Annotation of Amaya/amaya/AHTBridge.c, revision 1.75
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: */
1.75 ! cvs 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