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] */