1
0
Fork 0

Add the TCP Socket class and begin Wires-X support.

ycs232-kbc
Jonathan Naylor 8 years ago
parent 62a981a84e
commit 9e71805129

@ -231,3 +231,8 @@ void CGPS::transmitGPS(const unsigned char* source)
m_sent = true; m_sent = true;
} }
void CGPS::clock(unsigned int ms)
{
}

@ -0,0 +1,298 @@
/*
* Copyright (C) 2010-2013,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "TCPSocket.h"
#include "UDPSocket.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#if defined(_WIN32) || defined(_WIN64)
typedef int ssize_t;
#else
#include <cerrno>
#endif
CTCPSocket::CTCPSocket(const std::string& address, unsigned int port, const std::string& localAddress) :
m_address(address),
m_port(port),
m_localAddress(localAddress),
m_fd(-1)
{
assert(!address.empty());
assert(port > 0U);
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CTCPSocket::CTCPSocket(int fd) :
m_address(),
m_port(0U),
m_localAddress(),
m_fd(fd)
{
assert(fd >= 0);
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CTCPSocket::CTCPSocket() :
m_address(),
m_port(0U),
m_localAddress(),
m_fd(-1)
{
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CTCPSocket::~CTCPSocket()
{
#if defined(_WIN32) || defined(_WIN64)
::WSACleanup();
#endif
}
bool CTCPSocket::open(const std::string& address, unsigned int port, const std::string& localAddress)
{
m_address = address;
m_port = port;
m_localAddress = localAddress;
return open();
}
bool CTCPSocket::open()
{
if (m_fd != -1)
return true;
if (m_address.empty() || m_port == 0U)
return false;
m_fd = ::socket(PF_INET, SOCK_STREAM, 0);
if (m_fd < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot create the TCP client socket, err=%d", ::GetLastError());
#else
LogError("Cannot create the TCP client socket, err=%d", errno);
#endif
return false;
}
if (!m_localAddress.empty()) {
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = 0U;
#if defined(_WIN32) || defined(_WIN64)
addr.sin_addr.s_addr = ::inet_addr(m_localAddress.c_str());
#else
addr.sin_addr.s_addr = ::inet_addr(m_localAddress.c_str());
#endif
if (addr.sin_addr.s_addr == INADDR_NONE) {
LogError("The address is invalid - %s", m_localAddress.c_str());
close();
return false;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot bind the TCP client address, err=%d", ::GetLastError());
#else
LogError("Cannot bind the TCP client address, err=%d", errno);
#endif
close();
return false;
}
}
struct sockaddr_in addr;
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
addr.sin_addr = CUDPSocket::lookup(m_address);
if (addr.sin_addr.s_addr == INADDR_NONE) {
close();
return false;
}
if (::connect(m_fd, (sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot connect the TCP client socket, err=%d", ::GetLastError());
#else
LogError("Cannot connect the TCP client socket, err=%d", errno);
#endif
close();
return false;
}
int noDelay = 1;
if (::setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&noDelay, sizeof(noDelay)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot set the TCP client socket option, err=%d", ::GetLastError());
#else
LogError("Cannot set the TCP client socket option, err=%d", errno);
#endif
close();
return false;
}
return true;
}
int CTCPSocket::read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs)
{
assert(buffer != NULL);
assert(length > 0U);
assert(m_fd != -1);
// Check that the recv() won't block
fd_set readFds;
FD_ZERO(&readFds);
#if defined(_WIN32) || defined(_WIN64)
FD_SET((unsigned int)m_fd, &readFds);
#else
FD_SET(m_fd, &readFds);
#endif
// Return after timeout
timeval tv;
tv.tv_sec = secs;
tv.tv_usec = msecs * 1000;
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from TCP client select, err=%d", ::GetLastError());
#else
LogError("Error returned from TCP client select, err=%d", errno);
#endif
return -1;
}
#if defined(_WIN32) || defined(_WIN64)
if (!FD_ISSET((unsigned int)m_fd, &readFds))
return 0;
#else
if (!FD_ISSET(m_fd, &readFds))
return 0;
#endif
ssize_t len = ::recv(m_fd, (char*)buffer, length, 0);
if (len == 0) {
return -2;
} else if (len < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from recv, err=%d", ::GetLastError());
#else
LogError("Error returned from recv, err=%d", errno);
#endif
return -1;
}
return len;
}
int CTCPSocket::readLine(std::string& line, unsigned int secs)
{
// Maybe there is a better way to do this like reading blocks, pushing them for later calls
// Nevermind, we'll read one char at a time for the time being.
int resultCode;
int len = 0;
line.clear();
char c[2U];
c[1U] = 0x00U;
do
{
resultCode = read((unsigned char*)c, 1U, secs);
if (resultCode == 1){
line.append(c);
len++;
}
} while (c[0U] != '\n' && resultCode == 1);
return resultCode <= 0 ? resultCode : len;
}
bool CTCPSocket::write(const unsigned char* buffer, unsigned int length)
{
assert(buffer != NULL);
assert(length > 0U);
assert(m_fd != -1);
ssize_t ret = ::send(m_fd, (char *)buffer, length, 0);
if (ret != ssize_t(length)) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from send, err=%d", ::GetLastError());
#else
LogError("Error returned from send, err=%d", errno);
#endif
return false;
}
return true;
}
bool CTCPSocket::writeLine(const std::string& line)
{
std::string lineCopy(line);
if (lineCopy.length() > 0 && lineCopy.at(lineCopy.length() - 1) != '\n')
lineCopy.append("\n");
//stupidly write one char after the other
size_t len = lineCopy.length();
bool result = true;
for (size_t i = 0U; i < len && result; i++){
unsigned char c = lineCopy.at(i);
result = write(&c , 1);
}
return result;
}
void CTCPSocket::close()
{
if (m_fd != -1) {
#if defined(_WIN32) || defined(_WIN64)
::closesocket(m_fd);
#else
::close(m_fd);
#endif
m_fd = -1;
}
}

@ -0,0 +1,62 @@
/*
* Copyright (C) 2010,2011,2012,2013,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TCPSocket_H
#define TCPSocket_H
#if !defined(_WIN32) && !defined(_WIN64)
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
#include <string>
class CTCPSocket {
public:
CTCPSocket(const std::string& address, unsigned int port, const std::string& localAddress);
CTCPSocket(int fd);
CTCPSocket();
~CTCPSocket();
bool open(const std::string& address, unsigned int port, const std::string& localAddress);
bool open();
int read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs = 0U);
int readLine(std::string& line, unsigned int secs);
bool write(const unsigned char* buffer, unsigned int length);
bool writeLine(const std::string& line);
void close();
private:
std::string m_address;
unsigned short m_port;
std::string m_localAddress;
int m_fd;
};
#endif

@ -17,10 +17,15 @@
*/ */
#include "WiresX.h" #include "WiresX.h"
#include "YSFPayload.h"
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
const unsigned char CALL_DX[] = {0x5DU, 0x71U};
const unsigned char CALL_CONNECT[] = {0x5DU, 0x41U};
const unsigned char CALL_ALL[] = {0x5DU, 0x66U};
CWiresX::CWiresX(CNetwork* network) : CWiresX::CWiresX(CNetwork* network) :
m_network(network), m_network(network),
m_reflector() m_reflector()
@ -34,6 +39,23 @@ CWiresX::~CWiresX()
WX_STATUS CWiresX::process(const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn) WX_STATUS CWiresX::process(const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn)
{ {
if (fi != YSF_FI_COMMUNICATIONS || dt != YSF_DT_DATA_FR_MODE || fn != 1U)
return WXS_NONE;
unsigned char buffer[20U];
CYSFPayload payload;
bool valid = payload.readDataFRModeData2(data, buffer);
if (!valid)
return WXS_NONE;
if (::memcmp(buffer + 1U, CALL_DX, 2U) == 0)
processDX();
else if (::memcmp(buffer + 1U, CALL_ALL, 2U) == 0)
processAll();
else if (::memcmp(buffer + 1U, CALL_CONNECT, 2U) == 0)
return processConnect();
return WXS_NONE; return WXS_NONE;
} }
@ -41,3 +63,23 @@ std::string CWiresX::getReflector() const
{ {
return m_reflector; return m_reflector;
} }
void CWiresX::processDX()
{
}
void CWiresX::processAll()
{
}
WX_STATUS CWiresX::processConnect()
{
return WXS_NONE;
}
void CWiresX::clock(unsigned int ms)
{
}

