]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/other/userstat/datathread.cpp
Merge branch 'master' into full-month-stats
[stg.git] / projects / stargazer / plugins / other / userstat / datathread.cpp
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);
 }