1 /** 2 Copyright: Copyright (c) 2014-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module netlib.baseclient; 8 9 import core.thread; 10 import std.conv : to; 11 import std.string : toStringz; 12 import std.experimental.logger; 13 14 import derelict.enet.enet; 15 16 import netlib.connection; 17 18 abstract class BaseClient : Connection 19 { 20 ENetAddress serverAddress; 21 ENetPeer* server; 22 bool isConnecting; 23 bool isConnected; 24 25 void connect(string address, ushort port) 26 { 27 ENetAddress addr; 28 enet_address_set_host(&addr, address.toStringz); 29 addr.port = port; 30 31 if (isConnecting) 32 { 33 if (addr == serverAddress) 34 { 35 return; 36 } 37 else 38 { 39 disconnect(); 40 } 41 } 42 serverAddress = addr; 43 connect(); 44 } 45 46 void connect() 47 { 48 server = enet_host_connect(host, &serverAddress, 2, 42); 49 //enet_peer_timeout(server, 0, 0, 5000); 50 51 if (server is null) 52 { 53 error("An error occured while trying to create an ENet server peer"); 54 return; 55 } 56 57 isConnecting = true; 58 } 59 60 void disconnect() 61 { 62 if (isConnecting) 63 { 64 enet_peer_disconnect_now(server, 0); 65 isConnecting = false; 66 } 67 else 68 { 69 enet_peer_disconnect(server, 0); 70 } 71 } 72 73 void send(ubyte[] data, ubyte channel = 0) 74 { 75 if (!isRunning) return; 76 ENetPacket* packet = enet_packet_create(data.ptr, data.length, 77 ENET_PACKET_FLAG_RELIABLE); 78 enet_peer_send(server, channel, packet); 79 } 80 81 void send(P)(auto ref const(P) packet, ubyte channel = 0) 82 if (is(P == struct)) 83 { 84 if (packetId!P >= packetArray.length) 85 { 86 infof("Dropping packet %s: %s", P.stringof, packetId!P); 87 return; 88 } 89 90 send(createPacket(packet), channel); 91 } 92 93 // Set id mapping for packets 94 void setPacketMap(string[] packetNames) 95 { 96 import std.algorithm : countUntil, remove, SwapStrategy; 97 98 PacketInfo*[] newPacketArray; 99 newPacketArray.reserve(packetNames.length); 100 101 static bool pred(PacketInfo* packetInfo, string packetName) 102 { 103 return packetInfo.name == packetName; 104 } 105 106 foreach(i, packetName; packetNames) 107 { 108 ptrdiff_t index = countUntil!pred(packetArray, packetName); 109 size_t newId = newPacketArray.length; 110 111 if (index > -1) 112 { 113 newPacketArray ~= packetArray[index]; 114 remove!(SwapStrategy.unstable)(packetArray, index); 115 } 116 else 117 { 118 newPacketArray ~= new PacketInfo(packetName); 119 } 120 newPacketArray[$-1].id = newId; 121 } 122 123 packetArray = newPacketArray; 124 } 125 126 override void update() 127 { 128 ENetEvent event; 129 while (enet_host_service(host, &event, 0) > 0) 130 { 131 final switch (event.type) 132 { 133 case ENET_EVENT_TYPE_NONE: 134 break; 135 case ENET_EVENT_TYPE_CONNECT: 136 isConnecting = false; 137 isConnected = true; 138 onConnect(event); 139 break; 140 case ENET_EVENT_TYPE_RECEIVE: 141 onPacketReceived(event); 142 break; 143 case ENET_EVENT_TYPE_DISCONNECT: 144 onDisconnect(event); 145 isConnecting = false; 146 isConnected = false; 147 break; 148 } 149 } 150 } 151 }