summaryrefslogtreecommitdiff
path: root/lib/Socket.cc
blob: 5d80783d4e8d572656504f0b68f194182a478d69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.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;
}


    /***********************************************\
    * 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) {
	cerr << " - Resolving '" << host << "'..." << endl;
        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);
	cerr << " - Connecting to port " << port << " ..." << endl;
	if (!connect(GetHandle(), (struct sockaddr *)&remotesocketaddr, sizeof(remotesocketaddr))) {
	    cerr << " - Connected." << endl;
	    connected = true;
	} else {
	    cerr << " - Error connecting: " << strerror(errno) << endl;
	}
    }
    return connected;
}

bool Socket::Listen(void) {
    if (!listening && !connected) {
	if (listen(GetHandle(), 10)) {
	    listening = true;
	}
    }
    return listening;
}

Socket Socket::Accept(void) throw (GeneralException) {
    struct sockaddr inaddr;
    socklen_t inlen = sizeof(inaddr);
    int h;

    if ((h = accept(GetHandle(), &inaddr, &inlen)) < 0) {
	throw GeneralException("Failed accepting.");
    } else {
	return Socket(h);
    }
}