Files
Slnkdwf/SlnkDWFCom/WinSock.cpp
Jos Groot Lipman b1bf0bd021 Toch nog even compatible blijven met de winsock van Windows 2003R2
svn path=/Slnkdwf/trunk/; revision=26229
2015-09-08 15:22:02 +00:00

257 lines
5.9 KiB
C++

// WinSock.cpp : Implementation of CWinSock
#include "stdafx.h"
#include "WinSock.h"
// Gebaseerd op http://www.binarytides.com/winsock-socket-programming-tutorial/
// en op http://www.binarytides.com/category/programming/sockets/winsock-sockets/
// CWinSock
STDMETHODIMP CWinSock::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* const arr[] =
{
&IID_IWinSock
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
CWinSock::CWinSock()
{
m_Timeout = 21000;
}
CWinSock::~CWinSock()
{
if (m_must_close)
ShutdownConnection();
}
STDMETHODIMP CWinSock::get_LocalHostIP(BSTR* pVal)
{
CComBSTR bstrString(m_LocalHostIP);
return bstrString.CopyTo(pVal);
}
STDMETHODIMP CWinSock::put_LocalHostIP(BSTR newVal)
{
m_LocalHostIP = newVal;
return S_OK;
}
STDMETHODIMP CWinSock::get_RemoteHostIP(BSTR* pVal)
{
CComBSTR bstrString(m_RemoteHostIP);
return bstrString.CopyTo(pVal);
}
STDMETHODIMP CWinSock::put_RemoteHostIP(BSTR newVal)
{
m_RemoteHostIP = newVal;
return S_OK;
}
STDMETHODIMP CWinSock::get_RemotePort(ULONG* pVal)
{
(*pVal) = m_RemotePort;
return S_OK;
}
STDMETHODIMP CWinSock::put_RemotePort(ULONG newVal)
{
m_RemotePort = newVal;
return S_OK;
}
bool myconnect(SOCKET &sock, struct sockaddr_in &address, int timeout)
{
TIMEVAL Timeout;
Timeout.tv_sec = (long)(timeout / 1000);
Timeout.tv_usec = timeout % 1000;
// sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//set the socket in non-blocking
unsigned long iMode = 1;
int iResult = ioctlsocket(sock, FIONBIO, &iMode);
if (iResult != NO_ERROR)
{
throw myCString("ioctlsocket failed with error: %ld\n", iResult);
}
if (!connect(sock, (struct sockaddr *)&address, sizeof(address)))
{
return false;
}
// restart the socket mode
iMode = 0;
iResult = ioctlsocket(sock, FIONBIO, &iMode);
if (iResult != NO_ERROR)
{
throw myCString("ioctlsocket failed with error: %ld\n", iResult);
}
fd_set Write, Err;
FD_ZERO(&Write);
FD_ZERO(&Err);
FD_SET(sock, &Write);
FD_SET(sock, &Err);
// check if the socket is ready
iResult = select(0, NULL, &Write, &Err, &Timeout);
if (iResult == SOCKET_ERROR)
throw myCString("\nCWinSock: Could not connect %d", WSAGetLastError());
if (iResult == 0)
throw myCString("\nCWinSock: Timeout after %dms", timeout);
if (FD_ISSET(sock, &Write))
{
return true;
}
return false;
}
STDMETHODIMP CWinSock::OpenConnection()
{
WSADATA wsa;
struct sockaddr_in server;
// Initialize Winsock API
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
return myAtlReportError(GetObjectCLSID(), "\nCWinSock: Could not startup %d", WSAGetLastError());
}
// Create new socket
//if ((m_socket = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
if ((m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
return myAtlReportError(GetObjectCLSID(), "\nCWinSock: Could not create socket : %d", WSAGetLastError());
}
m_must_close = true;
int nTimeout = m_Timeout; // Milliseconde voor de send en receive (connect gaat apart)
setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&nTimeout, sizeof(int));
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int));
// InetPton(AF_INET, m_RemoteHostIP, &server.sin_addr.s_addr);
// Zolang we nog Windows 2003R2 (willen) ondersteunen:
// is dit gezet in stdafx.h: #define _WINSOCK_DEPRECATED_NO_WARNINGS
server.sin_addr.s_addr = inet_addr(m_RemoteHostIP);
server.sin_family = AF_INET;
server.sin_port = htons((u_short)(m_RemotePort));
// Connect to remote server
// De gewone connect werkt ook wel maar als de andere kant niet reageert heb je een
// timeout van 21 seconde die niet eenvoudig te overrulen is
//if (connect(m_socket, (struct sockaddr *)&server, sizeof(server)) < 0)
try
{
if (!myconnect(m_socket, server, m_Timeout))
{
return myAtlReportError(GetObjectCLSID(), "\nCWinSock: Could not connect %d", WSAGetLastError());
}
}
catch (CString& e)
{
return myAtlReportError(GetObjectCLSID(), e);
}
/* 'Bind socket to LocalHostIP
msaLocalAddr.sin_family = PF_INET
msaLocalAddr.sin_port = 0
msaLocalAddr.sin_addr.S_addr = inet_addr(mstrLocalHostIP)
If(msaLocalAddr.sin_addr.S_addr = INADDR_NONE) Then
SetLastErrorCode "Error in OpenConnection::inet_addr"
Exit Function
End If
WSAResult = bind(mlngSocket, msaLocalAddr, Len(msaLocalAddr))
If(WSAResult = SOCKET_ERROR) Then
SetLastErrorCode "Error in OpenConnection::bind"
Exit Function
End If
*/
return S_OK;
}
STDMETHODIMP CWinSock::SendData(BSTR sData, BYTE* bResult)
{
//Send some data
CString message(sData);
if (send(m_socket, message, message.GetLength(), 0) < 0)
{
return myAtlReportError(GetObjectCLSID(), "\nCWinSock: Send failed %d", WSAGetLastError());
}
return S_OK;
}
STDMETHODIMP CWinSock::isDataAvailable()
{
// TODO: Add your implementation code here
return S_OK;
}
STDMETHODIMP CWinSock::ReceiveData(BSTR* sData)
{
char server_reply[8192];
int recv_size;
//Receive a reply from the server
if ((recv_size = recv(m_socket, server_reply, sizeof(server_reply), 0)) == SOCKET_ERROR)
{
return myAtlReportError(GetObjectCLSID(), "\nCWinSock: Recv failed %d", WSAGetLastError());
}
CComBSTR bstrString(recv_size, server_reply);
return bstrString.CopyTo(sData);
}
STDMETHODIMP CWinSock::ShutdownConnection()
{
if (m_must_close)
{
shutdown(m_socket, SD_BOTH);
closesocket(m_socket);
WSACleanup();
}
return S_OK;
}
STDMETHODIMP CWinSock::get_Timeout(ULONG* pVal)
{
(*pVal) = m_Timeout;
return S_OK;
}
STDMETHODIMP CWinSock::put_Timeout(ULONG newVal)
{
m_Timeout = newVal;
return S_OK;
}