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);
175 int res = poll(&pollFds.front(), pollFds.size(), timeout);
182 printfd(__FILE__, "PROTO::Run() - events: %d\n", res);
190 bool PROTO::RecvPacket()
193 std::vector<struct pollfd>::iterator it;
194 std::list<std::pair<uint32_t, USER> >::iterator userIt;
195 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
196 for (it = pollFds.begin(), userIt = users.begin(); it != pollFds.end() && userIt != users.end(); ++it, ++userIt)
201 printfd(__FILE__, "PROTO::RecvPacket() - pollfd: %d, socket: %d\n", it->fd, userIt->second.GetSocket());
202 assert(it->fd == userIt->second.GetSocket() && "File descriptors from poll fds and users must be syncked");
203 struct sockaddr_in addr;
204 socklen_t fromLen = sizeof(addr);
206 int res = recvfrom(userIt->second.GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &fromLen);
214 result = result && HandlePacket(buffer, res, &(userIt->second));
221 bool PROTO::HandlePacket(const char * buffer, size_t length, USER * user)
223 if (!strncmp(buffer + 4 + sizeof(HDR_8), "ERR", 3))
225 return ERR_Proc(buffer, user);
228 for (size_t i = 0; i < length / 8; i++)
229 Blowfish_Decrypt(user->GetCtx(),
230 (uint32_t *)(buffer + i * 8),
231 (uint32_t *)(buffer + i * 8 + 4));
233 std::string packetName(buffer + 12);
235 std::map<std::string, PacketProcessor>::const_iterator it;
236 it = processors.find(packetName);
237 if (it != processors.end())
238 return (this->*it->second)(buffer, user);
240 printfd(__FILE__, "PROTO::HandlePacket() - invalid packet signature: '%s'\n", packetName.c_str());
245 bool PROTO::CONN_SYN_ACK_Proc(const void * buffer, USER * user)
247 const CONN_SYN_ACK_8 * packet = static_cast<const CONN_SYN_ACK_8 *>(buffer);
249 uint32_t rnd = packet->rnd;
250 uint32_t userTimeout = packet->userTimeOut;
251 uint32_t aliveTimeout = packet->aliveDelay;
255 SwapBytes(userTimeout);
256 SwapBytes(aliveDelay);
259 if (user->GetPhase() != 2)
261 errorStr = "Unexpected CONN_SYN_ACK";
262 printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
266 user->SetAliveTimeout(aliveTimeout);
267 user->SetUserTimeout(userTimeout);
272 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());
277 bool PROTO::ALIVE_SYN_Proc(const void * buffer, USER * user)
279 const ALIVE_SYN_8 * packet = static_cast<const ALIVE_SYN_8 *>(buffer);
281 uint32_t rnd = packet->rnd;
287 if (user->GetPhase() != 3)
289 errorStr = "Unexpected ALIVE_SYN";
290 printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong phase: %d\n", user->GetPhase());
294 user->SetRnd(rnd); // Set new rnd value for ALIVE_ACK
296 Send_ALIVE_ACK(user);
301 bool PROTO::DISCONN_SYN_ACK_Proc(const void * buffer, USER * user)
303 const DISCONN_SYN_ACK_8 * packet = static_cast<const DISCONN_SYN_ACK_8 *>(buffer);
305 uint32_t rnd = packet->rnd;
311 if (user->GetPhase() != 4)
313 errorStr = "Unexpected DISCONN_SYN_ACK";
314 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
317 if (user->GetRnd() + 1 != rnd)
319 errorStr = "Wrong control value at DISCONN_SYN_ACK";
320 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
326 Send_DISCONN_ACK(user);
331 bool PROTO::FIN_Proc(const void * buffer, USER * user)
333 if (user->GetPhase() != 5)
335 errorStr = "Unexpected FIN";
336 printfd(__FILE__, "PROTO::FIN_Proc() - wrong phase: %d\n", user->GetPhase());
344 bool PROTO::INFO_Proc(const void * buffer, USER * user)
346 //const INFO_8 * packet = static_cast<const INFO_8 *>(buffer);
351 bool PROTO::ERR_Proc(const void * buffer, USER * user)
353 const ERR_8 * packet = static_cast<const ERR_8 *>(buffer);
354 const char * ptr = static_cast<const char *>(buffer);
356 //uint32_t len = packet->len;
362 user->SetPhase(1); //TODO: Check
363 /*KOIToWin((const char*)err.text, &messageText);
364 if (pErrorCb != NULL)
365 pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
366 phaseTime = GetTickCount();
367 codeError = IA_SERVER_ERROR;*/
372 bool PROTO::Send_CONN_SYN(USER * user)
376 packet.len = sizeof(packet);
379 SwapBytes(packet.len);
382 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
383 strncpy((char *)packet.type, "CONN_SYN", sizeof(packet.type));
384 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
385 packet.dirs = 0xFFffFFff;
387 return SendPacket(&packet, sizeof(packet), user);
390 bool PROTO::Send_CONN_ACK(USER * user)
394 packet.len = sizeof(packet);
395 packet.rnd = user->IncRnd();
398 SwapBytes(packet.len);
399 SwapBytes(packet.rnd);
402 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
403 strncpy((char *)packet.type, "CONN_ACK", sizeof(packet.type));
405 return SendPacket(&packet, sizeof(packet), user);
408 bool PROTO::Send_ALIVE_ACK(USER * user)
412 packet.len = sizeof(packet);
413 packet.rnd = user->IncRnd();
416 SwapBytes(packet.len);
417 SwapBytes(packet.rnd);
420 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
421 strncpy((char *)packet.type, "ALIVE_ACK", sizeof(packet.type));
423 return SendPacket(&packet, sizeof(packet), user);
426 bool PROTO::Send_DISCONN_SYN(USER * user)
428 DISCONN_SYN_8 packet;
430 packet.len = sizeof(packet);
433 SwapBytes(packet.len);
436 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
437 strncpy((char *)packet.type, "DISCONN_SYN", sizeof(packet.type));
438 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
440 return SendPacket(&packet, sizeof(packet), user);
443 bool PROTO::Send_DISCONN_ACK(USER * user)
445 DISCONN_ACK_8 packet;
447 packet.len = sizeof(packet);
448 packet.rnd = user->IncRnd();
451 SwapBytes(packet.len);
452 SwapBytes(packet.rnd);
455 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
456 strncpy((char *)packet.type, "DISCONN_ACK", sizeof(packet.type));
458 return SendPacket(&packet, sizeof(packet), user);
461 bool PROTO::SendPacket(const void * packet, size_t length, USER * user)
465 assert(length < 2048 && "Packet length must not exceed 2048 bytes");
467 strncpy((char *)hdr.magic, IA_ID, sizeof(hdr.magic));
469 hdr.protoVer[1] = 8; // IA_PROTO_VER
471 unsigned char buffer[2048];
472 memset(buffer, 0, sizeof(buffer));
473 memcpy(buffer, packet, length);
474 memcpy(buffer, &hdr, sizeof(hdr));
476 size_t offset = sizeof(HDR_8);
477 for (size_t i = 0; i < IA_LOGIN_LEN / 8; i++)
479 Blowfish_Encrypt(&ctx,
480 (uint32_t *)(buffer + offset + i * 8),
481 (uint32_t *)(buffer + offset + i * 8 + 4));
484 offset += IA_LOGIN_LEN;
485 size_t encLen = (length - IA_LOGIN_LEN) / 8;
486 for (size_t i = 0; i < encLen; i++)
488 Blowfish_Encrypt(user->GetCtx(),
489 (uint32_t*)(buffer + offset + i * 8),
490 (uint32_t*)(buffer + offset + i * 8 + 4));
493 int res = sendto(user->GetSocket(), buffer, length, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
497 errorStr = "Failed to send packet: '";
498 errorStr += strerror(errno);
500 printfd(__FILE__, "PROTO::SendPacket() - %s, fd: %d\n", errorStr.c_str(), user->GetSocket());
506 errorStr = "Packet sent partially";
507 printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());
514 bool PROTO::RealConnect(USER * user)
516 if (user->GetPhase() != 1 &&
517 user->GetPhase() != 5)
519 errorStr = "Unexpected connect";
520 printfd(__FILE__, "PROTO::RealConnect() - wrong phase: %d\n", user->GetPhase());
524 return Send_CONN_SYN(user);
527 bool PROTO::RealDisconnect(USER * user)
529 if (user->GetPhase() != 3)
531 errorStr = "Unexpected disconnect";
532 printfd(__FILE__, "PROTO::RealDisconnect() - wrong phase: %d\n", user->GetPhase());
536 return Send_DISCONN_SYN(user);