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.3
Committed: Mon Jun 10 14:10:44 2002 UTC (22 years, 5 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +0 -0 lines
State: FILE REMOVED
Log Message:
Tidy up of files. These are all old things that are not only no longer used
but are also probably useless to anyone other than us. This saves checking
them out all the time, and makes the "cms/source" tree contain only current
stuff. They'll still exist in the attic's though :)

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