9 #include "stg/common.h"
13 PROTO::PROTO(const std::string & server,
21 uint32_t ip = inet_addr(server.c_str());
22 if (ip == INADDR_NONE)
24 struct hostent * hePtr = gethostbyname(server.c_str());
27 ip = *((uint32_t *)hePtr->h_addr_list[0]);
31 errorStr = "Unknown host: '";
34 printfd(__FILE__, "PROTO::PROTO() - %s\n", errorStr.c_str());
35 throw std::runtime_error(errorStr);
39 localAddr.sin_family = AF_INET;
40 localAddr.sin_port = htons(localPort);
41 localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
43 serverAddr.sin_family = AF_INET;
44 serverAddr.sin_port = htons(port);
45 serverAddr.sin_addr.s_addr = ip;
47 unsigned char key[IA_PASSWD_LEN];
48 memset(key, 0, IA_PASSWD_LEN);
49 strncpy(reinterpret_cast<char *>(key), "pr7Hhen", 8);
50 Blowfish_Init(&ctx, key, IA_PASSWD_LEN);
52 processors["CONN_SYN_ACK"] = &PROTO::CONN_SYN_ACK_Proc;
53 processors["ALIVE_SYN"] = &PROTO::ALIVE_SYN_Proc;
54 processors["DISCONN_SYN_ACK"] = &PROTO::DISCONN_SYN_ACK_Proc;
55 processors["FIN"] = &PROTO::FIN_Proc;
56 processors["INFO"] = &PROTO::INFO_Proc;
57 // ERR_Proc will be handled explicitly
64 void * PROTO::Runner(void * data)
66 PROTO * protoPtr = static_cast<PROTO *>(data);
74 if (pthread_create(&tid, NULL, &Runner, NULL))
76 errorStr = "Failed to create listening thread: '";
77 errorStr += strerror(errno);
79 printfd(__FILE__, "PROTO::Start() - %s\n", errorStr.c_str());
89 while (!stopped && time < timeout)
91 struct timespec ts = {1, 0};
97 errorStr = "Failed to stop listening thread - timed out";
98 printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
101 if (pthread_join(tid, NULL))
103 errorStr = "Failed to join listening thread after stop: '";
104 errorStr += strerror(errno);
106 printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str());
112 void PROTO::AddUser(const USER & user)
114 users.insert(std::make_pair(user.GetIP(), user));
116 pfd.fd = user.GetSocket();
119 pollFds.push_back(pfd);
122 bool PROTO::Connect(uint32_t ip)
124 std::map<uint32_t, USER>::const_iterator it;
126 if (it == users.end())
134 bool PROTO::Disconnect(uint32_t ip)
136 std::map<uint32_t, USER>::const_iterator it;
138 if (it == users.end())
150 int res = poll(&pollFds.front(), pollFds.size(), timeout);
162 bool PROTO::RecvPacket()
165 std::vector<struct pollfd>::iterator it;
166 std::map<uint32_t, USER>::iterator userIt(users.begin());
167 for (it = pollFds.begin(); it != pollFds.end(); ++it)
172 assert(it->fd == userIt->second.GetSocket() && "File descriptors from poll fds and users must be syncked");
173 struct sockaddr_in addr;
174 socklen_t fromLen = sizeof(addr);
176 int res = recvfrom(userIt->second.GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &fromLen);
185 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);
209 bool PROTO::CONN_SYN_ACK_Proc(const void * buffer, USER * user)
211 const CONN_SYN_ACK_8 * packet = static_cast<const CONN_SYN_ACK_8 *>(buffer);
213 uint32_t rnd = packet->rnd;
214 uint32_t userTimeout = packet->userTimeOut;
215 uint32_t aliveTimeout = packet->aliveDelay;
219 SwapBytes(userTimeout);
220 SwapBytes(aliveDelay);
225 if (user->GetPhase() != 2)
227 errorStr = "Unexpected CONN_SYN_ACK";
228 printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
232 user->SetAliveTimeout(aliveTimeout);
233 user->SetUserTimeout(userTimeout);
239 bool PROTO::ALIVE_SYN_Proc(const void * buffer, USER * user)
241 const ALIVE_SYN_8 * packet = static_cast<const ALIVE_SYN_8 *>(buffer);
243 uint32_t rnd = packet->rnd;
249 if (user->GetPhase() != 3)
251 errorStr = "Unexpected ALIVE_SYN";
252 printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong phase: %d\n", user->GetPhase());
255 if (user->GetRnd() + 1 != rnd)
257 errorStr = "Wrong control value at ALIVE_SYN";
258 printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
264 Send_ALIVE_ACK(user);
269 bool PROTO::DISCONN_SYN_ACK_Proc(const void * buffer, USER * user)
271 const DISCONN_SYN_ACK_8 * packet = static_cast<const DISCONN_SYN_ACK_8 *>(buffer);
273 uint32_t rnd = packet->rnd;
279 if (user->GetPhase() != 4)
281 errorStr = "Unexpected DISCONN_SYN_ACK";
282 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase());
285 if (user->GetRnd() + 1 != rnd)
287 errorStr = "Wrong control value at DISCONN_SYN_ACK";
288 printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1);
294 Send_DISCONN_ACK(user);
299 bool PROTO::FIN_Proc(const void * buffer, USER * user)
301 if (user->GetPhase() != 5)
303 errorStr = "Unexpected FIN";
304 printfd(__FILE__, "PROTO::FIN_Proc() - wrong phase: %d\n", user->GetPhase());
312 bool PROTO::INFO_Proc(const void * buffer, USER * user)
314 //const INFO_8 * packet = static_cast<const INFO_8 *>(buffer);
319 bool PROTO::ERR_Proc(const void * buffer, USER * user)
321 const ERR_8 * packet = static_cast<const ERR_8 *>(buffer);
323 for (int i = 0; i < len/8; i++)
324 Blowfish_Decrypt(&ctxPass, (uint32_t*)(buffer + i*8), (uint32_t*)(buffer + i*8 + 4));
326 //uint32_t len = packet->len;
332 user->SetPhase(1); //TODO: Check
333 /*KOIToWin((const char*)err.text, &messageText);
334 if (pErrorCb != NULL)
335 pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
336 phaseTime = GetTickCount();
337 codeError = IA_SERVER_ERROR;*/
342 bool PROTO::Send_CONN_SYN(USER * user)
346 packet.len = sizeof(packet);
349 SwapBytes(packet.len);
352 strncpy((char *)packet.type, "CONN_SYN", sizeof(packet.type));
353 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
354 packet.dirs = 0xFFffFFff;
356 return SendPacket(&packet, sizeof(packet), user);
359 bool PROTO::Send_CONN_ACK(USER * user)
363 packet.len = sizeof(packet);
364 packet.rnd = user->IncRnd();
367 SwapBytes(packet.len);
368 SwapBytes(packet.rnd);
371 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
372 strncpy((char *)packet.type, "CONN_ACK", sizeof(packet.type));
374 return SendPacket(&packet, sizeof(packet), user);
377 bool PROTO::Send_ALIVE_ACK(USER * user)
381 packet.len = sizeof(packet);
382 packet.rnd = user->IncRnd();
385 SwapBytes(packet.len);
386 SwapBytes(packet.rnd);
389 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
390 strncpy((char *)packet.type, "ALIVE_ACK", sizeof(packet.type));
392 return SendPacket(&packet, sizeof(packet), user);
395 bool PROTO::Send_DISCONN_SYN(USER * user)
397 DISCONN_SYN_8 packet;
399 packet.len = sizeof(packet);
402 SwapBytes(packet.len);
405 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
406 strncpy((char *)packet.type, "DISCONN_SYN", sizeof(packet.type));
407 strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login));
409 return SendPacket(&packet, sizeof(packet), user);
412 bool PROTO::Send_DISCONN_ACK(USER * user)
414 DISCONN_ACK_8 packet;
416 packet.len = sizeof(packet);
417 packet.rnd = user->IncRnd();
420 SwapBytes(packet.len);
421 SwapBytes(packet.rnd);
424 strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS));
425 strncpy((char *)packet.type, "DISCONN_ACK", sizeof(packet.type));
427 return SendPacket(&packet, sizeof(packet), user);
430 bool PROTO::SendPacket(const void * packet, size_t length, USER * user)
434 assert(sizeof(hdr) + length < 2048 && "Packet length must not exceed 2048 bytes");
436 strncpy((char *)hdr.magic, IA_ID, 6);
438 hdr.protoVer[1] = IA_PROTO_VER;
440 unsigned char buffer[2048];
441 memcpy(buffer, &hdr, sizeof(hdr));
442 memcpy(buffer + sizeof(hdr), packet, length);
444 size_t offset = sizeof(HDR_8);
445 for (size_t i = 0; i < IA_LOGIN_LEN / 8; i++)
447 Blowfish_Encrypt(&ctx,
448 (uint32_t *)(buffer + offset + i * 8),
449 (uint32_t *)(buffer + offset + i * 8 + 4));
452 offset += IA_LOGIN_LEN;
453 size_t encLen = (length - IA_LOGIN_LEN) / 8;
454 for (size_t i = 0; i < encLen; i++)
456 Blowfish_Encrypt(user->GetCtx(),
457 (uint32_t*)(buffer + offset + i * 8),
458 (uint32_t*)(buffer + offset + i * 8 + 4));
461 int res = sendto(user->GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
465 errorStr = "Failed to send packet: '";
466 errorStr += strerror(errno);
468 printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());
472 if (res < sizeof(buffer))
474 errorStr = "Packet sent partially";
475 printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str());