summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Handle.h8
-rw-r--r--include/Socket.h4
-rw-r--r--lib/Handle.cc100
-rw-r--r--lib/Socket.cc19
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 *