/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include "network_enet/enet_network.h" #include "nstring/nstring.h" #include "thread/mutex.h" #include "log/log.h" using GS::String; using namespace GS::Network; //------------------------------------------------------------------------------ void Enet::GetStatistics(Statistics &stat) { stat.received_data = host->totalReceivedData; stat.sent_data = host->totalSentData; } int Enet::GetPeerPacketLossRatio(void *peer) { ENetPeer *enet_peer = (ENetPeer *)peer; return enet_peer && enet_peer->packetsSent ? (enet_peer->packetsLost * 100) / enet_peer->packetsSent : 0; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Enet::SetPeerTimeout(void *peer, Timeout timeout) { int k = 1; switch (timeout) { case TimeoutLong: k = 2; break; case TimeoutVeryLong: k = 4; break; default: break; } enet_peer_timeout((ENetPeer *)peer, ENET_PEER_TIMEOUT_LIMIT * k, ENET_PEER_TIMEOUT_MINIMUM * k, ENET_PEER_TIMEOUT_MAXIMUM * k); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Enet::UpdateHost() { if (host) { ENetEvent event; while (enet_host_service(host, &event, 0) > 0) switch (event.type) { case ENET_EVENT_TYPE_CONNECT: OnPeerConnection(event.peer); break; case ENET_EVENT_TYPE_RECEIVE: OnPacketReceived(event.peer, (void *)event.packet->data, (size_t)event.packet->dataLength); enet_packet_destroy(event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: OnConnectionClosed(event.peer); break; default: break; } } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Enet::Close() { if (host) enet_host_destroy(host); host = NULL; } bool Enet::OpenServer(const char *hostname, int port) { Close(); ENetAddress address; if (hostname) enet_address_set_host(&address, hostname); else address.host = ENET_HOST_ANY; address.port = (enet_uint16)port; __LOG__ << "Starting server on " << (hostname ? hostname : "ANY") << ":" << port << "... "; if ((host = enet_host_create(&address, 4, 0, 0, 0)) != NULL) __LOG__ << "OK\n"; else __LOG__ << "FAILED\n"; /* if (host) enet_host_compress_with_range_coder(host); */ return asbool(host); } bool Enet::OpenClient(const char *hostname, int port) { Close(); if ((host = enet_host_create(NULL, 1, 0, 0, 0)) == NULL) return false; // enet_host_compress_with_range_coder(host); ENetAddress address; enet_address_set_host(&address, hostname); address.port = (enet_uint16)port; // Connect on one channel to server. __LOG__ << "Opening client connection to " << hostname << ":" << port << "... "; bool r = asbool(enet_host_connect(host, &address, 1, 0)); if (r) __LOG__ << "OK.\n"; else __LOG__ << "FAILED\n"; return r; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool Enet::GetHostAddress(String &address) { if (host) { char ip[64]; if (enet_address_get_host_ip(&((ENetHost *)host)->address, ip, 63) < 0) return false; address = ip; } return true; } bool Enet::GetPeerAddress(void *peer, String &address) { if (peer) { char ip[64]; if (enet_address_get_host_ip(&((ENetPeer *)peer)->address, ip, 63) < 0) return false; address = ip; } return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool Enet::Send(void *peer, const void *data, size_t size) { // __LOG_V__ << "Send Enet packet of " << size << " bytes.\n"; ENetPacket *packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE); if (!packet || enet_peer_send((ENetPeer *)peer, 0, packet)) return false; enet_host_flush(host); return true; } bool Enet::Broadcast(const void *data, size_t size) { ENetPacket *packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE); if (!packet) return false; enet_host_broadcast(host, 0, packet); enet_host_flush(host); return true; } void Enet::Disconnect(void *peer) { if (peer) enet_peer_disconnect((ENetPeer *)peer, 0); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ Enet::Enet() { host = NULL; enet_initialize(); } Enet::~Enet() { Close(); enet_deinitialize(); } //------------------------------------------------------------------------------