X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/2db7e7236c61f8ee346800c82c800eafcd65de4e..35b724400e504ae6f69a478339e4549475957bb9:/projects/rlm_stg/iface.cpp diff --git a/projects/rlm_stg/iface.cpp b/projects/rlm_stg/iface.cpp index 40a96f72..d99dd393 100644 --- a/projects/rlm_stg/iface.cpp +++ b/projects/rlm_stg/iface.cpp @@ -1,11 +1,37 @@ #include "iface.h" #include "stg_client.h" +#include "radlog.h" + +#include + +#include namespace { -STG_PAIR* toPairs(const PAIRS& source) +struct Response +{ + bool done; + pthread_mutex_t mutex; + pthread_cond_t cond; + RESULT result; + bool status; + + static bool callback(void* data, const RESULT& result, bool status) + { + Response& resp = *static_cast(data); + pthread_mutex_lock(&resp.mutex); + resp.result = result; + resp.status = status; + resp.done = true; + pthread_cond_signal(&resp.cond); + pthread_mutex_unlock(&resp.mutex); + return true; + } +} response; + +STG_PAIR* toSTGPairs(const PAIRS& source) { STG_PAIR * pairs = new STG_PAIR[source.size() + 1]; for (size_t pos = 0; pos < source.size(); ++pos) { @@ -13,103 +39,116 @@ STG_PAIR* toPairs(const PAIRS& source) bzero(pairs[pos].value, sizeof(STG_PAIR::value)); strncpy(pairs[pos].key, source[pos].first.c_str(), sizeof(STG_PAIR::key)); strncpy(pairs[pos].value, source[pos].second.c_str(), sizeof(STG_PAIR::value)); - ++pos; } - bzero(pairs[sources.size()].key, sizeof(STG_PAIR::key)); - bzero(pairs[sources.size()].value, sizeof(STG_PAIR::value)); + bzero(pairs[source.size()].key, sizeof(STG_PAIR::key)); + bzero(pairs[source.size()].value, sizeof(STG_PAIR::value)); return pairs; } +PAIRS fromSTGPairs(const STG_PAIR* pairs) +{ + const STG_PAIR* pair = pairs; + PAIRS res; + + while (!emptyPair(pair)) { + res.push_back(std::pair(pair->key, pair->value)); + ++pair; + } + + return res; } -int stgInstantiateImpl(const char* server, uint16_t port, const char* password) +STG_RESULT toResult(const RESULT& source) { - if (STG_CLIENT::configure(server, port, password)) - return 1; + STG_RESULT result; + result.modify = toSTGPairs(source.modify); + result.reply = toSTGPairs(source.reply); + return result; +} - return 0; +STG_RESULT emptyResult() +{ + STG_RESULT result = {NULL, NULL}; + return result; } -const STG_PAIR* stgAuthorizeImpl(const char* userName, const char* serviceType) +std::string toString(const char* value) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->authorize(userName, serviceType)); + if (value == NULL) + return ""; + else + return value; } -const STG_PAIR* stgAuthenticateImpl(const char* userName, const char* serviceType) +STG_RESULT stgRequest(STG_CLIENT::TYPE type, const char* userName, const char* password, const STG_PAIR* pairs) { STG_CLIENT* client = STG_CLIENT::get(); if (client == NULL) { - // TODO: log "Not configured" - return NULL; + RadLog("Client is not configured."); + return emptyResult(); + } + try { + if (!client->connected()) + { + if (!STG_CLIENT::reconnect()) + return emptyResult(); + client = STG_CLIENT::get(); + } + response.done = false; + client->request(type, toString(userName), toString(password), fromSTGPairs(pairs)); + pthread_mutex_lock(&response.mutex); + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 5; + int res = 0; + while (!response.done && res == 0) + res = pthread_cond_timedwait(&response.cond, &response.mutex, &ts); + pthread_mutex_unlock(&response.mutex); + if (res != 0 || !response.status) + return emptyResult(); + return toResult(response.result); + } catch (const STG_CLIENT::Error& ex) { + RadLog("Error: '%s'.", ex.what()); + return emptyResult(); } - return toPairs(client->authenticate(userName, serviceType)); } -const STG_PAIR* stgPostAuthImpl(const char* userName, const char* serviceType) +} + +int stgInstantiateImpl(const char* address) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->postAuth(userName, serviceType)); + pthread_mutex_init(&response.mutex, NULL); + pthread_cond_init(&response.cond, NULL); + response.done = false; + + if (STG_CLIENT::configure(toString(address), &Response::callback, &response)) + return 1; + + return 0; } -const STG_PAIR* stgPreAcctImpl(const char* userName, const char* serviceType) +STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->preAcct(userName, serviceType)); + return stgRequest(STG_CLIENT::AUTHORIZE, userName, password, pairs); } -const STG_PAIR* stgAccountingImpl(const char* userName, const char* serviceType, const char* statusType, const char* sessionId) +STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->account(userName, serviceType, statusType, sessionId)); + return stgRequest(STG_CLIENT::AUTHENTICATE, userName, password, pairs); } -int countValuePairs(const VALUE_PAIR* pairs) +STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - unsigned count = 0; - while (pairs != NULL) { - ++count; - pairs = pairs->next; - } - return count; + return stgRequest(STG_CLIENT::POST_AUTH, userName, password, pairs); } -STG_PAIR* fromValuePairs(const VALUE_PAIR* pairs) +STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - unsigned size = countValuePairs(pairs); - STG_PAIR* res = new STG_PAIR[size + 1]; - size_t pos = 0; - while (pairs != NULL) { - bzero(res[pos].key, sizeof(STG_PAIR::key)); - bzero(res[pos].value, sizeof(STG_PAIR::value)); - strncpy(res[pos].key, pairs->name, sizeof(STG_PAIR::key)); - strncpy(res[pos].value, pairs->data.strvalue, sizeof(STG_PAIR::value)); - ++pos; - pairs = pairs->next; - } - bzero(res[pos].key, sizeof(STG_PAIR::key)); - bzero(res[pos].value, sizeof(STG_PAIR::value)); - return res; + return stgRequest(STG_CLIENT::PRE_ACCT, userName, password, pairs); } -void deletePairs(const STG_PAIR* pairs) +STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - delete[] pairs; + return stgRequest(STG_CLIENT::ACCOUNT, userName, password, pairs); }