## modules/up/src/Core/sys/Pipe.cc

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. pipeRead
2. pipeWrite
3. pipeTimeout
4. Pipe
5. Pipe
6. Pipe
7. read
8. write
9. send
10. timeout
11. flush
12. flushAndClose

       1 //
       2 // $Id: Pipe.cc,v 1.1.1.1 2000/03/10 16:32:20 engin Exp $
       3 //
       4 // Author(s): Ramesh Govindan
       5
       6 #ifdef HAVE_CONFIG_H
       7 #include <config.h>
       8 #endif
       9
      10 #include "util/Types.hh"
      11 #include "util/Trail.hh"
      12 #include "util/Handler.hh"
      13 #include "util/Buffer.hh"
      14 #include "sys/Time.hh"
      15 #include "sys/File.hh"
      16 #include "sched/Timer.hh"
      17 #include "sched/Dispatcher.hh"
      18 #include "sys/Pipe.hh"
      19
      20 // Constants
      21 static const int        ReadBufferSize = 512;
      22
      23 // File locals
      24 static TraceCode        tracePipe("pipe");
      25
      26 static void
      27 pipeRead(void* ptr,
         /* [<][>][^][v][top][bottom][index][help] */
      28          void*)
      29 {
      30     ((Pipe*) ptr)->read();
      31 }
      32
      33 static void
      34 pipeWrite(void* ptr,
         /* [<][>][^][v][top][bottom][index][help] */
      35           void*)
      36 {
      37     ((Pipe*) ptr)->write();
      38 }
      39
      40 static void
      41 pipeTimeout(void* ptr,
         /* [<][>][^][v][top][bottom][index][help] */
      42             void*)
      43 {
      44     ((Pipe*) ptr)->timeout();
      45 }
      46
      47 Pipe::Pipe(ListenSocket* s,
         /* [<][>][^][v][top][bottom][index][help] */
      48            const TimeShort& t)
      49         : ListNode()
      50 {
      51     Handler     readH(pipeRead, this);
      52     Handler     nullH((CallBackFunc)NULL, (void *)NULL);
      53     Handler     tH(pipeTimeout, this);
      54     TimeLong    at;
      55
      56     incoming = new Buffer(ReadBufferSize);
      57     if (s->accept(&socket, address, &port, readH, nullH) < 0) {
      58         return;         // XXX: cleanup?
      59     }
      60
      61     timer = (Timer *)NULL;
      62     gotsome = false;
      63     connected = true;
      64     interval = t;
      65     passive = true;
      66     logicallyDeleted = false;
      67
      68     if (interval < InfiniteInterval) {
      69         dispatcher.systemClock.sync();
      70         at = dispatcher.systemClock;
      71         at = at + interval;
      72         timer = new Timer(tH, at);
      73     }
      74
      75     TRACE(tracePipe,
      76           "new passive end of pipe for %s:%u\n",
      77           address.name(), port);
      78     return;
      79 }
      80
      81 Pipe::Pipe(const Address& addr,
         /* [<][>][^][v][top][bottom][index][help] */
      82            Port p)
      83         : ListNode()
      84 {
      85     Handler     rh((CallBackFunc)NULL, (void *)NULL);
      86     Handler     wh(pipeWrite, this);
      87
      88     incoming = new Buffer(ReadBufferSize);
      89     address = addr;
      90     port = p;
      91     connected = false;
      92
      93     passive = false;
      94     gotsome = false;
      95     interval = InfiniteInterval;
      96     timer = (Timer *)NULL;
      97     logicallyDeleted = false;
      98
      99     socket = new StreamSocket(address, port, rh, wh);
     100     TRACE(tracePipe,
     101           "new active end for pipe to %s:%u\n",
     102           address.name(),
     103           port);
     104     return;
     105 }
     106
     107 Pipe::~Pipe()
         /* [<][>][^][v][top][bottom][index][help] */
     108 {
     109     TRACE(tracePipe,
     110           "deleting server %s:%u\n",
     111           address.name(),
     112           port);
     113
     114     if (timer) {
     115         delete timer;
     116     }
     117     delete socket;
     118     delete incoming;
     119     outgoing.clear();
     120 }
     121
     122 void
     123 Pipe::read()
         /* [<][>][^][v][top][bottom][index][help] */
     124 {
     125     int         length;
     126
     127     ASSERT(!logicallyDeleted);
     128
     129     gotsome = true;
     130     length = socket->read((char *) (incoming->contents + incoming->size),
     131                               incoming->capacity - incoming->size);
     132
     133     if (length == 0 || length == FileOpHardError) {
     134         terminate();
     135         return;
     136     } else if (length == FileOpSoftError) {
     137         return;
     138     }
     139
     140     TRACE(tracePipe,
     141           "read %u bytes from %s:%d, size %u\n",
     142           length, address.name(), port, incoming->size);
     143
     144     // Check if we can flush what we've read so far
     145     incoming->size += length;
     146     receive();
     147
     148     // If we have exceeded buffer capacity...
     149     if (incoming->size == incoming->capacity) {
     150         Buffer*         old = incoming;
     151
     152         incoming = new Buffer((old->capacity << 1));
     153         incoming->append(old->contents, old->size);
     154         delete old;
     155     }
     156
     157     return;
     158 }
     159
     160 void
     161 Pipe::write()
         /* [<][>][^][v][top][bottom][index][help] */
     162 {
     163     int         length;
     164     Handler     rh(pipeRead, this);
     165     Handler     nh((CallBackFunc)NULL, (void *)NULL);
     166     Buffer*     send;
     167
     168     if (!connected) {
     169         TRACE(tracePipe, "client connected to %s:%u\n",
     170               address.name(), port);
     171
     172         connected = true;
     173         if (outgoing.isEmpty()) {
     174             socket->setHandlers((logicallyDeleted) ? nh : rh, nh);
     175         }
     176         return;
     177     }
     178
     179     gotsome = true;
     180     send = outgoing.head();
     181     length = socket->write((char *) (send->contents + send->offset),
     182                            send->size - send->offset);
     183
     184     if (length < 0) {
     185         switch (length) {
     186             case FileOpHardError:
     187                 terminate();
     188                 return;
     189             case FileOpSoftError:
     190                 return;
     191             default:
     192                 ASSERT(false);
     193         }
     194     }
     195
     196     if (length == 0) {
     197         TRACE(tracePipe,
     198               "remote end %s:%u closed connection\n",
     199               address.name(), port);
     200         terminate();
     201         return;
     202     }
     203
     204     TRACE(tracePipe,
     205           "wrote %u bytes to %s:%u\n",
     206           length,
     207           address.name(),
     208           port);
     209
     210     send->offset += length;
     211     if (send->offset == send->size) {
     212         TRACE(tracePipe,
     213               "completed send of length %u on %s:%u\n",
     214               send->size, address.name(), port);
     215
     216         outgoing.remove(send);
     217         delete send;
     218         if (outgoing.isEmpty()) {
     219             if (logicallyDeleted) {
     220                 TRACE(tracePipe, "closing logically deleted pipe %s:%u\n",
     221                       address.name(), port);
     222                 terminate();
     223                 return;
     224             } else {
     225                 socket->setHandlers(rh, nh);
     226             }
     227         }
     228     }
     229     return;
     230 }
     231
     232 void
     233 Pipe::send(Buffer *buf)
         /* [<][>][^][v][top][bottom][index][help] */
     234 {
     235     Handler     rh(pipeRead, this);
     236     Handler     wh(pipeWrite, this);
     237
     238     // Can't call send after deleting pipe
     239     if (logicallyDeleted) {
     240       delete buf;
     241       return;
     242     }
     243
     244     buf->offset = 0;
     245     gotsome = true;
     246     if (outgoing.isEmpty()) {
     247         socket->setHandlers(rh, wh);
     248     }
     249     outgoing.append(buf);
     250
     251     TRACE(tracePipe,
     252           "queued response of length %u on %s:%u\n",
     253           buf->size, address.name(), port);
     254     return;
     255 }
     256
     257 void
     258 Pipe::timeout()
         /* [<][>][^][v][top][bottom][index][help] */
     259 {
     260     Handler     th(pipeTimeout, this);
     261     TimeLong    at;
     262
     263     timer = (Timer *)NULL;
     264     if (!gotsome) {
     265         TRACE(tracePipe,
     266               "no activity on connection to %s:%u, closing\n",
     267               address.name(), port);
     268         terminate();
     269         return;
     270     }
     271
     272     gotsome = false;
     273     dispatcher.systemClock.sync();
     274     at = dispatcher.systemClock;
     275     at = at + interval;
     276     timer = new Timer(th, at);
     277     return;
     278 }
     279
     280 void
     281 Pipe::flush(int length)
         /* [<][>][^][v][top][bottom][index][help] */
     282 {
     283     Buffer*     buf;
     284     int         rlen;
     285
     286     // Create a new buffer, and move up remaining data
     287     rlen = incoming->size - length;
     288     ASSERT(rlen >= 0);
     289     TRACE(tracePipe,
     290           "flushing %d bytes from incoming buffer for %s:%u\n",
     291           length, address.name(), port);
     292     if (rlen == 0) {
     293       incoming->size = 0;
     294       return;
     295     }
     296     buf = new Buffer(ReadBufferSize >? rlen);
     297     buf->append(incoming->contents + length, rlen);
     298     delete incoming;
     299     incoming = buf;
     300
     301     return;
     302 }
     303
     304 void
     305 Pipe::flushAndClose()
         /* [<][>][^][v][top][bottom][index][help] */
     306 {
     307     Handler     nh((CallBackFunc) NULL, (void*) NULL);
     308     Handler     wh(pipeWrite, this);
     309
     310     logicallyDeleted = true;
     311     if (outgoing.isEmpty()) {
     312         terminate();
     313         return;
     314     }
     315     socket->setHandlers(nh, wh);        // Prevent reads
     316     return;
     317 }
     318
     319 //  Copyright (c) 1994 by the University of Southern California.
     320 //  All rights reserved.
     321 //
     322 //  Permission to use, copy, modify, and distribute this software and
     323 //  its documentation in source and binary forms for lawful
     324 //  non-commercial purposes and without fee is hereby granted, provided
     325 //  that the above copyright notice appear in all copies and that both
     326 //  the copyright notice and this permission notice appear in supporting
     327 //  documentation, and that any documentation, advertising materials,
     328 //  and other materials related to such distribution and use acknowledge
     329 //  that the software was developed by the University of Southern
     330 //  California and/or Information Sciences Institute.
     331 //  The name of the University of Southern California may not
     332 //  be used to endorse or promote products derived from this software
     333 //  without specific prior written permission.
     334 //
     335 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
     336 //  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
     337 //  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     338 //  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     339 //  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
     340 //  NON-INFRINGEMENT.
     341 //
     342 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
     343 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
     344 //  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
     345 //  THE USE OR PERFORMANCE OF THIS SOFTWARE.
     346 //
     347 //  Questions concerning this software should be directed to
     348 //  info-ra@isi.edu.
     349 //
     350

/* [<][>][^][v][top][bottom][index][help] */