]> git.stg.codes - stg.git/blob - projects/rlm_stg/iface.cpp
d99dd393f8037aeadd9482befb4d9d7d5bd5e65c
[stg.git] / projects / rlm_stg / iface.cpp
1 #include "iface.h"
2
3 #include "stg_client.h"
4 #include "radlog.h"
5
6 #include <cstring>
7
8 #include <strings.h>
9
10 namespace
11 {
12
13 struct Response
14 {
15     bool done;
16     pthread_mutex_t mutex;
17     pthread_cond_t cond;
18     RESULT result;
19     bool status;
20
21     static bool callback(void* data, const RESULT& result, bool status)
22     {
23         Response& resp = *static_cast<Response*>(data);
24         pthread_mutex_lock(&resp.mutex);
25         resp.result = result;
26         resp.status = status;
27         resp.done = true;
28         pthread_cond_signal(&resp.cond);
29         pthread_mutex_unlock(&resp.mutex);
30         return true;
31     }
32 } response;
33
34 STG_PAIR* toSTGPairs(const PAIRS& source)
35 {
36     STG_PAIR * pairs = new STG_PAIR[source.size() + 1];
37     for (size_t pos = 0; pos < source.size(); ++pos) {
38         bzero(pairs[pos].key, sizeof(STG_PAIR::key));
39         bzero(pairs[pos].value, sizeof(STG_PAIR::value));
40         strncpy(pairs[pos].key, source[pos].first.c_str(), sizeof(STG_PAIR::key));
41         strncpy(pairs[pos].value, source[pos].second.c_str(), sizeof(STG_PAIR::value));
42     }
43     bzero(pairs[source.size()].key, sizeof(STG_PAIR::key));
44     bzero(pairs[source.size()].value, sizeof(STG_PAIR::value));
45
46     return pairs;
47 }
48
49 PAIRS fromSTGPairs(const STG_PAIR* pairs)
50 {
51     const STG_PAIR* pair = pairs;
52     PAIRS res;
53
54     while (!emptyPair(pair)) {
55         res.push_back(std::pair<std::string, std::string>(pair->key, pair->value));
56         ++pair;
57     }
58
59     return res;
60 }
61
62 STG_RESULT toResult(const RESULT& source)
63 {
64     STG_RESULT result;
65     result.modify = toSTGPairs(source.modify);
66     result.reply = toSTGPairs(source.reply);
67     return result;
68 }
69
70 STG_RESULT emptyResult()
71 {
72     STG_RESULT result = {NULL, NULL};
73     return result;
74 }
75
76 std::string toString(const char* value)
77 {
78     if (value == NULL)
79         return "";
80     else
81         return value;
82 }
83
84 STG_RESULT stgRequest(STG_CLIENT::TYPE type, const char* userName, const char* password, const STG_PAIR* pairs)
85 {
86     STG_CLIENT* client = STG_CLIENT::get();
87     if (client == NULL) {
88         RadLog("Client is not configured.");
89         return emptyResult();
90     }
91     try {
92         if (!client->connected())
93         {
94             if (!STG_CLIENT::reconnect())
95                 return emptyResult();
96             client = STG_CLIENT::get();
97         }
98         response.done = false;
99         client->request(type, toString(userName), toString(password), fromSTGPairs(pairs));
100         pthread_mutex_lock(&response.mutex);
101         timespec ts;
102         clock_gettime(CLOCK_REALTIME, &ts);
103         ts.tv_sec += 5;
104         int res = 0;
105         while (!response.done && res == 0)
106             res = pthread_cond_timedwait(&response.cond, &response.mutex, &ts);
107         pthread_mutex_unlock(&response.mutex);
108         if (res != 0 || !response.status)
109             return emptyResult();
110         return toResult(response.result);
111     } catch (const STG_CLIENT::Error& ex) {
112         RadLog("Error: '%s'.", ex.what());
113         return emptyResult();
114     }
115 }
116
117 }
118
119 int stgInstantiateImpl(const char* address)
120 {
121     pthread_mutex_init(&response.mutex, NULL);
122     pthread_cond_init(&response.cond, NULL);
123     response.done = false;
124
125     if (STG_CLIENT::configure(toString(address), &Response::callback, &response))
126         return 1;
127
128     return 0;
129 }
130
131 STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* pairs)
132 {
133     return stgRequest(STG_CLIENT::AUTHORIZE, userName, password, pairs);
134 }
135
136 STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* pairs)
137 {
138     return stgRequest(STG_CLIENT::AUTHENTICATE, userName, password, pairs);
139 }
140
141 STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* pairs)
142 {
143     return stgRequest(STG_CLIENT::POST_AUTH, userName, password, pairs);
144 }
145
146 STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* pairs)
147 {
148     return stgRequest(STG_CLIENT::PRE_ACCT, userName, password, pairs);
149 }
150
151 STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* pairs)
152 {
153     return stgRequest(STG_CLIENT::ACCOUNT, userName, password, pairs);
154 }