diff options
-rw-r--r-- | include/Handle.h | 8 | ||||
-rw-r--r-- | include/Socket.h | 4 | ||||
-rw-r--r-- | lib/Handle.cc | 100 | ||||
-rw-r--r-- | lib/Socket.cc | 19 |
4 files changed, 120 insertions, 11 deletions
diff --git a/include/Handle.h b/include/Handle.h index dd1cfd7..9fef098 100644 --- a/include/Handle.h +++ b/include/Handle.h @@ -2,6 +2,7 @@ #define __HANDLE_H__ #ifdef __cplusplus +#include <zlib.h> #include <unistd.h> #include <iostream.h> #include <String.h> @@ -24,15 +25,20 @@ class Handle : public Base { virtual String GetName(); virtual off_t GetSize(); virtual time_t GetModif(); - void close(); + void close() throw (GeneralException); int GetHandle(); virtual bool CanWatch(); virtual void Dup(const Handle &); + virtual void SetZ(int) throw (GeneralException); protected: Handle(int h); private: + ssize_t uwrite(const void *, size_t) throw (GeneralException); + ssize_t uread(void *, size_t); int h; bool closed, nonblock; + gzFile zfile; + int z; }; Handle & operator<<(Handle &, const String &); diff --git a/include/Socket.h b/include/Socket.h index a8076e3..b8ea05e 100644 --- a/include/Socket.h +++ b/include/Socket.h @@ -22,10 +22,12 @@ class Socket : public Handle { virtual bool CanWrite(); virtual String GetName(); int GetPort(); + void CloseWrite(); + void CloseRead(); private: Socket(int s); - bool connected, listening; + bool connected, listening, writeclosed, readclosed; }; #else diff --git a/lib/Handle.cc b/lib/Handle.cc index c02bc55..7b56df4 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -6,13 +6,21 @@ #include "Handle.h" #include "config.h" -Handle::Handle(const Handle & nh) : h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(false), nonblock(false) { } +Handle::Handle(const Handle & nh) : h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(false), nonblock(false), zfile(0), z(0) { + cerr << "Duplication of handle " << nh.h << " to " << h << endl; + if ((h >= 0) && (nh.z)) { + SetZ(nh.z); + } +} Handle::~Handle() { + cerr << "Destroying handle " << h << endl; close(); } -Handle::Handle(int nh) : h(nh), closed(false) { } +Handle::Handle(int nh) : h(nh), closed(false), zfile(0), z(0) { + cerr << "Initialising handle " << h << endl; +} int Handle::GetHandle() { return h; @@ -25,7 +33,7 @@ ssize_t Handle::write(const void *buf, size_t count) throw (GeneralException) { do { done = true; errno = 0; - if ((r = ::write(h, buf, count)) < 0) { + if ((r = uwrite(buf, count)) < 0) { if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus de place libre. Cela peut @@ -60,7 +68,7 @@ ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) { ssize_t r; errno = 0; - if ((r = ::read(h, buf, count)) < 0) { + if ((r = uread(buf, count)) < 0) { if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus d'octets. @@ -124,13 +132,29 @@ Handle & operator>>(Handle & h, String & s) { return h; } -void Handle::close() { +void Handle::close() throw (GeneralException) { if (IsClosed()) { return; } if (h >= 0) { - ::close(h); + if (z) { + cerr << "Performing gzclose on handle " << h << endl; + int err = gzclose(zfile); + cerr << "gzclose returned " << err << endl; + if (err) { + if (err == Z_ERRNO) { + throw GeneralException(String(_("Error during close: ")) + strerror(errno)); + } else { + throw GeneralException(_("Error in zlib during gzclose.")); + } + } + } else { + int err = ::close(h); + if (err) { + throw GeneralException(String(_("Error during close: ")) + strerror(errno)); + } + } } h = -1; @@ -168,3 +192,67 @@ void Handle::Dup(const Handle & H) { h = dup(H.h); } } + +void Handle::SetZ(int az) throw (GeneralException) { + if (z) { + throw GeneralException(_("Can't SetZ a Handle twice.")); + } + z = az; + if (h < 0) { + throw GeneralException(_("Can't SetZ a virtual Handle.")); + } + if (z) { + char format[4]; + int index = 0; + if (CanRead()) { + format[index++] = 'r'; + } + if (CanWrite()) { + format[index++] = 'w'; + } + format[index++] = (char) (z + '0'); + format[index] = 0; + cerr << "Performing gzdopen on handle " << h << " with mode \"" << format << "\"\n"; + if (!(zfile = gzdopen(h, format))) { + throw GeneralException(_("Was not able to gzdopen.")); + } + } +} + +ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) { + if (z) { + cerr << "Performing gzwrite of " << count << " byte for handle " << h << endl; + int err = gzwrite(zfile, buf, count); + cerr << "gzwrite returned " << err << endl; + if (err == 0) { + const char * m = gzerror(zfile, &err); + if (err == Z_ERRNO) { + return -1; + } else { + throw GeneralException(String(_("Error in zlib during gzwrite: ")) + m); + } + } + return err; + } else { + return ::write(h, buf, count); + } +} + +ssize_t Handle::uread(void * buf, size_t count) { + if (z) { + cerr << "Performing gzread of " << count << " byte for handle " << h << endl; + int err = gzread(zfile, buf, count); + cerr << "gzwrite returned " << err << endl; + if (err == -1) { + gzerror(zfile, &err); + if (err == Z_ERRNO) { + return -1; + } else { + return 0; + } + } + return err; + } else { + return ::read(h, buf, count); + } +} diff --git a/lib/Socket.cc b/lib/Socket.cc index a8c5beb..1d93bb5 100644 --- a/lib/Socket.cc +++ b/lib/Socket.cc @@ -13,7 +13,7 @@ #include "Output.h" #include "config.h" -Socket::Socket() throw (GeneralException) : Handle(socket(AF_INET, SOCK_STREAM, 0)), connected(false), listening(false) { +Socket::Socket() throw (GeneralException) : Handle(socket(AF_INET, SOCK_STREAM, 0)), connected(false), listening(false), writeclosed(false), readclosed(false) { if (GetHandle() < 0) { throw GeneralException(_("Error creating socket.")); } @@ -34,13 +34,26 @@ bool Socket::IsListening(void) { } bool Socket::CanRead(void) { - return connected; + return connected && !readclosed; } bool Socket::CanWrite(void) { - return connected; + return connected && !writeclosed; } +void Socket::CloseWrite(void) { + if (!writeclosed) { + writeclosed = true; + shutdown(GetHandle(), 1); + } +} + +void Socket::CloseRead(void) { + if (!readclosed) { + readclosed = true; + shutdown(GetHandle(), 0); + } +} /***********************************************\ * Toute la suite n'est pas à décrire. Consulter * |