diff --git a/src/NetworkPrimary.cpp b/src/NetworkPrimary.cpp index 26bdcf007..aad2e658f 100644 --- a/src/NetworkPrimary.cpp +++ b/src/NetworkPrimary.cpp @@ -112,30 +112,45 @@ void NetworkPrimary::connectToServer(std::string hostnames) //std::cout << "In NetworkPrimary, trying to set up to " << address.port << std::endl; /* Connect to some.server.net:18304. */ - enet_address_set_host (& address, thisHostname.c_str()); - - /* Initiate the connection, allocating the maximum number of channels. */ - peer = enet_host_connect (client, & address, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT, 0); - //Note we don't store peer pointer, as we broadcast to all connected peers. - if (peer == NULL) - { - std::cerr << "No available peers for initiating an ENet connection." << std::endl; - enet_deinitialize(); - exit(EXIT_FAILURE); - } - /* Wait up to 1 second for the connection attempt to succeed. */ - if (enet_host_service (client, & event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { - //std::string logMessage = "ENet connection succeeded to: "; - //logMessage.append(thisHostname); - device->getLogger()->log("ENet connection succeeded to:"); - device->getLogger()->log(thisHostname.c_str()); + if (enet_address_set_host (& address, thisHostname.c_str()) == 0) { + + /* Initiate the connection, allocating the maximum number of channels. */ + peer = enet_host_connect (client, & address, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT, 0); + //Note we don't store peer pointer, as we broadcast to all connected peers. + if (peer == NULL) + { + std::cerr << "No available peers for initiating an ENet connection." << std::endl; + enet_deinitialize(); + exit(EXIT_FAILURE); + } + + bool connectedPeer = false; + + // Retry connection 10 times + for (unsigned int j = 0; j < 10; j++) { + /* Wait up to 1 second for the connection attempt to succeed. */ + if (enet_host_service(client, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { + //std::string logMessage = "ENet connection succeeded to: "; + //logMessage.append(thisHostname); + device->getLogger()->log("ENet connection succeeded to:"); + device->getLogger()->log(thisHostname.c_str()); + connectedPeer = true; + break; + } + } + + if (!connectedPeer) { + /* Either the 1 second is up or a disconnect event was */ + /* received. Reset the peer in the event the 1 second */ + /* had run out without any significant event. */ + enet_peer_reset (peer); + device->getLogger()->log("ENet connection failed to:"); + device->getLogger()->log(thisHostname.c_str()); + } + } else { - /* Either the 1 second is up or a disconnect event was */ - /* received. Reset the peer in the event the 1 second */ - /* had run out without any significant event. */ - enet_peer_reset (peer); - device->getLogger()->log("ENet connection failed to:"); - device->getLogger()->log(thisHostname.c_str()); + // Failed to look up address with enet_address_set_host + std::cout << "ENet could not resolve hostname:" << thisHostname << std::endl; } } } @@ -175,7 +190,7 @@ void NetworkPrimary::receiveNetwork() std::cerr << "Network not linked to model" << std::endl; return; } - if (enet_host_service (client, & event, 10) > 0) { + while (enet_host_service (client, & event, 10) > 0) { if (event.type==ENET_EVENT_TYPE_RECEIVE) { //Convert into a string, max length 8192 @@ -455,16 +470,33 @@ void NetworkPrimary::sendNetwork(std::string aManualCmd) packetFlag = ENET_PACKET_FLAG_RELIABLE; } - /* Create a packet */ - ENetPacket * packet = enet_packet_create (stringToSend.c_str(), - strlen (stringToSend.c_str()) + 1, - packetFlag); - - /* Send the packet to all connected peers over channel id 0. */ - enet_host_broadcast(client, 0, packet); - - /* One could just use enet_host_service() instead. */ - enet_host_flush (client); + // Send data to connected peers + for (int i = 0; i < client->peerCount; i++) { + + // Skip non-connected peers + if (client->peers[i].state != ENET_PEER_STATE_CONNECTED) { + continue; + } + + /* Create a packet */ + ENetPacket* packet = enet_packet_create(stringToSend.c_str(), + strlen(stringToSend.c_str()) + 1, + packetFlag); + + /* Send the packet to each peer over channel id i. */ + enet_uint8 channelNumber = i; + if (channelNumber >= ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + channelNumber = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT - 1; + } + if (enet_peer_send(&client->peers[i], channelNumber, packet) == 0) { + /* One could just use enet_host_service() instead. */ + enet_host_flush(client); + } + else { + enet_packet_destroy(packet); + std::cout << "Could not send packet to peer " << i << std::endl; + } + } } } diff --git a/src/NetworkSecondary.cpp b/src/NetworkSecondary.cpp index 2bd3b7c56..625a06648 100644 --- a/src/NetworkSecondary.cpp +++ b/src/NetworkSecondary.cpp @@ -87,7 +87,7 @@ void NetworkSecondary::connectToServer(std::string hostnames) void NetworkSecondary::getScenarioFromNetwork(std::string& dataString) //Not used by primary { - if (enet_host_service (server, & event, 10) > 0) { //Wait 10ms for event + while (enet_host_service (server, & event, 10) > 0) { //Wait 10ms for event, and process multiple events if needed if (event.type ==ENET_EVENT_TYPE_RECEIVE) { //receive it @@ -104,11 +104,14 @@ void NetworkSecondary::getScenarioFromNetwork(std::string& dataString) //Not use (receivedString.substr(0,4) == "SCN5")) { //Check if it starts with SCN1-SCN5 //If valid, use this string dataString = receivedString; + // Break out of loop so we don't overwrite the scenario data + break; } } + /* Clean up the packet now that we're done using it. */ + enet_packet_destroy(event.packet); } - /* Clean up the packet now that we're done using it. */ - enet_packet_destroy (event.packet); + } } @@ -530,8 +533,12 @@ void NetworkSecondary::receiveMessage() //Send back to event.peer ENetPacket* packet = enet_packet_create (multiplayerFeedback.c_str(), strlen (multiplayerFeedback.c_str()) + 1,0/*reliable flag*/); if (packet!=0) { - enet_peer_send (event.peer, 0, packet); - enet_host_flush (server); + if (enet_peer_send(event.peer, event.channelID, packet) == 0) { + enet_host_flush(server); + } else { + enet_packet_destroy(packet); + std::cout << "Could not send multiplayer feedback packet on channel " << event.channelID << std::endl; + } } } @@ -586,8 +593,14 @@ void NetworkSecondary::receiveMessage() //Send back to event.peer ENetPacket* packet = enet_packet_create (controlOverride.c_str(), strlen (controlOverride.c_str()) + 1,0/*reliable flag*/); if (packet!=0) { - enet_peer_send (event.peer, 0, packet); - enet_host_flush (server); + if (enet_peer_send(event.peer, event.channelID, packet) == 0) { + enet_host_flush(server); + } + else { + enet_packet_destroy(packet); + std::cout << "Could not send control override packet on channel " << event.channelID << std::endl; + } + } } diff --git a/src/controller/Network.cpp b/src/controller/Network.cpp index f92bde924..445265b86 100644 --- a/src/controller/Network.cpp +++ b/src/controller/Network.cpp @@ -89,7 +89,7 @@ std::string Network::findWorldName() std::string worldName = ""; - if (enet_host_service (server, & event, 10) > 0) { + while (worldName == "" && enet_host_service (server, & event, 10) > 0) { if (event.type == ENET_EVENT_TYPE_RECEIVE) { //receive it char tempString[8192]; //Fixme: Think if this is long enough @@ -138,7 +138,7 @@ void Network::update(irr::f32& time, ShipData& ownShipData, std::vectorstringToSend.append("|"); } -void Network::sendMessage(ENetPeer* peer) +void Network::sendMessage(ENetPeer* peer, enet_uint8 channel) { //Assumes that event contains a received message @@ -173,14 +173,18 @@ void Network::sendMessage(ENetPeer* peer) strlen (stringToSend.c_str()) + 1, /*ENET_PACKET_FLAG_RELIABLE*/1); - /* Send the packet to the peer over channel id 0. */ + /* Send the packet to the peer over specified channel id. */ /* One could also broadcast the packet by */ /* enet_host_broadcast (host, 0, packet); */ - enet_peer_send (peer, 0, packet); - /* One could just use enet_host_service() instead. */ - enet_host_flush (server); + if (enet_peer_send(peer, channel, packet) == 0) { + /* One could just use enet_host_service() instead. */ + enet_host_flush(server); + stringToSend = ""; //Sent message, so clear it + } else { + enet_packet_destroy(packet); + } - stringToSend = ""; //Sent message, so clear it + } } diff --git a/src/controller/Network.hpp b/src/controller/Network.hpp index 2b0aa9d14..959c1baae 100644 --- a/src/controller/Network.hpp +++ b/src/controller/Network.hpp @@ -57,7 +57,7 @@ class Network void findOtherShipData(const std::vector& otherShipsDataString, std::vector& otherShipsData); void findBuoyPositionData(const std::vector& buoysDataString, std::vector& buoysData); - void sendMessage(ENetPeer * peer); + void sendMessage(ENetPeer * peer, enet_uint8 channel); }; #endif // __NETWORK_HPP_INCLUDED__ diff --git a/src/main.cpp b/src/main.cpp index 1500512f4..c120964e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -897,14 +897,6 @@ int main(int argc, char ** argv) //Network network(&model); network->connectToServer(hostname); - // If in multiplayer mode, also start 'normal' network, so we can send data to secondary displays - Network* extraNetwork = 0; - if ((mode == OperatingMode::Multiplayer) && (hostname.length() > 0 )) { - extraNetwork = Network::createNetwork(OperatingMode::Normal, udpPort, device); - extraNetwork->connectToServer(hostname); - //std::cout << "Starting extra network to " << hostname << " on " << udpPort << std::endl; - } - //Read in scenario data (work in progress) ScenarioData scenarioData; if (mode == OperatingMode::Normal) { @@ -934,6 +926,14 @@ int main(int argc, char ** argv) //Note: We could use this serialised format as a scenario import/export format or for online distribution + // If in multiplayer mode, also start 'normal' network, so we can send data to secondary displays + Network* extraNetwork = 0; + if ((mode == OperatingMode::Multiplayer) && (hostname.length() > 0 )) { + extraNetwork = Network::createNetwork(OperatingMode::Normal, udpPort, device); + extraNetwork->connectToServer(hostname); + //std::cout << "Starting extra network to " << hostname << " on " << udpPort << std::endl; + } + // Check VR mode bool vr3dMode = false; if (IniFile::iniFileTou32(iniFilename, "vr_mode")==1) { diff --git a/src/multiplayerHub/Network.cpp b/src/multiplayerHub/Network.cpp index 12b938b95..1b75b5333 100644 --- a/src/multiplayerHub/Network.cpp +++ b/src/multiplayerHub/Network.cpp @@ -97,28 +97,42 @@ void Network::connectToServer(std::string hostnames) } } - enet_address_set_host (& address, thisHostname.c_str()); + if (enet_address_set_host (& address, thisHostname.c_str()) == 0) { - /* Initiate the connection, allocating the maximum number of channels. */ - peer = enet_host_connect (client, & address, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT, 0); + /* Initiate the connection, allocating the maximum number of channels. */ + peer = enet_host_connect (client, & address, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT, 0); - if (peer == NULL) - { - std::cout << "No available peers for initiating an ENet connection." << std::endl; - exit (EXIT_FAILURE); - } - /* Wait up to 1 second for the connection attempt to succeed. */ - if (enet_host_service (client, & event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { - std::cout << "ENet connection succeeded to: " << thisHostname << std::endl; - //Store peer, and initialise the vector of latest strings received - peers.push_back(peer); - latestMessageFromPeer.push_back(""); + if (peer == NULL) + { + std::cout << "No available peers for initiating an ENet connection." << std::endl; + //exit (EXIT_FAILURE); + } + + bool connectedPeer = false; + + // Retry connection 10 times + for (unsigned int j = 0; j < 10; j++) { + /* Wait up to 1 second for the connection attempt to succeed. */ + if (enet_host_service(client, &event, 1000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { + std::cout << "ENet multiplayer connection succeeded to: " << thisHostname << std::endl; + //Store peer, and initialise the vector of latest strings received + peers.push_back(peer); + latestMessageFromPeer.push_back(""); + connectedPeer = true; + break; + } + } + if (!connectedPeer) { + /* Either the 1 second is up or a disconnect event was */ + /* received. Reset the peer in the event the 1 second */ + /* had run out without any significant event. */ + enet_peer_reset(peer); + std::cout << "ENet multiplayer connection failed to:" << thisHostname << std::endl; + } + } else { - /* Either the 1 second is up or a disconnect event was */ - /* received. Reset the peer in the event the 1 second */ - /* had run out without any significant event. */ - enet_peer_reset (peer); - std::cout << "ENet connection failed to:" << thisHostname << std::endl; + // Failed to look up address with enet_address_set_host + std::cout << "ENet multiplayer could not resolve hostname:" << thisHostname << std::endl; } } } @@ -144,11 +158,18 @@ void Network::sendString(std::string stringToSend, bool reliable, unsigned int p strlen (stringToSend.c_str()) + 1, reliableFlag); //Flag - // Send the packet to peer over channel id 0. - enet_peer_send(peers.at(peerNumber), 0, packet); - - // One could just use enet_host_service() instead. - enet_host_flush (client); + // Send the packet to peer over channel id matching the peer number (one channel per peer). + enet_uint8 channelNumber = peerNumber; + if (channelNumber >= ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + channelNumber = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT - 1; + } + if (enet_peer_send(peers.at(peerNumber), channelNumber, packet) == 0) { + // One could just use enet_host_service() instead. + enet_host_flush(client); + } else { + enet_packet_destroy(packet); + std::cout << "Could not send packet to peer " << peerNumber << std::endl; + } } } }