mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-11 02:28:18 +00:00
187 lines
4.1 KiB
C++
187 lines
4.1 KiB
C++
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
#include <base/system.h>
|
|
#include "network.h"
|
|
|
|
void CConsoleNetConnection::Reset()
|
|
{
|
|
m_State = NET_CONNSTATE_OFFLINE;
|
|
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
|
m_aErrorString[0] = 0;
|
|
|
|
m_Socket.type = NETTYPE_INVALID;
|
|
m_Socket.ipv4sock = -1;
|
|
m_Socket.ipv6sock = -1;
|
|
m_aBuffer[0] = 0;
|
|
m_BufferOffset = 0;
|
|
|
|
m_LineEndingDetected = false;
|
|
#if defined(CONF_FAMILY_WINDOWS)
|
|
m_aLineEnding[0] = '\r';
|
|
m_aLineEnding[1] = '\n';
|
|
m_aLineEnding[2] = 0;
|
|
#else
|
|
m_aLineEnding[0] = '\n';
|
|
m_aLineEnding[1] = 0;
|
|
m_aLineEnding[2] = 0;
|
|
#endif
|
|
}
|
|
|
|
void CConsoleNetConnection::Init(NETSOCKET Socket, const NETADDR *pAddr)
|
|
{
|
|
Reset();
|
|
|
|
m_Socket = Socket;
|
|
net_set_non_blocking(m_Socket);
|
|
|
|
m_PeerAddr = *pAddr;
|
|
m_State = NET_CONNSTATE_ONLINE;
|
|
}
|
|
|
|
void CConsoleNetConnection::Disconnect(const char *pReason)
|
|
{
|
|
if(State() == NET_CONNSTATE_OFFLINE)
|
|
return;
|
|
|
|
if(pReason && pReason[0])
|
|
Send(pReason);
|
|
|
|
net_tcp_close(m_Socket);
|
|
|
|
Reset();
|
|
}
|
|
|
|
int CConsoleNetConnection::Update()
|
|
{
|
|
if(State() == NET_CONNSTATE_ONLINE)
|
|
{
|
|
if((int)(sizeof(m_aBuffer)) <= m_BufferOffset)
|
|
{
|
|
m_State = NET_CONNSTATE_ERROR;
|
|
str_copy(m_aErrorString, "too weak connection (out of buffer)", sizeof(m_aErrorString));
|
|
return -1;
|
|
}
|
|
|
|
int Bytes = net_tcp_recv(m_Socket, m_aBuffer+m_BufferOffset, (int)(sizeof(m_aBuffer))-m_BufferOffset);
|
|
|
|
if(Bytes > 0)
|
|
{
|
|
m_BufferOffset += Bytes;
|
|
}
|
|
else if(Bytes < 0)
|
|
{
|
|
if(net_would_block()) // no data received
|
|
return 0;
|
|
|
|
m_State = NET_CONNSTATE_ERROR; // error
|
|
str_copy(m_aErrorString, "connection failure", sizeof(m_aErrorString));
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
m_State = NET_CONNSTATE_ERROR;
|
|
str_copy(m_aErrorString, "remote end closed the connection", sizeof(m_aErrorString));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CConsoleNetConnection::Recv(char *pLine, int MaxLength)
|
|
{
|
|
if(State() == NET_CONNSTATE_ONLINE)
|
|
{
|
|
if(m_BufferOffset)
|
|
{
|
|
// find message start
|
|
int StartOffset = 0;
|
|
while(m_aBuffer[StartOffset] == '\r' || m_aBuffer[StartOffset] == '\n')
|
|
{
|
|
// detect clients line ending format
|
|
if(!m_LineEndingDetected)
|
|
{
|
|
m_aLineEnding[0] = m_aBuffer[StartOffset];
|
|
if(StartOffset+1 < m_BufferOffset && (m_aBuffer[StartOffset+1] == '\r' || m_aBuffer[StartOffset+1] == '\n') &&
|
|
m_aBuffer[StartOffset] != m_aBuffer[StartOffset+1])
|
|
m_aLineEnding[1] = m_aBuffer[StartOffset+1];
|
|
m_LineEndingDetected = true;
|
|
}
|
|
|
|
if(++StartOffset >= m_BufferOffset)
|
|
{
|
|
m_BufferOffset = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// find message end
|
|
int EndOffset = StartOffset;
|
|
while(m_aBuffer[EndOffset] != '\r' && m_aBuffer[EndOffset] != '\n')
|
|
{
|
|
if(++EndOffset >= m_BufferOffset)
|
|
{
|
|
if(StartOffset > 0)
|
|
{
|
|
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
|
m_BufferOffset -= StartOffset;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// extract message and update buffer
|
|
if(MaxLength-1 < EndOffset-StartOffset)
|
|
{
|
|
if(StartOffset > 0)
|
|
{
|
|
mem_move(m_aBuffer, m_aBuffer+StartOffset, m_BufferOffset-StartOffset);
|
|
m_BufferOffset -= StartOffset;
|
|
}
|
|
return 0;
|
|
}
|
|
mem_copy(pLine, m_aBuffer+StartOffset, EndOffset-StartOffset);
|
|
pLine[EndOffset-StartOffset] = 0;
|
|
str_sanitize_cc(pLine);
|
|
mem_move(m_aBuffer, m_aBuffer+EndOffset, m_BufferOffset-EndOffset);
|
|
m_BufferOffset -= EndOffset;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CConsoleNetConnection::Send(const char *pLine)
|
|
{
|
|
if(State() != NET_CONNSTATE_ONLINE)
|
|
return -1;
|
|
|
|
char aBuf[1024];
|
|
str_copy(aBuf, pLine, (int)(sizeof(aBuf))-2);
|
|
int Length = str_length(aBuf);
|
|
aBuf[Length] = m_aLineEnding[0];
|
|
aBuf[Length+1] = m_aLineEnding[1];
|
|
aBuf[Length+2] = m_aLineEnding[2];
|
|
Length += 3;
|
|
const char *pData = aBuf;
|
|
|
|
while(true)
|
|
{
|
|
int Send = net_tcp_send(m_Socket, pData, Length);
|
|
if(Send < 0)
|
|
{
|
|
m_State = NET_CONNSTATE_ERROR;
|
|
str_copy(m_aErrorString, "failed to send packet", sizeof(m_aErrorString));
|
|
return -1;
|
|
}
|
|
|
|
if(Send >= Length)
|
|
break;
|
|
|
|
pData += Send;
|
|
Length -= Send;
|
|
}
|
|
|
|
return 0;
|
|
}
|