]> git.stg.codes - stg.git/commitdiff
Синхронизирую исходники мертвых проектов клиента юзерской статистики и
authorMaxim Mamontov <faust@user-desktop.(none)>
Mon, 8 Nov 2010 10:27:32 +0000 (12:27 +0200)
committerMaxim Mamontov <faust@user-desktop.(none)>
Mon, 8 Nov 2010 10:27:32 +0000 (12:27 +0200)
универсального драйвера БД. Вдруг когда-то кому-то понадобятся...

projects/stargazer/plugins/other/userstat/Makefile
projects/stargazer/plugins/other/userstat/datathread.cpp
projects/stargazer/plugins/other/userstat/datathread.h
projects/stargazer/plugins/other/userstat/userstat.cpp
projects/stargazer/plugins/other/userstat/userstat.h
projects/stargazer/plugins/store/db/pg_driver.cpp
projects/stargazer/plugins/store/db/pg_driver.h

index 23470f88da9c20add0f2e2d1c9459a0c843a743e..0046e2cf160c3f0b6931a46b4c2ca6e2ad9856da 100644 (file)
@@ -1,5 +1,5 @@
 ###############################################################################
-# $Id: Makefile,v 1.1 2008/07/05 12:35:53 faust Exp $
+# $Id: Makefile,v 1.4 2007/09/26 14:07:28 faust Exp $
 ###############################################################################
 
 include ../../../../../Makefile.conf
@@ -20,7 +20,8 @@ endif
 
 PROG = mod_userstat.so
 
-SRCS = ./userstat.cpp
+SRCS = ./userstat.cpp \
+       ./datathread.cpp
 
 LIBS += -lstg_common \
        -lstg_crypto
index 40d44305e642100e7d1e24988d7bc090b8bcf5d2..2409d4816591536a1d64f06853820c49863bc9e4 100644 (file)
 #include "datathread.h"
 
