From 8783b1559a2bb8b0a18253c776e40ed581af39d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Luttringer?= Date: Wed, 16 Jan 2008 17:34:39 +0000 Subject: [PATCH] Derniere version sll --- slc/trunk/src/screen.cc | 2 +- slc/trunk/src/sll/connection.cc | 133 +++++++++++++++---------------- slc/trunk/src/sll/connection.hh | 6 +- slc/trunk/src/sll/connection.hxx | 46 +++++++---- 4 files changed, 95 insertions(+), 92 deletions(-) diff --git a/slc/trunk/src/screen.cc b/slc/trunk/src/screen.cc index 7821bbf..4f37f14 100644 --- a/slc/trunk/src/screen.cc +++ b/slc/trunk/src/screen.cc @@ -540,7 +540,7 @@ void Screen::cmd_exec(const char *s) { // String is a remote command else { if (C.connected()) { - C.sendln(s, strlen(s)); + C.sendln(s); S << ">> " << s << "\n"; } else S << "Unable to send: " << s << ". Try to reconnect with /login !\n"; diff --git a/slc/trunk/src/sll/connection.cc b/slc/trunk/src/sll/connection.cc index f6b745d..a688f02 100644 --- a/slc/trunk/src/sll/connection.cc +++ b/slc/trunk/src/sll/connection.cc @@ -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; diff --git a/slc/trunk/src/sll/connection.hh b/slc/trunk/src/sll/connection.hh index 1581700..2c89e9b 100644 --- a/slc/trunk/src/sll/connection.hh +++ b/slc/trunk/src/sll/connection.hh @@ -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_(); diff --git a/slc/trunk/src/sll/connection.hxx b/slc/trunk/src/sll/connection.hxx index c5fdf3e..3440140 100644 --- a/slc/trunk/src/sll/connection.hxx +++ b/slc/trunk/src/sll/connection.hxx @@ -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); } -- GitLab