10 #include "stg/common.h"
 
  11 #include "stg/ia_packets.h"
 
  12 #include "stg/locker.h"
 
  16 class HasIP : public std::unary_function<std::pair<uint32_t, USER>, bool> {
 
  18         explicit HasIP(uint32_t i) : ip(i) {}
 
  19         bool operator()(const std::pair<uint32_t, USER> & value) { return value.first == ip; }
 
  24 PROTO::PROTO(const std::string & server,
 
  32 uint32_t ip = inet_addr(server.c_str());
 
  33 if (ip == INADDR_NONE)
 
  35     struct hostent * hePtr = gethostbyname(server.c_str());
 
  38         ip = *((uint32_t *)hePtr->h_addr_list[0]);
 
  42         errorStr = "Unknown host: '";
 
  45         printfd(__FILE__, "PROTO::PROTO() - %s\n", errorStr.c_str());
 
  46         throw std::runtime_error(errorStr);
 
  50 localAddr.sin_family = AF_INET;
 
  51 localAddr.sin_port = htons(localPort);
 
  52 localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
 
  54 serverAddr.sin_family = AF_INET;
 
  55 serverAddr.sin_port = htons(port);
 
  56 serverAddr.sin_addr.s_addr = ip;
 
  58 unsigned char key[IA_PASSWD_LEN];
 
  59 memset(key, 0, IA_PASSWD_LEN);
 
  60 strncpy(reinterpret_cast<char *>(key), "pr7Hhen", 8);
 
  61 Blowfish_Init(&ctx, key, IA_PASSWD_LEN);
 
  63 processors["CONN_SYN_ACK"] = &PROTO::CONN_SYN_ACK_Proc;
 
  64 processors["ALIVE_SYN"] = &PROTO::ALIVE_SYN_Proc;
 
  65 processors["DISCONN_SYN_ACK"] = &PROTO::DISCONN_SYN_ACK_Proc;
 
  66 processors["FIN"] = &PROTO::FIN_Proc;
 
  67 processors["INFO"] = &PROTO::INFO_Proc;
 
  68 // ERR_Proc will be handled explicitly
 
  70 pthread_mutex_init(&mutex, NULL);
 
  75 pthread_mutex_destroy(&mutex);
 
  78 void * PROTO::Runner(void * data)
 
  80 PROTO * protoPtr = static_cast<PROTO *>(data);
 
  89 if (pthread_create(&tid, NULL, &Runner, this))
 
  91     errorStr = "Failed to create listening thread: '";
 
  92     errorStr += strerror(errno);
 
  94     printfd(__FILE__, "PROTO::Start() - %s\n", errorStr.c_str());
 
 104 while (!stopped && time < timeout)
 
 106     struct timespec ts = {1, 0};
 
 107     nanosleep(&ts, NULL);
 
 112     errorStr = "Failed to stop listening thread - timed out";
 
 113     printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
 
 116 if (pthread_join(tid, NULL))
 
 118     errorStr = "Failed to join listening thread after stop: '";
 
 119     errorStr += strerror(errno);
 
 121     printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
 
 127 void PROTO::AddUser(const USER & user, bool connect)
 
 129 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 130 users.push_back(std::make_pair(user.GetIP(), user));
 
 131 users.back().second.InitNetwork();
 
 134 pfd.fd = users.back().second.GetSocket();
 
 137 pollFds.push_back(pfd);
 
 141     RealConnect(&users.back().second);
 
 145 bool PROTO::Connect(uint32_t ip)
 
 147 std::list<std::pair<uint32_t, USER> >::iterator it;
 
 148 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 149 it = std::find_if(users.begin(), users.end(), HasIP(ip));
 
 150 if (it == users.end())
 
 155 return RealConnect(&it->second);
 
 158 bool PROTO::Disconnect(uint32_t ip)
 
 160 std::list<std::pair<uint32_t, USER> >::iterator it;
 
 161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 162 it = std::find_if(users.begin(), users.end(), HasIP(ip));
 
 163 if (it == users.end())
 
 168 return RealDisconnect(&it->second);
 
 177         STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 178         res = poll(&pollFds.front(), pollFds.size(), timeout);
 
 186         printfd(__FILE__, "PROTO::Run() - events: %d\n", res);
 
 198 void PROTO::CheckTimeouts()
 
 200 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 201 std::list<std::pair<uint32_t, USER> >::iterator it;
 
 202 for (it = users.begin(); it != users.end(); ++it)
 
 204     int delta = difftime(time(NULL), it->second.GetPhaseChangeTime());
 
 205     if ((it->second.GetPhase() == 3) &&
 
 206         (delta > it->second.GetUserTimeout()))
 
 208         printfd(__FILE__, "PROTO::CheckTimeouts() - user alive timeout (ip: %s, login: '%s', delta: %d > %d)\n", inet_ntostring(it->second.GetIP()).c_str(), it->second.GetLogin().c_str(), delta, it->second.GetUserTimeout());
 
 209         it->second.SetPhase(1);
 
 211     if ((it->second.GetPhase() == 2) &&
 
 212         (delta > it->second.GetAliveTimeout()))
 
 214         printfd(__FILE__, "PROTO::CheckTimeouts() - user connect timeout (ip: %s, login: '%s', delta: %d > %d)\n", inet_ntostring(it->second.GetIP()).c_str(), it->second.GetLogin().c_str(), delta, it->second.GetAliveTimeout());
 
 215         it->second.SetPhase(1);
 
 220 bool PROTO::RecvPacket()
 
 223 std::vector<struct pollfd>::iterator it;
 
 224 std::list<std::pair<uint32_t, USER> >::iterator userIt;
 
 225 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 226 for (it = pollFds.begin(), userIt = users.begin(); it != pollFds.end() && userIt != users.end(); ++it, ++userIt)
 
 231         assert(it->fd == userIt->second.GetSocket() && "File descriptors from poll fds and users must be syncked");
 
 232         struct sockaddr_in addr;
 
 233         socklen_t fromLen = sizeof(addr);
 
 235         int res = recvfrom(userIt->second.GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &fromLen);
 
 243         result = result && HandlePacket(buffer, res, &(userIt->second));
 
 250 bool PROTO::HandlePacket(const char * buffer, size_t length, USER * user)
 
 252 if (!strncmp(buffer + 4 + sizeof(HDR_8), "ERR", 3))
 
 254     return ERR_Proc(buffer, user);
 
 257 for (size_t i = 0; i < length / 8; i++)
 
 258     Blowfish_Decrypt(user->GetCtx(),
 
 259                      (uint32_t *)(buffer + i * 8),
 
 260                      (uint32_t *)(buffer + i * 8 + 4));
 
 262 std::string packetName(buffer + 12);
 
 264 std::map<std::string, PacketProcessor>::const_iterator it;
 
 265 it = processors.find(packetName);
 
 266 if (it != processors.end())
 
 267     return (this->*it->second)(buffer, user);
 
 269 printfd(__FILE__, "PROTO::HandlePacket() - invalid packet signature: '%s'\n", packetName.c_str());
 
 274 bool PROTO::CONN_SYN_ACK_Proc(const void * buffer, USER * user)
 
 276 const CONN_SYN_ACK_8 * packet = static_cast<const CONN_SYN_ACK_8 *>(buffer);
 
 278 uint32_t rnd = packet->rnd;
 
 279 uint32_t userTimeout = packet->userTimeOut;
 
 280 uint32_t aliveTimeout = packet->aliveDelay;
 
 284 SwapBytes(userTimeout);
 
 285 SwapBytes(aliveDelay);
 
 288 if (user->GetPhase() != 2)
 
 290     errorStr = "Unexpected CONN_SYN_ACK";
 
 291     printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
 
 296 user->SetAliveTimeout(aliveTimeout);
 
 297 user->SetUserTimeout(userTimeout);
 
 302 printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - user '%s' successfully logged in from IP %s\n", user->GetLogin().c_str(), inet_ntostring(user->GetIP()).c_str());
 
 307 bool PROTO::ALIVE_SYN_Proc(const void * buffer, USER * user)
 
 309 const ALIVE_SYN_8 * packet = static_cast<const ALIVE_SYN_8 *>(buffer);
 
 311 uint32_t rnd = packet->rnd;
 
 317 if (user->GetPhase() != 3)
 
 319     errorStr = "Unexpected ALIVE_SYN";
 
 320     printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong phase: %d\n", user->GetPhase());
 
 325 user->SetRnd(rnd); // Set new rnd value for ALIVE_ACK
 
 327 Send_ALIVE_ACK(user);
 
 332 bool PROTO::DISCONN_SYN_ACK_Proc(const void * buffer, USER * user)
 
 334 const DISCONN_SYN_ACK_8 * packet = static_cast<const DISCONN_SYN_ACK_8 *>(buffer);
 
 336 uint32_t rnd = packet->rnd;
 
 342 if (user->GetPhase() != 4)
 
 344     errorStr = "Unexpected DISCONN_SYN_ACK";
 
 345     printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
 
 349 if (user->GetRnd() + 1 != rnd)
 
 351     errorStr = "Wrong control value at DISCONN_SYN_ACK";
 
 352     printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
 
 358 Send_DISCONN_ACK(user);
 
 363 bool PROTO::FIN_Proc(const void * buffer, USER * user)
 
 365 if (user->GetPhase() != 5)
 
 367     errorStr = "Unexpected FIN";
 
 368     printfd(__FILE__, "PROTO::FIN_Proc() - wrong phase: %d\n", user->GetPhase());
 
 377 bool PROTO::INFO_Proc(const void * buffer, USER * user)
 
 379 //const INFO_8 * packet = static_cast<const INFO_8 *>(buffer);
 
 384 bool PROTO::ERR_Proc(const void * buffer, USER * user)
 
 386 const ERR_8 * packet = static_cast<const ERR_8 *>(buffer);
 
 387 const char * ptr = static_cast<const char *>(buffer);
 
 389 //uint32_t len = packet->len;
 
 395 user->SetPhase(1); //TODO: Check
 
 396 /*KOIToWin((const char*)err.text, &messageText);
 
 397 if (pErrorCb != NULL)
 
 398     pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
 
 399 phaseTime = GetTickCount();
 
 400 codeError = IA_SERVER_ERROR;*/
 
 405 bool PROTO::Send_CONN_SYN(USER * user)
 
 409 packet.len = sizeof(packet);
 
 412 SwapBytes(packet.len);
 
 415 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
 
 416 strncpy((char *)packet.type, "CONN_SYN", sizeof(packet.type));
 
 417 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
 
 418 packet.dirs = 0xFFffFFff;
 
 420 return SendPacket(&packet, sizeof(packet), user);
 
 423 bool PROTO::Send_CONN_ACK(USER * user)
 
 427 packet.len = sizeof(packet);
 
 428 packet.rnd = user->IncRnd();
 
 431 SwapBytes(packet.len);
 
 432 SwapBytes(packet.rnd);
 
 435 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
 
 436 strncpy((char *)packet.type, "CONN_ACK", sizeof(packet.type));
 
 438 return SendPacket(&packet, sizeof(packet), user);
 
 441 bool PROTO::Send_ALIVE_ACK(USER * user)
 
 445 packet.len = sizeof(packet);
 
 446 packet.rnd = user->IncRnd();
 
 449 SwapBytes(packet.len);
 
 450 SwapBytes(packet.rnd);
 
 453 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
 
 454 strncpy((char *)packet.type, "ALIVE_ACK", sizeof(packet.type));
 
 456 return SendPacket(&packet, sizeof(packet), user);
 
 459 bool PROTO::Send_DISCONN_SYN(USER * user)
 
 461 DISCONN_SYN_8 packet;
 
 463 packet.len = sizeof(packet);
 
 466 SwapBytes(packet.len);
 
 469 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
 
 470 strncpy((char *)packet.type, "DISCONN_SYN", sizeof(packet.type));
 
 471 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
 
 473 return SendPacket(&packet, sizeof(packet), user);
 
 476 bool PROTO::Send_DISCONN_ACK(USER * user)
 
 478 DISCONN_ACK_8 packet;
 
 480 packet.len = sizeof(packet);
 
 481 packet.rnd = user->IncRnd();
 
 484 SwapBytes(packet.len);
 
 485 SwapBytes(packet.rnd);
 
 488 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
 
 489 strncpy((char *)packet.type, "DISCONN_ACK", sizeof(packet.type));
 
 491 return SendPacket(&packet, sizeof(packet), user);
 
 494 bool PROTO::SendPacket(const void * packet, size_t length, USER * user)
 
 498 assert(length < 2048 && "Packet length must not exceed 2048 bytes");
 
 500 strncpy((char *)hdr.magic, IA_ID, sizeof(hdr.magic));
 
 502 hdr.protoVer[1] = 8; // IA_PROTO_VER
 
 504 unsigned char buffer[2048];
 
 505 memset(buffer, 0, sizeof(buffer));
 
 506 memcpy(buffer, packet, length);
 
 507 memcpy(buffer, &hdr, sizeof(hdr));
 
 509 size_t offset = sizeof(HDR_8);
 
 510 for (size_t i = 0; i < IA_LOGIN_LEN / 8; i++)
 
 512     Blowfish_Encrypt(&ctx,
 
 513                      (uint32_t *)(buffer + offset + i * 8),
 
 514                      (uint32_t *)(buffer + offset + i * 8 + 4));
 
 517 offset += IA_LOGIN_LEN;
 
 518 size_t encLen = (length - IA_LOGIN_LEN) / 8;
 
 519 for (size_t i = 0; i < encLen; i++)
 
 521     Blowfish_Encrypt(user->GetCtx(),
 
 522                      (uint32_t*)(buffer + offset + i * 8),
 
 523                      (uint32_t*)(buffer + offset + i * 8 + 4));
 
 526 int res = sendto(user->GetSocket(), buffer, length, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
 
 530     errorStr = "Failed to send packet: '";
 
 531     errorStr += strerror(errno);
 
 533     printfd(__FILE__, "PROTO::SendPacket() - %s, fd: %d\n", errorStr.c_str(), user->GetSocket());
 
 539     errorStr = "Packet sent partially";
 
 540     printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());
 
 547 bool PROTO::RealConnect(USER * user)
 
 549 if (user->GetPhase() != 1 &&
 
 550     user->GetPhase() != 5)
 
 552     errorStr = "Unexpected connect";
 
 553     printfd(__FILE__, "PROTO::RealConnect() - wrong phase: %d\n", user->GetPhase());
 
 557 return Send_CONN_SYN(user);
 
 560 bool PROTO::RealDisconnect(USER * user)
 
 562 if (user->GetPhase() != 3)
 
 564     errorStr = "Unexpected disconnect";
 
 565     printfd(__FILE__, "PROTO::RealDisconnect() - wrong phase: %d\n", user->GetPhase());
 
 569 return Send_DISCONN_SYN(user);