Annotation of Amaya/amaya/AHTBridge.c, revision 1.14
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.10 cvs 18: #define 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 */
27: extern XtAppContext app_cont;
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 */
151: me->reqStatus = HT_BUSY;
152: if ((status = (*cbf) (*s, rqp, ops)) != HT_OK)
153: HTTrace ("Callback.... received != HT_OK");
1.4 cvs 154:
1.7 cvs 155: /* Several states can happen after this callback. They
156: * are indicated by the me->reqStatus structure member and
157: * the fds external variables. The following lines examine
158: * the states and correspondly update the Xt event register
159: *
160: * Regarding the me->reqStatus member, we have the following
161: * possible states:
162: *
163: * HT_BUSY: Request has blocked
164: * HT_WAITING: Request has been reissued
165: * HT_ABORT: Request has been stopped
166: * HT_END: Request has ended
167: */
168:
169: #ifdef WWW_XWINDOWS
170: if (me->reqStatus == HT_ABORT)
1.11 cvs 171: /* Has the user stopped the request? */
1.7 cvs 172: {
1.4 cvs 173: me->reqStatus = HT_WAITING;
174: StopRequest (me->docid);
1.7 cvs 175: if (THD_TRACE)
1.11 cvs 176: fprintf (stderr, "(BF) removing Xtinput %lu !RWE (Stop buttonl), sock %d\n", me->read_xtinput_id, *s);
1.7 cvs 177: return (0);
178: }
179: #endif /* WWW_XWINDOWS */
180:
1.11 cvs 181: if (me->reqStatus == HT_WAITING)
1.7 cvs 182: /* the request is being reissued */
183: {
184: /*
185: * (1) The old request has ended and the library
186: * assigned the old socket number to a pending
187: * request.
188: *
189: * (2) The request has been reissued after an
190: * authentication or redirection directive and
191: * we are using the same old socket number.
192: */
1.11 cvs 193:
194: if (THD_TRACE)
195: fprintf (stderr, "*** detected a reissue of request \n");
196: return (0);
1.7 cvs 197: }
1.4 cvs 198:
1.11 cvs 199: /* we verify if the request exists. If it has ended, we will have
200: a reqStatus with an HT_END value */
1.7 cvs 201:
202: if ((me->request->net == (HTNet *) NULL) || (me->reqStatus == HT_END || me->reqStatus == HT_ERR))
1.11 cvs 203: /* request has ended */
1.7 cvs 204: {
1.4 cvs 205: #ifdef WWW_XWINDOWS
1.7 cvs 206: if (THD_TRACE)
1.11 cvs 207: fprintf (stderr, "(BF) removing Xtinput %lu !RWE, sock %d (Request has ended)\n", *id, *s);
1.4 cvs 208: #endif
1.7 cvs 209: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC))
1.11 cvs 210: /* free the memory allocated for async requests */
1.7 cvs 211: {
212: AHTPrintPendingRequestStatus (me->docid, YES);
213: AHTReqContext_delete (me);
214: }
215: else if (me->reqStatus != HT_END && HTError_hasSeverity (HTRequest_error (me->request), ERR_NON_FATAL))
1.11 cvs 216: /* did the SYNC request end because of an error? If yes, report it back to the caller */
1.4 cvs 217: me->reqStatus = HT_ERR;
1.7 cvs 218: return (0);
219: }
1.11 cvs 220:
221: /* The request is still alive, so change it's status to indicate it's out of the
222: critical section */
1.7 cvs 223: me->reqStatus = HT_WAITING;
224: return (0);
1.4 cvs 225: }
226:
227:
1.10 cvs 228: /*----------------------------------------------------------------
229: Add_NewSocket_to_Loop
1.11 cvs 230: when there are more open requests than available sockets, the
231: requests are put in a "pending state." When a socket becomes
232: available, libwww associates it with a pending request and then
233: calls this callback function. This function is responsible for
234: opening the temporary file where the GET and POST results
235: will be stored. The function is also responsible for
236: registering the socket with the Xt event loop.
237: Consult the libwww manual for more details on the signature
238: of this function.
1.10 cvs 239: ----------------------------------------------------------------*/
1.4 cvs 240: #ifdef __STDC__
1.7 cvs 241: int Add_NewSocket_to_Loop (HTRequest * request, HTAlertOpcode op, int msgnum, const char *dfault, void *input, HTAlertPar * reply)
1.4 cvs 242: #else
1.7 cvs 243: int Add_NewSocket_to_Loop (request, op, msgnum, dfault, input, reply)
244: HTRequest *request;
245: HTAlertOpcode op;
246: int msgnum;
247: const char *dfault;
248: void *input;
249: HTAlertPar *reply;
250:
251: #endif /* __STDC__ */
1.4 cvs 252: {
1.7 cvs 253: AHTReqContext *me = HTRequest_context (request);
1.4 cvs 254:
1.7 cvs 255: if (me->reqStatus == HT_NEW_PENDING)
256: {
1.11 cvs 257: /* we are dequeing a pending request */
258: if (me->outputfile && (me->output = fopen (me->outputfile, "w")) == NULL)
1.7 cvs 259: {
1.11 cvs 260: /* the request is associated with a file */
1.7 cvs 261: me->outputfile[0] = '\0'; /* file could not be opened */
262: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
263: me->outputfile);
264: me->reqStatus = HT_ERR;
265: return (HT_ERROR);
266: }
267: if (THD_TRACE)
268: fprintf (stderr, "Add_NewSocket_to_Loop: Activating pending %s . Open fd %d\n", me->urlName, (int) me->output);
269: HTRequest_setOutputStream (me->request,
270: AHTFWriter_new (me->request, me->output, YES));
271: }
1.4 cvs 272:
1.11 cvs 273: /*change the status of the request */
1.7 cvs 274: me->reqStatus = HT_WAITING;
1.4 cvs 275:
1.7 cvs 276: if (THD_TRACE)
277: fprintf (stderr, "(Activating a pending request\n");
1.4 cvs 278:
1.7 cvs 279: return (HT_OK);
1.4 cvs 280: }
281:
282:
1.11 cvs 283: /*----------------------------------------------------------------------
284: AHTEvent_register
285: callback called by libwww whenever a socket is open and associated
286: to a request. It sets the pertinent Xt events so that the Xt Event
287: loops gets an interruption whenever there's action of the socket.
288: In addition, it registers the request with libwww.
289: ----------------------------------------------------------------------*/
1.4 cvs 290: #ifdef __STDC__
1.7 cvs 291: int AHTEvent_register (SOCKET sock, HTRequest * rqp, SockOps ops, HTEventCallback * cbf, HTPriority p)
1.4 cvs 292: #else
1.7 cvs 293: int AHTEvent_register (sock, rqp, ops, cbf, p)
294: SOCKET sock;
295: HTRequest *rqp;
296: SockOps ops;
297: HTEventCallback *cbf;
298: HTPriority p;
299:
300: #endif /* __STDC__ */
1.4 cvs 301: {
1.11 cvs 302: AHTReqContext *me; /* current request */
303: int status; /* libwww status associated with the socket number */
1.7 cvs 304:
305: if (sock == INVSOC)
1.4 cvs 306: return (0);
307:
1.7 cvs 308: /* get the request associated to the socket number */
309:
310: if ((status = HTEventrg_register (sock, rqp, ops,
311: cbf, p)) != HT_OK)
1.4 cvs 312: return (status);
313:
1.7 cvs 314: if (rqp)
315: {
316: me = HTRequest_context (rqp);
1.4 cvs 317:
1.7 cvs 318: /* verify if we need to open the fd */
319: if (me->reqStatus == HT_NEW_PENDING)
320: {
321: /* we are opening a pending request */
322: if ((me->output = fopen (me->outputfile, "w")) == NULL)
323: {
324: me->outputfile[0] = '\0'; /* file could not be opened */
325: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
326: me->outputfile);
327: me->reqStatus = HT_ERR;
328: return (HT_ERROR);
329: }
330: HTRequest_setOutputStream (me->request,
331: AHTFWriter_new (me->request, me->output, YES));
332: me->reqStatus = HT_WAITING;
333:
334: if (THD_TRACE)
335: fprintf (stderr, "AHTEvent_register: Activating pending request url %s, fd %d\n", me->urlName, (int) me->output);
336: }
1.4 cvs 337:
1.7 cvs 338: if (THD_TRACE)
339: fprintf (stderr, "AHTEvent_register: url %s, sock %d, ops %lu \n",
340: me->urlName, sock, ops);
1.4 cvs 341:
1.7 cvs 342: /* add the input */
343: if (me->reqStatus == HT_NEW)
344: me->reqStatus = HT_WAITING;
345:
346: if (ops & ReadBits)
347: {
348: me->read_ops = ops;
349:
350: #ifdef WWW_XWINDOWS
351: if (me->read_xtinput_id)
352: XtRemoveInput (me->read_xtinput_id);
353: me->read_xtinput_id =
354: XtAppAddInput (app_cont,
355: sock,
356: (XtPointer) XtInputReadMask,
357: (XtInputCallbackProc) AHTCallback_bridge,
358: (XtPointer) XtInputReadMask);
359: if (THD_TRACE)
360: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d R\n",
361: me->read_xtinput_id, sock);
362: #endif /* WWW_XWINDOWS */
363: }
364:
365: if (ops & WriteBits)
366: {
367: me->write_ops = ops;
368: #ifdef WWW_XWINDOWS
369: if (me->write_xtinput_id)
370: XtRemoveInput (me->write_xtinput_id);
371: me->write_xtinput_id = XtAppAddInput (app_cont, sock,
372: (XtPointer) XtInputWriteMask,
373: (XtInputCallbackProc) AHTCallback_bridge,
374: (XtPointer) XtInputWriteMask);
375: if (THD_TRACE)
376: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d W\n",
377: me->write_xtinput_id, sock);
378: #endif /* WWW_XWINDOWS */
379: }
380:
381: if (ops & ExceptBits)
382: {
383: me->except_ops = ops;
384: #ifdef WWW_XWINDOWS
385: if (me->except_xtinput_id)
386: XtRemoveInput (me->except_xtinput_id);
387:
388: me->except_xtinput_id = XtAppAddInput (app_cont, sock,
389: (XtPointer) XtInputExceptMask,
390: (XtInputCallbackProc) AHTCallback_bridge,
391: (XtPointer) XtInputExceptMask);
392: if (THD_TRACE)
393: fprintf (stderr, "(BT) adding Xtinput %lu Socket %d E\n", me->except_xtinput_id, sock);
1.4 cvs 394: #endif /* WWW_XWINDOWS */
1.7 cvs 395: }
396: }
1.4 cvs 397:
1.7 cvs 398: return (status);
1.4 cvs 399: }
400:
1.11 cvs 401:
402: /*----------------------------------------------------------------------
403: AHTEvent_unregister
404: callback called by libwww each time a request is unregistered. This
405: function takes care of unregistering the pertinent Xt events
406: associated with the request's socket. In addition, it unregisters
407: the request from libwww.
408: ----------------------------------------------------------------------*/
1.4 cvs 409: #ifdef __STDC__
1.7 cvs 410: int AHTEvent_unregister (SOCKET sock, SockOps ops)
1.4 cvs 411: #else
1.7 cvs 412: int AHTEvent_unregister (sock, ops)
413: SOCKET sock;
414: SockOps ops;
415:
416: #endif /* __STDC__ */
1.4 cvs 417: {
1.7 cvs 418: int status;
419:
420: HTRequest *rqp = NULL;
421: AHTReqContext *me;
1.4 cvs 422:
1.11 cvs 423: /* Libwww 5.0a does not take into account the third parameter
1.7 cvs 424: ** for this function call */
1.4 cvs 425:
1.7 cvs 426: HTEventCallback *cbf = (HTEventCallback *) __RetrieveCBF (sock, (SockOps) NULL, &rqp);
1.4 cvs 427:
1.8 cvs 428: #ifdef WWW_XWINDOWS
1.7 cvs 429: if (cbf)
430: {
431: if (rqp)
432: {
433: me = HTRequest_context (rqp);
434:
435: if (ops & ReadBits)
436: RequestKillReadXtevent (me);
1.4 cvs 437:
1.7 cvs 438: if (ops & WriteBits)
439: RequestKillWriteXtevent (me);
440:
441: if (ops & ExceptBits)
442: RequestKillExceptXtevent (me);
443:
444:
445: }
446: }
447:
448: status = HTEventrg_unregister (sock, ops);
1.8 cvs 449: #endif /* WWW_XWINDOWS */
1.7 cvs 450: return (status);
1.4 cvs 451: }
452:
1.11 cvs 453:
454: /*----------------------------------------------------------------------
455: RequestKillAllXtevents
456: front-end for kill all Xt events associated with the request pointed
457: to by "me".
458: ----------------------------------------------------------------------*/
1.4 cvs 459: #ifdef __STDC__
1.7 cvs 460: void RequestKillAllXtevents (AHTReqContext * me)
1.4 cvs 461: #else
1.7 cvs 462: void RequestKillAllXtevents (me)
463: AHTReqContext *me;
464:
465: #endif /* __STDC__ */
1.4 cvs 466: {
467: #ifdef WWW_XWINDOWS
1.7 cvs 468: if (THD_TRACE)
469: fprintf (stderr, "Request_kill: Clearing Xtinputs\n");
1.4 cvs 470:
1.7 cvs 471: RequestKillReadXtevent (me);
472: RequestKillWriteXtevent (me);
473: RequestKillExceptXtevent (me);
1.4 cvs 474: #endif /* WWW_XWINDOWS */
475: }
476:
1.11 cvs 477: /*----------------------------------------------------------------------
478: RequestKillReadXtevent
479: kills any read Xt event associated with the request pointed to by "me".
480: ----------------------------------------------------------------------*/
1.4 cvs 481: #ifdef __STDC__
1.7 cvs 482: static void RequestKillReadXtevent (AHTReqContext * me)
1.4 cvs 483: #else
1.7 cvs 484: static void RequestKillReadXtevent (me)
485: AHTReqContext *me;
486:
487: #endif /* __STDC__ */
1.4 cvs 488: {
489: #ifdef WWW_XWINDOWS
1.7 cvs 490: if (me->read_xtinput_id)
491: {
492: if (THD_TRACE)
493: fprintf (stderr, "Request_kill: Clearing Read Xtinputs%lu\n", me->read_xtinput_id);
494: XtRemoveInput (me->read_xtinput_id);
495: me->read_xtinput_id = (XtInputId) NULL;
496: }
1.4 cvs 497: #endif /* WWW_XWINDOWS */
498: }
499:
1.11 cvs 500: /*----------------------------------------------------------------------
501: RequestKillWriteXtevent
502: kills any write Xt event associated with the request pointed to
503: by "me".
504: ----------------------------------------------------------------------*/
1.4 cvs 505: #ifdef __STDC__
1.7 cvs 506: static void RequestKillWriteXtevent (AHTReqContext * me)
1.4 cvs 507: #else
1.7 cvs 508: static void RequestKillWriteXtevent (me)
509: AHTReqContext *me;
510:
511: #endif /* __STDC__ */
1.4 cvs 512: {
513: #ifdef WWW_XWINDOWS
1.7 cvs 514: if (me->write_xtinput_id)
515: {
516: if (THD_TRACE)
517: fprintf (stderr, "Request_kill: Clearing Write Xtinputs %lu\n", me->write_xtinput_id);
518: XtRemoveInput (me->write_xtinput_id);
519: me->write_xtinput_id = (XtInputId) NULL;
520: }
1.4 cvs 521: #endif /* WWW_XWINDOWS */
522: }
523:
1.11 cvs 524: /*----------------------------------------------------------------------
525: RequestKillExceptXtevent
526: kills any exception Xt event associated with the request pointed to
527: by "me".
528: ----------------------------------------------------------------------*/
1.4 cvs 529: #ifdef __STDC__
1.7 cvs 530: static void RequestKillExceptXtevent (AHTReqContext * me)
1.4 cvs 531: #else
1.7 cvs 532: static void RequestKillExceptXtevent (me)
533: AHTReqContext *me;
534:
535: #endif /* __STDC__ */
1.4 cvs 536: {
537: #ifdef WWW_XWINDOWS
1.7 cvs 538: if (me->except_xtinput_id)
539: {
540: if (THD_TRACE)
541: fprintf (stderr, "Request_kill: Clearing Except Xtinputs %lu\n", me->except_xtinput_id);
542: XtRemoveInput (me->except_xtinput_id);
543: me->except_xtinput_id = (XtInputId) NULL;
544: }
1.4 cvs 545: #endif /* WWW_XWINDOWS */
546: }
1.11 cvs 547:
548: /*
549: End of Module AHTBridge.c
550: */
551:
552:
553:
554:
555:
Webmaster