X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/641204dfbdb9fc870cdd2e7f9e3169a44693e7bf..8c6fa3fbaccc22127280bf77a48fab5a3ee0716e:/projects/rlm_stg/stg_client.cpp diff --git a/projects/rlm_stg/stg_client.cpp b/projects/rlm_stg/stg_client.cpp index 7be0a55e..e34c50cd 100644 --- a/projects/rlm_stg/stg_client.cpp +++ b/projects/rlm_stg/stg_client.cpp @@ -18,303 +18,133 @@ * Author : Maxim Mamontov */ -/* - * Realization of data access via Stargazer for RADIUS - * - * $Revision: 1.8 $ - * $Date: 2010/04/16 12:30:02 $ - * - */ - -#include -#include -#include // close -#include - #include "stg_client.h" -using namespace std; +#include "conn.h" +#include "radlog.h" -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -STG_CLIENT::STG_CLIENT() - : port(0), - localPort(0), - sock(0) -{ -} -//----------------------------------------------------------------------------- -STG_CLIENT::~STG_CLIENT() -{ -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetServer(const string & host) -{ -STG_CLIENT::host = host; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetPort(uint16_t port) -{ -STG_CLIENT::port = port; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetLocalPort(uint16_t port) -{ -STG_CLIENT::localPort = port; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetPassword(const string & password) -{ -STG_CLIENT::password = password; -} -//----------------------------------------------------------------------------- -uint32_t STG_CLIENT::GetFramedIP() const -{ -return framedIP; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::InitEncrypt() -{ -unsigned char keyL[RAD_PASSWORD_LEN]; -memset(keyL, 0, RAD_PASSWORD_LEN); -strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN); -Blowfish_Init(&ctx, keyL, RAD_PASSWORD_LEN); -} -//----------------------------------------------------------------------------- -int STG_CLIENT::PrepareNet() -{ -sock = socket(AF_INET, SOCK_DGRAM, 0); -if (sock == -1) - { - errorStr = "Socket create error"; - return -1; - } +#include "stg/locker.h" +#include "stg/common.h" -struct hostent * he = NULL; -he = gethostbyname(host.c_str()); -if (he == NULL) - { - errorStr = "gethostbyname error"; - return -1; - } +#include +#include -if (localPort != 0) - { - struct sockaddr_in localAddr; - localAddr.sin_family = AF_INET; - localAddr.sin_port = htons(localPort); - localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");; +using STG::RLM::Client; +using STG::RLM::Conn; +using STG::RLM::RESULT; - if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr))) - { - errorStr = "Bind failed"; - return -1; - } - } - -outerAddr.sin_family = AF_INET; -outerAddr.sin_port = htons(port); -outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr; +namespace { -outerAddrLen = sizeof(struct sockaddr_in); +Client* stgClient = NULL; -return 0; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::FinalizeNet() -{ -close(sock); } -//----------------------------------------------------------------------------- -int STG_CLIENT::Start() -{ -InitEncrypt(); -return PrepareNet(); -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Stop() +class Client::Impl { -FinalizeNet(); + public: + explicit Impl(const std::string& address); + ~Impl(); -return 0; -} -//----------------------------------------------------------------------------- -string STG_CLIENT::GetUserPassword() const -{ -return userPassword; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Send(const RAD_PACKET & packet) -{ -char buf[RAD_MAX_PACKET_LEN]; - -Encrypt(buf, (char *)&packet, sizeof(RAD_PACKET) / 8); + bool stop() { return m_conn ? m_conn->stop() : true; } -int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, outerAddrLen); + RESULT request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); -if (res == -1) - errorStr = "Error sending data"; + private: + std::string m_address; + boost::scoped_ptr m_conn; -return res; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::RecvData(RAD_PACKET * packet) -{ -char buf[RAD_MAX_PACKET_LEN]; -int res; + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + bool m_done; + RESULT m_result; -outerAddrLen = sizeof(struct sockaddr_in); + static bool callback(void* data, const RESULT& result) + { + Impl& impl = *static_cast(data); + STG_LOCKER lock(impl.m_mutex); + impl.m_result = result; + impl.m_done = true; + pthread_cond_signal(&impl.m_cond); + return true; + } +}; -res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, (struct sockaddr *)&outerAddr, &outerAddrLen); -if (res == -1) +Client::Impl::Impl(const std::string& address) + : m_address(address) +{ + try { - errorStr = "Error receiving data"; - return -1; + m_conn.reset(new Conn(m_address, &Impl::callback, this)); } - -Decrypt((char *)packet, buf, res / 8); - -return 0; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType) -{ -int res; - -memcpy((void *)&packet->magic, (void *)RAD_ID, RAD_MAGIC_LEN); -packet->protoVer[0] = '0'; -packet->protoVer[1] = '1'; -packet->packetType = packetType; -packet->ip = 0; -strncpy((char *)packet->login, login.c_str(), RAD_LOGIN_LEN); -strncpy((char *)packet->service, svc.c_str(), RAD_SERVICE_LEN); - -res = Send(*packet); -if (res == -1) - return -1; - -res = RecvData(packet); -if (res == -1) - return -1; - -if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN)) + catch (const std::runtime_error& ex) { - errorStr = "Magic invalid. Wanted: '"; - errorStr += RAD_ID; - errorStr += "', got: '"; - errorStr += (char *)packet->magic; - errorStr += "'"; - return -1; + RadLog("Connection error: %s.", ex.what()); } - -return 0; + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); + m_done = false; } -//----------------------------------------------------------------------------- -int STG_CLIENT::Authorize(const string & login, const string & svc) -{ -RAD_PACKET packet; - -userPassword = ""; -if (Request(&packet, login, svc, RAD_AUTZ_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -userPassword = (char *)packet.password; - -return 0; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Authenticate(const string & login, const string & svc) +Client::Impl::~Impl() { -RAD_PACKET packet; - -userPassword = ""; - -if (Request(&packet, login, svc, RAD_AUTH_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -return 0; + pthread_cond_destroy(&m_cond); + pthread_mutex_destroy(&m_mutex); } -//----------------------------------------------------------------------------- -int STG_CLIENT::PostAuthenticate(const string & login, const string & svc) -{ -RAD_PACKET packet; - -userPassword = ""; - -if (Request(&packet, login, svc, RAD_POST_AUTH_PACKET)) - return -1; -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -if (svc == "Framed-User") - framedIP = packet.ip; -else - framedIP = 0; - -return 0; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Account(const std::string & type, const string & login, const string & svc, const string & sessid) +RESULT Client::Impl::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) { -RAD_PACKET packet; + STG_LOCKER lock(m_mutex); + if (!m_conn || !m_conn->connected()) + m_conn.reset(new Conn(m_address, &Impl::callback, this)); + if (!m_conn->connected()) + throw Conn::Error("Failed to create connection to '" + m_address + "'."); -userPassword = ""; -strncpy((char *)packet.sessid, sessid.c_str(), RAD_SESSID_LEN); + m_done = false; + m_conn->request(type, userName, password, pairs); + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 5; + int res = 0; + while (!m_done && res == 0) + res = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); + if (res != 0) + throw Conn::Error("Request failed."); + return m_result; +} -if (type == "Start") - { - if (Request(&packet, login, svc, RAD_ACCT_START_PACKET)) - return -1; - } -else if (type == "Stop") - { - if (Request(&packet, login, svc, RAD_ACCT_STOP_PACKET)) - return -1; - } -else if (type == "Interim-Update") - { - if (Request(&packet, login, svc, RAD_ACCT_UPDATE_PACKET)) - return -1; - } -else - { - if (Request(&packet, login, svc, RAD_ACCT_OTHER_PACKET)) - return -1; - } +Client::Client(const std::string& address) + : m_impl(new Impl(address)) +{ +} -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; +Client::~Client() +{ +} -return 0; +bool Client::stop() +{ + return m_impl->stop(); } -//----------------------------------------------------------------------------- -void STG_CLIENT::Encrypt(char * dst, const char * src, int len8) + +RESULT Client::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) { -// len8 - длина в 8-ми байтовых блоках -if (dst != src) - memcpy(dst, src, len8 * 8); - -for (int i = 0; i < len8; i++) - Blowfish_Encrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4)); + return m_impl->request(type, userName, password, pairs); } -//----------------------------------------------------------------------------- -void STG_CLIENT::Decrypt(char * dst, const char * src, int len8) + +Client* Client::get() { -// len8 - длина в 8-ми байтовых блоках -if (dst != src) - memcpy(dst, src, len8 * 8); + return stgClient; +} -for (int i = 0; i < len8; i++) - Blowfish_Decrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4)); +bool Client::configure(const std::string& address) +{ + if ( stgClient != NULL ) + return stgClient->configure(address); + try { + stgClient = new Client(address); + return true; + } catch (const std::exception& ex) { + RadLog("Client configuration error: %s.", ex.what()); + } + return false; } -//-----------------------------------------------------------------------------