1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-01-31 18:07:14 +01:00
SqMod/vendor/POCO/Net/src/DialogSocket.cpp

296 lines
4.9 KiB
C++
Raw Normal View History

//
// DialogSocket.cpp
//
// Library: Net
// Package: Sockets
// Module: DialogSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/DialogSocket.h"
#include "Poco/Exception.h"
#include "Poco/Ascii.h"
#include <cstring>
namespace Poco {
namespace Net {
DialogSocket::DialogSocket():
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const SocketAddress& address):
StreamSocket(address),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const Socket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const DialogSocket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::~DialogSocket()
{
delete [] _pBuffer;
}
DialogSocket& DialogSocket::operator = (const Socket& socket)
{
StreamSocket::operator = (socket);
_pNext = _pBuffer;
_pEnd = _pBuffer;
return *this;
}
DialogSocket& DialogSocket::operator = (const DialogSocket& socket)
{
StreamSocket::operator = (socket);
_pNext = _pBuffer;
_pEnd = _pBuffer;
return *this;
}
void DialogSocket::sendByte(unsigned char ch)
{
sendBytes(&ch, 1);
}
void DialogSocket::sendString(const char* str)
{
sendBytes(str, (int) std::strlen(str));
}
void DialogSocket::sendString(const std::string& str)
{
sendBytes(str.data(), (int) str.length());
}
void DialogSocket::sendMessage(const std::string& message)
{
std::string line;
line.reserve(message.length() + 2);
line.append(message);
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg)
{
std::string line;
line.reserve(message.length() + arg.length() + 3);
line.append(message);
if (!arg.empty())
{
line.append(" ");
line.append(arg);
}
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2)
{
std::string line;
line.reserve(message.length() + arg1.length() +arg2.length() + 4);
line.append(message);
line.append(" ");
line.append(arg1);
if (!arg2.empty())
{
line.append(" ");
line.append(arg2);
}
line.append("\r\n");
sendString(line);
}
bool DialogSocket::receiveMessage(std::string& message)
{
message.clear();
return receiveLine(message, MAX_LINE_LENGTH);
}
int DialogSocket::receiveStatusMessage(std::string& message)
{
message.clear();
int status = receiveStatusLine(message, MAX_LINE_LENGTH);
if (status < 0)
{
while (status <= 0)
{
message += '\n';
status = receiveStatusLine(message, message.length() + MAX_LINE_LENGTH);
}
}
return status;
}
int DialogSocket::get()
{
refill();
if (_pNext != _pEnd)
return std::char_traits<char>::to_int_type(*_pNext++);
else
return EOF_CHAR;
}
int DialogSocket::peek()
{
refill();
if (_pNext != _pEnd)
return std::char_traits<char>::to_int_type(*_pNext);
else
return EOF_CHAR;
}
void DialogSocket::synch()
{
sendUrgent(TELNET_DM);
}
void DialogSocket::sendTelnetCommand(unsigned char command)
{
unsigned char buffer[2];
buffer[0] = TELNET_IAC;
buffer[1] = command;
sendBytes(buffer, 2);
}
void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg)
{
unsigned char buffer[3];
buffer[0] = TELNET_IAC;
buffer[1] = command;
buffer[2] = arg;
sendBytes(buffer, 3);
}
void DialogSocket::refill()
{
if (_pNext == _pEnd)
{
int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE);
if (n > 0)
{
_pNext = _pBuffer;
_pEnd = _pBuffer + n;
}
}
}
void DialogSocket::allocBuffer()
{
_pBuffer = new char [RECEIVE_BUFFER_SIZE];
_pNext = _pBuffer;
_pEnd = _pBuffer;
}
bool DialogSocket::receiveLine(std::string& line, std::size_t lineLengthLimit)
{
// An old wisdom goes: be strict in what you emit
// and generous in what you accept.
int ch = get();
while (ch != EOF_CHAR && ch != '\r' && ch != '\n')
{
if (lineLengthLimit == 0 || line.size() < lineLengthLimit)
line += (char) ch;
else
throw Poco::IOException("Line too long");
ch = get();
}
if (ch == '\r' && peek() == '\n')
get();
else if (ch == EOF_CHAR)
return false;
return true;
}
int DialogSocket::receiveStatusLine(std::string& line, std::size_t lineLengthLimit)
{
int status = 0;
int ch = get();
if (ch != EOF_CHAR) line += (char) ch;
int n = 0;
while (Poco::Ascii::isDigit(ch) && n < 3)
{
status *= 10;
status += ch - '0';
++n;
ch = get();
if (ch != EOF_CHAR) line += (char) ch;
}
if (n == 3)
{
if (ch == '-')
status = -status;
}
else status = 0;
if (ch != EOF_CHAR) receiveLine(line, lineLengthLimit);
return status;
}
int DialogSocket::receiveRawBytes(void* buffer, int length)
{
refill();
int n = static_cast<int>(_pEnd - _pNext);
if (n > length) n = length;
std::memcpy(buffer, _pNext, n);
_pNext += n;
return n;
}
} } // namespace Poco::Net