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, 9 months ago) by ab11
Content type: text/plain
Branch: MAIN
Log Message:
Networking class. Assumed to be bug free.

File Contents

# Content
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