ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/host/c++/socket++-1.10/sockstream.C
Revision: 1.1
Committed: Mon Feb 26 15:01:39 2001 UTC (23 years, 6 months ago) by ab11
Content type: text/plain
Branch: MAIN
Log Message:
Networking class. Assumed to be bug free.

File Contents

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