home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 400_01 / socketpp-1.5 / sockstream.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  13.7 KB  |  620 lines

  1. // sockstream.C -*- C++ -*- socket library
  2. // Copyright (C) 1992,1993 Gnanasekaran Swaminathan <gs4t@virginia.edu>
  3. // 
  4. // Permission is granted to use at your own risk and distribute this software
  5. // in source and binary forms provided the above copyright
  6. // notice and this paragraph are preserved on all copies.
  7. // This software is provided "as is" with no express or implied warranty.
  8. //
  9. // Version: 31Jan93 1.3
  10. //
  11. // You can simultaneously read and write into
  12. // a sockbuf just like you can listen and talk
  13. // through a telephone. Hence, the read and the
  14. // write buffers are different. That is, they do not
  15. // share the same memory.
  16. // 
  17. // Read:
  18. // gptr() points to the start of the get area.
  19. // The unread chars are gptr() - egptr().
  20. // base() points to the read buffer
  21. // 
  22. // eback() is set to base() so that pbackfail()
  23. // is called only when there is no place to
  24. // putback a char. And pbackfail() always returns EOF.
  25. // 
  26. // Write:
  27. // pptr() points to the start of the put area
  28. // The unflushed chars are pbase() - pptr()
  29. // pbase() points to the write buffer.
  30. // epptr() points to the end of the write buffer.
  31. // 
  32. // Output is flushed whenever one of the following conditions
  33. // holds:
  34. // (1) pptr() == epptr()
  35. // (2) EOF is written
  36. // (3) linebuffered and '\n' is written
  37. // 
  38. // Unbuffered:
  39. // Input buffer size is assumed to be of size 1 and output
  40. // buffer is of size 0. That is, egptr() <= base()+1 and
  41. // epptr() == pbase().
  42.  
  43.  
  44. #include <sockstream.h>
  45. #include <builtin.h>
  46. #include <sys/time.h>
  47.  
  48. #ifndef BUFSIZ
  49. #define BUFSIZ 1024
  50. #endif
  51.  
  52. #ifdef FD_ZERO
  53. #undef FD_ZERO
  54. #define FD_ZERO(p) (memset ((p), 0, sizeof *(p)))
  55. #endif
  56.  
  57. extern "C" {
  58.     int    socket        (int, int, int);
  59.     int    listen        (int sock, int num);
  60.     int    bind        (int sock, void* addr, int addrsize);
  61.     int    connect        (int sock, void* addr, int addrsize);
  62.     int    accept        (int sock, void* addr, int* addrsize);
  63.     int    getsockopt    (int sock, int level, int option_name,
  64.              void* option_value, int* optionlen);
  65.     int    setsockopt    (int sock, int level, int option_name,
  66.              void* option_value, int optionlen);
  67.     int    shutdown    (int sock, int how);
  68.     
  69.     int    recv        (int sock, void* buf, int len, int msgf);
  70.     int    recvfrom    (int sock, void* buf, int len, int msgf,
  71.              void* fromaddr, int* fromaddrlen);
  72.     int    recvmsg        (int sock, msghdr*, int msgf);
  73.     
  74.     int    send        (int sock, const void* buf, int len, int msgf);
  75.     int    sendto        (int sock, const void* buf, int len, int msgf,
  76.              void* toaddr, int toaddrlen);
  77.     int    sendmsg        (int sock, const msghdr*, int msgf);
  78.     
  79.     int    select        (int fd, fd_set* frd, fd_set* fwr, fd_set* fex,
  80.              timeval* timeout);
  81. }
  82.  
  83. void sockAddr::error (const char* msg) const
  84. {
  85.     extern int errno;
  86.  
  87.     if (errno)
  88.     perror (msg);
  89.     (*lib_error_handler) ("class sockAddr: ", msg);
  90. }
  91.  
  92. sockbuf::sockbuf (int soc)
  93. : rep (new sockcnt (soc, 1)),
  94.   stmo (-1), rtmo (-1)
  95. {
  96.     xsetflags (_S_LINE_BUF);
  97. }
  98.  
  99. sockbuf::sockbuf (int domain, type st, int proto)
  100. : rep (new sockcnt (::socket (domain, st, proto), 1)),
  101.   stmo (-1), rtmo (-1)
  102. {
  103.     if (rep->sock == -1) perror ("sockbuf::sockbuf");
  104.     xsetflags (_S_LINE_BUF);
  105. }
  106.  
  107. sockbuf::sockbuf (const sockbuf& sb)
  108. : rep (sb.rep), stmo (sb.stmo), rtmo (sb.rtmo)
  109. {
  110.     rep->cnt++;
  111.     xsetflags (_S_LINE_BUF);
  112. }
  113.  
  114. sockbuf& sockbuf::operator = (sockbuf& sb)
  115. {
  116.     if (this != &sb && rep != sb.rep && rep->sock != sb.rep->sock) {
  117.     this->sockbuf::~sockbuf();
  118.     rep  = sb.rep; stmo = sb.stmo; rtmo = sb.rtmo;
  119.     rep->cnt++;
  120.     xflags (sb.xflags ());
  121.     }
  122.     return *this;
  123. }
  124.  
  125. sockbuf::~sockbuf ()
  126. {
  127.     overflow (EOF);
  128.     if (rep->cnt == 1 && !(xflags () & _S_DELETE_DONT_CLOSE)) close ();
  129.     delete [] base ();
  130.     if (--rep->cnt == 0) delete rep;
  131. }
  132.  
  133. sockbuf* sockbuf::open (type, int)
  134. {
  135.     return 0;
  136. }
  137.  
  138. sockbuf* sockbuf::close()
  139. {
  140.     if (rep->sock >= 0) {
  141.     if (::close (rep->sock) == -1) return this;
  142.     rep->sock = -1;
  143.     }
  144.     return 0;
  145. }
  146.  
  147. _G_ssize_t sockbuf::sys_read (char* buf, _G_ssize_t len)
  148.      // return EOF on eof, 0 on timeout, and # of chars read on success
  149. {
  150.     return read (buf, len);
  151. }
  152.  
  153. _G_ssize_t sockbuf::sys_write (const void* buf, long len)
  154.      // return written_length; < len indicates error
  155. {
  156.     return write (buf, len);
  157. }
  158.  
  159. int sockbuf::flush_output()
  160.      // return 0 when there is nothing to flush or when the flush is a success
  161.      // return EOF when it could not flush
  162. {
  163.     if (pptr () <= pbase ()) return 0;
  164.     if (!(xflags () & _S_NO_WRITES)) {
  165.     int wlen   = pptr () - pbase ();
  166.     int wval   = sys_write (pbase (), wlen);
  167.     int status = (wval == wlen)? 0: EOF;
  168.     if (unbuffered()) setp (pbase (), pbase ());
  169.     else setp (pbase (), pbase () + BUFSIZ);
  170.     return status;
  171.     }
  172.     return EOF;
  173. }
  174.  
  175. int sockbuf::sync ()
  176. {
  177.     return flush_output ();
  178. }
  179.  
  180. int sockbuf::doallocate ()
  181.      // return 1 on allocation and 0 if there is no need
  182. {
  183.     if (!base ()) {
  184.     char*    buf = new char[2*BUFSIZ];
  185.     setb (buf, buf+BUFSIZ, 0);
  186.     setg (buf, buf, buf);
  187.     
  188.     buf += BUFSIZ;
  189.     setp (buf, buf+BUFSIZ);
  190.     return 1;
  191.     }
  192.     return 0;
  193. }
  194.  
  195. int sockbuf::underflow ()
  196. {
  197.     if (xflags () & _S_NO_READS) return EOF;
  198.     if (gptr () < egptr ()) return *(unsigned char*)gptr ();
  199.     
  200.     if (!base () && doallocate () != 1) return EOF;
  201.     int bufsz = unbuffered () ? 1: BUFSIZ;
  202.     int rval = sys_read (base (), bufsz);
  203.     if (rval == EOF) {
  204.     xsetflags (_S_EOF_SEEN);
  205.     return EOF;
  206.     }else if (rval == 0)
  207.     return EOF;
  208.     setg (eback (), base (), base () + rval);
  209.     return *(unsigned char*)gptr ();
  210. }
  211.  
  212. int sockbuf::overflow (int c)
  213.      // if c == EOF, return flush_output();
  214.      // if c == '\n' and linebuffered, insert c and
  215.      // return (flush_output()==EOF)? EOF: c;     
  216.      // otherwise insert c into the buffer and return c
  217. {
  218.     if (c == EOF) { return flush_output (); }
  219.     if (xflags () & _S_NO_WRITES) return EOF;
  220.     
  221.     if (!pbase () && doallocate () != 1) return EOF;
  222.     
  223.     xput_char (c);
  224.     if ((unbuffered () || linebuffered () && c == '\n' || pptr () >= epptr ())
  225.     && flush_output () == EOF)
  226.     return EOF;
  227.     return (unsigned char)c;
  228. }
  229.  
  230. int sockbuf::xsputn (const char* s, int n)
  231. {
  232.     if (n <= 0) return 0;
  233.     const unsigned char* p = (const unsigned char*)s;
  234.     for (int i=0; i<n; i++, p++) {
  235.     if (*p == '\n') {
  236.         if (overflow (*p) == EOF) return i;
  237.     } else
  238.         if (sputc (*p) == EOF) return i;
  239.     }
  240.     return n;
  241. }
  242.  
  243. void sockbuf::bind (sockAddr& sa)
  244. {
  245.     if (::bind (rep->sock, sa, sa.size ()) == -1) {
  246.     error ("sockbuf::bind");
  247.     }
  248. }
  249.  
  250. void sockbuf::connect (sockAddr& sa)
  251. {
  252.     if (::connect(rep->sock, sa, sa.size()) == -1) {
  253.     error ("sockbuf::connect");
  254.     }
  255. }
  256.  
  257. void sockbuf::listen (int num)
  258. {
  259.     if (::listen (rep->sock, num) == -1) {
  260.     error ("sockbuf::listen");
  261.     }
  262. }
  263.  
  264. sockbuf    sockbuf::accept (sockAddr& sa)
  265. {
  266.     int len = sa.size ();
  267.     int soc = ::accept (rep->sock, sa, &len);
  268.     if (soc == -1)
  269.     error ("sockbuf::accept");
  270.     return soc;
  271. }
  272.  
  273. sockbuf    sockbuf::accept ()
  274. {
  275.     int soc = ::accept (rep->sock, 0, 0);
  276.     if (soc == -1) {
  277.     error ("sockbuf::accept");
  278.     }
  279.     return soc;
  280. }
  281.  
  282. int sockbuf::read (void* buf, int len)
  283. {
  284.     if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  285.     
  286.     int    rval;
  287.     if ((rval = ::read (rep->sock, buf, len)) == -1)
  288.     error("sockbuf::read");
  289.     return (rval==0) ? EOF: rval;
  290. }
  291.  
  292. int sockbuf::recv (void* buf, int len, int msgf)
  293. {
  294.     if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  295.     
  296.     int    rval;
  297.     if ((rval = ::recv (rep->sock, buf, len, msgf)) == -1)
  298.     error ("sockbuf::recv");
  299.     return (rval==0) ? EOF: rval;
  300. }
  301.  
  302. int sockbuf::recvfrom (sockAddr& sa, void* buf, int len, int msgf)
  303. {
  304.     if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  305.     
  306.     int    rval;
  307.     int    sa_len = sa.size ();
  308.     
  309.     if ((rval = ::recvfrom (rep->sock, buf, len, msgf, sa, &sa_len)) == -1)
  310.     error ("sockbuf::recvfrom");
  311.     return (rval==0) ? EOF: rval;
  312. }
  313.  
  314. int sockbuf::recvmsg (msghdr* msg, int msgf)
  315. {
  316.     if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  317.     
  318.     int    rval;
  319.     if ((rval = ::recvmsg(rep->sock, msg, msgf)) == -1)
  320.     error ("sockbuf::recvmsg");
  321.     return (rval==0)? EOF: rval;
  322. }
  323.  
  324. int sockbuf::write(const void* buf, int len)
  325. {
  326.     if (stmo != -1 && is_writeready (stmo)==0) return 0;
  327.     
  328.     int    wlen=0;
  329.     while(len>0) {
  330.     int    wval;
  331.     if ((wval = ::write (rep->sock, buf, len)) == -1) {
  332.         error ("sockbuf::write");
  333.         return wval;
  334.     }
  335.     len -= wval;
  336.     wlen += wval;
  337.     }
  338.     return wlen; // == len if every thing is all right
  339. }
  340.  
  341. int sockbuf::send (const void* buf, int len, int msgf)
  342. {
  343.     if (stmo != -1 && is_writeready (stmo)==0) return 0;
  344.     
  345.     int    wlen=0;
  346.     while(len>0) {
  347.     int    wval;
  348.     if ((wval = ::send (rep->sock, buf, len, msgf)) == -1) {
  349.         error ("sockbuf::send");
  350.         return wval;
  351.     }
  352.     len -= wval;
  353.     wlen += wval;
  354.     }
  355.     return wlen;
  356. }
  357.  
  358. int sockbuf::sendto (sockAddr& sa, const void* buf, int len, int msgf)
  359. {
  360.     if (stmo != -1 && is_writeready (stmo)==0) return 0;
  361.     
  362.     int    wlen=0;
  363.     while(len>0) {
  364.     int    wval;
  365.     if ((wval = ::sendto (rep->sock, buf, len,
  366.                   msgf, sa, sa.size())) == -1) {
  367.         error ("sockbuf::sendto");
  368.         return wval;
  369.     }
  370.     len -= wval;
  371.     wlen += wval;
  372.     }
  373.     return wlen;
  374. }
  375.  
  376. int sockbuf::sendmsg (const msghdr* msg, int msgf)
  377. {
  378.     if (stmo != -1 && is_writeready (stmo)==0) return 0;
  379.     
  380.     int    wval;
  381.     if ((wval = ::sendmsg (rep->sock, msg, msgf)) == -1)
  382.     error("sockbuf::sendmsg");
  383.     return wval;
  384. }
  385.  
  386. int sockbuf::sendtimeout (int wp)
  387. {
  388.     int oldstmo = stmo;
  389.     stmo = (wp < 0) ? -1: wp;
  390.     return oldstmo;
  391. }
  392.  
  393. int sockbuf::recvtimeout (int wp)
  394. {
  395.     int oldrtmo = rtmo;
  396.     rtmo = (wp < 0) ? -1: wp;
  397.     return oldrtmo;
  398. }
  399.  
  400. int sockbuf::is_readready (int wp_sec, int wp_usec) const
  401. {
  402.     fd_set fds;
  403.     FD_ZERO (&fds);
  404.     FD_SET (rep->sock, &fds);
  405.     
  406.     timeval tv;
  407.     tv.tv_sec  = wp_sec;
  408.     tv.tv_usec = wp_usec;
  409.     
  410.     int ret = select (rep->sock+1, &fds, 0, 0, (wp_sec == -1) ? 0: &tv);
  411.     if (ret == -1) {
  412.     error ("sockbuf::readready");
  413.     return 0;
  414.     }
  415.     return ret;
  416. }
  417.  
  418. int sockbuf::is_writeready (int wp_sec, int wp_usec) const
  419. {
  420.     fd_set fds;
  421.     FD_ZERO (&fds);
  422.     FD_SET (rep->sock, &fds);
  423.     
  424.     timeval tv;
  425.     tv.tv_sec  = wp_sec;
  426.     tv.tv_usec = wp_usec;
  427.     
  428.     int ret = select (rep->sock+1, 0, &fds, 0, (wp_sec == -1) ? 0: &tv);
  429.     if (ret == -1) {
  430.     error ("Select::operator ()");
  431.     return 0;
  432.     }
  433.     return ret;
  434. }
  435.  
  436. int sockbuf::is_exceptionpending (int wp_sec, int wp_usec) const
  437. {
  438.     fd_set fds;
  439.     FD_ZERO (&fds);
  440.     FD_SET  (rep->sock, &fds);
  441.     
  442.     timeval tv;
  443.     tv.tv_sec = wp_sec;
  444.     tv.tv_usec = wp_usec;
  445.     
  446.     int ret = select (rep->sock+1, 0, 0, &fds, (wp_sec == -1) ? 0: &tv);
  447.     if (ret == -1) {
  448.     error ("Select::operator ()");
  449.     return 0;
  450.     }
  451.     return ret;
  452. }
  453.  
  454. void sockbuf::shutdown (shuthow sh)
  455. {
  456.     switch (sh) {
  457.     case shut_read:
  458.     xsetflags(_S_NO_READS);
  459.     break;
  460.     case shut_write:
  461.     xsetflags(_S_NO_WRITES);
  462.     break;
  463.     case shut_readwrite:
  464.     xsetflags(_S_NO_READS|_S_NO_WRITES);
  465.     break;
  466.     }
  467.     if (::shutdown(rep->sock, sh) == -1)
  468.     error("sockbuf::shutdown");
  469. }
  470.  
  471. int sockbuf::getopt (option op, void* buf, int len, level l) const
  472. {
  473.     int    rlen = len;
  474.     if (::getsockopt (rep->sock, l, op, buf, &rlen) == -1)
  475.     perror ("sockbuf::getopt");
  476.     return rlen;
  477. }
  478.  
  479. void sockbuf::setopt (option op, void* buf, int len, level l) const
  480. {
  481.     if (::setsockopt (rep->sock, l, op, buf, len) == -1)
  482.     perror ("sockbuf::setopt");
  483. }
  484.  
  485. sockbuf::type sockbuf::gettype () const
  486. {
  487.     int    ty=0;
  488.     getopt (so_type, &ty, sizeof (ty));
  489.     return sockbuf::type(ty);
  490. }
  491.  
  492. int sockbuf::clearerror () const
  493. {
  494.     int     err=0;
  495.     getopt (so_error, &err, sizeof (err));
  496.     return err;
  497. }
  498.  
  499. int sockbuf::debug (int opt) const
  500. {
  501.     int old=0;
  502.     getopt (so_debug, &old, sizeof (old));
  503.     if (opt != -1)
  504.     setopt (so_debug, &opt, sizeof (opt));
  505.     return old;
  506. }
  507.  
  508. int sockbuf::reuseaddr (int opt) const
  509. {
  510.     int old=0;
  511.     getopt (so_reuseaddr, &old, sizeof (old));
  512.     if (opt != -1)
  513.     setopt (so_reuseaddr, &opt, sizeof (opt));
  514.     return old;
  515. }
  516.  
  517. int sockbuf::keepalive (int opt) const
  518. {
  519.     int old=0;
  520.     getopt (so_keepalive, &old, sizeof (old));
  521.     if (opt != -1)
  522.     setopt (so_keepalive, &opt, sizeof (opt));
  523.     return old;
  524. }
  525.  
  526. int sockbuf::dontroute (int opt) const
  527. {
  528.     int old=0;
  529.     getopt (so_dontroute, &old, sizeof (old));
  530.     if (opt != -1)
  531.     setopt (so_dontroute, &opt, sizeof (opt));
  532.     return old;
  533. }
  534.  
  535. int sockbuf::broadcast (int opt) const
  536. {
  537.     int old=0;
  538.     getopt (so_broadcast, &old, sizeof (old));
  539.     if (opt != -1)
  540.     setopt (so_broadcast, &opt, sizeof (opt));
  541.     return old;
  542. }
  543.  
  544. int sockbuf::oobinline (int opt) const
  545. {
  546.     int old=0;
  547.     getopt (so_oobinline, &old, sizeof (old));
  548.     if (opt != -1)
  549.     setopt (so_oobinline, &opt, sizeof (opt));
  550.     return old;
  551. }
  552.  
  553. int sockbuf::linger (int opt) const
  554. {
  555.     socklinger    old;
  556.     getopt (so_linger, &old, sizeof (old));
  557.     if (opt > 0) {
  558.     socklinger nw = { 1, opt };
  559.     setopt (so_linger, &nw, sizeof (nw));
  560.     }else if (opt == 0) {
  561.     socklinger nw = { 0, old.l_linger };
  562.     setopt (so_linger, &nw, sizeof (nw));
  563.     }
  564.     return old.l_onoff ? old.l_linger: -1;
  565. }
  566.  
  567. int sockbuf::sendbufsz (int  sz) const
  568. {
  569.     int old=0;
  570.     getopt (so_sndbuf, &old, sizeof (old));
  571.     if (sz >= 0)
  572.     setopt (so_sndbuf, &sz, sizeof (sz));
  573.     return old;
  574. }
  575.  
  576. int sockbuf::recvbufsz (int sz) const
  577. {
  578.     int old=0;
  579.     getopt (so_rcvbuf, &old, sizeof (old));
  580.     if (sz >= 0)
  581.     setopt (so_rcvbuf, &sz, sizeof (sz));
  582.     return old;
  583. }
  584.  
  585. void sockbuf::error (const char* msg) const
  586. {
  587.     extern int errno;
  588.  
  589.     if (errno)
  590.     perror (msg);
  591.     (*lib_error_handler) ("class sockbuf: ", msg);
  592. }
  593.  
  594. void isockstream::error (const char* msg) const
  595. {
  596.     extern int errno;
  597.  
  598.     if (errno)
  599.     perror (msg);
  600.     (*lib_error_handler) ("class isockstream: ", msg);
  601. }
  602.  
  603. void osockstream::error (const char* msg) const
  604. {
  605.     extern int errno;
  606.  
  607.     if (errno)
  608.     perror (msg);
  609.     (*lib_error_handler) ("class osockstream: ", msg);
  610. }
  611.  
  612. void iosockstream::error (const char* msg) const
  613. {
  614.     extern int errno;
  615.  
  616.     if (errno)
  617.     perror (msg);
  618.     (*lib_error_handler) ("class iosockstream: ", msg);
  619. }
  620.