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