00001 #ifndef INCLUDED_netstream_h_
00002 #define INCLUDED_netstream_h_
00003
00004 #ifdef PLATFORM_APERIOS
00005 #error netstream not yet supported on AIBO/Aperios
00006 #endif
00007
00008 #include <cstdio>
00009 #include <cstring>
00010 #include <iostream>
00011 #include <iosfwd>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <ctype.h>
00015 #include <unistd.h>
00016 #include <stdexcept>
00017
00018 #include <errno.h>
00019 #include <signal.h>
00020
00021 #include <sys/types.h>
00022 #include <sys/socket.h>
00023 #include <netinet/in.h>
00024 #include <arpa/inet.h>
00025 #include <netdb.h>
00026 #include <cstring>
00027 #include <string>
00028 #include <poll.h>
00029
00030 #define OTAssert(str, b) if(!b) std::cerr << "ERR " << __FILE__ << '(' << __LINE__ << "): " << str << std::endl;
00031
00032 class IPaddr {
00033 public:
00034 typedef std::string ipname_t;
00035 typedef unsigned int ipnum_t;
00036 typedef unsigned short ipport_t;
00037 const static unsigned int maxHostNameLen;
00038
00039 IPaddr();
00040 explicit IPaddr(const ipnum_t& num);
00041 explicit IPaddr(const ipname_t& name);
00042 IPaddr(const ipnum_t& num, const ipport_t& port);
00043 IPaddr(const ipname_t& name, const ipport_t& port);
00044 virtual ~IPaddr() {}
00045
00046 virtual bool set_num(const ipnum_t& num);
00047 virtual bool set_name(const ipname_t& name);
00048 virtual bool set_addr(const ipnum_t& num, const ipport_t& port) { return set_num(num) && set_port(port); }
00049 virtual bool set_addr(const ipname_t& name, const ipport_t& port) { return set_name(name) && set_port(port); }
00050 virtual bool set_port(const ipport_t& port) { ipport=port; server.sin_port=htons(port); return true; }
00051 virtual ipnum_t get_num() const { return ntohl(server.sin_addr.s_addr); }
00052 virtual const ipname_t& get_name() const { return ipname; }
00053 virtual ipname_t get_display_num() const;
00054 virtual ipname_t get_rname() const;
00055 virtual ipport_t get_port() const { return ipport; }
00056
00057 virtual const sockaddr_in& get_addr() const { return server; }
00058 protected:
00059 void Init();
00060
00061 struct sockaddr_in server;
00062 ipname_t ipname;
00063 ipport_t ipport;
00064 };
00065
00066
00067 template <class charT, class traits=std::char_traits<charT> >
00068 class basic_netbuf : public std::basic_streambuf<charT,traits> {
00069 public:
00070
00071 typedef charT char_type;
00072 typedef typename traits::int_type int_type;
00073 typedef typename traits::pos_type pos_type;
00074 typedef typename traits::off_type off_type;
00075 typedef traits traits_type;
00076
00077
00078 basic_netbuf();
00079 basic_netbuf(const IPaddr& addr, bool datagram=false);
00080 basic_netbuf(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram=false);
00081 basic_netbuf(size_t buf_in_size, size_t buf_out_size);
00082 virtual ~basic_netbuf();
00083
00084
00085
00086
00087 public:
00088 virtual bool open(const IPaddr& addr, bool datagram=false);
00089 virtual bool open(const IPaddr::ipname_t& str, bool datagram=false);
00090 virtual bool open(const IPaddr::ipname_t& ahost, unsigned int aPort, bool datagram=false) { return open(IPaddr(ahost,aPort),datagram); }
00091 virtual bool listen(unsigned int aPort, bool datagram=false) { return listen(IPaddr(ntohl(INADDR_ANY),aPort),datagram); }
00092 virtual bool listen(const IPaddr& addr, bool datagram=false);
00093 virtual bool is_open() const { return (sock!=INVALID_SOCKET); }
00094 virtual void update_status();
00095 virtual void close();
00096 virtual void reset() { close(); reconnect(); }
00097
00098 virtual int adoptFD(int fd) { int old=sock; sock=fd; update_status(); return old; }
00099
00100 virtual void setReconnect(bool doReconnect) { autoReconnect = doReconnect; }
00101 virtual bool getReconnect() const { return autoReconnect; }
00102
00103 virtual void setEcho(bool val = true) { is_echoing = val; }
00104 virtual bool getEcho() { return is_echoing; }
00105
00106 virtual const IPaddr& getPeerAddress() const { return peerAddress; }
00107 virtual const IPaddr& getLocalAddress() const { return localAddress; }
00108
00109 protected:
00110 virtual void reconnect();
00111 static void printBuffer(const char* buf, int buflen, const char* header, const char* prefix);
00112 void Init() { Init(def_buf_in_size, def_buf_out_size); }
00113 void Init(size_t insize, size_t outsize);
00114
00115
00116
00117
00118 public:
00119 virtual void in_sync();
00120 virtual void out_flush();
00121
00122 protected:
00123 using std::basic_streambuf<charT,traits>::eback;
00124 using std::basic_streambuf<charT,traits>::gptr;
00125 using std::basic_streambuf<charT,traits>::egptr;
00126 using std::basic_streambuf<charT,traits>::gbump;
00127 using std::basic_streambuf<charT,traits>::pbase;
00128 using std::basic_streambuf<charT,traits>::pptr;
00129 using std::basic_streambuf<charT,traits>::epptr;
00130 using std::basic_streambuf<charT,traits>::pbump;
00131
00132
00133 virtual std::streamsize showmanyc();
00134
00135 virtual int_type underflow();
00136 virtual int_type uflow();
00137
00138
00139
00140
00141
00142 virtual int_type overflow(int_type c = traits::eof());
00143
00144
00145
00146 virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out);
00147 virtual pos_type seekpos(pos_type sp, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) { return seekoff(sp,std::ios_base::beg,which); }
00148 virtual int sync();
00149
00150
00151
00152
00153 protected:
00154 static const int INVALID_SOCKET=-1;
00155 charT *buf_in, *buf_out;
00156 bool using_buf_in, using_buf_out;
00157 static const size_t def_buf_in_size;
00158 static const size_t def_buf_out_size;
00159 int sock;
00160 bool canRead;
00161 bool canWrite;
00162 bool is_echoing;
00163 bool autoReconnect;
00164 bool sockFromServer;
00165
00166 IPaddr peerAddress;
00167 IPaddr localAddress;
00168 IPaddr tgtAddress;
00169 bool isDatagram;
00170
00171 private:
00172 basic_netbuf(const basic_netbuf&);
00173 basic_netbuf& operator=(const basic_netbuf&);
00174 };
00175 template <class charT, class traits>
00176 const size_t basic_netbuf<charT,traits>::def_buf_in_size=(1<<14)-28;
00177 template <class charT, class traits>
00178 const size_t basic_netbuf<charT,traits>::def_buf_out_size=(1<<14)-28;
00179
00180
00181 template <class charT, class traits=std::char_traits<charT> >
00182 class basic_netbuf_interface {
00183 public:
00184 basic_netbuf_interface() : nb() {}
00185 basic_netbuf_interface(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram) : nb(host,port,datagram) {}
00186 basic_netbuf_interface(const IPaddr& addr, bool datagram) : nb(addr,datagram) {}
00187 basic_netbuf_interface(size_t buf_in_size, size_t buf_out_size) : nb(buf_in_size,buf_out_size) {}
00188
00189 inline bool open(const IPaddr& addr, bool datagram=false) { return nb.open(addr,datagram); }
00190 inline bool open(const IPaddr::ipname_t& str, bool datagram=false) { return nb.open(str,datagram); }
00191 inline bool open(const IPaddr::ipname_t& ahost, unsigned int aPort, bool datagram=false) { return nb.open(ahost,aPort,datagram); }
00192 inline bool listen(unsigned int aPort, bool datagram=false) { return nb.listen(aPort,datagram); }
00193 inline bool listen(const IPaddr& addr, bool datagram=false) { return nb.listen(addr,datagram); }
00194
00195 inline bool is_open() const { return nb.is_open(); }
00196 inline void update_status() { nb.update_status(); }
00197
00198 inline void close() { nb.close(); }
00199 inline void reset() { nb.close(); nb.reconnect(); }
00200
00201 inline void setReconnect(bool reconnect) { nb.setReconnect(reconnect); }
00202 inline bool getReconnect() const { return nb.getReconnect(); }
00203
00204 inline void setEcho(bool val=true) { nb.setEcho(val); }
00205 inline bool getEcho() { return nb.getEcho(); }
00206
00207 inline const IPaddr& getPeerAddress() const { return nb.getPeerAddress(); }
00208 inline const IPaddr& getLocalAddress() const { return nb.getLocalAddress(); }
00209
00210 inline basic_netbuf<charT, traits>* rdbuf() const { return const_cast<basic_netbuf<charT, traits>*>(&nb); }
00211
00212 protected:
00213 ~basic_netbuf_interface() {}
00214 basic_netbuf<charT, traits> nb;
00215 };
00216
00217 template <class charT, class traits=std::char_traits<charT> >
00218 class basic_inetstream : public virtual basic_netbuf_interface<charT,traits>, public std::basic_istream<charT,traits>
00219 {
00220 public:
00221 typedef charT char_type;
00222 typedef typename traits::int_type int_type;
00223 typedef typename traits::pos_type pos_type;
00224 typedef typename traits::off_type off_type;
00225 typedef traits traits_type;
00226
00227 basic_inetstream() : basic_netbuf_interface<charT,traits>(), std::basic_istream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00228 basic_inetstream(const IPaddr& addr, bool datagram=false) : basic_netbuf_interface<charT,traits>(addr,datagram), std::basic_istream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00229 basic_inetstream(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram=false) : basic_netbuf_interface<charT,traits>(host,port,datagram), std::basic_istream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00230 basic_inetstream(size_t buf_in_size, size_t buf_out_size) : basic_netbuf_interface<charT,traits>(buf_in_size,buf_out_size), std::basic_istream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00231 using basic_netbuf_interface<charT,traits>::rdbuf;
00232 };
00233
00234
00235 template <class charT, class traits=std::char_traits<charT> >
00236 class basic_onetstream : public virtual basic_netbuf_interface<charT,traits>, public std::basic_ostream<charT,traits>
00237 {
00238 public:
00239 typedef charT char_type;
00240 typedef typename traits::int_type int_type;
00241 typedef typename traits::pos_type pos_type;
00242 typedef typename traits::off_type off_type;
00243 typedef traits traits_type;
00244
00245 basic_onetstream() : basic_netbuf_interface<charT,traits>(), std::basic_ostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00246 basic_onetstream(const IPaddr& addr, bool datagram=false) : basic_netbuf_interface<charT,traits>(addr,datagram), std::basic_ostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00247 basic_onetstream(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram=false) : basic_netbuf_interface<charT,traits>(host,port,datagram), std::basic_ostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00248 basic_onetstream(size_t buf_in_size, size_t buf_out_size) : basic_netbuf_interface<charT,traits>(buf_in_size,buf_out_size) , std::basic_ostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()){}
00249 using basic_netbuf_interface<charT,traits>::rdbuf;
00250 };
00251
00252
00253 template <class charT, class traits=std::char_traits<charT> >
00254 class basic_ionetstream : public virtual basic_netbuf_interface<charT,traits>, public std::basic_iostream<charT,traits>
00255 {
00256 public:
00257 typedef charT char_type;
00258 typedef typename traits::int_type int_type;
00259 typedef typename traits::pos_type pos_type;
00260 typedef typename traits::off_type off_type;
00261 typedef traits traits_type;
00262
00263 basic_ionetstream() : basic_netbuf_interface<charT,traits>(), std::basic_iostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00264 basic_ionetstream(const IPaddr& addr, bool datagram=false) : basic_netbuf_interface<charT,traits>(addr,datagram), std::basic_iostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00265 basic_ionetstream(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram=false) : basic_netbuf_interface<charT,traits>(host,port,datagram), std::basic_iostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()) {}
00266 basic_ionetstream(size_t buf_in_size, size_t buf_out_size) : basic_netbuf_interface<charT,traits>(buf_in_size,buf_out_size) , std::basic_iostream<charT,traits>(basic_netbuf_interface<charT,traits>::rdbuf()){}
00267 using basic_netbuf_interface<charT,traits>::rdbuf;
00268 };
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 typedef basic_netbuf<char, std::char_traits<char> > netbuf;
00289 typedef basic_inetstream<char, std::char_traits<char> > inetstream;
00290 typedef basic_onetstream<char, std::char_traits<char> > onetstream;
00291 typedef basic_ionetstream<char, std::char_traits<char> > ionetstream;
00292
00293
00294
00295
00296 template <class charT, class traits>
00297 basic_netbuf<charT,traits>::basic_netbuf()
00298 : std::basic_streambuf<charT,traits>(), buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00299 sock(INVALID_SOCKET), canRead(false), canWrite(false), is_echoing(false), autoReconnect(false), sockFromServer(),
00300 peerAddress(), localAddress(), tgtAddress(), isDatagram() {
00301 Init();
00302 }
00303 template <class charT, class traits>
00304 basic_netbuf<charT,traits>::basic_netbuf(const IPaddr& addr, bool datagram)
00305 : std::basic_streambuf<charT,traits>(), buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00306 sock(INVALID_SOCKET), canRead(false), canWrite(false), is_echoing(false), autoReconnect(false), sockFromServer(),
00307 peerAddress(), localAddress(), tgtAddress(), isDatagram() {
00308 Init();
00309 open(addr,datagram);
00310 }
00311
00312 template <class charT, class traits>
00313 basic_netbuf<charT,traits>::basic_netbuf(const IPaddr::ipname_t& host, const IPaddr::ipport_t port, bool datagram)
00314 : std::basic_streambuf<charT,traits>(), buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00315 sock(INVALID_SOCKET), canRead(false), canWrite(false), is_echoing(false), autoReconnect(false), sockFromServer(),
00316 peerAddress(), localAddress(), tgtAddress(), isDatagram() {
00317 Init();
00318 open(host,port,datagram);
00319 }
00320
00321 template <class charT, class traits>
00322 basic_netbuf<charT,traits>::basic_netbuf(size_t buf_in_size, size_t buf_out_size)
00323 : std::basic_streambuf<charT,traits>(), buf_in(NULL), buf_out(NULL), using_buf_in(false), using_buf_out(false),
00324 sock(INVALID_SOCKET), canRead(false), canWrite(false), is_echoing(false), autoReconnect(false), sockFromServer(),
00325 peerAddress(), localAddress(), tgtAddress(), isDatagram() {
00326 Init();
00327 }
00328
00329 template <class charT, class traits>
00330 basic_netbuf<charT,traits>::~basic_netbuf() {
00331 autoReconnect=false;
00332 if(is_open()) {
00333 out_flush();
00334 close();
00335 }
00336 if(using_buf_in)
00337 delete [] buf_in;
00338 if(using_buf_out)
00339 delete [] buf_out;
00340 }
00341
00342 template<class charT, class traits>
00343 void
00344 basic_netbuf<charT,traits>::Init(size_t insize, size_t outsize) {
00345 buf_in = new charT[insize];
00346 buf_out = new charT[outsize];
00347 using_buf_in = using_buf_out = true;
00348 setg(buf_in,buf_in+insize,buf_in+insize);
00349 setp(buf_out,buf_out+outsize);
00350
00351
00352
00353 }
00354
00355 template<class charT, class traits>
00356 void
00357 basic_netbuf<charT,traits>::update_status() {
00358 pollfd pfd;
00359 pfd.fd=sock;
00360 pfd.events = POLLIN | POLLOUT;
00361 if(poll(&pfd,1,0)==-1)
00362 perror("basic_netbuf poll");
00363 if(pfd.revents&(POLLERR|POLLHUP|POLLNVAL)) {
00364 close();
00365 if(autoReconnect)
00366 reconnect();
00367 if(is_open())
00368 update_status();
00369 } else {
00370 canRead = (pfd.revents&POLLIN);
00371 canWrite = (pfd.revents&POLLOUT);
00372 }
00373 }
00374
00375 template <class charT, class traits>
00376 bool
00377 basic_netbuf<charT,traits>::open(const IPaddr& addr, bool datagram) {
00378 if(is_open())
00379 close();
00380 tgtAddress=addr;
00381
00382 while(!is_open()) {
00383
00384
00385 int opsock = ::socket(AF_INET, datagram ? (int)SOCK_DGRAM : (int)SOCK_STREAM, 0);
00386 if(opsock < 1) {
00387 perror("netstream socket()");
00388
00389 return false;
00390 }
00391 int on=1;
00392 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 ) {
00393 perror("netstream SO_REUSEADDR setsockopt");
00394 }
00395 if(datagram) {
00396 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_BROADCAST, ( const char* ) &on, sizeof ( on ) ) == -1 ) {
00397 perror("netstream SO_BROADCAST setsockopt");
00398 }
00399 const int sndbuf=(epptr()-pbase());
00400 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_SNDBUF, ( const char* ) &sndbuf, sizeof ( sndbuf ) ) == -1 ) {
00401 perror("netstream SO_SNDBUF setsockopt");
00402 }
00403 }
00404
00405
00406 sockaddr_in server = addr.get_addr();
00407 int err = ::connect(opsock, (const sockaddr *) &server, sizeof(server));
00408 if(err < 0) {
00409
00410
00411 ::close(opsock);
00412 if(!autoReconnect)
00413 return false;
00414 usleep(750000);
00415 } else {
00416 sock=opsock;
00417 sockFromServer=false;
00418 isDatagram=datagram;
00419 socklen_t server_size=sizeof(server);
00420 err = ::getpeername(sock, reinterpret_cast<sockaddr *>(&server), &server_size);
00421 if(err<0)
00422 perror("netstream getpeername");
00423 else {
00424 peerAddress.set_addr(ntohl(server.sin_addr.s_addr), ntohs(server.sin_port));
00425 }
00426 err = ::getsockname(sock, reinterpret_cast<sockaddr *>(&server), &server_size);
00427 if(err<0)
00428 perror("netstream getsockname");
00429 else {
00430 localAddress.set_addr(ntohl(server.sin_addr.s_addr), ntohs(server.sin_port));
00431 }
00432
00433
00434 }
00435 }
00436
00437 return true;
00438 }
00439
00440 template <class charT, class traits>
00441 bool
00442 basic_netbuf<charT,traits>::listen(const IPaddr& addr, bool datagram) {
00443 if(is_open())
00444 close();
00445 tgtAddress=addr;
00446
00447
00448 int opsock = ::socket(AF_INET, datagram ? (int)SOCK_DGRAM : (int)SOCK_STREAM, 0);
00449 if(opsock < 1) {
00450 perror("netstream socket");
00451
00452 return false;
00453 }
00454 int on=1;
00455 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 ) {
00456 perror("netstream SO_REUSEADDR setsockopt");
00457 }
00458 if(datagram) {
00459 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_BROADCAST, ( const char* ) &on, sizeof ( on ) ) == -1 ) {
00460 perror("netstream SO_BROADCAST setsockopt");
00461 }
00462 const int sndbuf=(epptr()-pbase());
00463 if ( ::setsockopt ( opsock, SOL_SOCKET, SO_SNDBUF, ( const char* ) &sndbuf, sizeof ( sndbuf ) ) == -1 ) {
00464 perror("netstream SO_SNDBUF setsockopt");
00465 }
00466 }
00467
00468 sockaddr_in server = addr.get_addr();
00469
00470
00471 if(::bind(opsock, (const sockaddr *) &server, sizeof(server)) != 0) {
00472
00473 ::close(opsock);
00474 return false;
00475 }
00476
00477
00478 if(::listen(opsock, 1) != 0) {
00479 perror("netstream listen");
00480 ::close(opsock);
00481 return false;
00482 }
00483
00484 while(!is_open()) {
00485
00486 sockaddr tmp;
00487 socklen_t tmplen;
00488 int sock2 = ::accept(opsock, &tmp, &tmplen);
00489 if(sock2 < 0) {
00490 perror("netstream accept");
00491 if(!autoReconnect) {
00492 ::close(opsock);
00493 return false;
00494 }
00495 } else {
00496
00497 ::close(opsock);
00498
00499 sock=sock2;
00500 sockFromServer=true;
00501 isDatagram=datagram;
00502 socklen_t server_size=sizeof(server);
00503 int err = ::getpeername(sock, reinterpret_cast<sockaddr *>(&server), &server_size);
00504 if(err<0)
00505 perror("netstream getpeername");
00506 else {
00507 peerAddress.set_addr(ntohl(server.sin_addr.s_addr), ntohs(server.sin_port));
00508 }
00509 err = ::getsockname(sock, reinterpret_cast<sockaddr *>(&server), &server_size);
00510 if(err<0)
00511 perror("netstream getsockname");
00512 else {
00513 localAddress.set_addr(ntohl(server.sin_addr.s_addr), ntohs(server.sin_port));
00514 }
00515
00516
00517 }
00518 }
00519
00520 return true;
00521 }
00522
00523 template <class charT, class traits>
00524 bool
00525 basic_netbuf<charT,traits>::open(const IPaddr::ipname_t& str, bool datagram) {
00526 std::string::size_type colon = str.rfind(':');
00527 if(colon==std::string::npos)
00528 return false;
00529 IPaddr::ipport_t port = atoi(str.substr(colon+1).c_str());
00530 bool res = open(str.substr(0,colon),port,datagram);
00531 return res;
00532 }
00533
00534 template <class charT, class traits>
00535 void
00536 basic_netbuf<charT,traits>::close() {
00537
00538 if(!is_open())
00539 return;
00540
00541 ::close(sock);
00542
00543 sock = INVALID_SOCKET;
00544 }
00545
00546 template <class charT, class traits>
00547 void
00548 basic_netbuf<charT,traits>::reconnect() {
00549 if(sockFromServer) {
00550 listen(tgtAddress,isDatagram);
00551 } else {
00552 open(tgtAddress,isDatagram);
00553 }
00554 }
00555
00556 template <class charT, class traits>
00557 void
00558 basic_netbuf<charT,traits>::printBuffer(const char *buf, int buflen, const char *header, const char *prefix) {
00559 fputs(header, stderr);
00560 int line_begin = 0;
00561 for(int i = 0; i < buflen; i++) {
00562 if(buf[i] == '\n') {
00563 line_begin = 1;
00564 fputc('\n', stderr);
00565 } else {
00566 if(line_begin) fputs(prefix, stderr);
00567 line_begin = 0;
00568 fputc(buf[i], stderr);
00569 }
00570 }
00571 }
00572
00573 template <class charT, class traits>
00574 void
00575 basic_netbuf<charT,traits>::in_sync() {
00576 if(!is_open()) {
00577
00578 return;
00579 }
00580 update_status();
00581 if(!is_open())
00582 return;
00583 if(gptr()>egptr())
00584 gbump( egptr()-gptr() );
00585 if(gptr()==eback()) {
00586
00587 return;
00588 }
00589 unsigned long n = gptr()-eback()-1;
00590 charT * temp_buf = new char[n*sizeof(charT)];
00591 ssize_t used = read(sock, temp_buf, n*sizeof(charT));
00592 while(used==0 || used==(ssize_t)-1) {
00593
00594 close();
00595 if(autoReconnect)
00596 reconnect();
00597 if(!is_open()) {
00598 delete [] temp_buf;
00599 return;
00600 }
00601 used = read(sock, temp_buf, n*sizeof(charT));
00602 }
00603 if(is_echoing)
00604 printBuffer(temp_buf, used, "netstream receiving: ", "< ");
00605
00606 OTAssert("Partial char was dropped!",(ssize_t)((used/sizeof(charT))*sizeof(charT))==used);
00607 used/=sizeof(charT);
00608 size_t remain = egptr()-eback()-used;
00609 traits::move(eback(),egptr()-remain,remain);
00610 traits::copy(egptr()-used,temp_buf,used);
00611 delete [] temp_buf;
00612 gbump( -used );
00613 }
00614
00615 template <class charT, class traits>
00616 void
00617 basic_netbuf<charT,traits>::out_flush() {
00618 if(!is_open()) {
00619
00620 return;
00621 }
00622 update_status();
00623 if(!is_open())
00624 return;
00625 size_t n = (pptr()-pbase())*sizeof(charT);
00626 if(n==0)
00627 return;
00628 size_t total = 0;
00629 while(total<n) {
00630 int sent = write(sock, pbase()+total, n-total);
00631 while(sent < 0) {
00632
00633
00634 close();
00635 if(autoReconnect)
00636 reconnect();
00637 if(!is_open())
00638 return;
00639 sent = write(sock, pbase()+total, n-total);
00640 }
00641
00642
00643 if(is_echoing)
00644 printBuffer(pbase()+total, sent, "netstream sending: ", "> ");
00645 total += sent;
00646 }
00647 total/=sizeof(charT);
00648 n/=sizeof(charT);
00649 if(total!=n)
00650 traits::move(pbase(),pbase()+total,n-total);
00651 pbump( -total );
00652 }
00653
00654
00655 template <class charT, class traits>
00656 inline std::streamsize
00657 basic_netbuf<charT, traits>::showmanyc() {
00658 update_status();
00659 return (is_open() && canRead) ? 1 : 0;
00660
00661 }
00662
00663 template <class charT, class traits>
00664 inline typename basic_netbuf<charT, traits>::int_type
00665 basic_netbuf<charT, traits>::underflow() {
00666 in_sync();
00667 if(gptr()<egptr())
00668 return traits::to_int_type(*gptr());
00669
00670 return traits::eof();
00671 }
00672
00673 template <class charT, class traits>
00674 inline typename basic_netbuf<charT, traits>::int_type
00675 basic_netbuf<charT, traits>::uflow() {
00676 in_sync();
00677 if(gptr()<egptr()) {
00678 int_type ans = traits::to_int_type(*gptr());
00679 gbump(1);
00680 return ans;
00681 }
00682
00683 return traits::eof();
00684 }
00685
00686 template <class charT, class traits>
00687 inline typename basic_netbuf<charT, traits>::int_type
00688 basic_netbuf<charT, traits>::overflow(int_type c) {
00689 out_flush();
00690 if(!is_open())
00691 return traits::eof();
00692 if(!traits::eq_int_type(c, traits::eof())) {
00693 *pptr() = c;
00694 pbump(1);
00695 }
00696 return traits::not_eof(c);
00697 }
00698
00699
00700
00701
00702
00703
00704
00705 template <class charT, class traits>
00706 typename basic_netbuf<charT, traits>::pos_type
00707 basic_netbuf<charT, traits>::seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which ) {
00708 bool dog = (which & std::ios_base::in);
00709 bool dop = (which & std::ios_base::out);
00710 charT* newg, *newp;
00711 int gb,pb;
00712 switch(way) {
00713 case std::ios_base::beg: {
00714 newg = eback()+off;
00715 gb = newg-gptr();
00716 newp = pbase()+off;
00717 pb = newp-pptr();
00718 } break;
00719 case std::ios_base::cur: {
00720 newg = gptr()+off;
00721 newp = pptr()+off;
00722 gb=pb=off;
00723 } break;
00724 case std::ios_base::end: {
00725 newg = egptr()+off;
00726 gb = newg-gptr();
00727 newp = epptr()+off;
00728 pb = newp-pptr();
00729 } break;
00730 default:
00731 return pos_type(off_type(-1));
00732 }
00733 if(dog && (newg<eback() || egptr()<newg) || dop && (newp<pbase() || epptr()<newp))
00734 return pos_type(off_type(-1));
00735 if(dog)
00736 gbump(gb);
00737 if(dop) {
00738 pbump(pb);
00739 return pptr()-pbase();
00740 } else {
00741 return gptr()-eback();
00742 }
00743 }
00744
00745 template <class charT, class traits>
00746 inline int
00747 basic_netbuf<charT, traits>::sync() {
00748 out_flush();
00749
00750 return is_open()?0:-1;
00751 }
00752
00753 #undef OTAssert
00754
00755 #endif