diff options
Diffstat (limited to 'lib/Socket.cc')
-rw-r--r-- | lib/Socket.cc | 140 |
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); + } +} |