Annotation of Amaya/amaya/AHTBridge.c, revision 1.1.1.1
1.1 cvs 1: /* AHTBridge.c
2: * INTERFACE BRIDGE TO XT, LIBWWW, and AMAYA
3: *
4: * (c) COPYRIGHT
5: * Please first read the full copyright statement in the file COPYRIGH.
6: *
7: * This module implments the callback setup and handlers between
8: * the Xt, libwww, and Amaya procedures
9: *
10: * History:
11: * May 02 96 JK First semi-stable version, Jose Kahan
12: * June 01 96 JK First almost-complete version, Jose Kahan
13: */
14:
15: /* Unix/C/X */
16: #include "thot_gui.h"
17: #include "thot_sys.h"
18: #include "message.h"
19: #include "dialog.h"
20: #include "application.h"
21: #include "content.h"
22: #include "view.h"
23: #include "interface.h"
24: #include "amaya.h"
25:
26: #if 0
27: #include "AHTCommon.h"
28: #include "query.h"
29: #endif
30:
31: #include "AHTBridge.h" /* implemented here */
32:
33: #ifdef WWW_XWINDOWS
34: /* Amaya's X appcontext */
35: extern XtAppContext app_cont;
36: #endif
37:
38:
39: #ifndef HACK_WWW
40: extern PUBLIC HTEventCallback* HTEvent_Retrieve (SOCKET, SockOps, HTRequest** arp);
41: #endif
42:
43: /*
44: ** Private functions
45: */
46: #ifdef __STDC__
47: static void RequestKillReadXtevent (AHTReqContext*);
48: static void RequestKillWriteXtevent (AHTReqContext*);
49: static void RequestKillExceptXtevent (AHTReqContext*);
50: #else
51: static void RequestKillReadXtevent ();
52: static void RequestKillWriteXtevent ();
53: static void RequestKillExceptXtevent ();
54: #endif /*__STDC__*/
55:
56: /*
57: * Private variables
58: */
59:
60: /*
61: * this set of SockOps map our WinSock "socket event SockOps" into
62: * our read and write sets. Note that under the canonical Unix model,
63: * a non-blocking socket passed to an accept() call will appear as readable,
64: * whilst a non-blocking call to connect() will appear as writeable. In add.
65: * if the connection has been closed, the socket will appear readable under
66: * BSD Unix semantics
67: */
68: PRIVATE const SockOps ReadBits = FD_READ | FD_ACCEPT | FD_CLOSE;
69: PRIVATE const SockOps WriteBits = FD_WRITE | FD_CONNECT ;
70: PRIVATE const SockOps ExceptBits = FD_OOB ;
71:
72: /*
73: * Private functions
74: */
75:
76: /*
77: * Callback that acts as a bridge between X and wwwlib.
78: * This function is equivalent to the library's __DoCallback()
79: * function, but with a different API, to conform to Xt's event loop
80: * specifications. For more info, cf. the library's HTEvntrg.c module.
81: */
82:
83: #ifdef WWW_XWINDOWS
84: #ifdef __STDC__
85: XtInputCallbackProc AHTCallback_bridge (caddr_t cd, int* s, XtInputId* id)
86: #else
87: XtInputCallbackProc AHTCallback_bridge (cd, s, id)
88: caddr_t cd ;
89: int* s ;
90: XtInputId* id ;
91: #endif /* __STDC__ */
92:
93: #else /* WWW_XWINDOWS */
94: /* some winproc someday? */
95: LONG AHTCallback_bridge (caddr_t cd, int* s)
96: #endif /* !WWW_XWINDOWS */
97: {
98: int status;
99: HTRequest* rqp = NULL;
100: AHTReqContext* me;
101: SOCKET sock;
102: SockOps ops; /* what value goes here ? Ask eric */
103:
104: /* Libwww 4.1 does not take into account the third parameter
105: for this function call */
106:
107: #ifdef HACK_WWW
108: HTEventCallback* cbf;
109: #else
110: HTEventCallback* cbf = (HTEventCallback*) __RetrieveCBF(*s, ops, &rqp);
111: #endif
112: me = HTRequest_context (rqp);
113:
114: #if 0
115: switch ((XtInputId) cd) {
116: case XtInputReadMask:
117: ops = me->read_ops;
118: if (me->read_xtinput_id) {
119: XtRemoveInput (me->read_xtinput_id);
120: if (THD_TRACE)
121: fprintf (stderr, "(BT) removing Xtinput %lu R (AHTBridge before cbf), sock %d\n", me->read_xtinput_id, *s);
122: me->read_xtinput_id = 0;
123: }
124: break;
125: case XtInputWriteMask:
126: ops = me->write_ops;
127: if (me->write_xtinput_id) {
128: XtRemoveInput(me->write_xtinput_id);
129: if (THD_TRACE)
130: fprintf (stderr, "(BT) removing Xtinput %lu W (AHTBridge before cbf), sock %d\n", me->write_xtinput_id, *s);
131: me->write_xtinput_id = 0;
132: }
133: break;
134: case XtInputExceptMask:
135: ops = me->except_ops;
136: if (me->except_xtinput_id) {
137: XtRemoveInput (me->except_xtinput_id);
138: if (THD_TRACE)
139: fprintf(stderr, "(BT) removing Xtinput %lu E (AHTBridge before cbf), sock %d\n", me->except_xtinput_id, *s);
140: me->except_xtinput_id = 0;
141: }
142: break;
143: } /* switch */
144: #endif
145:
146: if (THD_TRACE)
147: fprintf (stderr, "AHTBridge: Processing url %s \n", me->urlName);
148:
149:
150: #ifdef WWW_XWINDOWS
151: switch ((XtInputId) cd) {
152: case XtInputReadMask:
153: ops = me->read_ops;
154: ops = FD_READ;
155: break;
156: case XtInputWriteMask:
157: ops = me->write_ops;
158: ops = FD_WRITE;
159: break;
160: case XtInputExceptMask:
161: ops = me->except_ops;
162: ops = FD_OOB;
163: break;
164: } /* switch */
165: #endif WWW_XWINDOWS
166:
167: /*
168: * Liberate the input, so that when a pending socket is activated,
169: * the socket status will be ... available
170: *
171: * verify if I can limit this to the unregister function
172: * does not look so
173: *
174: * although it makes no sense, callbacks can be null
175: */
176:
177: if (!cbf || !rqp || rqp->priority == HT_PRIORITY_OFF) {
178: if (THD_TRACE)
179: HTTrace("Callback.... No callback found\n");
180: /* put some more code to correctly destroy this request */
181: return (0);
182: }
183:
184: me->reqStatus = HT_BUSY;
185:
186: if ((status = (*cbf) (*s, rqp, ops)) != HT_OK)
187: HTTrace("Callback.... received != HT_OK");
188:
189: /* Several states can happen after this callback. They
190: * are indicated by the me->reqStatus structure member and
191: * the fds external variables. The following lines examine
192: * the states and correspondly update the Xt event register
193: *
194: * Regarding the me->reqStatus member, we have the following
195: * possible states:
196: *
197: * HT_BUSY: Request has blocked
198: * HT_WAITING: Request has been reissued
199: * HT_ABORT: Request has been stopped
200: * HT_END: Request has ended
201: */
202:
203: /* Has the request been stopped?
204: *
205: * we verify if the request exists. If it has ended, me will have
206: * a reqStatus with an HT_END value */
207:
208: /* Was the stop button pressed? */
209:
210: #ifdef WWW_XWINDOWS
211: if (me->reqStatus == HT_ABORT) {
212: me->reqStatus = HT_WAITING;
213: StopRequest (me->docid);
214: if (THD_TRACE)
215: fprintf(stderr, "(BF) removing Xtinput %lu !RWE (Stop buttonl), sock %d\n", me->read_xtinput_id, sock);
216: return(0);
217: }
218: #endif /* WWW_XWINDOWS */
219:
220: /* the request is being reissued */
221:
222: if (me->reqStatus == HT_WAITING) {
223: /*
224: * (1) The old request has ended and the library
225: * assigned the old socket number to a pending
226: * request.
227: *
228: * (2) The request has been reissued after an
229: * authentication or redirection directive and
230: * we are using the same old socket number.
231: */
232:
233: if (THD_TRACE)
234: fprintf(stderr, "*** detected a reissue of request \n");
235: return(0);
236: }
237:
238:
239: /* verify if the request is still alive !! */
240:
241: if ((me->request->net == (HTNet*) NULL) || (me->reqStatus == HT_END || me->reqStatus == HT_ERR)) {
242: /* the socket is now being used by a different request, so the request has ended */
243: #ifdef WWW_XWINDOWS
244: if (THD_TRACE)
245: fprintf(stderr, "(BF) removing Xtinput %lu !RWE, sock %d (Request has ended)\n", *id, *s);
246: #endif
247: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC)) {
248: AHTPrintPendingRequestStatus (me->docid, YES);
249: AHTReqContext_delete(me);
250: }
251: else
252: if (me->reqStatus != HT_END && HTError_hasSeverity(HTRequest_error(me->request), ERR_NON_FATAL))
253: me->reqStatus = HT_ERR;
254: return(0);
255: }
256: me->reqStatus = HT_WAITING;
257: return (0);
258: }
259:
260:
261: /*
262: * This function is called whenever a socket is available
263: * for a request. It the necessary events to the Xt
264: * A small interface to the HTLoadAnchor libwww function.
265: * It prepares Xt to handle the asynchronous data requests.
266: */
267:
268: #ifdef __STDC__
269: int Add_NewSocket_to_Loop (HTRequest* request, HTAlertOpcode op, int msgnum, const char* dfault, void* input, HTAlertPar* reply)
270: #else
271: int Add_NewSocket_to_Loop (request, op, msgnum, dfault, input, reply)
272: HTRequest* request;
273: HTAlertOpcode op;
274: int msgnum;
275: const char* dfault;
276: void* input;
277: HTAlertPar* reply;
278: #endif /*__STDC__*/
279: {
280: SOCKET req_socket;
281: AHTReqContext* me = HTRequest_context (request);
282:
283: /* AmayaOpenRequests *reqState; */
284:
285: if(me->reqStatus == HT_NEW_PENDING) {
286: /* we are opening a pending request */
287: if ((me->output = fopen (me->outputfile, "w")) == NULL) {
288: me->outputfile[0] = '\0'; /* file could not be opened */
289: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
290: me->outputfile);
291: me->reqStatus = HT_ERR;
292: return(HT_ERROR);
293: }
294: if (THD_TRACE)
295: fprintf(stderr, "Add_NewSocket_to_Loop: Activating pending %s . Open fd %d\n", me->urlName, (int) me->output);
296: HTRequest_setOutputStream (me->request,
297: AHTFWriter_new (me->request, me->output, YES));
298: }
299:
300: me->reqStatus = HT_WAITING;
301:
302: if (THD_TRACE)
303: fprintf(stderr, "(Activating a pending request\n");
304:
305: /* reusing this function to save on file descriptors */
306:
307:
308: return (HT_OK);
309:
310: /***
311: if(me->method == METHOD_PUT || me->method == METHOD_POST)
312: return (HT_OK);
313: ***/
314:
315: /* get the socket number associated to the request */
316:
317: req_socket = HTNet_socket(request->net);
318:
319: if (req_socket == INVSOC) {
320: /* this should never be true */
321: return (HT_ERROR);
322: }
323:
324: /* add the input */
325:
326: #ifdef WWW_XWINDOWS
327: me->write_xtinput_id =
328: XtAppAddInput (app_cont,req_socket, (XtPointer) XtInputWriteMask,
329: (XtInputCallbackProc) AHTCallback_bridge, NULL);
330: if (THD_TRACE)
331: fprintf(stderr, "(BT) adding Xtinput %lu Socket %d W \n", me->write_xtinput_id, req_socket);
332:
333: if (me->write_xtinput_id == (XtInputId) NULL) {
334: TtaSetStatus(me->docid, 1, TtaGetMessage(AMAYA, AM_XT_ERROR), me->urlName);
335:
336: /* I still need to add some error treatment here, to liberate memory */
337: return (HT_ERROR);
338: }
339:
340: #endif /* WWW_XWINDOWS */
341: /* To speed up the stop performances, we move the active requests to the top of the Amaya list */
342:
343: /*
344: reqState = DocRequestState(Amaya->open_requests, me->docid);
345:
346: if(reqState->counter > 1) {
347: HTList_removeObject (Amaya->reqlist, (void *) me);
348: HTList_addObject (Amaya->reqlist, (void *) me);
349: }
350: */
351: return (HT_OK);
352: }
353:
354:
355: /*
356: * This function is called whenever a socket is available
357: * for a request. It the necessary events to the Xt
358: * A small interface to the HTLoadAnchor libwww function.
359: * It prepares Xt to handle the asynchronous data requests.
360: */
361:
362: #ifdef __STDC__
363: int AHTEvent_register(SOCKET sock, HTRequest* rqp, SockOps ops, HTEventCallback* cbf, HTPriority p)
364: #else
365: int AHTEvent_register(sock, rqp, ops, cbf, p)
366: SOCKET sock;
367: HTRequest* rqp;
368: SockOps ops;
369: HTEventCallback* cbf;
370: HTPriority p;
371: #endif /*__STDC__*/
372: {
373: AHTReqContext* me;
374: int status;
375:
376: if (sock == INVSOC)
377: return (0);
378:
379: /* get the request associated to the socket number */
380:
381: if((status = HTEventrg_register (sock, rqp, ops,
382: cbf,p )) != HT_OK )
383: return (status);
384:
385: if(rqp) {
386:
387: me = HTRequest_context(rqp);
388:
389: /* verify if we need to open the fd */
390:
391: if(me->reqStatus == HT_NEW_PENDING) {
392: /* we are opening a pending request */
393: if ((me->output = fopen (me->outputfile, "w")) == NULL) {
394: me->outputfile[0] = '\0'; /* file could not be opened */
395: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
396: me->outputfile);
397: me->reqStatus = HT_ERR;
398: return(HT_ERROR);
399: }
400: HTRequest_setOutputStream (me->request,
401: AHTFWriter_new (me->request, me->output, YES));
402: me->reqStatus = HT_WAITING;
403:
404: if (THD_TRACE)
405: fprintf(stderr,"AHTEvent_register: Activating pending request url %s, fd %d\n", me->urlName, (int) me->output);
406: }
407:
408: if (THD_TRACE)
409: fprintf(stderr,"AHTEvent_register: url %s, sock %d, ops %lu \n",
410: me->urlName, sock, ops);
411:
412: /* add the input */
413: if(me->reqStatus == HT_NEW)
414: me->reqStatus = HT_WAITING;
415:
416: if (ops & ReadBits) {
417: me->read_ops = ops;
418:
419: #ifdef WWW_XWINDOWS
420: if(me->read_xtinput_id)
421: XtRemoveInput(me->read_xtinput_id);
422: me->read_xtinput_id =
423: XtAppAddInput(app_cont,
424: sock,
425: (XtPointer) XtInputReadMask,
426: (XtInputCallbackProc) AHTCallback_bridge,
427: (XtPointer) XtInputReadMask);
428: if (THD_TRACE)
429: fprintf(stderr, "(BT) adding Xtinput %lu Socket %d R\n",
430: me->read_xtinput_id, sock);
431: #endif /* WWW_XWINDOWS */
432: }
433:
434: if(ops & WriteBits) {
435: me->write_ops= ops;
436: #ifdef WWW_XWINDOWS
437: if (me->write_xtinput_id)
438: XtRemoveInput(me->write_xtinput_id);
439: me->write_xtinput_id = XtAppAddInput (app_cont, sock,
440: (XtPointer) XtInputWriteMask,
441: (XtInputCallbackProc) AHTCallback_bridge,
442: (XtPointer) XtInputWriteMask);
443: if (THD_TRACE)
444: fprintf(stderr, "(BT) adding Xtinput %lu Socket %d W\n",
445: me->write_xtinput_id, sock);
446: #endif /* WWW_XWINDOWS */
447: }
448:
449: if (ops & ExceptBits) {
450: me->except_ops = ops;
451: #ifdef WWW_XWINDOWS
452: if (me->except_xtinput_id)
453: XtRemoveInput(me->except_xtinput_id);
454:
455: me->except_xtinput_id = XtAppAddInput (app_cont, sock,
456: (XtPointer) XtInputExceptMask,
457: (XtInputCallbackProc) AHTCallback_bridge,
458: (XtPointer) XtInputExceptMask);
459: if (THD_TRACE)
460: fprintf(stderr, "(BT) adding Xtinput %lu Socket %d E\n", me->except_xtinput_id, sock);
461: #endif /* WWW_XWINDOWS */
462: }
463: }
464:
465:
466:
467: #if 0
468: if (me->xtinput_id == (XtInputId) NULL) {
469: TtaSetStatus(me->docid, 1, TtaGetMessage(AMAYA, AM_XT_ERROR), me->urlName);
470:
471: /* I still need to add some error treatment here, to liberate memory */
472: return (HT_ERROR);
473: }
474:
475: #endif
476:
477: return (status);
478: }
479:
480: #ifdef __STDC__
481: int AHTEvent_unregister (SOCKET sock, SockOps ops)
482: #else
483: int AHTEvent_unregister (sock, ops)
484: SOCKET sock;
485: SockOps ops;
486: #endif /*__STDC__*/
487: {
488: int status;
489:
490: HTRequest* rqp = NULL;
491: AHTReqContext* me;
492:
493: /* Libwww 4.1 does not take into account the third parameter
494: ** for this function call */
495:
496: HTEventCallback* cbf = (HTEventCallback*) __RetrieveCBF(sock, (SockOps) NULL, &rqp);
497:
498: if (cbf) {
499: #ifdef WWW_XWINDOWS
500: if(rqp) {
501: me = HTRequest_context(rqp);
502:
503: if(ops & ReadBits)
504: RequestKillReadXtevent (me);
505:
506: if(ops & WriteBits)
507: RequestKillWriteXtevent (me);
508:
509: if(ops & ExceptBits)
510: RequestKillExceptXtevent (me);
511:
512: #endif /* WWW_XWINDOWS */
513:
514: }
515: }
516:
517: status = HTEventrg_unregister(sock, ops);
518: return(status);
519: }
520:
521: #ifdef __STDC__
522: void RequestKillAllXtevents (AHTReqContext* me)
523: #else
524: void RequestKillAllXtevents (me)
525: AHTReqContext* me;
526: #endif /*__STDC__*/
527: {
528: #ifdef WWW_XWINDOWS
529: if (THD_TRACE)
530: fprintf(stderr, "Request_kill: Clearing Xtinputs\n");
531:
532: RequestKillReadXtevent (me);
533: RequestKillWriteXtevent (me);
534: RequestKillExceptXtevent (me);
535: #endif /* WWW_XWINDOWS */
536: }
537:
538: #ifdef __STDC__
539: static void RequestKillReadXtevent (AHTReqContext* me)
540: #else
541: static void RequestKillReadXtevent (me)
542: AHTReqContext* me;
543: #endif /*__STDC__*/
544: {
545: #ifdef WWW_XWINDOWS
546: if (me->read_xtinput_id) {
547: if (THD_TRACE)
548: fprintf (stderr, "Request_kill: Clearing Read Xtinputs%lu\n", me->read_xtinput_id);
549: XtRemoveInput (me->read_xtinput_id);
550: me->read_xtinput_id = (XtInputId) NULL;
551: }
552: #endif /* WWW_XWINDOWS */
553: }
554:
555: #ifdef __STDC__
556: static void RequestKillWriteXtevent (AHTReqContext* me)
557: #else
558: static void RequestKillWriteXtevent (me)
559: AHTReqContext* me;
560: #endif /*__STDC__*/
561: {
562: #ifdef WWW_XWINDOWS
563: if (me->write_xtinput_id) {
564: if (THD_TRACE)
565: fprintf(stderr, "Request_kill: Clearing Write Xtinputs %lu\n", me->write_xtinput_id);
566: XtRemoveInput(me->write_xtinput_id);
567: me->write_xtinput_id = (XtInputId) NULL;
568: }
569: #endif /* WWW_XWINDOWS */
570: }
571:
572: #ifdef __STDC__
573: static void RequestKillExceptXtevent (AHTReqContext* me)
574: #else
575: static void RequestKillExceptXtevent (me)
576: AHTReqContext* me;
577: #endif /*__STDC__*/
578: {
579: #ifdef WWW_XWINDOWS
580: if (me->except_xtinput_id) {
581: if (THD_TRACE)
582: fprintf (stderr, "Request_kill: Clearing Except Xtinputs %lu\n", me->except_xtinput_id);
583: XtRemoveInput (me->except_xtinput_id);
584: me->except_xtinput_id = (XtInputId) NULL;
585: }
586: #endif /* WWW_XWINDOWS */
587: }
588:
589:
590:
591:
592:
593:
Webmaster