-bool DataThread::Init()
+DataThread::DataThread()
+        : tid(-1),
+          users(NULL),
+          store(NULL),
+          sock(-1),
+          done(true),
+          pvList(NULL),
+          data(NULL),
+          dataSize(0)
 {
-    parser = XML_ParserCreate(NULL);
-    if (!parser) {
-        printfd(__FILE__, "Error creating XML parser\n");
+xmlParser = XML_ParserCreate(NULL);
+if (!xmlParser)
+    {
+    printfd(__FILE__, "DataThread::DataThread() Failed to create parser\n");
+    return;
     }
-    XML_SetStartElementHandler(parser, StartHandler);
-    XML_SetEndElementHandler(parser, EndHandler);
-    XML_SetCharacterDataHandler(parser, DataHandler);
+XML_SetElementHandler(xmlParser, DTXMLStart, DTXMLEnd);
 }
 
 DataThread::~DataThread()
 {
-    XML_ParserFree(parser);
+XML_ParserFree(xmlParser);
 }
 
-void * DataThread::Run(void * val)
+bool DataThread::Handle(int s)
 {
-    DataThread * dt = reinterpret_cast<DataThread *>(val);
-
-    running = true;
-    stoppped = false;
-    while (running) {
-        if (sock >= 0) {
-            done = false;
-            dt->Handle();
-            done = true;
-            close(sock);
-            sock = -1;
-        } else {
-            usleep(1000);
-        }
+if (users == NULL)
+    {
+    printfd(__FILE__, "DataThread::Handle() Users not set\n");
+    return false;
     }
-    stopped = true;
-    running = false;
+if (store == NULL)
+    {
+    printfd(__FILE__, "DataThread::Handle() Storage not set\n");
+    return false;
+    }
+
+sock = s;
 
-    return NULL;
+if (pthread_create(&tid, NULL, Run, this))
+    {
+    printfd(__FILE__, "DataThread::Handle() Failed to create thread\n");
+    return false;
+    }
+if (pthread_detach(tid))
+    {
+    printfd(__FILE__, "DataThread::Handle() Cannot detach the thread\n");
+    }
+return true;
 }
 
-void DataThread::Handle()
+void * DataThread::Run(void * self)
 {
-    int32_t size;
-    unsigned char * buf;
+DataThread * dt = reinterpret_cast<DataThread *>(self);
 
-    if (!PrepareContext())
-        return;
+dt->done = false;
 
-    res = read(sock, &size, sizeof(size));
-    if (res != sizeof(size))
+if (dt->ReadRequest())
     {
-        printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
-        return;
+    if (dt->DecodeRequest())
+        {
+        if (dt->ParseRequest())
+            {
+            if (dt->MakeAnswer())
+                {
+                printfd(__FILE__, "DataThread::Run() All done\n");
+                }
+            else
+                {
+                printfd(__FILE__, "DataThread::Run() Failed to answer the request\n");
+                }
+            }
+        else
+            {
+            printfd(__FILE__, "DataThread::Run() Cannot parse the request\n");
+            }
+        }
+    else
+        {
+        printfd(__FILE__, "DataThread::Run() Cannot decode the request\n");
+        }
+    }
+else
+    {
+    printfd(__FILE__, "DataThread::Run() Cannot read the request\n");
     }
 
-    printfd(__FILE__, "DataThread::Handle() size = %d\n", size);
+dt->Cleanup();
 
-    if (size < 0) {
-        printfd(__FILE__, "DataThread::Handle() Invalid data size.\n");
-        return;
+return NULL;
+}
+
+bool DataThread::ReadRequest()
+{
+int32_t size;
+char * buf;
+
+int res = read(sock, &size, sizeof(size));
+if (res != sizeof(size))
+    {
+    printfd(__FILE__, "DataThread::ReadRequest() Reading login size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+    done = true;
+    return false;
     }
 
-    buf = new unsigned char[size];
-    res = read(sock, buf, size);
-    if (res != size)
+if (size < 0)
     {
-        printfd(__FILE__, "Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
-        return;
+    printfd(__FILE__, "DataThread::ReadRequest() Invalid login size.\n");
+    done = true;
+    return false;
     }
 
-    std::string data;
-    Decode(buf, data, size);
+buf = new char[size];
+
+res = read(sock, buf, size);
+if (res != size)
+    {
+    printfd(__FILE__, "DataThread::ReadRequest() Reading login failed! Wanted %d bytes, got %d bytes.\n", size, res);
+    delete[] buf;
+    done = true;
+    return false;
+    }
 
-    printfd(__FILE__, "Received XML: %s\n", data.c_str());
+login.assign(buf, size);
+delete[] buf;
 
-    XML_ParserReset(parser, NULL);
+res = read(sock, &size, sizeof(size));
+if (res != sizeof(size))
+    {
+    printfd(__FILE__, "DataThread::ReadRequest() Reading request size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+    done = true;
+    return false;
+    }
 
-    if (XML_Parse(parser, data.c_str(), data.length(), true) == XML_STATUS_OK) {
-        SendReply();
-    } else {
-        SendError();
+if (size < 0)
+    {
+    printfd(__FILE__, "DataThread::ReadRequest() Invalid request size.\n");
+    done = true;
+    return false;
     }
 
-    delete[] buf;
+data = new char[size + 1];
+dataSize = size;
 
-    return;
+res = read(sock, data, size);
+if (res != size)
+    {
+    printfd(__FILE__, "DataThread::ReadRequest() Reading request failed! Wanted %d bytes, got %d bytes.\n", size, res);
+    done = true;
+    return false;
+    }
+data[res] = 0;
+
+return true;
 }
 
-bool DataThread::PrepareContext()
+bool DataThread::DecodeRequest()
 {
-    int32_t size;
-    char * login;
-
-    int res = read(sock, &size, sizeof(size));
-    if (res != sizeof(size))
+if (users->FindByName(login, &(uit)))
     {
-        printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
-        return;
+    printfd(__FILE__, "DataThread::DecodeRequest() User '%s' not found.\n", login.c_str());
+    done = true;
+    return false;
     }
 
-    printfd(__FILE__, "DataThread::Handle() size = %d\n", size);
+std::string password = uit->property.password;
 
-    if (size < 0) {
-        printfd(__FILE__, "DataThread::Handle() Invalid data size.\n");
-        return;
-    }
+BLOWFISH_CTX ctx;
+char * key = new char[password.length()];
+strncpy(key, password.c_str(), password.length());
 
-    login = new char[size];
+Blowfish_Init(&ctx,
+              reinterpret_cast<unsigned char *>(key),
+              password.length());
 
-    res = read(sock, login, size);
-    if (res != size)
+for (int i = 0; i < dataSize / 8; ++i)
     {
-        printfd(__FILE__, "Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
-        return;
+    uint32_t a;
+    uint32_t b;
+    a = n2l(reinterpret_cast<unsigned char *>(data + i * 8));
+    b = n2l(reinterpret_cast<unsigned char *>(data + i * 8 + 4));
+    Blowfish_Decrypt(&ctx,
+                     &a,
+                     &b);
+    l2n(a, reinterpret_cast<unsigned char *>(data + i * 8));
+    l2n(b, reinterpret_cast<unsigned char *>(data + i * 8 + 4));
     }
 
-    std::string l;
-    l.assign(login, size);
-    delete[] login;
+delete[] key;
 
-    user_iter it;
-    if (users->FindByName(l, &it))
+return true;
+}
+
+bool DataThread::ParseRequest()
+{
+if (XML_Parse(xmlParser, data, dataSize, 1) != XML_STATUS_OK)
     {
-        printfd(__FILE__, "User '%s' not found.\n", login);
-        return;
+    printfd(__FILE__, "DataThread::ParseRequest() Failed to parse the request\n");
+    request.isBad = true;
+    return false;
     }
+return true;
+}
 
-    password = it->property.password;
-    
-    printfd(__FILE__, "DataThread::Handle() Requested user: '%s'\n", login);
-    printfd(__FILE__, "DataThread::Handle() Encryption initiated using password: '%s'\n", password.c_str());
-
-    char * key = new char[password.length()];
-    strncpy(key, password.c_str(), password.length());
+bool DataThread::MakeAnswer()
+{
+if (MakeConf())
+    {
+    if (MakeStat())
+        {
+        if (SendAnswer())
+            {
+            // All is ok
+            }
+        else
+            {
+            printfd(__FILE__, "DataThread::MakeAnswer() Failed to send answer");
+            return false;
+            }
+        }
+    else
+        {
+        printfd(__FILE__, "DataThread::MakeAnswer() Failed to make stat answer\n");
+        return false;
+        }
+    }
+else
+    {
+    printfd(__FILE__, "DataThread::MakeAnswer() Failed to make conf answer\n");
+    return false;
+    }
 
-    Blowfish_Init(&ctx,
-                  reinterpret_cast<unsigned char *>(key),
-                  password.length());
-    delete[] key;
+return true;
+}
 
-    return true;
+void DataThread::Cleanup()
+{
+delete[] data;
+dataSize = 0;
+login = "";
+done = false;
+data = NULL;
+request.conf.erase(request.conf.begin(), request.conf.end());
+request.stat.erase(request.stat.begin(), request.stat.end());
+request.login = "";
+request.isOk = true;
+request.isBad = false;
 }
 
-void DataThread::Encode(const std::string & src, char * dst, int size)
+void DataThread::ParseTag(const std::string & name, const char ** attr)
 {
-    const char * ptr = src.c_str();
-    for (int i = 0; i < size / 8; ++i) {
-        uint32_t a;
-        uint32_t b;
-        a = n2l(ptr + i * 8);
-        b = n2l(ptr + i * 8 + 4);
-        Blowfish_Encrypt(&ctx,
-                         &a,
-                         &b);
-        l2n(a, dst + i * 8);
-        l2n(b, dst + i * 8 + 4);
+if (request.isBad)
+    return;
+if (name == "request")
+    {
+    if (attr == NULL)
+        {
+        printfd(__FILE__, "DataThread::ParseTag() 'request' tag require an attribute\n");
+        request.isBad = true;
+        return;
+        }
+    else
+        {
+        std::string attrName(*attr++);
+        std::string attrValue(*attr++);
+        if (attr != NULL)
+            {
+            printfd(__FILE__, "DataThread::ParseTag() Extra attributes on tag 'request'\n");
+            }
+        if (attrName == "login")
+            {
+            if (attrValue != login)
+                {
+                printfd(__FILE__, "DataThread::ParseTag() Logins doesn't match\n");
+                request.isBad = true;
+                return;
+                }
+            }
+        else
+            {
+            printfd(__FILE__, "DataThread::ParseTag() Unexpected attribute '%s'\n", attrName.c_str());
+            request.isBad = true;
+            return;
+            }
+        }
+    }
+else if (name == "conf")
+    {
+    pvList = &(request.conf);
+    }
+else if (name == "stat")
+    {
+    pvList = &(request.stat);
+    }
+else
+    {
+    (*pvList)[name];
     }
 }
 
-void DataThread::Decode(char * src, std::string & dst, int size)
+bool DataThread::MakeConf()
 {
-    char tmp[9];
-    tmp[8] = 0;
-    dst = "";
-
-    for (int i = 0; i < size / 8; ++i) {
-        uint32_t a;
-        uint32_t b;
-        a = n2l(src + i * 8);
-        b = n2l(src + i * 8 + 4);
-        Blowfish_Decrypt(&ctx,
-                         &a,
-                         &b);
-        l2n(a, tmp);
-        l2n(b, tmp + 4);
-
-        dst += tmp;
-    }
+return false;
+}
+
+bool DataThread::MakeStat()
+{
+return false;
 }
 
-void StartHandler(void *data, const char *el, const char **attr)
+bool DataThread::SendAnswer()
 {
-    printfd(__FILE__, "Node: %s\n", el);
+return false;
 }
 
-void EndHandler(void *data, const char *el)
+void DTXMLStart(void * data, const char * name, const char ** attr)
 {
+DataThread * dt = reinterpret_cast<DataThread *>(data);
+dt->ParseTag(name, attr);
 }
 
-void DataHandler(void *data, const char *el)
+void DTXMLEnd(void * data, const char * name)
 {
+//DataThread * dt = reinterpret_cast<DataThread *>(data);
 }
index cd9a87b6a26f13f6419a898289fd8b9880bf003d..4371516e4f552ceea3ef84c957e9340e43abc136 100644 (file)
@@ -1,58 +1,87 @@
 #ifndef __DATATHREAD_H__
 #define __DATATHREAD_H__
 
-#include "../../../users.h"
-#include "base_store.h"
-#include <pthread.h>
+#include <map>
+#include <string>
+
 #include <expat.h>
+#include <pthread.h>
+
+#include "common.h"
+#include "../../../users.h"
+
+uint32_t n2l(unsigned char * c)
+{
+    uint32_t t = *c++ << 24;
+    t += *c++ << 16;
+    t += *c++ << 8;
+    t += *c;
+    return t;
+}
+
+void l2n(uint32_t t, unsigned char * c)
+{
+    *c++ = t >> 24 & 0x000000FF;
+    *c++ = t >> 16 & 0x000000FF;
+    *c++ = t >> 8 & 0x000000FF;
+    *c++ = t & 0x000000FF;
+}
+
+typedef std::map<std::string, std::string> PV_LIST;
 
 class DataThread {
 public:
-    DataThread() : done(false), sock(-1) { Init(); };
-    DataThread(USERS * u, BASE_STORE * s, int sd)
-        : users(u),
-          store(s),
-          sock(sd),
-          done(false)
-    {
-        Init();
-    };
+    DataThread();
     ~DataThread();
 
     void SetUsers(USERS * u) { users = u; };
     void SetStore(BASE_STORE * s) { store = s; };
-    void SetSocket(int s) { sock = s; };
 
     bool isDone() const { return done; };
-    bool Init();
-
-    bool Start();
-    bool Stop();
-
-    static void * Run(void *);
 
+    bool Handle(int s);
 
+    friend void DTXMLStart(void * data, const char * name, const char ** attr);
+    friend void DTXMLEnd(void * data, const char * name);
 private:
-    pthread_t thread;
+    pthread_t tid;
     USERS * users;
     BASE_STORE * store;
-    XML_Parser parser;
     int sock;
     bool done;
-    bool running;
-    bool stopped;
-    BLOWFISH_CTX ctx;
-    std::string password;
-    std::string reply;
-
-    void Handle();
-    bool PrepareContect();
-    void Encode(const std::string &, char *);
-    void Decode(char *, const std::string &);
-
-    friend void StartHandler(void *data, const char *el, const char **attr);
-    friend void EndHandler(void *data, const char *el);
-    friend void DataHandler(void *data, const char *el);
+    struct Request {
+        PV_LIST conf;
+        PV_LIST stat;
+        std::string login;
+        bool isOk;
+        bool isBad;
+    } request;
+    PV_LIST * pvList;
+    char * data;
+    int32_t dataSize;
+
+    std::string login;
+    user_iter uit;
+
+    XML_Parser xmlParser;
+
+    static void * Run(void * self);
+
+    bool ReadRequest();
+    bool DecodeRequest();
+    bool ParseRequest();
+    bool MakeAnswer();
+
+    bool MakeConf();
+    bool MakeStat();
+    bool SendAnswer();
+
+    void Cleanup();
+
+    void ParseTag(const std::string & name, const char ** attr);
 };
 
+void DTXMLStart(void * data, const char * name, const char ** attr);
+void DTXMLEnd(void * data, const char * name);
+
 #endif
index eca424e89fe739e69e34524b8ab31289b96ed736..6b97111d3bf7f11518791c801ea34eada912c573 100644 (file)
@@ -15,16 +15,22 @@ return new USERSTAT();
 }
 
 USERSTAT::USERSTAT()
-    : maxThreads(16),
-      port(5555)
+    : isRunning(false),
+      nonstop(false),
+      errorStr(""),
+      version(USTAT_VERSION),
+      listenSocket(-1),
+      maxThreads(16),
+      port(5555),
+      thread(0),
+      users(NULL),
+      store(NULL)
 {
-xmlParser = XML_ParserCreate(NULL);
 pthread_mutex_init(&mutex, NULL);
 }
 
 USERSTAT::~USERSTAT()
 {
-XML_ParserFree(xmlParser);
 }
 
 int USERSTAT::ParseSettings()
@@ -41,6 +47,7 @@ for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
         if (str2x<uint16_t>(*(i->value.begin()), port)) 
             {
             errorStr = "'Port' parameter must be a numeric value";
+            printfd(__FILE__, "USERSTAT::ParseSettings() %s\n", errorStr.c_str());
             return -1;
             }
         }
@@ -49,6 +56,7 @@ for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
         if (str2x<unsigned>(*(i->value.begin()), maxThreads)) 
             {
             errorStr = "'MaxThreads' parameter must be a numeric value";
+            printfd(__FILE__, "USERSTAT::ParseSettings() %s\n", errorStr.c_str());
             return -1;
             }
         }
@@ -64,6 +72,7 @@ listenSocket = socket(PF_INET, SOCK_STREAM, 0);
 if (listenSocket < 0)
     {
     errorStr = "Create USERSTAT socket failed.";
+    printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
     return -1;
     }
 
@@ -78,6 +87,7 @@ int lng = 1;
 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
     {
     errorStr = "Setsockopt failed. " + string(strerror(errno));
+    printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
     return -1;
     }
 
@@ -88,6 +98,7 @@ int res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
 if (res == -1)
     {
     errorStr = "Bind USERSTAT socket failed";
+    printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
     return -1;
     }
 
@@ -97,6 +108,7 @@ res = listen(listenSocket, 0);
 if (res == -1)
     {
     errorStr = "Listen USERSTAT socket failed";
+    printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
     return -1;
     }
 printfd(__FILE__, "USERSTAT::Prepare() listen - ok\n");
@@ -112,6 +124,16 @@ return close(listenSocket);
 
 int USERSTAT::Start()
 {
+if (users == NULL) {
+    errorStr = "Users must be set";
+    printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
+    return -1;
+}
+if (store == NULL) {
+    errorStr = "Store must be set";
+    printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
+    return -1;
+}
 if (Prepare())
     {
     return -1;
@@ -120,6 +142,7 @@ nonstop = true;
 if (pthread_create(&thread, NULL, Run, this))
     {
     errorStr = "Cannot create thread";
+    printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
     return -1;
     }
 
@@ -132,6 +155,7 @@ nonstop = false;
 if (pthread_kill(thread, SIGTERM))
     {
     errorStr = "Cannot send signal to thread";
+    printfd(__FILE__, "USERSTAT::Stop() %s\n", errorStr.c_str());
     return -1;
     }
 for (int i = 0; i < 25; i++)
@@ -144,6 +168,7 @@ for (int i = 0; i < 25; i++)
 if (isRunning)
     {
     errorStr = "Cannot stop thread";
+    printfd(__FILE__, "USERSTAT::Stop() %s\n", errorStr.c_str());
     return -1;
     }
 return 0;
@@ -174,6 +199,9 @@ while (us->nonstop)
         info.store = us->store;
         info.outerSocket = outerSocket;
         info.done = false;
+
+        info.request.Reset();
+
         us->pool.push_back(info);
         it = us->pool.end();
         --it;
@@ -181,7 +209,7 @@ while (us->nonstop)
         if (pthread_create(&thread, NULL, Operate, &(*it)))
             {
             us->errorStr = "Cannot create thread";
-            printfd(__FILE__, "Cannot create thread\n");
+            printfd(__FILE__, "USERSTAT::Run() %s\n", us->errorStr.c_str());
             }
         it->thread = thread;
         }
@@ -200,7 +228,7 @@ void * USERSTAT::Operate(void * i)
     int res = read(info->outerSocket, &size, sizeof(size));
     if (res != sizeof(size))
     {
-        printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+        printfd(__FILE__, "USERSTAT::Operate() Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
         info->done = true;
         return NULL;
     }
@@ -218,7 +246,7 @@ void * USERSTAT::Operate(void * i)
     res = read(info->outerSocket, login, size);
     if (res != size)
     {
-        printfd(__FILE__, "Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
+        printfd(__FILE__, "USERSTAT::Operate() Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
         info->done = true;
         return NULL;
     }
@@ -229,7 +257,7 @@ void * USERSTAT::Operate(void * i)
     res = read(info->outerSocket, &size, sizeof(size));
     if (res != sizeof(size))
     {
-        printfd(__FILE__, "Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
+        printfd(__FILE__, "USERSTAT::Operate() Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
         info->done = true;
         return NULL;
     }
@@ -246,22 +274,22 @@ void * USERSTAT::Operate(void * i)
     res = read(info->outerSocket, buf, size);
     if (res != size)
     {
-        printfd(__FILE__, "Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
+        printfd(__FILE__, "USERSTAT::Operate() Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
         info->done = true;
         return NULL;
     }
+    buf[res] = 0;
 
-    printfd(__FILE__, "Received data: %s\n", buf);
+    printfd(__FILE__, "USERSTAT::Operate() Received data: %s\n", buf);
 
-    user_iter it;
-    if (info->users->FindByName(l, &it))
+    if (info->users->FindByName(l, &(info->uit)))
     {
-        printfd(__FILE__, "User '%s' not found.\n", login);
+        printfd(__FILE__, "USERSTAT::Operate() User '%s' not found.\n", login);
         info->done = true;
         return NULL;
     }
 
-    std::string password = it->property.password;
+    std::string password = info->uit->property.password;
     
     printfd(__FILE__, "USERSTAT::Operate() Requested user: '%s'\n", login);
     printfd(__FILE__, "USERSTAT::Operate() Encription init using password: '%s'\n", password.c_str());
@@ -288,9 +316,205 @@ void * USERSTAT::Operate(void * i)
 
     delete[] key;
 
-    printfd(__FILE__, "Received XML: %s\n", buf);
+    printfd(__FILE__, "USERSTAT::Operate() Received XML: %s\n", buf);
+
+    if (XML_Parse(info->xmlParser,
+                  reinterpret_cast<char *>(buf),
+                  size,
+                  1) != XML_STATUS_OK) {
+        printfd(__FILE__, "USERSTAT::Operate() Invalid password\n", login);
+        info->done = true;
+        delete[] buf;
+        return NULL;
+    }
+
+    if (!info->request.isOk) {
+        printfd(__FILE__, "USERSTAT::Operate() Malformed XML\n");
+        info->done = true;
+        delete[] buf;
+        return NULL;
+    }
+
+    info->Handle();
+
+    std::cout << "USERSTAT::Operate() Request:" << std::endl;
+    std::for_each(info->request.conf.begin(),
+                  info->request.conf.end(),
+                  THREAD_INFO::LinePrinter());
+    std::for_each(info->request.stat.begin(),
+                  info->request.stat.end(),
+                  THREAD_INFO::LinePrinter());
 
     info->done = true;
     delete[] buf;
     return NULL;
 }
+
+void TIParseXMLStart(void * data, const char * name, const char ** attr)
+{
+    THREAD_INFO * ti = reinterpret_cast<THREAD_INFO *>(data);
+    if (strncmp(name, "request", 7) == 0) {
+        if (attr == NULL) {
+            printfd(__FILE__, "ParseXMLStart() 'reqest' tag require a 'login' parameter\n");
+            ti->request.isOk |= false;
+            return;
+        } else {
+            ti->request.login = *attr;
+        }
+    } else if (strncmp(name, "stat", 4)) {
+        ti->pvList = &(ti->request.stat);
+    } else if (strncmp(name, "conf", 4)) {
+        ti->pvList = &(ti->request.conf);
+    } else {
+        if (ti->pvList == NULL) {
+            printfd(__FILE__, "ParseXMLStart() Unexpected tag: '%s'\n", name);
+            ti->request.isOk |= false;
+            return;
+        }
+        (*ti->pvList)[name];
+    }
+}
+
+void TIParseXMLEnd(void * data, const char * name)
+{
+    THREAD_INFO * ti = reinterpret_cast<THREAD_INFO *>(data);
+    if (strncmp(name, "stat", 4) == 0) {
+        ti->pvList = NULL;
+    } else if (strncmp(name, "conf", 4) == 0) {
+        ti->pvList = NULL;
+    } else if (strncmp(name, "request", 7) == 0) {
+    }
+}
+
+THREAD_INFO::THREAD_INFO() : pvList(NULL),
+                users(NULL),
+                store(NULL),
+                outerSocket(-1),
+                done(true)
+{
+    printfd(__FILE__, "THREAD_INFO::THREAD_INFO()\n");
+    xmlParser = XML_ParserCreate(NULL);
+
+    if (!xmlParser)
+        {
+        printfd(__FILE__, "USERSTAT::Run() Couldn't allocate memory for parser\n");
+        }
+
+    XML_ParserReset(xmlParser, NULL);
+    XML_SetElementHandler(xmlParser, TIParseXMLStart, TIParseXMLEnd);
+    XML_SetUserData(xmlParser, this);
+}
+
+THREAD_INFO::~THREAD_INFO()
+{
+    printfd(__FILE__, "THREAD_INFO::~THREAD_INFO()\n");
+    XML_ParserFree(xmlParser);
+}
+
+int THREAD_INFO::Handle()
+{
+    if (!request.isOk)
+        return -1;
+
+    if (HandleStat())
+        return -1;
+
+    if (HandleConf())
+        return -1;
+
+    return 0;
+}
+
+int THREAD_INFO::HandleConf()
+{
+    PV_LIST::iterator it(request.conf.begin());
+
+    for (; it != request.conf.end(); ++it)
+        {
+        if (it->first == "password")
+            {
+            it->second = uit->property.password;
+            }
+        else if (it->first == "passive")
+            {
+            it->second = uit->property.passive;
+            }
+        else if (it->first == "disabled")
+            {
+            it->second = uit->property.disabled;
+            }
+        else if (it->first == "disabledDetailStat")
+            {
+            it->second = uit->property.disabledDetailStat;
+            }
+        else if (it->first == "alwaysOnline")
+            {
+            it->second = uit->property.alwaysOnline;
+            }
+        else if (it->first == "tariffName")
+            {
+            it->second = uit->property.tariffName;
+            }
+        else if (it->first == "address")
+            {
+            it->second = uit->property.address;
+            }
+        else if (it->first == "phone")
+            {
+            it->second = uit->property.phone;
+            }
+        else if (it->first == "email")
+            {
+            it->second = uit->property.email;
+            }
+        else if (it->first == "note")
+            {
+            it->second = uit->property.note;
+            }
+        else if (it->first == "realName")
+            {
+            it->second = uit->property.realName;
+            }
+        else if (it->first == "group")
+            {
+            it->second = uit->property.group;
+            }
+        else if (it->first == "credit")
+            {
+            it->second = uit->property.credit;
+            }
+        else if (it->first == "creditExpire")
+            {
+            it->second = uit->property.creditExpire;
+            }
+        else if (it->first == "nextTariff")
+            {
+            it->second = uit->property.nextTariff;
+            }
+        else
+            {
+            printfd(__FILE__, "THREAD_INFO::HandleConf() Invalid param: '%s'\n", it->first.c_str());
+            }
+        }
+
+    return 0;
+}
+
+int THREAD_INFO::HandleStat()
+{
+    PV_LIST::iterator it(request.conf.begin());
+
+    for (; it != request.conf.end(); ++it)
+        {
+        if (it->first == "cash")
+            {
+            it->second = uit->property.password;
+            }
+        else
+            {
+            printfd(__FILE__, "THREAD_INFO::HandleConf() Invalid param: '%s'\n", it->first.c_str());
+            }
+        }
+
+    return 0;
+}
index 83f66202b45714d5161cd31158c126b903732e98..9dd01f2524e6a6a38ef7afe52c3b8b4244f708e9 100644 (file)
  */
 
 /*
- $Revision: 1.1 $
- $Date: 2008/07/05 12:35:53 $
- $Author: faust $
+ $Revision: $
+ $Date: $
+ $Author: $
 */
 
 #ifndef __USERSTAT_H__
 #define __USERSTAT_H__
 
-#include <expat.h>
+#include <string>
+#include <map>
+#include <functional>
+
 #include <pthread.h>
 #include <netinet/in.h>
 
 #include "base_plugin.h"
 
-extern "C" BASE_PLUGIN * GetPlugin();
-
-struct THREAD_INFO
-{
-    pthread_t thread;
-    USERS * users;
-    BASE_STORE * store;
-    int outerSocket;
-    bool done;
-};
-
-uint32_t n2l(unsigned char * c)
-{
-    uint32_t t = *c++ << 24;
-    t += *c++ << 16;
-    t += *c++ << 8;
-    t += *c;
-    return t;
-}
+#define USTAT_VERSION "UserStats 1.0_alt"
 
-void l2n(uint32_t t, unsigned char * c)
-{
-    *c++ = t >> 24 & 0x000000FF;
-    *c++ = t >> 16 & 0x000000FF;
-    *c++ = t >> 8 & 0x000000FF;
-    *c++ = t & 0x000000FF;
-}
+extern "C" BASE_PLUGIN * GetPlugin();
 
 class USERSTAT : public BASE_PLUGIN
 {
@@ -85,9 +64,9 @@ public:
     virtual uint16_t        GetStopPosition() const { return 0; };
 
 private:
-    struct IsDone : public unary_function<THREAD_INFO, bool>
+    struct IsDone : public unary_function<DataThread, bool>
     {
-        bool operator()(const THREAD_INFO & info) { return info.done; };
+        bool operator()(const DataThread & info) { return info.IsDone(); };
     };
     struct ToLower : public unary_function<char, char>
     {
@@ -97,7 +76,7 @@ private:
     bool nonstop;
     std::string errorStr;
     std::string version;
-    std::vector<THREAD_INFO> pool;
+    std::vector<DataThread> pool;
     int listenSocket;
     int threads;
     unsigned maxThreads;
@@ -110,15 +89,10 @@ private:
 
     MODULE_SETTINGS settings;
 
-    XML_Parser xmlParser;
-
     int Prepare();
     int Finalize();
     static void * Run(void *);
     static void * Operate(void *);
-
-    friend void ParseXMLStart(void * data, char * name, char ** attr);
-    friend void ParseXMLEnd(void * data, char * name);
 };
 
 #endif
index 4dda25d38ffed5dc65c1ddae7866c7a900221fc1..61adda2648f73cbdf123f7eebc5ad3113d4d151f 100644 (file)
@@ -21,9 +21,9 @@ PG_DRIVER::~PG_DRIVER()
 bool PG_DRIVER::Connect()
 {
     std::stringstream params;
-    params << "host=" << host << " "
-          << "dbname=" << database << " "
-          << "user=" << user << " "
+    params << "host=" << host
+          << "dbname=" << database
+          << "user=" << user
           << "password=" << password;
     std::string str = params.str();
     conn = PQconnectdb(str.c_str());
@@ -35,7 +35,8 @@ bool PG_DRIVER::Disconnect()
 {
     if (PQstatus(conn) == CONNECTION_OK) {
        PQfinish(conn);
-       conn = NULL;
+       errorMsg = PQerrorMessage(conn);
+       return PQstatus(conn) != CONNECTION_BAD;
     }
 
     return false;
@@ -43,6 +44,9 @@ bool PG_DRIVER::Disconnect()
 
 bool PG_DRIVER::Query(const std::string & query)
 {
+    cols.erase(cols.begin(), cols.end());
+    cols.reserve(columns);
+
     PQclear(result);
     result = PQexec(conn, query.c_str());
     errorMsg = PQerrorMessage(conn);
@@ -50,13 +54,9 @@ bool PG_DRIVER::Query(const std::string & query)
     columns = PQnfields(result);
     affected = atoi(PQcmdTuples(result));
 
-    cols.erase(cols.begin(), cols.end());
-    cols.reserve(columns);
-
     if (tuples) {
-       for (int i = 0; i < columns; ++i) {
+       for (int i = 0; i < columns; ++i)
            cols.push_back(PQfname(result, i));
-       }
     }
 
     if (!result)
index a6cee6e2069247e76eef1c28d3a91ef6eac49a74..95b938fa2cb84c206848274cd1ef1d29a66df956 100644 (file)
@@ -5,6 +5,9 @@
 
 #include "base_db.h"
 
+extern "C" BASE_DB * CreateDriver();
+extern "C" void DestroyDriver(BASE_DB *);
+
 class PG_DRIVER : public BASE_DB {
 public:
     virtual ~PG_DRIVER();
@@ -22,6 +25,7 @@ public:
 private:
     PGconn * conn;
     PGresult * result;
+    COLUMNS cols;
 };
 
 #endif