Commit is being made to allow additions of GPL3+ code previously un-addable. With these changes, contributions back to cuberite are possible with the backporting exemtion, as well as adding stuff in minetest with minetest code properly being read through and implimented to upgrade it to GPL3 from GPL2. project still has Apache2.0 license and credits to all its contributers, but now has the freedom of GPL3+ and all the code that can be implimented and shared with it.
162 lines
4.0 KiB
C++
162 lines
4.0 KiB
C++
|
|
/*
|
|
* Copyright 2011-2022 Cuberite Contributors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// EchoServer.cpp
|
|
|
|
// Implements an Echo server using the LibEvent-based cNetwork API, as a test of that API
|
|
|
|
#include "Globals.h"
|
|
#include <iostream>
|
|
#include <string>
|
|
#include "OSSupport/Network.h"
|
|
#include "OSSupport/NetworkSingleton.h"
|
|
|
|
|
|
|
|
|
|
|
|
/** cTCPLink callbacks that echo everything they receive back to the remote peer. */
|
|
class cEchoLinkCallbacks:
|
|
public cTCPLink::cCallbacks
|
|
{
|
|
// cTCPLink::cCallbacks overrides:
|
|
virtual void OnLinkCreated(cTCPLinkPtr a_Link) override
|
|
{
|
|
ASSERT(m_Link == nullptr);
|
|
m_Link = a_Link;
|
|
}
|
|
|
|
|
|
virtual void OnReceivedData(const char * a_Data, size_t a_Size) override
|
|
{
|
|
ASSERT(m_Link != nullptr);
|
|
|
|
// Echo the incoming data back to outgoing data:
|
|
LOGD("%p (%s:%d): Data received (%u bytes), echoing back.", static_cast<void *>(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort(), static_cast<unsigned>(a_Size));
|
|
m_Link->Send(a_Data, a_Size);
|
|
LOGD("Echo queued");
|
|
|
|
// Search for a Ctrl+Z, if found, drop the connection:
|
|
for (size_t i = 0; i < a_Size; i++)
|
|
{
|
|
if (a_Data[i] == '\x1a')
|
|
{
|
|
m_Link->Close();
|
|
m_Link.reset();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
virtual void OnRemoteClosed(void) override
|
|
{
|
|
ASSERT(m_Link != nullptr);
|
|
|
|
LOGD("%p (%s:%d): Remote has closed the connection.", static_cast<void *>(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort());
|
|
m_Link.reset();
|
|
}
|
|
|
|
|
|
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
|
|
{
|
|
ASSERT(m_Link != nullptr);
|
|
|
|
LOGD("%p (%s:%d): Error %d in the cEchoLinkCallbacks: %s", static_cast<void *>(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort(), a_ErrorCode, a_ErrorMsg.c_str());
|
|
m_Link.reset();
|
|
}
|
|
|
|
/** The link attached to this callbacks instance. */
|
|
cTCPLinkPtr m_Link;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class cEchoServerCallbacks:
|
|
public cNetwork::cListenCallbacks
|
|
{
|
|
virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override
|
|
{
|
|
LOGD("New incoming connection(%s:%d).", a_RemoteIPAddress.c_str(), a_RemotePort);
|
|
return std::make_shared<cEchoLinkCallbacks>();
|
|
}
|
|
|
|
virtual void OnAccepted(cTCPLink & a_Link) override
|
|
{
|
|
LOGD("New client accepted (%s:%d), sending welcome message.", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort());
|
|
// Send a welcome message to each connecting client:
|
|
a_Link.Send("Welcome to the simple echo server.\r\n");
|
|
LOGD("Welcome message queued.");
|
|
}
|
|
|
|
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
|
|
{
|
|
LOGWARNING("An error occured while listening for connections: %d (%s).", a_ErrorCode, a_ErrorMsg.c_str());
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void DoTest(void)
|
|
{
|
|
LOGD("EchoServer: starting up");
|
|
cServerHandlePtr Server = cNetwork::Listen(9876, std::make_shared<cEchoServerCallbacks>());
|
|
if (!Server->IsListening())
|
|
{
|
|
LOGWARNING("Cannot listen on port 9876");
|
|
abort();
|
|
}
|
|
ASSERT(Server->IsListening());
|
|
|
|
// Wait for the user to terminate the server:
|
|
printf("Press enter to close the server.\n");
|
|
AString line;
|
|
std::getline(std::cin, line);
|
|
|
|
// Close the server and all its active connections:
|
|
LOG("Server terminating.");
|
|
Server->Close();
|
|
ASSERT(!Server->IsListening());
|
|
Server.reset();
|
|
LOGD("Server has been closed.");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main()
|
|
{
|
|
DoTest();
|
|
|
|
printf("Press enter to exit test.\n");
|
|
AString line;
|
|
std::getline(std::cin, line);
|
|
cNetworkSingleton::Get().Terminate();
|
|
|
|
LOG("Network test finished.");
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|