Urbi SDK Remote for C++  2.7.5
uabstractclient.hh
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2006-2011, Gostai S.A.S.
00003  *
00004  * This software is provided "as is" without warranty of any kind,
00005  * either expressed or implied, including but not limited to the
00006  * implied warranties of fitness for a particular purpose.
00007  *
00008  * See the LICENSE file for more information.
00009  */
00010 
00013 
00014 #ifndef URBI_UABSTRACTCLIENT_HH
00015 # define URBI_UABSTRACTCLIENT_HH
00016 
00017 # include <libport/cstdio>
00018 # include <libport/sys/types.h>
00019 # include <libport/cstring>
00020 # include <libport/cstdlib>
00021 # include <cstdarg>
00022 
00023 # include <list>
00024 # include <iostream>
00025 # include <string>
00026 
00027 # include <libport/compiler.hh>
00028 # include <libport/fwd.hh>
00029 # include <libport/lockable.hh>
00030 # include <libport/traits.hh>
00031 
00032 # include <urbi/fwd.hh>
00033 # include <urbi/export.hh>
00034 # include <urbi/ubinary.hh>
00035 # include <urbi/umessage.hh>
00036 
00046 namespace urbi
00047 {
00049 
00055   enum UCallbackAction
00056     {
00057       URBI_CONTINUE=0,
00058       URBI_REMOVE
00059     };
00060 
00062   enum { URBI_MAX_TAG_LENGTH = 64 };
00063 
00064   typedef unsigned int UCallbackID;
00065 
00066 # define UINVALIDCALLBACKID 0
00067 
00069   typedef UCallbackAction (*UCallback)             (const UMessage&msg);
00070 
00071   typedef UCallbackAction (*UCustomCallback)       (void * callbackData,
00072                                                     const UMessage&msg);
00073 
00074 
00075   //used internaly
00076   class UCallbackInfo
00077   {
00078   public:
00079     UCallbackInfo(UCallbackWrapper &w);
00080     bool operator==(UCallbackID id) const;
00081 
00082     char tag[URBI_MAX_TAG_LENGTH];
00083     UCallbackWrapper& callback;
00084     UCallbackID id;
00085   };
00086 
00087   //used internaly
00088   class UClientStreambuf;
00089 
00090 
00091   class LockableOstream: public std::ostream
00092   {
00093   public:
00094     LockableOstream(std::streambuf* sb)
00095     : std::ostream(sb)
00096     {
00097     }
00098     mutable libport::Lockable sendBufferLock;
00099   };
00100 
00101 
00103 
00120   class URBI_SDK_API UAbstractClient : public LockableOstream
00121   {
00122   public:
00124     enum { URBI_BUFLEN = 128000 };
00126     enum { URBI_PORT = 54000 } ;
00128     static const char* default_host();
00129 
00133     typedef int error_type;
00134 
00136 
00143     UAbstractClient(const std::string& host = default_host(),
00144                     unsigned port = URBI_PORT,
00145                     size_t buflen = URBI_BUFLEN,
00146                     bool server = false);
00147 
00148     virtual ~UAbstractClient();
00149 
00150     bool init() const;
00152     error_type error() const;
00153 
00154     /*----------.
00155     | Sending.  |
00156     `----------*/
00165 
00166 
00170     ATTRIBUTE_PRINTF(2, 3)
00171     error_type send(const char* format, ...);
00172 
00174     error_type send(const std::string& s);
00175 
00177     error_type send(const urbi::UValue& v);
00178 
00180     error_type send(std::istream& is);
00181 
00183     error_type sendBinary(const void* data, size_t len,
00184                           const std::string& header);
00185 
00187     error_type sendBin(const void*, size_t len);
00188 
00190     ATTRIBUTE_PRINTF(4, 5)
00191     error_type sendBin(const void*, size_t len, const char* header, ...);
00192 
00195     error_type startPack();
00196 
00199     error_type endPack();
00200 
00204     ATTRIBUTE_PRINTF(2, 3)
00205     error_type pack(const char* format, ...);
00206 
00209     error_type vpack(const char* format, va_list args);
00210 
00213     error_type sendFile(const std::string& f);
00214 
00217     ATTRIBUTE_PRINTF(3, 4)
00218     UCallbackID sendCommand(UCallback, const char*, ...);
00219 
00222     ATTRIBUTE_PRINTF(4, 5)
00223     UCallbackID sendCommand(UCustomCallback, void *, const char*, ...);
00224 
00226     error_type sendSound(const char* device,
00227                   const urbi::USound& sound, const char* tag = 0);
00228 
00230     error_type putFile(const char* localName, const char* remoteName = 0);
00231 
00233     error_type putFile(const void* buffer, size_t length,
00234                        const char* remoteName);
00235 
00237 
00239 
00249 
00250 
00254     UCallbackID setCallback(UCallbackWrapper& callback, const char* tag);
00255 
00257     UCallbackID setErrorCallback(UCallbackWrapper& callback);
00258 
00260     UCallbackID setWildcardCallback(UCallbackWrapper& callback);
00261 
00263     UCallbackID setClientErrorCallback(UCallbackWrapper& callback);
00264 
00266     UCallbackID setCallback(UCallback, const char* tag);
00267 
00271     UCallbackID setCallback(UCustomCallback, void* callbackData,
00272                             const char* tag);
00273 
00275 
00276 
00277 
00278     template<class C>
00279     UCallbackID
00280     setCallback(C& ref, UCallbackAction (C::*)(const UMessage&),
00281                             const char * tag);
00282     template<class C, class P1>
00283     UCallbackID
00284     setCallback(C& ref, UCallbackAction (C::*)(P1, const UMessage&),
00285                 P1, const char * tag);
00286     template<class C, class P1, class P2>
00287     UCallbackID
00288     setCallback(C& ref, UCallbackAction (C::*)(P1 , P2, const UMessage&),
00289                 P1, P2,    const char * tag);
00290 
00291     template<class C, class P1, class P2, class P3>
00292     UCallbackID
00293       setCallback(C& ref, UCallbackAction (C::*)(P1 , P2, P3, const UMessage&),
00294                   P1, P2, P3, const char* tag);
00295 
00296     template<class C, class P1, class P2, class P3, class P4>
00297     UCallbackID
00298     setCallback(C& ref, UCallbackAction(C::*)(P1 , P2, P3, P4, const UMessage&),
00299                 P1, P2, P3, P4, const char* tag);
00301 
00304     int getAssociatedTag(UCallbackID id, char* tag);
00305 
00308     int deleteCallback(UCallbackID id);
00309 
00311     std::string fresh();
00312 
00315     ATTRIBUTE_DEPRECATED
00316     void makeUniqueTag(char* tag);
00317 
00320     virtual void notifyCallbacks(const UMessage& msg);
00321 
00323     ATTRIBUTE_PRINTF(2, 3)
00324     virtual void printf(const char* format, ...) = 0;
00325 
00328     virtual unsigned int getCurrentTime() const = 0;
00329 
00337     virtual void setKeepAliveCheck(unsigned pingInterval,
00338                                    unsigned pongTimeout) = 0;
00339 
00341     const std::string& getServerName() const;
00342 
00344     unsigned getServerPort() const;
00346     void processRecvBuffer();
00347 
00348   private:
00351     bool process_recv_buffer_binary_();
00352 
00355     bool process_recv_buffer_text_();
00356 
00357   public:
00359     std::ostream& stream_get();
00360 
00362     static const char* CLIENTERROR_TAG;
00363 
00367     /* Inherited from LockableOstream libport::Lockable sendBufferLock;*/
00368   protected:
00370     void onConnection();
00371 
00373     virtual error_type onClose();
00374     bool closed_;
00375 
00377     virtual error_type effectiveSend(const void* buffer, size_t size) = 0;
00378 
00381     error_type effective_send(const void* buffer, size_t size);
00382 
00384     error_type effective_send(const char* buffer);
00385 
00387     error_type effective_send(const std::string& buffer);
00388 
00389     libport::Lockable listLock;
00390 
00392     UCallbackID addCallback(const char* tag, UCallbackWrapper& w);
00393 
00398     void clientError(std::string msg, int code = 0);
00399     void clientError(const char* msg = 0, int code = 0);
00400 
00402     std::string host_;
00404     unsigned port_;
00405 
00407     bool server_;
00408 
00410     size_t sendBufSize;
00411     size_t recvBufSize;
00412 
00416     error_type rc;
00417 
00419     char* recvBuffer;
00421     size_t recvBufferPosition;
00423     char* sendBuffer;
00424 
00427   public:
00432     const std::string& kernelVersion() const;
00434     int kernelMajor() const;
00436     int kernelMinor() const;
00440     virtual void waitForKernelVersion() const = 0;
00441 
00442   protected:
00445     std::string kernelVersion_;
00447     int kernelMajor_;
00449     int kernelMinor_;
00450 
00453     virtual UCallbackAction setVersion(const UMessage& msg);
00455 
00456   public:
00457     const std::string& connectionID() const;
00458 
00459   protected:
00460     std::string connectionID_;
00463     virtual UCallbackAction setConnectionID(const UMessage& msg);
00464 
00465   private:
00467     binaries_type bins;
00468 
00470     void bins_clear();
00471 
00473     void* binaryBuffer;
00475     size_t binaryBufferPosition;
00477     size_t binaryBufferLength;
00478 
00480     size_t parsePosition;
00482     bool inString;
00484     size_t nBracket;
00486     char* currentCommand;
00487 
00489     bool binaryMode;
00490 
00492     bool system;
00493 
00495     size_t endOfHeaderPosition;
00496     char currentTag[URBI_MAX_TAG_LENGTH];
00497 
00498     int currentTimestamp;
00499 
00500   protected:
00502     bool init_;
00503 
00504   public:
00505     int getCurrentTimestamp() const;
00506 
00507   private:
00508     typedef std::list<UCallbackInfo> callbacks_type;
00509     callbacks_type callbacks_;
00510 
00512     unsigned int counter_;
00513 
00516     std::ostream* stream_;
00517 
00518     friend class UClientStreambuf;
00519   };
00520 
00522   class UCallbackWrapper
00523   {
00524   public:
00525     virtual UCallbackAction operator ()(const UMessage&)=0;
00526     virtual ~UCallbackWrapper() {}
00527   };
00528 
00529 
00532   class UCallbackWrapperF
00533     : public UCallbackWrapper
00534   {
00535     UCallback cb;
00536   public:
00537     UCallbackWrapperF(UCallback cb) : cb(cb) {}
00538     virtual UCallbackAction operator ()(const UMessage& msg)
00539     {
00540       return cb(msg);
00541     }
00542     virtual ~UCallbackWrapperF() {}
00543   };
00544 
00545   class UCallbackWrapperCF
00546     : public UCallbackWrapper
00547   {
00548     UCustomCallback cb;
00549     void* cbData;
00550   public:
00551     UCallbackWrapperCF(UCustomCallback cb, void* cbData)
00552       : cb(cb), cbData(cbData)
00553     {}
00554     virtual UCallbackAction operator ()(const UMessage& msg)
00555     {
00556       return cb(cbData, msg);
00557     }
00558     virtual ~UCallbackWrapperCF() {}
00559   };
00560 
00561   template<class C>
00562   class UCallbackWrapper0 :
00563     public UCallbackWrapper
00564   {
00565     C& instance;
00566     UCallbackAction (C::*func)(const UMessage&);
00567   public:
00568     UCallbackWrapper0(C& instance, UCallbackAction (C::*func)(const UMessage&))
00569       : instance(instance), func(func)
00570     {}
00571     virtual UCallbackAction operator ()(const UMessage& msg)
00572     {
00573       return (instance.*func)(msg);
00574     }
00575     virtual ~UCallbackWrapper0() {}
00576   };
00577 
00578   template<class C, class P1>
00579   class UCallbackWrapper1
00580     : public UCallbackWrapper
00581   {
00582     C& instance;
00583     UCallbackAction (C::*funcPtr)(P1, const UMessage&);
00584     typename libport::traits::remove_reference<P1>::type p1;
00585   public:
00586     UCallbackWrapper1(C& instance,
00587                       UCallbackAction (C::*func)(P1, const UMessage&), P1 p1)
00588       : instance(instance), funcPtr(func), p1(p1)
00589     {}
00590     virtual UCallbackAction operator ()(const UMessage& msg)
00591     {
00592       return (instance.*funcPtr)(p1, msg);
00593     }
00594     virtual ~UCallbackWrapper1()
00595     {}
00596   };
00597 
00598   template<class C, class P1, class P2>
00599   class UCallbackWrapper2 : public UCallbackWrapper
00600   {
00601     C& instance;
00602     UCallbackAction (C::*func)(P1, P2, const UMessage&);
00603     typename libport::traits::remove_reference<P1>::type p1;
00604     typename libport::traits::remove_reference<P2>::type p2;
00605   public:
00606     UCallbackWrapper2(
00607       C& instance, UCallbackAction (C::*func)(P1, P2, const UMessage&),
00608       P1 p1, P2 p2)
00609       : instance(instance), func(func), p1(p1), p2(p2)
00610     {}
00611     virtual UCallbackAction operator ()(const UMessage& msg)
00612     {
00613       return (instance.*func)(p1, p2, msg);
00614     }
00615     virtual ~UCallbackWrapper2()
00616     {}
00617   };
00618 
00619 
00620   template<class C, class P1, class P2, class P3>
00621   class UCallbackWrapper3 : public UCallbackWrapper
00622   {
00623     C& instance;
00624     UCallbackAction (C::*func)(P1, P2, P3, const UMessage&);
00625     typename libport::traits::remove_reference<P1>::type p1;
00626     typename libport::traits::remove_reference<P2>::type p2;
00627     typename libport::traits::remove_reference<P3>::type p3;
00628   public:
00629     UCallbackWrapper3(
00630       C& instance, UCallbackAction (C::*func)(P1, P2, P3, const UMessage&),
00631       P1 p1, P2 p2, P3 p3)
00632       : instance(instance), func(func), p1(p1), p2(p2), p3(p3)
00633     {}
00634     virtual UCallbackAction operator ()(const UMessage& msg)
00635     {
00636       return (instance.*func)(p1, p2, p3, msg);
00637     }
00638     virtual ~UCallbackWrapper3()
00639     {}
00640   };
00641 
00642 
00643   template<class C, class P1, class P2, class P3, class P4>
00644   class UCallbackWrapper4 : public UCallbackWrapper
00645   {
00646     C& instance;
00647     UCallbackAction (C::*func)(P1, P2, P3, P4, const UMessage&);
00648     typename libport::traits::remove_reference<P1>::type p1;
00649     typename libport::traits::remove_reference<P2>::type p2;
00650     typename libport::traits::remove_reference<P3>::type p3;
00651     typename libport::traits::remove_reference<P4>::type p4;
00652   public:
00653     UCallbackWrapper4(
00654       C& instance, UCallbackAction(C::*func)(P1, P2, P3, P4, const UMessage&),
00655       P1 p1, P2 p2, P3 p3, P4 p4)
00656       : instance(instance), func(func), p1(p1), p2(p2), p3(p3), p4(p4)
00657     {}
00658     virtual UCallbackAction operator ()(const UMessage& msg)
00659     {
00660       return (instance.*func)(p1, p2, p3, p4, msg);
00661     }
00662     virtual ~UCallbackWrapper4()
00663     {}
00664   };
00666   //overloaded callback generators
00667 
00669 
00670 
00677   inline UCallbackWrapper& callback(UCallback cb)
00678   {
00679     return *new UCallbackWrapperF(cb);
00680   }
00681   inline UCallbackWrapper& callback(UCustomCallback cb, void* data)
00682   {
00683     return *new UCallbackWrapperCF(cb, data);
00684   }
00685 
00686 
00687   template<class C> UCallbackWrapper&
00688   callback(C& ref, UCallbackAction (C::*func)(const UMessage&))
00689   {
00690     return *new UCallbackWrapper0<C>(ref, func);
00691   }
00692 
00693   template<class C, class P1> UCallbackWrapper&
00694   callback(C& ref, UCallbackAction (C::*func)(P1, const UMessage&), P1 p1)
00695   {
00696     return *new UCallbackWrapper1<C, P1>(ref, func, p1);
00697   }
00698 
00699   template<class C, class P1, class P2>  UCallbackWrapper&
00700   callback(C& ref, UCallbackAction (C::*func)(P1, P2, const UMessage&),
00701            P1 p1, P2 p2)
00702   {
00703     return *new UCallbackWrapper2<C, P1, P2>(ref, func, p1, p2);
00704   }
00705 
00706   template<class C, class P1, class P2, class P3> UCallbackWrapper&
00707   callback(C& ref, UCallbackAction (C::*func)(P1, P2, P3, const UMessage&),
00708            P1 p1, P2 p2, P3 p3)
00709   {
00710     return *new UCallbackWrapper3<C, P1, P2, P3>(ref, func, p1, p2, p3);
00711   }
00712 
00713   template<class C, class P1, class P2, class P3, class P4>  UCallbackWrapper&
00714   callback(C& ref, UCallbackAction (C::*func)(P1, P2, P3, P4, const UMessage&),
00715            P1 p1, P2 p2, P3 p3, P4 p4)
00716   {
00717     return *new UCallbackWrapper4<C, P1, P2, P3, P4>(ref, func, p1, p2, p3, p4);
00718   }
00719 
00721 
00722 
00723   //old-style addCallback, deprecated
00724   template<class C>
00725   UCallbackID
00726   UAbstractClient::setCallback(C& ref,
00727                                UCallbackAction (C::*func)(const UMessage&),
00728                                const char* tag)
00729   {
00730     return addCallback(tag,*new UCallbackWrapper0<C>(ref, func));
00731   }
00732 
00733   template<class C, class P1>
00734   UCallbackID
00735   UAbstractClient::setCallback(C& ref,
00736                                UCallbackAction (C::*func)(P1 , const UMessage&),
00737                                P1 p1, const char* tag)
00738   {
00739     return addCallback(tag, *new UCallbackWrapper1<C, P1>(ref, func, p1));
00740   }
00741 
00742   template<class C, class P1, class P2>
00743   UCallbackID
00744   UAbstractClient::setCallback(
00745     C& ref, UCallbackAction (C::*func)(P1, P2, const UMessage&),
00746     P1 p1, P2 p2, const char* tag)
00747   {
00748     return addCallback(tag, *new UCallbackWrapper2<C, P1, P2>
00749                        (ref, func, p1, p2));
00750   }
00751 
00752   template<class C, class P1, class P2, class P3>
00753   UCallbackID
00754   UAbstractClient::setCallback(
00755     C& ref, UCallbackAction (C::*func)(P1, P2, P3, const UMessage&),
00756     P1 p1 , P2 p2, P3 p3, const char* tag)
00757   {
00758     return addCallback(tag, *new UCallbackWrapper3<C, P1, P2, P3>
00759                        (ref, func, p1, p2, p3));
00760   }
00761 
00762   template<class C, class P1, class P2, class P3, class P4>
00763   UCallbackID
00764   UAbstractClient::setCallback(
00765     C& ref, UCallbackAction (C::*func)(P1, P2, P3, P4, const UMessage&),
00766     P1 p1, P2 p2, P3 p3, P4 p4, const char* tag)
00767   {
00768     return addCallback(tag, *new UCallbackWrapper4<C, P1, P2, P3, P4>
00769                        (ref, func, p1, p2, p3, p4));
00770   }
00771 
00772 
00774 
00792 # ifndef URBI
00793 #  define URBI(A)                               \
00794   ::urbi::unarmorAndSend(#A)
00795 # endif
00796 
00797   static const char semicolon = ';';
00798   static const char pipe = '|';
00799   static const char parallel = '&';
00800   static const char comma = ',';
00801 
00803   URBI_SDK_API
00804   void execute(void);
00805 
00807   URBI_SDK_API
00808   void exit(int code);
00809 
00811   URBI_SDK_API
00812   UClient& connect(const std::string& host);
00813 
00816   URBI_SDK_API
00817   void disconnect(UClient &client);
00818 
00819   /*-----------------.
00820   | Default client.  |
00821   `-----------------*/
00822 
00824   URBI_SDK_API
00825   UClient* getDefaultClient();
00826 
00828   URBI_SDK_API
00829   UClient& get_default_client();
00830 
00832   URBI_SDK_API
00833   void setDefaultClient(UClient* cl);
00834 
00835   URBI_SDK_API
00836   std::string getClientConnectionID(const UAbstractClient* cli);
00837 
00838 # ifndef DISABLE_IOSTREAM
00839 
00840   URBI_SDK_API
00841   std::ostream&
00842   unarmorAndSend(const char* str,
00843                  UAbstractClient* c = (UAbstractClient*)getDefaultClient());
00844 # endif
00845 
00846   URBI_SDK_API
00847   extern UClient* defaultClient;
00848 
00850   URBI_SDK_API
00851   std::ostream& default_stream();
00852 
00853 } // namespace urbi
00854 
00855 # include <urbi/uabstractclient.hxx>
00856 
00857 #endif // URBI_UABSTRACTCLIENT_HH