Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

ionetstream.h

Go to the documentation of this file.
00001 #ifndef __NETSTREAM_H__
00002 #define __NETSTREAM_H__
00003 
00004 #include <cstdio>
00005 #include <cstring>
00006 
00007 #include <iostream>
00008 #include <iosfwd>
00009 #include <streambuf.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 #include <unistd.h>
00014 
00015 #include <string.h>
00016 #include <string>
00017 
00018 #define INVALID_SOCKET (~0)
00019 
00020 using namespace std;
00021 
00022 template <class charT, class traits>
00023 class basic_netbuf : public streambuf {
00024   public:
00025   //  Types:
00026   typedef charT                     char_type;
00027   typedef typename traits::int_type int_type;
00028   typedef typename traits::pos_type pos_type;
00029   typedef typename traits::off_type off_type;
00030   typedef traits                    traits_type;
00031   //Constructors/Destructors:
00032   basic_netbuf();
00033   basic_netbuf(const IPaddr& addr);
00034   basic_netbuf(const IPaddr::ipnum_t& host, const IPaddr::ipport_t port);
00035   basic_netbuf(const IPaddr::const_ipname_t& host, const IPaddr::ipport_t port);
00036   basic_netbuf(size_t buf_in_size, size_t buf_out_size);
00037   virtual ~basic_netbuf();
00038   
00039   
00040   
00041   //basic_netbuf Functions:
00042   public:
00043   virtual bool      open(const IPaddr& addr);
00044   virtual bool      open(const IPaddr::const_ipname_t& str);
00045   virtual bool      open(const IPaddr::ipnum_t& addr, const IPaddr::ipport_t& aPort);
00046   virtual bool      open(const IPaddr::const_ipname_t& ahost, unsigned int aPort) { return open(IPaddr(ahost,aPort)); }
00047   virtual bool      is_open() const { return (sock!=INVALID_SOCKET); }
00048   virtual void      close();
00049 
00050   virtual void      setEcho(bool val = true) { is_echoing = val; }
00051   virtual bool      getEcho() { return is_echoing; }
00052   protected:
00053     static void     printBuffer(const char* buf, int buflen, const char* header);
00054     void          Init() { Init(def_buf_in_size, def_buf_out_size); }
00055     void          Init(size_t insize, size_t outsize);
00056 
00057   
00058   //Inherited Functions:
00059   public:
00060   virtual void      in_sync(); //users shouldn't need to call this directly... but can if want to
00061   virtual void      out_flush();
00062 
00063   protected:
00064   //  lib.streambuf.virt.get Get area:
00065   virtual streamsize  showmanyc();
00066   //  virtual streamsize xsgetn(char_type* s, streamsize n);
00067   virtual int_type    underflow();
00068   virtual int_type    uflow();
00069   
00070   //  lib.streambuf.virt.pback Putback:
00071   //  virtual int_type pbackfail(int_type c = traits::eof() );
00072   //  lib.streambuf.virt.put Put area:
00073   //  virtual streamsize xsputn(const char_type* s, streamsize n);
00074   virtual int_type    overflow(int_type c  = traits::eof());
00075   
00076   //  lib.streambuf.virt.buffer Buffer management and positioning:
00077   //  virtual _Myt basic_netbuf<char_type, traits_type>* setbuf(char_type* s, streamsize n);
00078   //  virtual pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out);
00079   //  virtual pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out);
00080   virtual int     sync();
00081   //  lib.streambuf.virt.locales Locales:
00082   //  virtual void imbue(const locale &loc);
00083   //Data:
00084   protected:
00085   charT *buf_in, *buf_out;
00086   bool using_buf_in, using_buf_out;
00087   static const size_t def_buf_in_size;
00088   static const size_t def_buf_out_size;
00089   int sock;
00090   bool is_echoing;
00091 };
00092 template <class charT, class traits>
00093 const size_t basic_netbuf<charT,traits>::def_buf_in_size=1<<8;
00094 template <class charT, class traits>
00095 const size_t basic_netbuf<charT,traits>::def_buf_out_size=1<<12;
00096 
00097 
00098 template <class charT, class traits>
00099 class basic_iNetStream
00100   : public istream
00101 {
00102 public:
00103   typedef charT                     char_type;
00104   typedef typename traits::int_type int_type;
00105   typedef typename traits::pos_type pos_type;
00106   typedef typename traits::off_type off_type;
00107   typedef traits                    traits_type;
00108   //  lib.ifstream.cons Constructors:
00109   basic_iNetStream() : istream(&nb), nb() {}
00110   basic_iNetStream(const IPaddr::ipnum_t& host, const IPaddr::ipport_t port) : basic_iNetStream(&nb), nb(host,port) {}
00111   basic_iNetStream(const IPaddr::const_ipname_t& host, const IPaddr::ipport_t port) : basic_iNetStream(&nb), nb(host,port) {}
00112   basic_iNetStream(const IPaddr& addr) : istream(&nb), nb(addr) {}
00113   basic_iNetStream(size_t buf_in_size, size_t buf_out_size) : istream(&nb), nb(buf_in_size,buf_out_size) {}
00114   //  lib.ifstream.members Members:
00115   inline basic_netbuf<charT, traits>* rdbuf() const { return const_cast<basic_netbuf<charT, traits>*>(&nb); }
00116   
00117   inline bool     open(const IPaddr& addr) { return nb.open(addr); }
00118   inline bool     open(const IPaddr::const_ipname_t& str) { return nb.open(str); }
00119   inline bool     open(const IPaddr::ipnum_t& addr, const IPaddr::ipport_t& aPort) { return nb.open(addr,aPort); }
00120   inline bool     open(const IPaddr::const_ipname_t& ahost, unsigned int aPort) { return nb.open(ahost,aPort); }
00121   inline bool     is_open() const { return nb.is_open(); }
00122 /*  inline IPaddr::ipnum_t    remotehost() { return nb.remotehost(); }
00123   inline IPaddr::ipport_t   remoteport() { return nb.remoteport(); }
00124   inline IPaddr::ipnum_t    localhost() { return nb.localhost();}
00125   inline IPaddr::ipport_t   localport() { return nb.localport();}
00126 */
00127   inline void       close() { return nb.close(); }
00128   inline void       setEcho(bool val=true) { return nb.setEcho(val); }
00129   inline bool       getEcho() { return nb.getEcho(); }
00130 private:
00131   basic_netbuf<charT, traits> nb;
00132 };
00133 
00134 
00135 template <class charT, class traits>
00136 class basic_oNetStream
00137   : public ostream
00138 {
00139 public:
00140   typedef charT                     char_type;
00141   typedef typename traits::int_type int_type;
00142   typedef typename traits::pos_type pos_type;
00143   typedef typename traits::off_type off_type;
00144   typedef traits                    traits_type;
00145   //  lib.ifstream.cons Constructors:
00146   basic_oNetStream() : ostream(&nb), nb() {}
00147   basic_oNetStream(const IPaddr::ipnum_t& host, const IPaddr::ipport_t port) : basic_oNetStream(&nb), nb(host,port) {}
00148   basic_oNetStream(const IPaddr::const_ipname_t& host, const IPaddr::ipport_t port) : basic_oNetStream(&nb), nb(host,port) {}
00149   basic_oNetStream(const IPaddr& addr) : basic_oNetStream(&nb), nb(addr) {}
00150   basic_oNetStream(size_t buf_in_size, size_t buf_out_size) : ostream(&nb), nb(buf_in_size,buf_out_size) {}
00151   //  lib.ifstream.members Members:
00152   inline basic_netbuf<charT, traits>* rdbuf() const { return const_cast<basic_netbuf<charT, traits>*>(&nb); }
00153   
00154   inline bool     open(const IPaddr& addr) { return nb.open(addr); }
00155   inline bool     open(const IPaddr::const_ipname_t& str) { return nb.open(str); }
00156   inline bool     open(const IPaddr::ipnum_t& addr, const IPaddr::ipport_t& aPort) { return nb.open(addr,aPort); }
00157   inline bool     open(const IPaddr::const_ipname_t& ahost, unsigned int aPort) { return nb.open(ahost,aPort); }
00158   inline bool     is_open() const { return nb.is_open(); }
00159 /*  inline IPaddr::ipnum_t    remotehost() { return nb.remotehost(); }
00160   inline IPaddr::ipport_t   remoteport() { return nb.remoteport(); }
00161   inline IPaddr::ipnum_t    localhost() { return nb.localhost();}
00162   inline IPaddr::ipport_t   localport() { return nb.localport();}
00163 */
00164   inline void       close() { return nb.close(); }
00165   inline void       setEcho(bool val=true) { return nb.setEcho(val); }
00166   inline bool       getEcho() { return nb.getEcho(); }
00167 private:
00168   basic_netbuf<charT, traits> nb;
00169 };
00170 
00171 
00172 template <class charT, class traits>
00173 class basic_ioNetStream
00174   : public iostream
00175 {
00176 public:
00177   typedef charT                     char_type;
00178   typedef typename traits::int_type int_type;
00179   typedef typename traits::pos_type pos_type;
00180   typedef typename traits::off_type off_type;
00181   typedef traits                    traits_type;
00182   //  lib.ifstream.cons Constructors:
00183   basic_ioNetStream() : iostream(&nb), nb() {}
00184   basic_ioNetStream(const IPaddr& addr) : basic_ioNetStream(&nb), nb(addr) {}
00185   basic_ioNetStream(const IPaddr::ipnum_t& host, const IPaddr::ipport_t port) : basic_ioNetStream(&nb), nb(host,port) {}
00186   basic_ioNetStream(const IPaddr::const_ipname_t& host, const IPaddr::ipport_t port) : basic_ioNetStream(&nb), nb(host,port) {}
00187   basic_ioNetStream(size_t buf_in_size, size_t buf_out_size) : iostream(&nb), nb(buf_in_size,buf_out_size) {}
00188   //  lib.ifstream.members Members:
00189   inline basic_netbuf<charT, traits>* rdbuf() const { return const_cast<basic_netbuf<charT, traits>*>(&nb); }
00190   
00191   inline bool     open(const IPaddr& addr) { return nb.open(addr); }
00192   inline bool     open(const IPaddr::const_ipname_t& str) { return nb.open(str); }
00193   inline bool     open(const IPaddr::ipnum_t& addr, const IPaddr::ipport_t& aPort) { return nb.open(addr,aPort); }
00194   inline bool     open(const IPaddr::const_ipname_t& ahost, unsigned int aPort) { return nb.open(ahost,aPort); }
00195   inline bool     is_open() { return nb.is_open(); }
00196 /*  inline IPaddr::ipnum_t    remotehost() { return nb.remotehost(); }
00197   inline IPaddr::ipport_t   remoteport() { return nb.remoteport(); }
00198   inline IPaddr::ipnum_t    localhost() { return nb.localhost();}
00199   inline IPaddr::ipport_t   localport() { return nb.localport();}
00200 */
00201   inline void       close() { nb.close(); }
00202   inline void       setEcho(bool val=true) { return nb.setEcho(val); }
00203   inline bool       getEcho() { return nb.getEcho(); }
00204 private:
00205   basic_netbuf<charT, traits> nb;
00206 };
00207 
00208 template<class T>
00209 class char_traits {
00210 public:
00211   typedef T char_type;
00212   typedef int int_type;
00213   typedef T* pos_type;
00214   typedef unsigned int off_type;
00215   static void copy(pos_type dst, pos_type src, off_type size) {
00216     memcpy(dst,src,size);
00217   }
00218   static void move(pos_type dst, pos_type src, off_type size) {
00219     memmove(dst,src,size);
00220   }
00221   static int to_int_type(T c) { return c; }
00222   static int eof() { return EOF; }
00223 };
00224 
00225 typedef basic_netbuf<char, char_traits<char> > netbuf;
00226 typedef basic_iNetStream<char, char_traits<char> > iNetStream;
00227 typedef basic_oNetStream<char, char_traits<char> > oNetStream;
00228 typedef basic_ioNetStream<char, char_traits<char> > ioNetStream;
00229 
00230 
00231 
00232 
00233 template <class charT, class traits>
00234 basic_netbuf<charT,traits>::basic_netbuf() 
00235   : buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00236   sock(INVALID_SOCKET), is_echoing(false) {
00237   Init();
00238 }
00239 template <class charT, class traits>
00240 basic_netbuf<charT,traits>::basic_netbuf(const IPaddr& addr)
00241   : buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00242   sock(INVALID_SOCKET), is_echoing(false) {
00243   Init();
00244   open(addr);
00245 }
00246 
00247 template <class charT, class traits>
00248 basic_netbuf<charT,traits>::basic_netbuf(const IPaddr::ipnum_t& host, const IPaddr::ipport_t port)
00249   : buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00250   sock(INVALID_SOCKET), is_echoing(false) {
00251   Init();
00252   open(host,port);
00253 }
00254 
00255 template <class charT, class traits>
00256 basic_netbuf<charT,traits>::basic_netbuf(const IPaddr::const_ipname_t& host, const IPaddr::ipport_t port)
00257   : buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00258   sock(INVALID_SOCKET), is_echoing(false) {
00259   Init();
00260   open(host,port);
00261 }
00262 
00263 template <class charT, class traits>
00264 basic_netbuf<charT,traits>::basic_netbuf(size_t buf_in_size, size_t buf_out_size) 
00265   : buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00266   sock(INVALID_SOCKET), is_echoing(false) {
00267   Init();
00268 }
00269 
00270 template <class charT, class traits>
00271 basic_netbuf<charT,traits>::~basic_netbuf() {
00272   if(using_buf_in)
00273     delete [] buf_in;
00274   if(using_buf_out)
00275     delete [] buf_out;
00276 }
00277 
00278 template<class charT, class traits>
00279 void
00280 basic_netbuf<charT,traits>::Init(size_t insize, size_t outsize) {
00281   buf_in = new charT[insize];
00282   buf_out = new charT[outsize];
00283   using_buf_in = using_buf_out = true;
00284   setg(buf_in,buf_in+insize,buf_in+insize);
00285   setp(buf_out,buf_out+outsize);
00286 //  cout << "Buffer is:" << endl;
00287 //  cout << "Input buffer: " << egptr() << " to " << egptr() << " at " << gptr() << endl;
00288 //  cout << "Output buffer: " << pbase() << " to " << epptr() << " at " << pptr() << endl;
00289 }
00290 
00291 template <class charT, class traits>
00292 bool
00293 basic_netbuf<charT,traits>::open(const IPaddr& addr) {
00294   if(addr.get_num())
00295     return open(addr.get_num(),addr.get_port());
00296   return false;
00297 }
00298 
00299 template <class charT, class traits>
00300 bool
00301 basic_netbuf<charT,traits>::open(const IPaddr::const_ipname_t& str) {
00302   const char*const colon = strrchr(str,':');
00303   if(colon==NULL)
00304     return false;
00305   char* tmp = new char[strlen(str)];
00306   char * d = tmp;
00307   for(const char * s=str; s!=colon; s++,d++)
00308     *d=*s;
00309   *d='\0';
00310   IPaddr::ipport_t port = atoi(colon+1);
00311   bool res = open(tmp,port);
00312   delete [] tmp;
00313   return res;
00314 }
00315 
00316 template <class charT, class traits>
00317 bool
00318 basic_netbuf<charT,traits>::open(const IPaddr::ipnum_t& addr, const IPaddr::ipport_t& aPort) { //depends on timeout
00319   struct sockaddr_in server;
00320   
00321   memset((char *) &server, sizeof(server), 0);
00322   server.sin_family      = AF_INET;
00323   server.sin_addr.s_addr = addr;
00324   server.sin_port        = htons(aPort);
00325 
00326   // create socket
00327   sock = socket(AF_INET, SOCK_STREAM, 0);
00328   if(sock < 1) {
00329     cout << "NetClient error: socket failed to create stream socket" << endl;
00330     sock = INVALID_SOCKET;
00331     return false;
00332   }
00333 
00334   // connect to server.
00335   int err = connect(sock, (struct sockaddr *) &server, sizeof(server));
00336   if(err < 0) {
00337     cout << "NetClient error: connect failed to connect to requested address" << endl;
00338     sock = INVALID_SOCKET;
00339     return false;
00340   }
00341 
00342   return true;
00343 }
00344 
00345 template <class charT, class traits>
00346 void
00347 basic_netbuf<charT,traits>::close() {
00348   cout << "close called" << endl;
00349   if(!is_open())
00350     return;
00351   if(sock != INVALID_SOCKET) {
00352     cout << "closing" << endl;
00353     ::close(sock);
00354     cout << "closed" << endl;
00355     sock = INVALID_SOCKET;
00356   }
00357 }
00358 
00359 template <class charT, class traits>
00360 void
00361 basic_netbuf<charT,traits>::printBuffer(const char *buf, int buflen, const char *header) {
00362   int line_begin = 1;
00363   for(int i = 0; i < buflen; i++) {
00364     if(buf[i] == '\n') {
00365       line_begin = 1;
00366       fputc('\n', stderr);
00367     } else {
00368       if(line_begin) fputs(header, stderr);
00369       line_begin = 0;
00370       fputc(buf[i], stderr);
00371     }
00372   }
00373 }
00374 
00375 template <class charT, class traits>
00376 void
00377 basic_netbuf<charT,traits>::in_sync() {
00378   if(!is_open()) {
00379     cout << "NetClient error: must open connection before reading from it" << endl;
00380     return;
00381   }
00382   if(gptr()>egptr())
00383     gbump( egptr()-gptr() );
00384   unsigned long n = gptr()-eback()-1;
00385   charT * temp_buf = new char[n*sizeof(charT)];
00386   unsigned int used = read(sock, temp_buf, n*sizeof(charT));
00387   if(used<=0) {
00388     cout << "NetClient error: connection dropped" << endl;
00389     delete [] temp_buf;
00390     close();
00391     return;
00392   }
00393   if(is_echoing)
00394     printBuffer(temp_buf, used, "NetClient: recv: ");
00395   //TODO - what if sizeof(charT)>1?  We might need to worry about getting/storing partial char
00396   used/=sizeof(charT);
00397   size_t remain = egptr()-eback()-used;
00398   traits::move(eback(),egptr()-remain,remain);
00399   traits::copy(egptr()-used,temp_buf,used);
00400   delete [] temp_buf;
00401   gbump( -used );
00402 }
00403 
00404 template <class charT, class traits>
00405 void
00406 basic_netbuf<charT,traits>::out_flush() {
00407   if(!is_open()) {
00408     cout << "NetClient error: must open connection before writing to it" << endl;
00409     return;
00410   }
00411   size_t n = (pptr()-pbase())*sizeof(charT);
00412   if(n==0)
00413     return;
00414   size_t total = 0;
00415   while(total<n) {
00416     int sent = write(sock, pbase()+total, n-total);
00417     if(sent < 0) {
00418       cout << "NetClient error: send error" << endl;
00419       perror("send");
00420       close();
00421       return;
00422     }
00423     if(is_echoing)
00424       printBuffer(pbase()+total, sent, "NetClient: sent: ");
00425     total += sent;
00426   }
00427   total/=sizeof(charT);
00428   n/=sizeof(charT);
00429   if(total!=n)
00430     traits::move(pbase(),pbase()+total,n-total);
00431   pbump( -total );
00432 }
00433 
00434 
00435 template <class charT, class traits>
00436 inline streamsize
00437 basic_netbuf<charT, traits>::showmanyc() {
00438   return (gptr()<egptr())?(egptr()-gptr()):0;
00439 }
00440 
00441 template <class charT, class traits>
00442 inline typename basic_netbuf<charT, traits>::int_type
00443 basic_netbuf<charT, traits>::underflow() {
00444   in_sync();
00445   if(gptr()<egptr())
00446     return traits::to_int_type(*gptr());
00447 //  if( cur_input()!=kOTInvalidEndpointRef )
00448 //    return uflow();
00449 //  cout << "UNDERFLOW" << endl;
00450   return traits::eof();
00451 }
00452 
00453 template <class charT, class traits>
00454 inline typename basic_netbuf<charT, traits>::int_type
00455 basic_netbuf<charT, traits>::uflow() {
00456   in_sync();
00457   if(gptr()<egptr()) {
00458     int_type ans = traits::to_int_type(*gptr());
00459     gbump(1);
00460     return ans;
00461   }
00462 //  cout << "UNDERFLOW" << endl;
00463   return traits::eof();
00464 }
00465 
00466 template <class charT, class traits>
00467 inline typename basic_netbuf<charT, traits>::int_type
00468 basic_netbuf<charT, traits>::overflow(int_type c) { 
00469   out_flush();
00470   *pptr() = c;
00471   pbump(1);
00472   return is_open()?c:traits::eof();
00473 }
00474 
00475 template <class charT, class traits>
00476 inline int
00477 basic_netbuf<charT, traits>::sync() {
00478   out_flush();
00479   in_sync();
00480   return is_open()?0:-1;
00481 }
00482 
00483 
00484 #endif

Tekkotsu v1.4
Generated Sat Jul 19 00:06:30 2003 by Doxygen 1.3.2