~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/atobj/atobj-rcvr.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * atobj-rcvr.cc --
  3  *
  4  *      member functions of
  5  *          - AtobjRcvr
  6  *
  7  * Copyright (c) 1997-2002 The Regents of the University of California.
  8  * All rights reserved.
  9  *
 10  * Redistribution and use in source and binary forms, with or without
 11  * modification, are permitted provided that the following conditions are met:
 12  *
 13  * A. Redistributions of source code must retain the above copyright notice,
 14  *    this list of conditions and the following disclaimer.
 15  * B. Redistributions in binary form must reproduce the above copyright notice,
 16  *    this list of conditions and the following disclaimer in the documentation
 17  *    and/or other materials provided with the distribution.
 18  * C. Neither the names of the copyright holders nor the names of its
 19  *    contributors may be used to endorse or promote products derived from this
 20  *    software without specific prior written permission.
 21  *
 22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 23  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 32  * POSSIBILITY OF SUCH DAMAGE.
 33  */
 34 
 35 #ifndef ATOBJ_RCVR_CC
 36 #define ATOBJ_RCVR_CC
 37 
 38 #ifndef lint
 39 static const char rcsid[] = "$Header: /usr/mash/src/repository/mash/mash-1/atobj/atobj-rcvr.cc,v 1.12 2003/11/19 19:20:14 aswan Exp $";
 40 #endif
 41 
 42 #include "mb/mb.h"
 43 #include "mb/mb-nethost.h"
 44 #include "rtp/inet.h"
 45 #include "atobj/atobj-rcvr.h"
 46 #include "atobj/atobj-sm.h"
 47 #include "misc/str.h"
 48 
 49 class AtobjSM;
 50 
 51 static class AtObjRcvrClass : public TclClass {
 52 public:
 53         AtObjRcvrClass() : TclClass("Atobj_rcvr") {}
 54         TclObject* create(int argc, const char*const* argv);
 55 } atobjRcvr_class;
 56 
 57 TclObject* AtObjRcvrClass::create(int argc, const char*const* argv)
 58 {
 59         // format:
 60         //    new AtobjRcvr <sess-mgr> [<uid-in-hex> <addr-in-hex>]
 61         //        (use local addr/getuid() if not specified)
 62 
 63         // REVIEW: Tcl should start arg with 1!
 64         const int cTclArgStart = 4; // first argument is at argv[4]
 65         if (argc < cTclArgStart+1) {
 66                 SignalError(("wrong args, usage: new AtobjRcvr"
 67                              " <sess-mgr> [<uid-in-hex> <addr-in-hex>]"));
 68         }
 69         AtobjSM* pMgr = (AtobjSM*)TclObject::lookup(argv[cTclArgStart]);
 70         SrcId sid;
 71         if (argc < cTclArgStart+3) {
 72                 sid.ss_uid = getuid();
 73                 sid.ss_addr = LookupLocalAddr();
 74         } else {
 75                 sid.ss_uid  = strtoul(argv[cTclArgStart+1], (char **)NULL, 16);
 76                 sid.ss_addr = strtoul(argv[cTclArgStart+2], (char **)NULL, 16);
 77         }
 78         return (new AtobjRcvr(pMgr, sid));
 79 }
 80 
 81 AtobjRcvr::AtobjRcvr(AtobjSM *pSM, const SrcId& srcId)
 82         // REVIEW: what is the use of 'hdrlen' in SRM?
 83         : SRM_PacketHandler(0), nextAnmId_(1)
 84 {
 85         srcId_ = srcId;
 86         pMgr_ = pSM;
 87         phtAnimations_ = new Tcl_HashTable;
 88 
 89         // the following must be true
 90         // otherwise we would use garbage as part of the keys
 91         assert( sizeof(AnimationId) == sizeof(char*) );
 92         Tcl_InitHashTable(phtAnimations_, TCL_ONE_WORD_KEYS);
 93 
 94         phtRequests_ = new Tcl_HashTable;
 95         // keys are pointers
 96         Tcl_InitHashTable(phtRequests_, TCL_ONE_WORD_KEYS);
 97 
 98         phtReplies_ = new Tcl_HashTable;
 99         // keys are pointers
100         Tcl_InitHashTable(phtReplies_, TCL_ONE_WORD_KEYS);
101 }
102 
103 AtobjRcvr::~AtobjRcvr()
104 {
105         Tcl_HashSearch search;
106         Tcl_HashEntry *pEntry = Tcl_FirstHashEntry(phtAnimations_, &search);
107         while (pEntry) {
108                 char *szAnmName = (char *)Tcl_GetHashValue(pEntry);
109                 Tcl::instance().evalf("delete %s", szAnmName);
110                 delete[] szAnmName;
111                 pEntry = Tcl_NextHashEntry(&search);
112         }
113         Tcl_DeleteHashTable(phtAnimations_);
114         delete phtAnimations_;
115 
116         pEntry = Tcl_FirstHashEntry(phtRequests_, &search);
117         while (pEntry) {
118                 Atobj_request* pRequest =
119                         (Atobj_request*) Tcl_GetHashValue(pEntry);
120                 pRequest->cancel(); // cancel will delete the request
121                 pEntry = Tcl_NextHashEntry(&search);
122         }
123         Tcl_DeleteHashTable(phtRequests_);
124         delete phtRequests_;
125 
126         pEntry = Tcl_FirstHashEntry(phtReplies_, &search);
127         while (pEntry) {
128                 Atobj_reply* pReply =
129                         (Atobj_reply*) Tcl_GetHashValue(pEntry);
130                 pReply->cancel(); // cancel will delete the reply
131                 pEntry = Tcl_NextHashEntry(&search);
132         }
133         Tcl_DeleteHashTable(phtReplies_);
134         delete phtReplies_;
135 }
136 
137 /*
138  *----------------------------------------------------------------------
139  *
140  * AtobjRcvr::create_animator --
141  *
142  *  Creates a new animation
143  *
144  *  Note: called by other member functions, return string will be stored
145  *        as part of hash table and deleted at destruction time.
146  *
147  *----------------------------------------------------------------------
148  */
149 char* AtobjRcvr::create_animation(const AnimationId& anmId)
150 {
151         MB_DefTcl(tcl);
152         // REVIEW: figure out dynamic creation of objects with diff. types
153         tcl.evalf("%s new_animation %lu", name(), anmId);
154         char *sz = NULL;
155         ::AllocNCopy(&sz, tcl.result());
156         Trace(VERBOSE, ("new animation returns %s", sz));
157         return sz;
158 }
159 
160 /*
161  *----------------------------------------------------------------------
162  *
163  * AtobjRcvr::define_animation --
164  *
165  *  Creates an animation if we did not know about it yet, otherwise
166  *  create a new one.
167  *
168  *----------------------------------------------------------------------
169  */
170 
171 int AtobjRcvr::define_animation(const AnimationId& anmId)
172 {
173         int created;
174         char* szAnim;
175         Tcl_HashEntry *pEntry =
176                 Tcl_CreateHashEntry(phtAnimations_, (char*)anmId, &created);
177         if (created) {
178                 szAnim = create_animation(anmId);
179                 assert(szAnim);
180                 Tcl_SetHashValue(pEntry, (ClientData) szAnim);
181         }
182         return created;
183 }
184 
185 /*
186  *----------------------------------------------------------------------
187  *
188  * AtobjRcvr::get_animation --
189  *
190  * returns the (tcl) name of an animation given anmId
191  *    if animation not found, return NULL
192  *
193  *----------------------------------------------------------------------
194  */
195 const char* AtobjRcvr::get_animation(const AnimationId& anmId)
196 {
197         Tcl_HashEntry *pEntry = Tcl_FindHashEntry(phtAnimations_,
198                                                   (char*)anmId);
199         if (!pEntry) return NULL;
200         else return (char*)Tcl_GetHashValue(pEntry);
201 }
202 
203 /*
204  *----------------------------------------------------------------------
205  *
206  * AtobjRcvr::add_animation --
207  *
208  *  Adds a new animation given its name, this is appropriate for local
209  *     receivers
210  *
211  *  szAnim : animation (tcl) name
212  *  anmId : Id of the animation that we want to create
213  *
214  *----------------------------------------------------------------------
215  */
216 
217 void AtobjRcvr::add_animation(const char* szAnim, const AnimationId& anmId)
218 {
219         int created;
220         Tcl_HashEntry *pEntry =
221                 Tcl_CreateHashEntry(phtAnimations_, (char*)anmId, &created);
222 
223         assert(created && "animation was added twice?");
224         assert(szAnim && "creating with null animation?");
225         char *szName;
226         ::AllocNCopy(&szName, szAnim);
227         Tcl_SetHashValue(pEntry, (ClientData) szName);
228 
229         Tcl& tcl = Tcl::instance();
230         tcl.evalf("%s setAnmId %d", szAnim, anmId);
231 }
232 
233 /*
234  *----------------------------------------------------------------------
235  *
236  * AtobjRcvr::next_ADU --
237  *
238  *  return the next ADU from a animator
239  *
240  *----------------------------------------------------------------------
241  */
242 /*virtual*/
243 int AtobjRcvr::next_ADU(Byte *pb, int maxPktLen)
244 {
245         char* szADU=NULL;
246         AtoPkt_event* pPkt = (AtoPkt_event*) pb;
247 
248         // For now we get data from animations in arbitrary order
249         // REVIEW: obviously we should poll them in a better sequence
250         Tcl& tcl = Tcl::instance();
251         Tcl_HashSearch search;
252         Tcl_HashEntry *pEntry=NULL;
253         for ( pEntry = Tcl_FirstHashEntry(phtAnimations_, &search);
254               pEntry != NULL;
255               pEntry = Tcl_NextHashEntry(&search) ) {
256 
257                 char *szAnmName = (char *)Tcl_GetHashValue(pEntry);
258                 tcl.evalf("%s next_ADU %ld", szAnmName, maxPktLen);
259                 szADU = tcl.result();
260                 if (szADU[0] != cchNull) {
261                         break;
262                 }
263                 pEntry = Tcl_NextHashEntry(&search);
264         }
265         if (!szADU) return 0;
266 
267         AnimationId anmId =
268                 (AnimationId) Tcl_GetHashKey(phtAnimations_, pEntry);
269 
270         pPkt->pe_anmId = host2net(anmId);
271         // REVIEW: decide where eventids go
272         pPkt->pe_eventId = 0;
273         int strLen = PKT_ROUNDUP(strlen(szADU)+1);
274         pPkt->pe_strLen = host2net(strLen);
275         strcpy(pPkt->pe_achContent, szADU);
276                                 // zero out the rest of the string
277         for (int i=strlen(szADU); i<strLen; i++) {
278                 pPkt->pe_achContent[i] = cchNull;
279         }
280         assert((int)sizeof(AtoPkt_event)+strLen <= maxPktLen);
281         return (sizeof(AtoPkt_event)+strLen);
282 }
283 
284 
285 /*
286  *----------------------------------------------------------------------
287  *
288  * AtobjRcvr::recv --
289  *
290  *  The callback from SRM_PacketHandler
291  *
292  *----------------------------------------------------------------------
293  */
294 
295 /*virtual*/
296 #ifdef MB_DEBUG
297 void AtobjRcvr::recv(Byte *pb, u_int len)
298 #else
299 void AtobjRcvr::recv(Byte *pb, u_int /* len */)
300 #endif
301 {
302         AtoPkt_event* pEvent=(AtoPkt_event*) pb;
303         AnimationId anmId = net2host(pEvent->pe_anmId);
304         //    EventId evId = net2host(pEvent->pe_anmId);
305         //    int len = net2host(pEvent->len);
306         // REVIEW: do something more efficient here
307         MB_DefTcl(tcl);
308         // REVIEW: check the length .... might not be null terminated...
309 
310         // create it if not found
311         define_animation(anmId);
312         Trace(VERYVERBOSE, ("received %d bytes", len));
313         const char* szAnim = get_animation(anmId);
314         if (szAnim) {
315                 char* szCmd = Concat3(szAnim, " recv_ADU ",
316                                       pEvent->pe_achContent);
317                 tcl.eval(szCmd);
318                 delete[] szCmd;
319         } else {
320                 Trace(VERBOSE, ("ignoring data"));
321         }
322 }
323 
324 /*
325  *----------------------------------------------------------------------
326  *
327  * AtobjRcvr::handleRequest --
328  *
329  *      upcall to the animation to handle it
330  *
331  *----------------------------------------------------------------------
332  */
333 void AtobjRcvr::handleRequest(AtoPkt_request *pPkt)
334 {
335         AnimationId anmId = net2host(pPkt->pr_anmId);
336         int isNew = define_animation(anmId);
337         // if this is the first time we see this animation, no point
338         // handing it the request.
339         Tcl& tcl=Tcl::instance();
340         if (!isNew) {
341                 const char* szAnim = get_animation(anmId);
342                 tcl.evalf("%s handle_request %s", szAnim,
343                           pPkt->pr_achContent);
344         }
345 }
346 
347 /*
348  *----------------------------------------------------------------------
349  *
350  * AtobjRcvr::schedRequest --
351  *
352  *  Creates a request object and schedules it
353  *
354  *----------------------------------------------------------------------
355  */
356 Atobj_request* AtobjRcvr::schedRequest(const AnimationId& anmId)
357 {
358         Atobj_request* pRequest = new Atobj_request(this, anmId);
359         int created;
360         Tcl_HashEntry *pEntry =
361                 Tcl_CreateHashEntry(phtRequests_, (char*)pRequest, &created);
362         assert(created && "2 request at the same memory?");
363 
364         assert(sizeof(anmId)==sizeof(ClientData));
365         Tcl_SetHashValue(pEntry, (ClientData)anmId);
366 
367         pMgr_->schedRequest(pRequest, srcId_);
368         return pRequest;
369 }
370 
371 /*
372  *----------------------------------------------------------------------
373  *
374  * AtobjRcvr::updateRequest --
375  *
376  *  returns true if request is still needed, false otherwise
377  *
378  *----------------------------------------------------------------------
379  */
380 int AtobjRcvr::updateRequest(Atobj_request* pRequest,
381                                const AnimationId& anmId)
382 {
383         const char* szAnmName = get_animation(anmId);
384         Tcl& tcl = Tcl::instance();
385         tcl.evalf("%s update_request %lu", szAnmName, pRequest);
386         int ret;
387         int ok = str2int(tcl.result(), ret);
388         assert(ok && "conversion error!");
389         return (int)ok;
390 }
391 
392 /*
393  *----------------------------------------------------------------------
394  *
395  * AtobjRcvr::fillRequest --
396  *
397  *    use an upcall to get request
398  *
399  *----------------------------------------------------------------------
400  */
401 u_int AtobjRcvr::fillRequest(Atobj_request* pRequest,
402                              const AnimationId& anmId, Byte* pb, int len)
403 {
404         const char* szAnmName = get_animation(anmId);
405         Tcl& tcl = Tcl::instance();
406         tcl.evalf("%s fill_request %lu %d", szAnmName, pRequest,
407                   len - sizeof(AtoPkt_request));
408         const char* szResult = tcl.result();
409         if (szResult[0]==cchNull)
410                 return 0;
411 
412         AtoPkt_request* pPkt = (AtoPkt_request*) pb;
413         host2net(srcId_, pPkt->pr_srcId);
414         Trace(VERYVERBOSE, ("(%x) filling rqt src=%d@%s", this, srcId_.ss_uid,
415                         intoa(srcId_.ss_addr)));
416         pPkt->pr_anmId = host2net(anmId);
417 
418         int strLen = PKT_ROUNDUP(strlen(szResult)+1);
419         strcpy(pPkt->pr_achContent, szResult);
420         // zero out the rest of the string
421         for (int i=strlen(szResult); i<strLen; i++) {
422                 pPkt->pr_achContent[i] = cchNull;
423         }
424         assert((int)sizeof(AtoPkt_request)+strLen < len);
425         return (sizeof(AtoPkt_request)+strLen);
426 }
427 
428 /*
429  *----------------------------------------------------------------------
430  *
431  * AtobjRcvr::cancelRequest --
432  *
433  *    cancel an request, we notify the animation also in case the
434  *    cancellation is due to # requests exceeding cMaxNumRequests
435  *
436  *    return false on invalid id's or requests.
437  *
438  *----------------------------------------------------------------------
439  */
440 int AtobjRcvr::cancelRequest(Atobj_request* pRequest,
441                              const AnimationId& anmId, int wantCallback)
442 {
443         Tcl_HashEntry *pEntry =
444                 Tcl_FindHashEntry(phtRequests_, (char*)pRequest);
445         if (!pEntry) return FALSE;
446 
447         if (wantCallback) {
448                 const char* szAnmName = get_animation(anmId);
449                 if (!szAnmName) return FALSE;
450 
451                 Tcl& tcl = Tcl::instance();
452                 tcl.evalf("%s cancel_request %lu", szAnmName, (u_int)pRequest);
453         }
454 
455         assert(pEntry && "cannot find request!");
456         Tcl_DeleteHashEntry(pEntry);
457         pRequest->cancel();
458         return TRUE;
459 }
460 
461 
462 /*
463  *----------------------------------------------------------------------
464  *
465  * AtobjRcvr::cancelReply --
466  *
467  *    use an upcall to get an reply
468  *
469  *    return false on invalid id's or requests.
470  *----------------------------------------------------------------------
471  */
472 int AtobjRcvr::cancelReply(Atobj_reply* pReply, const AnimationId& anmId)
473 {
474         Tcl_HashEntry *pEntry =
475                 Tcl_FindHashEntry(phtReplies_, (char*)pReply);
476         if (!pEntry) return FALSE;
477 
478         const char* szAnmName = get_animation(anmId);
479         if (!szAnmName) return FALSE;
480 
481         Tcl& tcl = Tcl::instance();
482         tcl.evalf("%s cancel_reply %lu", szAnmName, (u_int)pReply);
483 
484         assert(pEntry && "cannot find reply!");
485         Tcl_DeleteHashEntry(pEntry);
486         pReply->cancel();
487         return TRUE;
488 }
489 
490 
491 /*
492  *----------------------------------------------------------------------
493  *
494  * AtobjRcvr::schedReply --
495  *
496  *  Creates a reply object and schedules it
497  *
498  *----------------------------------------------------------------------
499  */
500 Atobj_reply* AtobjRcvr::schedReply(const AnimationId& anmId)
501 {
502         Atobj_reply* pReply = new Atobj_reply(this, anmId);
503         int created;
504         Tcl_HashEntry *pEntry =
505                 Tcl_CreateHashEntry(phtReplies_, (char*)pReply, &created);
506         assert(created && "2 reply at the same memory?");
507 
508         assert(sizeof(anmId)==sizeof(ClientData));
509         Tcl_SetHashValue(pEntry, (ClientData)anmId);
510         pMgr_->schedReply(pReply, srcId_);
511 
512         return pReply;
513 }
514 
515 
516 /*
517  *----------------------------------------------------------------------
518  *
519  * AtobjRcvr::handleReply --
520  *
521  *      upcall to the animation to handle it
522  *
523  *----------------------------------------------------------------------
524  */
525 void AtobjRcvr::handleReply(AtoPkt_reply *pPkt)
526 {
527         AnimationId anmId = net2host(pPkt->pr_anmId);
528         define_animation(anmId);
529 
530         const char* szAnim = get_animation(anmId);
531         char* szCmd=Concat3(szAnim, " handle_reply ", pPkt->pr_achContent);
532         Tcl::instance().eval(szCmd);
533         delete[] szCmd;
534 }
535 
536 /*
537  *----------------------------------------------------------------------
538  *
539  * AtobjRcvr::fillReply --
540  *
541  *    use an upcall to get an reply
542  *
543  *----------------------------------------------------------------------
544  */
545 u_int AtobjRcvr::fillReply(Atobj_reply* pReply,
546                              const AnimationId& anmId, Byte* pb, int len)
547 {
548         const char* szAnmName = get_animation(anmId);
549         Tcl& tcl = Tcl::instance();
550         // -8 so that the rounding up is being taken care of
551         // REVIEW: less than -8 ?
552         tcl.evalf("%s fill_reply %lu %d", szAnmName, pReply,
553                   len - sizeof(AtoPkt_reply)- 6);
554         const char* szResult = tcl.result();
555 
556         if (szResult[0]==cchNull)
557                 return 0;
558 
559         AtoPkt_reply* pPkt = (AtoPkt_reply*) pb;
560         host2net(srcId_, pPkt->pr_srcId);
561         pPkt->pr_anmId = host2net(anmId);
562 
563         int strLen = PKT_ROUNDUP(strlen(szResult)+1);
564         strcpy(pPkt->pr_achContent, szResult);
565         // zero out the rest of the string
566         for (int i=strlen(szResult); i<strLen; i++) {
567                 pPkt->pr_achContent[i] = cchNull;
568         }
569         assert((int)sizeof(AtoPkt_reply) + strLen < len);
570         return (sizeof(AtoPkt_reply) + strLen);
571 }
572 
573 /*
574  *----------------------------------------------------------------------
575  *
576  * AtobjRcvr::fillSA --
577  *
578  *----------------------------------------------------------------------
579  */
580 u_int AtobjRcvr::fillSA(Byte* pb)
581 {
582         /* REVIEW: modify this to take multiple animations */
583         Tcl_HashSearch hs;
584         Tcl_HashEntry *pEntry = Tcl_FirstHashEntry(phtAnimations_, &hs);
585         if (!pEntry) {
586                 bzero(pb, sizeof(AtoPkt_SA));
587                 return sizeof(AtoPkt_SA);       // nothing
588         }
589 
590         const char* szAnmName = (char*) Tcl_GetHashValue(pEntry);
591         AnimationId anmId =
592                 (AnimationId) Tcl_GetHashKey(phtAnimations_, pEntry);
593         /* REVIEW: get the size right! */
594         Tcl& tcl = Tcl::instance();
595         tcl.evalf("%s fill_sa", szAnmName);
596         const char* szResult = tcl.result();
597         if (szResult[0]==cchNull) return 0;
598 
599         AtoPkt_SA *pSA = (AtoPkt_SA *)pb;
600         host2net(srcId_, pSA->sa_srcId);
601         pSA->sa_anmId = host2net(anmId);
602         int strLen = PKT_ROUNDUP(strlen(szResult)+1);
603         strcpy(pSA->sa_achSA, szResult);
604         // zero out the rest of the string
605         for (int i=strlen(szResult); i<strLen; i++) {
606                 pSA->sa_achSA[i] = cchNull;
607         }
608         assert(sizeof(AtoPkt_SA) + strLen < SRM_MTU);
609         return (sizeof(AtoPkt_SA) + strLen);
610 }
611 
612 
613 /*
614  *----------------------------------------------------------------------
615  *
616  * AtobjRcvr::handleSA --
617  *
618  *----------------------------------------------------------------------
619  */
620 void AtobjRcvr::handleSA(AtoPkt_SA* pSA)
621 {
622         AnimationId anmId = net2host(pSA->sa_anmId);
623         MB_DefTcl(tcl);
624         define_animation(anmId);
625         const char* szAnim = get_animation(anmId);
626         if (szAnim) {
627                 char* szCmd = Concat3(szAnim, " handle_sa ",
628                                       pSA->sa_achSA);
629                 tcl.eval(szCmd);
630                 delete[] szCmd;
631         } else {
632                 Trace(VERBOSE, ("ignoring data"));
633         }
634 }
635 
636 
637 /*virtual*/
638 int AtobjRcvr::command(int argc, const char*const* argv)
639 {
640         const char* cszUsage =
641                 "wrong usage, should be: \n"
642                 "$atobjRcvr begin_xmit len\n"
643                 "   add_animation anm_name [id]\n"
644                 "   sched_request anmId\n"
645                 "   sched_reply anmId\n"
646                 "   backoff_request reqId\n"
647                 "   cancel_request reqId anmId wantCallback\n"
648                 "   cancel_reply replyId anmId\n";
649         int len;
650 
651         Tcl& tcl=Tcl::instance();
652         if (!strcmp(argv[1], "begin_xmit") && argc==3) {
653                 if (str2int(argv[2], len)) {
654                         len = PKT_ROUNDUP(len+1);
655                         len += sizeof(AtoPkt_event);
656                         pMgr_->begin_xmit(len);
657                 } else {
658                         goto err;
659                 }
660         } else if (!strcmp(argv[1], "add_animation") && argc>=3) {
661                 int id;
662                 if (argc==4) {
663                         if (!str2int(argv[3], id))
664                                 goto err;
665                 }
666                 id = nextAnmId_++;
667                 add_animation(argv[2], id);
668         } else if (!strcmp(argv[1], "sched_request") && argc==3) {
669                 int id;
670                 if (!str2int(argv[2], id)) goto err;
671                 Atobj_request* pRequest = schedRequest(id);
672                 tcl.resultf("%lu", (u_int)pRequest);
673         } else if (!strcmp(argv[1], "backoff_request") && argc==3) {
674                 int p;
675                 if (!str2int(argv[2], p)) goto err;
676                 Atobj_request* pRequest=(Atobj_request*)p;
677                 pRequest->backoff();
678         } else if (!strcmp(argv[1], "cancel_request") && argc==5) {
679                 int p, anmId, wantCallback;
680                 if (!str2int(argv[2], p)) goto err;
681                 Atobj_request* pRequest=(Atobj_request*)p;
682                 if (!str2int(argv[3], anmId)) goto err;
683                 if (!str2int(argv[4], wantCallback)) goto err;
684                 if (!cancelRequest(pRequest, anmId, wantCallback)) {
685                         Tcl_AddErrorInfo(tcl.interp(),
686                                          "cancel request failed");
687                         return TCL_ERROR;
688                 }
689         }  else if (!strcmp(argv[1], "sched_reply") && argc==3) {
690                 int id;
691                 if (!str2int(argv[2], id)) goto err;
692                 Atobj_reply* pReply = schedReply(id);
693                 tcl.resultf("%lu", (u_int)pReply);
694         } else if (!strcmp(argv[1], "cancel_reply") && argc==4) {
695                 int p, anmId;
696                 if (!str2int(argv[2], p)) goto err;
697                 Atobj_reply* pReply=(Atobj_reply*)p;
698                 if (!str2int(argv[3], anmId)) goto err;
699                 if (!cancelReply(pReply, anmId)) {
700                         Tcl_AddErrorInfo(tcl.interp(),
701                                          "cancel reply failed");
702                         return TCL_ERROR;
703                 }
704         } else {
705                 goto err;
706         }
707         return TCL_OK;
708 
709  err:
710                                 // invalid parameter
711         Tcl_AddErrorInfo(tcl.interp(), (char *)cszUsage);
712         return TCL_ERROR;
713 }
714 
715 
716 #endif /* #ifdef ATOBJ_RCVR_CC */
717 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.