Newer
Older
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
/*
This file is part of SLL.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
SLL is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
SLL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SLLo; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
# include "error.hh"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
/*******************************************************************************
** Public method
******************************************************************************/
/**
* Return the connection sate
* Cannot be const, du to mutex locking
*
* @return see description
*/
bool Connection::connected() {
// get connection mutex
pthread_mutex_lock(&c_mutex_);
bool ret = (socket_fd_ >= 0);
pthread_mutex_unlock(&c_mutex_);
return ret;
}
/**
* Send @param data on socket
*/
void Connection::send(const string &data) {
send(data.c_str(), data.length());
}
/**
* Send @param data followed by '\n' on socket
*/
void Connection::sendln(const string &data) {
string tosend = data + "\n";
send(tosend.c_str(), tosend.length());
}
/*******************************************************************************
** Protected method
******************************************************************************/
/**
* Free a socket
* No mutex used !
*/
void Connection::disconnect_() {
close(socket_fd_);
socket_fd_ = -1;
}
/**
* Reserve a socket
* No mutex used !
*/
void Connection::socket_() {
assert(socket_fd_ == -1);
int yes = 1;
if ((socket_fd_ = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
throw Error(ERR_NET, (string) "Unable to open socket: " + strerror(errno));
if (::setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
throw Error(ERR_NET, (string) "Unable to set socket options: " + strerror(errno));
}
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
/**
* Send @param size byte of @param buf into socket @param socket
* No mutex used!
*/
void Connection::send_(int socket_fd, const void *buf, size_t size) {
if (::send(socket_fd, buf, size, MSG_NOSIGNAL)) {
if (errno == ECONNRESET || errno == EPIPE)
throw Error(ERR_NET, "Connection reset by peer");
else
throw Error(ERR_NET, "send: " + (string) strerror(errno));
}
}
/**
* Send @param size byte of @param buf into socket @param socket
* No mutex used!
*/
int Connection::recv_(int socket_fd, void *buf, size_t size) {
int ret = ::recv(socket_fd, buf, size, 0);
if (ret == 0)
throw Error(ERR_NET, "Connection reset by peer");
else if (ret == -1)
throw Error(ERR_NET, (string) "recvln: " + strerror(errno));
return ret;
}
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/**
* Set local ip
* No mutex used !
*/
void Connection::setlocalip_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
if (::getsockname(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to get local ip: " + strerror(errno));
local_ip_ = inet_ntoa(addr.sin_addr);
}
/**
* Set local port
* No mutex used !
*/
void Connection::setlocalport_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
if (::getsockname(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to get local port: " + strerror(errno));
local_port_ = ntohs(addr.sin_port);
}
/**
* Set remote ip
* No mutex used !
*/
void Connection::setremoteip_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
// get socket
if (::getpeername(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to get remote ip: " + strerror(errno));
remote_ip_ = inet_ntoa(addr.sin_addr);
}
/**
* Set remote hostname
* No mutex used !
*/
void Connection::setremotehostname_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
// get sockaddr_in
if (::getpeername(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to get remote ip: " + strerror(errno));
if (remote_ip_.empty())
remote_ip_ = inet_ntoa(addr.sin_addr);
// get hostname
struct hostent *h;
if ((h = ::gethostbyaddr(&addr.sin_addr, sizeof addr.sin_addr, AF_INET)) == 0)
throw Error(ERR_NET, (string) "Unable to get remote hostname: " + hstrerror(h_errno));
remote_hostname_ = h->h_name;
}
/**
* Set remote port
* No mutex used !
*/
void Connection::setremoteport_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
if (::getpeername(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to get remote port: " + strerror(errno));
remote_port_ = ntohs(addr.sin_port);
}