@ -43,6 +43,10 @@ public:
private: private:
CNetwork* m_network; CNetwork* m_network;
std::string m_reflector; std::string m_reflector;
WX_STATUS processConnect();
void processDX();
void processAll();
}; };
#endif #endif

@ -24,8 +24,9 @@ FileRoot=YSFGateway
[aprs.fi] [aprs.fi]
Enable=1 Enable=1
Server= # Server=noam.aprs2.net
Port= Server=euro.aprs2.net
Port=14580
Password=9999 Password=9999
[Network] [Network]

@ -155,6 +155,7 @@
<ClInclude Include="Network.h" /> <ClInclude Include="Network.h" />
<ClInclude Include="RingBuffer.h" /> <ClInclude Include="RingBuffer.h" />
<ClInclude Include="StopWatch.h" /> <ClInclude Include="StopWatch.h" />
<ClInclude Include="TCPSocket.h" />
<ClInclude Include="Timer.h" /> <ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" /> <ClInclude Include="UDPSocket.h" />
<ClInclude Include="Utils.h" /> <ClInclude Include="Utils.h" />
@ -175,6 +176,7 @@
<ClCompile Include="Log.cpp" /> <ClCompile Include="Log.cpp" />
<ClCompile Include="Network.cpp" /> <ClCompile Include="Network.cpp" />
<ClCompile Include="StopWatch.cpp" /> <ClCompile Include="StopWatch.cpp" />
<ClCompile Include="TCPSocket.cpp" />
<ClCompile Include="Timer.cpp" /> <ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" /> <ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="Utils.cpp" /> <ClCompile Include="Utils.cpp" />

@ -68,6 +68,9 @@
<ClInclude Include="WiresX.h"> <ClInclude Include="WiresX.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="TCPSocket.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Network.cpp"> <ClCompile Include="Network.cpp">
@ -118,5 +121,8 @@
<ClCompile Include="WiresX.cpp"> <ClCompile Include="WiresX.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="TCPSocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>
Loading…
Cancel
Save