257 lines
5.9 KiB
C++
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;
|
|
}
|