├── CPPBot.cpp ├── README.md ├── build.sh ├── config.json ├── corefunc.h ├── enet ├── callbacks.c ├── compress.c ├── host.c ├── include │ ├── callbacks.h │ ├── enet.h │ ├── list.h │ ├── protocol.h │ ├── time2.h │ ├── types.h │ ├── unix.h │ ├── utility.h │ └── win32.h ├── list.c ├── packet.c ├── peer.c ├── protocol.c ├── unix.c └── win32.c ├── json.hpp ├── linux.sh ├── pch.cpp ├── pch.h ├── termux.sh ├── userfunc.h └── utilsfunc.h /CPPBot.cpp: -------------------------------------------------------------------------------- 1 | // CPPBot.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "corefunc.h" 9 | #include "userfunc.h" 10 | #include 11 | #include 12 | #include 13 | #include "json.hpp" 14 | 15 | using json = nlohmann::json; 16 | using namespace std; 17 | vector bots; 18 | 19 | int main() { 20 | ifstream i("config.json"); 21 | json j; 22 | i >> j; 23 | init(); 24 | system("clear"); 25 | cout << "GrowtopiaBot v1.0 [Not included QT]! by GrowtopiaNoobs and DrOreo002" << endl; 26 | 27 | if (j["ip"] == "Ip Target") 28 | { 29 | cout << "Please change the \"Ip Target\" to ip gtps on config.json" << endl; 30 | return 0; 31 | } 32 | 33 | GrowtopiaBot bot = { 34 | j["username"], j["password"], j["ip"], j["port"] 35 | }; 36 | cout << "------------------------" << endl; 37 | cout << "Bot loaded!. Using username " << j["username"].get() << ", With owner " + j["ownerUsername"].get() << endl; 38 | 39 | bot.gameVersion = j["gameVersion"].get(); 40 | bot.worldName = j["targetWorld"].get(); 41 | bot.ownerUsername = j["ownerUsername"].get(); 42 | 43 | bot.userInit(); 44 | bots.push_back(bot); 45 | 46 | while (true) { 47 | bot.eventLoop(); 48 | bot.userLoop(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GTBotLinux 2 | A GrowtopiaBot can run on Linux, GrowtopiaBot Made by DrOreo002 and GrowtopiaNoobs
3 | i just make support linux
4 | Update = Now gtbot Support login to real gt (thanks to atipls) 5 | # Warning 6 | GTBotLinux is still experiment, if you get error, dont forget to screenshot and post to issue
7 | # How to build 8 | 15 | Termux
16 | 1. pkg update -y && pkg upgrade -y 17 | 2. pkg install git nano 18 | 3. git clone https://github.com/GuckTubeYT/GTBotLinux 19 | 4. cd GTBotLinux 20 | 5. bash termux.sh 21 | 6. dont forget to edit config.json, Command = nano config.json 22 | 7. ./gtbot 23 | 24 | Linux
25 | 1. sudo apt update -y && sudo apt upgrade -y 26 | 2. sudo apt install git nano 27 | 3. git clone https://github.com/GuckTubeYT/GTBotLinux 28 | 4. cd GTBotLinux 29 | 5. bash linux.sh 30 | 6. dont forget to edit config.json, Command = nano config.json 31 | 7. ./gtbot 32 | # Setting 33 | Just edit the config.json
34 | To edit = nano config.json 35 | # Join 36 | Join my Discord Group = https://bit.ly/guckproject 37 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | # If you already install g++ or build-essential, use this 2 | g++ CPPBot.cpp enet/callbacks.c enet/compress.c enet/host.c enet/list.c enet/packet.c enet/peer.c enet/protocol.c enet/unix.c -Wall -std=c++11 -fpermissive -o gtbot -latomic #Build source code into executable 3 | echo "Build Successfully! you just do ./gtbot on terminal" 4 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "Dirgahayu", 3 | "password": "Indonesia75Tahun", 4 | "gameVersion": "3.53", 5 | "targetWorld": "INDONESIA", 6 | "ownerUsername": "DrOreo002", 7 | "ip": "Ip Target", 8 | "port": 17091 9 | } 10 | -------------------------------------------------------------------------------- /corefunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Grotopia Bot 4 | // Copyright (C) 2018 Growtopia Noobs 5 | // 6 | // This program is free software: you can redistribute it and/or modify 7 | // it under the terms of the GNU Affero General Public License as published 8 | // by the Free Software Foundation, either version 3 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU Affero General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU Affero General Public License 17 | // along with this program. If not, see . 18 | 19 | #include "enet/include/enet.h" 20 | #include 21 | //#include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "json.hpp" 32 | #define byte uint8_t 33 | #define BYTE uint8_t 34 | 35 | typedef unsigned long DWORD; 36 | typedef unsigned long dword; 37 | 38 | using namespace std; 39 | using json = nlohmann::json; 40 | 41 | /********* hidden vars ********/ 42 | class GrowtopiaBot { 43 | public: 44 | ENetPeer *peer; 45 | ENetHost * client; 46 | 47 | int login_user = 0; 48 | int login_token = 0; 49 | 50 | string currentWorld; 51 | int timeFromWorldEnter = 0; // in 10mss... 52 | 53 | string gameVersion = "3.011"; 54 | /********* hidden vars ********/ 55 | 56 | 57 | /********** user sutff ***************/ 58 | int owner = -1; 59 | string ownerUsername; 60 | 61 | struct ObjectData 62 | { 63 | int netId = -1; // used to interact with stuff in world 64 | int userId = -1; // growtopia id 65 | string name = ""; 66 | string country = ""; 67 | string objectType = ""; // "avatar" is player creature 68 | float x = -1; 69 | float y = -1; 70 | bool isGone = false; // set true if character left 71 | int rectX; // collision stuff 72 | int rectY; // collision stuff 73 | int rectWidth; // collision stuff 74 | int rectHeight; // collision stuff 75 | bool isMod = false; 76 | bool isLocal = false; 77 | }; 78 | 79 | vector objects; 80 | 81 | string uname; 82 | string upass; 83 | string SERVER_HOST; 84 | int SERVER_PORT; 85 | string worldName; // excepted world name 86 | 87 | bool isFollowing = false; 88 | bool backwardWalk = false; 89 | 90 | int respawnX; 91 | int respawnY; 92 | /********** user sutff ***************/ 93 | 94 | /*********** structs declaration *********/ 95 | struct PlayerMoving { 96 | int netID; 97 | float x; 98 | float y; 99 | int characterState; 100 | int plantingTree; 101 | float XSpeed; 102 | float YSpeed; 103 | int punchX; 104 | int punchY; 105 | 106 | }; 107 | /*********** structs declaration *********/ 108 | 109 | 110 | /********* user funcs *********/ 111 | void userRender(); 112 | void userRender2(); 113 | void userLoop(); 114 | void userInit(); 115 | void onLoginRequested(); 116 | void packet_type3(string text); 117 | void packet_type6(string text); 118 | void packet_unknown(ENetPacket* packet); 119 | void OnSendToServer(string address, int port, int userId, int token); 120 | void OnConsoleMessage(string message); 121 | void OnPlayPositioned(string sound); 122 | void OnSetFreezeState(int state); 123 | void OnRemove(string data); 124 | void OnSpawn(string data); 125 | void OnAction(string command); 126 | void SetHasGrowID(int state, string name, string password); 127 | void SetHasAccountSecured(int state); 128 | void OnTalkBubble(int netID, string bubbleText, int type); 129 | void SetRespawnPos(int respawnPos); 130 | void OnEmoticonDataChanged(int val1, string emoticons); 131 | void OnSetPos(float x, float y); 132 | void OnAddNotification(string image, string message, string audio, int val1); 133 | void AtApplyTileDamage(int x, int y, int damge); 134 | void AtApplyLock(int x, int y, int itemId); 135 | void AtPlayerMoving(PlayerMoving* data); 136 | void AtAvatarSetIconState(int netID, int state); 137 | void WhenConnected(); 138 | void WhenDisconnected(); 139 | 140 | void respawn(); 141 | /********* user funcs *********/ 142 | 143 | /*************** debug stuff ***************/ 144 | void dbgPrint(string text) 145 | { 146 | cout << "[DBG] " + text << endl; 147 | } 148 | /*************** debug stuff ***************/ 149 | 150 | GrowtopiaBot(string username, string password, string ip, int port) 151 | { 152 | this->uname = username; 153 | this->upass = password; 154 | this->SERVER_HOST = ip; 155 | this->SERVER_PORT = port; 156 | } 157 | 158 | /******************* enet core *********************/ 159 | void SendPacket(int a1, string a2, ENetPeer* enetPeer) 160 | { 161 | if (enetPeer) 162 | { 163 | ENetPacket* v3 = enet_packet_create(0, a2.length() + 5, 1); 164 | memcpy(v3->data, &a1, 4); 165 | //*(v3->data) = (DWORD)a1; 166 | memcpy((v3->data) + 4, a2.c_str(), a2.length()); 167 | 168 | //cout << std::hex << (int)(char)v3->data[3] << endl; 169 | enet_peer_send(enetPeer, 0, v3); 170 | } 171 | } 172 | 173 | void SendPacketRaw(int a1, void *packetData, size_t packetDataSize, void *a4, ENetPeer* peer, int packetFlag) 174 | { 175 | ENetPacket *p; 176 | 177 | if (peer) // check if we have it setup 178 | { 179 | if (a1 == 4 && *((BYTE *)packetData + 12) & 8) 180 | { 181 | p = enet_packet_create(0, packetDataSize + *((DWORD *)packetData + 13) + 5, packetFlag); 182 | int four = 4; 183 | memcpy(p->data, &four, 4); 184 | memcpy((char *)p->data + 4, packetData, packetDataSize); 185 | memcpy((char *)p->data + packetDataSize + 4, a4, *((DWORD *)packetData + 13)); 186 | enet_peer_send(peer, 0, p); 187 | } 188 | else 189 | { 190 | p = enet_packet_create(0, packetDataSize + 5, packetFlag); 191 | memcpy(p->data, &a1, 4); 192 | memcpy((char *)p->data + 4, packetData, packetDataSize); 193 | enet_peer_send(peer, 0, p); 194 | } 195 | } 196 | } 197 | 198 | // Connect with default value 199 | void connectClient() { 200 | connectClient(SERVER_HOST, SERVER_PORT); 201 | } 202 | 203 | void connectClient(string hostName, int port) 204 | { 205 | cout << "Connecting bot to " << hostName << ":" << port << endl; 206 | client = enet_host_create(NULL /* create a client host */, 207 | 1 /* only allow 1 outgoing connection */, 208 | 2 /* allow up 2 channels to be used, 0 and 1 */, 209 | 0 /* 56K modem with 56 Kbps downstream bandwidth */, 210 | 0 /* 56K modem with 14 Kbps upstream bandwidth */); 211 | client->usingNewPacket = true; 212 | if (client == NULL) 213 | { 214 | cout << "An error occurred while trying to create an ENet client host.\n"; 215 | 216 | exit(EXIT_FAILURE); 217 | } 218 | ENetAddress address; 219 | 220 | client->checksum = enet_crc32; 221 | enet_host_compress_with_range_coder(client); 222 | enet_address_set_host(&address, hostName.c_str()); 223 | address.port = port; 224 | 225 | /* Initiate the connection, allocating the two channels 0 and 1. */ 226 | peer = enet_host_connect(client, &address, 2, 0); 227 | if (peer == NULL) 228 | { 229 | cout << "No available peers for initiating an ENet connection.\n"; 230 | 231 | exit(EXIT_FAILURE); 232 | } 233 | enet_host_flush(client); 234 | } 235 | /******************* enet core *********************/ 236 | 237 | 238 | 239 | /*************** sender sutff **************/ 240 | 241 | void RequestItemActivate(unsigned int item) 242 | { 243 | BYTE* data = new BYTE[56]; 244 | for (int i = 0; i < 56; i++) 245 | { 246 | data[i] = 0; 247 | } 248 | BYTE ten = 10; 249 | memcpy(data + 0, &ten, 1); 250 | memcpy(data + 20, &item, 1); 251 | SendPacketRaw(4, data, 0x38u, 0, peer, 1); 252 | free(data); 253 | } 254 | 255 | void SetAndBroadcastIconState(int netID, int state) 256 | { 257 | BYTE* data = new BYTE[56]; 258 | for (int i = 0; i < 56; i++) 259 | { 260 | data[i] = 0; 261 | } 262 | BYTE eighteen = 18; 263 | memcpy(data + 0, &eighteen, 1); 264 | memcpy(data + 4, &netID, 4); // (a1+40) 265 | memcpy(data + 44, &state, 4); 266 | SendPacketRaw(4, data, 0x38u, 0, peer, 1); 267 | free(data); 268 | } 269 | 270 | void SendPing() 271 | { 272 | BYTE* data = new BYTE[56]; 273 | for (int i = 0; i < 56; i++) 274 | { 275 | data[i] = 0; 276 | } 277 | BYTE twentytwo = 22; 278 | memcpy(data + 0, &twentytwo, 1); 279 | SendPacketRaw(4, data, 56, 0, peer, 1); 280 | free(data); 281 | } 282 | 283 | /*************** sender sutff **************/ 284 | 285 | 286 | int GetMessageTypeFromPacket(ENetPacket* packet) 287 | { 288 | int result; 289 | 290 | if (packet->dataLength > 3u) 291 | { 292 | result = *(packet->data); 293 | } 294 | else 295 | { 296 | cout << "Bad packet length, ignoring message" << endl; 297 | result = 0; 298 | } 299 | return result; 300 | } 301 | 302 | char* GetTextPointerFromPacket(ENetPacket* packet) 303 | { 304 | char zero = 0; 305 | memcpy(packet->data + packet->dataLength - 1, &zero, 1); 306 | return (char*)(packet->data + 4); 307 | } 308 | 309 | struct OnSendToServerStruct 310 | { 311 | string address; 312 | int port; 313 | int userId; 314 | int token; 315 | }; 316 | 317 | struct OnConsoleMessageStruct 318 | { 319 | string message; 320 | }; 321 | 322 | struct OnPlayPositionedStruct 323 | { 324 | string sound; 325 | }; 326 | 327 | struct OnSetFreezeStateStruct 328 | { 329 | int state; 330 | }; 331 | 332 | struct OnRemoveStruct 333 | { 334 | string data; 335 | }; 336 | 337 | struct OnSpawnStruct 338 | { 339 | string data; 340 | }; 341 | 342 | struct OnActionStruct 343 | { 344 | string data; 345 | }; 346 | 347 | struct SetHasGrowIDStruct 348 | { 349 | int state; 350 | string name; 351 | string password; 352 | }; 353 | 354 | struct SetHasAccountSecuredStruct 355 | { 356 | int state; 357 | }; 358 | 359 | struct OnTalkBubbleStruct 360 | { 361 | int netID; 362 | string bubbleText; 363 | int type; 364 | }; 365 | 366 | struct SetRespawnPosStruct 367 | { 368 | int respawnPos; 369 | }; 370 | 371 | struct OnEmoticonDataChangedStruct 372 | { 373 | int val1; 374 | string emoticons; 375 | }; 376 | 377 | struct OnSetPosStruct 378 | { 379 | float x; 380 | float y; 381 | }; 382 | 383 | struct OnAddNotificationStruct 384 | { 385 | string image; 386 | string message; 387 | string audio; 388 | int val1; 389 | }; 390 | 391 | //SerializeFromMem(GetExtendedDataPointerFromTankPacket(structPointer), *(int*)(structPointer + 52), 0, *(int*)(structPointer + 4)); 392 | void SerializeFromMem(byte *pSrc, int bufferSize, int *pBytesReadOut, int netId) 393 | { 394 | string action = ""; 395 | BYTE* dataStruct = NULL; 396 | byte* startPtr = pSrc; 397 | byte *pStartPos = pSrc; 398 | byte count = pSrc[0]; pSrc++; 399 | bool isNetIdHandled = false; 400 | cout << "Buffer size " << bufferSize << "NetID: " << netId << endl; 401 | cout << std::to_string(count) + "asdf" << endl; 402 | for (int i = 0; i < 10; i++) cout << (int)*(pSrc + i) << endl; 403 | for (int i = 0; i < count; i++) 404 | { 405 | byte index = pSrc[0]; pSrc++; 406 | byte type = pSrc[0]; pSrc++; 407 | cout << "Index " << i << " with type of " << std::to_string(type) << endl; 408 | switch (type) 409 | { 410 | case 2: 411 | { 412 | int strlen; 413 | memcpy(&strlen, pSrc, 4); pSrc += 4; 414 | 415 | string v; 416 | v.resize(strlen); 417 | memcpy(&v[0], pSrc, strlen); pSrc += strlen; 418 | if (index == 0) 419 | { 420 | action = v; 421 | if (action == "OnSendToServer") 422 | { 423 | dataStruct = (BYTE*)new OnSendToServerStruct; 424 | } 425 | else if (action == "OnConsoleMessage") 426 | { 427 | dataStruct = (BYTE*)new OnConsoleMessageStruct; 428 | } 429 | else if (action == "OnPlayPositioned") 430 | { 431 | dataStruct = (BYTE*)new OnPlayPositionedStruct; 432 | } 433 | else if (action == "OnSetFreezeState") 434 | { 435 | dataStruct = (BYTE*)new OnSetFreezeStateStruct; 436 | } 437 | else if (action == "OnRemove") 438 | { 439 | dataStruct = (BYTE*)new OnRemoveStruct; 440 | } 441 | else if (action == "OnSpawn") 442 | { 443 | dataStruct = (BYTE*)new OnSpawnStruct; 444 | } 445 | else if (action == "OnAction") 446 | { 447 | dataStruct = (BYTE*)new OnActionStruct; 448 | } 449 | else if (action == "SetHasGrowID") 450 | { 451 | dataStruct = (BYTE*)new SetHasGrowIDStruct; 452 | } 453 | else if (action == "SetHasAccountSecured") 454 | { 455 | dataStruct = (BYTE*)new SetHasAccountSecuredStruct; 456 | } 457 | else if (action == "OnTalkBubble") 458 | { 459 | dataStruct = (BYTE*)new OnTalkBubbleStruct; 460 | } 461 | else if (action == "SetRespawnPos") 462 | { 463 | dataStruct = (BYTE*)new SetRespawnPosStruct; 464 | } 465 | else if (action == "OnEmoticonDataChanged") 466 | { 467 | dataStruct = (BYTE*)new OnEmoticonDataChangedStruct; 468 | } 469 | else if (action == "OnSetPos") 470 | { 471 | dataStruct = (BYTE*)new OnSetPosStruct; 472 | } 473 | else if (action == "OnAddNotification") 474 | { 475 | dataStruct = (BYTE*)new OnAddNotificationStruct; 476 | } /*else*/ { 477 | dbgPrint("String found at " + std::to_string((int)index) + ": " + v); 478 | } 479 | } 480 | if (action == "OnSendToServer" && index == 4) 481 | { 482 | v.resize(v.length() - 1); 483 | ((OnSendToServerStruct*)dataStruct)->address = v; 484 | } 485 | else if (action == "OnConsoleMessage" && index == 1) 486 | { 487 | ((OnConsoleMessageStruct*)dataStruct)->message = v; 488 | } 489 | else if (action == "OnPlayPositioned" && index == 1) 490 | { 491 | ((OnPlayPositionedStruct*)dataStruct)->sound = v; 492 | } 493 | else if (action == "OnRemove" && index == 1) 494 | { 495 | ((OnRemoveStruct*)dataStruct)->data = v; 496 | } 497 | else if (action == "OnSpawn" && index == 1) 498 | { 499 | ((OnRemoveStruct*)dataStruct)->data = v; 500 | } 501 | else if (action == "OnAction" && index == 1) 502 | { 503 | ((OnRemoveStruct*)dataStruct)->data = v; 504 | } 505 | else if (action == "SetHasGrowID" && index == 2) 506 | { 507 | ((SetHasGrowIDStruct*)dataStruct)->name = v; 508 | } 509 | else if (action == "SetHasAccountSecured" && index == 3) 510 | { 511 | ((SetHasGrowIDStruct*)dataStruct)->password = v; 512 | } 513 | else if (action == "OnTalkBubble" && index == 2) 514 | { 515 | ((OnTalkBubbleStruct*)dataStruct)->bubbleText = v; 516 | } 517 | else if (action == "OnEmoticonDataChanged" && index == 2) 518 | { 519 | ((OnEmoticonDataChangedStruct*)dataStruct)->emoticons = v; 520 | } 521 | else if (action == "OnAddNotification" && index == 1) 522 | { 523 | ((OnAddNotificationStruct*)dataStruct)->image = v; 524 | } 525 | else if (action == "OnAddNotification" && index == 2) 526 | { 527 | ((OnAddNotificationStruct*)dataStruct)->message = v; 528 | } 529 | else if (action == "OnAddNotification" && index == 3) 530 | { 531 | ((OnAddNotificationStruct*)dataStruct)->audio = v; 532 | } 533 | else if (index != 0) 534 | { 535 | dbgPrint("String found at " + std::to_string((int)index) + ": " + v); 536 | } 537 | break; 538 | } 539 | 540 | case 5: 541 | { 542 | int v; 543 | memcpy(&v, pSrc, sizeof(int)); 544 | pSrc += sizeof(int); 545 | if (action == "OnSetFreezeState" && index == 1) 546 | { 547 | ((OnSetFreezeStateStruct*)dataStruct)->state = v; 548 | } 549 | else if (action == "SetHasGrowID" && index == 1) 550 | { 551 | ((SetHasGrowIDStruct*)dataStruct)->state = v; 552 | } 553 | else if (action == "SetHasAccountSecured" && index == 1) 554 | { 555 | ((SetHasAccountSecuredStruct*)dataStruct)->state = v; 556 | } 557 | else if (action == "OnTalkBubble" && index == 1) 558 | { 559 | ((OnTalkBubbleStruct*)dataStruct)->netID = v; 560 | } 561 | else if (action == "OnTalkBubble" && index == 3) 562 | { 563 | ((OnTalkBubbleStruct*)dataStruct)->type = v; 564 | } 565 | else if (action == "SetRespawnPos" && index == 1) 566 | { 567 | ((SetRespawnPosStruct*)dataStruct)->respawnPos = v; 568 | } 569 | else if (action == "OnAddNotification" && index == 4) 570 | { 571 | ((OnAddNotificationStruct*)dataStruct)->val1 = v; 572 | } 573 | else { 574 | dbgPrint("Intx found at " + std::to_string((int)index) + ": " + std::to_string(v)); 575 | } 576 | break; 577 | } 578 | case 9: 579 | { 580 | int v; 581 | memcpy(&v, pSrc, sizeof(int)); 582 | pSrc += sizeof(int); 583 | if (action == "OnSendToServer" && index == 1) 584 | { 585 | ((OnSendToServerStruct*)dataStruct)->port = v; 586 | } 587 | else if (action == "OnSendToServer" && index == 2) 588 | { 589 | ((OnSendToServerStruct*)dataStruct)->token = v; 590 | } 591 | else if (action == "OnSendToServer" && index == 3) 592 | { 593 | ((OnSendToServerStruct*)dataStruct)->userId = v; 594 | } 595 | else if (action == "OnEmoticonDataChanged" && index == 1) 596 | { 597 | ((OnEmoticonDataChangedStruct*)dataStruct)->val1 = v; 598 | } 599 | else { 600 | dbgPrint("Int found at " + std::to_string((int)index) + ": " + std::to_string(v)); 601 | } 602 | break; 603 | } 604 | 605 | case 1: 606 | { 607 | float v; 608 | memcpy(&v, pSrc, sizeof(float)); 609 | pSrc += sizeof(float); 610 | dbgPrint("Float found at " + std::to_string((int)index) + ": " + std::to_string(v)); 611 | 612 | break; 613 | } 614 | 615 | case 3: 616 | { 617 | /*CL_Vec2f v; 618 | memcpy(&v, pSrc, sizeof(CL_Vec2f)); 619 | pSrc += sizeof(CL_Vec2f); 620 | m_variant[index].Set(v);*/ 621 | //cout << bufferSize - (pSrc - startPtr); 622 | 623 | float v1; 624 | memcpy(&v1, pSrc, sizeof(float)); 625 | pSrc += sizeof(float); 626 | float v2; 627 | memcpy(&v2, pSrc, sizeof(float)); 628 | pSrc += sizeof(float); 629 | 630 | if (action == "OnSetPos" && index == 1) 631 | { 632 | ((OnSetPosStruct*)dataStruct)->x = v1; 633 | ((OnSetPosStruct*)dataStruct)->y = v2; 634 | } 635 | else { 636 | dbgPrint("Vector found at " + std::to_string((int)index) + ": " + std::to_string(v1) + "x" + std::to_string(v2)); 637 | } 638 | break; 639 | 640 | } 641 | 642 | case 4: 643 | { 644 | /*CL_Vec3f v; 645 | memcpy(&v, pSrc, sizeof(CL_Vec3f)); 646 | pSrc += sizeof(CL_Vec3f); 647 | m_variant[index].Set(v);*/ 648 | float v1; 649 | memcpy(&v1, pSrc, sizeof(float)); 650 | pSrc += sizeof(float); 651 | float v2; 652 | memcpy(&v2, pSrc, sizeof(float)); 653 | pSrc += sizeof(float); 654 | float v3; 655 | memcpy(&v3, pSrc, sizeof(float)); 656 | pSrc += sizeof(float); 657 | dbgPrint("Vector3 found at " + std::to_string((int)index) + ": " + std::to_string(v1) + "x" + std::to_string(v2) + "x" + std::to_string(v3)); 658 | break; 659 | } 660 | 661 | case 8: 662 | { 663 | /*CL_Rectf v; 664 | memcpy(&v, pSrc, sizeof(CL_Rectf)); 665 | pSrc += sizeof(CL_Rectf); 666 | m_variant[index].Set(v);*/ 667 | dbgPrint("Uh3... Oh..."); 668 | return; 669 | break; 670 | } 671 | 672 | default: 673 | dbgPrint("Unknown var type..."); 674 | return; 675 | //pSrc += 4; 676 | } 677 | } 678 | if (action == "OnSendToServer") 679 | { 680 | OnSendToServer(((OnSendToServerStruct*)dataStruct)->address, ((OnSendToServerStruct*)dataStruct)->port, ((OnSendToServerStruct*)dataStruct)->userId, ((OnSendToServerStruct*)dataStruct)->token); 681 | } 682 | else if (action == "OnConsoleMessage") 683 | { 684 | OnConsoleMessage(((OnConsoleMessageStruct*)dataStruct)->message); 685 | } 686 | else if (action == "OnPlayPositioned") 687 | { 688 | OnPlayPositioned(((OnPlayPositionedStruct*)dataStruct)->sound); 689 | } 690 | else if (action == "OnSetFreezeState") 691 | { 692 | OnSetFreezeState(((OnSetFreezeStateStruct*)dataStruct)->state); 693 | } 694 | else if (action == "OnRemove") 695 | { 696 | OnRemove(((OnRemoveStruct*)dataStruct)->data); 697 | } 698 | else if (action == "OnSpawn") 699 | { 700 | OnSpawn(((OnSpawnStruct*)dataStruct)->data); 701 | } 702 | else if (action == "OnAction") 703 | { 704 | OnAction(((OnActionStruct*)dataStruct)->data); 705 | } 706 | else if (action == "SetHasGrowID") 707 | { 708 | SetHasGrowID(((SetHasGrowIDStruct*)dataStruct)->state, ((SetHasGrowIDStruct*)dataStruct)->name, ((SetHasGrowIDStruct*)dataStruct)->password); 709 | } 710 | else if (action == "SetHasAccountSecured") 711 | { 712 | SetHasAccountSecured(((SetHasAccountSecuredStruct*)dataStruct)->state); 713 | } 714 | else if (action == "OnTalkBubble") 715 | { 716 | OnTalkBubble(((OnTalkBubbleStruct*)dataStruct)->netID, ((OnTalkBubbleStruct*)dataStruct)->bubbleText, ((OnTalkBubbleStruct*)dataStruct)->type); 717 | } 718 | else if (action == "SetRespawnPos") 719 | { 720 | SetRespawnPos(((SetRespawnPosStruct*)dataStruct)->respawnPos); 721 | } 722 | else if (action == "OnEmoticonDataChanged") 723 | { 724 | OnEmoticonDataChanged(((OnEmoticonDataChangedStruct*)dataStruct)->val1, ((OnEmoticonDataChangedStruct*)dataStruct)->emoticons); 725 | } 726 | else if (action == "OnSetPos") 727 | { 728 | OnSetPos(((OnSetPosStruct*)dataStruct)->x, ((OnSetPosStruct*)dataStruct)->y); 729 | } 730 | else if (action == "OnAddNotification") 731 | { 732 | OnAddNotification(((OnAddNotificationStruct*)dataStruct)->image, ((OnAddNotificationStruct*)dataStruct)->message, ((OnAddNotificationStruct*)dataStruct)->audio, ((OnAddNotificationStruct*)dataStruct)->val1); 733 | } 734 | if (dataStruct != NULL) 735 | { 736 | free(dataStruct); 737 | } 738 | if (!isNetIdHandled && netId != -1) 739 | { 740 | dbgPrint("Unhandled NetID " + std::to_string(netId) + " for event " + action); 741 | } 742 | } 743 | 744 | class EntityComponent { 745 | 746 | }; 747 | 748 | BYTE* GetExtendedDataPointerFromTankPacket(BYTE* a1) 749 | { 750 | return (BYTE*)((intptr_t)(a1 + 56)); 751 | } 752 | 753 | /*void AtSetTile(int x, int y, int itemId) 754 | { 755 | cout << "Item " + std::to_string(itemId) + " applied at X:" + std::to_string(x) + " Y: " + std::to_string(y) << endl; 756 | }*/ 757 | 758 | void HandlePacketTileChangeRequest(BYTE* data) 759 | { 760 | switch ((*(int*)data) - 8) 761 | { 762 | case 0: 763 | AtApplyTileDamage(*(int*)(data + 44), *(int*)(data + 48), *(int*)(data + 20)); 764 | break; 765 | case 4: 766 | break; 767 | case 7: 768 | AtApplyLock(*(int*)(data + 44), *(int*)(data + 48), *(int*)(data + 20)); 769 | break; 770 | default: 771 | /*if (*(BYTE *)data != 3) 772 | return; 773 | AtSetTile(*(int*)(data + 44), *(int*)(data + 48), *(int*)(data + 20));*/ 774 | break; 775 | } 776 | } 777 | 778 | struct WorldThingStruct 779 | { 780 | 781 | }; 782 | 783 | struct WorldStruct 784 | { 785 | int XSize; 786 | int YSize; 787 | int tileCount; 788 | string name; 789 | __int16_t* foreground; 790 | __int16_t* background; 791 | WorldThingStruct* specials; 792 | }; 793 | 794 | BYTE* packPlayerMoving(PlayerMoving* dataStruct) 795 | { 796 | BYTE* data = new BYTE[56]; 797 | for (int i = 0; i < 56; i++) 798 | { 799 | data[i] = 0; 800 | } 801 | memcpy(data + 4, &dataStruct->netID, 4); 802 | memcpy(data + 12, &dataStruct->characterState, 4); 803 | memcpy(data + 20, &dataStruct->plantingTree, 4); 804 | memcpy(data + 24, &dataStruct->x, 4); 805 | memcpy(data + 28, &dataStruct->y, 4); 806 | memcpy(data + 32, &dataStruct->XSpeed, 4); 807 | memcpy(data + 36, &dataStruct->YSpeed, 4); 808 | memcpy(data + 44, &dataStruct->punchX, 4); 809 | memcpy(data + 48, &dataStruct->punchY, 4); 810 | return data; 811 | } 812 | 813 | PlayerMoving* unpackPlayerMoving(BYTE* data) 814 | { 815 | PlayerMoving* dataStruct = new PlayerMoving; 816 | memcpy(&dataStruct->netID, data + 4, 4); 817 | memcpy(&dataStruct->characterState, data + 12, 4); 818 | memcpy(&dataStruct->plantingTree, data + 20, 4); 819 | memcpy(&dataStruct->x, data + 24, 4); 820 | memcpy(&dataStruct->y, data + 28, 4); 821 | memcpy(&dataStruct->XSpeed, data + 32, 4); 822 | memcpy(&dataStruct->YSpeed, data + 36, 4); 823 | memcpy(&dataStruct->punchX, data + 44, 4); 824 | memcpy(&dataStruct->punchY, data + 48, 4); 825 | return dataStruct; 826 | } 827 | 828 | WorldStruct* world = NULL; 829 | 830 | //ProcessTankUpdatePacket(0, NULL, tankUpdatePacket); 831 | void ProcessTankUpdatePacket(float someVal, EntityComponent* entityComponent, BYTE* structPointer) 832 | { 833 | cout << "Processing tank packet with id of: " << +(*(char*)structPointer) << " Where first byte is " << std::to_string(structPointer[0]) << endl; 834 | switch (*(char*)structPointer) 835 | { 836 | case 1: 837 | { 838 | try { 839 | SerializeFromMem(GetExtendedDataPointerFromTankPacket(structPointer), *(int*)(structPointer + 52), 0, *(int*)(structPointer + 4)); 840 | 841 | } 842 | catch (int e) 843 | { 844 | 845 | } 846 | break; 847 | } 848 | case 0x15: 849 | { 850 | dbgPrint("Ping reply found!"); 851 | break; 852 | } 853 | case 0x10: 854 | { 855 | BYTE* itemsData = GetExtendedDataPointerFromTankPacket(structPointer); 856 | __int16_t val1 = *(__int16_t*)itemsData; 857 | int itemsCount = *(int*)(itemsData + 2); 858 | break; 859 | } 860 | case 0xF: 861 | { 862 | HandlePacketTileChangeRequest(structPointer); 863 | //cout << *(int*)(structPointer + 4) << endl; 864 | break; 865 | } 866 | case 8: 867 | { 868 | HandlePacketTileChangeRequest(structPointer); 869 | //cout << *(int*)(structPointer + 4) << endl; 870 | break; 871 | } 872 | case 9: 873 | { 874 | BYTE* playerItems = GetExtendedDataPointerFromTankPacket(structPointer); 875 | dbgPrint("Update player inventory.."); 876 | break; 877 | } 878 | 879 | case 5: 880 | { 881 | BYTE* tileData = GetExtendedDataPointerFromTankPacket(structPointer); 882 | dbgPrint("Update of blocks visuals.."); 883 | } 884 | case 0x16: 885 | { 886 | dbgPrint("We need to send packet raw response!"); 887 | // SendPacketRaw(4, &v205, 0x38u, 0, peer, 1); 888 | } 889 | break; 890 | case 0x12: 891 | { 892 | AtAvatarSetIconState(*(int*)(structPointer + 4), *(int*)(structPointer + 44)); 893 | break; 894 | } 895 | case 0x14: 896 | { 897 | // *(int*)(structPointer + 4) <-- NetID 898 | // NetAvatar::SetCharacterState 899 | dbgPrint("Set character state"); 900 | /*cout << std::to_string(*(BYTE*)(structPointer + 1)) << endl; 901 | cout << std::to_string((*(BYTE*)(structPointer + 3)) - 128) << endl; 902 | cout << std::to_string((*(BYTE*)(structPointer + 2)) - 128) << endl; 903 | cout << std::to_string(*(int*)(structPointer + 16)) << endl; 904 | cout << std::to_string(*(int*)(structPointer + 20)) << endl; 905 | cout << std::to_string(*(float*)(structPointer + 24)) << endl; 906 | cout << std::to_string(*(float*)(structPointer + 28)) << endl; 907 | cout << std::to_string(*(float*)(structPointer + 32)) << endl; 908 | cout << std::to_string(*(float*)(structPointer + 36)) << endl; 909 | cout << std::to_string(*(int*)(structPointer + 44)) << endl; 910 | cout << "----------------------------------" << endl;*/ 911 | break; 912 | } 913 | case 0xC: 914 | { 915 | string x = std::to_string(*(int*)(structPointer + 44)); 916 | string y = std::to_string(*(int*)(structPointer + 48)); 917 | cout << "Some tile change at X:" + x + " Y: " + y << endl; 918 | break; 919 | } 920 | case 0xE: 921 | { 922 | dbgPrint("Object change request! TODO!!!!!!"); 923 | /*cout << *(int*)(structPointer + 4) << endl; 924 | cout << *(int*)(structPointer + 20) << endl;*/ 925 | } 926 | case 0x23u: 927 | // MemorySerialize((TileExtra *)((char *)this + 12), v61, v7, a4); 928 | dbgPrint("Got some tile extra information!!! TODO!!!"); 929 | break; 930 | case 3: 931 | dbgPrint("Destroyed/placed tile might be tree also!!! TODO!!!"); 932 | // *(int*)(structPointer + 4) <-- NetID 933 | /*cout << std::to_string(*(int*)(structPointer + 44)) << endl; 934 | cout << std::to_string(*(int*)(structPointer + 48)) << endl; 935 | cout << std::to_string(*(int*)(structPointer + 20)) << endl;*/ // <---- 18 at destroy aka fist 936 | /*HandlePacketTileChangeRequest(structPointer);*/ 937 | break; 938 | case 4: 939 | { 940 | BYTE* worldPtr = GetExtendedDataPointerFromTankPacket(structPointer); // World::LoadFromMem 941 | world = new WorldStruct; 942 | /*for (int i = 0; i < 40000; i++) 943 | { 944 | cout << std::hex << " " << (int)worldPtr[i]; 945 | }*/ 946 | /*ofstream fout; 947 | fout.open("file.bin", ios::binary | ios::out); 948 | 949 | fout.write((const char*)worldPtr-120, 60000); 950 | 951 | fout.close();*/ 952 | worldPtr += 6; 953 | __int16_t strlen = *(__int16_t*)worldPtr; 954 | worldPtr += 2; 955 | world->name = ""; 956 | for (int i = 0; i < strlen; i++) 957 | { 958 | world->name += worldPtr[0]; 959 | worldPtr++; 960 | } 961 | world->XSize = *(int*)worldPtr; 962 | worldPtr += 4; 963 | world->YSize = *(int*)worldPtr; 964 | worldPtr += 4; 965 | world->tileCount = *(int*)worldPtr; 966 | worldPtr += 4; 967 | world->foreground = (__int16_t*)malloc(world->tileCount * sizeof(__int16_t)); 968 | world->background = (__int16_t*)malloc(world->tileCount * sizeof(__int16_t)); 969 | 970 | for (int i = 0; i < world->tileCount; i++) 971 | { 972 | world->foreground[i] = *(__int16_t*)worldPtr; 973 | //if (i<100) 974 | cout << std::hex << *(__int16_t*)worldPtr << " "; 975 | worldPtr += 2; 976 | world->background[i] = *(__int16_t*)worldPtr; 977 | worldPtr += 2; 978 | if (*(BYTE*)worldPtr == 0xae) // locked area 979 | { 980 | cout << "?"; 981 | for (int j = 0; j < 6; j++) 982 | { 983 | cout << std::hex << " " << (int)worldPtr[j]; 984 | } 985 | cout << "?"; 986 | worldPtr += 2; //10 // 0 4 6 8 10 987 | }/* else 988 | if(*(BYTE*)worldPtr == 2) 989 | { 990 | worldPtr+=4; 991 | }*/ else if (world->foreground[i] == 0xca) // small lock 992 | { 993 | worldPtr += 10; 994 | } 995 | else if (world->foreground[i] == 242) // world lock 996 | { 997 | worldPtr += 30; // 12 998 | } 999 | else if (world->foreground[i] == 4802) // crown lock? 1000 | { 1001 | worldPtr += 14; 1002 | } 1003 | else if (world->foreground[i] == 6) // main door 1004 | { 1005 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1006 | } 1007 | else if (world->foreground[i] == 20) // sign 1008 | { 1009 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1010 | for (int j = -10; j < 60; j++) 1011 | { 1012 | cout << "? " << (int)worldPtr[j]; 1013 | } 1014 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4 + 3; 1015 | } 1016 | else if (world->foreground[i] == 28) // danger sign // TODO 1017 | { 1018 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1019 | for (int j = -10; j < 60; j++) 1020 | { 1021 | cout << "? " << (int)worldPtr[j]; 1022 | } 1023 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4 + 3; 1024 | } 1025 | else if (world->foreground[i] == 1682) // gateway to adventure 1026 | { 1027 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1028 | for (int j = -10; j < 60; j++) 1029 | { 1030 | cout << "? " << (int)worldPtr[j]; 1031 | } 1032 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1033 | } 1034 | else if (world->foreground[i] == 858) // screen door 1035 | { 1036 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1037 | for (int j = -10; j < 60; j++) 1038 | { 1039 | cout << "? " << (int)worldPtr[j]; 1040 | } 1041 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1042 | } 1043 | else if (world->foreground[i] == 382) // time space rupture 1044 | { 1045 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1046 | for (int j = -10; j < 60; j++) 1047 | { 1048 | cout << "? " << (int)worldPtr[j]; 1049 | } 1050 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1051 | } 1052 | else if (world->foreground[i] == 546) // blue portal 1053 | { 1054 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1055 | for (int j = -10; j < 60; j++) 1056 | { 1057 | cout << "? " << (int)worldPtr[j]; 1058 | } 1059 | for (int j = 0; j < *(__int16_t*)(worldPtr + 5); j++) 1060 | { 1061 | cout << worldPtr[j + 7]; 1062 | } 1063 | cout << endl; 1064 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1065 | } 1066 | else if (world->foreground[i] == 12) // door 1067 | { 1068 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1069 | for (int j = -10; j < 60; j++) 1070 | { 1071 | cout << "? " << (int)worldPtr[j]; 1072 | } 1073 | for (int j = 0; j < *(__int16_t*)(worldPtr + 5); j++) 1074 | { 1075 | cout << worldPtr[j + 7]; 1076 | } 1077 | cout << endl; 1078 | worldPtr += (*(__int16_t*)(worldPtr + 5)) + 4; 1079 | } 1080 | else if (world->foreground[i] == 3808) // race end flag 1081 | { 1082 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1083 | for (int j = -10; j < 60; j++) 1084 | { 1085 | cout << "? " << (int)worldPtr[j]; 1086 | } 1087 | worldPtr += 1; 1088 | } 1089 | else if (world->foreground[i] == 3804) // challenge timer 1090 | { 1091 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1092 | for (int j = -10; j < 60; j++) 1093 | { 1094 | cout << "? " << (int)worldPtr[j]; 1095 | } 1096 | worldPtr += 1; 1097 | } 1098 | else if (world->foreground[i] == 3806) // challenge start flag 1099 | { 1100 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1101 | for (int j = -10; j < 60; j++) 1102 | { 1103 | cout << "? " << (int)worldPtr[j]; 1104 | } 1105 | worldPtr += 1; 1106 | } 1107 | else if (world->foreground[i] == 658) // bulletin board 1108 | { 1109 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1110 | for (int j = -10; j < 60; j++) 1111 | { 1112 | cout << "? " << (int)worldPtr[j]; 1113 | } 1114 | worldPtr += 7; 1115 | } 1116 | else if (world->foreground[i] == 1684) // path marker 1117 | { 1118 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1119 | for (int j = -10; j < 60; j++) 1120 | { 1121 | cout << "? " << (int)worldPtr[j]; 1122 | } 1123 | worldPtr += 7; 1124 | } 1125 | else if (world->foreground[i] == 3760) // data bedrock 1126 | { 1127 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1128 | for (int j = -10; j < 60; j++) 1129 | { 1130 | cout << "? " << (int)worldPtr[j]; 1131 | } 1132 | worldPtr += 2; 1133 | } 1134 | else if (world->foreground[i] == 1420) // mannequin 1135 | { 1136 | cout << *(__int16_t*)(worldPtr - 4) << "x" << endl; 1137 | for (int j = -10; j < 60; j++) 1138 | { 1139 | cout << "? " << (int)worldPtr[j]; 1140 | } 1141 | worldPtr += 26; 1142 | } 1143 | else if (world->foreground[i] % 2) { // seeds 1144 | worldPtr += 6; 1145 | 1146 | } 1147 | else if (0 != *(BYTE*)worldPtr) 1148 | { 1149 | cout << std::hex << "!" << (int)(*(BYTE*)worldPtr) << "!"; 1150 | //_getch(); 1151 | } 1152 | worldPtr += 4; 1153 | } 1154 | cout << "World " + std::to_string(world->XSize) + "x" + std::to_string(world->YSize) + " with name " + world->name << endl; 1155 | currentWorld = world->name; 1156 | break; 1157 | } 1158 | case 0: // AvatarPacketReceiver::LerpState 1159 | { 1160 | PlayerMoving* structCahce = unpackPlayerMoving(structPointer); 1161 | AtPlayerMoving(structCahce); 1162 | free(structCahce); 1163 | break; 1164 | } 1165 | default: 1166 | dbgPrint("Unknown tank update packet type " + std::to_string(*(char*)structPointer)); 1167 | break; 1168 | } 1169 | 1170 | } 1171 | 1172 | BYTE* GetStructPointerFromTankPacket(ENetPacket* packet) 1173 | { 1174 | unsigned int packetLenght = packet->dataLength; 1175 | BYTE* result = NULL; 1176 | if (packetLenght >= 0x3C) 1177 | { 1178 | BYTE* packetData = packet->data; 1179 | result = packetData + 4; 1180 | 1181 | if (*(BYTE*)(packetData + 16) & 8) 1182 | { 1183 | cout << "Is zero!" << *(int*)(packetData + 56) << endl; 1184 | if (packetLenght < *(int*)(packetData + 56) + 60) 1185 | { 1186 | cout << "Packet too small for extended packet to be valid" << endl; 1187 | cout << "Sizeof float is 4. TankUpdatePacket size: 56" << endl; 1188 | result = 0; 1189 | } 1190 | } 1191 | else 1192 | { 1193 | int zero = 0; 1194 | memcpy(packetData + 56, &zero, 4); 1195 | } 1196 | } 1197 | return result; 1198 | } 1199 | 1200 | void ProcessPacket(ENetEvent* event, ENetPeer* peer) 1201 | { 1202 | int messageType = GetMessageTypeFromPacket(event->packet); 1203 | //cout << "Packet type is " << messageType << endl; 1204 | //cout << (event->packet->data+4) << endl; 1205 | switch (messageType) { 1206 | case 1: 1207 | onLoginRequested(); 1208 | break; 1209 | default: 1210 | packet_unknown(event->packet); 1211 | break; 1212 | case 3: 1213 | packet_type3(GetTextPointerFromPacket(event->packet)); 1214 | break; 1215 | case 4: 1216 | { 1217 | BYTE* tankUpdatePacket = GetStructPointerFromTankPacket(event->packet); 1218 | if (tankUpdatePacket) 1219 | { 1220 | //cout << std::hex << (char*)(tankUpdatePacket+4) << endl; 1221 | /*v12 = (EntityComponent *)GetGameLogic(); 1222 | GameLogicComponent::ProcessTankUpdatePacket(a1, v12, tankUpdatePacket);*/ 1223 | //cout << "Size: " << event->packet->dataLength << endl; 1224 | ProcessTankUpdatePacket(0, NULL, tankUpdatePacket); 1225 | } 1226 | 1227 | else { 1228 | cout << "Got bad tank packet"; 1229 | } 1230 | /*char buffer[2048]; 1231 | for (int i = 0; i < event->packet->dataLength; i++) 1232 | { 1233 | sprintf(&buffer[2 * i], "%02X", event->packet->data[i]); 1234 | } 1235 | cout << buffer;*/ 1236 | } 1237 | break; 1238 | case 5: 1239 | 1240 | break; 1241 | case 6: 1242 | packet_type6(GetTextPointerFromPacket(event->packet)); 1243 | break; 1244 | } 1245 | } 1246 | 1247 | void eventLoop() 1248 | { 1249 | ENetEvent event; 1250 | while (enet_host_service(client, &event, 0) > 0) 1251 | { 1252 | switch (event.type) 1253 | { 1254 | case ENET_EVENT_TYPE_NONE: 1255 | cout << "No event???" << endl; 1256 | break; 1257 | case ENET_EVENT_TYPE_CONNECT: 1258 | WhenConnected(); 1259 | break; 1260 | case ENET_EVENT_TYPE_DISCONNECT: 1261 | WhenDisconnected(); 1262 | break; 1263 | case ENET_EVENT_TYPE_RECEIVE: 1264 | ProcessPacket(&event, peer); 1265 | enet_packet_destroy(event.packet); 1266 | break; 1267 | default: 1268 | cout << "WTF???" << endl; 1269 | break; 1270 | } 1271 | } 1272 | userLoop(); 1273 | } 1274 | }; 1275 | 1276 | void init() { 1277 | if (enet_initialize() != 0) { 1278 | fprintf(stderr, "An error occurred while initializing ENet.\n"); 1279 | exit(0); 1280 | } 1281 | atexit(enet_deinitialize); 1282 | srand(time(NULL)); 1283 | } 1284 | -------------------------------------------------------------------------------- /enet/callbacks.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.c 3 | @brief ENet callback functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "include/enet.h" 7 | 8 | static ENetCallbacks callbacks = { malloc, free, abort }; 9 | 10 | int 11 | enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits) 12 | { 13 | if (version < ENET_VERSION_CREATE (1, 3, 0)) 14 | return -1; 15 | 16 | if (inits -> malloc != NULL || inits -> free != NULL) 17 | { 18 | if (inits -> malloc == NULL || inits -> free == NULL) 19 | return -1; 20 | 21 | callbacks.malloc = inits -> malloc; 22 | callbacks.free = inits -> free; 23 | } 24 | 25 | if (inits -> no_memory != NULL) 26 | callbacks.no_memory = inits -> no_memory; 27 | 28 | return enet_initialize (); 29 | } 30 | 31 | ENetVersion 32 | enet_linked_version (void) 33 | { 34 | return ENET_VERSION; 35 | } 36 | 37 | void * 38 | enet_malloc (size_t size) 39 | { 40 | void * memory = callbacks.malloc (size); 41 | 42 | if (memory == NULL) 43 | callbacks.no_memory (); 44 | 45 | return memory; 46 | } 47 | 48 | void 49 | enet_free (void * memory) 50 | { 51 | callbacks.free (memory); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /enet/compress.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file compress.c 3 | @brief An adaptive order-2 PPM range coder 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include 7 | #include "include/enet.h" 8 | 9 | typedef struct _ENetSymbol 10 | { 11 | /* binary indexed tree of symbols */ 12 | enet_uint8 value; 13 | enet_uint8 count; 14 | enet_uint16 under; 15 | enet_uint16 left, right; 16 | 17 | /* context defined by this symbol */ 18 | enet_uint16 symbols; 19 | enet_uint16 escapes; 20 | enet_uint16 total; 21 | enet_uint16 parent; 22 | } ENetSymbol; 23 | 24 | /* adaptation constants tuned aggressively for small packet sizes rather than large file compression */ 25 | enum 26 | { 27 | ENET_RANGE_CODER_TOP = 1<<24, 28 | ENET_RANGE_CODER_BOTTOM = 1<<16, 29 | 30 | ENET_CONTEXT_SYMBOL_DELTA = 3, 31 | ENET_CONTEXT_SYMBOL_MINIMUM = 1, 32 | ENET_CONTEXT_ESCAPE_MINIMUM = 1, 33 | 34 | ENET_SUBCONTEXT_ORDER = 2, 35 | ENET_SUBCONTEXT_SYMBOL_DELTA = 2, 36 | ENET_SUBCONTEXT_ESCAPE_DELTA = 5 37 | }; 38 | 39 | /* context exclusion roughly halves compression speed, so disable for now */ 40 | #undef ENET_CONTEXT_EXCLUSION 41 | 42 | typedef struct _ENetRangeCoder 43 | { 44 | /* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */ 45 | ENetSymbol symbols[4096]; 46 | } ENetRangeCoder; 47 | 48 | void * 49 | enet_range_coder_create (void) 50 | { 51 | ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder)); 52 | if (rangeCoder == NULL) 53 | return NULL; 54 | 55 | return rangeCoder; 56 | } 57 | 58 | void 59 | enet_range_coder_destroy (void * context) 60 | { 61 | ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context; 62 | if (rangeCoder == NULL) 63 | return; 64 | 65 | enet_free (rangeCoder); 66 | } 67 | 68 | #define ENET_SYMBOL_CREATE(symbol, value_, count_) \ 69 | { \ 70 | symbol = & rangeCoder -> symbols [nextSymbol ++]; \ 71 | symbol -> value = value_; \ 72 | symbol -> count = count_; \ 73 | symbol -> under = count_; \ 74 | symbol -> left = 0; \ 75 | symbol -> right = 0; \ 76 | symbol -> symbols = 0; \ 77 | symbol -> escapes = 0; \ 78 | symbol -> total = 0; \ 79 | symbol -> parent = 0; \ 80 | } 81 | 82 | #define ENET_CONTEXT_CREATE(context, escapes_, minimum) \ 83 | { \ 84 | ENET_SYMBOL_CREATE (context, 0, 0); \ 85 | (context) -> escapes = escapes_; \ 86 | (context) -> total = escapes_ + 256*minimum; \ 87 | (context) -> symbols = 0; \ 88 | } 89 | 90 | static enet_uint16 91 | enet_symbol_rescale (ENetSymbol * symbol) 92 | { 93 | enet_uint16 total = 0; 94 | for (;;) 95 | { 96 | symbol -> count -= symbol->count >> 1; 97 | symbol -> under = symbol -> count; 98 | if (symbol -> left) 99 | symbol -> under += enet_symbol_rescale (symbol + symbol -> left); 100 | total += symbol -> under; 101 | if (! symbol -> right) break; 102 | symbol += symbol -> right; 103 | } 104 | return total; 105 | } 106 | 107 | #define ENET_CONTEXT_RESCALE(context, minimum) \ 108 | { \ 109 | (context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \ 110 | (context) -> escapes -= (context) -> escapes >> 1; \ 111 | (context) -> total += (context) -> escapes + 256*minimum; \ 112 | } 113 | 114 | #define ENET_RANGE_CODER_OUTPUT(value) \ 115 | { \ 116 | if (outData >= outEnd) \ 117 | return 0; \ 118 | * outData ++ = value; \ 119 | } 120 | 121 | #define ENET_RANGE_CODER_ENCODE(under, count, total) \ 122 | { \ 123 | encodeRange /= (total); \ 124 | encodeLow += (under) * encodeRange; \ 125 | encodeRange *= (count); \ 126 | for (;;) \ 127 | { \ 128 | if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \ 129 | { \ 130 | if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \ 131 | encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \ 132 | } \ 133 | ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \ 134 | encodeRange <<= 8; \ 135 | encodeLow <<= 8; \ 136 | } \ 137 | } 138 | 139 | #define ENET_RANGE_CODER_FLUSH \ 140 | { \ 141 | while (encodeLow) \ 142 | { \ 143 | ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \ 144 | encodeLow <<= 8; \ 145 | } \ 146 | } 147 | 148 | #define ENET_RANGE_CODER_FREE_SYMBOLS \ 149 | { \ 150 | if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \ 151 | { \ 152 | nextSymbol = 0; \ 153 | ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \ 154 | predicted = 0; \ 155 | order = 0; \ 156 | } \ 157 | } 158 | 159 | #define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \ 160 | { \ 161 | under_ = value*minimum; \ 162 | count_ = minimum; \ 163 | if (! (context) -> symbols) \ 164 | { \ 165 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 166 | (context) -> symbols = symbol_ - (context); \ 167 | } \ 168 | else \ 169 | { \ 170 | ENetSymbol * node = (context) + (context) -> symbols; \ 171 | for (;;) \ 172 | { \ 173 | if (value_ < node -> value) \ 174 | { \ 175 | node -> under += update; \ 176 | if (node -> left) { node += node -> left; continue; } \ 177 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 178 | node -> left = symbol_ - node; \ 179 | } \ 180 | else \ 181 | if (value_ > node -> value) \ 182 | { \ 183 | under_ += node -> under; \ 184 | if (node -> right) { node += node -> right; continue; } \ 185 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 186 | node -> right = symbol_ - node; \ 187 | } \ 188 | else \ 189 | { \ 190 | count_ += node -> count; \ 191 | under_ += node -> under - node -> count; \ 192 | node -> under += update; \ 193 | node -> count += update; \ 194 | symbol_ = node; \ 195 | } \ 196 | break; \ 197 | } \ 198 | } \ 199 | } 200 | 201 | #ifdef ENET_CONTEXT_EXCLUSION 202 | static const ENetSymbol emptyContext = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 203 | 204 | #define ENET_CONTEXT_WALK(context, body) \ 205 | { \ 206 | const ENetSymbol * node = (context) + (context) -> symbols; \ 207 | const ENetSymbol * stack [256]; \ 208 | size_t stackSize = 0; \ 209 | while (node -> left) \ 210 | { \ 211 | stack [stackSize ++] = node; \ 212 | node += node -> left; \ 213 | } \ 214 | for (;;) \ 215 | { \ 216 | body; \ 217 | if (node -> right) \ 218 | { \ 219 | node += node -> right; \ 220 | while (node -> left) \ 221 | { \ 222 | stack [stackSize ++] = node; \ 223 | node += node -> left; \ 224 | } \ 225 | } \ 226 | else \ 227 | if (stackSize <= 0) \ 228 | break; \ 229 | else \ 230 | node = stack [-- stackSize]; \ 231 | } \ 232 | } 233 | 234 | #define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \ 235 | ENET_CONTEXT_WALK(context, { \ 236 | if (node -> value != value_) \ 237 | { \ 238 | enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \ 239 | if (node -> value < value_) \ 240 | under -= parentCount; \ 241 | total -= parentCount; \ 242 | } \ 243 | }) 244 | #endif 245 | 246 | size_t 247 | enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit) 248 | { 249 | ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context; 250 | enet_uint8 * outStart = outData, * outEnd = & outData [outLimit]; 251 | const enet_uint8 * inData, * inEnd; 252 | enet_uint32 encodeLow = 0, encodeRange = ~0; 253 | ENetSymbol * root; 254 | enet_uint16 predicted = 0; 255 | size_t order = 0, nextSymbol = 0; 256 | 257 | if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0) 258 | return 0; 259 | 260 | inData = (const enet_uint8 *) inBuffers -> data; 261 | inEnd = & inData [inBuffers -> dataLength]; 262 | inBuffers ++; 263 | inBufferCount --; 264 | 265 | ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); 266 | 267 | for (;;) 268 | { 269 | ENetSymbol * subcontext, * symbol; 270 | #ifdef ENET_CONTEXT_EXCLUSION 271 | const ENetSymbol * childContext = & emptyContext; 272 | #endif 273 | enet_uint8 value; 274 | enet_uint16 count, under, * parent = & predicted, total; 275 | if (inData >= inEnd) 276 | { 277 | if (inBufferCount <= 0) 278 | break; 279 | inData = (const enet_uint8 *) inBuffers -> data; 280 | inEnd = & inData [inBuffers -> dataLength]; 281 | inBuffers ++; 282 | inBufferCount --; 283 | } 284 | value = * inData ++; 285 | 286 | for (subcontext = & rangeCoder -> symbols [predicted]; 287 | subcontext != root; 288 | #ifdef ENET_CONTEXT_EXCLUSION 289 | childContext = subcontext, 290 | #endif 291 | subcontext = & rangeCoder -> symbols [subcontext -> parent]) 292 | { 293 | ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0); 294 | * parent = symbol - rangeCoder -> symbols; 295 | parent = & symbol -> parent; 296 | total = subcontext -> total; 297 | #ifdef ENET_CONTEXT_EXCLUSION 298 | if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA) 299 | ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0); 300 | #endif 301 | if (count > 0) 302 | { 303 | ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, total); 304 | } 305 | else 306 | { 307 | if (subcontext -> escapes > 0 && subcontext -> escapes < total) 308 | ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, total); 309 | subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA; 310 | subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA; 311 | } 312 | subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; 313 | if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100) 314 | ENET_CONTEXT_RESCALE (subcontext, 0); 315 | if (count > 0) goto nextInput; 316 | } 317 | 318 | ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM); 319 | * parent = symbol - rangeCoder -> symbols; 320 | parent = & symbol -> parent; 321 | total = root -> total; 322 | #ifdef ENET_CONTEXT_EXCLUSION 323 | if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA) 324 | ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM); 325 | #endif 326 | ENET_RANGE_CODER_ENCODE (root -> escapes + under, count, total); 327 | root -> total += ENET_CONTEXT_SYMBOL_DELTA; 328 | if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100) 329 | ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM); 330 | 331 | nextInput: 332 | if (order >= ENET_SUBCONTEXT_ORDER) 333 | predicted = rangeCoder -> symbols [predicted].parent; 334 | else 335 | order ++; 336 | ENET_RANGE_CODER_FREE_SYMBOLS; 337 | } 338 | 339 | ENET_RANGE_CODER_FLUSH; 340 | 341 | return (size_t) (outData - outStart); 342 | } 343 | 344 | #define ENET_RANGE_CODER_SEED \ 345 | { \ 346 | if (inData < inEnd) decodeCode |= * inData ++ << 24; \ 347 | if (inData < inEnd) decodeCode |= * inData ++ << 16; \ 348 | if (inData < inEnd) decodeCode |= * inData ++ << 8; \ 349 | if (inData < inEnd) decodeCode |= * inData ++; \ 350 | } 351 | 352 | #define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total))) 353 | 354 | #define ENET_RANGE_CODER_DECODE(under, count, total) \ 355 | { \ 356 | decodeLow += (under) * decodeRange; \ 357 | decodeRange *= (count); \ 358 | for (;;) \ 359 | { \ 360 | if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \ 361 | { \ 362 | if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \ 363 | decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \ 364 | } \ 365 | decodeCode <<= 8; \ 366 | if (inData < inEnd) \ 367 | decodeCode |= * inData ++; \ 368 | decodeRange <<= 8; \ 369 | decodeLow <<= 8; \ 370 | } \ 371 | } 372 | 373 | #define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \ 374 | { \ 375 | under_ = 0; \ 376 | count_ = minimum; \ 377 | if (! (context) -> symbols) \ 378 | { \ 379 | createRoot; \ 380 | } \ 381 | else \ 382 | { \ 383 | ENetSymbol * node = (context) + (context) -> symbols; \ 384 | for (;;) \ 385 | { \ 386 | enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \ 387 | visitNode; \ 388 | if (code >= after) \ 389 | { \ 390 | under_ += node -> under; \ 391 | if (node -> right) { node += node -> right; continue; } \ 392 | createRight; \ 393 | } \ 394 | else \ 395 | if (code < after - before) \ 396 | { \ 397 | node -> under += update; \ 398 | if (node -> left) { node += node -> left; continue; } \ 399 | createLeft; \ 400 | } \ 401 | else \ 402 | { \ 403 | value_ = node -> value; \ 404 | count_ += node -> count; \ 405 | under_ = after - before; \ 406 | node -> under += update; \ 407 | node -> count += update; \ 408 | symbol_ = node; \ 409 | } \ 410 | break; \ 411 | } \ 412 | } \ 413 | } 414 | 415 | #define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \ 416 | ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0) 417 | 418 | #define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \ 419 | ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \ 420 | { \ 421 | value_ = code / minimum; \ 422 | under_ = code - code%minimum; \ 423 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 424 | (context) -> symbols = symbol_ - (context); \ 425 | }, \ 426 | exclude (node -> value, after, before), \ 427 | { \ 428 | value_ = node->value + 1 + (code - after)/minimum; \ 429 | under_ = code - (code - after)%minimum; \ 430 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 431 | node -> right = symbol_ - node; \ 432 | }, \ 433 | { \ 434 | value_ = node->value - 1 - (after - before - code - 1)/minimum; \ 435 | under_ = code - (after - before - code - 1)%minimum; \ 436 | ENET_SYMBOL_CREATE (symbol_, value_, update); \ 437 | node -> left = symbol_ - node; \ 438 | }) \ 439 | 440 | #ifdef ENET_CONTEXT_EXCLUSION 441 | typedef struct _ENetExclude 442 | { 443 | enet_uint8 value; 444 | enet_uint16 under; 445 | } ENetExclude; 446 | 447 | #define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \ 448 | { \ 449 | enet_uint16 under = 0; \ 450 | nextExclude = excludes; \ 451 | ENET_CONTEXT_WALK (context, { \ 452 | under += rangeCoder -> symbols [node -> parent].count + minimum; \ 453 | nextExclude -> value = node -> value; \ 454 | nextExclude -> under = under; \ 455 | nextExclude ++; \ 456 | }); \ 457 | total -= under; \ 458 | } 459 | 460 | #define ENET_CONTEXT_EXCLUDED(value_, after, before) \ 461 | { \ 462 | size_t low = 0, high = nextExclude - excludes; \ 463 | for(;;) \ 464 | { \ 465 | size_t mid = (low + high) >> 1; \ 466 | const ENetExclude * exclude = & excludes [mid]; \ 467 | if (value_ < exclude -> value) \ 468 | { \ 469 | if (low + 1 < high) \ 470 | { \ 471 | high = mid; \ 472 | continue; \ 473 | } \ 474 | if (exclude > excludes) \ 475 | after -= exclude [-1].under; \ 476 | } \ 477 | else \ 478 | { \ 479 | if (value_ > exclude -> value) \ 480 | { \ 481 | if (low + 1 < high) \ 482 | { \ 483 | low = mid; \ 484 | continue; \ 485 | } \ 486 | } \ 487 | else \ 488 | before = 0; \ 489 | after -= exclude -> under; \ 490 | } \ 491 | break; \ 492 | } \ 493 | } 494 | #endif 495 | 496 | #define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before) 497 | 498 | size_t 499 | enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit) 500 | { 501 | ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context; 502 | enet_uint8 * outStart = outData, * outEnd = & outData [outLimit]; 503 | const enet_uint8 * inEnd = & inData [inLimit]; 504 | enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0; 505 | ENetSymbol * root; 506 | enet_uint16 predicted = 0; 507 | size_t order = 0, nextSymbol = 0; 508 | #ifdef ENET_CONTEXT_EXCLUSION 509 | ENetExclude excludes [256]; 510 | ENetExclude * nextExclude = excludes; 511 | #endif 512 | 513 | if (rangeCoder == NULL || inLimit <= 0) 514 | return 0; 515 | 516 | ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); 517 | 518 | ENET_RANGE_CODER_SEED; 519 | 520 | for (;;) 521 | { 522 | ENetSymbol * subcontext, * symbol, * patch; 523 | #ifdef ENET_CONTEXT_EXCLUSION 524 | const ENetSymbol * childContext = & emptyContext; 525 | #endif 526 | enet_uint8 value = 0; 527 | enet_uint16 code, under, count, bottom, * parent = & predicted, total; 528 | 529 | for (subcontext = & rangeCoder -> symbols [predicted]; 530 | subcontext != root; 531 | #ifdef ENET_CONTEXT_EXCLUSION 532 | childContext = subcontext, 533 | #endif 534 | subcontext = & rangeCoder -> symbols [subcontext -> parent]) 535 | { 536 | if (subcontext -> escapes <= 0) 537 | continue; 538 | total = subcontext -> total; 539 | #ifdef ENET_CONTEXT_EXCLUSION 540 | if (childContext -> total > 0) 541 | ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0); 542 | #endif 543 | if (subcontext -> escapes >= total) 544 | continue; 545 | code = ENET_RANGE_CODER_READ (total); 546 | if (code < subcontext -> escapes) 547 | { 548 | ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, total); 549 | continue; 550 | } 551 | code -= subcontext -> escapes; 552 | #ifdef ENET_CONTEXT_EXCLUSION 553 | if (childContext -> total > 0) 554 | { 555 | ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED); 556 | } 557 | else 558 | #endif 559 | { 560 | ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED); 561 | } 562 | bottom = symbol - rangeCoder -> symbols; 563 | ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, total); 564 | subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; 565 | if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100) 566 | ENET_CONTEXT_RESCALE (subcontext, 0); 567 | goto patchContexts; 568 | } 569 | 570 | total = root -> total; 571 | #ifdef ENET_CONTEXT_EXCLUSION 572 | if (childContext -> total > 0) 573 | ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM); 574 | #endif 575 | code = ENET_RANGE_CODER_READ (total); 576 | if (code < root -> escapes) 577 | { 578 | ENET_RANGE_CODER_DECODE (0, root -> escapes, total); 579 | break; 580 | } 581 | code -= root -> escapes; 582 | #ifdef ENET_CONTEXT_EXCLUSION 583 | if (childContext -> total > 0) 584 | { 585 | ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED); 586 | } 587 | else 588 | #endif 589 | { 590 | ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_NOT_EXCLUDED); 591 | } 592 | bottom = symbol - rangeCoder -> symbols; 593 | ENET_RANGE_CODER_DECODE (root -> escapes + under, count, total); 594 | root -> total += ENET_CONTEXT_SYMBOL_DELTA; 595 | if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100) 596 | ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM); 597 | 598 | patchContexts: 599 | for (patch = & rangeCoder -> symbols [predicted]; 600 | patch != subcontext; 601 | patch = & rangeCoder -> symbols [patch -> parent]) 602 | { 603 | ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0); 604 | * parent = symbol - rangeCoder -> symbols; 605 | parent = & symbol -> parent; 606 | if (count <= 0) 607 | { 608 | patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA; 609 | patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA; 610 | } 611 | patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; 612 | if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100) 613 | ENET_CONTEXT_RESCALE (patch, 0); 614 | } 615 | * parent = bottom; 616 | 617 | ENET_RANGE_CODER_OUTPUT (value); 618 | 619 | if (order >= ENET_SUBCONTEXT_ORDER) 620 | predicted = rangeCoder -> symbols [predicted].parent; 621 | else 622 | order ++; 623 | ENET_RANGE_CODER_FREE_SYMBOLS; 624 | } 625 | 626 | return (size_t) (outData - outStart); 627 | } 628 | 629 | /** @defgroup host ENet host functions 630 | @{ 631 | */ 632 | 633 | /** Sets the packet compressor the host should use to the default range coder. 634 | @param host host to enable the range coder for 635 | @returns 0 on success, < 0 on failure 636 | */ 637 | int 638 | enet_host_compress_with_range_coder (ENetHost * host) 639 | { 640 | ENetCompressor compressor; 641 | memset (& compressor, 0, sizeof (compressor)); 642 | compressor.context = enet_range_coder_create(); 643 | if (compressor.context == NULL) 644 | return -1; 645 | compressor.compress = enet_range_coder_compress; 646 | compressor.decompress = enet_range_coder_decompress; 647 | compressor.destroy = enet_range_coder_destroy; 648 | enet_host_compress (host, & compressor); 649 | return 0; 650 | } 651 | 652 | /** @} */ 653 | 654 | 655 | -------------------------------------------------------------------------------- /enet/host.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file host.c 3 | @brief ENet host management functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include 7 | #include "include/enet.h" 8 | 9 | /** @defgroup host ENet host functions 10 | @{ 11 | */ 12 | 13 | /** Creates a host for communicating to peers. 14 | 15 | @param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host. 16 | @param peerCount the maximum number of peers that should be allocated for the host. 17 | @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT 18 | @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. 19 | @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. 20 | 21 | @returns the host on success and NULL on failure 22 | 23 | @remarks ENet will strategically drop packets on specific sides of a connection between hosts 24 | to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine 25 | the window size of a connection which limits the amount of reliable packets that may be in transit 26 | at any given time. 27 | */ 28 | ENetHost * 29 | enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) 30 | { 31 | ENetHost * host; 32 | ENetPeer * currentPeer; 33 | 34 | if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) 35 | return NULL; 36 | 37 | host = (ENetHost *) enet_malloc (sizeof (ENetHost)); 38 | if (host == NULL) 39 | return NULL; 40 | memset (host, 0, sizeof (ENetHost)); 41 | 42 | host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); 43 | if (host -> peers == NULL) 44 | { 45 | enet_free (host); 46 | 47 | return NULL; 48 | } 49 | memset (host -> peers, 0, peerCount * sizeof (ENetPeer)); 50 | 51 | host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM); 52 | if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0)) 53 | { 54 | if (host -> socket != ENET_SOCKET_NULL) 55 | enet_socket_destroy (host -> socket); 56 | 57 | enet_free (host -> peers); 58 | enet_free (host); 59 | 60 | return NULL; 61 | } 62 | 63 | enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1); 64 | enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1); 65 | enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); 66 | enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); 67 | 68 | if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0) 69 | host -> address = * address; 70 | 71 | if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) 72 | channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; 73 | else 74 | if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) 75 | channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; 76 | 77 | host -> randomSeed = (enet_uint32) (size_t) host; 78 | host -> randomSeed += enet_host_random_seed (); 79 | host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16); 80 | host -> channelLimit = channelLimit; 81 | host -> incomingBandwidth = incomingBandwidth; 82 | host -> outgoingBandwidth = outgoingBandwidth; 83 | host -> bandwidthThrottleEpoch = 0; 84 | host -> recalculateBandwidthLimits = 0; 85 | host -> mtu = ENET_HOST_DEFAULT_MTU; 86 | host -> peerCount = peerCount; 87 | host -> commandCount = 0; 88 | host -> bufferCount = 0; 89 | host -> checksum = NULL; 90 | host -> receivedAddress.host = ENET_HOST_ANY; 91 | host -> receivedAddress.port = 0; 92 | host -> receivedData = NULL; 93 | host -> receivedDataLength = 0; 94 | 95 | host -> totalSentData = 0; 96 | host -> totalSentPackets = 0; 97 | host -> totalReceivedData = 0; 98 | host -> totalReceivedPackets = 0; 99 | 100 | host -> connectedPeers = 0; 101 | host -> bandwidthLimitedPeers = 0; 102 | host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; 103 | host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; 104 | host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; 105 | 106 | host -> compressor.context = NULL; 107 | host -> compressor.compress = NULL; 108 | host -> compressor.decompress = NULL; 109 | host -> compressor.destroy = NULL; 110 | 111 | host -> intercept = NULL; 112 | 113 | enet_list_clear (& host -> dispatchQueue); 114 | 115 | for (currentPeer = host -> peers; 116 | currentPeer < & host -> peers [host -> peerCount]; 117 | ++ currentPeer) 118 | { 119 | currentPeer -> host = host; 120 | currentPeer -> incomingPeerID = currentPeer - host -> peers; 121 | currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF; 122 | currentPeer -> data = NULL; 123 | 124 | enet_list_clear (& currentPeer -> acknowledgements); 125 | enet_list_clear (& currentPeer -> sentReliableCommands); 126 | enet_list_clear (& currentPeer -> sentUnreliableCommands); 127 | enet_list_clear (& currentPeer -> outgoingReliableCommands); 128 | enet_list_clear (& currentPeer -> outgoingUnreliableCommands); 129 | enet_list_clear (& currentPeer -> dispatchedCommands); 130 | 131 | enet_peer_reset (currentPeer); 132 | } 133 | 134 | return host; 135 | } 136 | 137 | /** Destroys the host and all resources associated with it. 138 | @param host pointer to the host to destroy 139 | */ 140 | void 141 | enet_host_destroy (ENetHost * host) 142 | { 143 | ENetPeer * currentPeer; 144 | 145 | if (host == NULL) 146 | return; 147 | 148 | enet_socket_destroy (host -> socket); 149 | 150 | for (currentPeer = host -> peers; 151 | currentPeer < & host -> peers [host -> peerCount]; 152 | ++ currentPeer) 153 | { 154 | enet_peer_reset (currentPeer); 155 | } 156 | 157 | if (host -> compressor.context != NULL && host -> compressor.destroy) 158 | (* host -> compressor.destroy) (host -> compressor.context); 159 | 160 | enet_free (host -> peers); 161 | enet_free (host); 162 | } 163 | 164 | /** Initiates a connection to a foreign host. 165 | @param host host seeking the connection 166 | @param address destination for the connection 167 | @param channelCount number of channels to allocate 168 | @param data user data supplied to the receiving host 169 | @returns a peer representing the foreign host on success, NULL on failure 170 | @remarks The peer returned will have not completed the connection until enet_host_service() 171 | notifies of an ENET_EVENT_TYPE_CONNECT event for the peer. 172 | */ 173 | ENetPeer * 174 | enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data) 175 | { 176 | ENetPeer * currentPeer; 177 | ENetChannel * channel; 178 | ENetProtocol command; 179 | 180 | if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) 181 | channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; 182 | else 183 | if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) 184 | channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; 185 | 186 | for (currentPeer = host -> peers; 187 | currentPeer < & host -> peers [host -> peerCount]; 188 | ++ currentPeer) 189 | { 190 | if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) 191 | break; 192 | } 193 | 194 | if (currentPeer >= & host -> peers [host -> peerCount]) 195 | return NULL; 196 | 197 | currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); 198 | if (currentPeer -> channels == NULL) 199 | return NULL; 200 | currentPeer -> channelCount = channelCount; 201 | currentPeer -> state = ENET_PEER_STATE_CONNECTING; 202 | currentPeer -> address = * address; 203 | currentPeer -> connectID = ++ host -> randomSeed; 204 | 205 | if (host -> outgoingBandwidth == 0) 206 | currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; 207 | else 208 | currentPeer -> windowSize = (host -> outgoingBandwidth / 209 | ENET_PEER_WINDOW_SIZE_SCALE) * 210 | ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; 211 | 212 | if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) 213 | currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; 214 | else 215 | if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) 216 | currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; 217 | 218 | for (channel = currentPeer -> channels; 219 | channel < & currentPeer -> channels [channelCount]; 220 | ++ channel) 221 | { 222 | channel -> outgoingReliableSequenceNumber = 0; 223 | channel -> outgoingUnreliableSequenceNumber = 0; 224 | channel -> incomingReliableSequenceNumber = 0; 225 | channel -> incomingUnreliableSequenceNumber = 0; 226 | 227 | enet_list_clear (& channel -> incomingReliableCommands); 228 | enet_list_clear (& channel -> incomingUnreliableCommands); 229 | 230 | channel -> usedReliableWindows = 0; 231 | memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows)); 232 | } 233 | 234 | command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 235 | command.header.channelID = 0xFF; 236 | command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); 237 | command.connect.incomingSessionID = currentPeer -> incomingSessionID; 238 | command.connect.outgoingSessionID = currentPeer -> outgoingSessionID; 239 | command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu); 240 | command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize); 241 | command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount); 242 | command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); 243 | command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); 244 | command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); 245 | command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); 246 | command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); 247 | command.connect.connectID = currentPeer -> connectID; 248 | command.connect.data = ENET_HOST_TO_NET_32 (data); 249 | 250 | enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0); 251 | 252 | return currentPeer; 253 | } 254 | 255 | /** Queues a packet to be sent to all peers associated with the host. 256 | @param host host on which to broadcast the packet 257 | @param channelID channel on which to broadcast 258 | @param packet packet to broadcast 259 | */ 260 | void 261 | enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet) 262 | { 263 | ENetPeer * currentPeer; 264 | 265 | for (currentPeer = host -> peers; 266 | currentPeer < & host -> peers [host -> peerCount]; 267 | ++ currentPeer) 268 | { 269 | if (currentPeer -> state != ENET_PEER_STATE_CONNECTED) 270 | continue; 271 | 272 | enet_peer_send (currentPeer, channelID, packet); 273 | } 274 | 275 | if (packet -> referenceCount == 0) 276 | enet_packet_destroy (packet); 277 | } 278 | 279 | /** Sets the packet compressor the host should use to compress and decompress packets. 280 | @param host host to enable or disable compression for 281 | @param compressor callbacks for for the packet compressor; if NULL, then compression is disabled 282 | */ 283 | void 284 | enet_host_compress (ENetHost * host, const ENetCompressor * compressor) 285 | { 286 | if (host -> compressor.context != NULL && host -> compressor.destroy) 287 | (* host -> compressor.destroy) (host -> compressor.context); 288 | 289 | if (compressor) 290 | host -> compressor = * compressor; 291 | else 292 | host -> compressor.context = NULL; 293 | } 294 | 295 | /** Limits the maximum allowed channels of future incoming connections. 296 | @param host host to limit 297 | @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT 298 | */ 299 | void 300 | enet_host_channel_limit (ENetHost * host, size_t channelLimit) 301 | { 302 | if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) 303 | channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; 304 | else 305 | if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) 306 | channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; 307 | 308 | host -> channelLimit = channelLimit; 309 | } 310 | 311 | 312 | /** Adjusts the bandwidth limits of a host. 313 | @param host host to adjust 314 | @param incomingBandwidth new incoming bandwidth 315 | @param outgoingBandwidth new outgoing bandwidth 316 | @remarks the incoming and outgoing bandwidth parameters are identical in function to those 317 | specified in enet_host_create(). 318 | */ 319 | void 320 | enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) 321 | { 322 | host -> incomingBandwidth = incomingBandwidth; 323 | host -> outgoingBandwidth = outgoingBandwidth; 324 | host -> recalculateBandwidthLimits = 1; 325 | } 326 | 327 | void 328 | enet_host_bandwidth_throttle (ENetHost * host) 329 | { 330 | enet_uint32 timeCurrent = enet_time_get (), 331 | elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch, 332 | peersRemaining = (enet_uint32) host -> connectedPeers, 333 | dataTotal = ~0, 334 | bandwidth = ~0, 335 | throttle = 0, 336 | bandwidthLimit = 0; 337 | int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0; 338 | ENetPeer * peer; 339 | ENetProtocol command; 340 | 341 | if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) 342 | return; 343 | 344 | host -> bandwidthThrottleEpoch = timeCurrent; 345 | 346 | if (peersRemaining == 0) 347 | return; 348 | 349 | if (host -> outgoingBandwidth != 0) 350 | { 351 | dataTotal = 0; 352 | bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; 353 | 354 | for (peer = host -> peers; 355 | peer < & host -> peers [host -> peerCount]; 356 | ++ peer) 357 | { 358 | if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) 359 | continue; 360 | 361 | dataTotal += peer -> outgoingDataTotal; 362 | } 363 | } 364 | 365 | while (peersRemaining > 0 && needsAdjustment != 0) 366 | { 367 | needsAdjustment = 0; 368 | 369 | if (dataTotal <= bandwidth) 370 | throttle = ENET_PEER_PACKET_THROTTLE_SCALE; 371 | else 372 | throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; 373 | 374 | for (peer = host -> peers; 375 | peer < & host -> peers [host -> peerCount]; 376 | ++ peer) 377 | { 378 | enet_uint32 peerBandwidth; 379 | 380 | if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || 381 | peer -> incomingBandwidth == 0 || 382 | peer -> outgoingBandwidthThrottleEpoch == timeCurrent) 383 | continue; 384 | 385 | peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000; 386 | if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth) 387 | continue; 388 | 389 | peer -> packetThrottleLimit = (peerBandwidth * 390 | ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal; 391 | 392 | if (peer -> packetThrottleLimit == 0) 393 | peer -> packetThrottleLimit = 1; 394 | 395 | if (peer -> packetThrottle > peer -> packetThrottleLimit) 396 | peer -> packetThrottle = peer -> packetThrottleLimit; 397 | 398 | peer -> outgoingBandwidthThrottleEpoch = timeCurrent; 399 | 400 | peer -> incomingDataTotal = 0; 401 | peer -> outgoingDataTotal = 0; 402 | 403 | needsAdjustment = 1; 404 | -- peersRemaining; 405 | bandwidth -= peerBandwidth; 406 | dataTotal -= peerBandwidth; 407 | } 408 | } 409 | 410 | if (peersRemaining > 0) 411 | { 412 | if (dataTotal <= bandwidth) 413 | throttle = ENET_PEER_PACKET_THROTTLE_SCALE; 414 | else 415 | throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; 416 | 417 | for (peer = host -> peers; 418 | peer < & host -> peers [host -> peerCount]; 419 | ++ peer) 420 | { 421 | if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || 422 | peer -> outgoingBandwidthThrottleEpoch == timeCurrent) 423 | continue; 424 | 425 | peer -> packetThrottleLimit = throttle; 426 | 427 | if (peer -> packetThrottle > peer -> packetThrottleLimit) 428 | peer -> packetThrottle = peer -> packetThrottleLimit; 429 | 430 | peer -> incomingDataTotal = 0; 431 | peer -> outgoingDataTotal = 0; 432 | } 433 | } 434 | 435 | if (host -> recalculateBandwidthLimits) 436 | { 437 | host -> recalculateBandwidthLimits = 0; 438 | 439 | peersRemaining = (enet_uint32) host -> connectedPeers; 440 | bandwidth = host -> incomingBandwidth; 441 | needsAdjustment = 1; 442 | 443 | if (bandwidth == 0) 444 | bandwidthLimit = 0; 445 | else 446 | while (peersRemaining > 0 && needsAdjustment != 0) 447 | { 448 | needsAdjustment = 0; 449 | bandwidthLimit = bandwidth / peersRemaining; 450 | 451 | for (peer = host -> peers; 452 | peer < & host -> peers [host -> peerCount]; 453 | ++ peer) 454 | { 455 | if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || 456 | peer -> incomingBandwidthThrottleEpoch == timeCurrent) 457 | continue; 458 | 459 | if (peer -> outgoingBandwidth > 0 && 460 | peer -> outgoingBandwidth >= bandwidthLimit) 461 | continue; 462 | 463 | peer -> incomingBandwidthThrottleEpoch = timeCurrent; 464 | 465 | needsAdjustment = 1; 466 | -- peersRemaining; 467 | bandwidth -= peer -> outgoingBandwidth; 468 | } 469 | } 470 | 471 | for (peer = host -> peers; 472 | peer < & host -> peers [host -> peerCount]; 473 | ++ peer) 474 | { 475 | if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) 476 | continue; 477 | 478 | command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 479 | command.header.channelID = 0xFF; 480 | command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); 481 | 482 | if (peer -> incomingBandwidthThrottleEpoch == timeCurrent) 483 | command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth); 484 | else 485 | command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit); 486 | 487 | enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); 488 | } 489 | } 490 | } 491 | 492 | /** @} */ 493 | -------------------------------------------------------------------------------- /enet/include/callbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.h 3 | @brief ENet callbacks 4 | */ 5 | #ifndef __ENET_CALLBACKS_H__ 6 | #define __ENET_CALLBACKS_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetCallbacks 11 | { 12 | void * (ENET_CALLBACK * malloc) (size_t size); 13 | void (ENET_CALLBACK * free) (void * memory); 14 | void (ENET_CALLBACK * no_memory) (void); 15 | } ENetCallbacks; 16 | 17 | /** @defgroup callbacks ENet internal callbacks 18 | @{ 19 | @ingroup private 20 | */ 21 | extern void * enet_malloc (size_t); 22 | extern void enet_free (void *); 23 | 24 | /** @} */ 25 | 26 | #endif /* __ENET_CALLBACKS_H__ */ 27 | 28 | -------------------------------------------------------------------------------- /enet/include/enet.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file enet.h 3 | @brief ENet public header file 4 | */ 5 | #ifndef __ENET_ENET_H__ 6 | #define __ENET_ENET_H__ 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | #include 14 | 15 | #ifdef _WIN32 16 | #include "win32.h" 17 | #else 18 | #include "unix.h" 19 | #endif 20 | 21 | #include "types.h" 22 | #include "protocol.h" 23 | #include "list.h" 24 | #include "callbacks.h" 25 | 26 | #define ENET_VERSION_MAJOR 1 27 | #define ENET_VERSION_MINOR 3 28 | #define ENET_VERSION_PATCH 14 29 | #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) 30 | #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) 31 | #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) 32 | #define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) 33 | #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) 34 | 35 | typedef enet_uint32 ENetVersion; 36 | 37 | struct _ENetHost; 38 | struct _ENetEvent; 39 | struct _ENetPacket; 40 | 41 | typedef enum _ENetSocketType 42 | { 43 | ENET_SOCKET_TYPE_STREAM = 1, 44 | ENET_SOCKET_TYPE_DATAGRAM = 2 45 | } ENetSocketType; 46 | 47 | typedef enum _ENetSocketWait 48 | { 49 | ENET_SOCKET_WAIT_NONE = 0, 50 | ENET_SOCKET_WAIT_SEND = (1 << 0), 51 | ENET_SOCKET_WAIT_RECEIVE = (1 << 1), 52 | ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) 53 | } ENetSocketWait; 54 | 55 | typedef enum _ENetSocketOption 56 | { 57 | ENET_SOCKOPT_NONBLOCK = 1, 58 | ENET_SOCKOPT_BROADCAST = 2, 59 | ENET_SOCKOPT_RCVBUF = 3, 60 | ENET_SOCKOPT_SNDBUF = 4, 61 | ENET_SOCKOPT_REUSEADDR = 5, 62 | ENET_SOCKOPT_RCVTIMEO = 6, 63 | ENET_SOCKOPT_SNDTIMEO = 7, 64 | ENET_SOCKOPT_ERROR = 8, 65 | ENET_SOCKOPT_NODELAY = 9 66 | } ENetSocketOption; 67 | 68 | typedef enum _ENetSocketShutdown 69 | { 70 | ENET_SOCKET_SHUTDOWN_READ = 0, 71 | ENET_SOCKET_SHUTDOWN_WRITE = 1, 72 | ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 73 | } ENetSocketShutdown; 74 | 75 | #define ENET_HOST_ANY 0 76 | #define ENET_HOST_BROADCAST 0xFFFFFFFFU 77 | #define ENET_PORT_ANY 0 78 | 79 | /** 80 | * Portable internet address structure. 81 | * 82 | * The host must be specified in network byte-order, and the port must be in host 83 | * byte-order. The constant ENET_HOST_ANY may be used to specify the default 84 | * server host. The constant ENET_HOST_BROADCAST may be used to specify the 85 | * broadcast address (255.255.255.255). This makes sense for enet_host_connect, 86 | * but not for enet_host_create. Once a server responds to a broadcast, the 87 | * address is updated from ENET_HOST_BROADCAST to the server's actual IP address. 88 | */ 89 | typedef struct _ENetAddress { 90 | enet_uint32 host; 91 | enet_uint16 port; 92 | } ENetAddress; 93 | 94 | /** 95 | * Packet flag bit constants. 96 | * 97 | * The host must be specified in network byte-order, and the port must be in 98 | * host byte-order. The constant ENET_HOST_ANY may be used to specify the 99 | * default server host. 100 | 101 | @sa ENetPacket 102 | */ 103 | typedef enum _ENetPacketFlag 104 | { 105 | /** packet must be received by the target peer and resend attempts should be 106 | * made until the packet is delivered */ 107 | ENET_PACKET_FLAG_RELIABLE = (1 << 0), 108 | /** packet will not be sequenced with other packets 109 | * not supported for reliable packets 110 | */ 111 | ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), 112 | /** packet will not allocate data, and user must supply it instead */ 113 | ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), 114 | /** packet will be fragmented using unreliable (instead of reliable) sends 115 | * if it exceeds the MTU */ 116 | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), 117 | 118 | /** whether the packet has been sent from all queues it has been entered into */ 119 | ENET_PACKET_FLAG_SENT = (1<<8) 120 | } ENetPacketFlag; 121 | 122 | typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); 123 | 124 | /** 125 | * ENet packet structure. 126 | * 127 | * An ENet data packet that may be sent to or received from a peer. The shown 128 | * fields should only be read and never modified. The data field contains the 129 | * allocated data for the packet. The dataLength fields specifies the length 130 | * of the allocated data. The flags field is either 0 (specifying no flags), 131 | * or a bitwise-or of any combination of the following flags: 132 | * 133 | * ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer 134 | * and resend attempts should be made until the packet is delivered 135 | * 136 | * ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets 137 | * (not supported for reliable packets) 138 | * 139 | * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead 140 | * 141 | * ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable 142 | * (instead of reliable) sends if it exceeds the MTU 143 | * 144 | * ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into 145 | @sa ENetPacketFlag 146 | */ 147 | typedef struct _ENetPacket 148 | { 149 | size_t referenceCount; /**< internal use only */ 150 | enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */ 151 | enet_uint8 * data; /**< allocated data for packet */ 152 | size_t dataLength; /**< length of data */ 153 | ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ 154 | void * userData; /**< application private data, may be freely modified */ 155 | } ENetPacket; 156 | 157 | typedef struct _ENetAcknowledgement 158 | { 159 | ENetListNode acknowledgementList; 160 | enet_uint32 sentTime; 161 | ENetProtocol command; 162 | } ENetAcknowledgement; 163 | 164 | typedef struct _ENetOutgoingCommand 165 | { 166 | ENetListNode outgoingCommandList; 167 | enet_uint16 reliableSequenceNumber; 168 | enet_uint16 unreliableSequenceNumber; 169 | enet_uint32 sentTime; 170 | enet_uint32 roundTripTimeout; 171 | enet_uint32 roundTripTimeoutLimit; 172 | enet_uint32 fragmentOffset; 173 | enet_uint16 fragmentLength; 174 | enet_uint16 sendAttempts; 175 | ENetProtocol command; 176 | ENetPacket * packet; 177 | } ENetOutgoingCommand; 178 | 179 | typedef struct _ENetIncomingCommand 180 | { 181 | ENetListNode incomingCommandList; 182 | enet_uint16 reliableSequenceNumber; 183 | enet_uint16 unreliableSequenceNumber; 184 | ENetProtocol command; 185 | enet_uint32 fragmentCount; 186 | enet_uint32 fragmentsRemaining; 187 | enet_uint32 * fragments; 188 | ENetPacket * packet; 189 | } ENetIncomingCommand; 190 | 191 | typedef enum _ENetPeerState 192 | { 193 | ENET_PEER_STATE_DISCONNECTED = 0, 194 | ENET_PEER_STATE_CONNECTING = 1, 195 | ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, 196 | ENET_PEER_STATE_CONNECTION_PENDING = 3, 197 | ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, 198 | ENET_PEER_STATE_CONNECTED = 5, 199 | ENET_PEER_STATE_DISCONNECT_LATER = 6, 200 | ENET_PEER_STATE_DISCONNECTING = 7, 201 | ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, 202 | ENET_PEER_STATE_ZOMBIE = 9 203 | } ENetPeerState; 204 | 205 | #ifndef ENET_BUFFER_MAXIMUM 206 | #define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS) 207 | #endif 208 | 209 | enum 210 | { 211 | ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, 212 | ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, 213 | ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, 214 | ENET_HOST_DEFAULT_MTU = 1400, 215 | ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, 216 | ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, 217 | 218 | ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, 219 | ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, 220 | ENET_PEER_PACKET_THROTTLE_SCALE = 32, 221 | ENET_PEER_PACKET_THROTTLE_COUNTER = 7, 222 | ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2, 223 | ENET_PEER_PACKET_THROTTLE_DECELERATION = 2, 224 | ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000, 225 | ENET_PEER_PACKET_LOSS_SCALE = (1 << 16), 226 | ENET_PEER_PACKET_LOSS_INTERVAL = 10000, 227 | ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024, 228 | ENET_PEER_TIMEOUT_LIMIT = 32, 229 | ENET_PEER_TIMEOUT_MINIMUM = 5000, 230 | ENET_PEER_TIMEOUT_MAXIMUM = 30000, 231 | ENET_PEER_PING_INTERVAL = 500, 232 | ENET_PEER_UNSEQUENCED_WINDOWS = 64, 233 | ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024, 234 | ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32, 235 | ENET_PEER_RELIABLE_WINDOWS = 16, 236 | ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000, 237 | ENET_PEER_FREE_RELIABLE_WINDOWS = 8 238 | }; 239 | 240 | typedef struct _ENetChannel 241 | { 242 | enet_uint16 outgoingReliableSequenceNumber; 243 | enet_uint16 outgoingUnreliableSequenceNumber; 244 | enet_uint16 usedReliableWindows; 245 | enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS]; 246 | enet_uint16 incomingReliableSequenceNumber; 247 | enet_uint16 incomingUnreliableSequenceNumber; 248 | ENetList incomingReliableCommands; 249 | ENetList incomingUnreliableCommands; 250 | } ENetChannel; 251 | 252 | /** 253 | * An ENet peer which data packets may be sent or received from. 254 | * 255 | * No fields should be modified unless otherwise specified. 256 | */ 257 | typedef struct _ENetPeer 258 | { 259 | ENetListNode dispatchList; 260 | struct _ENetHost * host; 261 | enet_uint16 outgoingPeerID; 262 | enet_uint16 incomingPeerID; 263 | enet_uint32 connectID; 264 | enet_uint8 outgoingSessionID; 265 | enet_uint8 incomingSessionID; 266 | ENetAddress address; /**< Internet address of the peer */ 267 | void * data; /**< Application private data, may be freely modified */ 268 | ENetPeerState state; 269 | ENetChannel * channels; 270 | size_t channelCount; /**< Number of channels allocated for communication with peer */ 271 | enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */ 272 | enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */ 273 | enet_uint32 incomingBandwidthThrottleEpoch; 274 | enet_uint32 outgoingBandwidthThrottleEpoch; 275 | enet_uint32 incomingDataTotal; 276 | enet_uint32 outgoingDataTotal; 277 | enet_uint32 lastSendTime; 278 | enet_uint32 lastReceiveTime; 279 | enet_uint32 nextTimeout; 280 | enet_uint32 earliestTimeout; 281 | enet_uint32 packetLossEpoch; 282 | enet_uint32 packetsSent; 283 | enet_uint32 packetsLost; 284 | enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */ 285 | enet_uint32 packetLossVariance; 286 | enet_uint32 packetThrottle; 287 | enet_uint32 packetThrottleLimit; 288 | enet_uint32 packetThrottleCounter; 289 | enet_uint32 packetThrottleEpoch; 290 | enet_uint32 packetThrottleAcceleration; 291 | enet_uint32 packetThrottleDeceleration; 292 | enet_uint32 packetThrottleInterval; 293 | enet_uint32 pingInterval; 294 | enet_uint32 timeoutLimit; 295 | enet_uint32 timeoutMinimum; 296 | enet_uint32 timeoutMaximum; 297 | enet_uint32 lastRoundTripTime; 298 | enet_uint32 lowestRoundTripTime; 299 | enet_uint32 lastRoundTripTimeVariance; 300 | enet_uint32 highestRoundTripTimeVariance; 301 | enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */ 302 | enet_uint32 roundTripTimeVariance; 303 | enet_uint32 mtu; 304 | enet_uint32 windowSize; 305 | enet_uint32 reliableDataInTransit; 306 | enet_uint16 outgoingReliableSequenceNumber; 307 | ENetList acknowledgements; 308 | ENetList sentReliableCommands; 309 | ENetList sentUnreliableCommands; 310 | ENetList outgoingReliableCommands; 311 | ENetList outgoingUnreliableCommands; 312 | ENetList dispatchedCommands; 313 | int needsDispatch; 314 | enet_uint16 incomingUnsequencedGroup; 315 | enet_uint16 outgoingUnsequencedGroup; 316 | enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; 317 | enet_uint32 eventData; 318 | size_t totalWaitingData; 319 | } ENetPeer; 320 | 321 | /** An ENet packet compressor for compressing UDP packets before socket sends or receives. 322 | */ 323 | typedef struct _ENetCompressor 324 | { 325 | /** Context data for the compressor. Must be non-NULL. */ 326 | void * context; 327 | /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ 328 | size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit); 329 | /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ 330 | size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit); 331 | /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */ 332 | void (ENET_CALLBACK * destroy) (void * context); 333 | } ENetCompressor; 334 | 335 | /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ 336 | typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount); 337 | 338 | /** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ 339 | typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event); 340 | 341 | /** An ENet host for communicating with peers. 342 | * 343 | * No fields should be modified unless otherwise stated. 344 | 345 | @sa enet_host_create() 346 | @sa enet_host_destroy() 347 | @sa enet_host_connect() 348 | @sa enet_host_service() 349 | @sa enet_host_flush() 350 | @sa enet_host_broadcast() 351 | @sa enet_host_compress() 352 | @sa enet_host_compress_with_range_coder() 353 | @sa enet_host_channel_limit() 354 | @sa enet_host_bandwidth_limit() 355 | @sa enet_host_bandwidth_throttle() 356 | */ 357 | typedef struct _ENetHost 358 | { 359 | ENetSocket socket; 360 | ENetAddress address; /**< Internet address of the host */ 361 | enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */ 362 | enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */ 363 | enet_uint32 bandwidthThrottleEpoch; 364 | enet_uint32 mtu; 365 | enet_uint32 randomSeed; 366 | int recalculateBandwidthLimits; 367 | ENetPeer * peers; /**< array of peers allocated for this host */ 368 | size_t peerCount; /**< number of peers allocated for this host */ 369 | size_t channelLimit; /**< maximum number of channels allowed for connected peers */ 370 | enet_uint32 serviceTime; 371 | ENetList dispatchQueue; 372 | int continueSending; 373 | size_t packetSize; 374 | enet_uint16 headerFlags; 375 | ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; 376 | size_t commandCount; 377 | ENetBuffer buffers [ENET_BUFFER_MAXIMUM]; 378 | size_t bufferCount; 379 | ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */ 380 | ENetCompressor compressor; 381 | enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU]; 382 | ENetAddress receivedAddress; 383 | enet_uint8 * receivedData; 384 | size_t receivedDataLength; 385 | enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */ 386 | enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ 387 | enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ 388 | enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ 389 | ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ 390 | size_t connectedPeers; 391 | size_t bandwidthLimitedPeers; 392 | size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ 393 | size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ 394 | size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ 395 | size_t usingNewPacket; /**< the New and Improved! */ 396 | } ENetHost; 397 | 398 | /** 399 | * An ENet event type, as specified in @ref ENetEvent. 400 | */ 401 | typedef enum _ENetEventType 402 | { 403 | /** no event occurred within the specified time limit */ 404 | ENET_EVENT_TYPE_NONE = 0, 405 | 406 | /** a connection request initiated by enet_host_connect has completed. 407 | * The peer field contains the peer which successfully connected. 408 | */ 409 | ENET_EVENT_TYPE_CONNECT = 1, 410 | 411 | /** a peer has disconnected. This event is generated on a successful 412 | * completion of a disconnect initiated by enet_peer_disconnect, if 413 | * a peer has timed out, or if a connection request intialized by 414 | * enet_host_connect has timed out. The peer field contains the peer 415 | * which disconnected. The data field contains user supplied data 416 | * describing the disconnection, or 0, if none is available. 417 | */ 418 | ENET_EVENT_TYPE_DISCONNECT = 2, 419 | 420 | /** a packet has been received from a peer. The peer field specifies the 421 | * peer which sent the packet. The channelID field specifies the channel 422 | * number upon which the packet was received. The packet field contains 423 | * the packet that was received; this packet must be destroyed with 424 | * enet_packet_destroy after use. 425 | */ 426 | ENET_EVENT_TYPE_RECEIVE = 3 427 | } ENetEventType; 428 | 429 | /** 430 | * An ENet event as returned by enet_host_service(). 431 | 432 | @sa enet_host_service 433 | */ 434 | typedef struct _ENetEvent 435 | { 436 | ENetEventType type; /**< type of the event */ 437 | ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */ 438 | enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */ 439 | enet_uint32 data; /**< data associated with the event, if appropriate */ 440 | ENetPacket * packet; /**< packet associated with the event, if appropriate */ 441 | } ENetEvent; 442 | 443 | /** @defgroup global ENet global functions 444 | @{ 445 | */ 446 | 447 | /** 448 | Initializes ENet globally. Must be called prior to using any functions in 449 | ENet. 450 | @returns 0 on success, < 0 on failure 451 | */ 452 | ENET_API int enet_initialize (void); 453 | 454 | /** 455 | Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. 456 | 457 | @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use 458 | @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults 459 | @returns 0 on success, < 0 on failure 460 | */ 461 | ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); 462 | 463 | /** 464 | Shuts down ENet globally. Should be called when a program that has 465 | initialized ENet exits. 466 | */ 467 | ENET_API void enet_deinitialize (void); 468 | 469 | /** 470 | Gives the linked version of the ENet library. 471 | @returns the version number 472 | */ 473 | ENET_API ENetVersion enet_linked_version (void); 474 | 475 | /** @} */ 476 | 477 | /** @defgroup private ENet private implementation functions */ 478 | 479 | /** 480 | Returns the wall-time in milliseconds. Its initial value is unspecified 481 | unless otherwise set. 482 | */ 483 | ENET_API enet_uint32 enet_time_get (void); 484 | /** 485 | Sets the current wall-time in milliseconds. 486 | */ 487 | ENET_API void enet_time_set (enet_uint32); 488 | 489 | /** @defgroup socket ENet socket functions 490 | @{ 491 | */ 492 | ENET_API ENetSocket enet_socket_create (ENetSocketType); 493 | ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *); 494 | ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *); 495 | ENET_API int enet_socket_listen (ENetSocket, int); 496 | ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); 497 | ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); 498 | ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); 499 | ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); 500 | ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); 501 | ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int); 502 | ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *); 503 | ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); 504 | ENET_API void enet_socket_destroy (ENetSocket); 505 | ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); 506 | 507 | /** @} */ 508 | 509 | /** @defgroup Address ENet address functions 510 | @{ 511 | */ 512 | 513 | /** Attempts to parse the printable form of the IP address in the parameter hostName 514 | and sets the host field in the address parameter if successful. 515 | @param address destination to store the parsed IP address 516 | @param hostName IP address to parse 517 | @retval 0 on success 518 | @retval < 0 on failure 519 | @returns the address of the given hostName in address on success 520 | */ 521 | ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName); 522 | 523 | /** Attempts to resolve the host named by the parameter hostName and sets 524 | the host field in the address parameter if successful. 525 | @param address destination to store resolved address 526 | @param hostName host name to lookup 527 | @retval 0 on success 528 | @retval < 0 on failure 529 | @returns the address of the given hostName in address on success 530 | */ 531 | ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); 532 | 533 | /** Gives the printable form of the IP address specified in the address parameter. 534 | @param address address printed 535 | @param hostName destination for name, must not be NULL 536 | @param nameLength maximum length of hostName. 537 | @returns the null-terminated name of the host in hostName on success 538 | @retval 0 on success 539 | @retval < 0 on failure 540 | */ 541 | ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength); 542 | 543 | /** Attempts to do a reverse lookup of the host field in the address parameter. 544 | @param address address used for reverse lookup 545 | @param hostName destination for name, must not be NULL 546 | @param nameLength maximum length of hostName. 547 | @returns the null-terminated name of the host in hostName on success 548 | @retval 0 on success 549 | @retval < 0 on failure 550 | */ 551 | ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength); 552 | 553 | /** @} */ 554 | 555 | ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); 556 | ENET_API void enet_packet_destroy (ENetPacket *); 557 | ENET_API int enet_packet_resize (ENetPacket *, size_t); 558 | ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t); 559 | 560 | ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); 561 | ENET_API void enet_host_destroy (ENetHost *); 562 | ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32); 563 | ENET_API int enet_host_check_events (ENetHost *, ENetEvent *); 564 | ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32); 565 | ENET_API void enet_host_flush (ENetHost *); 566 | ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *); 567 | ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *); 568 | ENET_API int enet_host_compress_with_range_coder (ENetHost * host); 569 | ENET_API void enet_host_channel_limit (ENetHost *, size_t); 570 | ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); 571 | extern void enet_host_bandwidth_throttle (ENetHost *); 572 | extern enet_uint32 enet_host_random_seed (void); 573 | 574 | ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); 575 | ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); 576 | ENET_API void enet_peer_ping (ENetPeer *); 577 | ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32); 578 | ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); 579 | ENET_API void enet_peer_reset (ENetPeer *); 580 | ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32); 581 | ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32); 582 | ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32); 583 | ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); 584 | extern int enet_peer_throttle (ENetPeer *, enet_uint32); 585 | extern void enet_peer_reset_queues (ENetPeer *); 586 | extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); 587 | extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); 588 | extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); 589 | extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); 590 | extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *); 591 | extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *); 592 | extern void enet_peer_on_connect (ENetPeer *); 593 | extern void enet_peer_on_disconnect (ENetPeer *); 594 | 595 | ENET_API void * enet_range_coder_create (void); 596 | ENET_API void enet_range_coder_destroy (void *); 597 | ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t); 598 | ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t); 599 | 600 | extern size_t enet_protocol_command_size (enet_uint8); 601 | 602 | #ifdef __cplusplus 603 | } 604 | #endif 605 | 606 | #endif /* __ENET_ENET_H__ */ 607 | 608 | -------------------------------------------------------------------------------- /enet/include/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.h 3 | @brief ENet list management 4 | */ 5 | #ifndef __ENET_LIST_H__ 6 | #define __ENET_LIST_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetListNode 11 | { 12 | struct _ENetListNode * next; 13 | struct _ENetListNode * previous; 14 | } ENetListNode; 15 | 16 | typedef ENetListNode * ENetListIterator; 17 | 18 | typedef struct _ENetList 19 | { 20 | ENetListNode sentinel; 21 | } ENetList; 22 | 23 | extern void enet_list_clear (ENetList *); 24 | 25 | extern ENetListIterator enet_list_insert (ENetListIterator, void *); 26 | extern void * enet_list_remove (ENetListIterator); 27 | extern ENetListIterator enet_list_move (ENetListIterator, void *, void *); 28 | 29 | extern size_t enet_list_size (ENetList *); 30 | 31 | #define enet_list_begin(list) ((list) -> sentinel.next) 32 | #define enet_list_end(list) (& (list) -> sentinel) 33 | 34 | #define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list)) 35 | 36 | #define enet_list_next(iterator) ((iterator) -> next) 37 | #define enet_list_previous(iterator) ((iterator) -> previous) 38 | 39 | #define enet_list_front(list) ((void *) (list) -> sentinel.next) 40 | #define enet_list_back(list) ((void *) (list) -> sentinel.previous) 41 | 42 | #endif /* __ENET_LIST_H__ */ 43 | 44 | -------------------------------------------------------------------------------- /enet/include/protocol.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file protocol.h 3 | @brief ENet protocol 4 | */ 5 | #ifndef __ENET_PROTOCOL_H__ 6 | #define __ENET_PROTOCOL_H__ 7 | 8 | #include "types.h" 9 | 10 | enum 11 | { 12 | ENET_PROTOCOL_MINIMUM_MTU = 576, 13 | ENET_PROTOCOL_MAXIMUM_MTU = 4096, 14 | ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, 15 | ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, 16 | ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, 17 | ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, 18 | ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, 19 | ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, 20 | ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 21 | }; 22 | 23 | typedef enum _ENetProtocolCommand 24 | { 25 | ENET_PROTOCOL_COMMAND_NONE = 0, 26 | ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1, 27 | ENET_PROTOCOL_COMMAND_CONNECT = 2, 28 | ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3, 29 | ENET_PROTOCOL_COMMAND_DISCONNECT = 4, 30 | ENET_PROTOCOL_COMMAND_PING = 5, 31 | ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, 32 | ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, 33 | ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, 34 | ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, 35 | ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, 36 | ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, 37 | ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12, 38 | ENET_PROTOCOL_COMMAND_COUNT = 13, 39 | 40 | ENET_PROTOCOL_COMMAND_MASK = 0x0F 41 | } ENetProtocolCommand; 42 | 43 | typedef enum _ENetProtocolFlag 44 | { 45 | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), 46 | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), 47 | 48 | ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14), 49 | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), 50 | ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME, 51 | 52 | ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12), 53 | ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 54 | } ENetProtocolFlag; 55 | 56 | #ifdef _MSC_VER 57 | #pragma pack(push, 1) 58 | #define ENET_PACKED 59 | #elif defined(__GNUC__) || defined(__clang__) 60 | #define ENET_PACKED __attribute__ ((packed)) 61 | #else 62 | #define ENET_PACKED 63 | #endif 64 | 65 | typedef struct _ENetProtocolHeader 66 | { 67 | enet_uint16 peerID; 68 | enet_uint16 sentTime; 69 | } ENET_PACKED ENetProtocolHeader; 70 | 71 | typedef struct _ENetProtocolHeaderUbisoft { 72 | enet_uint16 integrity[3]; 73 | enet_uint16 peerID; 74 | enet_uint16 sentTime; 75 | } ENET_PACKED ENetProtocolHeaderUbisoft; 76 | 77 | typedef struct _ENetProtocolCommandHeader 78 | { 79 | enet_uint8 command; 80 | enet_uint8 channelID; 81 | enet_uint16 reliableSequenceNumber; 82 | } ENET_PACKED ENetProtocolCommandHeader; 83 | 84 | typedef struct _ENetProtocolAcknowledge 85 | { 86 | ENetProtocolCommandHeader header; 87 | enet_uint16 receivedReliableSequenceNumber; 88 | enet_uint16 receivedSentTime; 89 | } ENET_PACKED ENetProtocolAcknowledge; 90 | 91 | typedef struct _ENetProtocolConnect 92 | { 93 | ENetProtocolCommandHeader header; 94 | enet_uint16 outgoingPeerID; 95 | enet_uint8 incomingSessionID; 96 | enet_uint8 outgoingSessionID; 97 | enet_uint32 mtu; 98 | enet_uint32 windowSize; 99 | enet_uint32 channelCount; 100 | enet_uint32 incomingBandwidth; 101 | enet_uint32 outgoingBandwidth; 102 | enet_uint32 packetThrottleInterval; 103 | enet_uint32 packetThrottleAcceleration; 104 | enet_uint32 packetThrottleDeceleration; 105 | enet_uint32 connectID; 106 | enet_uint32 data; 107 | } ENET_PACKED ENetProtocolConnect; 108 | 109 | typedef struct _ENetProtocolVerifyConnect 110 | { 111 | ENetProtocolCommandHeader header; 112 | enet_uint16 outgoingPeerID; 113 | enet_uint8 incomingSessionID; 114 | enet_uint8 outgoingSessionID; 115 | enet_uint32 mtu; 116 | enet_uint32 windowSize; 117 | enet_uint32 channelCount; 118 | enet_uint32 incomingBandwidth; 119 | enet_uint32 outgoingBandwidth; 120 | enet_uint32 packetThrottleInterval; 121 | enet_uint32 packetThrottleAcceleration; 122 | enet_uint32 packetThrottleDeceleration; 123 | enet_uint32 connectID; 124 | } ENET_PACKED ENetProtocolVerifyConnect; 125 | 126 | typedef struct _ENetProtocolBandwidthLimit 127 | { 128 | ENetProtocolCommandHeader header; 129 | enet_uint32 incomingBandwidth; 130 | enet_uint32 outgoingBandwidth; 131 | } ENET_PACKED ENetProtocolBandwidthLimit; 132 | 133 | typedef struct _ENetProtocolThrottleConfigure 134 | { 135 | ENetProtocolCommandHeader header; 136 | enet_uint32 packetThrottleInterval; 137 | enet_uint32 packetThrottleAcceleration; 138 | enet_uint32 packetThrottleDeceleration; 139 | } ENET_PACKED ENetProtocolThrottleConfigure; 140 | 141 | typedef struct _ENetProtocolDisconnect 142 | { 143 | ENetProtocolCommandHeader header; 144 | enet_uint32 data; 145 | } ENET_PACKED ENetProtocolDisconnect; 146 | 147 | typedef struct _ENetProtocolPing 148 | { 149 | ENetProtocolCommandHeader header; 150 | } ENET_PACKED ENetProtocolPing; 151 | 152 | typedef struct _ENetProtocolSendReliable 153 | { 154 | ENetProtocolCommandHeader header; 155 | enet_uint16 dataLength; 156 | } ENET_PACKED ENetProtocolSendReliable; 157 | 158 | typedef struct _ENetProtocolSendUnreliable 159 | { 160 | ENetProtocolCommandHeader header; 161 | enet_uint16 unreliableSequenceNumber; 162 | enet_uint16 dataLength; 163 | } ENET_PACKED ENetProtocolSendUnreliable; 164 | 165 | typedef struct _ENetProtocolSendUnsequenced 166 | { 167 | ENetProtocolCommandHeader header; 168 | enet_uint16 unsequencedGroup; 169 | enet_uint16 dataLength; 170 | } ENET_PACKED ENetProtocolSendUnsequenced; 171 | 172 | typedef struct _ENetProtocolSendFragment 173 | { 174 | ENetProtocolCommandHeader header; 175 | enet_uint16 startSequenceNumber; 176 | enet_uint16 dataLength; 177 | enet_uint32 fragmentCount; 178 | enet_uint32 fragmentNumber; 179 | enet_uint32 totalLength; 180 | enet_uint32 fragmentOffset; 181 | } ENET_PACKED ENetProtocolSendFragment; 182 | 183 | typedef union _ENetProtocol 184 | { 185 | ENetProtocolCommandHeader header; 186 | ENetProtocolAcknowledge acknowledge; 187 | ENetProtocolConnect connect; 188 | ENetProtocolVerifyConnect verifyConnect; 189 | ENetProtocolDisconnect disconnect; 190 | ENetProtocolPing ping; 191 | ENetProtocolSendReliable sendReliable; 192 | ENetProtocolSendUnreliable sendUnreliable; 193 | ENetProtocolSendUnsequenced sendUnsequenced; 194 | ENetProtocolSendFragment sendFragment; 195 | ENetProtocolBandwidthLimit bandwidthLimit; 196 | ENetProtocolThrottleConfigure throttleConfigure; 197 | } ENET_PACKED ENetProtocol; 198 | 199 | #ifdef _MSC_VER 200 | #pragma pack(pop) 201 | #endif 202 | 203 | #endif /* __ENET_PROTOCOL_H__ */ 204 | 205 | -------------------------------------------------------------------------------- /enet/include/time2.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file time.h 3 | @brief ENet time constants and macros 4 | */ 5 | #ifndef __ENET_TIME_H__ 6 | #define __ENET_TIME_H__ 7 | 8 | #define ENET_TIME_OVERFLOW 86400000 9 | 10 | #define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) 11 | #define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) 12 | #define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) 13 | #define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) 14 | 15 | #define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) 16 | 17 | #endif /* __ENET_TIME_H__ */ 18 | 19 | -------------------------------------------------------------------------------- /enet/include/types.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file types.h 3 | @brief type definitions for ENet 4 | */ 5 | #ifndef __ENET_TYPES_H__ 6 | #define __ENET_TYPES_H__ 7 | 8 | typedef unsigned char enet_uint8; /**< unsigned 8-bit type */ 9 | typedef unsigned short enet_uint16; /**< unsigned 16-bit type */ 10 | typedef unsigned int enet_uint32; /**< unsigned 32-bit type */ 11 | 12 | #endif /* __ENET_TYPES_H__ */ 13 | 14 | -------------------------------------------------------------------------------- /enet/include/unix.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file unix.h 3 | @brief ENet Unix header 4 | */ 5 | #ifndef _WIN32 6 | #ifndef __ENET_UNIX_H__ 7 | #define __ENET_UNIX_H__ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef MSG_MAXIOVLEN 18 | #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN 19 | #endif 20 | 21 | typedef int ENetSocket; 22 | 23 | #define ENET_SOCKET_NULL -1 24 | 25 | #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ 26 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ 27 | 28 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */ 29 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */ 30 | 31 | typedef struct 32 | { 33 | void * data; 34 | size_t dataLength; 35 | } ENetBuffer; 36 | 37 | #define ENET_CALLBACK 38 | 39 | #define ENET_API extern 40 | 41 | typedef fd_set ENetSocketSet; 42 | 43 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 44 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 45 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 46 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 47 | 48 | #endif /* __ENET_UNIX_H__ */ 49 | #endif -------------------------------------------------------------------------------- /enet/include/utility.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file utility.h 3 | @brief ENet utility header 4 | */ 5 | #ifndef __ENET_UTILITY_H__ 6 | #define __ENET_UTILITY_H__ 7 | 8 | #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) 9 | #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) 10 | 11 | #endif /* __ENET_UTILITY_H__ */ 12 | 13 | -------------------------------------------------------------------------------- /enet/include/win32.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file win32.h 3 | @brief ENet Win32 header 4 | */ 5 | #ifdef _WIN32 6 | #ifndef __ENET_WIN32_H__ 7 | #define __ENET_WIN32_H__ 8 | 9 | #ifdef _MSC_VER 10 | #ifdef ENET_BUILDING_LIB 11 | #pragma warning (disable: 4267) // size_t to int conversion 12 | #pragma warning (disable: 4244) // 64bit to 32bit int 13 | #pragma warning (disable: 4018) // signed/unsigned mismatch 14 | #pragma warning (disable: 4146) // unary minus operator applied to unsigned type 15 | #endif 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | typedef SOCKET ENetSocket; 23 | 24 | #define ENET_SOCKET_NULL INVALID_SOCKET 25 | 26 | #define ENET_HOST_TO_NET_16(value) (htons (value)) 27 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) 28 | 29 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) 30 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) 31 | 32 | typedef struct 33 | { 34 | size_t dataLength; 35 | void * data; 36 | } ENetBuffer; 37 | 38 | #define ENET_CALLBACK __cdecl 39 | 40 | #ifdef ENET_DLL 41 | #ifdef ENET_BUILDING_LIB 42 | #define ENET_API __declspec( dllexport ) 43 | #else 44 | #define ENET_API __declspec( dllimport ) 45 | #endif /* ENET_BUILDING_LIB */ 46 | #else /* !ENET_DLL */ 47 | #define ENET_API extern 48 | #endif /* ENET_DLL */ 49 | 50 | typedef fd_set ENetSocketSet; 51 | 52 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 53 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 54 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 55 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 56 | 57 | #endif /* __ENET_WIN32_H__ */ 58 | #endif -------------------------------------------------------------------------------- /enet/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.c 3 | @brief ENet linked list functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "include/enet.h" 7 | 8 | /** 9 | @defgroup list ENet linked list utility functions 10 | @ingroup private 11 | @{ 12 | */ 13 | void 14 | enet_list_clear (ENetList * list) 15 | { 16 | list -> sentinel.next = & list -> sentinel; 17 | list -> sentinel.previous = & list -> sentinel; 18 | } 19 | 20 | ENetListIterator 21 | enet_list_insert (ENetListIterator position, void * data) 22 | { 23 | ENetListIterator result = (ENetListIterator) data; 24 | 25 | result -> previous = position -> previous; 26 | result -> next = position; 27 | 28 | result -> previous -> next = result; 29 | position -> previous = result; 30 | 31 | return result; 32 | } 33 | 34 | void * 35 | enet_list_remove (ENetListIterator position) 36 | { 37 | position -> previous -> next = position -> next; 38 | position -> next -> previous = position -> previous; 39 | 40 | return position; 41 | } 42 | 43 | ENetListIterator 44 | enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast) 45 | { 46 | ENetListIterator first = (ENetListIterator) dataFirst, 47 | last = (ENetListIterator) dataLast; 48 | 49 | first -> previous -> next = last -> next; 50 | last -> next -> previous = first -> previous; 51 | 52 | first -> previous = position -> previous; 53 | last -> next = position; 54 | 55 | first -> previous -> next = first; 56 | position -> previous = last; 57 | 58 | return first; 59 | } 60 | 61 | size_t 62 | enet_list_size (ENetList * list) 63 | { 64 | size_t size = 0; 65 | ENetListIterator position; 66 | 67 | for (position = enet_list_begin (list); 68 | position != enet_list_end (list); 69 | position = enet_list_next (position)) 70 | ++ size; 71 | 72 | return size; 73 | } 74 | 75 | /** @} */ 76 | -------------------------------------------------------------------------------- /enet/packet.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file packet.c 3 | @brief ENet packet management functions 4 | */ 5 | #include 6 | #define ENET_BUILDING_LIB 1 7 | #include "include/enet.h" 8 | 9 | /** @defgroup Packet ENet packet functions 10 | @{ 11 | */ 12 | 13 | /** Creates a packet that may be sent to a peer. 14 | @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. 15 | @param dataLength size of the data allocated for this packet 16 | @param flags flags for this packet as described for the ENetPacket structure. 17 | @returns the packet on success, NULL on failure 18 | */ 19 | ENetPacket * 20 | enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) 21 | { 22 | ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); 23 | if (packet == NULL) 24 | return NULL; 25 | 26 | if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) 27 | packet -> data = (enet_uint8 *) data; 28 | else 29 | if (dataLength <= 0) 30 | packet -> data = NULL; 31 | else 32 | { 33 | packet -> data = (enet_uint8 *) enet_malloc (dataLength); 34 | if (packet -> data == NULL) 35 | { 36 | enet_free (packet); 37 | return NULL; 38 | } 39 | 40 | if (data != NULL) 41 | memcpy (packet -> data, data, dataLength); 42 | } 43 | 44 | packet -> referenceCount = 0; 45 | packet -> flags = flags; 46 | packet -> dataLength = dataLength; 47 | packet -> freeCallback = NULL; 48 | packet -> userData = NULL; 49 | 50 | return packet; 51 | } 52 | 53 | /** Destroys the packet and deallocates its data. 54 | @param packet packet to be destroyed 55 | */ 56 | void 57 | enet_packet_destroy (ENetPacket * packet) 58 | { 59 | if (packet == NULL) 60 | return; 61 | 62 | if (packet -> freeCallback != NULL) 63 | (* packet -> freeCallback) (packet); 64 | if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && 65 | packet -> data != NULL) 66 | enet_free (packet -> data); 67 | enet_free (packet); 68 | } 69 | 70 | /** Attempts to resize the data in the packet to length specified in the 71 | dataLength parameter 72 | @param packet packet to resize 73 | @param dataLength new size for the packet data 74 | @returns 0 on success, < 0 on failure 75 | */ 76 | int 77 | enet_packet_resize (ENetPacket * packet, size_t dataLength) 78 | { 79 | enet_uint8 * newData; 80 | 81 | if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) 82 | { 83 | packet -> dataLength = dataLength; 84 | 85 | return 0; 86 | } 87 | 88 | newData = (enet_uint8 *) enet_malloc (dataLength); 89 | if (newData == NULL) 90 | return -1; 91 | 92 | memcpy (newData, packet -> data, packet -> dataLength); 93 | enet_free (packet -> data); 94 | 95 | packet -> data = newData; 96 | packet -> dataLength = dataLength; 97 | 98 | return 0; 99 | } 100 | 101 | static int initializedCRC32 = 0; 102 | static enet_uint32 crcTable [256]; 103 | 104 | static enet_uint32 105 | reflect_crc (int val, int bits) 106 | { 107 | int result = 0, bit; 108 | 109 | for (bit = 0; bit < bits; bit ++) 110 | { 111 | if(val & 1) result |= 1 << (bits - 1 - bit); 112 | val >>= 1; 113 | } 114 | 115 | return result; 116 | } 117 | 118 | static void 119 | initialize_crc32 (void) 120 | { 121 | int byte; 122 | 123 | for (byte = 0; byte < 256; ++ byte) 124 | { 125 | enet_uint32 crc = reflect_crc (byte, 8) << 24; 126 | int offset; 127 | 128 | for(offset = 0; offset < 8; ++ offset) 129 | { 130 | if (crc & 0x80000000) 131 | crc = (crc << 1) ^ 0x04c11db7; 132 | else 133 | crc <<= 1; 134 | } 135 | 136 | crcTable [byte] = reflect_crc (crc, 32); 137 | } 138 | 139 | initializedCRC32 = 1; 140 | } 141 | 142 | enet_uint32 143 | enet_crc32 (const ENetBuffer * buffers, size_t bufferCount) 144 | { 145 | enet_uint32 crc = 0xFFFFFFFF; 146 | 147 | if (! initializedCRC32) initialize_crc32 (); 148 | 149 | while (bufferCount -- > 0) 150 | { 151 | const enet_uint8 * data = (const enet_uint8 *) buffers -> data, 152 | * dataEnd = & data [buffers -> dataLength]; 153 | 154 | while (data < dataEnd) 155 | { 156 | crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++]; 157 | } 158 | 159 | ++ buffers; 160 | } 161 | 162 | return ENET_HOST_TO_NET_32 (~ crc); 163 | } 164 | 165 | /** @} */ 166 | -------------------------------------------------------------------------------- /enet/peer.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file peer.c 3 | @brief ENet peer management functions 4 | */ 5 | #include 6 | #define ENET_BUILDING_LIB 1 7 | #include "include/enet.h" 8 | 9 | /** @defgroup peer ENet peer functions 10 | @{ 11 | */ 12 | 13 | /** Configures throttle parameter for a peer. 14 | 15 | Unreliable packets are dropped by ENet in response to the varying conditions 16 | of the Internet connection to the peer. The throttle represents a probability 17 | that an unreliable packet should not be dropped and thus sent by ENet to the peer. 18 | The lowest mean round trip time from the sending of a reliable packet to the 19 | receipt of its acknowledgement is measured over an amount of time specified by 20 | the interval parameter in milliseconds. If a measured round trip time happens to 21 | be significantly less than the mean round trip time measured over the interval, 22 | then the throttle probability is increased to allow more traffic by an amount 23 | specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE 24 | constant. If a measured round trip time happens to be significantly greater than 25 | the mean round trip time measured over the interval, then the throttle probability 26 | is decreased to limit traffic by an amount specified in the deceleration parameter, which 27 | is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has 28 | a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by 29 | ENet, and so 100% of all unreliable packets will be sent. When the throttle has a 30 | value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable 31 | packets will be sent. Intermediate values for the throttle represent intermediate 32 | probabilities between 0% and 100% of unreliable packets being sent. The bandwidth 33 | limits of the local and foreign hosts are taken into account to determine a 34 | sensible limit for the throttle probability above which it should not raise even in 35 | the best of conditions. 36 | 37 | @param peer peer to configure 38 | @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL. 39 | @param acceleration rate at which to increase the throttle probability as mean RTT declines 40 | @param deceleration rate at which to decrease the throttle probability as mean RTT increases 41 | */ 42 | void 43 | enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration) 44 | { 45 | ENetProtocol command; 46 | 47 | peer -> packetThrottleInterval = interval; 48 | peer -> packetThrottleAcceleration = acceleration; 49 | peer -> packetThrottleDeceleration = deceleration; 50 | 51 | command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 52 | command.header.channelID = 0xFF; 53 | 54 | command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval); 55 | command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration); 56 | command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration); 57 | 58 | enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); 59 | } 60 | 61 | int 62 | enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt) 63 | { 64 | if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance) 65 | { 66 | peer -> packetThrottle = peer -> packetThrottleLimit; 67 | } 68 | else 69 | if (rtt < peer -> lastRoundTripTime) 70 | { 71 | peer -> packetThrottle += peer -> packetThrottleAcceleration; 72 | 73 | if (peer -> packetThrottle > peer -> packetThrottleLimit) 74 | peer -> packetThrottle = peer -> packetThrottleLimit; 75 | 76 | return 1; 77 | } 78 | else 79 | if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance) 80 | { 81 | if (peer -> packetThrottle > peer -> packetThrottleDeceleration) 82 | peer -> packetThrottle -= peer -> packetThrottleDeceleration; 83 | else 84 | peer -> packetThrottle = 0; 85 | 86 | return -1; 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | /** Queues a packet to be sent. 93 | @param peer destination for the packet 94 | @param channelID channel on which to send 95 | @param packet packet to send 96 | @retval 0 on success 97 | @retval < 0 on failure 98 | */ 99 | int 100 | enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) 101 | { 102 | ENetChannel * channel = & peer -> channels [channelID]; 103 | ENetProtocol command; 104 | size_t fragmentLength; 105 | 106 | if (peer -> state != ENET_PEER_STATE_CONNECTED || 107 | channelID >= peer -> channelCount || 108 | packet -> dataLength > peer -> host -> maximumPacketSize) 109 | return -1; 110 | 111 | if (peer->host->usingNewPacket) { 112 | fragmentLength = peer->mtu - sizeof(ENetProtocolHeaderUbisoft) - sizeof(ENetProtocolSendFragment); 113 | } else { 114 | fragmentLength = peer->mtu - sizeof(ENetProtocolHeader) - sizeof(ENetProtocolSendFragment); 115 | } 116 | if (peer->host->checksum != NULL) 117 | fragmentLength -= sizeof(enet_uint32); 118 | 119 | if (packet -> dataLength > fragmentLength) 120 | { 121 | enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength, 122 | fragmentNumber, 123 | fragmentOffset; 124 | enet_uint8 commandNumber; 125 | enet_uint16 startSequenceNumber; 126 | ENetList fragments; 127 | ENetOutgoingCommand * fragment; 128 | 129 | if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) 130 | return -1; 131 | 132 | if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && 133 | channel -> outgoingUnreliableSequenceNumber < 0xFFFF) 134 | { 135 | commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT; 136 | startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1); 137 | } 138 | else 139 | { 140 | commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 141 | startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1); 142 | } 143 | 144 | enet_list_clear (& fragments); 145 | 146 | for (fragmentNumber = 0, 147 | fragmentOffset = 0; 148 | fragmentOffset < packet -> dataLength; 149 | ++ fragmentNumber, 150 | fragmentOffset += fragmentLength) 151 | { 152 | if (packet -> dataLength - fragmentOffset < fragmentLength) 153 | fragmentLength = packet -> dataLength - fragmentOffset; 154 | 155 | fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); 156 | if (fragment == NULL) 157 | { 158 | while (! enet_list_empty (& fragments)) 159 | { 160 | fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments)); 161 | 162 | enet_free (fragment); 163 | } 164 | 165 | return -1; 166 | } 167 | 168 | fragment -> fragmentOffset = fragmentOffset; 169 | fragment -> fragmentLength = fragmentLength; 170 | fragment -> packet = packet; 171 | fragment -> command.header.command = commandNumber; 172 | fragment -> command.header.channelID = channelID; 173 | fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; 174 | fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); 175 | fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount); 176 | fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); 177 | fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); 178 | fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); 179 | 180 | enet_list_insert (enet_list_end (& fragments), fragment); 181 | } 182 | 183 | packet -> referenceCount += fragmentNumber; 184 | 185 | while (! enet_list_empty (& fragments)) 186 | { 187 | fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments)); 188 | 189 | enet_peer_setup_outgoing_command (peer, fragment); 190 | } 191 | 192 | return 0; 193 | } 194 | 195 | command.header.channelID = channelID; 196 | 197 | if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED) 198 | { 199 | command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; 200 | command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); 201 | } 202 | else 203 | if (packet -> flags & ENET_PACKET_FLAG_RELIABLE || channel -> outgoingUnreliableSequenceNumber >= 0xFFFF) 204 | { 205 | command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 206 | command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); 207 | } 208 | else 209 | { 210 | command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; 211 | command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); 212 | } 213 | 214 | if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL) 215 | return -1; 216 | 217 | return 0; 218 | } 219 | 220 | /** Attempts to dequeue any incoming queued packet. 221 | @param peer peer to dequeue packets from 222 | @param channelID holds the channel ID of the channel the packet was received on success 223 | @returns a pointer to the packet, or NULL if there are no available incoming queued packets 224 | */ 225 | ENetPacket * 226 | enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID) 227 | { 228 | ENetIncomingCommand * incomingCommand; 229 | ENetPacket * packet; 230 | 231 | if (enet_list_empty (& peer -> dispatchedCommands)) 232 | return NULL; 233 | 234 | incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands)); 235 | 236 | if (channelID != NULL) 237 | * channelID = incomingCommand -> command.header.channelID; 238 | 239 | packet = incomingCommand -> packet; 240 | 241 | -- packet -> referenceCount; 242 | 243 | if (incomingCommand -> fragments != NULL) 244 | enet_free (incomingCommand -> fragments); 245 | 246 | enet_free (incomingCommand); 247 | 248 | peer -> totalWaitingData -= packet -> dataLength; 249 | 250 | return packet; 251 | } 252 | 253 | static void 254 | enet_peer_reset_outgoing_commands (ENetList * queue) 255 | { 256 | ENetOutgoingCommand * outgoingCommand; 257 | 258 | while (! enet_list_empty (queue)) 259 | { 260 | outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue)); 261 | 262 | if (outgoingCommand -> packet != NULL) 263 | { 264 | -- outgoingCommand -> packet -> referenceCount; 265 | 266 | if (outgoingCommand -> packet -> referenceCount == 0) 267 | enet_packet_destroy (outgoingCommand -> packet); 268 | } 269 | 270 | enet_free (outgoingCommand); 271 | } 272 | } 273 | 274 | static void 275 | enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand) 276 | { 277 | ENetListIterator currentCommand; 278 | 279 | for (currentCommand = startCommand; currentCommand != endCommand; ) 280 | { 281 | ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; 282 | 283 | currentCommand = enet_list_next (currentCommand); 284 | 285 | enet_list_remove (& incomingCommand -> incomingCommandList); 286 | 287 | if (incomingCommand -> packet != NULL) 288 | { 289 | -- incomingCommand -> packet -> referenceCount; 290 | 291 | if (incomingCommand -> packet -> referenceCount == 0) 292 | enet_packet_destroy (incomingCommand -> packet); 293 | } 294 | 295 | if (incomingCommand -> fragments != NULL) 296 | enet_free (incomingCommand -> fragments); 297 | 298 | enet_free (incomingCommand); 299 | } 300 | } 301 | 302 | static void 303 | enet_peer_reset_incoming_commands (ENetList * queue) 304 | { 305 | enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue)); 306 | } 307 | 308 | void 309 | enet_peer_reset_queues (ENetPeer * peer) 310 | { 311 | ENetChannel * channel; 312 | 313 | if (peer -> needsDispatch) 314 | { 315 | enet_list_remove (& peer -> dispatchList); 316 | 317 | peer -> needsDispatch = 0; 318 | } 319 | 320 | while (! enet_list_empty (& peer -> acknowledgements)) 321 | enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements))); 322 | 323 | enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); 324 | enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands); 325 | enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands); 326 | enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands); 327 | enet_peer_reset_incoming_commands (& peer -> dispatchedCommands); 328 | 329 | if (peer -> channels != NULL && peer -> channelCount > 0) 330 | { 331 | for (channel = peer -> channels; 332 | channel < & peer -> channels [peer -> channelCount]; 333 | ++ channel) 334 | { 335 | enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands); 336 | enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands); 337 | } 338 | 339 | enet_free (peer -> channels); 340 | } 341 | 342 | peer -> channels = NULL; 343 | peer -> channelCount = 0; 344 | } 345 | 346 | void 347 | enet_peer_on_connect (ENetPeer * peer) 348 | { 349 | if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) 350 | { 351 | if (peer -> incomingBandwidth != 0) 352 | ++ peer -> host -> bandwidthLimitedPeers; 353 | 354 | ++ peer -> host -> connectedPeers; 355 | } 356 | } 357 | 358 | void 359 | enet_peer_on_disconnect (ENetPeer * peer) 360 | { 361 | if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) 362 | { 363 | if (peer -> incomingBandwidth != 0) 364 | -- peer -> host -> bandwidthLimitedPeers; 365 | 366 | -- peer -> host -> connectedPeers; 367 | } 368 | } 369 | 370 | /** Forcefully disconnects a peer. 371 | @param peer peer to forcefully disconnect 372 | @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout 373 | on its connection to the local host. 374 | */ 375 | void 376 | enet_peer_reset (ENetPeer * peer) 377 | { 378 | enet_peer_on_disconnect (peer); 379 | 380 | peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; 381 | peer -> connectID = 0; 382 | 383 | peer -> state = ENET_PEER_STATE_DISCONNECTED; 384 | 385 | peer -> incomingBandwidth = 0; 386 | peer -> outgoingBandwidth = 0; 387 | peer -> incomingBandwidthThrottleEpoch = 0; 388 | peer -> outgoingBandwidthThrottleEpoch = 0; 389 | peer -> incomingDataTotal = 0; 390 | peer -> outgoingDataTotal = 0; 391 | peer -> lastSendTime = 0; 392 | peer -> lastReceiveTime = 0; 393 | peer -> nextTimeout = 0; 394 | peer -> earliestTimeout = 0; 395 | peer -> packetLossEpoch = 0; 396 | peer -> packetsSent = 0; 397 | peer -> packetsLost = 0; 398 | peer -> packetLoss = 0; 399 | peer -> packetLossVariance = 0; 400 | peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE; 401 | peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE; 402 | peer -> packetThrottleCounter = 0; 403 | peer -> packetThrottleEpoch = 0; 404 | peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; 405 | peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; 406 | peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; 407 | peer -> pingInterval = ENET_PEER_PING_INTERVAL; 408 | peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; 409 | peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; 410 | peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; 411 | peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; 412 | peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; 413 | peer -> lastRoundTripTimeVariance = 0; 414 | peer -> highestRoundTripTimeVariance = 0; 415 | peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; 416 | peer -> roundTripTimeVariance = 0; 417 | peer -> mtu = peer -> host -> mtu; 418 | peer -> reliableDataInTransit = 0; 419 | peer -> outgoingReliableSequenceNumber = 0; 420 | peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; 421 | peer -> incomingUnsequencedGroup = 0; 422 | peer -> outgoingUnsequencedGroup = 0; 423 | peer -> eventData = 0; 424 | peer -> totalWaitingData = 0; 425 | 426 | memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); 427 | 428 | enet_peer_reset_queues (peer); 429 | } 430 | 431 | /** Sends a ping request to a peer. 432 | @param peer destination for the ping request 433 | @remarks ping requests factor into the mean round trip time as designated by the 434 | roundTripTime field in the ENetPeer structure. ENet automatically pings all connected 435 | peers at regular intervals, however, this function may be called to ensure more 436 | frequent ping requests. 437 | */ 438 | void 439 | enet_peer_ping (ENetPeer * peer) 440 | { 441 | ENetProtocol command; 442 | 443 | if (peer -> state != ENET_PEER_STATE_CONNECTED) 444 | return; 445 | 446 | command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 447 | command.header.channelID = 0xFF; 448 | 449 | enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); 450 | } 451 | 452 | /** Sets the interval at which pings will be sent to a peer. 453 | 454 | Pings are used both to monitor the liveness of the connection and also to dynamically 455 | adjust the throttle during periods of low traffic so that the throttle has reasonable 456 | responsiveness during traffic spikes. 457 | 458 | @param peer the peer to adjust 459 | @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 460 | */ 461 | void 462 | enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval) 463 | { 464 | peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; 465 | } 466 | 467 | /** Sets the timeout parameters for a peer. 468 | 469 | The timeout parameter control how and when a peer will timeout from a failure to acknowledge 470 | reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable 471 | packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, 472 | the timeout will be doubled until it reaches a set limit. If the timeout is thus at this 473 | limit and reliable packets have been sent but not acknowledged within a certain minimum time 474 | period, the peer will be disconnected. Alternatively, if reliable packets have been sent 475 | but not acknowledged for a certain maximum time period, the peer will be disconnected regardless 476 | of the current timeout limit value. 477 | 478 | @param peer the peer to adjust 479 | @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 480 | @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 481 | @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 482 | */ 483 | 484 | void 485 | enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) 486 | { 487 | peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; 488 | peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; 489 | peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; 490 | } 491 | 492 | /** Force an immediate disconnection from a peer. 493 | @param peer peer to disconnect 494 | @param data data describing the disconnection 495 | @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not 496 | guaranteed to receive the disconnect notification, and is reset immediately upon 497 | return from this function. 498 | */ 499 | void 500 | enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data) 501 | { 502 | ENetProtocol command; 503 | 504 | if (peer -> state == ENET_PEER_STATE_DISCONNECTED) 505 | return; 506 | 507 | if (peer -> state != ENET_PEER_STATE_ZOMBIE && 508 | peer -> state != ENET_PEER_STATE_DISCONNECTING) 509 | { 510 | enet_peer_reset_queues (peer); 511 | 512 | command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; 513 | command.header.channelID = 0xFF; 514 | command.disconnect.data = ENET_HOST_TO_NET_32 (data); 515 | 516 | enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); 517 | 518 | enet_host_flush (peer -> host); 519 | } 520 | 521 | enet_peer_reset (peer); 522 | } 523 | 524 | /** Request a disconnection from a peer. 525 | @param peer peer to request a disconnection 526 | @param data data describing the disconnection 527 | @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() 528 | once the disconnection is complete. 529 | */ 530 | void 531 | enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) 532 | { 533 | ENetProtocol command; 534 | 535 | if (peer -> state == ENET_PEER_STATE_DISCONNECTING || 536 | peer -> state == ENET_PEER_STATE_DISCONNECTED || 537 | peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT || 538 | peer -> state == ENET_PEER_STATE_ZOMBIE) 539 | return; 540 | 541 | enet_peer_reset_queues (peer); 542 | 543 | command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT; 544 | command.header.channelID = 0xFF; 545 | command.disconnect.data = ENET_HOST_TO_NET_32 (data); 546 | 547 | if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) 548 | command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; 549 | else 550 | command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; 551 | 552 | enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); 553 | 554 | if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) 555 | { 556 | enet_peer_on_disconnect (peer); 557 | 558 | peer -> state = ENET_PEER_STATE_DISCONNECTING; 559 | } 560 | else 561 | { 562 | enet_host_flush (peer -> host); 563 | enet_peer_reset (peer); 564 | } 565 | } 566 | 567 | /** Request a disconnection from a peer, but only after all queued outgoing packets are sent. 568 | @param peer peer to request a disconnection 569 | @param data data describing the disconnection 570 | @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() 571 | once the disconnection is complete. 572 | */ 573 | void 574 | enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) 575 | { 576 | if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && 577 | ! (enet_list_empty (& peer -> outgoingReliableCommands) && 578 | enet_list_empty (& peer -> outgoingUnreliableCommands) && 579 | enet_list_empty (& peer -> sentReliableCommands))) 580 | { 581 | peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; 582 | peer -> eventData = data; 583 | } 584 | else 585 | enet_peer_disconnect (peer, data); 586 | } 587 | 588 | ENetAcknowledgement * 589 | enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime) 590 | { 591 | ENetAcknowledgement * acknowledgement; 592 | 593 | if (command -> header.channelID < peer -> channelCount) 594 | { 595 | ENetChannel * channel = & peer -> channels [command -> header.channelID]; 596 | enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, 597 | currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; 598 | 599 | if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber) 600 | reliableWindow += ENET_PEER_RELIABLE_WINDOWS; 601 | 602 | if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS) 603 | return NULL; 604 | } 605 | 606 | acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement)); 607 | if (acknowledgement == NULL) 608 | return NULL; 609 | 610 | peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge); 611 | 612 | acknowledgement -> sentTime = sentTime; 613 | acknowledgement -> command = * command; 614 | 615 | enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement); 616 | 617 | return acknowledgement; 618 | } 619 | 620 | void 621 | enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) 622 | { 623 | ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID]; 624 | 625 | peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; 626 | 627 | if (outgoingCommand -> command.header.channelID == 0xFF) 628 | { 629 | ++ peer -> outgoingReliableSequenceNumber; 630 | 631 | outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber; 632 | outgoingCommand -> unreliableSequenceNumber = 0; 633 | } 634 | else 635 | if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) 636 | { 637 | ++ channel -> outgoingReliableSequenceNumber; 638 | channel -> outgoingUnreliableSequenceNumber = 0; 639 | 640 | outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; 641 | outgoingCommand -> unreliableSequenceNumber = 0; 642 | } 643 | else 644 | if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) 645 | { 646 | ++ peer -> outgoingUnsequencedGroup; 647 | 648 | outgoingCommand -> reliableSequenceNumber = 0; 649 | outgoingCommand -> unreliableSequenceNumber = 0; 650 | } 651 | else 652 | { 653 | if (outgoingCommand -> fragmentOffset == 0) 654 | ++ channel -> outgoingUnreliableSequenceNumber; 655 | 656 | outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; 657 | outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber; 658 | } 659 | 660 | outgoingCommand -> sendAttempts = 0; 661 | outgoingCommand -> sentTime = 0; 662 | outgoingCommand -> roundTripTimeout = 0; 663 | outgoingCommand -> roundTripTimeoutLimit = 0; 664 | outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber); 665 | 666 | switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) 667 | { 668 | case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: 669 | outgoingCommand -> command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> unreliableSequenceNumber); 670 | break; 671 | 672 | case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: 673 | outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup); 674 | break; 675 | 676 | default: 677 | break; 678 | } 679 | 680 | if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) 681 | enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); 682 | else 683 | enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); 684 | } 685 | 686 | ENetOutgoingCommand * 687 | enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length) 688 | { 689 | ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); 690 | if (outgoingCommand == NULL) 691 | return NULL; 692 | 693 | outgoingCommand -> command = * command; 694 | outgoingCommand -> fragmentOffset = offset; 695 | outgoingCommand -> fragmentLength = length; 696 | outgoingCommand -> packet = packet; 697 | if (packet != NULL) 698 | ++ packet -> referenceCount; 699 | 700 | enet_peer_setup_outgoing_command (peer, outgoingCommand); 701 | 702 | return outgoingCommand; 703 | } 704 | 705 | void 706 | enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel) 707 | { 708 | ENetListIterator droppedCommand, startCommand, currentCommand; 709 | 710 | for (droppedCommand = startCommand = currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands); 711 | currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); 712 | currentCommand = enet_list_next (currentCommand)) 713 | { 714 | ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; 715 | 716 | if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) 717 | continue; 718 | 719 | if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber) 720 | { 721 | if (incomingCommand -> fragmentsRemaining <= 0) 722 | { 723 | channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; 724 | continue; 725 | } 726 | 727 | if (startCommand != currentCommand) 728 | { 729 | enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); 730 | 731 | if (! peer -> needsDispatch) 732 | { 733 | enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); 734 | 735 | peer -> needsDispatch = 1; 736 | } 737 | 738 | droppedCommand = currentCommand; 739 | } 740 | else 741 | if (droppedCommand != currentCommand) 742 | droppedCommand = enet_list_previous (currentCommand); 743 | } 744 | else 745 | { 746 | enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, 747 | currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; 748 | if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) 749 | reliableWindow += ENET_PEER_RELIABLE_WINDOWS; 750 | if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) 751 | break; 752 | 753 | droppedCommand = enet_list_next (currentCommand); 754 | 755 | if (startCommand != currentCommand) 756 | { 757 | enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); 758 | 759 | if (! peer -> needsDispatch) 760 | { 761 | enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); 762 | 763 | peer -> needsDispatch = 1; 764 | } 765 | } 766 | } 767 | 768 | startCommand = enet_list_next (currentCommand); 769 | } 770 | 771 | if (startCommand != currentCommand) 772 | { 773 | enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); 774 | 775 | if (! peer -> needsDispatch) 776 | { 777 | enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); 778 | 779 | peer -> needsDispatch = 1; 780 | } 781 | 782 | droppedCommand = currentCommand; 783 | } 784 | 785 | enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); 786 | } 787 | 788 | void 789 | enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel) 790 | { 791 | ENetListIterator currentCommand; 792 | 793 | for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands); 794 | currentCommand != enet_list_end (& channel -> incomingReliableCommands); 795 | currentCommand = enet_list_next (currentCommand)) 796 | { 797 | ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; 798 | 799 | if (incomingCommand -> fragmentsRemaining > 0 || 800 | incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1)) 801 | break; 802 | 803 | channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber; 804 | 805 | if (incomingCommand -> fragmentCount > 0) 806 | channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1; 807 | } 808 | 809 | if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands)) 810 | return; 811 | 812 | channel -> incomingUnreliableSequenceNumber = 0; 813 | 814 | enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand)); 815 | 816 | if (! peer -> needsDispatch) 817 | { 818 | enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); 819 | 820 | peer -> needsDispatch = 1; 821 | } 822 | 823 | if (! enet_list_empty (& channel -> incomingUnreliableCommands)) 824 | enet_peer_dispatch_incoming_unreliable_commands (peer, channel); 825 | } 826 | 827 | ENetIncomingCommand * 828 | enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) 829 | { 830 | static ENetIncomingCommand dummyCommand; 831 | 832 | ENetChannel * channel = & peer -> channels [command -> header.channelID]; 833 | enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0; 834 | enet_uint16 reliableWindow, currentWindow; 835 | ENetIncomingCommand * incomingCommand; 836 | ENetListIterator currentCommand; 837 | ENetPacket * packet = NULL; 838 | 839 | if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) 840 | goto discardCommand; 841 | 842 | if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) 843 | { 844 | reliableSequenceNumber = command -> header.reliableSequenceNumber; 845 | reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; 846 | currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; 847 | 848 | if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber) 849 | reliableWindow += ENET_PEER_RELIABLE_WINDOWS; 850 | 851 | if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) 852 | goto discardCommand; 853 | } 854 | 855 | switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) 856 | { 857 | case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: 858 | case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: 859 | if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) 860 | goto discardCommand; 861 | 862 | for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); 863 | currentCommand != enet_list_end (& channel -> incomingReliableCommands); 864 | currentCommand = enet_list_previous (currentCommand)) 865 | { 866 | incomingCommand = (ENetIncomingCommand *) currentCommand; 867 | 868 | if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) 869 | { 870 | if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) 871 | continue; 872 | } 873 | else 874 | if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) 875 | break; 876 | 877 | if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber) 878 | { 879 | if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) 880 | break; 881 | 882 | goto discardCommand; 883 | } 884 | } 885 | break; 886 | 887 | case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: 888 | case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: 889 | unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber); 890 | 891 | if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && 892 | unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) 893 | goto discardCommand; 894 | 895 | for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); 896 | currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); 897 | currentCommand = enet_list_previous (currentCommand)) 898 | { 899 | incomingCommand = (ENetIncomingCommand *) currentCommand; 900 | 901 | if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) 902 | continue; 903 | 904 | if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) 905 | { 906 | if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) 907 | continue; 908 | } 909 | else 910 | if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) 911 | break; 912 | 913 | if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) 914 | break; 915 | 916 | if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber) 917 | continue; 918 | 919 | if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber) 920 | { 921 | if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) 922 | break; 923 | 924 | goto discardCommand; 925 | } 926 | } 927 | break; 928 | 929 | case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: 930 | currentCommand = enet_list_end (& channel -> incomingUnreliableCommands); 931 | break; 932 | 933 | default: 934 | goto discardCommand; 935 | } 936 | 937 | if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData) 938 | goto notifyError; 939 | 940 | packet = enet_packet_create (data, dataLength, flags); 941 | if (packet == NULL) 942 | goto notifyError; 943 | 944 | incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); 945 | if (incomingCommand == NULL) 946 | goto notifyError; 947 | 948 | incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber; 949 | incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF; 950 | incomingCommand -> command = * command; 951 | incomingCommand -> fragmentCount = fragmentCount; 952 | incomingCommand -> fragmentsRemaining = fragmentCount; 953 | incomingCommand -> packet = packet; 954 | incomingCommand -> fragments = NULL; 955 | 956 | if (fragmentCount > 0) 957 | { 958 | if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) 959 | incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); 960 | if (incomingCommand -> fragments == NULL) 961 | { 962 | enet_free (incomingCommand); 963 | 964 | goto notifyError; 965 | } 966 | memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32)); 967 | } 968 | 969 | if (packet != NULL) 970 | { 971 | ++ packet -> referenceCount; 972 | 973 | peer -> totalWaitingData += packet -> dataLength; 974 | } 975 | 976 | enet_list_insert (enet_list_next (currentCommand), incomingCommand); 977 | 978 | switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) 979 | { 980 | case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: 981 | case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: 982 | enet_peer_dispatch_incoming_reliable_commands (peer, channel); 983 | break; 984 | 985 | default: 986 | enet_peer_dispatch_incoming_unreliable_commands (peer, channel); 987 | break; 988 | } 989 | 990 | return incomingCommand; 991 | 992 | discardCommand: 993 | if (fragmentCount > 0) 994 | goto notifyError; 995 | 996 | if (packet != NULL && packet -> referenceCount == 0) 997 | enet_packet_destroy (packet); 998 | 999 | return & dummyCommand; 1000 | 1001 | notifyError: 1002 | if (packet != NULL && packet -> referenceCount == 0) 1003 | enet_packet_destroy (packet); 1004 | 1005 | return NULL; 1006 | } 1007 | 1008 | /** @} */ 1009 | -------------------------------------------------------------------------------- /enet/unix.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file unix.c 3 | @brief ENet Unix system specific functions 4 | */ 5 | #ifndef _WIN32 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define ENET_BUILDING_LIB 1 19 | #include "include/enet.h" 20 | 21 | #ifdef __APPLE__ 22 | #ifdef HAS_POLL 23 | #undef HAS_POLL 24 | #endif 25 | #ifndef HAS_FCNTL 26 | #define HAS_FCNTL 1 27 | #endif 28 | #ifndef HAS_INET_PTON 29 | #define HAS_INET_PTON 1 30 | #endif 31 | #ifndef HAS_INET_NTOP 32 | #define HAS_INET_NTOP 1 33 | #endif 34 | #ifndef HAS_MSGHDR_FLAGS 35 | #define HAS_MSGHDR_FLAGS 1 36 | #endif 37 | #ifndef HAS_SOCKLEN_T 38 | #define HAS_SOCKLEN_T 1 39 | #endif 40 | #ifndef HAS_GETADDRINFO 41 | #define HAS_GETADDRINFO 1 42 | #endif 43 | #ifndef HAS_GETNAMEINFO 44 | #define HAS_GETNAMEINFO 1 45 | #endif 46 | #endif 47 | 48 | #ifdef HAS_FCNTL 49 | #include 50 | #endif 51 | 52 | #ifdef HAS_POLL 53 | #include 54 | #endif 55 | 56 | #ifndef HAS_SOCKLEN_T 57 | #ifndef __socklen_t_defined 58 | //typedef int socklen_t; 59 | //typedef unsigned long socklen_t 60 | #endif 61 | #endif 62 | 63 | #ifndef MSG_NOSIGNAL 64 | #define MSG_NOSIGNAL 0 65 | #endif 66 | 67 | static enet_uint32 timeBase = 0; 68 | 69 | int 70 | enet_initialize (void) 71 | { 72 | return 0; 73 | } 74 | 75 | void 76 | enet_deinitialize (void) 77 | { 78 | } 79 | 80 | enet_uint32 81 | enet_host_random_seed (void) 82 | { 83 | return (enet_uint32) time (NULL); 84 | } 85 | 86 | enet_uint32 87 | enet_time_get (void) 88 | { 89 | struct timeval timeVal; 90 | 91 | gettimeofday (& timeVal, NULL); 92 | 93 | return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase; 94 | } 95 | 96 | void 97 | enet_time_set (enet_uint32 newTimeBase) 98 | { 99 | struct timeval timeVal; 100 | 101 | gettimeofday (& timeVal, NULL); 102 | 103 | timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase; 104 | } 105 | 106 | int 107 | enet_address_set_host_ip (ENetAddress * address, const char * name) 108 | { 109 | #ifdef HAS_INET_PTON 110 | if (! inet_pton (AF_INET, name, & address -> host)) 111 | #else 112 | if (! inet_aton (name, (struct in_addr *) & address -> host)) 113 | #endif 114 | return -1; 115 | 116 | return 0; 117 | } 118 | 119 | int 120 | enet_address_set_host (ENetAddress * address, const char * name) 121 | { 122 | #ifdef HAS_GETADDRINFO 123 | struct addrinfo hints, * resultList = NULL, * result = NULL; 124 | 125 | memset (& hints, 0, sizeof (hints)); 126 | hints.ai_family = AF_INET; 127 | 128 | if (getaddrinfo (name, NULL, NULL, & resultList) != 0) 129 | return -1; 130 | 131 | for (result = resultList; result != NULL; result = result -> ai_next) 132 | { 133 | if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in)) 134 | { 135 | struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr; 136 | 137 | address -> host = sin -> sin_addr.s_addr; 138 | 139 | freeaddrinfo (resultList); 140 | 141 | return 0; 142 | } 143 | } 144 | 145 | if (resultList != NULL) 146 | freeaddrinfo (resultList); 147 | #else 148 | struct hostent * hostEntry = NULL; 149 | #ifdef HAS_GETHOSTBYNAME_R 150 | struct hostent hostData; 151 | char buffer [2048]; 152 | int errnum; 153 | 154 | #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 155 | gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); 156 | #else 157 | hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); 158 | #endif 159 | #else 160 | hostEntry = gethostbyname (name); 161 | #endif 162 | 163 | if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET) 164 | { 165 | address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; 166 | 167 | return 0; 168 | } 169 | #endif 170 | 171 | return enet_address_set_host_ip (address, name); 172 | } 173 | 174 | int 175 | enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) 176 | { 177 | #ifdef HAS_INET_NTOP 178 | if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL) 179 | #else 180 | char * addr = inet_ntoa (* (struct in_addr *) & address -> host); 181 | if (addr != NULL) 182 | { 183 | size_t addrLen = strlen(addr); 184 | if (addrLen >= nameLength) 185 | return -1; 186 | memcpy (name, addr, addrLen + 1); 187 | } 188 | else 189 | #endif 190 | return -1; 191 | return 0; 192 | } 193 | 194 | int 195 | enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) 196 | { 197 | #ifdef HAS_GETNAMEINFO 198 | struct sockaddr_in sin; 199 | int err; 200 | 201 | memset (& sin, 0, sizeof (struct sockaddr_in)); 202 | 203 | sin.sin_family = AF_INET; 204 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 205 | sin.sin_addr.s_addr = address -> host; 206 | 207 | err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD); 208 | if (! err) 209 | { 210 | if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength)) 211 | return -1; 212 | return 0; 213 | } 214 | if (err != EAI_NONAME) 215 | return -1; 216 | #else 217 | struct in_addr in; 218 | struct hostent * hostEntry = NULL; 219 | #ifdef HAS_GETHOSTBYADDR_R 220 | struct hostent hostData; 221 | char buffer [2048]; 222 | int errnum; 223 | 224 | in.s_addr = address -> host; 225 | 226 | #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 227 | gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); 228 | #else 229 | hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum); 230 | #endif 231 | #else 232 | in.s_addr = address -> host; 233 | 234 | hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); 235 | #endif 236 | 237 | if (hostEntry != NULL) 238 | { 239 | size_t hostLen = strlen (hostEntry -> h_name); 240 | if (hostLen >= nameLength) 241 | return -1; 242 | memcpy (name, hostEntry -> h_name, hostLen + 1); 243 | return 0; 244 | } 245 | #endif 246 | 247 | return enet_address_get_host_ip (address, name, nameLength); 248 | } 249 | 250 | int 251 | enet_socket_bind (ENetSocket socket, const ENetAddress * address) 252 | { 253 | struct sockaddr_in sin; 254 | 255 | memset (& sin, 0, sizeof (struct sockaddr_in)); 256 | 257 | sin.sin_family = AF_INET; 258 | 259 | if (address != NULL) 260 | { 261 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 262 | sin.sin_addr.s_addr = address -> host; 263 | } 264 | else 265 | { 266 | sin.sin_port = 0; 267 | sin.sin_addr.s_addr = INADDR_ANY; 268 | } 269 | 270 | return bind (socket, 271 | (struct sockaddr *) & sin, 272 | sizeof (struct sockaddr_in)); 273 | } 274 | 275 | int 276 | enet_socket_get_address (ENetSocket socket, ENetAddress * address) 277 | { 278 | struct sockaddr_in sin; 279 | socklen_t sinLength = sizeof (struct sockaddr_in); 280 | 281 | if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) 282 | return -1; 283 | 284 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 285 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 286 | 287 | return 0; 288 | } 289 | 290 | int 291 | enet_socket_listen (ENetSocket socket, int backlog) 292 | { 293 | return listen (socket, backlog < 0 ? SOMAXCONN : backlog); 294 | } 295 | 296 | ENetSocket 297 | enet_socket_create (ENetSocketType type) 298 | { 299 | return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); 300 | } 301 | 302 | int 303 | enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) 304 | { 305 | int result = -1; 306 | switch (option) 307 | { 308 | case ENET_SOCKOPT_NONBLOCK: 309 | #ifdef HAS_FCNTL 310 | result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK)); 311 | #else 312 | result = ioctl (socket, FIONBIO, & value); 313 | #endif 314 | break; 315 | 316 | case ENET_SOCKOPT_BROADCAST: 317 | result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int)); 318 | break; 319 | 320 | case ENET_SOCKOPT_REUSEADDR: 321 | result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int)); 322 | break; 323 | 324 | case ENET_SOCKOPT_RCVBUF: 325 | result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int)); 326 | break; 327 | 328 | case ENET_SOCKOPT_SNDBUF: 329 | result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); 330 | break; 331 | 332 | case ENET_SOCKOPT_RCVTIMEO: 333 | { 334 | struct timeval timeVal; 335 | timeVal.tv_sec = value / 1000; 336 | timeVal.tv_usec = (value % 1000) * 1000; 337 | result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval)); 338 | break; 339 | } 340 | 341 | case ENET_SOCKOPT_SNDTIMEO: 342 | { 343 | struct timeval timeVal; 344 | timeVal.tv_sec = value / 1000; 345 | timeVal.tv_usec = (value % 1000) * 1000; 346 | result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval)); 347 | break; 348 | } 349 | 350 | case ENET_SOCKOPT_NODELAY: 351 | result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); 352 | break; 353 | 354 | default: 355 | break; 356 | } 357 | return result == -1 ? -1 : 0; 358 | } 359 | 360 | int 361 | enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) 362 | { 363 | int result = -1; 364 | socklen_t len; 365 | switch (option) 366 | { 367 | case ENET_SOCKOPT_ERROR: 368 | len = sizeof (int); 369 | result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len); 370 | break; 371 | 372 | default: 373 | break; 374 | } 375 | return result == -1 ? -1 : 0; 376 | } 377 | 378 | int 379 | enet_socket_connect (ENetSocket socket, const ENetAddress * address) 380 | { 381 | struct sockaddr_in sin; 382 | int result; 383 | 384 | memset (& sin, 0, sizeof (struct sockaddr_in)); 385 | 386 | sin.sin_family = AF_INET; 387 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 388 | sin.sin_addr.s_addr = address -> host; 389 | 390 | result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); 391 | if (result == -1 && errno == EINPROGRESS) 392 | return 0; 393 | 394 | return result; 395 | } 396 | 397 | ENetSocket 398 | enet_socket_accept (ENetSocket socket, ENetAddress * address) 399 | { 400 | int result; 401 | struct sockaddr_in sin; 402 | socklen_t sinLength = sizeof (struct sockaddr_in); 403 | 404 | result = accept (socket, 405 | address != NULL ? (struct sockaddr *) & sin : NULL, 406 | address != NULL ? & sinLength : NULL); 407 | 408 | if (result == -1) 409 | return ENET_SOCKET_NULL; 410 | 411 | if (address != NULL) 412 | { 413 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 414 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 415 | } 416 | 417 | return result; 418 | } 419 | 420 | int 421 | enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) 422 | { 423 | return shutdown (socket, (int) how); 424 | } 425 | 426 | void 427 | enet_socket_destroy (ENetSocket socket) 428 | { 429 | if (socket != -1) 430 | close (socket); 431 | } 432 | 433 | int 434 | enet_socket_send (ENetSocket socket, 435 | const ENetAddress * address, 436 | const ENetBuffer * buffers, 437 | size_t bufferCount) 438 | { 439 | struct msghdr msgHdr; 440 | struct sockaddr_in sin; 441 | int sentLength; 442 | 443 | memset (& msgHdr, 0, sizeof (struct msghdr)); 444 | 445 | if (address != NULL) 446 | { 447 | memset (& sin, 0, sizeof (struct sockaddr_in)); 448 | 449 | sin.sin_family = AF_INET; 450 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 451 | sin.sin_addr.s_addr = address -> host; 452 | 453 | msgHdr.msg_name = & sin; 454 | msgHdr.msg_namelen = sizeof (struct sockaddr_in); 455 | } 456 | 457 | msgHdr.msg_iov = (struct iovec *) buffers; 458 | msgHdr.msg_iovlen = bufferCount; 459 | 460 | sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL); 461 | 462 | if (sentLength == -1) 463 | { 464 | if (errno == EWOULDBLOCK) 465 | return 0; 466 | 467 | return -1; 468 | } 469 | 470 | return sentLength; 471 | } 472 | 473 | int 474 | enet_socket_receive (ENetSocket socket, 475 | ENetAddress * address, 476 | ENetBuffer * buffers, 477 | size_t bufferCount) 478 | { 479 | struct msghdr msgHdr; 480 | struct sockaddr_in sin; 481 | int recvLength; 482 | 483 | memset (& msgHdr, 0, sizeof (struct msghdr)); 484 | 485 | if (address != NULL) 486 | { 487 | msgHdr.msg_name = & sin; 488 | msgHdr.msg_namelen = sizeof (struct sockaddr_in); 489 | } 490 | 491 | msgHdr.msg_iov = (struct iovec *) buffers; 492 | msgHdr.msg_iovlen = bufferCount; 493 | 494 | recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL); 495 | 496 | if (recvLength == -1) 497 | { 498 | if (errno == EWOULDBLOCK) 499 | return 0; 500 | 501 | return -1; 502 | } 503 | 504 | #ifdef HAS_MSGHDR_FLAGS 505 | if (msgHdr.msg_flags & MSG_TRUNC) 506 | return -1; 507 | #endif 508 | 509 | if (address != NULL) 510 | { 511 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 512 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 513 | } 514 | 515 | return recvLength; 516 | } 517 | 518 | int 519 | enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout) 520 | { 521 | struct timeval timeVal; 522 | 523 | timeVal.tv_sec = timeout / 1000; 524 | timeVal.tv_usec = (timeout % 1000) * 1000; 525 | 526 | return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal); 527 | } 528 | 529 | int 530 | enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) 531 | { 532 | #ifdef HAS_POLL 533 | struct pollfd pollSocket; 534 | int pollCount; 535 | 536 | pollSocket.fd = socket; 537 | pollSocket.events = 0; 538 | 539 | if (* condition & ENET_SOCKET_WAIT_SEND) 540 | pollSocket.events |= POLLOUT; 541 | 542 | if (* condition & ENET_SOCKET_WAIT_RECEIVE) 543 | pollSocket.events |= POLLIN; 544 | 545 | pollCount = poll (& pollSocket, 1, timeout); 546 | 547 | if (pollCount < 0) 548 | { 549 | if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) 550 | { 551 | * condition = ENET_SOCKET_WAIT_INTERRUPT; 552 | 553 | return 0; 554 | } 555 | 556 | return -1; 557 | } 558 | 559 | * condition = ENET_SOCKET_WAIT_NONE; 560 | 561 | if (pollCount == 0) 562 | return 0; 563 | 564 | if (pollSocket.revents & POLLOUT) 565 | * condition |= ENET_SOCKET_WAIT_SEND; 566 | 567 | if (pollSocket.revents & POLLIN) 568 | * condition |= ENET_SOCKET_WAIT_RECEIVE; 569 | 570 | return 0; 571 | #else 572 | fd_set readSet, writeSet; 573 | struct timeval timeVal; 574 | int selectCount; 575 | 576 | timeVal.tv_sec = timeout / 1000; 577 | timeVal.tv_usec = (timeout % 1000) * 1000; 578 | 579 | FD_ZERO (& readSet); 580 | FD_ZERO (& writeSet); 581 | 582 | if (* condition & ENET_SOCKET_WAIT_SEND) 583 | FD_SET (socket, & writeSet); 584 | 585 | if (* condition & ENET_SOCKET_WAIT_RECEIVE) 586 | FD_SET (socket, & readSet); 587 | 588 | selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); 589 | 590 | if (selectCount < 0) 591 | { 592 | if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) 593 | { 594 | * condition = ENET_SOCKET_WAIT_INTERRUPT; 595 | 596 | return 0; 597 | } 598 | 599 | return -1; 600 | } 601 | 602 | * condition = ENET_SOCKET_WAIT_NONE; 603 | 604 | if (selectCount == 0) 605 | return 0; 606 | 607 | if (FD_ISSET (socket, & writeSet)) 608 | * condition |= ENET_SOCKET_WAIT_SEND; 609 | 610 | if (FD_ISSET (socket, & readSet)) 611 | * condition |= ENET_SOCKET_WAIT_RECEIVE; 612 | 613 | return 0; 614 | #endif 615 | } 616 | 617 | #endif 618 | 619 | -------------------------------------------------------------------------------- /enet/win32.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file win32.c 3 | @brief ENet Win32 system specific functions 4 | */ 5 | #ifdef _WIN32 6 | 7 | #define ENET_BUILDING_LIB 1 8 | #include "include/enet.h" 9 | #include 10 | #include 11 | 12 | #pragma warning(disable : 4996) 13 | 14 | static enet_uint32 timeBase = 0; 15 | 16 | int 17 | enet_initialize (void) 18 | { 19 | WORD versionRequested = MAKEWORD (1, 1); 20 | WSADATA wsaData; 21 | 22 | if (WSAStartup (versionRequested, & wsaData)) 23 | return -1; 24 | 25 | if (LOBYTE (wsaData.wVersion) != 1|| 26 | HIBYTE (wsaData.wVersion) != 1) 27 | { 28 | WSACleanup (); 29 | 30 | return -1; 31 | } 32 | 33 | timeBeginPeriod (1); 34 | 35 | return 0; 36 | } 37 | 38 | void 39 | enet_deinitialize (void) 40 | { 41 | timeEndPeriod (1); 42 | 43 | WSACleanup (); 44 | } 45 | 46 | enet_uint32 47 | enet_host_random_seed (void) 48 | { 49 | return (enet_uint32) timeGetTime (); 50 | } 51 | 52 | enet_uint32 53 | enet_time_get (void) 54 | { 55 | return (enet_uint32) timeGetTime () - timeBase; 56 | } 57 | 58 | void 59 | enet_time_set (enet_uint32 newTimeBase) 60 | { 61 | timeBase = (enet_uint32) timeGetTime () - newTimeBase; 62 | } 63 | 64 | int 65 | enet_address_set_host_ip (ENetAddress * address, const char * name) 66 | { 67 | enet_uint8 vals [4] = { 0, 0, 0, 0 }; 68 | int i; 69 | 70 | for (i = 0; i < 4; ++ i) 71 | { 72 | const char * next = name + 1; 73 | if (* name != '0') 74 | { 75 | long val = strtol (name, (char **) & next, 10); 76 | if (val < 0 || val > 255 || next == name || next - name > 3) 77 | return -1; 78 | vals [i] = (enet_uint8) val; 79 | } 80 | 81 | if (* next != (i < 3 ? '.' : '\0')) 82 | return -1; 83 | name = next + 1; 84 | } 85 | 86 | memcpy (& address -> host, vals, sizeof (enet_uint32)); 87 | return 0; 88 | } 89 | 90 | int 91 | enet_address_set_host (ENetAddress * address, const char * name) 92 | { 93 | struct hostent * hostEntry; 94 | 95 | hostEntry = gethostbyname (name); 96 | if (hostEntry == NULL || 97 | hostEntry -> h_addrtype != AF_INET) 98 | return enet_address_set_host_ip (address, name); 99 | 100 | address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; 101 | 102 | return 0; 103 | } 104 | 105 | int 106 | enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) 107 | { 108 | char * addr = inet_ntoa (* (struct in_addr *) & address -> host); 109 | if (addr == NULL) 110 | return -1; 111 | else 112 | { 113 | size_t addrLen = strlen(addr); 114 | if (addrLen >= nameLength) 115 | return -1; 116 | memcpy (name, addr, addrLen + 1); 117 | } 118 | return 0; 119 | } 120 | 121 | int 122 | enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) 123 | { 124 | struct in_addr in; 125 | struct hostent * hostEntry; 126 | 127 | in.s_addr = address -> host; 128 | 129 | hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); 130 | if (hostEntry == NULL) 131 | return enet_address_get_host_ip (address, name, nameLength); 132 | else 133 | { 134 | size_t hostLen = strlen (hostEntry -> h_name); 135 | if (hostLen >= nameLength) 136 | return -1; 137 | memcpy (name, hostEntry -> h_name, hostLen + 1); 138 | } 139 | 140 | return 0; 141 | } 142 | 143 | int 144 | enet_socket_bind (ENetSocket socket, const ENetAddress * address) 145 | { 146 | struct sockaddr_in sin; 147 | 148 | memset (& sin, 0, sizeof (struct sockaddr_in)); 149 | 150 | sin.sin_family = AF_INET; 151 | 152 | if (address != NULL) 153 | { 154 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 155 | sin.sin_addr.s_addr = address -> host; 156 | } 157 | else 158 | { 159 | sin.sin_port = 0; 160 | sin.sin_addr.s_addr = INADDR_ANY; 161 | } 162 | 163 | return bind (socket, 164 | (struct sockaddr *) & sin, 165 | sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; 166 | } 167 | 168 | int 169 | enet_socket_get_address (ENetSocket socket, ENetAddress * address) 170 | { 171 | struct sockaddr_in sin; 172 | int sinLength = sizeof (struct sockaddr_in); 173 | 174 | if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) 175 | return -1; 176 | 177 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 178 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 179 | 180 | return 0; 181 | } 182 | 183 | int 184 | enet_socket_listen (ENetSocket socket, int backlog) 185 | { 186 | return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; 187 | } 188 | 189 | ENetSocket 190 | enet_socket_create (ENetSocketType type) 191 | { 192 | return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); 193 | } 194 | 195 | int 196 | enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) 197 | { 198 | int result = SOCKET_ERROR; 199 | switch (option) 200 | { 201 | case ENET_SOCKOPT_NONBLOCK: 202 | { 203 | u_long nonBlocking = (u_long) value; 204 | result = ioctlsocket (socket, FIONBIO, & nonBlocking); 205 | break; 206 | } 207 | 208 | case ENET_SOCKOPT_BROADCAST: 209 | result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int)); 210 | break; 211 | 212 | case ENET_SOCKOPT_REUSEADDR: 213 | result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int)); 214 | break; 215 | 216 | case ENET_SOCKOPT_RCVBUF: 217 | result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int)); 218 | break; 219 | 220 | case ENET_SOCKOPT_SNDBUF: 221 | result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); 222 | break; 223 | 224 | case ENET_SOCKOPT_RCVTIMEO: 225 | result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); 226 | break; 227 | 228 | case ENET_SOCKOPT_SNDTIMEO: 229 | result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); 230 | break; 231 | 232 | case ENET_SOCKOPT_NODELAY: 233 | result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); 234 | break; 235 | 236 | default: 237 | break; 238 | } 239 | return result == SOCKET_ERROR ? -1 : 0; 240 | } 241 | 242 | int 243 | enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) 244 | { 245 | int result = SOCKET_ERROR, len; 246 | switch (option) 247 | { 248 | case ENET_SOCKOPT_ERROR: 249 | len = sizeof(int); 250 | result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); 251 | break; 252 | 253 | default: 254 | break; 255 | } 256 | return result == SOCKET_ERROR ? -1 : 0; 257 | } 258 | 259 | int 260 | enet_socket_connect (ENetSocket socket, const ENetAddress * address) 261 | { 262 | struct sockaddr_in sin; 263 | int result; 264 | 265 | memset (& sin, 0, sizeof (struct sockaddr_in)); 266 | 267 | sin.sin_family = AF_INET; 268 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 269 | sin.sin_addr.s_addr = address -> host; 270 | 271 | result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); 272 | if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) 273 | return -1; 274 | 275 | return 0; 276 | } 277 | 278 | ENetSocket 279 | enet_socket_accept (ENetSocket socket, ENetAddress * address) 280 | { 281 | SOCKET result; 282 | struct sockaddr_in sin; 283 | int sinLength = sizeof (struct sockaddr_in); 284 | 285 | result = accept (socket, 286 | address != NULL ? (struct sockaddr *) & sin : NULL, 287 | address != NULL ? & sinLength : NULL); 288 | 289 | if (result == INVALID_SOCKET) 290 | return ENET_SOCKET_NULL; 291 | 292 | if (address != NULL) 293 | { 294 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 295 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 296 | } 297 | 298 | return result; 299 | } 300 | 301 | int 302 | enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) 303 | { 304 | return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; 305 | } 306 | 307 | void 308 | enet_socket_destroy (ENetSocket socket) 309 | { 310 | if (socket != INVALID_SOCKET) 311 | closesocket (socket); 312 | } 313 | 314 | int 315 | enet_socket_send (ENetSocket socket, 316 | const ENetAddress * address, 317 | const ENetBuffer * buffers, 318 | size_t bufferCount) 319 | { 320 | struct sockaddr_in sin; 321 | DWORD sentLength; 322 | 323 | if (address != NULL) 324 | { 325 | memset (& sin, 0, sizeof (struct sockaddr_in)); 326 | 327 | sin.sin_family = AF_INET; 328 | sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); 329 | sin.sin_addr.s_addr = address -> host; 330 | } 331 | 332 | if (WSASendTo (socket, 333 | (LPWSABUF) buffers, 334 | (DWORD) bufferCount, 335 | & sentLength, 336 | 0, 337 | address != NULL ? (struct sockaddr *) & sin : NULL, 338 | address != NULL ? sizeof (struct sockaddr_in) : 0, 339 | NULL, 340 | NULL) == SOCKET_ERROR) 341 | { 342 | if (WSAGetLastError () == WSAEWOULDBLOCK) 343 | return 0; 344 | 345 | return -1; 346 | } 347 | 348 | return (int) sentLength; 349 | } 350 | 351 | int 352 | enet_socket_receive (ENetSocket socket, 353 | ENetAddress * address, 354 | ENetBuffer * buffers, 355 | size_t bufferCount) 356 | { 357 | INT sinLength = sizeof (struct sockaddr_in); 358 | DWORD flags = 0, 359 | recvLength; 360 | struct sockaddr_in sin; 361 | 362 | if (WSARecvFrom (socket, 363 | (LPWSABUF) buffers, 364 | (DWORD) bufferCount, 365 | & recvLength, 366 | & flags, 367 | address != NULL ? (struct sockaddr *) & sin : NULL, 368 | address != NULL ? & sinLength : NULL, 369 | NULL, 370 | NULL) == SOCKET_ERROR) 371 | { 372 | switch (WSAGetLastError ()) 373 | { 374 | case WSAEWOULDBLOCK: 375 | case WSAECONNRESET: 376 | return 0; 377 | } 378 | 379 | return -1; 380 | } 381 | 382 | if (flags & MSG_PARTIAL) 383 | return -1; 384 | 385 | if (address != NULL) 386 | { 387 | address -> host = (enet_uint32) sin.sin_addr.s_addr; 388 | address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); 389 | } 390 | 391 | return (int) recvLength; 392 | } 393 | 394 | int 395 | enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout) 396 | { 397 | struct timeval timeVal; 398 | 399 | timeVal.tv_sec = timeout / 1000; 400 | timeVal.tv_usec = (timeout % 1000) * 1000; 401 | 402 | return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal); 403 | } 404 | 405 | int 406 | enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) 407 | { 408 | fd_set readSet, writeSet; 409 | struct timeval timeVal; 410 | int selectCount; 411 | 412 | timeVal.tv_sec = timeout / 1000; 413 | timeVal.tv_usec = (timeout % 1000) * 1000; 414 | 415 | FD_ZERO (& readSet); 416 | FD_ZERO (& writeSet); 417 | 418 | if (* condition & ENET_SOCKET_WAIT_SEND) 419 | FD_SET (socket, & writeSet); 420 | 421 | if (* condition & ENET_SOCKET_WAIT_RECEIVE) 422 | FD_SET (socket, & readSet); 423 | 424 | selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); 425 | 426 | if (selectCount < 0) 427 | return -1; 428 | 429 | * condition = ENET_SOCKET_WAIT_NONE; 430 | 431 | if (selectCount == 0) 432 | return 0; 433 | 434 | if (FD_ISSET (socket, & writeSet)) 435 | * condition |= ENET_SOCKET_WAIT_SEND; 436 | 437 | if (FD_ISSET (socket, & readSet)) 438 | * condition |= ENET_SOCKET_WAIT_RECEIVE; 439 | 440 | return 0; 441 | } 442 | 443 | #endif 444 | 445 | -------------------------------------------------------------------------------- /linux.sh: -------------------------------------------------------------------------------- 1 | # If linux use yum 2 | if [ -f /etc/redhat-release ]; then 3 | sudo yum update -y && sudo yum upgrade -y # Update and Upgrade termux first 4 | sudo yum install -y build-essential # Install build-essential (for build .cpp and .c source code) 5 | g++ CPPBot.cpp enet/callbacks.c enet/compress.c enet/host.c enet/list.c enet/packet.c enet/peer.c enet/protocol.c enet/unix.c -Wall -std=c++11 -fpermissive -o gtbot -latomic #Build source code into executable 6 | echo "Build Successfully! you just do ./gtbot on terminal" 7 | fi 8 | 9 | # If linux use apt-get 10 | if [ -f /etc/lsb-release ]; then 11 | sudo apt-get update -y && sudo apt upgrade -y # Update and Upgrade termux first 12 | sudo apt-get install -y build-essential # Install build-essential (for build .cpp and .c source code) 13 | g++ CPPBot.cpp enet/callbacks.c enet/compress.c enet/host.c enet/list.c enet/packet.c enet/peer.c enet/protocol.c enet/unix.c -Wall -std=c++11 -fpermissive -o gtbot -latomic #Build source code into executable 14 | echo "Build Successfully! you just do ./gtbot on terminal" 15 | fi 16 | -------------------------------------------------------------------------------- /pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed 2 | 3 | #include "pch.h" 4 | #include "json.hpp" 5 | // In general, ignore this file, but keep it around if you are using pre-compiled headers. 6 | -------------------------------------------------------------------------------- /pch.h: -------------------------------------------------------------------------------- 1 | // Tips for Getting Started: 2 | // 1. Use the Solution Explorer window to add/manage files 3 | // 2. Use the Team Explorer window to connect to source control 4 | // 3. Use the Output window to see build output and other messages 5 | // 4. Use the Error List window to view errors 6 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 7 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 8 | 9 | #ifndef PCH_H 10 | #define PCH_H 11 | #include "json.hpp" 12 | // TODO: add headers that you want to pre-compile here 13 | 14 | #endif //PCH_H 15 | -------------------------------------------------------------------------------- /termux.sh: -------------------------------------------------------------------------------- 1 | # Same like Linux 2 | rm $PREFIX/etc/apt/sources.list && echo "deb https://termux.net stable main" >> $PREFIX/etc/apt/sources.list && apt-get update 3 | echo "export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib" >> ~/.bashrc && . ~/.bashrc 4 | apt install -y build-essential # Install build-essential (for build .cpp and .c source code) 5 | g++ CPPBot.cpp enet/callbacks.c enet/compress.c enet/host.c enet/list.c enet/packet.c enet/peer.c enet/protocol.c enet/unix.c -Wall -std=c++11 -fpermissive -o gtbot -latomic #Build source code into executable 6 | echo "Build Successfully! you just do ./gtbot on terminal" 7 | -------------------------------------------------------------------------------- /userfunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Grotopia Bot 4 | // Copyright (C) 2018 Growtopia Noobs 5 | // 6 | // This program is free software: you can redistribute it and/or modify 7 | // it under the terms of the GNU Affero General Public License as published 8 | // by the Free Software Foundation, either version 3 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU Affero General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU Affero General Public License 17 | // along with this program. If not, see . 18 | #include "json.hpp" 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "utilsfunc.h" 30 | #include "corefunc.h" 31 | #include "userfunc.h" 32 | #include "enet/include/enet.h" 33 | 34 | //#define WORLD_GO 35 | 36 | using namespace std; 37 | 38 | 39 | 40 | char hexmap[] = { '0', '1', '2', '3', '4', '5', '6', '7', 41 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 42 | 43 | std::string hexStr(unsigned char data) 44 | { 45 | std::string s(2, ' '); 46 | s[0] = hexmap[(data & 0xF0) >> 4]; 47 | s[1] = hexmap[data & 0x0F]; 48 | return s; 49 | } 50 | 51 | string generateMeta() 52 | { 53 | string x; 54 | for (int i = 0; i < 9; i++) 55 | { 56 | x += hexStr(rand()); 57 | } 58 | x += ".com"; 59 | return x; 60 | } 61 | 62 | string generateMac() 63 | { 64 | string x; 65 | for (int i = 0; i < 6; i++) 66 | { 67 | x += hexStr(rand()); 68 | if (i != 5) 69 | x += ":"; 70 | } 71 | return x; 72 | } 73 | 74 | string generateRid() 75 | { 76 | string x; 77 | for (int i = 0; i < 16; i++) 78 | { 79 | x += hexStr(rand()); 80 | } 81 | for (auto & c : x) c = toupper(c); 82 | return x; 83 | } 84 | 85 | string stripMessage(string msg) { 86 | regex e("\\x60[a-zA-Z0-9!@#$%^&*()_+\\-=\\[\\]\\{};':\"\\\\|,.<>\\/?]"); 87 | string result = regex_replace(msg, e, ""); 88 | result.erase(std::remove(result.begin(), result.end(), '`'), result.end()); 89 | return result; 90 | } 91 | 92 | void GrowtopiaBot::onLoginRequested() 93 | { 94 | cout << "Logging on..." << endl; 95 | string token; 96 | if (!login_user && !login_token) { 97 | token = ""; 98 | } else { 99 | token = "\nuser|" + std::to_string(login_user) + "\ntoken|" + std::to_string(login_token); 100 | } 101 | string ver = gameVersion; 102 | string hash = std::to_string((unsigned int)rand()); 103 | string hash2 = std::to_string((unsigned int)rand()); 104 | string packet = "tankIDName|" + uname + "\ntankIDPass|" + upass + "\nrequestedName|SmileZero\nf|1\nprotocol|84\ngame_version|" + ver + "\nfz|5367464\nlmode|0\ncbits|0\nplayer_age|18\nGDPR|1\nhash2|" + hash2 + "\nmeta|" + generateMeta() + "\nfhash|-716928004\nrid|" + generateRid() + "\nplatformID|0\ndeviceVersion|0\ncountry|us\nhash|" + hash + "\nmac|" + generateMac() + "\nwk|" + generateRid() + "\nzf|-496303939" + token; 105 | cout << packet; 106 | SendPacket(2, "tankIDName|" + uname + "\ntankIDPass|" + upass + "\nrequestedName|SmileZero\nf|1\nprotocol|84\ngame_version|" + ver + "\nfz|5367464\nlmode|0\ncbits|0\nplayer_age|18\nGDPR|1\nhash2|" + hash2 + "\nmeta|" + generateMeta() + "\nfhash|-716928004\nrid|" + generateRid() + "\nplatformID|0\ndeviceVersion|0\ncountry|us\nhash|" + hash + "\nmac|" + generateMac() + "\nwk|" + generateRid() + "\nzf|-496303939" + token, peer); 107 | 108 | currentWorld = ""; 109 | } 110 | 111 | void GrowtopiaBot::packet_type3(string text) 112 | { 113 | dbgPrint("Some text is here: " + text); 114 | if (text.find("LOGON ATTEMPTS") != string::npos) 115 | { 116 | cout << "Wrong username / password!. (LOGON ATTEMPTS)"; 117 | } 118 | if (text.find("password is wrong") != string::npos) 119 | { 120 | cout << "Wrong password!"; 121 | } 122 | if (text.find("action|logon_fail") != string::npos) 123 | { 124 | connectClient(); 125 | objects.clear(); 126 | currentWorld = ""; 127 | } 128 | } 129 | 130 | void GrowtopiaBot::packet_type6(string text) 131 | { 132 | //dbgPrint("Some text is here: " + text); 133 | SendPacket(2, "action|enter_game\n", peer); 134 | enet_host_flush(client); 135 | } 136 | 137 | void GrowtopiaBot::packet_unknown(ENetPacket* packet) 138 | { 139 | dbgPrint("Got unknown packet type: " + std::to_string(GetMessageTypeFromPacket(packet))); 140 | dbgPrint("Packet size is " + std::to_string(packet->dataLength)); 141 | } 142 | 143 | void GrowtopiaBot::OnSendToServer(string address, int port, int userId, int token) 144 | { 145 | login_user = userId; 146 | login_token = token; 147 | connectClient(address, port); 148 | } 149 | 150 | void GrowtopiaBot::OnConsoleMessage(string message) { 151 | cout << "Found console message: " << endl; 152 | string strippedMessage = stripMessage(message); 153 | cout << strippedMessage << endl; 154 | 155 | if (strippedMessage.find("MSG") != std::string::npos) { 156 | cout << "Found message!" << endl; 157 | } 158 | 159 | cout << "------------------------" << endl; 160 | } 161 | 162 | void GrowtopiaBot::OnPlayPositioned(string sound) 163 | { 164 | 165 | } 166 | 167 | void GrowtopiaBot::OnSetFreezeState(int state) 168 | { 169 | 170 | } 171 | 172 | void GrowtopiaBot::OnRemove(string data) // "netID|x\n" 173 | { 174 | std::stringstream ss(data.c_str()); 175 | std::string to; 176 | int netID = -1; 177 | while (std::getline(ss, to, '\n')) { 178 | string id = to.substr(0, to.find("|")); 179 | string act = to.substr(to.find("|") + 1, to.length() - to.find("|")); 180 | if (id == "netID") 181 | { 182 | netID = atoi(act.c_str()); 183 | } 184 | else { 185 | dbgPrint(id + "!!!!!!!!!!!" + act); 186 | } 187 | } 188 | for (ObjectData& objectData : objects) 189 | { 190 | if (objectData.netId == netID) 191 | { 192 | objectData.isGone = true; 193 | } 194 | } 195 | //SendPacket(2, "action|input\n|text|Bye bye ::((", peer); 196 | } 197 | 198 | void GrowtopiaBot::OnSpawn(string data) 199 | { 200 | std::stringstream ss(data.c_str()); 201 | std::string to; 202 | cout << data; 203 | ObjectData objectData; 204 | bool actuallyOwner = false; 205 | 206 | while (std::getline(ss, to, '\n')) { 207 | string id = to.substr(0, to.find("|")); 208 | string act = to.substr(to.find("|") + 1, to.length() - to.find("|") - 1); 209 | if (id == "country") 210 | { 211 | objectData.country = act; 212 | } 213 | else if (id == "name") 214 | { 215 | if (stripMessage(act) == ownerUsername) actuallyOwner = true; 216 | objectData.name = act; 217 | } 218 | else if (id == "netID") 219 | { 220 | if (actuallyOwner) owner = atoi(act.c_str()); 221 | objectData.netId = atoi(act.c_str()); 222 | } 223 | else if (id == "userID") 224 | { 225 | objectData.userId = atoi(act.c_str()); 226 | } 227 | else if (id == "posXY") 228 | { 229 | int x = atoi(act.substr(0, to.find("|")).c_str()); 230 | int y = atoi(act.substr(act.find("|") + 1, act.length() - act.find("|") - 1).c_str()); 231 | objectData.x = x; 232 | objectData.y = y; 233 | } 234 | else if (id == "type") 235 | { 236 | if (act == "local") 237 | objectData.isLocal = true; 238 | } 239 | else if (act != "0" && (id == "invis" || id == "mstate" || id == "smstate")) 240 | { 241 | cout << "Some fishy boy is here: " << objectData.name << "; " << objectData.country << "; " << objectData.userId << "; " << objectData.netId << "; " << endl; 242 | objectData.isMod = true; 243 | } 244 | } 245 | 246 | if (actuallyOwner) cout << "Owner netID has been updated to " << objectData.netId << " username is " << ownerUsername; 247 | objects.push_back(objectData); 248 | //SendPacket(2, "action|input\n|text|`3Hello " + name + " `3with id " + netid + " from " + country + "! Your Growtopia ID is "+uid, peer); 249 | } 250 | 251 | void GrowtopiaBot::OnAction(string command) 252 | { 253 | //SendPacket(2, "action|input\n|text|Why do you "+command.substr(1, command.length())+"?", peer); 254 | } 255 | 256 | void GrowtopiaBot::SetHasGrowID(int state, string name, string password) 257 | { 258 | 259 | } 260 | 261 | void GrowtopiaBot::SetHasAccountSecured(int state) 262 | { 263 | 264 | } 265 | 266 | void GrowtopiaBot::OnTalkBubble(int netID, string bubbleText, int type) 267 | { 268 | if (netID != owner) return; 269 | cout << bubbleText << endl; 270 | if (bubbleText.find("!pos") != string::npos) 271 | { 272 | for (ObjectData x : objects) 273 | { 274 | if (owner == x.netId) 275 | { 276 | SendPacket(2, "action|input\n|text|Owner pos is " + std::to_string(x.x) + ":" + std::to_string(x.y) + ".", peer); 277 | } 278 | } 279 | } 280 | if (bubbleText.find("!follow") != string::npos) 281 | { 282 | isFollowing = true; 283 | } 284 | if (bubbleText.find("!stop") != string::npos) 285 | { 286 | isFollowing = false; 287 | } 288 | if (bubbleText.find("!dance") != string::npos) 289 | { 290 | SendPacket(2, "action|input\n|text|/dance", peer); 291 | } 292 | if (bubbleText.find("!about") != string::npos || bubbleText.find("!help") != string::npos) 293 | { 294 | SendPacket(2, "action|input\n|text|This is bot from Growtopia Noobs. Modified my DrOreo002", peer); 295 | } 296 | } 297 | 298 | void GrowtopiaBot::SetRespawnPos(int respawnPos) 299 | { 300 | respawnX = respawnPos % 100; // hacky!!! TODO: get from world data (100) 301 | respawnY = respawnPos / 100; // hacky!!! TODO: get from world data (100) 302 | } 303 | 304 | void GrowtopiaBot::OnEmoticonDataChanged(int val1, string emoticons) 305 | { 306 | 307 | } 308 | 309 | void GrowtopiaBot::OnSetPos(float x, float y) 310 | { 311 | 312 | } 313 | 314 | void GrowtopiaBot::OnAddNotification(string image, string message, string audio, int val1) // You will see that when banned :( 315 | { 316 | 317 | } 318 | 319 | /* 320 | 321 | void GrowtopiaBot::OnFailedToEnterWorld() 322 | { 323 | 324 | } 325 | 326 | void GrowtopiaBot::OnSuperMainStartAcceptLogonFB211131ddf(int val1, string domain, string folder, string deniedApps, string settings) 327 | { 328 | 329 | } 330 | 331 | void GrowtopiaBot::OnSetBux(int val1, int val2, int val3) // missing params 332 | { 333 | 334 | } 335 | 336 | void GrowtopiaBot::OnZoomCamera(float val1, int val2) 337 | { 338 | 339 | } 340 | 341 | void GrowtopiaBot::OnGuildDataChanged(int val1, int val2, int val3, int val4) 342 | { 343 | 344 | } 345 | 346 | void GrowtopiaBot::OnFactionDataChanged(int val1, int val2, int val3, string data) 347 | { 348 | 349 | } 350 | 351 | void GrowtopiaBot::OnSetClothing(int hair, int shirt, int pants, int feet, int face, int hand, int back, int mask, int necklace, int val1, int val2, int val3, int val4) 352 | { 353 | 354 | }*/ 355 | 356 | void GrowtopiaBot::AtApplyTileDamage(int x, int y, int damge) 357 | { 358 | cout << "Damage " + std::to_string(damge) + " applied at X:" + std::to_string(x) + " Y: " + std::to_string(y) << endl; 359 | } 360 | 361 | void GrowtopiaBot::AtApplyLock(int x, int y, int itemId) // ApplyLockFromGamePacket TODO: *(int*)(data + 4) 362 | { 363 | SendPacket(2, "action|input\n|text|Lock " + std::to_string(itemId) + " applied at X:" + std::to_string(x) + " Y: " + std::to_string(y), peer); 364 | } 365 | 366 | void GrowtopiaBot::AtPlayerMoving(PlayerMoving* data) 367 | { 368 | int object = -1; 369 | //cout << std::hex << data->characterState << "; " << data->x << "; " << data->y << "; "<< data->XSpeed << "; "<< data->plantingTree << endl; 370 | for (int i = 0; i < objects.size(); i++) 371 | { 372 | if (objects.at(i).netId == data->netID) 373 | { 374 | object = i; 375 | } 376 | } 377 | if (object != -1) 378 | { 379 | objects[object].x = data->x; 380 | objects[object].y = data->y; 381 | } 382 | if (isFollowing && data->netID == owner && data->punchX == -1 && data->punchY == -1 && data->plantingTree == 0) // <--- bypass - can get banned from character state!!!, replacing isnt enought 383 | { 384 | if (backwardWalk) 385 | data->characterState ^= 0x10; 386 | if ((data->characterState & 0x800) && (data->characterState & 0x100)) { 387 | SendPacket(2, "action|respawn", peer); 388 | } 389 | for (int i = 0; i < objects.size(); i++) 390 | if (objects.at(i).isLocal) { 391 | objects.at(i).x = data->x; 392 | objects.at(i).y = data->y; 393 | } 394 | SendPacketRaw(4, packPlayerMoving(data), 56, 0, peer, ENET_PACKET_FLAG_RELIABLE); 395 | } 396 | } 397 | 398 | void GrowtopiaBot::AtAvatarSetIconState(int netID, int state) // if player goes BRB, etc... 399 | { 400 | 401 | } 402 | 403 | void GrowtopiaBot::WhenConnected() 404 | { 405 | cout << "Connected to server!" << endl; 406 | } 407 | 408 | void GrowtopiaBot::WhenDisconnected() 409 | { 410 | cout << "Disconnected from server..." << endl; 411 | connectClient(); 412 | } 413 | 414 | int counter = 0; // 10ms per step 415 | 416 | vector explode(const string &delimiter, const string &str) 417 | { 418 | vector arr; 419 | 420 | int strleng = str.length(); 421 | int delleng = delimiter.length(); 422 | if (delleng == 0) 423 | return arr;//no change 424 | 425 | int i = 0; 426 | int k = 0; 427 | while (i < strleng) 428 | { 429 | int j = 0; 430 | while (i + j < strleng && j < delleng && str[i + j] == delimiter[j]) 431 | j++; 432 | if (j == delleng)//found delimiter 433 | { 434 | arr.push_back(str.substr(k, i - k)); 435 | i += delleng; 436 | k = i; 437 | } 438 | else 439 | { 440 | i++; 441 | } 442 | } 443 | arr.push_back(str.substr(k, i - k)); 444 | return arr; 445 | } 446 | 447 | void GrowtopiaBot::userLoop() { 448 | if (timeFromWorldEnter > 200 && currentWorld != worldName) { 449 | if (worldName == "" || worldName == "-") { 450 | timeFromWorldEnter = 0; 451 | } else { 452 | SendPacket(3, "action|join_request\nname|" + worldName, peer); // MARRKS 453 | objects.clear(); 454 | } 455 | timeFromWorldEnter = 0; 456 | currentWorld = worldName; 457 | } 458 | timeFromWorldEnter++; 459 | counter++; 460 | if ((counter % 1800) == 0) 461 | { 462 | string name = ""; 463 | float distance = std::numeric_limits::infinity(); 464 | float ownerX; 465 | float ownerY; 466 | for (ObjectData x : objects) 467 | { 468 | if (x.netId == owner) 469 | { 470 | ownerX = x.x; 471 | ownerY = x.y; 472 | } 473 | } 474 | } 475 | } 476 | 477 | void GrowtopiaBot::userInit() { 478 | connectClient(); 479 | cout << flush; 480 | } 481 | 482 | void GrowtopiaBot::respawn() 483 | { 484 | PlayerMoving data; 485 | data.characterState = 0x924; // animation 486 | SendPacket(2, "action|respawn", peer); // respawn request 487 | for (int i = 0; i < objects.size(); i++) 488 | if (objects.at(i).isLocal) 489 | { 490 | data.x = objects.at(i).x; 491 | data.y = objects.at(i).y; 492 | data.netID = objects.at(i).netId; 493 | SendPacketRaw(4, packPlayerMoving(&data), 56, 0, peer, ENET_PACKET_FLAG_RELIABLE); 494 | cout << "Send" << endl; 495 | break; 496 | } 497 | } 498 | -------------------------------------------------------------------------------- /utilsfunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | //#include 5 | #include "json.hpp" 6 | using namespace std; 7 | 8 | namespace patch 9 | { 10 | template < typename T > std::string to_string(const T& n) 11 | { 12 | std::ostringstream stm; 13 | stm << n; 14 | return stm.str(); 15 | } 16 | } 17 | 18 | int GetApp() 19 | { 20 | return 0xA2Cu; 21 | } 22 | 23 | unsigned int HashString(const char *str, int len) 24 | { 25 | if (!str) return 0; 26 | 27 | unsigned char *n = (unsigned char *)str; 28 | unsigned int acc = 0x55555555; 29 | 30 | if (len == 0) 31 | { 32 | while (*n) 33 | acc = (acc >> 27) + (acc << 5) + *n++; 34 | } 35 | else 36 | { 37 | for (int i = 0; i < len; i++) 38 | { 39 | acc = (acc >> 27) + (acc << 5) + *n++; 40 | } 41 | } 42 | return acc; 43 | } 44 | 45 | int GetDeviceHash(string deviceId) 46 | { 47 | string v8 = deviceId; 48 | int v3; 49 | v8 += patch::to_string(GetApp() + 2280); 50 | v8 += "RT"; 51 | v3 = HashString(v8.c_str(), 0); 52 | return v3; 53 | } 54 | 55 | 56 | int GetDeviceSecondaryHash(string macAddr) 57 | { 58 | int v1; 59 | string v3 = ""; 60 | for (std::string::size_type i = 0; i < macAddr.length(); ++i) 61 | v3 += tolower(macAddr[i]); 62 | v3 += "RT"; 63 | v1 = HashString(v3.c_str(), 0); 64 | return v1; 65 | } 66 | 67 | string createLoginData(string swearFilter, string protocol, string gameVer, string fz, string lmode, string 68 | 69 | cbits, string hash2, string meta, string fhash, string rid, string platformID, string deviceVersion, string 70 | 71 | country, string hash, string mac, string wk) 72 | { 73 | string loginPacket; 74 | loginPacket = "f|"; 75 | loginPacket += swearFilter; 76 | loginPacket += "\n"; 77 | loginPacket += "protocol|"; 78 | loginPacket += protocol; 79 | loginPacket += "\n"; 80 | loginPacket += "game_version|"; 81 | loginPacket += gameVer; 82 | loginPacket += "\n"; 83 | loginPacket += "fz|"; 84 | loginPacket += fz; 85 | loginPacket += "\n"; 86 | loginPacket += "lmode|"; 87 | loginPacket += lmode; 88 | loginPacket += "\n"; 89 | loginPacket += "cbits|"; 90 | loginPacket += cbits; 91 | loginPacket += "\n"; 92 | loginPacket += "hash2|"; 93 | loginPacket += hash2; 94 | loginPacket += "\n"; 95 | loginPacket += "meta|"; 96 | loginPacket += meta; 97 | loginPacket += "\n"; 98 | loginPacket += "fhash|"; 99 | loginPacket += fhash; 100 | loginPacket += "\n"; 101 | loginPacket += "rid|"; 102 | loginPacket += rid; 103 | loginPacket += "\n"; 104 | loginPacket += "platformID|"; 105 | loginPacket += platformID; 106 | loginPacket += "\n"; 107 | loginPacket += "deviceVersion|"; 108 | loginPacket += deviceVersion; 109 | loginPacket += "\n"; 110 | loginPacket += "country|"; 111 | loginPacket += country; 112 | loginPacket += "\n"; 113 | loginPacket += "hash|"; 114 | loginPacket += hash; 115 | loginPacket += "\n"; 116 | loginPacket += "mac|"; 117 | loginPacket += mac; 118 | loginPacket += "\n"; 119 | loginPacket += "wk|"; 120 | loginPacket += wk; 121 | loginPacket += "\n"; 122 | return loginPacket; 123 | } 124 | 125 | /*void SendPacketRaw(int a1, void *a2, size_t a3, void *a4, ENetPeer* a5, int a6) 126 | { 127 | ENetPacket *v6; 128 | ENetPacket *v7; 129 | 130 | if (a5) 131 | { 132 | if (a1 == 4 && *((BYTE *)a2 + 12) & 8) 133 | { 134 | v7 = enet_packet_create(0, a3 + *((DWORD *)a2 + 13) + 5, a6); 135 | *(DWORD *)v7->data = 4; 136 | memcpy((char *)v7->data + 4, a2, a3); 137 | memcpy((char *)v7->data + a3 + 4, a4, *((DWORD *)a2 + 13)); 138 | enet_peer_send(a5, 0, v7); 139 | } 140 | else 141 | { 142 | v6 = enet_packet_create(0, a3 + 5, a6); 143 | *(DWORD *)v6->data = a1; 144 | memcpy((char *)v6->data + 4, a2, a3); 145 | enet_peer_send(a5, 0, v6); 146 | } 147 | } 148 | }*/ 149 | 150 | 151 | char* CreateGameUpdatePacketWithExtraDataAtEnd(int a1) 152 | { 153 | char* result = new char[a1 + 56]; 154 | 155 | *(DWORD *)result = 0; 156 | *(DWORD *)(result + 4) = 0; 157 | *(DWORD *)(result + 8) = 0; 158 | *(DWORD *)(result + 12) = 8; 159 | *(DWORD *)(result + 16) = 0; 160 | *(DWORD *)(result + 20) = 0; 161 | *(DWORD *)(result + 24) = 0; 162 | *(DWORD *)(result + 28) = 0; 163 | *(DWORD *)(result + 32) = 0; 164 | *(DWORD *)(result + 36) = 0; 165 | *(DWORD *)(result + 40) = 0; 166 | *(DWORD *)(result + 44) = 0; 167 | *(DWORD *)(result + 48) = 0; 168 | *(DWORD *)(result + 52) = a1; 169 | return result; 170 | } 171 | 172 | 173 | 174 | std::string colorstr(string str) 175 | { 176 | string chrs = "0123456789bwpo^$#@!qertas"; 177 | string s; 178 | for (int i = 0; i < str.length(); i++) 179 | { 180 | s += "`"; 181 | char* x; 182 | x = (char*)malloc(2); 183 | x[0] = chrs[rand() % chrs.length()]; 184 | x[1] = 0; 185 | string y = x; 186 | s += y; 187 | free(x); 188 | s += str[i]; 189 | } 190 | return s; 191 | } 192 | 193 | std::string colorstr2(string str) 194 | { 195 | string chrs = "0123456789bwpo^$#@!qertas"; 196 | char* x; 197 | x = (char*)malloc(2); 198 | x[0] = chrs[rand() % chrs.length()]; 199 | x[1] = 0; 200 | string y = x; 201 | free(x); 202 | return "`" + y + str; 203 | } 204 | 205 | 206 | /*string text_encode(char* text) 207 | { 208 | string ret = ""; 209 | while (text[0] != 0) 210 | { 211 | switch (text[0]) 212 | { 213 | case '\n': 214 | ret += "\\n"; 215 | break; 216 | case '\t': 217 | ret += "\\t"; 218 | break; 219 | case '\b': 220 | ret += "\\b"; 221 | break; 222 | case '\\': 223 | ret += "\\\\"; 224 | break; 225 | case '\r': 226 | ret += "\\r"; 227 | break; 228 | default: 229 | ret += text[0]; 230 | break; 231 | } 232 | text++; 233 | } 234 | return ret; 235 | }*/ 236 | --------------------------------------------------------------------------------