Commit 9d5f9a22 authored by Seblu's avatar Seblu

new versions from sls

parent e6982f80
......@@ -51,7 +51,13 @@ Connection::Connection(int fd) : socket_fd_(fd), local_port_(-1), remote_port_(-
if (socket_fd_ >= 0) {
id_ = getconnid();
setconninfo_();
try {
setlocalip_();
setlocalport_();
setremoteip_();
setremoteport_();
}
catch (...) { }
}
}
......@@ -87,24 +93,6 @@ void Connection::disconnect() {
pthread_mutex_unlock(&c_mutex_);
}
/**
* 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;
}
/**
* Create connection with @param addr on port @param port
*/
......@@ -156,15 +144,27 @@ void Connection::connect(const char *addr, int port) {
// connect
if (::connect(socket_fd_, (struct sockaddr *) &daddr, sizeof daddr) == -1) {
int errno__ = errno;
disconnect_();
pthread_mutex_unlock(&w_mutex_);
pthread_mutex_unlock(&r_mutex_);
pthread_mutex_unlock(&c_mutex_);
throw Error(ERR_NET, (string) "Unable to connect to " + addr + ": " + hstrerror(h_errno));
throw Error(ERR_NET, (string) "Unable to connect to " + addr + ": " + strerror(errno__));
}
// set infos
setconninfo_();
try {
setlocalip_();
setlocalport_();
setremoteip_();
setremoteport_();
}
catch (...) {
pthread_mutex_unlock(&w_mutex_);
pthread_mutex_unlock(&r_mutex_);
pthread_mutex_unlock(&c_mutex_);
throw;
}
pthread_mutex_unlock(&w_mutex_);
pthread_mutex_unlock(&r_mutex_);
......@@ -229,7 +229,16 @@ void Connection::listen(int port, int max) {
}
// set all infos
setconninfo_();
try {
setlocalip_();
setlocalport_();
}
catch (...) {
pthread_mutex_unlock(&w_mutex_);
pthread_mutex_unlock(&r_mutex_);
pthread_mutex_unlock(&c_mutex_);
throw;
}
pthread_mutex_unlock(&w_mutex_);
pthread_mutex_unlock(&r_mutex_);
......@@ -274,72 +283,59 @@ Connection *Connection::accept() {
* Send data on @param buf of size @param len on socket
*/
void Connection::send(const char* buf, size_t len) {
// keep the socket fd
// lock mutex for operation
pthread_mutex_lock(&c_mutex_);
pthread_mutex_lock(&w_mutex_);
// retreive socket_fd and free conn mutex
int socket_fd = socket_fd_;
pthread_mutex_unlock(&c_mutex_);
// test socket validity
if (socket_fd < 0)
if (socket_fd < 0) {
pthread_mutex_unlock(&w_mutex_);
throw Error(ERR_NET, "No connection established but trying to send data");
}
// send is a write operation
pthread_mutex_lock(&w_mutex_);
int ret = ::send(socket_fd_, buf, len, 0);
pthread_mutex_unlock(&w_mutex_);
if (ret == -1 && errno == ECONNRESET)
throw Error(ERR_NET, "Connection reset by peer");
if (ret == -1)
throw Error(ERR_NET, "send: " + (string) strerror(errno));
}
/**
* Send data on @param buf of size @param len followed by '\n' on socket
*/
void Connection::sendln(const char* buf, size_t len) {
// keep the socket fd
pthread_mutex_lock(&c_mutex_);
int socket_fd = socket_fd_;
pthread_mutex_unlock(&c_mutex_);
// test socket validity
if (socket_fd < 0)
throw Error(ERR_NET, "No connection established but trying to send line");
int ret = ::send(socket_fd_, buf, len, MSG_NOSIGNAL);
// send is a write op
pthread_mutex_lock(&w_mutex_);
// write data
int ret = ::send(socket_fd, buf, len, 0);
// treat error
if (ret == -1) {
pthread_mutex_unlock(&w_mutex_);
if (errno == ECONNRESET)
int errno__ = errno;
pthread_mutex_lock(&c_mutex_);
pthread_mutex_lock(&r_mutex_);
disconnect_();
pthread_mutex_unlock(&r_mutex_);
pthread_mutex_unlock(&c_mutex_);
pthread_mutex_unlock(&r_mutex_);
if (errno__ == ECONNRESET || errno__ == EPIPE)
throw Error(ERR_NET, "Connection reset by peer");
throw Error(ERR_NET, "sendln: " + (string) strerror(errno));
else
throw Error(ERR_NET, "send: " + (string) strerror(errno__));
}
// write '\n'
ret = ::send(socket_fd, "\n", 1, 0);
// release the mutex
pthread_mutex_unlock(&w_mutex_);
if (ret == -1)
throw Error(ERR_NET, "sendln: " + (string) strerror(errno));
}
/**
* Receive a line
*/
string Connection::recvln() {
// keep the socket fd
// lock mutex for operation
pthread_mutex_lock(&c_mutex_);
pthread_mutex_lock(&r_mutex_);
int socket_fd = socket_fd_;
pthread_mutex_unlock(&c_mutex_);
// test socket validity
if (socket_fd < 0)
if (socket_fd < 0) {
pthread_mutex_unlock(&r_mutex_);
throw Error(ERR_NET, "No connection established but trying to receive line");
}
// recv is a read opearation
pthread_mutex_lock(&r_mutex_);
do {
// check EOL char
size_t offset = rbuf_.find('\n');
......@@ -354,25 +350,22 @@ string Connection::recvln() {
static char local_buf[MAX_LINE_SIZE];
int ret = ::recv(socket_fd, local_buf, MAX_LINE_SIZE, 0);
if (ret == 0) {
if (ret == -1 || ret == 0) {
pthread_mutex_lock(&c_mutex_);
pthread_mutex_lock(&w_mutex_);
disconnect_();
pthread_mutex_unlock(&r_mutex_);
pthread_mutex_unlock(&c_mutex_);
pthread_mutex_unlock(&r_mutex_);
throw Error(ERR_NET, "Connection reset by peer");
}
if (ret == -1) {
*local_buf = 0;
// unlock before error
pthread_mutex_unlock(&r_mutex_);
throw Error(ERR_NET, (string) "recvln: " + strerror(errno));
if (ret == 0)
throw Error(ERR_NET, "Connection reset by peer");
else
throw Error(ERR_NET, (string) "recvln: " + strerror(errno));
}
else local_buf[ret] = 0;
local_buf[ret] = 0;
// add read data in buffer
rbuf_ += local_buf;
......
......@@ -35,15 +35,14 @@ public:
void listen(int port, int max);
void disconnect();
bool connected();
inline bool connected();
Connection *accept();
// send methods
inline void send(const string &data);
void send(const char* buf, size_t len);
inline void send(const string &data);
inline void sendln(const string &data);
void sendln(const char* buf, size_t len);
// recv methods
string recvln();
......@@ -64,7 +63,6 @@ protected:
inline void socket_();
inline void disconnect_();
inline void setconninfo_();
inline void setlocalip_();
inline void setlocalport_();
inline void setremoteip_();
......
......@@ -27,6 +27,24 @@
** 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
*/
......@@ -38,30 +56,20 @@ void Connection::send(const string &data) {
* Send @param data followed by '\n' on socket
*/
void Connection::sendln(const string &data) {
sendln(data.c_str(), data.length());
string tosend = data + "\n";
send(tosend.c_str(), tosend.length());
}
/*******************************************************************************
** Protected method
******************************************************************************/
/**
* Set all information about a connection
*/
void Connection::setconninfo_() {
setlocalip_();
setlocalport_();
setremoteip_();
setremoteport_();
}
/**
* Free a socket
* No mutex used !
*/
void Connection::disconnect_() {
if (socket_fd_ == -1)
return;
assert(socket_fd_ >= 0);
close(socket_fd_);
socket_fd_ = -1;
......@@ -90,7 +98,8 @@ void Connection::setlocalip_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
::getsockname(socket_fd_, (struct sockaddr*) &addr, &len);
if (::getsockname(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to set local ip: " + strerror(errno));
local_ip_ = inet_ntoa(addr.sin_addr);
}
......@@ -102,7 +111,8 @@ void Connection::setlocalport_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
::getsockname(socket_fd_, (struct sockaddr*) &addr, &len);
if (::getsockname(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to set local port: " + strerror(errno));
local_port_ = ntohs(addr.sin_port);
}
......@@ -114,7 +124,8 @@ void Connection::setremoteip_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
::getpeername(socket_fd_, (struct sockaddr*) &addr, &len);
if (::getpeername(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to set remote ip: " + strerror(errno));
remote_ip_ = inet_ntoa(addr.sin_addr);
}
......@@ -126,6 +137,7 @@ void Connection::setremoteport_() {
struct sockaddr_in addr;
socklen_t len = sizeof addr;
::getpeername(socket_fd_, (struct sockaddr*) &addr, &len);
if (::getpeername(socket_fd_, (struct sockaddr*) &addr, &len) != 0)
throw Error(ERR_NET, (string) "Unable to set remote port: " + strerror(errno));
remote_port_ = ntohs(addr.sin_port);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment