summaryrefslogtreecommitdiff
path: root/lib/Socket.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Socket.cc')
-rw-r--r--lib/Socket.cc140
1 files changed, 140 insertions, 0 deletions
diff --git a/lib/Socket.cc b/lib/Socket.cc
new file mode 100644
index 0000000..100d434
--- /dev/null
+++ b/lib/Socket.cc
@@ -0,0 +1,140 @@
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include "String.h"
+#include "Socket.h"
+#include "Exceptions.h"
+#include "config.h"
+#include "Input.h"
+#include "Output.h"
+
+Socket::Socket() throw (GeneralException) : Handle(socket(AF_INET, SOCK_STREAM, 0)), connected(false), listening(false) {
+ if (GetHandle() < 0) {
+ throw GeneralException("Error creating socket.");
+ }
+}
+
+Socket::Socket(int h) : Handle(h), connected(true), listening(false) { }
+
+String Socket::GetName(void) {
+ return String("socket");
+}
+
+bool Socket::IsConnected(void) {
+ return connected;
+}
+
+bool Socket::IsListening(void) {
+ return listening;
+}
+
+bool Socket::CanRead(void) {
+ return connected;
+}
+
+bool Socket::CanWrite(void) {
+ return connected;
+}
+
+size_t Socket::WriteFile(Output & o) {
+ char c;
+ size_t s = 0;
+
+ while (!IsClosed()) {
+ s += read(&c, 1);
+ o.write(&c, 1);
+ }
+ return s;
+}
+
+size_t Socket::ReadFile(Input & i) {
+ char c;
+ size_t s = 0;
+
+ while (!i.IsClosed()) {
+ s += i.read(&c, 1);
+ write(&c, 1);
+ }
+ return s;
+}
+
+
+ /***********************************************\
+ * Toute la suite n'est pas à décrire. Consulter *
+ * plutôt un document décrivant les sockets. *
+ \***********************************************/
+
+
+bool Socket::SetLocal(String vhost, int port) {
+ struct hostent * localhostent;
+ struct in_addr localhostaddr;
+ struct sockaddr_in localsocketaddr;
+
+
+ memset((void *)&localhostaddr, 0, sizeof(localhostaddr));
+
+ if (vhost.strlen() != 0) {
+ if ((localhostent = gethostbyname(vhost.to_charp()))) {
+ memcpy((void *)&localhostaddr, localhostent->h_addr, sizeof(localhostaddr));
+ } else {
+ return false;
+ }
+ } else {
+ localhostaddr.s_addr = htonl(INADDR_ANY);
+ }
+
+ memset(&localsocketaddr, 0, sizeof(struct sockaddr_in));
+ localsocketaddr.sin_family = AF_INET;
+ localsocketaddr.sin_addr = localhostaddr;
+ localsocketaddr.sin_port = htons(port);
+
+ if (bind(GetHandle(), (struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool Socket::Connect(String host, int port) {
+ struct hostent * remotehostent;
+ struct sockaddr_in remotesocketaddr;
+
+ if (!listening && !connected) {
+ if (!(remotehostent = gethostbyname(host.to_charp()))) {
+ return false;
+ }
+
+ remotesocketaddr.sin_family = AF_INET;
+ remotesocketaddr.sin_port = htons(port);
+ bcopy(remotehostent->h_addr, &remotesocketaddr.sin_addr, remotehostent->h_length);
+ if(connect(GetHandle(), (struct sockaddr *)&remotesocketaddr, sizeof(remotesocketaddr)) < 0) {
+ connected = true;
+ }
+ }
+ return connected;
+}
+
+bool Socket::Listen(void) {
+ if (!listening && !connected) {
+ if (listen(GetHandle(), 10)) {
+ listening = true;
+ }
+ }
+ return listening;
+}
+
+Socket Socket::Accept(void) {
+ struct sockaddr inaddr;
+ socklen_t inlen = sizeof(inaddr);
+ int h;
+
+ if ((h = accept(GetHandle(), &inaddr, &inlen)) < 0) {
+ return Socket();
+ } else {
+ return Socket(h);
+ }
+}