landsystem6.c

Go to the documentation of this file.
00001 
00002 /*  $Id: landsystem6.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "landinternal.h"
00029 #include "landtransport.h"
00030 
00031 
00032 
00033 typedef struct tysys6transportinfo { 
00034     
00035     short sys6processid; /*process id of message receiver*/
00036     } tysys6transportinfo, *ptrsys6transportinfo, **hdlsys6transportinfo;
00037     
00038     
00039 #define mostrecentversionnumber 1
00040 
00041 
00042 typedef struct tymessageheader { /*one of these at the head of each sys6 message*/
00043     
00044     short versionnumber; /*makes it easy to upgrade the message format*/
00045     
00046     tyverbclass verbclass; /*4-byte class of verb, thank you very much Apple*/
00047     
00048     tyverbtoken verbtoken; /*4-byte name of verb, thank you Apple*/
00049     
00050     tyapplicationid idsender; /*tells message receiver who to send value to*/
00051     
00052     short ctparams; /*the number of parameters in this verb*/
00053     } tymessageheader, *ptrmessageheader, **hdlmessageheader;
00054     
00055     
00056 
00057 
00058 static boolean landsystem6packparam (typaramrecord param, Handle hpacked) {
00059     
00060     /*
00061     push the verb parameter at the end of the packed handle.
00062     
00063     we split the world into two cases -- scalars and non-scalars.  for scalars,
00064     just push the verbparam record.  for non-scalars, change the val field of
00065     the verbparam to store the length of the value, which is pushed at the end
00066     of the handle following the verbparam record.
00067     
00068     we noticed that all non-scalar value types currently supported (10/22/90 DW) 
00069     are simple handles, with no handles dangling from their records.  we exploit
00070     this fact -- if it's not a scalar, we just size the handle, store the length
00071     and push the handle contents.  if at some time we have more complex value
00072     structures, this routine will get more complex.
00073     */
00074     
00075     register Handle hdata;
00076     register boolean fl;
00077     
00078     if (landscalartype (param.type)) { /*scalars are very easy to handle*/
00079         
00080         return (landenlargehandle (hpacked, longsizeof (typaramrecord), &param));
00081         }
00082         
00083     /*assume that the value field points to an already-packed handle*/
00084     
00085     hdata = param.val.binaryvalue; /*copy the handle into a register*/
00086     
00087     param.val.longvalue = landgethandlesize (hdata); /*set size*/
00088     
00089     if (!landenlargehandle (hpacked, longsizeof (typaramrecord), &param))
00090         return (false);
00091         
00092     landlockhandle (hdata);
00093     
00094     fl = landenlargehandle (hpacked, param.val.longvalue, *hdata);
00095     
00096     landunlockhandle (hdata);
00097     
00098     return (fl);
00099     } /*landsystem6packparam*/
00100     
00101     
00102 static boolean landsystem6unpackparam (Handle hpacked, long *ix, typaramrecord *param) {
00103     
00104     /*
00105     unpack the parameter from offset indicated by ix, if it's a scalar we're done,
00106     if it's heap-allocated there's more work to do.  see comment at head of the
00107     packing routine.
00108     */
00109     
00110     typaramrecord info;
00111     register long ctbytes;
00112     Handle hdata;
00113     
00114     if (!landloadfromhandle (hpacked, ix, longsizeof (info), &info))
00115         return (false);
00116         
00117     if (landscalartype (info.type)) { /*scalars are very easy to handle*/
00118     
00119         *param = info; /*copy into returned record*/
00120         
00121         return (true);
00122         }
00123     
00124     ctbytes = info.val.longvalue;
00125     
00126     if (!landloadfromhandletohandle (hpacked, ix, ctbytes, &hdata))
00127         return (false);
00128         
00129     info.val.binaryvalue = hdata; /*copy handle into value, works for all types*/
00130     
00131     *param = info; /*copy into returned record*/
00132     
00133     return (true);
00134     } /*landsystem6unpackparam*/
00135     
00136     
00137 static boolean landsystem6packallparams (hdlverbrecord hverb, Handle hpacked) {
00138     
00139     register hdlverbrecord hv = hverb;
00140     register short ct = (**hv).nextparam;
00141     register short i;
00142     
00143     for (i = 0; i < ct; i++) {
00144         
00145         if (!landsystem6packparam ((**hv).params [i], hpacked)) 
00146             return (false);
00147         } /*for*/
00148         
00149     return (true);
00150     } /*landsystem6packallparams*/
00151 
00152 
00153 static boolean landsystem6packverb (hdlverbrecord hverb, Handle *hpacked) {
00154     
00155     /*
00156     pack up all the information in the verb record into a single contiguous
00157     hunk of memory, suitable for transportation.
00158     
00159     10/31/90 DW: the number of parameters linked into the verb isn't ctparams,
00160     that's just the amount of space allocated in verbrecord for params.  the
00161     logical number of params (as opposed to physical) is the value of nextparam,
00162     since the array is 0-based and a count is 1-based.
00163     */
00164     
00165     register hdlverbrecord hv = hverb;
00166     register Handle h;
00167     tymessageheader header;
00168     
00169     header.versionnumber = mostrecentversionnumber;
00170     
00171     header.verbclass = (**hv).verbclass;
00172     
00173     header.verbtoken = (**hv).verbtoken;
00174     
00175     header.idsender = (**hv).idsender;
00176     
00177     header.ctparams = (**hv).nextparam;
00178     
00179     *hpacked = nil; /*default return value*/
00180     
00181     if (!landnewfilledhandle (&header, longsizeof (header), hpacked))
00182         return (false);
00183     
00184     h = *hpacked; /*copy into register*/
00185     
00186     if (!landsystem6packallparams (hv, h)) {
00187         
00188         landdisposehandle (h);
00189         
00190         *hpacked = nil;
00191         
00192         return (false);     
00193         }
00194         
00195     return (true);
00196     } /*landsystem6packverb*/
00197     
00198     
00199 static boolean landsystem6unpackverb (Handle hpacked, hdlverbrecord *hverb) {
00200     
00201     /*
00202     turn a packed handle, transported by our system 6 INIT, into a verb record
00203     which is almost operating-system-independent.
00204     
00205     we have a handle linked into the verb record, transportinfo, in which we
00206     record the process id of the message sender, so we know who to send the
00207     returned value to.
00208     */
00209     
00210     register hdlverbrecord hv;
00211     long ix = 0;
00212     tymessageheader header;
00213     register short i;
00214     
00215     if (!landloadfromhandle (hpacked, &ix, longsizeof (header), &header)) 
00216         return (false);
00217     
00218     if (!landnewverb (header.idsender, header.verbclass, header.verbtoken, header.ctparams, hverb))
00219         return (false);
00220     
00221     hv = *hverb; /*copy into register*/
00222     
00223     for (i = 0; i < header.ctparams; i++) {
00224         
00225         typaramrecord param;
00226         
00227         if (!landsystem6unpackparam (hpacked, &ix, &param))
00228             goto error;
00229             
00230         if (!landpushparamrecord (hv, param))
00231             goto error;
00232         } /*for*/
00233     
00234     return (true); /*loop completed, all params popped with no errors*/
00235     
00236     error:
00237     
00238     landdisposeverb (hv);
00239     
00240     return (false);
00241     } /*landsystem6unpackverb*/
00242 
00243 
00244 boolean landsystem6apprunning (tyapplicationid idapp) {
00245     
00246     /*
00247     under system 6, we consider a "running" app to be one that has 
00248     registered with the UserLand INIT.  note that landapprunning will, 
00249     in addition, try to send a special message to the app.
00250     */
00251     
00252     bigstring bs;
00253     short id;
00254     
00255     land4bytestostring (idapp, bs);
00256     
00257     return (ipcFind ((PIN *) bs, &id) == noErr);
00258     } /*landsystem6apprunning*/
00259     
00260     
00261 boolean landsystem6newverb (hdlverbrecord hverb) {
00262     
00263     register hdlverbrecord hv = hverb;
00264     register tyapplicationid idreceiver;
00265     hdlsys6transportinfo h;
00266     bigstring bs;
00267     short id;
00268     
00269     if (!landnewclearhandle (longsizeof (tysys6transportinfo), (Handle *) &h))
00270         return (false);
00271     
00272     idreceiver = (**hv).idreceiver; /*copy into register*/
00273     
00274     if (idreceiver == idnull) /*a message sent to no one*/
00275         id = -1;
00276         
00277     else {
00278         land4bytestostring (idreceiver, bs);
00279     
00280         if (ipcFind ((PIN *) bs, &id) != noErr) {
00281         
00282             landdisposehandle ((Handle) h);
00283             
00284             return (false);
00285             }
00286         }
00287         
00288     (**h).sys6processid = id;
00289     
00290     (**hv).transportinfo = (Handle) h;
00291     
00292     return (true);
00293     } /*landsystem6newverb*/
00294     
00295 
00296 
00297 boolean landsystem6send (hverb, hvalues) hdlverbrecord hverb, *hvalues; {
00298     
00299     /*
00300     by popular request -- a much richer version of verb sending.
00301     
00302     we send the verb as in the original version and wait for a returned 
00303     packet.  that reply can have lots of returned values, not just one as with 
00304     the original send.
00305     
00306     we push all those returned values onto a newly created verb record, and
00307     the you can call the usual parameter-getting routines to pull off the
00308     values you're interested in.
00309     
00310     11/6/90 dmb: support noreply mode
00311     
00312     1/1/90-3/x/90 mao: networking support and several other fixes (incl. queuing events)
00313     */
00314     
00315     register hdllandglobals hg = landgetglobals ();
00316     register hdlverbrecord hv = hverb;
00317     register short idsender, idreceiver;
00318     short idmessage;
00319     register boolean fl = true;
00320     Handle hpacked;
00321     long ix = 0;
00322 
00323     if (!landsystem6packverb (hv, &hpacked))
00324         return (false);
00325 
00326     idreceiver = (**(hdlsys6transportinfo) (**hv).transportinfo).sys6processid;
00327     
00328     idsender = (**hg).system6processid;
00329         
00330     fl = ipcSend (idsender, idreceiver, hpacked) == noErr;
00331     
00332     landdisposehandle (hpacked);
00333     
00334     if (!fl)
00335         return (false);
00336 
00337     while (true) { /*wait for returned value*/
00338         
00339         EventRecord ev;
00340         
00341         landsurrenderprocessor (&ev); /*give the other guy a chance to respond*/
00342         
00343         if (landbreakembrace (&ev)) /*user holding down cmd, option and shift keys*/
00344             return (false);
00345         
00346         ipcReceive (idsender, &idmessage, &hpacked);
00347         
00348         if (hpacked == nil) /*no message received*/
00349             continue;
00350             
00351         if (idmessage != idreceiver) { /*message is from someone else, queue it*/
00352             
00353             landpushqueue (hpacked);
00354             
00355             continue;
00356             }
00357             
00358         /*we got our answer, process it and return*/
00359                 
00360         if (!landnewverb (idnull, nullclass, nulltoken, 0, hvalues)) {
00361             
00362             /*failed to create verb handle to hold returned values*/
00363 
00364             landdisposehandle (hpacked);
00365 
00366             return (false); 
00367             }
00368         
00369         hv = *hvalues; /*copy into register*/
00370         
00371         while (true) { /*unpack params*/
00372             
00373             typaramrecord param;
00374         
00375             if (!landsystem6unpackparam (hpacked, &ix, &param)) { /*no more params*/
00376                 
00377                 landdisposehandle (hpacked);
00378                 
00379                 return (true);
00380                 }
00381                 
00382             if (!landpushparamrecord (hv, param)) {
00383                 
00384                 landdisposehandle (hpacked);
00385                 
00386                 return (false);
00387                 }
00388             } /*while*/
00389         } /*while*/
00390     } /*landsystem6send*/
00391     
00392 
00393 static boolean landsystem6poll (hdlverbrecord *hverb) {
00394 
00395     /*
00396     1/1/91-3/x/91 mao: made networkable, other fixes (queued events)
00397     */
00398     
00399     register hdllandglobals hg = landgetglobals ();
00400     register hdlverbrecord hv;
00401     register hdlsys6transportinfo ht;
00402     register boolean fl;
00403     Handle hpacked; 
00404     short senderid;
00405 
00406     *hverb = nil; /*default, no verb available*/
00407     
00408     if (!landpopqueue (&hpacked)) /*nothing waiting in the queue*/
00409         ipcReceive ((**hg).system6processid, &senderid, &hpacked);  
00410         
00411     if (hpacked == nil)
00412         return (true);
00413     
00414     fl = landsystem6unpackverb (hpacked, hverb);
00415     
00416     landdisposehandle (hpacked);
00417     
00418     if (!fl) /*error unpacking verb*/
00419         return (false);
00420     
00421     hv = *hverb; /*copy into register*/
00422     
00423     ht = (hdlsys6transportinfo) (**hv).transportinfo;
00424     
00425     (**ht).sys6processid = senderid; /*this guy gets the returned value*/
00426     
00427     return (true);
00428     } /*landsystem6poll*/
00429 
00430 
00431 boolean landsystem6eventfilter (EventRecord *ev) {
00432     
00433     /*
00434     during null events, poll for incoming messages and process one 
00435     if available.
00436     
00437     return true if we consume the event, false otherwise.
00438     */
00439     
00440     hdlverbrecord hverb;
00441 
00442     switch ((*ev).what) {
00443     
00444         case nullEvent:
00445             if (landsystem6poll (&hverb) && (hverb != nil)) { /*got on incoming message*/
00446                 
00447                 landhandleverb (hverb);
00448                 
00449                 return (true); /*consume the event*/
00450                 }
00451         } /*switch*/
00452     
00453     return (false); /*don't consume the event*/
00454     } /*landsystem6eventfilter*/
00455 
00456 
00457 static boolean landsystem6returnhandle (hdlverbrecord hverb, Handle hpacked) {
00458 
00459     register hdllandglobals hg = landgetglobals ();
00460     register hdlsys6transportinfo ht;
00461     register boolean fl;
00462     
00463     ht = (hdlsys6transportinfo) (**hverb).transportinfo;
00464 
00465     fl = ipcSend ((**hg).system6processid, (**ht).sys6processid, hpacked) == noErr;
00466     
00467     landdisposehandle (hpacked);
00468         
00469     return (fl);
00470     } /*landsystem6returnhandle*/
00471     
00472 
00473 boolean landsystem6returnmultiple (hdlverbrecord hverb) {
00474     
00475     /*
00476     hverb is the verb we're responding to with a series of returned values which
00477     are linked into the params array of the verbrecord.
00478     */
00479     
00480     register hdlverbrecord hv = hverb;
00481     register short ct = (**hv).nextparam;
00482     Handle hpacked;
00483     
00484     if (!landnewemptyhandle (&hpacked))
00485         return (false);
00486     
00487     if (!landsystem6packallparams (hv, hpacked)) {
00488     
00489         landdisposehandle (hpacked);
00490         
00491         return (false);
00492         }
00493     
00494     return (landsystem6returnhandle (hv, hpacked));
00495     } /*landsystem6returnmultiple*/
00496     
00497     
00498 boolean landsystem6close (void) {
00499     
00500     register hdllandglobals hg = landgetglobals ();
00501     
00502     landemptyqueue ();
00503     
00504     return (ipcClose ((**hg).system6processid) == noErr);
00505     } /*landsystem6close*/
00506     
00507 
00508 boolean landsystem6init (void) {
00509 
00510     register hdllandglobals hg = landgetglobals ();
00511     tysystem6processid id;
00512     bigstring bs;
00513     
00514     land4bytestostring ((**hg).applicationid, bs);
00515     
00516     if (ipcOpen ((PIN *) bs, &id) != noErr)
00517         return (false);
00518     
00519     (**hg).system6processid = id;   
00520     
00521     (**hg).hqueue = nil;
00522     
00523     return (true);
00524     } /*landsystem6init*/
00525 
00526 
00527 boolean landsystem6setapplicationid (tyapplicationid newid) {
00528 
00529     /*
00530     allows toolkit user to change application id on the fly (e.g. 'ascr' to 
00531     'mao!')  this call flushes outstanding queued local and network requests.
00532     */
00533 
00534     register hdllandglobals hg = landgetglobals ();
00535     bigstring bs;
00536     tysystem6processid newprocessid;
00537     
00538     land4bytestostring (newid, bs);
00539     
00540     if (ipcOpen ((PIN *) bs, &newprocessid) != noErr)
00541         return (false);
00542 
00543     if (ipcClose ((**hg).system6processid) != noErr) {
00544     
00545         ipcClose (newprocessid); /*get rid of the one we just made*/
00546         
00547         return (false);
00548         }
00549         
00550     landemptyqueue (); /*flush out queued requests for old id*/
00551     
00552     (**hg).system6processid = newprocessid;
00553     
00554     (**hg).applicationid = newid;
00555 
00556     return (true);
00557     } /*landsystem6setapplicationid*/
00558     
00559     

Generated on Wed May 31 18:19:50 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6