#include "iface.h"
#include "stg_client.h"
+#include "radlog.h"
+
+#include <cstring>
+
+#include <strings.h>
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<Response*>(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) {
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<std::string, std::string>(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);
}