<ClInclude Include="..\src\lib\platform\util\StdString.h" />
<ClInclude Include="..\src\lib\platform\util\timeutils.h" />
<ClInclude Include="..\src\lib\platform\windows\os-socket.h" />
- <ClInclude Include="..\src\lib\platform\windows\os-tcp.h" />
<ClInclude Include="..\src\lib\platform\windows\os-threads.h" />
<ClInclude Include="..\src\lib\platform\windows\os-types.h" />
+ <ClInclude Include="..\src\lib\platform\windows\stdint.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\lib\adapter\AdapterCommunication.cpp" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <Filter Include="platform">
- <UniqueIdentifier>{cc48ddc0-be11-43ec-a805-3a9434f443ed}</UniqueIdentifier>
- </Filter>
<Filter Include="exports">
<UniqueIdentifier>{01b9c84a-dcfe-4bdc-b983-69e3e3929b0f}</UniqueIdentifier>
</Filter>
<Filter Include="devices">
<UniqueIdentifier>{bfc43a58-636d-4c1a-b191-486cb8509c7c}</UniqueIdentifier>
</Filter>
- <Filter Include="platform\windows">
- <UniqueIdentifier>{fa3d5953-d288-45e9-93f4-8419e6b701c7}</UniqueIdentifier>
- </Filter>
- <Filter Include="platform\threads">
- <UniqueIdentifier>{38a27e9e-86ad-46f6-a4fb-e1e524267b74}</UniqueIdentifier>
- </Filter>
<Filter Include="adapter">
<UniqueIdentifier>{51614b77-8a0e-47a8-8500-5beb0fd12d49}</UniqueIdentifier>
</Filter>
- <Filter Include="platform\util">
- <UniqueIdentifier>{4e963de7-5c42-40a0-9c81-bb112d5a24f9}</UniqueIdentifier>
+ <Filter Include="platform">
+ <UniqueIdentifier>{7d05b1b5-e728-4f9e-b78f-d63cac4ded8e}</UniqueIdentifier>
</Filter>
<Filter Include="platform\sockets">
- <UniqueIdentifier>{e3945145-efa2-4393-b201-f50e1e775008}</UniqueIdentifier>
+ <UniqueIdentifier>{6cfe4bad-ed3a-4a16-8c59-4489089f5fe5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="platform\util">
+ <UniqueIdentifier>{39a56ebf-ba93-4e7b-bf72-2f57b99a1ee1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="platform\threads">
+ <UniqueIdentifier>{be183456-d61e-4283-b642-fe25ed71e9c5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="platform\windows">
+ <UniqueIdentifier>{65c4a590-4577-40e4-91ad-339e20b99ebe}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\lib\devices\CECTV.h">
<Filter>devices</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\os.h">
- <Filter>platform</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
- <Filter>platform\windows</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\os-types.h">
- <Filter>platform\windows</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\threads\mutex.h">
- <Filter>platform\threads</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\threads\threads.h">
- <Filter>platform\threads</Filter>
- </ClInclude>
<ClInclude Include="..\src\lib\adapter\AdapterCommunication.h">
<Filter>adapter</Filter>
</ClInclude>
<ClInclude Include="..\src\lib\adapter\AdapterMessage.h">
<Filter>adapter</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\util\StdString.h">
+ <ClInclude Include="..\src\lib\platform\os.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\platform\sockets\serialport.h">
+ <Filter>platform\sockets</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\platform\sockets\socket.h">
+ <Filter>platform\sockets</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\platform\sockets\tcp.h">
+ <Filter>platform\sockets</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\lib\platform\util\baudrate.h">
<Filter>platform\util</Filter>
</ClInclude>
<ClInclude Include="..\src\lib\platform\util\buffer.h">
<Filter>platform\util</Filter>
</ClInclude>
+ <ClInclude Include="..\src\lib\platform\util\StdString.h">
+ <Filter>platform\util</Filter>
+ </ClInclude>
<ClInclude Include="..\src\lib\platform\util\timeutils.h">
<Filter>platform\util</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\sockets\serialport.h">
- <Filter>platform\sockets</Filter>
+ <ClInclude Include="..\src\lib\platform\threads\mutex.h">
+ <Filter>platform\threads</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\sockets\socket.h">
- <Filter>platform\sockets</Filter>
+ <ClInclude Include="..\src\lib\platform\threads\threads.h">
+ <Filter>platform\threads</Filter>
</ClInclude>
<ClInclude Include="..\src\lib\platform\windows\os-socket.h">
<Filter>platform\windows</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\util\baudrate.h">
- <Filter>platform\util</Filter>
+ <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
+ <Filter>platform\windows</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\sockets\tcp.h">
- <Filter>platform\sockets</Filter>
+ <ClInclude Include="..\src\lib\platform\windows\os-types.h">
+ <Filter>platform\windows</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\os-tcp.h">
+ <ClInclude Include="..\src\lib\platform\windows\stdint.h">
<Filter>platform\windows</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\cec.h" />
<ClInclude Include="..\include\cecloader.h" />
- <ClInclude Include="..\src\lib\platform\os.h" />
- <ClInclude Include="..\src\lib\platform\threads\mutex.h" />
- <ClInclude Include="..\src\lib\platform\threads\threads.h" />
- <ClInclude Include="..\src\lib\platform\timeutils.h" />
- <ClInclude Include="..\src\lib\platform\windows\dlfcn-win32.h" />
- <ClInclude Include="..\src\lib\platform\windows\os-threads.h" />
- <ClInclude Include="..\src\lib\platform\windows\os-types.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\lib\platform\windows\dlfcn-win32.cpp" />
<ClCompile Include="..\src\testclient\main.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="platform">
<UniqueIdentifier>{f08c0a80-22d9-4bdd-90de-b9cf5fa88f99}</UniqueIdentifier>
</Filter>
- <Filter Include="platform\threads">
- <UniqueIdentifier>{fb28e188-b2a5-48d3-9010-b56024b19850}</UniqueIdentifier>
- </Filter>
- <Filter Include="platform\windows">
- <UniqueIdentifier>{a8b22b54-3252-44fb-a499-e42f9bac0e15}</UniqueIdentifier>
- </Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\cec.h">
<ClInclude Include="..\include\cecloader.h">
<Filter>exports</Filter>
</ClInclude>
- <ClInclude Include="..\src\lib\platform\os.h">
- <Filter>platform</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\timeutils.h">
- <Filter>platform</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\dlfcn-win32.h">
- <Filter>platform\windows</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\os-threads.h">
- <Filter>platform\windows</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\windows\os-types.h">
- <Filter>platform\windows</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\threads\mutex.h">
- <Filter>platform\threads</Filter>
- </ClInclude>
- <ClInclude Include="..\src\lib\platform\threads\threads.h">
- <Filter>platform\threads</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\testclient\main.cpp" />
- <ClCompile Include="..\src\lib\platform\windows\dlfcn-win32.cpp">
- <Filter>platform\windows</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="testclient.rc" />
m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
m_lastInitiator(CECDEVICE_UNKNOWN),
m_strDeviceName(strDeviceName),
+ m_communication(NULL),
m_controller(controller),
m_bMonitor(false),
m_iStandardLineTimeout(3),
m_iRetryLineTimeout(3),
m_iLastTransmission(0)
{
- m_communication = new CAdapterCommunication(this);
m_logicalAddresses.Clear();
m_logicalAddresses.Set(iLogicalAddress);
m_types.clear();
m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
m_strDeviceName(strDeviceName),
m_types(types),
+ m_communication(NULL),
m_controller(controller),
m_bMonitor(false),
m_iStandardLineTimeout(3),
m_iRetryLineTimeout(3),
m_iLastTransmission(0)
{
- m_communication = new CAdapterCommunication(this);
m_logicalAddresses.Clear();
for (int iPtr = 0; iPtr < 16; iPtr++)
{
{
bool bReturn(false);
CLockObject lock(m_mutex);
- if (!m_communication)
+ if (m_communication)
{
- CLibCEC::AddLog(CEC_LOG_ERROR, "no connection handler found");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "existing connection handler found");
return bReturn;
}
+ m_communication = new CAdapterCommunication(this, strPort, iBaudRate);
+
/* check for an already opened connection */
if (m_communication->IsOpen())
{
bool bConnected(false), bPinged(false);
/* open a new connection */
- while (iNow < iTarget && (bConnected = m_communication->Open(strPort, iBaudRate, iTimeoutMs)) == false)
+ while (iNow < iTarget && (bConnected = m_communication->Open(iTimeoutMs)) == false)
{
CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
Sleep(500);
{
CLockObject lock(m_mutex);
if (m_commandBuffer.Pop(command))
- {
bParseFrame = true;
- }
else if (m_communication->IsOpen() && m_communication->Read(msg, 50))
{
if ((bParseFrame = (ParseMessage(msg) && !IsStopped())) == true)
using namespace CEC;
using namespace PLATFORM;
-CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor) :
+CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) :
m_port(NULL),
m_processor(processor),
m_iLineTimeout(0),
m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN)
{
- m_port = new PLATFORM::CSerialPort;
+ m_port = new PLATFORM::CSerialPort(strPort, iBaudRate);
}
CAdapterCommunication::~CAdapterCommunication(void)
}
}
-bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38400 */, uint32_t iTimeoutMs /* = 10000 */)
+bool CAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */)
{
uint64_t iNow = GetTimeMs();
uint64_t iTimeout = iNow + iTimeoutMs;
bool bConnected(false);
while (!bConnected && iNow < iTimeout)
{
- if ((bConnected = m_port->Open(strPort, iBaudRate)) == false)
+ if ((bConnected = m_port->Open(iTimeout)) == false)
{
- strError.Format("error opening serial port '%s': %s", strPort, m_port->GetError().c_str());
+ strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str());
Sleep(250);
iNow = GetTimeMs();
}
return bTransmitSucceeded && !bError;
}
-void CAdapterCommunication::AddData(uint8_t *data, uint8_t iLen)
+void CAdapterCommunication::AddData(uint8_t *data, size_t iLen)
{
CLockObject lock(m_mutex);
- for (uint8_t iPtr = 0; iPtr < iLen; iPtr++)
+ for (size_t iPtr = 0; iPtr < iLen; iPtr++)
m_inBuffer.Push(data[iPtr]);
m_rcvCondition.Signal();
bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout)
{
- int32_t iBytesRead;
- uint8_t buff[1024];
+ ssize_t iBytesRead;
+ uint8_t buff[256];
if (!m_port)
return false;
iBytesRead = m_port->Read(buff, sizeof(buff), iTimeout);
if (iBytesRead < 0 || iBytesRead > 256)
{
- CStdString strError;
- strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
- CLibCEC::AddLog(CEC_LOG_ERROR, strError);
+ CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
return false;
}
else if (iBytesRead > 0)
- AddData(buff, (uint8_t) iBytesRead);
+ {
+ AddData(buff, iBytesRead);
+ }
return iBytesRead > 0;
}
{
CLockObject adapterLock(m_mutex);
CLockObject lock(msg->mutex);
- if (m_port->Write(msg->packet.data, msg->Size()) != (int32_t) msg->Size())
+ if (m_port->Write(msg->packet.data, msg->Size()) != (ssize_t) msg->Size())
{
CStdString strError;
strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
namespace PLATFORM
{
- class CSerialPort;
+ class ISocket;
}
namespace CEC
class CAdapterCommunication : private PLATFORM::CThread
{
public:
- CAdapterCommunication(CCECProcessor *processor);
+ CAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate = 38400);
virtual ~CAdapterCommunication();
- bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
+ bool Open(uint32_t iTimeoutMs = 10000);
bool Read(CCECAdapterMessage &msg, uint32_t iTimeout = 1000);
bool Write(CCECAdapterMessage *data);
void Close(void);
private:
void SendMessageToAdapter(CCECAdapterMessage *msg);
void WriteNextCommand(void);
- void AddData(uint8_t *data, uint8_t iLen);
+ void AddData(uint8_t *data, size_t iLen);
bool ReadFromDevice(uint32_t iTimeout);
- PLATFORM::CSerialPort * m_port;
+ PLATFORM::ISocket * m_port;
CCECProcessor * m_processor;
PLATFORM::SyncedBuffer<uint8_t> m_inBuffer;
PLATFORM::SyncedBuffer<CCECAdapterMessage *> m_outBuffer;
while (!bReturn && ++iTries <= iMaxTries)
{
m_expectedResponse = expectedResponse;
- if ((bReturn = m_processor->Transmit(command)))
+ if ((bReturn = m_processor->Transmit(command)) == true)
{
CLibCEC::AddLog(CEC_LOG_DEBUG, "command transmitted");
if (bExpectResponse)
#include "../util/timeutils.h"
#include <stdio.h>
#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <poll.h>
namespace PLATFORM
{
+ // Standard sockets
+ //@{
inline void SocketClose(socket_t socket)
{
- if (socket != INVALID_SOCKET)
+ if (socket != INVALID_SOCKET_VALUE)
close(socket);
}
inline void SocketSetBlocking(socket_t socket, bool bSetTo)
{
-// return bSetTo ?
-// fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK) == 0 :
-// fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK) == 0;
- fcntl(socket, F_SETFL, bSetTo ? FNDELAY : 0);
+ if (socket != INVALID_SOCKET_VALUE)
+ {
+ if (bSetTo)
+ fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
+ else
+ fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+ }
}
- inline int64_t SocketWrite(socket_t socket, int *iError, uint8_t* data, uint32_t len)
+ inline ssize_t SocketWrite(socket_t socket, int *iError, void* data, size_t len)
{
fd_set port;
- if (socket == -1)
+ if (socket == INVALID_SOCKET_VALUE)
{
*iError = EINVAL;
return -1;
}
- int64_t iBytesWritten = 0;
+ ssize_t iBytesWritten(0);
struct timeval *tv(NULL);
- while (iBytesWritten < len)
+ while (iBytesWritten < (ssize_t)len)
{
FD_ZERO(&port);
FD_SET(socket, &port);
return -1;
}
- returnv = write(socket, data + iBytesWritten, len - iBytesWritten);
+ returnv = write(socket, (char*)data + iBytesWritten, len - iBytesWritten);
if (returnv == -1)
{
*iError = errno;
return iBytesWritten;
}
- inline int32_t SocketRead(socket_t socket, int *iError, uint8_t* data, uint32_t len, uint64_t iTimeoutMs /*= 0*/)
+ inline ssize_t SocketRead(socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
{
fd_set port;
struct timeval timeout, *tv;
int64_t iNow(0), iTarget(0);
- int32_t iBytesRead = 0;
+ ssize_t iBytesRead(0);
*iError = 0;
- if (socket == -1)
+ if (socket == INVALID_SOCKET_VALUE)
{
*iError = EINVAL;
return -1;
iTarget = iNow + (int64_t) iTimeoutMs;
}
- while (iBytesRead < (int32_t) len && (iTimeoutMs == 0 || iTarget > iNow))
+ while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
{
if (iTimeoutMs == 0)
{
break; //nothing to read
}
- returnv = read(socket, data + iBytesRead, len - iBytesRead);
+ returnv = read(socket, (char*)data + iBytesRead, len - iBytesRead);
if (returnv == -1)
{
*iError = errno;
return iBytesRead;
}
+ //@}
+
+ // TCP
+ //@{
+ inline void TcpSocketClose(tcp_socket_t socket)
+ {
+ SocketClose(socket);
+ }
+
+ inline void TcpSocketShutdown(tcp_socket_t socket)
+ {
+ if (socket != INVALID_SOCKET_VALUE)
+ shutdown(socket, SHUT_RDWR);
+ }
+
+ inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len)
+ {
+ if (socket == INVALID_SOCKET_VALUE)
+ {
+ *iError = EINVAL;
+ return -1;
+ }
+
+ ssize_t iReturn = send(socket, data, len, 0);
+ if (iReturn < (ssize_t)len)
+ *iError = errno;
+ return iReturn;
+ }
+
+ inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
+ {
+ int64_t iNow(0), iTarget(0);
+ ssize_t iBytesRead(0);
+ *iError = 0;
+
+ if (socket == INVALID_SOCKET_VALUE)
+ {
+ *iError = EINVAL;
+ return -1;
+ }
+
+ if (iTimeoutMs > 0)
+ {
+ iNow = GetTimeMs();
+ iTarget = iNow + (int64_t) iTimeoutMs;
+ }
+
+ struct pollfd fds;
+ fds.fd = socket;
+ fds.events = POLLIN;
+ fds.revents = 0;
+
+ while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
+ {
+ if (iTimeoutMs > 0)
+ {
+ int iPollResult = poll(&fds, 1, iTarget - iNow);
+ if (iPollResult == 0)
+ {
+ *iError = ETIMEDOUT;
+ return -ETIMEDOUT;
+ }
+ }
+
+ ssize_t iReadResult = (iTimeoutMs > 0) ?
+ recv(socket, (char*)data + iBytesRead, len - iBytesRead, MSG_DONTWAIT) :
+ recv(socket, data, len, MSG_WAITALL);
+ if (iReadResult < 0)
+ {
+ if (errno == EAGAIN && iTimeoutMs > 0)
+ continue;
+ *iError = errno;
+ return -errno;
+ }
+ else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0))
+ {
+ *iError = ECONNRESET;
+ return -ECONNRESET;
+ }
+
+ iBytesRead += iReadResult;
+
+ if (iTimeoutMs > 0)
+ iNow = GetTimeMs();
+ }
+
+ if (iBytesRead < (ssize_t)len)
+ *iError = ETIMEDOUT;
+ return iBytesRead;
+ }
+
+ inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
+ {
+ struct addrinfo hints;
+ char service[33];
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ sprintf(service, "%d", iPort);
+
+ *iError = getaddrinfo(strHost, service, &hints, info);
+ return !(*iError);
+ }
+
+ inline int TcpGetSocketError(tcp_socket_t socket)
+ {
+ int iReturn(0);
+ socklen_t optLen = sizeof(socket_t);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&iReturn, &optLen);
+ return iReturn;
+ }
+
+ inline bool TcpSetNoDelay(tcp_socket_t socket)
+ {
+ int iSetTo(1);
+ setsockopt(socket, SOL_TCP, TCP_NODELAY, &iSetTo, sizeof(iSetTo));
+ return true;
+ }
+
+ inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
+ {
+ *iError = 0;
+ int iConnectResult = connect(socket, addr->ai_addr, addr->ai_addrlen);
+ if (iConnectResult == -1)
+ {
+ if (errno == EINPROGRESS)
+ {
+ struct pollfd pfd;
+ pfd.fd = socket;
+ pfd.events = POLLOUT;
+ pfd.revents = 0;
+
+ int iPollResult = poll(&pfd, 1, iTimeout);
+ if (iPollResult == 0)
+ *iError = ETIMEDOUT;
+ else if (iPollResult == -1)
+ *iError = errno;
+
+ socklen_t errlen = sizeof(int);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)iError, &errlen);
+ }
+ else
+ {
+ *iError = errno;
+ }
+ }
+
+ return *iError == 0;
+ }
+ //@}
}
+++ /dev/null
-#pragma once
-/*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing <license@pulse-eight.com>
- * http://www.pulse-eight.com/
- * http://www.pulse-eight.net/
- */
-
-#include "../os.h"
-#include "../sockets/socket.h"
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <poll.h>
-
-namespace PLATFORM
-{
- inline void TcpShutdownSocket(socket_t socket)
- {
- shutdown(socket, SHUT_RDWR);
- }
-
- inline int TcpGetSocketError(socket_t socket)
- {
- int iReturn(0);
- socklen_t optLen = sizeof(socket_t);
- getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&iReturn, &optLen);
- return iReturn;
- }
-
- inline bool TcpSetNoDelay(socket_t socket)
- {
- int iSetTo(1);
- setsockopt(socket, SOL_TCP, TCP_NODELAY, &iSetTo, sizeof(iSetTo));
- return true;
- }
-
- inline bool TcpConnectSocket(socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
- {
- bool bConnected = (connect(socket, addr->ai_addr, addr->ai_addrlen) == 0);
- if (!bConnected && errno == EINPROGRESS)
- {
- struct pollfd pfd;
- pfd.fd = socket;
- pfd.events = POLLOUT;
- pfd.revents = 0;
-
- int iPollResult = poll(&pfd, 1, iTimeout);
- if (iPollResult == 0)
- *iError = ETIMEDOUT;
- else if (iPollResult == -1)
- *iError = errno;
- else
- bConnected = true;
- }
- else
- {
- *iError = errno;
- }
-
- return bConnected;
- }
-
- inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
- {
- struct addrinfo hints;
- char service[33];
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- sprintf(service, "%d", iPort);
-
- *iError = getaddrinfo(strHost, service, &hints, info);
- return !(*iError);
- }
-}
#define DECLSPEC
typedef int socket_t;
-#define INVALID_SOCKET (-1)
-#define SOCKET_ERROR (-1)
-
+typedef socket_t tcp_socket_t;
+#define INVALID_SOCKET_VALUE (-1)
+typedef socket_t serial_socket_t;
+#define INVALID_SERIAL_SOCKET_VALUE (-1)
#include <fcntl.h>
#include "../sockets/serialport.h"
#include "../util/baudrate.h"
+#include "../posix/os-socket.h"
#if defined(__APPLE__)
#ifndef XCASE
using namespace std;
using namespace PLATFORM;
-CSerialPort::CSerialPort()
+void CSerialSocket::Close(void)
{
- m_bToStdOut = false;
+ SocketClose(m_socket);
+}
+
+void CSerialSocket::Shutdown(void)
+{
+ SocketClose(m_socket);
+}
+
+ssize_t CSerialSocket::Write(void* data, size_t len)
+{
+ return SocketWrite(m_socket, &m_iError, data, len);
+}
+
+ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */)
+{
+ return SocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
}
//setting all this stuff up is a pain in the ass
-bool CSerialPort::Open(string name, uint32_t baudrate, uint8_t databits /* = 8 */, uint8_t stopbits /* = 1 */, uint8_t parity /* = PAR_NONE */)
+bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */)
{
- m_strName = name;
+ iTimeoutMs = 0;
CLockObject lock(m_mutex);
- if (databits < 5 || databits > 8)
+ if (m_iDatabits != SERIAL_DATA_BITS_FIVE && m_iDatabits != SERIAL_DATA_BITS_SIX &&
+ m_iDatabits != SERIAL_DATA_BITS_SEVEN && m_iDatabits != SERIAL_DATA_BITS_EIGHT)
{
m_strError = "Databits has to be between 5 and 8";
return false;
}
- if (stopbits != 1 && stopbits != 2)
+ if (m_iStopbits != SERIAL_STOP_BITS_ONE && m_iStopbits != SERIAL_STOP_BITS_TWO)
{
m_strError = "Stopbits has to be 1 or 2";
return false;
}
- if (parity != PAR_NONE && parity != PAR_EVEN && parity != PAR_ODD)
+ if (m_iParity != SERIAL_PARITY_NONE && m_iParity != SERIAL_PARITY_EVEN && m_iParity != SERIAL_PARITY_ODD)
{
m_strError = "Parity has to be none, even or odd";
return false;
}
- m_socket = open(name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+ m_socket = open(m_strName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
- if (m_socket == INVALID_SOCKET)
+ if (m_socket == INVALID_SERIAL_SOCKET_VALUE)
{
m_strError = strerror(errno);
return false;
SocketSetBlocking(m_socket, false);
- if (!SetBaudRate(baudrate))
+ if (!SetBaudRate(m_iBaudrate))
return false;
m_options.c_cflag |= (CLOCAL | CREAD);
m_options.c_cflag &= ~HUPCL;
m_options.c_cflag &= ~CSIZE;
- if (databits == 5) m_options.c_cflag |= CS5;
- if (databits == 6) m_options.c_cflag |= CS6;
- if (databits == 7) m_options.c_cflag |= CS7;
- if (databits == 8) m_options.c_cflag |= CS8;
+ if (m_iDatabits == SERIAL_DATA_BITS_FIVE) m_options.c_cflag |= CS5;
+ if (m_iDatabits == SERIAL_DATA_BITS_SIX) m_options.c_cflag |= CS6;
+ if (m_iDatabits == SERIAL_DATA_BITS_SEVEN) m_options.c_cflag |= CS7;
+ if (m_iDatabits == SERIAL_DATA_BITS_EIGHT) m_options.c_cflag |= CS8;
m_options.c_cflag &= ~PARENB;
- if (parity == PAR_EVEN || parity == PAR_ODD)
+ if (m_iParity == SERIAL_PARITY_EVEN || m_iParity == SERIAL_PARITY_ODD)
m_options.c_cflag |= PARENB;
- if (parity == PAR_ODD)
+ if (m_iParity == SERIAL_PARITY_ODD)
m_options.c_cflag |= PARODD;
#ifdef CRTSCTS
m_options.c_cflag &= ~CNEW_RTSCTS;
#endif
- if (stopbits == 1) m_options.c_cflag &= ~CSTOPB;
+ if (m_iStopbits == SERIAL_STOP_BITS_ONE) m_options.c_cflag &= ~CSTOPB;
else m_options.c_cflag |= CSTOPB;
//I guessed a little here
m_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | XCASE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | TOSTOP);
- if (parity == PAR_NONE)
- {
+ if (m_iParity == SERIAL_PARITY_NONE)
m_options.c_iflag &= ~INPCK;
- }
else
- {
m_options.c_iflag |= INPCK | ISTRIP;
- }
m_options.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT | INLCR | IGNCR | ICRNL | IUCLC | IMAXBEL);
m_options.c_oflag &= ~(OPOST | ONLCR | OCRNL);
}
SocketSetBlocking(m_socket, true);
+ m_bIsOpen = true;
return true;
}
-bool CSerialPort::SetBaudRate(uint32_t baudrate)
+bool CSerialSocket::SetBaudRate(uint32_t baudrate)
{
int rate = IntToBaudrate(baudrate);
if (rate == -1)
m_strError = buff;
return false;
}
-
+
//get the current port attributes
if (tcgetattr(m_socket, &m_options) != 0)
{
m_strError = strerror(errno);
return false;
}
-
+
if (cfsetospeed(&m_options, rate) != 0)
{
m_strError = strerror(errno);
namespace PLATFORM
{
- #define PAR_NONE 0
- #define PAR_EVEN 1
- #define PAR_ODD 2
+ enum SerialParity
+ {
+ SERIAL_PARITY_NONE = 0,
+ SERIAL_PARITY_EVEN,
+ SERIAL_PARITY_ODD
+ };
+
+ enum SerialStopBits
+ {
+ SERIAL_STOP_BITS_ONE = 1,
+ SERIAL_STOP_BITS_TWO = 2
+ };
+
+ enum SerialDataBits
+ {
+ SERIAL_DATA_BITS_FIVE = 5,
+ SERIAL_DATA_BITS_SIX = 6,
+ SERIAL_DATA_BITS_SEVEN = 7,
+ SERIAL_DATA_BITS_EIGHT = 8
+ };
- class CSerialPort : public CSocket
+ class CSerialSocket : public CCommonSocket<serial_socket_t>
{
public:
- CSerialPort(void);
- virtual ~CSerialPort(void) {}
+ CSerialSocket(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) :
+ CCommonSocket<serial_socket_t>(INVALID_SERIAL_SOCKET_VALUE, strName),
+ m_bIsOpen(false),
+ m_iBaudrate(iBaudrate),
+ m_iDatabits(iDatabits),
+ m_iStopbits(iStopbits),
+ m_iParity(iParity) {}
- bool Open(std::string name, uint32_t baudrate, uint8_t databits = 8, uint8_t stopbits = 1, uint8_t parity = PAR_NONE);
+ virtual ~CSerialSocket(void) {}
- CStdString GetName(void) const
+ virtual bool Open(uint64_t iTimeoutMs = 0);
+ virtual void Close(void);
+ virtual void Shutdown(void);
+ virtual ssize_t Write(void* data, size_t len);
+ virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0);
+
+ virtual bool IsOpen(void)
{
- CStdString strName;
- strName = m_strName;
- return strName;
+ return m_socket != INVALID_SERIAL_SOCKET_VALUE &&
+ m_bIsOpen;
}
- #ifdef __WINDOWS__
- virtual bool IsOpen(void);
- virtual void Close(void);
- virtual int64_t Write(uint8_t* data, uint32_t len);
- virtual int32_t Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs = 0);
- #endif
+ virtual bool SetBaudRate(uint32_t baudrate);
- private:
- bool SetBaudRate(uint32_t baudrate);
+ protected:
+ #ifndef __WINDOWS__
+ struct termios m_options;
+ #endif
- private:
- #ifdef __WINDOWS__
- void FormatWindowsError(int iErrorCode, CStdString &strMessage);
- bool SetTimeouts(bool bBlocking);
+ bool m_bIsOpen;
+ uint32_t m_iBaudrate;
+ SerialDataBits m_iDatabits;
+ SerialStopBits m_iStopbits;
+ SerialParity m_iParity;
+ };
- HANDLE m_handle;
- bool m_bIsOpen;
- uint32_t m_iBaudrate;
- uint8_t m_iDatabits;
- uint8_t m_iStopbits;
- uint8_t m_iParity;
- int64_t m_iTimeout;
- SyncedBuffer<uint8_t> m_buffer;
- HANDLE m_ovHandle;
- #else
- struct termios m_options;
- #endif
- std::string m_strName;
- bool m_bToStdOut;
+ class CSerialPort : public CProtectedSocket<CSerialSocket>
+ {
+ public:
+ CSerialPort(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) :
+ CProtectedSocket<CSerialSocket> (new CSerialSocket(strName, iBaudrate, iDatabits, iStopbits, iParity)) {}
+ virtual ~CSerialPort(void) {}
};
};
namespace PLATFORM
{
- class CSocket : public PreventCopy
+ class ISocket : public PreventCopy
{
- public:
- CSocket(void) :
- m_socket(INVALID_SOCKET),
- m_iError(0) {};
+ public:
+ ISocket(void) {};
+ virtual ~ISocket(void) {}
- virtual ~CSocket(void)
- {
- Close();
- }
+ virtual bool Open(uint64_t iTimeoutMs = 0) = 0;
+ virtual void Close(void) = 0;
+ virtual void Shutdown(void) = 0;
+ virtual bool IsOpen(void) = 0;
+ virtual ssize_t Write(void* data, size_t len) = 0;
+ virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) = 0;
+ virtual CStdString GetError(void) = 0;
+ virtual int GetErrorNumber(void) = 0;
+ virtual CStdString GetName(void) = 0;
+ };
- virtual bool IsOpen(void)
- {
- CLockObject lock(m_mutex);
- return m_socket != INVALID_SOCKET &&
- m_socket != SOCKET_ERROR;
- }
+ template <typename _SType>
+ class CCommonSocket : public ISocket
+ {
+ public:
+ CCommonSocket(_SType initialSocketValue, const CStdString &strName) :
+ m_socket(initialSocketValue),
+ m_strName(strName),
+ m_iError(0) {}
- virtual void Close(void)
- {
- CLockObject lock(m_mutex);
- SocketClose(m_socket);
- m_socket = INVALID_SOCKET;
- m_strError = "";
- }
+ virtual ~CCommonSocket(void) {}
- virtual int64_t Write(uint8_t* data, uint32_t len)
- {
- CLockObject lock(m_mutex);
- int64_t iReturn = SocketWrite(m_socket, &m_iError, data, len);
- m_strError = strerror(m_iError);
- return iReturn;
- }
+ virtual CStdString GetError(void)
+ {
+ CStdString strError;
+ strError = m_strError.IsEmpty() && m_iError != 0 ? strerror(m_iError) : m_strError;
+ return strError;
+ }
+
+ virtual int GetErrorNumber(void)
+ {
+ return m_iError;
+ }
+
+ virtual CStdString GetName(void)
+ {
+ CStdString strName;
+ strName = m_strName;
+ return strName;
+ }
+
+ protected:
+ _SType m_socket;
+ CStdString m_strError;
+ CStdString m_strName;
+ int m_iError;
+ CMutex m_mutex;
+ };
+
+ template <typename _Socket>
+ class CProtectedSocket : public ISocket
+ {
+ public:
+ CProtectedSocket(_Socket *socket) :
+ m_socket(socket),
+ m_iUseCount(0) {}
+
+ virtual ~CProtectedSocket(void)
+ {
+ Close();
+ delete m_socket;
+ }
- virtual int32_t Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs = 0)
+ virtual bool Open(uint64_t iTimeoutMs = 0)
+ {
+ bool bReturn(false);
+ if (m_socket && WaitReady())
{
- CLockObject lock(m_mutex);
- int32_t iReturn = SocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
- m_strError = strerror(m_iError);
- return iReturn;
+ bReturn = m_socket->Open(iTimeoutMs);
+ MarkReady();
}
+ return bReturn;
+ }
- virtual CStdString GetError(void) const
+ virtual void Close(void)
+ {
+ if (m_socket && WaitReady())
{
- CStdString strReturn;
- strReturn = m_strError;
- return strReturn;
+ m_socket->Close();
+ MarkReady();
}
+ }
- virtual int GetErrorNumber(void) const
+ virtual void Shutdown(void)
+ {
+ if (m_socket && WaitReady())
{
- return m_iError;
+ m_socket->Shutdown();
+ MarkReady();
}
+ }
+
+ virtual bool IsOpen(void)
+ {
+ CLockObject lock(m_mutex);
+ return m_socket && m_socket->IsOpen();
+ }
+
+ virtual bool IsBusy(void)
+ {
+ CLockObject lock(m_mutex);
+ return m_socket && m_iUseCount > 0;
+ }
+
+ virtual int GetUseCount(void)
+ {
+ CLockObject lock(m_mutex);
+ return m_iUseCount;
+ }
+
+ virtual ssize_t Write(void* data, size_t len)
+ {
+ if (!m_socket || !WaitReady())
+ return EINVAL;
+
+ ssize_t iReturn = m_socket->Write(data, len);
+ MarkReady();
+
+ return iReturn;
+ }
+
+ virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0)
+ {
+ if (!m_socket || !WaitReady())
+ return EINVAL;
+
+ ssize_t iReturn = m_socket->Read(data, len, iTimeoutMs);
+ MarkReady();
+
+ return iReturn;
+ }
+
+ virtual CStdString GetError(void)
+ {
+ CStdString strError;
+ CLockObject lock(m_mutex);
+ strError = m_socket ? m_socket->GetError() : "";
+ return strError;
+ }
+
+ virtual int GetErrorNumber(void)
+ {
+ CLockObject lock(m_mutex);
+ return m_socket ? m_socket->GetErrorNumber() : EINVAL;
+ }
+
+ virtual CStdString GetName(void)
+ {
+ CStdString strName;
+ CLockObject lock(m_mutex);
+ strName = m_socket ? m_socket->GetName() : "";
+ return strName;
+ }
+
+ private:
+ bool WaitReady(void)
+ {
+ CLockObject lock(m_mutex);
+ if (m_iUseCount > 0)
+ m_condition.Wait(m_mutex);
+
+ if (m_iUseCount > 0)
+ return false;
+
+ ++m_iUseCount;
+ return true;
+ }
+
+ void MarkReady(void)
+ {
+ CLockObject lock(m_mutex);
+ if (m_iUseCount > 0)
+ --m_iUseCount;
+ m_condition.Broadcast();
+ }
- protected:
- socket_t m_socket;
- CStdString m_strError;
- int m_iError;
- CMutex m_mutex;
+ _Socket *m_socket;
+ CMutex m_mutex;
+ CCondition m_condition;
+ int m_iUseCount;
};
};
#include "socket.h"
-#if defined(__WINDOWS__)
-#include "../windows/os-tcp.h"
-#else
-#include "../posix/os-tcp.h"
-#endif
-
using namespace std;
namespace PLATFORM
{
- class CTcpSocket : public CSocket
+ class CTcpSocket : public CCommonSocket<tcp_socket_t>
{
public:
- CTcpSocket(void) {};
+ CTcpSocket(const CStdString &strHostname, uint16_t iPort) :
+ CCommonSocket<tcp_socket_t>(INVALID_SOCKET_VALUE, strHostname),
+ m_iPort(iPort) {}
+
virtual ~CTcpSocket(void) {}
- virtual bool Open(const CStdString &strHostname, uint16_t iPort, uint64_t nTimeout)
+ virtual bool Open(uint64_t iTimeoutMs = 0)
{
bool bReturn(false);
struct addrinfo *address(NULL), *addr(NULL);
- CLockObject lock(m_mutex);
- if (!TcpResolveAddress(strHostname.c_str(), iPort, &m_iError, &address))
+ if (!TcpResolveAddress(m_strName.c_str(), m_iPort, &m_iError, &address))
{
m_strError = strerror(m_iError);
return bReturn;
for(addr = address; !bReturn && addr; addr = addr->ai_next)
{
- m_socket = TcpCreateSocket(addr, &m_iError, nTimeout);
- if (m_socket != INVALID_SOCKET && m_socket != SOCKET_ERROR)
+ m_socket = TcpCreateSocket(addr, &m_iError, iTimeoutMs);
+ if (m_socket != INVALID_SOCKET_VALUE)
bReturn = true;
else
m_strError = strerror(m_iError);
return bReturn;
}
+ virtual void Close(void)
+ {
+ TcpSocketClose(m_socket);
+ m_socket = INVALID_SOCKET_VALUE;
+ }
+
virtual void Shutdown(void)
{
- CLockObject lock(m_mutex);
- if (m_socket != INVALID_SOCKET && m_socket != SOCKET_ERROR)
- TcpShutdownSocket(m_socket);
- m_socket = INVALID_SOCKET;
- m_strError = "";
+ TcpSocketShutdown(m_socket);
+ m_socket = INVALID_SOCKET_VALUE;
+ }
+
+ virtual ssize_t Write(void* data, size_t len)
+ {
+ return TcpSocketWrite(m_socket, &m_iError, data, len);
+ }
+
+ virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0)
+ {
+ return TcpSocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
}
- protected:
- virtual socket_t TcpCreateSocket(struct addrinfo* addr, int* iError, uint64_t iTimeout)
- {
- socket_t fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
- if (fdSock == INVALID_SOCKET || fdSock == SOCKET_ERROR)
+ virtual bool IsOpen(void)
{
- *iError = errno;
- return (socket_t)SOCKET_ERROR;
+ return m_socket != INVALID_SOCKET_VALUE;
}
- if (!TcpConnectSocket(fdSock, addr, iError, iTimeout))
+ protected:
+ virtual tcp_socket_t TcpCreateSocket(struct addrinfo* addr, int* iError, uint64_t iTimeout)
{
- SocketClose(fdSock);
- return (socket_t)SOCKET_ERROR;
+ tcp_socket_t fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if (fdSock == INVALID_SOCKET_VALUE)
+ {
+ *iError = errno;
+ return (tcp_socket_t)INVALID_SOCKET_VALUE;
+ }
+
+ if (!TcpConnectSocket(fdSock, addr, iError, iTimeout))
+ {
+ TcpSocketClose(fdSock);
+ return (tcp_socket_t)INVALID_SOCKET_VALUE;
+ }
+
+ TcpSetNoDelay(fdSock);
+
+ return fdSock;
}
- TcpSetNoDelay(fdSock);
+ uint16_t m_iPort;
+ };
- return fdSock;
- }
+ class CTcpConnection : public CProtectedSocket<CTcpSocket>
+ {
+ public:
+ CTcpConnection(const CStdString &strHostname, uint16_t iPort) :
+ CProtectedSocket<CTcpSocket> (new CTcpSocket(strHostname, iPort)) {}
+ virtual ~CTcpConnection(void) {}
};
};
}
}
- inline void SocketClose(socket_t socket)
+ // Serial port
+ //@{
+ inline void SerialSocketClose(serial_socket_t socket)
{
- if (socket != SOCKET_ERROR && socket != INVALID_SOCKET)
- closesocket(socket);
+ if (socket != INVALID_HANDLE_VALUE)
+ CloseHandle(socket);
}
- inline void SocketSetBlocking(socket_t socket, bool bSetTo)
+ inline ssize_t SerialSocketWrite(serial_socket_t socket, int *iError, void* data, size_t len)
{
- u_long nVal = bSetTo ? 1 : 0;
- ioctlsocket(socket, FIONBIO, &nVal);
+ DWORD iBytesWritten(0);
+ if (socket != INVALID_HANDLE_VALUE)
+ {
+ if (!WriteFile(socket, data, len, &iBytesWritten, NULL))
+ {
+ *iError = GetLastError();
+ return -1;
+ }
+ return (ssize_t)iBytesWritten;
+ }
+
+ return -1;
}
- inline int64_t SocketWrite(socket_t socket, int *iError, uint8_t* data, uint32_t len)
+ inline ssize_t SerialSocketRead(serial_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
{
- int64_t iReturn(-1);
- if (socket != SOCKET_ERROR && socket != INVALID_SOCKET)
+ DWORD iBytesRead(0);
+ if (socket != INVALID_HANDLE_VALUE)
{
- iReturn = send(socket, (char*)data, len, 0);
- if (iReturn <= 0)
- *iError = GetSocketError();
+ if(!ReadFile(socket, data, len, &iBytesRead, NULL) != 0)
+ {
+ *iError = GetLastError();
+ return -1;
+ }
+ return (ssize_t)iBytesRead;
}
- return iReturn;
+ return -1;
}
+ //@}
- inline int SocketReadFixed(socket_t socket, char *buf, int iLength, int iFlags)
+ // TCP
+ //@{
+ inline void TcpSocketSetBlocking(tcp_socket_t socket, bool bSetTo)
{
- int iReadResult(1), iBytesRead(0);
+ u_long iSetTo = bSetTo ? 0 : 1;
+ ioctlsocket(socket, FIONBIO, &iSetTo);
+ }
- if ((iFlags & MSG_WAITALL) == 0)
- return recv(socket, buf, iLength, iFlags);
+ inline void TcpSocketClose(tcp_socket_t socket)
+ {
+ closesocket(socket);
+ }
- iFlags &= ~MSG_WAITALL;
- while(iBytesRead < iLength && iReadResult > 0)
+ inline void TcpSocketShutdown(tcp_socket_t socket)
+ {
+ if (socket != INVALID_SOCKET &&
+ socket != SOCKET_ERROR)
+ shutdown(socket, SHUT_RDWR);
+ }
+
+ inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len)
+ {
+ if (socket == INVALID_SOCKET ||
+ socket == SOCKET_ERROR)
{
- if ((iReadResult = recv(socket, buf + iBytesRead, iLength - iBytesRead, iFlags)) < 0)
- return iReadResult;
+ *iError = EINVAL;
+ return -1;
}
- return iLength - iBytesRead;
+
+ ssize_t iReturn = send(socket, (char*)data, len, 0);
+ if (iReturn < (ssize_t)len)
+ *iError = errno;
+ return iReturn;
}
- inline int32_t SocketRead(socket_t socket, void *buf, uint32_t nLen)
+ inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/)
{
- int iReadResult = SocketReadFixed(socket, (char *)buf, nLen, MSG_WAITALL);
+ int64_t iNow(0), iTarget(0);
+ ssize_t iBytesRead(0);
+ *iError = 0;
- if (iReadResult == -1)
- return GetSocketError();
- if (iReadResult < (int)nLen)
- return ECONNRESET;
+ if (socket == INVALID_SOCKET ||
+ socket == SOCKET_ERROR)
+ {
+ *iError = EINVAL;
+ return -1;
+ }
- return 0;
- }
+ if (iTimeoutMs > 0)
+ {
+ iNow = GetTimeMs();
+ iTarget = iNow + (int64_t) iTimeoutMs;
+ }
- inline int32_t SocketRead(socket_t socket, int *iError, uint8_t* data, uint32_t iLength, uint64_t iTimeoutMs)
- {
- int iReadResult(0);
- uint32_t iBytesRead(0);
fd_set fd_read;
struct timeval tv;
+ while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow))
+ {
+ if (iTimeoutMs > 0)
+ {
+ tv.tv_sec = (long)(iTimeoutMs / 1000);
+ tv.tv_usec = 1000 * (long)(iTimeoutMs % 1000);
- if (iTimeoutMs <= 0)
- return EINVAL;
+ FD_ZERO(&fd_read);
+ FD_SET(socket, &fd_read);
- uint64_t iNow = GetTimeMs();
- uint64_t iTarget = iNow + iTimeoutMs;
+ if (select(socket + 1, &fd_read, NULL, NULL, &tv) == 0)
+ return ETIMEDOUT;
+ TcpSocketSetBlocking(socket, false);
+ }
- while(iNow < iTarget && iBytesRead < iLength)
- {
- tv.tv_sec = (long)(iTarget - iNow / 1000);
- tv.tv_usec = (long)(1000 * (iTarget - iNow % 1000));
+ ssize_t iReadResult = (iTimeoutMs > 0) ?
+ recv(socket, (char*)data + iBytesRead, len - iBytesRead, MSG_WAITALL) :
+ recv(socket, (char*)data, len, MSG_WAITALL);
+ *iError = GetSocketError();
+ if (iReadResult < 0)
+ {
+ if (errno == EAGAIN && iTimeoutMs > 0)
+ continue;
+ *iError = errno;
+ return -1;
+ }
+ else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0))
+ {
+ *iError = ECONNRESET;
+ return -1;
+ }
- FD_ZERO(&fd_read);
- FD_SET(socket, &fd_read);
+ iBytesRead += iReadResult;
- if ((iReadResult = select(socket + 1, &fd_read, NULL, NULL, &tv)) == 0)
- return ETIMEDOUT;
+ if (iTimeoutMs > 0)
+ {
+ TcpSocketSetBlocking(socket, true);
+ iNow = GetTimeMs();
+ }
+ }
+ return 0;
+ }
- SocketSetBlocking(socket, false);
+ inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
+ {
+ struct addrinfo hints;
+ char service[33];
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ sprintf(service, "%d", iPort);
- iReadResult = SocketReadFixed(socket, (char *)data + iBytesRead, iLength - iBytesRead, 0);
+ *iError = getaddrinfo(strHost, service, &hints, info);
+ return !(*iError);
+ }
- SocketSetBlocking(socket, true);
+ inline int TcpGetSocketError(tcp_socket_t socket)
+ {
+ int iReturn(0);
+ socklen_t optLen = sizeof(tcp_socket_t);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen);
+ return iReturn;
+ }
- if (iReadResult == -1)
+ inline bool TcpSetNoDelay(tcp_socket_t socket)
+ {
+ int iSetTo(1);
+ setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo));
+ return true;
+ }
+
+ inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
+ {
+ TcpSocketSetBlocking(socket, false);
+
+ *iError = 0;
+ int iConnectResult = connect(socket, addr->ai_addr, addr->ai_addrlen);
+ if (iConnectResult == -1)
+ {
+ if (GetSocketError() == EINPROGRESS ||
+ GetSocketError() == EAGAIN)
{
- int iError = GetSocketError();
- if (iError == EAGAIN)
- continue;
- return iError;
- }
- else if (iReadResult == 0)
- return ECONNRESET;
+ fd_set fd_write, fd_except;
+ struct timeval tv;
+ tv.tv_sec = (long)(iTimeout / 1000);
+ tv.tv_usec = 1000 * (long)(iTimeout % 1000);
- iBytesRead += iReadResult;
+ FD_ZERO(&fd_write);
+ FD_ZERO(&fd_except);
+ FD_SET(socket, &fd_write);
+ FD_SET(socket, &fd_except);
+
+ int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv);
+ if (iPollResult == 0)
+ *iError = ETIMEDOUT;
+ else if (iPollResult == -1)
+ *iError = GetSocketError();
+ else
+ {
+ socklen_t errlen = sizeof(int);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen);
+ }
+ }
+ else
+ {
+ *iError = errno;
+ }
}
- return iBytesRead == iLength ? 0 : ECONNRESET;
+ TcpSocketSetBlocking(socket, true);
+
+ return *iError == 0;
}
}
+++ /dev/null
-#pragma once
-/*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing <license@pulse-eight.com>
- * http://www.pulse-eight.com/
- * http://www.pulse-eight.net/
- */
-
-#include "../os.h"
-#include "../sockets/socket.h"
-
-namespace PLATFORM
-{
- inline void TcpShutdownSocket(socket_t socket)
- {
- shutdown(socket, SHUT_RDWR);
- }
-
- inline int TcpResolveAddress(const CStdString &strHostname, uint16_t iPort, struct addrinfo *address)
- {
- struct addrinfo hints;
- char service[33];
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- sprintf(service, "%d", iPort);
-
- return getaddrinfo(strHostname.c_str(), service, &hints, &address);
- }
-
- inline int TcpGetSocketError()
- {
- int error = WSAGetLastError();
- switch(error)
- {
- case WSAEINPROGRESS: return EINPROGRESS;
- case WSAECONNRESET : return ECONNRESET;
- case WSAETIMEDOUT : return ETIMEDOUT;
- case WSAEWOULDBLOCK: return EAGAIN;
- default : return error;
- }
- }
-
- inline int TcpConnectSocket(struct addrinfo* addr, socket_t socket, int *iError, uint64_t iTimeout)
- {
- int nRes = 0;
- socklen_t errlen = sizeof(int);
-
- SocketSetBlocking(socket, false);
-
- /* connect to the other side */
- nRes = connect(socket, addr->ai_addr, addr->ai_addrlen);
-
- /* poll until a connection is established */
- if (nRes == -1)
- {
- if (TcpGetSocketError() == EINPROGRESS || TcpGetSocketError() == EAGAIN)
- {
- fd_set fd_write, fd_except;
- struct timeval tv;
- tv.tv_sec = (long)(iTimeout / 1000);
- tv.tv_usec = (long)(1000 * (iTimeout % 1000));
-
- FD_ZERO(&fd_write);
- FD_ZERO(&fd_except);
- FD_SET(socket, &fd_write);
- FD_SET(socket, &fd_except);
-
- nRes = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv);
- if (nRes == 0)
- {
- *iError = ETIMEDOUT;
- return SOCKET_ERROR;
- }
- else if (nRes == -1)
- {
- *iError = TcpGetSocketError();
- return SOCKET_ERROR;
- }
-
- /* check for errors */
- getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen);
- }
- else
- {
- *iError = TcpGetSocketError();
- }
- }
-
- SocketSetBlocking(socket, true);
-
- return 0;
- }
-
- inline bool TcpSetNoDelay(socket_t socket)
- {
- int nVal = 1;
- setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nVal, sizeof(nVal));
- return true;
- }
-}
#include <stddef.h>
#include <process.h>
-typedef SOCKET socket_t;
+typedef SOCKET tcp_socket_t;
+#define INVALID_SOCKET_VALUE INVALID_SOCKET
+typedef HANDLE serial_socket_t;
+#define INVALID_SERIAL_SOCKET_VALUE INVALID_HANDLE_VALUE
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
+#ifndef _SSIZE_T_DEFINED
+#ifdef _WIN64
+typedef __int64 ssize_t;
+#else
+typedef _W64 int ssize_t;
+#endif
+#define _SSIZE_T_DEFINED
+#endif
+
#define snprintf _snprintf
#if defined(_MSC_VER)
using namespace std;
using namespace PLATFORM;
-void CSerialPort::FormatWindowsError(int iErrorCode, CStdString &strMessage)
+void FormatWindowsError(int iErrorCode, CStdString &strMessage)
{
if (iErrorCode != ERROR_SUCCESS)
{
}
}
-CSerialPort::CSerialPort(void) :
- m_handle(INVALID_HANDLE_VALUE),
- m_bIsOpen(false),
- m_iBaudrate(0),
- m_iDatabits(0),
- m_iStopbits(0),
- m_iParity(0)
+bool SetTimeouts(serial_socket_t socket, int* iError, bool bBlocking)
{
+ if (socket == INVALID_HANDLE_VALUE)
+ return false;
+
+ COMMTIMEOUTS cto;
+ if (!GetCommTimeouts(socket, &cto))
+ {
+ *iError = GetLastError();
+ return false;
+ }
+
+ if (bBlocking)
+ {
+ cto.ReadIntervalTimeout = 0;
+ cto.ReadTotalTimeoutConstant = 0;
+ cto.ReadTotalTimeoutMultiplier = 0;
+ }
+ else
+ {
+ cto.ReadIntervalTimeout = MAXDWORD;
+ cto.ReadTotalTimeoutConstant = 0;
+ cto.ReadTotalTimeoutMultiplier = 0;
+ }
+
+ if (!SetCommTimeouts(socket, &cto))
+ {
+ *iError = GetLastError();
+ return false;
+ }
+
+ return true;
}
-bool CSerialPort::Open(string name, uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity)
+void CSerialSocket::Close(void)
{
- CStdString strComPath = "\\\\.\\" + name;
+ SerialSocketClose(m_socket);
+}
+
+void CSerialSocket::Shutdown(void)
+{
+ SerialSocketClose(m_socket);
+}
+
+ssize_t CSerialSocket::Write(void* data, size_t len)
+{
+ return SerialSocketWrite(m_socket, &m_iError, data, len);
+}
+
+ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */)
+{
+ return SerialSocketRead(m_socket, &m_iError, data, len, iTimeoutMs);
+}
+
+bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */)
+{
+ iTimeoutMs = 0;
+ CStdString strComPath = "\\\\.\\" + m_strName;
CLockObject lock(m_mutex);
- m_handle = CreateFile(strComPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (m_handle == INVALID_HANDLE_VALUE)
+ m_socket = CreateFile(strComPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (m_socket == INVALID_HANDLE_VALUE)
{
m_strError = "Unable to open COM port";
FormatWindowsError(GetLastError(), m_strError);
commConfig.dwSize = dwSize;
if (GetDefaultCommConfig(strComPath.c_str(), &commConfig,&dwSize))
{
- if (!SetCommConfig(m_handle, &commConfig,dwSize))
+ if (!SetCommConfig(m_socket, &commConfig,dwSize))
{
m_strError = "unable to set default config";
FormatWindowsError(GetLastError(), m_strError);
FormatWindowsError(GetLastError(), m_strError);
}
- if (!SetupComm(m_handle, 64, 64))
+ if (!SetupComm(m_socket, 64, 64))
{
m_strError = "unable to set up the com port";
FormatWindowsError(GetLastError(), m_strError);
}
- m_iDatabits = databits;
- m_iStopbits = stopbits;
- m_iParity = parity;
- if (!SetBaudRate(baudrate))
+ if (!SetBaudRate(m_iBaudrate))
{
m_strError = "unable to set baud rate";
FormatWindowsError(GetLastError(), m_strError);
return false;
}
- if (!SetTimeouts(false))
+ if (!SetTimeouts(m_socket, &m_iError, false))
{
m_strError = "unable to set timeouts";
FormatWindowsError(GetLastError(), m_strError);
return m_bIsOpen;
}
-bool CSerialPort::SetTimeouts(bool bBlocking)
-{
- if (m_handle == INVALID_HANDLE_VALUE)
- return false;
-
- COMMTIMEOUTS cto;
- if (!GetCommTimeouts(m_handle, &cto))
- {
- m_strError = "GetCommTimeouts failed";
- FormatWindowsError(GetLastError(), m_strError);
- return false;
- }
-
- if (bBlocking)
- {
- cto.ReadIntervalTimeout = 0;
- cto.ReadTotalTimeoutConstant = 0;
- cto.ReadTotalTimeoutMultiplier = 0;
- }
- else
- {
- cto.ReadIntervalTimeout = MAXDWORD;
- cto.ReadTotalTimeoutConstant = 0;
- cto.ReadTotalTimeoutMultiplier = 0;
- }
-
- if (!SetCommTimeouts(m_handle, &cto))
- {
- m_strError = "SetCommTimeouts failed";
- FormatWindowsError(GetLastError(), m_strError);
- return false;
- }
-
- return true;
-}
-
-void CSerialPort::Close(void)
-{
- CLockObject lock(m_mutex);
- if (m_bIsOpen)
- {
- CloseHandle(m_handle);
- m_bIsOpen = false;
- }
-}
-
-int64_t CSerialPort::Write(uint8_t* data, uint32_t len)
-{
- CLockObject lock(m_mutex);
- DWORD iBytesWritten = 0;
- if (!m_bIsOpen)
- return -1;
-
- if (!WriteFile(m_handle, data, len, &iBytesWritten, NULL))
- {
- m_strError = "Error while writing to COM port";
- FormatWindowsError(GetLastError(), m_strError);
- return -1;
- }
-
- return (int64_t)iBytesWritten;
-}
-
-int32_t CSerialPort::Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs /* = 0 */)
-{
- CLockObject lock(m_mutex);
- int32_t iReturn(-1);
- DWORD iBytesRead = 0;
- if (m_handle == 0)
- {
- m_strError = "Error while reading from COM port: invalid handle";
- return iReturn;
- }
-
- if(!ReadFile(m_handle, data, len, &iBytesRead, NULL) != 0)
- {
- m_strError = "unable to read from device";
- FormatWindowsError(GetLastError(), m_strError);
- iReturn = -1;
- }
- else
- {
- iReturn = (int32_t) iBytesRead;
- }
-
- return iReturn;
-}
-
-bool CSerialPort::SetBaudRate(uint32_t baudrate)
+bool CSerialSocket::SetBaudRate(uint32_t baudrate)
{
int32_t rate = IntToBaudrate(baudrate);
if (rate < 0)
dcb.fInX = false;
dcb.fAbortOnError = true;
- if (m_iParity == PAR_NONE)
+ if (m_iParity == SERIAL_PARITY_NONE)
dcb.Parity = NOPARITY;
- else if (m_iParity == PAR_EVEN)
+ else if (m_iParity == SERIAL_PARITY_EVEN)
dcb.Parity = EVENPARITY;
else
dcb.Parity = ODDPARITY;
- if (m_iStopbits == 2)
+ if (m_iStopbits == SERIAL_STOP_BITS_TWO)
dcb.StopBits = TWOSTOPBITS;
else
dcb.StopBits = ONESTOPBIT;
- dcb.ByteSize = m_iDatabits;
+ dcb.ByteSize = (BYTE)m_iDatabits;
- if(!SetCommState(m_handle,&dcb))
+ if(!SetCommState(m_socket,&dcb))
{
m_strError = "SetCommState failed";
FormatWindowsError(GetLastError(), m_strError);
return true;
}
-
-bool CSerialPort::IsOpen(void)
-{
- CLockObject lock(m_mutex);
- return m_bIsOpen;
-}