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: */ 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 15: * 16: */ 1.4 cvs 17: 1.16 ! cvs 18: #define THOT_EXPORT extern 1.4 cvs 19: #include "amaya.h" 1.10 cvs 20: #include "AHTBridge_f.h" 21: #include "AHTFWrite_f.h" 22: #include "query_f.h" 23: #include "answer_f.h" 1.4 cvs 24: 25: #ifdef WWW_XWINDOWS 26: /* Amaya's X appcontext */ 1.16 ! cvs 27: extern ThotAppContext app_cont; 1.4 cvs 28: #endif 29: 30: 31: #ifndef HACK_WWW 1.10 cvs 32: extern HTEventCallback *HTEvent_Retrieve (SOCKET, SockOps, HTRequest ** arp); 1.4 cvs 33: #endif 34: 35: /* 1.7 cvs 36: * Private functions 37: */ 1.4 cvs 38: #ifdef __STDC__ 1.7 cvs 39: static void RequestKillReadXtevent (AHTReqContext *); 40: static void RequestKillWriteXtevent (AHTReqContext *); 41: static void RequestKillExceptXtevent (AHTReqContext *); 42: 1.4 cvs 43: #else 1.7 cvs 44: static void RequestKillReadXtevent (); 45: static void RequestKillWriteXtevent (); 46: static void RequestKillExceptXtevent (); 47: 48: #endif 1.4 cvs 49: 50: /* 51: * Private variables 52: */ 53: 54: /* 55: * this set of SockOps map our WinSock "socket event SockOps" into 56: * our read and write sets. Note that under the canonical Unix model, 57: * a non-blocking socket passed to an accept() call will appear as readable, 58: * whilst a non-blocking call to connect() will appear as writeable. In add. 59: * if the connection has been closed, the socket will appear readable under 60: * BSD Unix semantics 61: */ 1.10 cvs 62: static const SockOps ReadBits = FD_READ | FD_ACCEPT | FD_CLOSE; 63: static const SockOps WriteBits = FD_WRITE | FD_CONNECT; 64: static const SockOps ExceptBits = FD_OOB; 1.4 cvs 65: 66: /* 67: * Private functions 68: */ 69: 1.10 cvs 70: /*-------------------------------------------------------------------- 71: AHTCallback_bridge 1.11 cvs 72: this function acts as a bridge between Xt and libwww. From the Xt 73: point of view, this function is the callback handler whenever there's 74: any activity on the sockets associated with the active requests. From 75: the libwww point of view, this is the function that takes the initiative 76: to invoke the callback function associated with an active request, 77: whenever there's an activity in the socket associated to it. 78: In this latter aspect, this function is similar to the library's 79: own __DoCallback() function. 80: Upon activation, the function looks up the request associated with the 81: active socket and then looks up the cbf associated with that request. 82: Upon completion of the execution of the request's cbf, it verifies 83: the state of the request and, if it's an asynchronous request, deletes 84: the memory allocated to it. 1.10 cvs 85: -------------------------------------------------------------------*/ 1.4 cvs 86: 87: #ifdef __STDC__ 1.12 cvs 88: void *AHTCallback_bridge (caddr_t cd, int *s, XtInputId * id) 1.7 cvs 89: #else 1.12 cvs 90: void *AHTCallback_bridge (cd, s, id) 1.7 cvs 91: caddr_t cd; 92: int *s; 93: XtInputId *id; 1.4 cvs 94: #endif /* __STDC__ */ 95: { 1.11 cvs 96: int status; /* the status result of the libwwww call */ 1.7 cvs 97: HTRequest *rqp = NULL; 98: AHTReqContext *me; 1.11 cvs 99: SockOps ops; 1.4 cvs 100: 1.10 cvs 101: /* Libwww 5.0a does not take into account the ops parameter 1.11 cvs 102: in the invocation of for this function call */ 1.4 cvs 103: 104: #ifdef HACK_WWW 1.7 cvs 105: HTEventCallback *cbf; 106: 1.4 cvs 107: #else 1.13 cvs 108: HTEventCallback *cbf; 1.7 cvs 109: 1.13 cvs 110: ops = FD_WRITE; 111: cbf = (HTEventCallback *) __RetrieveCBF (*s, ops, &rqp); 1.4 cvs 112: #endif 1.13 cvs 113: 1.7 cvs 114: me = HTRequest_context (rqp); 115: if (THD_TRACE) 1.10 cvs 116: fprintf (stderr, "AHTBridge: Processing url %s \n", me->urlName); 1.4 cvs 117: 118: 119: #ifdef WWW_XWINDOWS 1.7 cvs 120: switch ((XtInputId) cd) 121: { 122: case XtInputWriteMask: 123: ops = me->write_ops; 124: ops = FD_WRITE; 125: break; 126: case XtInputExceptMask: 127: ops = me->except_ops; 128: ops = FD_OOB; 129: break; 1.11 cvs 130: default: 131: case XtInputReadMask: 132: ops = me->read_ops; 133: ops = FD_READ; 134: break; 1.7 cvs 135: } /* switch */ 136: #endif /* WWW_XWINDOWS */ 137: 1.11 cvs 138: /* verify if there's any callback associated with the request */ 1.7 cvs 139: if (!cbf || !rqp || rqp->priority == HT_PRIORITY_OFF) 140: { 1.4 cvs 141: if (THD_TRACE) 1.7 cvs 142: HTTrace ("Callback.... No callback found\n"); 1.4 cvs 143: /* put some more code to correctly destroy this request */ 144: return (0); 1.7 cvs 145: } 146: 1.11 cvs 147: /* Invokes the callback associated to the requests */ 148: 149: /* first we change the status of the request, to say it 150: has entered a critical section */ 1.15 cvs 151: 152: if((HTRequest_outputStream(me->request) == (HTStream *) NULL)) 153: fprintf(stderr,"\n **ERROR** opening %s\n\n",me->urlName); 154: 1.11 cvs 155: me->reqStatus = HT_BUSY; 156: if ((status = (*cbf) (*s, rqp, ops)) != HT_OK) 157: HTTrace ("Callback.... received != HT_OK"); 1.4 cvs 158: 1.7 cvs 159: /* Several states can happen after this callback. They 160: * are indicated by the me->reqStatus structure member and 161: * the fds external variables. The following lines examine 162: * the states and correspondly update the Xt event register 163: * 164: * Regarding the me->reqStatus member, we have the following 165: * possible states: 166: * 167: * HT_BUSY: Request has blocked 168: * HT_WAITING: Request has been reissued 169: * HT_ABORT: Request has been stopped 170: * HT_END: Request has ended 171: */ 172: 173: #ifdef WWW_XWINDOWS 174: if (me->reqStatus == HT_ABORT) 1.11 cvs 175: /* Has the user stopped the request? */ 1.7 cvs 176: { 1.4 cvs 177: me->reqStatus = HT_WAITING; 178: StopRequest (me->docid); 1.7 cvs 179: if (THD_TRACE) 1.11 cvs 180: fprintf (stderr, "(BF) removing Xtinput %lu !RWE (Stop buttonl), sock %d\n", me->read_xtinput_id, *s); 1.7 cvs 181: return (0); 182: } 183: #endif /* WWW_XWINDOWS */ 184: 1.11 cvs 185: if (me->reqStatus == HT_WAITING) 1.7 cvs 186: /* the request is being reissued */ 187: { 188: /* 189: * (1) The old request has ended and the library 190: * assigned the old socket number to a pending 191: * request. 192: * 193: * (2) The request has been reissued after an 194: * authentication or redirection directive and 195: * we are using the same old socket number. 196: */ 1.11 cvs 197: 198: if (THD_TRACE) 199: fprintf (stderr, "*** detected a reissue of request \n"); 200: return (0); 1.7 cvs 201: } 1.4 cvs 202: 1.11 cvs 203: /* we verify if the request exists. If it has ended, we will have 204: a reqStatus with an HT_END value */ 1.7 cvs 205: 206: if ((me->request->net == (HTNet *) NULL) || (me->reqStatus == HT_END || me->reqStatus == HT_ERR)) 1.11 cvs 207: /* request has ended */ 1.7 cvs 208: { 1.4 cvs 209: #ifdef WWW_XWINDOWS 1.7 cvs 210: if (THD_TRACE) 1.11 cvs 211: fprintf (stderr, "(BF) removing Xtinput %lu !RWE, sock %d (Request has ended)\n", *id, *s); 1.4 cvs 212: #endif 1.7 cvs 213: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC)) 1.11 cvs 214: /* free the memory allocated for async requests */ 1.7 cvs 215: { 216: AHTPrintPendingRequestStatus (me->docid, YES); 217: AHTReqContext_delete (me); 218: } 219: else if (me->reqStatus != HT_END && HTError_hasSeverity (HTRequest_error (me->request), ERR_NON_FATAL)) 1.11 cvs 220: /* did the SYNC request end because of an error? If yes, report it back to the caller */ 1.4 cvs 221: me->reqStatus = HT_ERR; 1.7 cvs 222: return (0); 223: } 1.11 cvs 224: 225: /* The request is still alive, so change it's status to indicate it's out of the 226: critical section */ 1.7 cvs 227: me->reqStatus = HT_WAITING; 228: return (0); 1.4 cvs 229: } 230: 231: 1.10 cvs 232: /*---------------------------------------------------------------- 233: Add_NewSocket_to_Loop 1.11 cvs 234: when there are more open requests than available sockets, the 235: requests are put in a "pending state." When a socket becomes 236: available, libwww associates it with a pending request and then 237: calls this callback function. This function is responsible for 238: opening the temporary file where the GET and POST results 239: will be stored. The function is also responsible for 240: registering the socket with the Xt event loop. 241: Consult the libwww manual for more details on the signature 242: of this function. 1.10 cvs 243: ----------------------------------------------------------------*/ 1.4 cvs 244: #ifdef __STDC__ 1.7 cvs 245: int Add_NewSocket_to_Loop (HTRequest * request, HTAlertOpcode op, int msgnum, const char *dfault, void *input, HTAlertPar * reply) 1.4 cvs 246: #else 1.7 cvs 247: int Add_NewSocket_to_Loop (request, op, msgnum, dfault, input, reply) 248: HTRequest *request; 249: HTAlertOpcode op; 250: int msgnum; 251: const char *dfault; 252: void *input; 253: HTAlertPar *reply; 254: 255: #endif /* __STDC__ */ 1.4 cvs 256: { 1.7 cvs 257: AHTReqContext *me = HTRequest_context (request); 1.4 cvs 258: 1.15 cvs 259: if (me->reqStatus == HT_BUSY) 260: /* request was aborted and now is is being reissued */ 1.7 cvs 261: { 1.15 cvs 262: rewind (me->output); 263: HTRequest_setOutputStream (me->request, AHTFWriter_new (me->request, me->output, YES)); 264: } else if (me->reqStatus == HT_NEW_PENDING) 265: { 266: /* we are dequeing a pending request */ 267: if (me->outputfile && (me->output = fopen (me->outputfile, "w")) == NULL) 268: { 269: /* the request is associated with a file */ 1.7 cvs 270: me->outputfile[0] = '\0'; /* file could not be opened */ 271: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE), 272: me->outputfile); 273: me->reqStatus = HT_ERR; 274: return (HT_ERROR); 1.15 cvs 275: } 276: if (THD_TRACE) 1.7 cvs 277: fprintf (stderr, "Add_NewSocket_to_Loop: Activating pending %s . Open fd %d\n", me->urlName, (int) me->output); 1.15 cvs 278: HTRequest_setOutputStream (me->request, 279: AHTFWriter_new (me->request, me->output, YES)); 280: } 1.4 cvs 281: 1.11 cvs 282: /*change the status of the request */ 1.7 cvs 283: me->reqStatus = HT_WAITING; 1.4 cvs 284: 1.7 cvs 285: if (THD_TRACE) 1.15 cvs 286: fprintf (stderr, "(Activating a pending request\n"); 1.4 cvs 287: 1.7 cvs 288: return (HT_OK); 1.4 cvs 289: } 290: 291: 1.11 cvs 292: /*---------------------------------------------------------------------- 293: AHTEvent_register 294: callback called by libwww whenever a socket is open and associated 295: to a request. It sets the pertinent Xt events so that the Xt Event 296: loops gets an interruption whenever there's action of the socket. 297: In addition, it registers the request with libwww. 298: ----------------------------------------------------------------------*/ 1.4 cvs 299: #ifdef __STDC__ 1.7 cvs 300: int AHTEvent_register (SOCKET sock, HTRequest * rqp, SockOps ops, HTEventCallback * cbf, HTPriority p) 1.4 cvs 301: #else 1.7 cvs 302: int AHTEvent_register (sock, rqp, ops, cbf, p) 303: SOCKET sock; 304: HTRequest *rqp; 305: SockOps ops; 306: HTEventCallback *cbf; 307: HTPriority p; 308: 309: #endif /* __STDC__ */ 1.4 cvs 310: { 1.11 cvs 311: AHTReqContext *me; /* current request */ 312: int status; /* libwww status associated with the socket number */ 1.7 cvs 313: 314: if (sock == INVSOC) 1.4 cvs 315: return (0); 316: 1.7 cvs 317: /* get the request associated to the socket number */ 318: 319: if ((status = HTEventrg_register (sock, rqp, ops, 320: cbf, p)) != HT_OK) 1.4 cvs 321: return (status); 322: 1.7 cvs 323: if (rqp) 324: { 325: me = HTRequest_context (rqp); 1.4 cvs 326: 1.7 cvs 327: /* verify if we need to open the fd */ 328: if (me->reqStatus == HT_NEW_PENDING) 329: { 330: /* we are opening a pending request */ 331: if ((me->output = fopen (me->outputfile, "w")) == NULL) 332: { 333: me->outputfile[0] = '\0'; /* file could not be opened */ 334: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE), 335: me->outputfile); 336: me->reqStatus = HT_ERR; 337: return (HT_ERROR); 338: } 339: HTRequest_setOutputStream (me->request, 340: AHTFWriter_new (me->request, me->output, YES)); 341: me->reqStatus = HT_WAITING; 342: 343: if (THD_TRACE) 344: fprintf (stderr, "AHTEvent_register: Activating pending request url %s, fd %d\n", me->urlName, (int) me->output); 345: } 1.4 cvs 346: 1.7 cvs 347: if (THD_TRACE) 348: fprintf (stderr, "AHTEvent_register: url %s, sock %d, ops %lu \n", 349: me->urlName, sock, ops); 1.4 cvs 350: 1.7 cvs 351: /* add the input */ 352: if (me->reqStatus == HT_NEW) 353: me->reqStatus = HT_WAITING; 354: 355: if (ops & ReadBits) 356: { 357: me->read_ops = ops; 358: 359: #ifdef WWW_XWINDOWS 360: if (me->read_xtinput_id) 361: XtRemoveInput (me->read_xtinput_id); 362: me->read_xtinput_id = 363: XtAppAddInput (app_cont, 364: sock, 365: (XtPointer) XtInputReadMask, 366: (XtInputCallbackProc) AHTCallback_bridge, 367: (XtPointer) XtInputReadMask); 368: if (THD_TRACE) 369: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d R\n", 370: me->read_xtinput_id, sock); 371: #endif /* WWW_XWINDOWS */ 372: } 373: 374: if (ops & WriteBits) 375: { 376: me->write_ops = ops; 377: #ifdef WWW_XWINDOWS 378: if (me->write_xtinput_id) 379: XtRemoveInput (me->write_xtinput_id); 380: me->write_xtinput_id = XtAppAddInput (app_cont, sock, 381: (XtPointer) XtInputWriteMask, 382: (XtInputCallbackProc) AHTCallback_bridge, 383: (XtPointer) XtInputWriteMask); 384: if (THD_TRACE) 385: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d W\n", 386: me->write_xtinput_id, sock); 387: #endif /* WWW_XWINDOWS */ 388: } 389: 390: if (ops & ExceptBits) 391: { 392: me->except_ops = ops; 393: #ifdef WWW_XWINDOWS 394: if (me->except_xtinput_id) 395: XtRemoveInput (me->except_xtinput_id); 396: 397: me->except_xtinput_id = XtAppAddInput (app_cont, sock, 398: (XtPointer) XtInputExceptMask, 399: (XtInputCallbackProc) AHTCallback_bridge, 400: (XtPointer) XtInputExceptMask); 401: if (THD_TRACE) 402: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d E\n", me->except_xtinput_id, sock); 1.4 cvs 403: #endif /* WWW_XWINDOWS */ 1.7 cvs 404: } 405: } 1.4 cvs 406: 1.7 cvs 407: return (status); 1.4 cvs 408: } 409: 1.11 cvs 410: 411: /*---------------------------------------------------------------------- 412: AHTEvent_unregister 413: callback called by libwww each time a request is unregistered. This 414: function takes care of unregistering the pertinent Xt events 415: associated with the request's socket. In addition, it unregisters 416: the request from libwww. 417: ----------------------------------------------------------------------*/ 1.4 cvs 418: #ifdef __STDC__ 1.7 cvs 419: int AHTEvent_unregister (SOCKET sock, SockOps ops) 1.4 cvs 420: #else 1.7 cvs 421: int AHTEvent_unregister (sock, ops) 422: SOCKET sock; 423: SockOps ops; 424: 425: #endif /* __STDC__ */ 1.4 cvs 426: { 1.7 cvs 427: int status; 428: 429: HTRequest *rqp = NULL; 430: AHTReqContext *me; 1.4 cvs 431: 1.11 cvs 432: /* Libwww 5.0a does not take into account the third parameter 1.7 cvs 433: ** for this function call */ 1.4 cvs 434: 1.7 cvs 435: HTEventCallback *cbf = (HTEventCallback *) __RetrieveCBF (sock, (SockOps) NULL, &rqp); 1.4 cvs 436: 1.8 cvs 437: #ifdef WWW_XWINDOWS 1.7 cvs 438: if (cbf) 439: { 440: if (rqp) 441: { 442: me = HTRequest_context (rqp); 443: 444: if (ops & ReadBits) 445: RequestKillReadXtevent (me); 1.4 cvs 446: 1.7 cvs 447: if (ops & WriteBits) 448: RequestKillWriteXtevent (me); 449: 450: if (ops & ExceptBits) 451: RequestKillExceptXtevent (me); 452: 453: 454: } 455: } 456: 457: status = HTEventrg_unregister (sock, ops); 1.8 cvs 458: #endif /* WWW_XWINDOWS */ 1.7 cvs 459: return (status); 1.4 cvs 460: } 461: 1.11 cvs 462: 463: /*---------------------------------------------------------------------- 464: RequestKillAllXtevents 465: front-end for kill all Xt events associated with the request pointed 466: to by "me". 467: ----------------------------------------------------------------------*/ 1.4 cvs 468: #ifdef __STDC__ 1.7 cvs 469: void RequestKillAllXtevents (AHTReqContext * me) 1.4 cvs 470: #else 1.7 cvs 471: void RequestKillAllXtevents (me) 472: AHTReqContext *me; 473: 474: #endif /* __STDC__ */ 1.4 cvs 475: { 476: #ifdef WWW_XWINDOWS 1.7 cvs 477: if (THD_TRACE) 478: fprintf (stderr, "Request_kill: Clearing Xtinputs\n"); 1.4 cvs 479: 1.7 cvs 480: RequestKillReadXtevent (me); 481: RequestKillWriteXtevent (me); 482: RequestKillExceptXtevent (me); 1.4 cvs 483: #endif /* WWW_XWINDOWS */ 484: } 485: 1.11 cvs 486: /*---------------------------------------------------------------------- 487: RequestKillReadXtevent 488: kills any read Xt event associated with the request pointed to by "me". 489: ----------------------------------------------------------------------*/ 1.4 cvs 490: #ifdef __STDC__ 1.7 cvs 491: static void RequestKillReadXtevent (AHTReqContext * me) 1.4 cvs 492: #else 1.7 cvs 493: static void RequestKillReadXtevent (me) 494: AHTReqContext *me; 495: 496: #endif /* __STDC__ */ 1.4 cvs 497: { 498: #ifdef WWW_XWINDOWS 1.7 cvs 499: if (me->read_xtinput_id) 500: { 501: if (THD_TRACE) 502: fprintf (stderr, "Request_kill: Clearing Read Xtinputs%lu\n", me->read_xtinput_id); 503: XtRemoveInput (me->read_xtinput_id); 504: me->read_xtinput_id = (XtInputId) NULL; 505: } 1.4 cvs 506: #endif /* WWW_XWINDOWS */ 507: } 508: 1.11 cvs 509: /*---------------------------------------------------------------------- 510: RequestKillWriteXtevent 511: kills any write Xt event associated with the request pointed to 512: by "me". 513: ----------------------------------------------------------------------*/ 1.4 cvs 514: #ifdef __STDC__ 1.7 cvs 515: static void RequestKillWriteXtevent (AHTReqContext * me) 1.4 cvs 516: #else 1.7 cvs 517: static void RequestKillWriteXtevent (me) 518: AHTReqContext *me; 519: 520: #endif /* __STDC__ */ 1.4 cvs 521: { 522: #ifdef WWW_XWINDOWS 1.7 cvs 523: if (me->write_xtinput_id) 524: { 525: if (THD_TRACE) 526: fprintf (stderr, "Request_kill: Clearing Write Xtinputs %lu\n", me->write_xtinput_id); 527: XtRemoveInput (me->write_xtinput_id); 528: me->write_xtinput_id = (XtInputId) NULL; 529: } 1.4 cvs 530: #endif /* WWW_XWINDOWS */ 531: } 532: 1.11 cvs 533: /*---------------------------------------------------------------------- 534: RequestKillExceptXtevent 535: kills any exception Xt event associated with the request pointed to 536: by "me". 537: ----------------------------------------------------------------------*/ 1.4 cvs 538: #ifdef __STDC__ 1.7 cvs 539: static void RequestKillExceptXtevent (AHTReqContext * me) 1.4 cvs 540: #else 1.7 cvs 541: static void RequestKillExceptXtevent (me) 542: AHTReqContext *me; 543: 544: #endif /* __STDC__ */ 1.4 cvs 545: { 546: #ifdef WWW_XWINDOWS 1.7 cvs 547: if (me->except_xtinput_id) 548: { 549: if (THD_TRACE) 550: fprintf (stderr, "Request_kill: Clearing Except Xtinputs %lu\n", me->except_xtinput_id); 551: XtRemoveInput (me->except_xtinput_id); 552: me->except_xtinput_id = (XtInputId) NULL; 553: } 1.4 cvs 554: #endif /* WWW_XWINDOWS */ 555: } 1.11 cvs 556: 557: /* 558: End of Module AHTBridge.c 559: */ 560: 561: 562: 563: 564: