]> git.stg.codes - stg.git/blobdiff - stglibs/ia.lib/ia.cpp
Stop plugins before stopping core.
[stg.git] / stglibs / ia.lib / ia.cpp
index 81bd75fb7df8ec48b7bc198bb21642f2342af54f..a05d30614dc54f49208cecbe1bd6ac8db379157f 100644 (file)
 
 //---------------------------------------------------------------------------
 
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+#include <winnt.h>
+#else
+#include <fcntl.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <csignal>
+#endif
+
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
 #include <cassert>
 
-#ifdef WIN32
-    #include <winsock2.h>
-    #include <windows.h>
-    #include <winbase.h>
-    #include <winnt.h>
-#else
-    #include <fcntl.h>
-    #include <netdb.h>
-    #include <arpa/inet.h>
-    #include <unistd.h>
-#endif
-
 #include "stg/common.h"
-#include "ia.h"
+#include "stg/ia.h"
 
 #define IA_NONE            (0)
 #define IA_CONNECT         (1)
 //---------------------------------------------------------------------------
 #ifndef WIN32
 #include <sys/time.h>
+void Sleep(int ms)
+{
+long long res = ms * 1000000;
+struct timespec ts = {res / 1000000000, res % 1000000000};
+nanosleep(&ts, NULL);
+}
+//---------------------------------------------------------------------------
 void * RunL(void * data)
 {
 sigset_t signalSet;
 sigfillset(&signalSet);
 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
-
 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
 static int a = 0;
 
@@ -84,13 +91,6 @@ while (c->GetNonstop())
 return NULL;
 }
 //---------------------------------------------------------------------------
-void Sleep(int ms)
-{
-long long res = ms * 1000000;
-struct timespec ts = {res / 1000000000, res % 1000000000};
-nanosleep(&ts, NULL);
-}
-//---------------------------------------------------------------------------
 long GetTickCount()
 {
 struct timeval tv;
@@ -108,10 +108,36 @@ return 0;
 }
 //---------------------------------------------------------------------------
 #endif
+
+namespace
+{
+
+bool HostNameToIP(const std::string & hostName, uint32_t & ip)
+{
+ip = inet_addr(hostName.c_str());
+if (ip == INADDR_NONE)
+    {
+    hostent * phe = gethostbyname(hostName.c_str());
+    if (phe)
+        {
+        ip = *((uint32_t *)phe->h_addr_list[0]);
+        }
+    else
+        {
+        return false;
+        }
+    }
+
+return true;
+}
+
+}
+
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-IA_CLIENT_PROT::IA_CLIENT_PROT(const string & sn, unsigned short p, uint16_t localPort)
+IA_CLIENT_PROT::IA_CLIENT_PROT(const std::string & sn, unsigned short p,
+                               const std::string & ln, uint16_t lp)
     : action(IA_NONE),
       phase(1),
       phaseTime(0),
@@ -122,7 +148,8 @@ IA_CLIENT_PROT::IA_CLIENT_PROT(const string & sn, unsigned short p, uint16_t loc
       serverName(sn),
       port(p),
       ip(0),
-      localPort(localPort),
+      localName(ln),
+      localPort(lp),
       firstConnect(true),
       reconnect(0),
       sockr(0),
@@ -190,7 +217,7 @@ servAddr.sin_addr.s_addr = ip;
 //---------------------------------------------------------------------------
 void IA_CLIENT_PROT::PrepareNet()
 {
-struct hostent * phe;
+/*struct hostent * phe;
 unsigned long ip;
 
 ip = inet_addr(serverName.c_str());
@@ -208,6 +235,16 @@ if (ip == INADDR_NONE)
         if (pErrorCb != NULL)
             pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
         }
+    }*/
+
+if (!HostNameToIP(serverName, ip))
+    {
+    ip = 0;
+    strError = std::string("Unknown host ") + "\'" + serverName + "\'";
+    codeError = IA_GETHOSTBYNAME_ERROR;
+    if (pErrorCb != NULL)
+        pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
+    return;
     }
 
 #ifndef WIN32
@@ -225,7 +262,24 @@ if (localPort)
     localAddrR.sin_port = htons(localPort);
 else
     localAddrR.sin_port = htons(port);
-localAddrR.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (!localName.empty())
+    {
+    if (!HostNameToIP(localName, localIP))
+        {
+        strError = std::string("Unknown host ") + "\'" + serverName + "\'";
+        codeError = IA_GETHOSTBYNAME_ERROR;
+        if (pErrorCb != NULL)
+            pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
+        localIP = INADDR_ANY;
+        }
+    }
+else
+    {
+    localIP = INADDR_ANY;
+    }
+
+localAddrR.sin_addr.s_addr = localIP;
 
 servAddr.sin_family = AF_INET;
 servAddr.sin_port = htons(port);
@@ -243,7 +297,7 @@ if (res == -1)
 
 #ifdef WIN32
 unsigned long arg = 1;
-res = ioctlsocket(sockr, FIONBIO, &arg);
+ioctlsocket(sockr, FIONBIO, &arg);
 #else
 if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
     {
@@ -268,7 +322,7 @@ WSACleanup();
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
 {
-map<string, int>::iterator pi;
+std::map<std::string, int>::iterator pi;
 pi = packetTypes.find(buffer);
 if (pi == packetTypes.end())
     {
@@ -297,18 +351,11 @@ if (!isNetPrepared)
     }
 
 int db = sizeof(HDR_8);
-for (int i = 0; i < IA_LOGIN_LEN/8; i++)
-    {
-    Blowfish_Encrypt(&ctxHdr, (uint32_t*)(buffer + db + i*8), (uint32_t*)(buffer + db + i*8 + 4));
-    }
+EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &ctxHdr);
 
 db += IA_LOGIN_LEN;
-int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
-for (int i = 0; i < encLen; i++)
-    {
-    Blowfish_Encrypt(&ctxPass, (uint32_t*)(buffer + db), (uint32_t*)(buffer + db + 4));
-    db += 8;
-    }
+int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN);
+EncryptString(buffer + db, buffer + db, encLen, &ctxPass);
 
 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
 }
@@ -329,10 +376,7 @@ if (res == -1)
     return res;
 
 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
-    {
-    for (int i = 0; i < len/8; i++)
-        Blowfish_Decrypt(&ctxPass, (uint32_t*)(buffer + i*8), (uint32_t*)(buffer + i*8 + 4));
-    }
+    DecryptString(buffer, buffer, len, &ctxPass);
 
 return 0;
 }
