9 #include "stg/common.h"
10 #include "stg/ia_packets.h"
14 PROTO::PROTO(const std::string & server,
22 uint32_t ip = inet_addr(server.c_str());
23 if (ip == INADDR_NONE)
25 struct hostent * hePtr = gethostbyname(server.c_str());
28 ip = *((uint32_t *)hePtr->h_addr_list[0]);
32 errorStr = "Unknown host: '";
35 printfd(__FILE__, "PROTO::PROTO() - %s\n", errorStr.c_str());
36 throw std::runtime_error(errorStr);
40 localAddr.sin_family = AF_INET;
41 localAddr.sin_port = htons(localPort);
42 localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
44 serverAddr.sin_family = AF_INET;
45 serverAddr.sin_port = htons(port);
46 serverAddr.sin_addr.s_addr = ip;
48 unsigned char key[IA_PASSWD_LEN];
49 memset(key, 0, IA_PASSWD_LEN);
50 strncpy(reinterpret_cast<char *>(key), "pr7Hhen", 8);
51 Blowfish_Init(&ctx, key, IA_PASSWD_LEN);
53 processors["CONN_SYN_ACK"] = &PROTO::CONN_SYN_ACK_Proc;
54 processors["ALIVE_SYN"] = &PROTO::ALIVE_SYN_Proc;
55 processors["DISCONN_SYN_ACK"] = &PROTO::DISCONN_SYN_ACK_Proc;
56 processors["FIN"] = &PROTO::FIN_Proc;
57 processors["INFO"] = &PROTO::INFO_Proc;
58 // ERR_Proc will be handled explicitly
65 void * PROTO::Runner(void * data)
67 PROTO * protoPtr = static_cast<PROTO *>(data);
76 if (pthread_create(&tid, NULL, &Runner, NULL))
78 errorStr = "Failed to create listening thread: '";
79 errorStr += strerror(errno);
81 printfd(__FILE__, "PROTO::Start() - %s\n", errorStr.c_str());
91 while (!stopped && time < timeout)
93 struct timespec ts = {1, 0};
99 errorStr = "Failed to stop listening thread - timed out";
100 printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
103 if (pthread_join(tid, NULL))
105 errorStr = "Failed to join listening thread after stop: '";
106 errorStr += strerror(errno);
108 printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
114 void PROTO::AddUser(const USER & user)
116 users.push_back(std::make_pair(user.GetIP(), user));
118 pfd.fd = user.GetSocket();
121 pollFds.push_back(pfd);
124 bool PROTO::Connect(uint32_t ip)
126 /*std::vector<std::pair<uint32_t, USER> >::const_iterator it;
128 if (it == users.end())
136 bool PROTO::Disconnect(uint32_t ip)
138 /*std::vector<std::pair<uint32_t, USER> >::const_iterator it;
140 if (it == users.end())
152 int res = poll(&pollFds.front(), pollFds.size(), timeout);
164 bool PROTO::RecvPacket()
167 std::vector<struct pollfd>::iterator it;
168 std::vector<std::pair<uint32_t, USER> >::iterator userIt;
169 for (it = pollFds.begin(), userIt = users.begin(); it != pollFds.end() && userIt != users.end(); ++it, ++userIt)
174 assert(it->fd == userIt->second.GetSocket() && "File descriptors from poll fds and users must be syncked");
175 struct sockaddr_in addr;
176 socklen_t fromLen = sizeof(addr);
178 int res = recvfrom(userIt->second.GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &fromLen);
186 result = result && HandlePacket(buffer, &(userIt->second));
193 bool PROTO::HandlePacket(const char * buffer, USER * user)
195 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
197 return ERR_Proc(buffer, user);
200 std::string packetName(buffer + 12);
201 std::map<std::string, PacketProcessor>::const_iterator it;
202 it = processors.find(packetName);
203 if (it != processors.end())
204 return (this->*it->second)(buffer, user);
206 printfd(__FILE__, "PROTO::HandlePacket() - invalid packet signature: '%s'\n", packetName.c_str());
211 bool PROTO::CONN_SYN_ACK_Proc(const void * buffer, USER * user)
213 const CONN_SYN_ACK_8 * packet = static_cast<const CONN_SYN_ACK_8 *>(buffer);
215 uint32_t rnd = packet->rnd;
216 uint32_t userTimeout = packet->userTimeOut;
217 uint32_t aliveTimeout = packet->aliveDelay;
221 SwapBytes(userTimeout);
222 SwapBytes(aliveDelay);
227 if (user->GetPhase() != 2)
229 errorStr = "Unexpected CONN_SYN_ACK";
230 printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
234 user->SetAliveTimeout(aliveTimeout);
235 user->SetUserTimeout(userTimeout);
241 bool PROTO::ALIVE_SYN_Proc(const void * buffer, USER * user)
243 const ALIVE_SYN_8 * packet = static_cast<const ALIVE_SYN_8 *>(buffer);
245 uint32_t rnd = packet->rnd;
251 if (user->GetPhase() != 3)
253 errorStr = "Unexpected ALIVE_SYN";
254 printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong phase: %d\n", user->GetPhase());
257 if (user->GetRnd() + 1 != rnd)
259 errorStr = "Wrong control value at ALIVE_SYN";
260 printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
266 Send_ALIVE_ACK(user);
271 bool PROTO::DISCONN_SYN_ACK_Proc(const void * buffer, USER * user)
273 const DISCONN_SYN_ACK_8 * packet = static_cast<const DISCONN_SYN_ACK_8 *>(buffer);
275 uint32_t rnd = packet->rnd;
281 if (user->GetPhase() != 4)
283 errorStr = "Unexpected DISCONN_SYN_ACK";
284 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
287 if (user->GetRnd() + 1 != rnd)
289 errorStr = "Wrong control value at DISCONN_SYN_ACK";
290 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
296 Send_DISCONN_ACK(user);
301 bool PROTO::FIN_Proc(const void * buffer, USER * user)
303 if (user->GetPhase() != 5)
305 errorStr = "Unexpected FIN";
306 printfd(__FILE__, "PROTO::FIN_Proc() - wrong phase: %d\n", user->GetPhase());
314 bool PROTO::INFO_Proc(const void * buffer, USER * user)
316 //const INFO_8 * packet = static_cast<const INFO_8 *>(buffer);
321 bool PROTO::ERR_Proc(const void * buffer, USER * user)
323 const ERR_8 * packet = static_cast<const ERR_8 *>(buffer);
324 const char * ptr = static_cast<const char *>(buffer);
326 for (size_t i = 0; i < sizeof(ERR_8) / 8; i++)
327 Blowfish_Decrypt(user->GetCtx(), (uint32_t *)(ptr + i * 8), (uint32_t *)(ptr + i * 8 + 4));
329 //uint32_t len = packet->len;
335 user->SetPhase(1); //TODO: Check
336 /*KOIToWin((const char*)err.text, &messageText);
337 if (pErrorCb != NULL)
338 pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
339 phaseTime = GetTickCount();
340 codeError = IA_SERVER_ERROR;*/
345 bool PROTO::Send_CONN_SYN(USER * user)
349 packet.len = sizeof(packet);
352 SwapBytes(packet.len);
355 strncpy((char *)packet.type, "CONN_SYN", sizeof(packet.type));
356 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
357 packet.dirs = 0xFFffFFff;
359 return SendPacket(&packet, sizeof(packet), user);
362 bool PROTO::Send_CONN_ACK(USER * user)
366 packet.len = sizeof(packet);
367 packet.rnd = user->IncRnd();
370 SwapBytes(packet.len);
371 SwapBytes(packet.rnd);
374 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
375 strncpy((char *)packet.type, "CONN_ACK", sizeof(packet.type));
377 return SendPacket(&packet, sizeof(packet), user);
380 bool PROTO::Send_ALIVE_ACK(USER * user)
384 packet.len = sizeof(packet);
385 packet.rnd = user->IncRnd();
388 SwapBytes(packet.len);
389 SwapBytes(packet.rnd);
392 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
393 strncpy((char *)packet.type, "ALIVE_ACK", sizeof(packet.type));
395 return SendPacket(&packet, sizeof(packet), user);
398 bool PROTO::Send_DISCONN_SYN(USER * user)
400 DISCONN_SYN_8 packet;
402 packet.len = sizeof(packet);
405 SwapBytes(packet.len);
408 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
409 strncpy((char *)packet.type, "DISCONN_SYN", sizeof(packet.type));
410 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
412 return SendPacket(&packet, sizeof(packet), user);
415 bool PROTO::Send_DISCONN_ACK(USER * user)
417 DISCONN_ACK_8 packet;
419 packet.len = sizeof(packet);
420 packet.rnd = user->IncRnd();
423 SwapBytes(packet.len);
424 SwapBytes(packet.rnd);
427 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
428 strncpy((char *)packet.type, "DISCONN_ACK", sizeof(packet.type));
430 return SendPacket(&packet, sizeof(packet), user);
433 bool PROTO::SendPacket(const void * packet, size_t length, USER * user)
437 assert(sizeof(hdr) + length < 2048 && "Packet length must not exceed 2048 bytes");
439 strncpy((char *)hdr.magic, IA_ID, 6);
441 hdr.protoVer[1] = 8; // IA_PROTO_VER
443 unsigned char buffer[2048];
444 memcpy(buffer, &hdr, sizeof(hdr));
445 memcpy(buffer + sizeof(hdr), packet, length);
447 size_t offset = sizeof(HDR_8);
448 for (size_t i = 0; i < IA_LOGIN_LEN / 8; i++)
450 Blowfish_Encrypt(&ctx,
451 (uint32_t *)(buffer + offset + i * 8),
452 (uint32_t *)(buffer + offset + i * 8 + 4));
455 offset += IA_LOGIN_LEN;
456 size_t encLen = (length - IA_LOGIN_LEN) / 8;
457 for (size_t i = 0; i < encLen; i++)
459 Blowfish_Encrypt(user->GetCtx(),
460 (uint32_t*)(buffer + offset + i * 8),
461 (uint32_t*)(buffer + offset + i * 8 + 4));
464 int res = sendto(user->GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
468 errorStr = "Failed to send packet: '";
469 errorStr += strerror(errno);
471 printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());
475 if (res < sizeof(buffer))
477 errorStr = "Packet sent partially";
478 printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());