client.cc | client.cc | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* | * | |||
*/ | */ | |||
#include "mem_config.h" | #include "libtest/yatlcon.h" | |||
#include <libtest/common.h> | #include <libtest/common.h> | |||
#ifdef HAVE_POLL_H | ||||
# include <poll.h> | ||||
#endif | ||||
#include <sys/types.h> | #include <sys/types.h> | |||
#include <sys/socket.h> | #include <sys/socket.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <string> | #include <string> | |||
#ifdef HAVE_POLL_H | ||||
# include <poll.h> | ||||
#endif | ||||
#ifndef HAVE_MSG_NOSIGNAL | #ifndef HAVE_MSG_NOSIGNAL | |||
# define MSG_NOSIGNAL 0 | # define MSG_NOSIGNAL 0 | |||
#endif | #endif | |||
namespace libtest { | namespace libtest { | |||
SimpleClient::SimpleClient(const std::string& hostname_, in_port_t port_) : | SimpleClient::SimpleClient(const std::string& hostname_, in_port_t port_) : | |||
_is_connected(false), | ||||
_hostname(hostname_), | _hostname(hostname_), | |||
_port(port_), | _port(port_), | |||
sock_fd(INVALID_SOCKET), | sock_fd(INVALID_SOCKET), | |||
requested_message(1) | requested_message(1) | |||
{ | { | |||
} | } | |||
bool SimpleClient::ready(int event_) | bool SimpleClient::ready(int event_) | |||
{ | { | |||
struct pollfd fds[1]; | struct pollfd fds[1]; | |||
fds[0].fd= sock_fd; | fds[0].fd= sock_fd; | |||
fds[0].events= event_; | fds[0].events= event_; | |||
fds[0].revents= 0; | fds[0].revents= 0; | |||
int ready_fds= poll(fds, 1, 5000); | int timeout= 5000; | |||
if (_is_connected == false) | ||||
{ | ||||
timeout= timeout * 30; | ||||
} | ||||
int ready_fds= poll(fds, 1, timeout); | ||||
if (ready_fds == -1) | if (ready_fds == -1) | |||
{ | { | |||
_error= strerror(errno); | _error= strerror(errno); | |||
return false; | return false; | |||
} | } | |||
else if (ready_fds == 1) | else if (ready_fds == 1) | |||
{ | { | |||
if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) | if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) | |||
{ | { | |||
skipping to change at line 101 | skipping to change at line 107 | |||
_error= "getsockopt() returned no error but poll() indicated one existed"; | _error= "getsockopt() returned no error but poll() indicated one existed"; | |||
return false; | return false; | |||
} | } | |||
errno= err; | errno= err; | |||
} | } | |||
_error= strerror(errno); | _error= strerror(errno); | |||
return false; | return false; | |||
} | } | |||
_is_connected= true; | ||||
if (fds[0].revents & event_) | if (fds[0].revents & event_) | |||
{ | { | |||
return true; | return true; | |||
} | } | |||
} | } | |||
fatal_assert(ready_fds == 0); | fatal_assert(ready_fds == 0); | |||
_error= "TIMEOUT"; | _error= "TIMEOUT"; | |||
return false; | return false; | |||
} | } | |||
struct addrinfo* SimpleClient::lookup() | struct addrinfo* SimpleClient::lookup() | |||
{ | { | |||
struct addrinfo *ai= NULL; | struct addrinfo *ai= NULL; | |||
struct addrinfo hints; | struct addrinfo hints; | |||
memset(&hints, 0, sizeof(struct addrinfo)); | memset(&hints, 0, sizeof(struct addrinfo)); | |||
hints.ai_socktype= SOCK_STREAM; | hints.ai_socktype= SOCK_STREAM; | |||
hints.ai_protocol= IPPROTO_TCP; | hints.ai_protocol= IPPROTO_TCP; | |||
char service[NI_MAXSERV]; | libtest::vchar_t service; | |||
(void)snprintf(service, NI_MAXSERV, "%d", _port); | service.resize(NI_MAXSERV); | |||
(void)snprintf(&service[0], service.size(), "%d", _port); | ||||
int getaddrinfo_error; | int getaddrinfo_error; | |||
if ((getaddrinfo_error= getaddrinfo(_hostname.c_str(), service, &hints, & ai)) != 0) | if ((getaddrinfo_error= getaddrinfo(_hostname.c_str(), &service[0], &hint s, &ai)) != 0) | |||
{ | { | |||
if (getaddrinfo_error != EAI_SYSTEM) | if (getaddrinfo_error != EAI_SYSTEM) | |||
{ | { | |||
_error= gai_strerror(getaddrinfo_error); | _error= gai_strerror(getaddrinfo_error); | |||
return NULL; | return NULL; | |||
} | } | |||
else | else | |||
{ | { | |||
_error= strerror(getaddrinfo_error); | _error= strerror(getaddrinfo_error); | |||
return NULL; | return NULL; | |||
skipping to change at line 149 | skipping to change at line 157 | |||
return ai; | return ai; | |||
} | } | |||
SimpleClient::~SimpleClient() | SimpleClient::~SimpleClient() | |||
{ | { | |||
close_socket(); | close_socket(); | |||
} | } | |||
void SimpleClient::close_socket() | void SimpleClient::close_socket() | |||
{ | { | |||
close(sock_fd); | if (sock_fd != INVALID_SOCKET) | |||
sock_fd= INVALID_SOCKET; | { | |||
close(sock_fd); | ||||
sock_fd= INVALID_SOCKET; | ||||
} | ||||
} | } | |||
bool SimpleClient::instance_connect() | bool SimpleClient::instance_connect() | |||
{ | { | |||
_is_connected= false; | ||||
struct addrinfo *ai; | struct addrinfo *ai; | |||
if ((ai= lookup())) | if ((ai= lookup())) | |||
{ | { | |||
{ | { | |||
struct addrinfo* address_info_next= ai; | struct addrinfo* address_info_next= ai; | |||
while (address_info_next and sock_fd == INVALID_SOCKET) | while (address_info_next and sock_fd == INVALID_SOCKET) | |||
{ | { | |||
if ((sock_fd= socket(address_info_next->ai_family, address_info_nex t->ai_socktype, address_info_next->ai_protocol)) != SOCKET_ERROR) | if ((sock_fd= socket(address_info_next->ai_family, address_info_nex t->ai_socktype, address_info_next->ai_protocol)) != SOCKET_ERROR) | |||
{ | { | |||
skipping to change at line 203 | skipping to change at line 215 | |||
{ | { | |||
_error.clear(); | _error.clear(); | |||
if (sock_fd == INVALID_SOCKET) | if (sock_fd == INVALID_SOCKET) | |||
{ | { | |||
return instance_connect(); | return instance_connect(); | |||
} | } | |||
return true; | return true; | |||
} | } | |||
bool SimpleClient::message(const std::string& arg) | bool SimpleClient::message(const char* ptr, const size_t len) | |||
{ | { | |||
if (is_valid()) | if (is_valid()) | |||
{ | { | |||
if (ready(POLLOUT)) | if (ready(POLLOUT)) | |||
{ | { | |||
off_t offset= 0; | off_t offset= 0; | |||
const char* ptr= arg.c_str(); | ||||
size_t len= arg.size(); | ||||
do | do | |||
{ | { | |||
ssize_t nw= send(sock_fd, ptr + offset, len - offset, MSG_NOSIGNAL) ; | ssize_t nw= send(sock_fd, ptr + offset, len - offset, MSG_NOSIGNAL) ; | |||
if (nw == -1) | if (nw == -1) | |||
{ | { | |||
if (errno != EINTR) | if (errno != EINTR) | |||
{ | { | |||
_error= strerror(errno); | _error= strerror(errno); | |||
return false; | return false; | |||
} | } | |||
skipping to change at line 241 | skipping to change at line 250 | |||
} | } | |||
} | } | |||
fatal_assert(_error.size()); | fatal_assert(_error.size()); | |||
return false; | return false; | |||
} | } | |||
bool SimpleClient::send_message(const std::string& arg) | bool SimpleClient::send_message(const std::string& arg) | |||
{ | { | |||
if (message(arg) == true) | if (message(arg.c_str(), arg.size()) == true) | |||
{ | { | |||
return message("\r\n"); | return message("\r\n", 2); | |||
} | ||||
return false; | ||||
} | ||||
bool SimpleClient::send_data(const libtest::vchar_t& message_, libtest::vch | ||||
ar_t& response_) | ||||
{ | ||||
requested_message++; | ||||
if (message(&message_[0], message_.size())) | ||||
{ | ||||
return response(response_); | ||||
} | } | |||
return false; | return false; | |||
} | } | |||
bool SimpleClient::send_message(const std::string& message_, std::string& r esponse_) | bool SimpleClient::send_message(const std::string& message_, std::string& r esponse_) | |||
{ | { | |||
requested_message++; | requested_message++; | |||
if (send_message(message_)) | if (send_message(message_)) | |||
{ | { | |||
return response(response_); | return response(response_); | |||
} | } | |||
return false; | return false; | |||
} | } | |||
bool SimpleClient::response(libtest::vchar_t& response_) | ||||
{ | ||||
response_.clear(); | ||||
if (is_valid()) | ||||
{ | ||||
if (ready(POLLIN)) | ||||
{ | ||||
bool more= true; | ||||
char buffer[2]; | ||||
buffer[1]= 0; | ||||
do | ||||
{ | ||||
ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL); | ||||
if (nr == -1) | ||||
{ | ||||
if (errno != EINTR) | ||||
{ | ||||
_error= strerror(errno); | ||||
return false; | ||||
} | ||||
} | ||||
else if (nr == 0) | ||||
{ | ||||
close_socket(); | ||||
more= false; | ||||
} | ||||
else | ||||
{ | ||||
response_.reserve(response_.size() + nr +1); | ||||
fatal_assert(nr == 1); | ||||
if (buffer[0] == '\n') | ||||
{ | ||||
more= false; | ||||
} | ||||
response_.insert(response_.end(), buffer, buffer +nr); | ||||
} | ||||
} while (more); | ||||
return response_.size(); | ||||
} | ||||
} | ||||
fatal_assert(_error.size()); | ||||
return false; | ||||
} | ||||
bool SimpleClient::response(std::string& response_) | bool SimpleClient::response(std::string& response_) | |||
{ | { | |||
response_.clear(); | response_.clear(); | |||
if (is_valid()) | if (is_valid()) | |||
{ | { | |||
if (ready(POLLIN)) | if (ready(POLLIN)) | |||
{ | { | |||
bool more= true; | bool more= true; | |||
char buffer[2]; | char buffer[2]; | |||
skipping to change at line 282 | skipping to change at line 349 | |||
{ | { | |||
ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL); | ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL); | |||
if (nr == -1) | if (nr == -1) | |||
{ | { | |||
if (errno != EINTR) | if (errno != EINTR) | |||
{ | { | |||
_error= strerror(errno); | _error= strerror(errno); | |||
return false; | return false; | |||
} | } | |||
} | } | |||
else if (nr == 0) | ||||
{ | ||||
close_socket(); | ||||
more= false; | ||||
} | ||||
else | else | |||
{ | { | |||
fatal_assert(nr == 1); | fatal_assert(nr == 1); | |||
if (buffer[0] == '\n') | if (buffer[0] == '\n') | |||
{ | { | |||
more= false; | more= false; | |||
} | } | |||
response_.append(buffer); | response_.append(buffer); | |||
} | } | |||
} while (more); | } while (more); | |||
End of changes. 16 change blocks. | ||||
18 lines changed or deleted | 91 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |