⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.23
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
local
/
src
/
libmemcached-1.0.18
/
libtest
/
View File Name :
client.cc
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: * * Data Differential YATL (i.e. libtest) library * * Copyright (C) 2012 Data Differential, http://datadifferential.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * * The names of its contributors may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "libtest/yatlcon.h" #include <libtest/common.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <string> #ifdef HAVE_POLL_H # include <poll.h> #endif #ifndef HAVE_MSG_NOSIGNAL # define MSG_NOSIGNAL 0 #endif namespace libtest { SimpleClient::SimpleClient(const std::string& hostname_, in_port_t port_) : _is_connected(false), _hostname(hostname_), _port(port_), sock_fd(INVALID_SOCKET), requested_message(1) { } bool SimpleClient::ready(int event_) { struct pollfd fds[1]; fds[0].fd= sock_fd; fds[0].events= event_; fds[0].revents= 0; int timeout= 5000; if (_is_connected == false) { timeout= timeout * 30; } int ready_fds= poll(fds, 1, timeout); if (ready_fds == -1) { _error= strerror(errno); return false; } else if (ready_fds == 1) { if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { int err; socklen_t len= sizeof (err); // We replace errno with err if getsockopt() passes, but err has been // set. if (getsockopt(fds[0].fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0) { // We check the value to see what happened wth the socket. if (err == 0) { _error= "getsockopt() returned no error but poll() indicated one existed"; return false; } errno= err; } _error= strerror(errno); return false; } _is_connected= true; if (fds[0].revents & event_) { return true; } } fatal_assert(ready_fds == 0); _error= "TIMEOUT"; return false; } struct addrinfo* SimpleClient::lookup() { struct addrinfo *ai= NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype= SOCK_STREAM; hints.ai_protocol= IPPROTO_TCP; libtest::vchar_t service; service.resize(NI_MAXSERV); (void)snprintf(&service[0], service.size(), "%d", _port); int getaddrinfo_error; if ((getaddrinfo_error= getaddrinfo(_hostname.c_str(), &service[0], &hints, &ai)) != 0) { if (getaddrinfo_error != EAI_SYSTEM) { _error= gai_strerror(getaddrinfo_error); return NULL; } else { _error= strerror(getaddrinfo_error); return NULL; } } return ai; } SimpleClient::~SimpleClient() { close_socket(); } void SimpleClient::close_socket() { if (sock_fd != INVALID_SOCKET) { close(sock_fd); sock_fd= INVALID_SOCKET; } } bool SimpleClient::instance_connect() { _is_connected= false; struct addrinfo *ai; if ((ai= lookup())) { { struct addrinfo* address_info_next= ai; while (address_info_next and sock_fd == INVALID_SOCKET) { if ((sock_fd= socket(address_info_next->ai_family, address_info_next->ai_socktype, address_info_next->ai_protocol)) != SOCKET_ERROR) { if (connect(sock_fd, address_info_next->ai_addr, address_info_next->ai_addrlen) == SOCKET_ERROR) { switch (errno) { case EINTR: close_socket(); continue; case EINPROGRESS: // nonblocking mode - first return case EALREADY: // nonblocking mode - subsequent returns continue; // Jump to while() and continue on case ECONNREFUSED: default: break; } close_socket(); _error= strerror(errno); } } else { FATAL(strerror(errno)); } address_info_next= address_info_next->ai_next; } freeaddrinfo(ai); } if (sock_fd == INVALID_SOCKET) { fatal_assert(_error.size()); } return bool(sock_fd != INVALID_SOCKET); } return false; } bool SimpleClient::is_valid() { _error.clear(); if (sock_fd == INVALID_SOCKET) { return instance_connect(); } return true; } bool SimpleClient::message(const char* ptr, const size_t len) { if (is_valid()) { if (ready(POLLOUT)) { off_t offset= 0; do { ssize_t nw= send(sock_fd, ptr + offset, len - offset, MSG_NOSIGNAL); if (nw == -1) { if (errno != EINTR) { _error= strerror(errno); return false; } } else { offset += nw; } } while (offset < ssize_t(len)); return true; } } fatal_assert(_error.size()); return false; } bool SimpleClient::send_message(const std::string& arg) { if (message(arg.c_str(), arg.size()) == true) { return message("\r\n", 2); } return false; } bool SimpleClient::send_data(const libtest::vchar_t& message_, libtest::vchar_t& response_) { requested_message++; if (message(&message_[0], message_.size())) { return response(response_); } return false; } bool SimpleClient::send_message(const std::string& message_, std::string& response_) { requested_message++; if (send_message(message_)) { return response(response_); } 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_) { 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 { fatal_assert(nr == 1); if (buffer[0] == '\n') { more= false; } response_.append(buffer); } } while (more); return response_.size(); } } fatal_assert(_error.size()); return false; } } // namespace libtest