00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Pipe.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "Pipe.h"
00012
00013 #include <unistd.h>
00014 #include <fcntl.h>
00015
00016 using namespace sella::net;
00017
00018 Pipe::Pipe(bool nonBlock) throw (SocketException) {
00019 if (::pipe(fd) != 0) {
00020 THROW2(SocketException, "pipe()");
00021 }
00022
00023 if (nonBlock) {
00024 fcntl(fd[0], F_SETFL, O_NONBLOCK);
00025 }
00026 }
00027
00028 Pipe::~Pipe() {
00029 close(fd[0]);
00030 close(fd[1]);
00031 }
00032
00033 ssize_t Pipe::write(const void *data, size_t len) throw (SocketException) {
00034 ssize_t c, r = len;
00035 int flg;
00036
00037 do {
00038 if ((c = ::write(fd[1], data, len)) < 0) {
00039 switch (errno) {
00040 case EINTR:
00041 case EMSGSIZE:
00042 case ENOBUFS:
00043 break;
00044
00045 #if ((EAGAIN) != (EWOULDBLOCK))
00046 case EAGAIN:
00047 #endif
00048 case EWOULDBLOCK:
00049 if ((flg = fcntl(fd[1], F_GETFL)) != -1 && (flg & O_NONBLOCK)) {
00050 THROW_CODE(SocketException, EWOULDBLOCK, "Nonblocking socket would have blocked");
00051 }
00052
00053 THROW_CODE(SocketException, EWOULDBLOCK, "Send timed out");
00054 }
00055
00056 THROW2(SocketException, "write()");
00057 } else if (c == 0) {
00058 break;
00059 }
00060 } while ((r -= c) > 0);
00061
00062 return len;
00063 }
00064
00065 ssize_t Pipe::write(const std::string &data) throw (SocketException) {
00066 return write((const void*) data.c_str(), data.size());
00067 }
00068
00069 ssize_t Pipe::write(const std::vector<uint8_t> &data) throw (SocketException) {
00070 return write((const void*) data.data(), data.size());
00071 }
00072
00073 ssize_t Pipe::read(void *data, size_t len) throw (SocketException) {
00074 ssize_t c;
00075 int flg;
00076
00077 if ((c = ::read(fd[0], data, len)) < 0) {
00078 switch (errno) {
00079 case EINTR:
00080 break;
00081
00082 #if ((EAGAIN) != (EWOULDBLOCK))
00083 case EAGAIN:
00084 #endif
00085 case EWOULDBLOCK:
00086 if ((flg = fcntl(fd[0], F_GETFL)) != -1 && (flg & O_NONBLOCK)) {
00087 THROW_CODE(SocketException, EWOULDBLOCK, "Nonblocking socket would have blocked");
00088 }
00089
00090 THROW_CODE(SocketException, EWOULDBLOCK, "Receive timed out");
00091 }
00092
00093 THROW2(SocketException, "read()");
00094 }
00095
00096 return c;
00097 }
00098
00099 ssize_t Pipe::read(std::string &data, size_t len) throw (SocketException) {
00100 uint8_t buf[len];
00101 ssize_t size = read(buf, len);
00102
00103 std::string(buf, buf + len).swap(data);
00104
00105 return size;
00106 }
00107
00108 ssize_t Pipe::read(std::vector<uint8_t> &data, size_t len) throw (SocketException) {
00109 uint8_t buf[len];
00110 ssize_t size = read(buf, len);
00111
00112 std::vector<uint8_t>(buf, buf + len).swap(data);
00113
00114 return size;
00115 }
00116
00117 int Pipe::getWriteFD(void) {
00118 return fd[1];
00119 }
00120
00121 int Pipe::getReadFD(void) {
00122 return fd[0];
00123 }
00124
00125 const Pipe::shared Pipe::shared_ptr(bool nonBlock) throw (SocketException) {
00126 return std::make_shared<Pipe>(nonBlock);
00127 }
00128
00129
00130
00131