Return to AHTBridge.c CVS log | Up to [Public] / Amaya / amaya |
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.78 ! cvs 253: if (me->outputfile && me->outputfile[0] != EOS) 1.41 cvs 254: { 1.70 cvs 255: TtaFileUnlink (me->outputfile); 1.78 ! cvs 256: me->outputfile[0] = 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.78 ! cvs 265: if (me->outputfile && me->outputfile[0] != EOS) 1.41 cvs 266: { 1.70 cvs 267: TtaFileUnlink (me->outputfile); 1.78 ! cvs 268: me->outputfile[0] = 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.78 ! cvs 318: && (me->output = fopen (me->outputfile, "wb")) == NULL) { 1.58 cvs 319: /* the request is associated with a file */ 1.78 ! cvs 320: me->outputfile[0] = 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.76 kahan 472: 473: if (sock == INVSOC) 474: return HT_OK; 1.38 cvs 475: 476: #ifndef _WINDOWS 1.58 cvs 477: /* remove the Xt event hooks */ 478: if (type & ReadBits) 479: RequestKillReadXtevent (sock); 480: 481: if (type & WriteBits) 482: RequestKillWriteXtevent (sock); 483: 484: if (type & ExceptBits) 485: RequestKillExceptXtevent (sock); 1.36 cvs 486: #endif /* !_WINDOWS */ 1.35 cvs 487: 1.58 cvs 488: /* @@@ if this is the default for windows, no need to have AHTEvent_.. 489: in windows!! */ 1.35 cvs 490: 1.58 cvs 491: /* call libwww's default routine */ 492: status = HTEventList_unregister (sock, type); 493: 1.7 cvs 494: return (status); 1.4 cvs 495: } 1.68 cvs 496: #endif /* _GTK */ 497: 498: #ifdef _GTK 499: /*---------------------------------------------------------------------- 500: AHTEvent_unregister FOR GTK 501: callback called by libwww each time a request is unregistered. This 502: function takes care of unregistering the pertinent Xt events 503: associated with the request's socket. In addition, it unregisters 504: the request from libwww. 505: ----------------------------------------------------------------------*/ 506: int AHTEvent_unregister (SOCKET s, HTEventType type) 507: { 1.76 kahan 508: SockInfo *info; 509: 510: if (s == INVSOC) 511: return HT_OK; 512: 513: info = get_sock_info(s, FALSE); 1.68 cvs 514: 515: if (info) { 516: if (info->ev[HTEvent_INDEX(type)].io_tag) 517: g_source_remove(info->ev[HTEvent_INDEX(type)].io_tag); 518: if (info->ev[HTEvent_INDEX(type)].timer_tag) 519: g_source_remove(info->ev[HTEvent_INDEX(type)].timer_tag); 520: 521: info->ev[HTEvent_INDEX(type)].event = NULL; 522: info->ev[HTEvent_INDEX(type)].io_tag = 0; 523: info->ev[HTEvent_INDEX(type)].timer_tag = 0; 524: 525: /* clean up sock hash if needed */ 526: if (info->ev[0].event == NULL && 527: info->ev[1].event == NULL && 528: info->ev[2].event == NULL) { 529: g_hash_table_remove(sockhash, GINT_TO_POINTER(s)); 530: g_io_channel_unref(info->io); 531: g_free(info); 532: } 533: 534: return HT_OK; 535: } 536: return HT_ERROR; 537: } 538: static gboolean 539: glibwww_timeout_func (gpointer data) 540: { 541: SockEventInfo *info = (SockEventInfo *)data; 542: HTEvent *event = info->event; 543: 544: (* event->cbf) (info->s, event->param, HTEvent_TIMEOUT); 545: return TRUE; 546: } 547: 548: static gboolean 549: glibwww_io_func(GIOChannel *source, GIOCondition condition, gpointer data) 550: { 551: SockEventInfo *info = (SockEventInfo *)data; 552: HTEvent *event = info->event; 553: 554: if (info->timer_tag) 555: g_source_remove(info->timer_tag); 556: if (info->event->millis >= 0) { 557: gint priority = G_PRIORITY_DEFAULT; 558: 559: if (event->priority != HT_PRIORITY_OFF) 560: priority = WWW_SCALE_PRIORITY(event->priority); 561: info->timer_tag = 562: g_timeout_add_full(priority, info->event->millis, glibwww_timeout_func, 563: info, NULL); 564: } 565: 566: (* event->cbf) (info->s, event->param, info->type); 567: return TRUE; 568: } 569: 570: #endif /* _GTK */ 1.35 cvs 571: 572: #ifndef _WINDOWS 1.4 cvs 573: 1.58 cvs 574: /* Private functions */ 575: 1.11 cvs 576: /*---------------------------------------------------------------------- 577: RequestKillAllXtevents 578: front-end for kill all Xt events associated with the request pointed 579: to by "me". 580: ----------------------------------------------------------------------*/ 1.4 cvs 581: #ifdef __STDC__ 1.7 cvs 582: void RequestKillAllXtevents (AHTReqContext * me) 1.4 cvs 583: #else 1.7 cvs 584: void RequestKillAllXtevents (me) 585: AHTReqContext *me; 586: #endif /* __STDC__ */ 1.4 cvs 587: { 1.68 cvs 588: #ifndef _GTK 1.58 cvs 589: int sock = INVSOC; 590: 591: return; 592: 593: /* @@@ what to do with this one? @@@ */ 594: if (me->read_sock != INVSOC) 595: sock = me->read_sock; 596: else 597: if (me->write_sock != INVSOC) 598: sock = me->write_sock; 599: else 600: if (me->except_sock != INVSOC) 601: sock = me->except_sock; 602: 603: #ifdef DEBUG_LIBWWW 1.7 cvs 604: if (THD_TRACE) 1.58 cvs 605: fprintf (stderr, "RequestKillAllXtEvents: Clearing XtInputs\n"); 606: #endif /* DEBUG_LIBWWW */ 1.4 cvs 607: 1.58 cvs 608: 609: RequestKillReadXtevent (sock); 610: RequestKillWriteXtevent (sock); 611: RequestKillExceptXtevent (sock); 1.68 cvs 612: #endif /* _GTK */ 1.4 cvs 613: } 614: 1.68 cvs 615: #ifndef _GTK 1.11 cvs 616: /*---------------------------------------------------------------------- 1.18 cvs 617: RequestRegisterReadXtevent 618: Registers with Xt the read events associated with socket sock 619: ----------------------------------------------------------------------*/ 620: #ifdef __STDC__ 1.58 cvs 621: static void RequestRegisterReadXtevent (SOCKET sock) 1.18 cvs 622: #else 1.58 cvs 623: static void RequestRegisterReadXtevent (sock) 1.18 cvs 624: SOCKET sock; 625: #endif /* __STDC__ */ 626: { 1.58 cvs 627: int v; 628: 629: v = HASH (sock); 630: 631: if (!persSockets[v].read) 1.18 cvs 632: { 1.58 cvs 633: persSockets[v].read = 634: XtAppAddInput (app_cont, 635: sock, 636: (XtPointer) XtInputReadMask, 637: (XtInputCallbackProc) AHTCallback_bridge, 638: (XtPointer) XtInputReadMask); 639: 640: #ifdef DEBUG_LIBWWW 1.18 cvs 641: if (THD_TRACE) 1.58 cvs 642: fprintf (stderr, "RegisterReadXtEvent: adding XtInput %lu Socket %d\n", 643: persSockets[v].read, sock); 644: #endif /* DEBUG_LIBWWW */ 1.18 cvs 645: } 646: 647: } 648: 649: /*---------------------------------------------------------------------- 1.11 cvs 650: RequestKillReadXtevent 651: kills any read Xt event associated with the request pointed to by "me". 652: ----------------------------------------------------------------------*/ 1.4 cvs 653: #ifdef __STDC__ 1.58 cvs 654: static void RequestKillReadXtevent (SOCKET sock) 1.4 cvs 655: #else 1.58 cvs 656: static void RequestKillReadXtevent (sock) 657: SOCKET sock; 1.7 cvs 658: #endif /* __STDC__ */ 1.4 cvs 659: { 1.58 cvs 660: int v; 661: 662: v = HASH (sock); 663: 664: if (persSockets[v].read) 665: { 666: #ifdef DEBUG_LIBWWW 667: if (THD_TRACE) 668: fprintf (stderr, "UnregisterReadXtEvent: Clearing XtInput %lu\n", 669: persSockets[v].read); 670: #endif /* DEBUG_LIBWWW */ 671: XtRemoveInput (persSockets[v].read); 672: persSockets[v].read = (XtInputId) NULL; 673: } 1.18 cvs 674: } 675: 676: /*---------------------------------------------------------------------- 677: RequestRegisterWriteXtevent 678: Registers with Xt the write events associated with socket sock 679: ----------------------------------------------------------------------*/ 680: #ifdef __STDC__ 1.58 cvs 681: static void RequestRegisterWriteXtevent (SOCKET sock) 1.18 cvs 682: #else 1.58 cvs 683: static void RequestRegisterWriteXtevent (sock) 1.18 cvs 684: SOCKET sock; 685: 686: #endif /* __STDC__ */ 687: { 1.58 cvs 688: int v; 689: v = HASH (sock); 1.18 cvs 690: 1.58 cvs 691: if (!persSockets[v].write) 692: { 693: persSockets[v].write = 694: XtAppAddInput (app_cont, 695: sock, 1.18 cvs 696: (XtPointer) XtInputWriteMask, 697: (XtInputCallbackProc) AHTCallback_bridge, 698: (XtPointer) XtInputWriteMask); 1.58 cvs 699: #ifdef DEBUG_LIBWWW 1.18 cvs 700: if (THD_TRACE) 1.58 cvs 701: fprintf (stderr, "RegisterWriteXtEvent: Adding XtInput %lu Socket %d\n", 702: persSockets[v].write, sock); 703: #endif /* DEBUG_LIBWWW */ 704: 705: } 1.4 cvs 706: } 707: 1.11 cvs 708: /*---------------------------------------------------------------------- 709: RequestKillWriteXtevent 710: kills any write Xt event associated with the request pointed to 711: by "me". 712: ----------------------------------------------------------------------*/ 1.4 cvs 713: #ifdef __STDC__ 1.58 cvs 714: static void RequestKillWriteXtevent (SOCKET sock) 1.4 cvs 715: #else 1.58 cvs 716: static void RequestKillWriteXtevent (sock) 717: SOCKET sock; 1.7 cvs 718: #endif /* __STDC__ */ 1.4 cvs 719: { 1.58 cvs 720: int v; 721: 722: v = HASH (sock); 723: 724: if (persSockets[v].write) 725: { 726: #ifdef DEBUG_LIBWWW 727: if (THD_TRACE) 728: fprintf (stderr, "UnRegisterWriteXtEvent: Clearing Write XtInputs " 729: "%lu\n", 730: persSockets[v].write); 731: #endif /* DEBUG_LIBWWW */ 732: XtRemoveInput (persSockets[v].write); 733: persSockets[v].write = (XtInputId) NULL; 734: } 1.18 cvs 735: } 736: 737: /*---------------------------------------------------------------------- 738: RequestRegisterExceptXtevent 739: Registers with Xt the except events associated with socket sock 740: ----------------------------------------------------------------------*/ 741: #ifdef __STDC__ 1.58 cvs 742: static void RequestRegisterExceptXtevent (SOCKET sock) 1.18 cvs 743: #else 1.58 cvs 744: static void RequestRegisterExceptXtevent (sock) 1.18 cvs 745: SOCKET sock; 746: 747: #endif /* __STDC__ */ 748: { 1.58 cvs 749: int v; 750: 751: v = HASH (sock); 752: 753: if (!persSockets[v].except) 1.18 cvs 754: { 1.58 cvs 755: 756: persSockets[v].except = 757: XtAppAddInput (app_cont, 758: sock, 759: (XtPointer) XtInputExceptMask, 760: (XtInputCallbackProc) AHTCallback_bridge, 761: (XtPointer) XtInputExceptMask); 762: #ifdef DEBUG_LIBWWW 763: if (THD_TRACE) 764: fprintf (stderr, "RegisterExceptXtEvent: adding XtInput %lu Socket %d\n", 765: persSockets[v].except, sock); 766: #endif /* DEBUG_LIBWWW */ 1.18 cvs 767: } 1.4 cvs 768: } 769: 1.11 cvs 770: /*---------------------------------------------------------------------- 771: RequestKillExceptXtevent 772: kills any exception Xt event associated with the request pointed to 773: by "me". 774: ----------------------------------------------------------------------*/ 1.4 cvs 775: #ifdef __STDC__ 1.58 cvs 776: static void RequestKillExceptXtevent (SOCKET sock) 1.4 cvs 777: #else 1.58 cvs 778: static void RequestKillExceptXtevent (sock) 779: SOCKET sock; 1.7 cvs 780: #endif /* __STDC__ */ 1.4 cvs 781: { 1.58 cvs 782: int v; 783: 784: v = HASH (sock); 785: if (persSockets[v].except) 786: { 787: #ifdef DEBUG_LIBWWW 788: if (THD_TRACE) 789: fprintf (stderr, "UnregisterExceptXtEvent: Clearing Except XtInputs " 790: "%lu\n", persSockets[v].except); 791: #endif /* DEBUG_LIBWWW */ 792: XtRemoveInput (persSockets[v].except); 793: persSockets[v].except = (XtInputId) NULL; 794: } 795: } 796: 797: /*---------------------------------------------------------------------- 798: Xt Timer functions 799: ----------------------------------------------------------------------*/ 800: 801: struct _HTTimer { 802: ms_t millis; /* Relative value in millis */ 803: ms_t expires; /* Absolute value in millis */ 804: BOOL relative; 805: BOOL repetitive; 806: void * param; /* Client supplied context */ 807: HTTimerCallback * cbf; 808: }; 809: 810: struct _AmayaTimer { 811: HTTimer *libwww_timer; 812: XtIntervalId xt_timer; 813: }; 814: 815: typedef struct _AmayaTimer AmayaTimer; 816: 817: static HTList *Timers = NULL; 818: 819: /*---------------------------------------------------------------------- 820: ----------------------------------------------------------------------*/ 821: void *TimerCallback (XtPointer cdata, XtIntervalId *id) 822: { 823: HTList *cur, *last; 824: AmayaTimer *me; 825: HTTimer *libwww_timer; 826: 827: if (!AmayaIsAlive () 828: || Timers == NULL) 829: return (0); 830: 831: /* find the timer from the uid */ 832: last = cur = Timers; 833: while ((me = (AmayaTimer * ) HTList_nextObject (cur))) 834: { 835: if (me->xt_timer == *id) 836: break; 837: last = cur; 838: } 839: 840: if (me) 841: { 842: libwww_timer = me->libwww_timer; 843: /* remove the element from the list @@@ can be optimized later */ 844: HTList_quickRemoveElement(cur, last); 845: TtaFreeMemory (me); 846: HTTimer_dispatch (libwww_timer); 847: } 848: 849: return (0); 850: } 851: 852: /*---------------------------------------------------------------------- 1.59 cvs 853: KillAllTimers 1.58 cvs 854: ----------------------------------------------------------------------*/ 1.59 cvs 855: #ifdef __STDC__ 856: void KillAllTimers (void) 857: #else 1.58 cvs 858: void KillAllTimers () 1.59 cvs 859: #endif /* __STDC__ */ 1.58 cvs 860: { 861: /* @@@ maybe add something else to kill the Xt things */ 862: if (Timers) 863: HTList_delete (Timers); 1.65 cvs 864: Timers = NULL; 1.58 cvs 865: } 866: 867: /*---------------------------------------------------------------------- 1.59 cvs 868: AMAYA_SetTimer 869: ----------------------------------------------------------------------*/ 870: #ifdef __STDC__ 871: void AMAYA_SetTimer (HTTimer *libwww_timer) 872: #else 873: void AMAYA_SetTimer (libwww_timer) 874: HTTimer *libwww_timer; 875: #endif /* __STDC__ */ 1.58 cvs 876: { 877: HTList *cur, *last; 878: AmayaTimer *me; 879: 880: if (!AmayaIsAlive 881: || libwww_timer == NULL 882: || libwww_timer->expires == 0) 883: return; 884: 885: if (Timers == NULL) 886: Timers = HTList_new (); 887: 888: /* see if this timer existed already */ 889: last = cur = Timers; 890: while ((me = (AmayaTimer * ) HTList_nextObject (cur))) 891: { 892: if (me->libwww_timer == libwww_timer) 893: break; 894: last = cur; 895: } 896: 897: if (me) 898: { 899: /* remove the old timer */ 900: if (me->xt_timer) 901: { 902: XtRemoveTimeOut (me->xt_timer); 1.59 cvs 903: me->xt_timer = (XtIntervalId) NULL; 1.58 cvs 904: } 905: } 906: else 907: { 908: /* create a new element */ 909: me = TtaGetMemory (sizeof (AmayaTimer)); 910: /* and add it to the list */ 911: HTList_addObject(last, (void *) me); 912: me->libwww_timer = libwww_timer; 913: } 914: 915: /* add a new time out */ 916: me->xt_timer = XtAppAddTimeOut (app_cont, 917: me->libwww_timer->millis, 918: (XtTimerCallbackProc) TimerCallback, 919: (XtPointer *) (void *) me); 920: 921: } 922: 923: /*---------------------------------------------------------------------- 1.59 cvs 924: AMAYA_DeleteTimer 1.58 cvs 925: ----------------------------------------------------------------------*/ 1.59 cvs 926: #ifdef __STDC__ 927: void AMAYA_DeleteTimer (HTTimer *libwww_timer) 928: #else 929: void AMAYA_DeleteTimer (libwww_timer) 930: HTTimer *libwww_timer; 931: #endif /* __STDC__ */ 1.58 cvs 932: { 933: HTList *cur, *last; 934: AmayaTimer *me; 935: 1.59 cvs 936: if (Timers == NULL || libwww_timer == NULL) 1.58 cvs 937: return; 938: 939: /* find the id */ 940: last = cur = Timers; 941: while ((me = (AmayaTimer * ) HTList_nextObject (cur))) 942: { 1.59 cvs 943: if (me->libwww_timer == libwww_timer) 1.58 cvs 944: break; 945: last = cur; 946: } 947: 948: if (me) 949: { 950: /* remove the Xt timer */ 951: XtRemoveTimeOut (me->xt_timer); 952: /* and the element from the list */ 1.65 cvs 953: HTList_removeObject (Timers, me); 1.58 cvs 954: TtaFreeMemory (me); 955: } 1.31 cvs 956: } 1.68 cvs 957: #endif /* _GTK */ 1.58 cvs 958: 1.32 cvs 959: #endif /* !_WINDOWS */