sockstream.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:16k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. // sockstream.C -*- C++ -*- socket library
  2. // Copyright (C) 1992,1993,1994 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: 17Oct95 1.10
  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. #include "SWIutilInternal.h"
  43. #include "sockstream.h"
  44. #include <string.h>
  45. #ifndef _WIN32
  46. EXTERN_C_BEGIN
  47. #include <sys/time.h>
  48. #include <sys/socket.h>
  49. #include <unistd.h>
  50. #include <errno.h>
  51. #include <sys/ioctl.h>
  52. #ifdef _solaris_
  53. #include <sys/filio.h>
  54. #endif
  55. EXTERN_C_END
  56. #else
  57. #include <winsock.h>
  58. #ifdef EINTR
  59. #undef EINTR
  60. #endif
  61. #define EINTR WSAEINTR
  62. #endif /* !_WIN32 */
  63. #ifndef BUFSIZ
  64. #  define BUFSIZ 1024
  65. #endif
  66. #ifdef FD_ZERO
  67. #  undef FD_ZERO    // bzero causes so much trouble to us
  68. #endif
  69. #define FD_ZERO(p) (memset ((p), 0, sizeof *(p)))
  70. #define LOG_ERROR(_err, _func) Error(_err, L"%s%s", L"Func", _func);
  71. #ifdef _WIN32
  72. #define LOG_ERROR_DETAILED(_err, _func) 
  73.   int wserr = WSAGetLastError(); 
  74.   Error(_err, L"%s%s%s%i", L"Func", _func, L"WinsockError", wserr); 
  75. }
  76. #else
  77. #define LOG_ERROR_DETAILED(_err, _func) LOG_ERROR(_err, _func)
  78. #endif
  79. sockbuf::sockbuf (const VXIchar *moduleName, VXIlogInterface *pVXILog, 
  80.   VXIunsigned diagTagBase, SOCKET soc)
  81.   : streambuf(), SWIutilLogger(moduleName, pVXILog, diagTagBase),
  82.     rep (new sockcnt (soc, 1)), stmo (-1), rtmo (-1)
  83. {
  84.   xflags (0);
  85.   xsetflags (_S_LINE_BUF);
  86. }
  87. sockbuf::sockbuf (const VXIchar *moduleName, VXIlogInterface *pVXILog, 
  88.   VXIunsigned diagTagBase, int domain, sockbuf::type st,
  89.   int proto)
  90.   : streambuf(), SWIutilLogger(moduleName, pVXILog, diagTagBase),
  91.     rep (0), stmo (-1), rtmo (-1)
  92. {
  93.   SOCKET soc = ::socket (domain, st, proto);
  94.   rep = new sockcnt (soc, 1);
  95.   xflags (0);
  96.   if ((! rep) || (rep->sock == INVALID_SOCKET)) 
  97.     error ("invalid socket");
  98.   xsetflags (_S_LINE_BUF);
  99. }
  100. sockbuf::sockbuf (const sockbuf& sb)
  101.   : streambuf(), SWIutilLogger(sb),
  102.     rep (sb.rep), stmo (sb.stmo), rtmo (sb.rtmo)
  103. {
  104.   xflags (0);
  105.   rep->cnt++;
  106.   xsetflags (_S_LINE_BUF);
  107. }
  108. sockbuf& sockbuf::operator = (const sockbuf& sb)
  109. {
  110.   if (this != &sb && rep != sb.rep && rep->sock != sb.rep->sock) {
  111.     this->sockbuf::~sockbuf();
  112.     rep  = sb.rep; stmo = sb.stmo; rtmo = sb.rtmo; 
  113.     SWIutilLogger::Create(sb.GetModuleName(), sb.GetLog(), sb.GetDiagBase());
  114.     rep->cnt++;
  115. #ifdef _S_NOLIBGXX
  116.     xflags (sb.xflags ());
  117. #else
  118.     // xflags () is a non-const member function in libg++.
  119.     xflags (((sockbuf&)sb).xflags ());
  120. #endif
  121.   }
  122.   return *this;
  123. }
  124. sockbuf::~sockbuf ()
  125. {
  126.   overflow (EOF);
  127.   if (rep->cnt == 1 && !(xflags () & _S_DELETE_DONT_CLOSE)) close ();
  128.   delete [] base ();
  129.   if (--rep->cnt == 0) delete rep;
  130. }
  131. sockbuf* sockbuf::open (type, int)
  132. {
  133.   return 0;
  134. }
  135. sockbuf* sockbuf::close()
  136. {
  137. #ifdef _WIN32
  138.   if (rep->sock != INVALID_SOCKET)
  139.   {
  140.      closesocket(rep->sock);
  141.      rep->sock = INVALID_SOCKET;
  142.   }
  143. #else
  144.   if (rep->sock >= 0)
  145.   {
  146.     if (::close (rep->sock) == -1) return this;
  147.     rep->sock = -1;
  148.   }
  149. #endif
  150.   return 0;
  151. }
  152. _G_ssize_t sockbuf::sys_read (char* buf, _G_ssize_t len)
  153. // return EOF on eof, 0 on timeout, and # of chars read on success
  154. {
  155.   return read (buf, len);
  156. }
  157. _G_ssize_t sockbuf::sys_write (const void* buf, long len)
  158. // return written_length; < len indicates error
  159. {
  160.   return write (buf, (int) len);
  161. }
  162. int sockbuf::flush_output()
  163. // return 0 when there is nothing to flush or when the flush is a success
  164. // return EOF when it could not flush
  165. {
  166.   if (pptr () <= pbase ()) return 0;
  167.   if (!(xflags () & _S_NO_WRITES)) {
  168.     int wlen   = pptr () - pbase ();
  169.     int wval   = sys_write (pbase (), wlen);
  170.     int status = (wval == wlen)? 0: EOF;
  171. #ifndef _WIN32
  172.     if (unbuffered()) setp (pbase (), pbase ());
  173.     else
  174. #endif
  175. setp (pbase (), pbase () + BUFSIZ);
  176.     return status;
  177.   }
  178.   return EOF;
  179. }
  180. int sockbuf::sync ()
  181. {
  182.   return flush_output ();
  183. }
  184. int sockbuf::doallocate ()
  185. // return 1 on allocation and 0 if there is no need
  186. {
  187.   if (!base ()) {
  188.     char* buf = new char[2*BUFSIZ];
  189.     setb (buf, buf+BUFSIZ);
  190.     setg (buf, buf, buf);
  191.     buf += BUFSIZ;
  192.     setp (buf, buf+BUFSIZ);
  193.     return 1;
  194.   }
  195.   return 0;
  196. }
  197. underflow_ret_t sockbuf::underflow ()
  198. {
  199.   if (xflags () & _S_NO_READS) return EOF;
  200.   if (gptr () < egptr ()) return *(unsigned char*)gptr ();
  201.   if (base () == 0 && doallocate () == 0) return EOF;
  202.   int bufsz = unbuffered () ? 1: BUFSIZ;
  203.   int rval = sys_read (base (), bufsz);
  204.   if (rval == EOF) {
  205.     xsetflags (_S_EOF_SEEN);
  206.     return EOF;
  207.   }else if (rval == 0)
  208.     return EOF;
  209.   setg (eback (), base (), base () + rval);
  210.   return *(unsigned char*)gptr ();
  211. }
  212. sockbuf::int_type sockbuf::overflow (sockbuf::int_type 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.   if (pbase () == 0 && doallocate () == 0) return EOF;
  221.   if (pptr () >= epptr() && flush_output () == EOF)
  222.     return EOF;
  223.   xput_char (c);
  224.   if ((unbuffered () || linebuffered () && c == 'n' || pptr () >= epptr ())
  225.       && flush_output () == EOF)
  226.     return EOF;
  227.   return c;
  228. }
  229. int sockbuf::xsputn (const char* s, int n)
  230. {
  231.   if (n <= 0) return 0;
  232.   const unsigned char* p = (const unsigned char*)s;
  233.   for (int i=0; i<n; i++, p++) {
  234.     if (*p == 'n') {
  235.       if (overflow (*p) == EOF) return i;
  236.     } else
  237.       if (sputc (*p) == EOF) return i;
  238.   }
  239.   return n;
  240. }
  241. int sockbuf::bind (sockAddr& sa)
  242. {
  243.   return ::bind (rep->sock, sa.addr (), sa.size ());
  244. }
  245. int sockbuf::connect (sockAddr& sa)
  246. {
  247.   if (::connect(rep->sock, sa.addr (), sa.size()) != 0) {
  248. #ifdef _WIN32
  249.     int wserr = WSAGetLastError();
  250.     if (wserr != WSAEWOULDBLOCK) {
  251.       Error(500, L"%s%s%s%i", L"Func", L"connect", L"WinsockError", wserr);
  252.       return -1;
  253.     }
  254. #else
  255.     if (errno != EINPROGRESS) {
  256.       Error(500, L"%s%s%s%i", L"Func", L"connect", L"errno", errno);
  257.       return -1;
  258.     }
  259. #endif
  260.   }
  261.   return 0;
  262. }
  263. int sockbuf::listen (int num)
  264. {
  265.   return ::listen (rep->sock, num);
  266. }
  267. sockbuf sockbuf::accept (sockAddr& sa)
  268. {
  269.   socklen_t len = sa.size ();
  270.   SOCKET soc = INVALID_SOCKET;
  271.   while ((soc = ::accept (rep->sock, sa.addr (), &len)) == INVALID_SOCKET
  272.  && errno == EINTR);
  273.   return sockbuf(GetModuleName(), GetLog(), GetDiagBase(), soc);
  274. }
  275. sockbuf sockbuf::accept ()
  276. {
  277.   SOCKET soc = INVALID_SOCKET;
  278.   while ((soc = ::accept (rep->sock, 0, 0)) == INVALID_SOCKET
  279.  && errno == EINTR);
  280.   return sockbuf(GetModuleName(), GetLog(), GetDiagBase(), soc);
  281. }
  282. int sockbuf::read (void* buf, int len)
  283. {
  284. #ifdef _WIN32
  285.   return recv (buf, len); // Winsock uses recv
  286. #else
  287.   if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  288.   int rval;
  289.   if ((rval = ::read (rep->sock, (char*) buf, len)) == -1)
  290.     error("read");
  291.   return (rval==0) ? EOF: rval;
  292. #endif // _WIN32
  293. }
  294. int sockbuf::recv (void* buf, int len, int msgf)
  295. {
  296.   if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  297.   int rval;
  298.   if ((rval = ::recv (rep->sock, (char*) buf, len, msgf)) == -1)
  299.     LOG_ERROR_DETAILED (500, L"recv");
  300.   return (rval==0) ? EOF: rval;
  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.   int rval;
  306.   socklen_t sa_len = sa.size ();
  307.   if ((rval = ::recvfrom (rep->sock, (char*) buf, len,
  308.   msgf, sa.addr (), &sa_len)) == -1)
  309.     LOG_ERROR_DETAILED (500, L"recvfrom");
  310.   return (rval==0) ? EOF: rval;
  311. }
  312. int sockbuf::write(const void* buf, int len)
  313. {
  314. #ifdef _WIN32
  315.   return send(buf, len); // Winsock uses send
  316. #else
  317.   if (stmo != -1 && is_writeready (stmo)==0) return 0;
  318.   int wlen=0;
  319.   while(len>0) {
  320.     int wval;
  321.     if ((wval = ::write (rep->sock, (char*) buf, len)) == -1) {
  322.       error ("sockbuf::write");
  323.       return wval;
  324.     }
  325.     len -= wval;
  326.     wlen += wval;
  327.   }
  328.   return wlen; // == len if every thing is all right
  329. #endif // _WIN32
  330. }
  331. int sockbuf::send (const void* buf, int len, int msgf)
  332. {
  333.   if (stmo != -1 && is_writeready (stmo)==0) return 0;
  334.   int wlen=0;
  335.   while(len>0) {
  336.     int wval;
  337.     if ((wval = ::send (rep->sock, (char*) buf, len, msgf)) == -1) {
  338.       LOG_ERROR_DETAILED (500, L"send");
  339.       return wval;
  340.     }
  341.     len -= wval;
  342.     wlen += wval;
  343.   }
  344.   return wlen;
  345. }
  346. int sockbuf::sendto (sockAddr& sa, const void* buf, int len, int msgf)
  347. {
  348.   if (stmo != -1 && is_writeready (stmo)==0) return 0;
  349.   int wlen=0;
  350.   while(len>0) {
  351.     int wval;
  352.     if ((wval = ::sendto (rep->sock, (char*) buf, len,
  353.   msgf, sa.addr (), sa.size())) == -1) {
  354.       LOG_ERROR_DETAILED (500, L"sendto");
  355.       return wval;
  356.     }
  357.     len -= wval;
  358.     wlen += wval;
  359.   }
  360.   return wlen;
  361. }
  362. #if !defined (__linux__) && !defined(_WIN32)
  363. // linux does not have sendmsg or recvmsg
  364. int sockbuf::recvmsg (msghdr* msg, int msgf)
  365. {
  366.   if (rtmo != -1 && is_readready (rtmo)==0) return 0;
  367.   int rval;
  368.   if ((rval = ::recvmsg(rep->sock, msg, msgf)) == -1)
  369.     error ("sockbuf::recvmsg");
  370.   return (rval==0)? EOF: rval;
  371. }
  372. int sockbuf::sendmsg (msghdr* msg, int msgf)
  373. {
  374.   if (stmo != -1 && is_writeready (stmo)==0) return 0;
  375.   int wval;
  376.   if ((wval = ::sendmsg (rep->sock, msg, msgf)) == -1)
  377.     error("sendmsg");
  378.   return wval;
  379. }
  380. #endif //!__linux__
  381. int sockbuf::sendtimeout (int wp)
  382. {
  383.   int oldstmo = stmo;
  384.   stmo = (wp < 0) ? -1: wp;
  385.   return oldstmo;
  386. }
  387. int sockbuf::recvtimeout (int wp)
  388. {
  389.   int oldrtmo = rtmo;
  390.   rtmo = (wp < 0) ? -1: wp;
  391.   return oldrtmo;
  392. }
  393. int sockbuf::is_readready (int wp_sec, int wp_usec) const
  394. {
  395.   fd_set rfds;
  396.   FD_ZERO (&rfds);
  397.   FD_SET (rep->sock, &rfds);
  398.   fd_set efds;
  399.   FD_ZERO (&efds);
  400.   FD_SET (rep->sock, &efds);
  401.   timeval tv;
  402.   tv.tv_sec  = wp_sec;
  403.   tv.tv_usec = wp_usec;
  404.   int ret = select (rep->sock+1, &rfds, 0, &efds, (wp_sec == -1) ? 0: &tv);
  405.   if (ret < 0) 
  406.   {
  407.     LOG_ERROR_DETAILED (500, L"select");
  408.     return ret;
  409.   }
  410.   else if (ret == 0)
  411.   {
  412.     LOG_ERROR (501, L"select");
  413.     return ret;
  414.   }
  415.   if (FD_ISSET(rep->sock, &efds))
  416.   {
  417.     LOG_ERROR (502, L"select");
  418.     return -1;
  419.   }
  420.   return FD_ISSET(rep->sock,&rfds);
  421. }
  422. int sockbuf::is_writeready (int wp_sec, int wp_usec) const
  423. {
  424.   fd_set wfds;
  425.   FD_ZERO (&wfds);
  426.   FD_SET (rep->sock, &wfds);
  427.   fd_set efds;
  428.   FD_ZERO (&efds);
  429.   FD_SET (rep->sock, &efds);
  430.   timeval tv;
  431.   tv.tv_sec  = wp_sec;
  432.   tv.tv_usec = wp_usec;
  433.   int ret = select (rep->sock+1, 0, &wfds, &efds, (wp_sec == -1) ? 0: &tv);
  434.   if (ret < 0) 
  435.   {
  436.     LOG_ERROR_DETAILED (500, L"select");
  437.     return ret;
  438.   }
  439.   else if (ret == 0)
  440.   {
  441.     LOG_ERROR (501, L"select");
  442.     return ret;
  443.   }
  444.   if (FD_ISSET(rep->sock, &efds))
  445.   {
  446.     LOG_ERROR (502, L"select");
  447.     return -1;
  448.   }
  449.   return FD_ISSET(rep->sock,&wfds);
  450. }
  451. int sockbuf::is_exceptionpending (int wp_sec, int wp_usec) const
  452. {
  453.   fd_set fds;
  454.   FD_ZERO (&fds);
  455.   FD_SET  (rep->sock, &fds);
  456.   timeval tv;
  457.   tv.tv_sec = wp_sec;
  458.   tv.tv_usec = wp_usec;
  459.   int ret = select (rep->sock+1, 0, 0, &fds, (wp_sec == -1) ? 0: &tv);
  460.   if (ret == -1) {
  461.     LOG_ERROR_DETAILED (500, L"select");
  462.     return 0;
  463.   }
  464.   return ret;
  465. }
  466. void sockbuf::shutdown (shuthow sh)
  467. {
  468.   switch (sh) {
  469.   case shut_read:
  470.     xsetflags(_S_NO_READS);
  471.     break;
  472.   case shut_write:
  473.     xsetflags(_S_NO_WRITES);
  474.     break;
  475.   case shut_readwrite:
  476.     xsetflags(_S_NO_READS|_S_NO_WRITES);
  477.     break;
  478.   }
  479.   if (::shutdown(rep->sock, sh) == INVALID_SOCKET)
  480.     error("shutdown");
  481. }
  482. int sockbuf::getopt (option op, void* buf, int len, level l) const
  483. {
  484.   socklen_t rlen = len;
  485.   if (::getsockopt (rep->sock, l, op, (char*) buf, &rlen) == -1)
  486.     error ("sockbuf::getopt");
  487.   return rlen;
  488. }
  489. int sockbuf::setBlocking(bool blocking)
  490. {
  491.   unsigned long x = (unsigned long) !blocking;
  492. #ifdef _WIN32
  493.   return ioctlsocket(rep->sock, FIONBIO, &x);
  494. #else
  495.   return ioctl(rep->sock, FIONBIO, &x);
  496. #endif
  497. }
  498. void sockbuf::setopt (option op, void* buf, int len, level l) const
  499. {
  500.   if (::setsockopt (rep->sock, l, op, (char*) buf, len) == -1)
  501.     error ("sockbuf::setopt");
  502. }
  503. sockbuf::type sockbuf::gettype () const
  504. {
  505.   int ty=0;
  506.   getopt (so_type, &ty, sizeof (ty));
  507.   return sockbuf::type(ty);
  508. }
  509. int sockbuf::clearerror () const
  510. {
  511.   int  err=0;
  512.   getopt (so_error, &err, sizeof (err));
  513.   return err;
  514. }
  515. int sockbuf::debug (int opt) const
  516. {
  517.   int old=0;
  518.   getopt (so_debug, &old, sizeof (old));
  519.   if (opt != -1)
  520.     setopt (so_debug, &opt, sizeof (opt));
  521.   return old;
  522. }
  523. int sockbuf::reuseaddr (int opt) const
  524. {
  525.   int old=0;
  526.   getopt (so_reuseaddr, &old, sizeof (old));
  527.   if (opt != -1)
  528.     setopt (so_reuseaddr, &opt, sizeof (opt));
  529.   return old;
  530. }
  531. int sockbuf::keepalive (int opt) const
  532. {
  533.   int old=0;
  534.   getopt (so_keepalive, &old, sizeof (old));
  535.   if (opt != -1)
  536.     setopt (so_keepalive, &opt, sizeof (opt));
  537.   return old;
  538. }
  539. int sockbuf::dontroute (int opt) const
  540. {
  541.   int old=0;
  542.   getopt (so_dontroute, &old, sizeof (old));
  543.   if (opt != -1)
  544.     setopt (so_dontroute, &opt, sizeof (opt));
  545.   return old;
  546. }
  547. int sockbuf::broadcast (int opt) const
  548. {
  549.   int old=0;
  550.   getopt (so_broadcast, &old, sizeof (old));
  551.   if (opt != -1)
  552.     setopt (so_broadcast, &opt, sizeof (opt));
  553.   return old;
  554. }
  555. int sockbuf::oobinline (int opt) const
  556. {
  557.   int old=0;
  558.   getopt (so_oobinline, &old, sizeof (old));
  559.   if (opt != -1)
  560.     setopt (so_oobinline, &opt, sizeof (opt));
  561.   return old;
  562. }
  563. int sockbuf::linger (int opt) const
  564. {
  565.   socklinger old (0, 0);
  566.   getopt (so_linger, &old, sizeof (old));
  567.   if (opt > 0) {
  568.     socklinger nw (1, opt);
  569.     setopt (so_linger, &nw, sizeof (nw));
  570.   }else if (opt == 0) {
  571.     socklinger nw (0, old.l_linger);
  572.     setopt (so_linger, &nw, sizeof (nw));
  573.   }
  574.   return old.l_onoff ? old.l_linger: -1;
  575. }
  576. int sockbuf::sendbufsz (int  sz) const
  577. {
  578.   int old=0;
  579.   getopt (so_sndbuf, &old, sizeof (old));
  580.   if (sz >= 0)
  581.     setopt (so_sndbuf, &sz, sizeof (sz));
  582.   return old;
  583. }
  584. int sockbuf::recvbufsz (int sz) const
  585. {
  586.   int old=0;
  587.   getopt (so_rcvbuf, &old, sizeof (old));
  588.   if (sz >= 0)
  589.     setopt (so_rcvbuf, &sz, sizeof (sz));
  590.   return old;
  591. }
  592. void sockbuf::error (const char* msg) const
  593. {
  594.   SOCK_ERROR("sockbuf", msg);
  595. }
  596. isockstream::~isockstream ()
  597. {
  598. }
  599. osockstream::~osockstream ()
  600. {
  601. }
  602. iosockstream::~iosockstream ()
  603. {
  604. }