]> git.stg.codes - stg.git/commitdiff
Add proto implementation and user state holder
authorMaxim Mamontov <faust@gts.dp.ua>
Thu, 5 May 2011 15:00:57 +0000 (18:00 +0300)
committerMaxim Mamontov <faust@gts.dp.ua>
Thu, 5 May 2011 15:00:57 +0000 (18:00 +0300)
projects/sgauthstress/proto.cpp [new file with mode: 0644]
projects/sgauthstress/proto.h [new file with mode: 0644]
projects/sgauthstress/user.cpp [new file with mode: 0644]
projects/sgauthstress/user.h [new file with mode: 0644]

diff --git a/projects/sgauthstress/proto.cpp b/projects/sgauthstress/proto.cpp
new file mode 100644 (file)
index 0000000..06a67d8
--- /dev/null
@@ -0,0 +1,209 @@
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <cerrno>
+#include <cstring>
+#include <stdexcept>
+
+#include "stg/common.h"
+
+#include "proto.h"
+
+int WaitPacket(int sd, int timeout)
+{
+fd_set rfds;
+FD_ZERO(&rfds);
+FD_SET(sd, &rfds);
+
+struct timeval tv;
+tv.tv_sec = timeout;
+tv.tv_usec = 0;
+
+int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+if (res == -1) // Error
+    {
+    if (errno != EINTR)
+        {
+        printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
+        }
+    return -1;
+    }
+
+if (res == 0) // Timeout
+    {
+    return 0;
+    }
+
+return 1;
+}
+
+PROTO::PROTO(const std::string & server,
+             uint16_t port,
+             uint16_t localPort,
+             int to)
+    : running(false),
+      stopped(true),
+      timeout(to)
+{
+uint32_t ip = inet_addr(server.c_str());
+if (ip == INADDR_NONE)
+    {
+    struct hostent * hePtr = gethostbyname(server.c_str());
+    if (hePtr)
+        {
+        ip = *((uint32_t *)hePtr->h_addr_list[0]);
+        }
+    else
+        {
+        errorStr = "Unknown host: '";
+        errorStr += server;
+        errorStr += "'";
+        printfd(__FILE__, "PROTO::PROTO() - %s\n", errorStr.c_str());
+        throw std::runtime_error(errorStr);
+        }
+    }
+
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+localAddr.sin_family = AF_INET;
+localAddr.sin_port = htons(localPort);
+localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+serverAddr.sin_family = AF_INET;
+serverAddr.sin_port = htons(port);
+serverAddr.sin_addr.s_addr = ip;
+
+unsigned char key[IA_PASSWD_LEN];
+memset(key, 0, IA_PASSWD_LEN);
+strncpy(reinterpret_cast<char *>(key), "pr7Hhen", 8);
+Blowfish_Init(&ctx, key, IA_PASSWD_LEN);
+
+processors["CONN_SYN_ACK"] = &PROTO::CONN_SYN_ACK_Proc;
+processors["ALIVE_SYN"] = &PROTO::ALIVE_SYN_Proc;
+processors["DISCONN_SYN_ACK"] = &PROTO::DISCONN_SYN_ACK_Proc;
+processors["FIN"] = &PROTO::FIN_Proc;
+processors["INFO"] = &PROTO::INFO_Proc;
+// ERR_Proc will be handled explicitly
+}
+
+PROTO::~PROTO()
+{
+close(sock);
+}
+
+void * PROTO::Runner(void * data)
+{
+PROTO * protoPtr = static_cast<PROTO *>(data);
+protoPtr->Run();
+}
+
+bool PROTO::Start()
+{
+stopped = false;
+running = true;
+if (pthread_create(&tid, NULL, &Runner, NULL))
+    {
+    errorStr = "Failed to create listening thread: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "PROTO::Start() - %s\n", errorStr.c_str());
+    return false;
+    }
+return true;
+}
+
+bool PROTO::Stop()
+{
+running = false;
+int time = 0;
+while (!stopped && time < timeout)
+    {
+    struct timespec ts = {1, 0};
+    nanosleep(&ts, NULL);
+    ++time;
+    }
+if (!stopped)
+    {
+    errorStr = "Failed to stop listening thread - timed out";
+    printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
+    return false;
+    }
+if (pthread_join(tid, NULL))
+    {
+    errorStr = "Failed to join listening thread after stop: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
+    return false;
+    }
+return true;
+}
+
+bool PROTO::Connect(const std::string & login)
+{
+std::map<std::string, USER>::const_iterator it;
+it = users.find(login);
+if (it == users.end())
+    return false;
+
+// Do something
+
+return true;
+}
+
+bool PROTO::Disconnect(const std::string & login)
+{
+std::map<std::string, USER>::const_iterator it;
+it = users.find(login);
+if (it == users.end())
+    return false;
+
+// Do something
+
+return true;
+}
+
+void PROTO::Run()
+{
+while (running)
+    {
+    int res = WaitPacket(sock, timeout);
+    if (res < 0)
+        break;
+    if (!running)
+        break;
+    if (res)
+        RecvPacket();
+    }
+
+stopped = true;
+}
+
+bool PROTO::RecvPacket()
+{
+struct sockaddr_in addr;
+socklen_t fromLen = sizeof(addr);
+char buffer[2048];
+int res = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &fromLen);
+
+if (res == -1)
+    return res;
+
+return HandlePacket(buffer);
+}
+
+bool PROTO::HandlePacket(char * buffer)
+{
+if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
+    {
+    return ERR_Proc(buffer);
+    }
+
+std::string packetName(buffer + 12);
+std::map<std::string, PacketProcessor>::const_iterator it;
+it = processors.find(packetName);
+if (it != processors.end())
+    return (this->*it->second)(buffer);
+
+return false;
+}
diff --git a/projects/sgauthstress/proto.h b/projects/sgauthstress/proto.h
new file mode 100644 (file)
index 0000000..f478c0e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __PROTO_H__
+#define __PROTO_H__
+
+#include <netinet/ip.h>
+#include <pthread.h>
+
+#include <string>
+#include <map>
+
+#include "stg/os_int.h"
+#include "stg/blowfish.h"
+
+#include "user.h"
+
+class PROTO;
+
+typedef bool (PROTO::*PacketProcessor)(char *);
+
+class PROTO {
+    public:
+        PROTO(const std::string & server,
+              uint16_t port,
+              uint16_t localPort,
+              int timeout = 1);
+        ~PROTO();
+
+        bool Start();
+        bool Stop();
+
+        const std::string GetStrError() const { return errorStr; }
+
+        bool Connect(const std::string & login);
+        bool Disconnect(const std::string & login);
+    private:
+        int sock;
+        BLOWFISH_CTX ctx;
+        struct sockaddr_in localAddr;
+        struct sockaddr_in serverAddr;
+        int timeout;
+
+        std::map<std::string, USER> users;
+
+        bool running;
+        bool stopped;
+
+        pthread_t tid;
+
+        std::string errorStr;
+
+        std::map<std::string, PacketProcessor> processors;
+
+        static void * Runner(void * data);
+
+        void Run();
+        bool RecvPacket();
+        bool HandlePacket(char * buffer);
+
+        bool CONN_SYN_ACK_Proc(char * buffer);
+        bool ALIVE_SYN_Proc(char * buffer);
+        bool DISCONN_SYN_ACK_Proc(char * buffer);
+        bool FIN_Proc(char * buffer);
+        bool INFO_Proc(char * buffer);
+        bool ERR_Proc(char * buffer);
+};
+
+#endif
diff --git a/projects/sgauthstress/user.cpp b/projects/sgauthstress/user.cpp
new file mode 100644 (file)
index 0000000..bea1c6b
--- /dev/null
@@ -0,0 +1,26 @@
+#include "user.h"
+
+USER::USER(const std::string & l,
+           const std::string & pwd)
+    : login(l),
+      phase(1),
+      rnd(0),
+      sock(0)
+{
+char key[IA_PASSWD_LEN];
+memset(key, 0, IA_PASSWD_LEN);
+strncpy(key, password.c_str(), IA_PASSWD_LEN);
+Blowfish_Init(&ctx, key, IA_PASSWD_LEN);
+}
+
+USER::~USER()
+{
+}
+
+void USER::Connect()
+{
+}
+
+void USER::Disconnect()
+{
+}
diff --git a/projects/sgauthstress/user.h b/projects/sgauthstress/user.h
new file mode 100644 (file)
index 0000000..1ab31d9
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __USER_H__
+#define __USER_H__
+
+#include <string>
+
+#include "stg/os_int.h"
+#include "stg/ia.h"
+
+class USER {
+    public:
+        USER(const std::string & login,
+             const std::string & password);
+        ~USER();
+
+        void Connect();
+        void Disconnect();
+
+    private:
+        const std::string login;
+        int phase;
+        int rnd;
+        int sock;
+        BLOWFISH_CTX ctx;
+};
+
+#endif