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); +    } +} | 
