skstream
skstream.h
00001 /**************************************************************************
00002  FreeSockets - Portable C++ classes for IP(sockets) applications. (v0.3)
00003  Copyright (C) 2000-2001 Rafael Guterres Jeffman
00004            (C) 2002-2006 Alistair Riddoch
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 **************************************************************************/
00021 
00029 #ifndef RGJ_FREE_STREAM_H_
00030 #define RGJ_FREE_STREAM_H_
00031 
00032 #include <iostream>
00033 
00034 #include <skstream/sksocket.h>
00035 
00036 // To not include full <cstdio>, we define only EOF
00037 #ifndef EOF
00038 #define EOF (-1)
00039 #endif
00040 
00042 // class socketbuf
00044 
00046 class socketbuf : public std::streambuf {
00047 private:
00048   std::streambuf::char_type *_buffer;
00049 
00050 protected:
00051   SOCKET_TYPE _socket;
00052 
00053   timeval _underflow_timeout;
00054   timeval _overflow_timeout;
00055 
00056 private:
00058   socketbuf(const socketbuf&);
00060   socketbuf& operator=(const socketbuf&);
00061 
00062 protected:
00063   bool Timeout;
00064 
00065 public:
00069   explicit socketbuf(SOCKET_TYPE sock, std::streamsize insize = 0x8000,
00070                                        std::streamsize outsize = 0x8000);
00074   socketbuf(SOCKET_TYPE sock, std::streambuf::char_type * buf,
00075                               std::streamsize length);
00076 
00078   virtual ~socketbuf();
00079 
00081   void setSocket(SOCKET_TYPE sock);
00082 
00084   SOCKET_TYPE getSocket() const {
00085       return _socket; 
00086   }
00087 
00091   void setReadTimeout(unsigned sec, unsigned usec=0) {
00092     _underflow_timeout.tv_sec  = sec;
00093     _underflow_timeout.tv_usec = usec;
00094   }
00095 
00099   void setWriteTimeout(unsigned sec, unsigned usec=0) {
00100     _overflow_timeout.tv_sec  = sec;
00101     _overflow_timeout.tv_usec = usec;
00102   }
00103 
00104   void setTimeout(unsigned sec, unsigned usec=0) {
00105     setWriteTimeout(sec, usec);
00106   }
00107 
00109   bool timeout() const {
00110     return Timeout;
00111   }
00112 
00113 protected:
00115   virtual int_type overflow(int_type nCh = traits_type::eof()) = 0;
00117   virtual int_type underflow() = 0;
00118 
00120   virtual int sync();
00121 
00125   std::streambuf * setbuf(std::streambuf::char_type * buf, std::streamsize len);
00126 };
00127 
00129 class stream_socketbuf : public socketbuf {
00130 public:
00134   explicit stream_socketbuf(SOCKET_TYPE sock,
00135                             std::streamsize insize = 0x8000,
00136                             std::streamsize outsize = 0x8000);
00140   stream_socketbuf(SOCKET_TYPE sock, std::streambuf::char_type * buf,
00141                                      std::streamsize length);
00142 
00144   virtual ~stream_socketbuf();
00145 
00146 protected:
00148   virtual int_type overflow(int_type nCh = traits_type::eof());
00150   virtual int_type underflow();
00151 
00152 };
00153 
00155 class dgram_socketbuf : public socketbuf {
00156 public:
00160   explicit dgram_socketbuf(SOCKET_TYPE sock, std::streamsize insize = 0x8000,
00161                                              std::streamsize outsize = 0x8000);
00165   dgram_socketbuf(SOCKET_TYPE sock,
00166                   std::streambuf::char_type * buf,
00167                   std::streamsize length);
00168 
00170   virtual ~dgram_socketbuf();
00171 
00172   bool setTarget(const std::string& address, unsigned port, int proto);
00173 
00174   void setOutpeer(const sockaddr_storage & peer) { 
00175     out_peer = peer; 
00176   }
00177 
00178   const sockaddr_storage & getOutpeer() const {
00179     return out_peer; 
00180   }
00181 
00182   const sockaddr_storage & getInpeer() const { 
00183     return in_peer; 
00184   }
00185 
00186   SOCKLEN getOutpeerSize() const {
00187     return out_p_size;
00188   }
00189 
00190   SOCKLEN getInpeerSize() const {
00191     return in_p_size;
00192   }
00193 
00194 protected:
00196   sockaddr_storage out_peer;
00198   sockaddr_storage in_peer;
00200   SOCKLEN out_p_size;
00202   SOCKLEN in_p_size;
00203 
00205   virtual int_type overflow(int_type nCh = traits_type::eof());
00207   virtual int_type underflow();
00208 
00209 };
00210 
00212 // class socket_stream
00214 
00216 class basic_socket_stream : public basic_socket, public std::iostream {
00217 protected:
00218   socketbuf & _sockbuf;
00219   int m_protocol;
00220 
00221 public:
00223   basic_socket_stream(socketbuf & buffer, int proto = FreeSockets::proto_IP);
00224 
00225   // Destructor
00226   virtual ~basic_socket_stream();
00227 
00228   bool fail();
00229 
00230   bool operator!() {
00231     return fail();
00232   }
00233 
00234   bool timeout() const {
00235     return _sockbuf.timeout();
00236   }
00237 
00238   virtual SOCKET_TYPE getSocket() const;
00239 
00240   // Needs to be virtual to handle in-progress connect()'s for
00241   // tcp sockets
00242   virtual void close();
00243 
00244   void shutdown(bool wr_only = false);
00245 
00246   void setSocket(SOCKET_TYPE sock) {
00247     _sockbuf.setSocket(sock);
00248   }
00249 
00250   void setTimeout(unsigned sec, unsigned usec=0) { 
00251     _sockbuf.setTimeout(sec,usec); 
00252   }
00253 
00254   int getProtocol() const { 
00255     return m_protocol; 
00256   }
00257 };
00258 
00260 // class stream_socket_stream
00262 
00263 class stream_socket_stream : public basic_socket_stream {
00264 private:
00265   stream_socket_stream(const stream_socket_stream&);
00266   stream_socket_stream& operator=(const stream_socket_stream& socket);
00267 
00268 protected:
00269   SOCKET_TYPE _connecting_socket;
00270 
00271   stream_socket_stream();
00272   stream_socket_stream(SOCKET_TYPE socket);
00273 public:
00274   virtual ~stream_socket_stream();
00275   
00276   virtual void close();
00277   virtual SOCKET_TYPE getSocket() const;
00278 
00279   bool connect_pending() const {
00280     return (_connecting_socket != INVALID_SOCKET);
00281   }
00282 };
00283 
00285 // class tcp_socket_stream
00287 
00288 struct addrinfo;
00289 
00291 class tcp_socket_stream : public stream_socket_stream {
00292 private:
00293   tcp_socket_stream(const tcp_socket_stream&);
00294 
00295   tcp_socket_stream& operator=(const tcp_socket_stream& socket);
00296 
00297   struct addrinfo * _connecting_address;
00298   struct addrinfo * _connecting_addrlist;
00299 
00300 public:
00301   tcp_socket_stream();
00302   tcp_socket_stream(SOCKET_TYPE socket);
00303 
00304   tcp_socket_stream(const std::string& address, int service,
00305                     bool nonblock = false);
00306 
00307   tcp_socket_stream(const std::string& address, int service,
00308                     unsigned int milliseconds);
00309 
00310   virtual ~tcp_socket_stream();
00311 
00312   int open(const std::string& address, int service, bool nonblock = false);
00313   int open(const std::string& address, int service, unsigned int milliseconds);
00314   int open(struct addrinfo *, bool nonblock = false);
00315   int open_next();
00316 
00317   const std::string getRemoteHost(bool lookup = false) const;
00318   const std::string getRemoteService(bool lookup = false) const;
00319   bool isReady(unsigned int milliseconds = 0);
00320 };
00321 
00323 class dgram_socket_stream : public basic_socket_stream {
00324 private:
00325   dgram_socket_stream(const dgram_socket_stream&);
00326 
00327   dgram_socket_stream& operator=(const dgram_socket_stream& socket);
00328 
00329 protected:
00330   dgram_socketbuf & dgram_sockbuf;
00331 
00332   int bindToIpService(int service, int type, int protocol);
00333 
00334 public:
00335   dgram_socket_stream();
00336 
00337   virtual ~dgram_socket_stream();
00338 
00339   bool setTarget(const std::string& address, unsigned port) { 
00340     return dgram_sockbuf.setTarget(address, port, m_protocol); 
00341   }
00342 
00343   void setOutpeer(const sockaddr_storage& peer) { 
00344     return dgram_sockbuf.setOutpeer(peer); 
00345   }
00346 
00347   const sockaddr_storage & getOutpeer() const { 
00348     return dgram_sockbuf.getOutpeer(); 
00349   }
00350 
00351   const sockaddr_storage & getInpeer() const { 
00352     return dgram_sockbuf.getInpeer(); 
00353   }
00354 
00355   SOCKLEN getOutpeerSize() const {
00356     return dgram_sockbuf.getOutpeerSize();
00357   }
00358 
00359   SOCKLEN getInpeerSize() const {
00360     return dgram_sockbuf.getInpeerSize();
00361   }
00362 };
00363 
00364 
00366 // class udp_socket_stream
00368 
00370 class udp_socket_stream : public dgram_socket_stream {
00371 private:
00372   udp_socket_stream(const udp_socket_stream&);
00373 
00374   udp_socket_stream& operator=(const udp_socket_stream& socket);
00375 
00376 public:
00377   udp_socket_stream();
00378 
00379   virtual ~udp_socket_stream();
00380 
00381   int open(int service);
00382 };
00383 
00384 #ifdef SOCK_RAW
00385 
00387 // class raw_socket_stream
00389 
00391 class raw_socket_stream : public dgram_socket_stream {
00392 private:
00393   raw_socket_stream(const raw_socket_stream&);
00394 
00395   raw_socket_stream& operator=(const raw_socket_stream& socket);
00396 
00397 public:
00398   raw_socket_stream(FreeSockets::IP_Protocol proto=FreeSockets::proto_RAW);
00399 
00400   virtual ~raw_socket_stream();
00401 
00402   void setProtocol(FreeSockets::IP_Protocol proto);
00403 
00404   bool setTarget(const std::string& address, unsigned port) { 
00405     return dgram_sockbuf.setTarget(address, port, m_protocol); 
00406   }
00407 
00408   bool setBroadcast(bool opt=false);
00409 };
00410 
00411 #endif // SOCK_RAW
00412 
00413 #endif // RGJ_FREE_STREAM_H_
00414