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