@@ -543,19 +587,19 @@ void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
 memcpy(ls, &stat, sizeof(stat));
 }
 //---------------------------------------------------------------------------
-void IA_CLIENT_PROT::SetServer(const string & sn, unsigned short p)
+void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
 {
 serverName = sn;
 port = p;
 PrepareNet();
 }
 //---------------------------------------------------------------------------
-void IA_CLIENT_PROT::SetLogin(const string & l)
+void IA_CLIENT_PROT::SetLogin(const std::string & l)
 {
 login = l;
 }
 //---------------------------------------------------------------------------
-void IA_CLIENT_PROT::SetPassword(const string & p)
+void IA_CLIENT_PROT::SetPassword(const std::string & p)
 {
 password = p;
 
@@ -583,7 +627,7 @@ action = IA_DISCONNECT;
 return 0;
 }
 //---------------------------------------------------------------------------
-int IA_CLIENT_PROT::GetStrError(string * error) const
+int IA_CLIENT_PROT::GetStrError(std::string * error) const
 {
 int ret = codeError;
 *error = strError;
@@ -594,7 +638,7 @@ return ret;
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
 {
-vector<string> dirNames;
+std::vector<std::string> dirNames;
 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
 
 #ifdef ARCH_BE
@@ -720,13 +764,14 @@ int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
 {
 connSyn8 = (CONN_SYN_8*)buffer;
 
+assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
+
+connSyn8->len = sizeof(CONN_SYN_8);
+
 #ifdef ARCH_BE
 SwapBytes(connSyn8->len);
 #endif
 
-assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
-
-connSyn8->len = sizeof(CONN_SYN_8);
 strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
 strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
 connSyn8->dirs = 0;
@@ -734,18 +779,13 @@ for (int i = 0; i < DIR_NUM; i++)
     {
     connSyn8->dirs |= (selectedDirs[i] << i);
     }
-return connSyn8->len;
+return sizeof(CONN_SYN_8);
 }
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
 {
 connAck8 = (CONN_ACK_8*)buffer;
 
-#ifdef ARCH_BE
-SwapBytes(connAck8->len);
-SwapBytes(connAck8->rnd);
-#endif
-
 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
 
 connAck8->len = sizeof(CONN_ACK_8);
@@ -754,18 +794,18 @@ strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN);
 rnd++;
 connAck8->rnd = rnd;
 
-return connAck8->len;
+#ifdef ARCH_BE
+SwapBytes(connAck8->len);
+SwapBytes(connAck8->rnd);
+#endif
+
+return sizeof(CONN_ACK_8);
 }
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
 {
 aliveAck8 = (ALIVE_ACK_8*)buffer;
 
-#ifdef ARCH_BE
-SwapBytes(aliveAck8->len);
-SwapBytes(aliveAck8->rnd);
-#endif
-
 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
 
 aliveAck8 = (ALIVE_ACK_8*)buffer;
@@ -773,42 +813,50 @@ aliveAck8->len = sizeof(ALIVE_ACK_8);
 strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN);
 strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN);
 aliveAck8->rnd = ++rnd;
-return aliveAck8->len;
+
+#ifdef ARCH_BE
+SwapBytes(aliveAck8->len);
+SwapBytes(aliveAck8->rnd);
+#endif
+
+return sizeof(ALIVE_ACK_8);
 }
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
 {
 disconnSyn8 = (DISCONN_SYN_8*)buffer;
 
+assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
+
+disconnSyn8->len = sizeof(DISCONN_SYN_8);
+
 #ifdef ARCH_BE
 SwapBytes(disconnSyn8->len);
 #endif
 
-assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
-
-disconnSyn8->len = sizeof(DISCONN_SYN_8);
 strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN);
 strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN);
 strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN);
-return disconnSyn8->len;
+return sizeof(DISCONN_SYN_8);
 }
 //---------------------------------------------------------------------------
 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
 {
 disconnAck8 = (DISCONN_ACK_8*)buffer;
 
+assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
+
+disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
+disconnAck8->rnd = rnd + 1;
+
 #ifdef ARCH_BE
 SwapBytes(disconnAck8->len);
 SwapBytes(disconnAck8->rnd);
 #endif
 
-assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
-
-disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
-disconnAck8->rnd = rnd + 1;
 strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN);
 strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN);
-return disconnAck8->len;
+return Min8(sizeof(DISCONN_ACK_8));
 }
 //---------------------------------------------------------------------------
 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)