hostile-takeover/game/win/WsTransport.cpp
2014-07-06 17:47:28 -07:00

202 lines
5.3 KiB
C++

#include "..\ht.h"
#include "..\Multiplayer.h"
#include <WsTransport.h>
#ifdef DEBUG
const TCHAR *PszFromSocError();
const TCHAR *PszFromSocError(int nError);
#endif
//---------------------------------------------------------------------------
// WsTransport implementation
int WsTransport::GetTransportDescriptions(TransportDescription *atrad, int ctradMax)
{
char szHostName[100];
gethostname(szHostName, sizeof(szHostName));
HOSTENT *phste = gethostbyname(szHostName);
TransportDescription *ptrad = atrad;
for (int i = 0; phste->h_addr_list[i] != NULL && i < ctradMax; i++, ptrad++) {
in_addr *pina = (in_addr *)phste->h_addr_list[i];
ptrad->trat = ktratIP;
sprintf(ptrad->szName, "IP %s", inet_ntoa(*pina));
ptrad->pfnOpen = WsTransport::Open;
ptrad->dwTransportSpecific = ntohl(pina->S_un.S_addr);
}
return i;
// This is a good start for finding the Bluetooth transport on a device that has
// Microsoft's Bluetooth stack. Haven't encountered one yet.
#if 0
WSAQUERYSET qs;
memset(&qs, 0, sizeof(qs));
qs.dwSize = sizeof(qs);
// UNDONE: namespace?
HANDLE hls = NULL;
int err = WSALookupServiceBegin(&qs,
LUP_FLUSHCACHE | LUP_NEAREST | LUP_RETURN_NAME | LUP_RETURN_TYPE | LUP_RETURN_COMMENT | LUP_RETURN_ADDR,
&hls);
if (err != 0) {
#ifdef DEBUG
HostMessageBox(TEXT("WSALookupServiceBegin err: %s"), PszFromSocError());
#else
HostMessageBox(TEXT("Unable to enumerate transports"));
#endif
return 0;
}
TransportDescription *ptrad = atrad;
while (true) {
DWORD dwSize = sizeof(qs);
int err = WSALookupServiceNext(hls,
LUP_FLUSHCACHE | LUP_NEAREST | LUP_RETURN_NAME | LUP_RETURN_TYPE | LUP_RETURN_COMMENT | LUP_RETURN_ADDR,
&dwSize, &qs);
if (err == WSA_E_NO_MORE || err == WSAENOMORE)
break;
if (err != 0) {
#ifdef DEBUG
HostMessageBox(TEXT("WSALookupServiceNet err: %s"), PszFromSocError(err));
#else
HostMessageBox(TEXT("Unable to enumerate transports"));
#endif
return 0;
}
// UNDONE: translate qs.lpServiceClassId into a TransportType
strncpyz(ptrad->szName, qs.lpszServiceInstanceName, sizeof(ptrad->szName));
ctrad++;
ptrad++;
}
return ctrad;
#endif
}
Transport *WsTransport::Open(TransportDescription *ptrad)
{
Transport *ptra = new WsTransport(ptrad->dwTransportSpecific);
if (ptra == NULL)
return NULL;
if (!ptra->Open())
return NULL;
return ptra;
}
bool WsTransport::Open()
{
WSADATA wsad;
int err = WSAStartup(MAKEWORD(1, 1), &wsad);
if (err != 0) {
// unrecoverable low-level problem (e.g., socket limit reached, network
// subsystem not ready, requested version not supported)
#ifdef DEBUG
HostMessageBox(TEXT("WSAStartup err: %s"), PszFromSocError(err));
#else
HostMessageBox(TEXT("Unable to initialize network"));
#endif
return false;
}
return SocTransport::Open();
}
void WsTransport::Close()
{
SocTransport::Close(); // Closes any open Connections
WSACleanup();
}
WsTransport::WsTransport(dword dwIpAddress) : SocTransport(dwIpAddress)
{
}
// Error strings for WSA errors
#ifdef DEBUG
struct {
int nError;
TCHAR *pszError;
} aSocErrors[] = {
{ WSAEINTR, TEXT("EINTR") },
{ WSAEBADF, TEXT("EBADF") },
{ WSAEACCES, TEXT("EACCES") },
{ WSAEFAULT, TEXT("EFAULT") },
{ WSAEINVAL, TEXT("EINVAL") },
{ WSAEMFILE, TEXT("EMFILE") },
{ WSAEWOULDBLOCK, TEXT("EWOULDBLOCK") },
{ WSAEINPROGRESS, TEXT("EINPROGRESS") },
{ WSAEALREADY, TEXT("EALREADY") },
{ WSAENOTSOCK, TEXT("ENOTSOCK") },
{ WSAEDESTADDRREQ, TEXT("EDESTADDRREQ") },
{ WSAEMSGSIZE, TEXT("EMSGSIZE") },
{ WSAEPROTOTYPE, TEXT("EPROTOTYPE") },
{ WSAENOPROTOOPT, TEXT("ENOPROTOOPT") },
{ WSAEPROTONOSUPPORT, TEXT("EPROTONOSUPPORT") },
{ WSAESOCKTNOSUPPORT, TEXT("ESOCKTNOSUPPORT") },
{ WSAEOPNOTSUPP, TEXT("EOPNOTSUPP") },
{ WSAEPFNOSUPPORT, TEXT("EPFNOSUPPORT") },
{ WSAEAFNOSUPPORT, TEXT("EAFNOSUPPORT") },
{ WSAEADDRINUSE, TEXT("EADDRINUSE") },
{ WSAEADDRNOTAVAIL, TEXT("EADDRNOTAVAIL") },
{ WSAENETDOWN, TEXT("ENETDOWN") },
{ WSAENETUNREACH, TEXT("ENETUNREACH") },
{ WSAENETRESET, TEXT("ENETRESET") },
{ WSAECONNABORTED, TEXT("ECONNABORTED") },
{ WSAECONNRESET, TEXT("ECONNRESET") },
{ WSAENOBUFS, TEXT("ENOBUFS") },
{ WSAEISCONN, TEXT("EISCONN") },
{ WSAENOTCONN, TEXT("ENOTCONN") },
{ WSAESHUTDOWN, TEXT("ESHUTDOWN") },
{ WSAETOOMANYREFS, TEXT("ETOOMANYREFS") },
{ WSAETIMEDOUT, TEXT("ETIMEDOUT") },
{ WSAECONNREFUSED, TEXT("ECONNREFUSED") },
{ WSAELOOP, TEXT("ELOOP") },
{ WSAENAMETOOLONG, TEXT("ENAMETOOLONG") },
{ WSAEHOSTDOWN, TEXT("EHOSTDOWN") },
{ WSAEHOSTUNREACH, TEXT("EHOSTUNREACH") },
{ WSAENOTEMPTY, TEXT("ENOTEMPTY") },
{ WSAEPROCLIM, TEXT("EPROCLIM") },
{ WSAEUSERS, TEXT("EUSERS") },
{ WSAEDQUOT, TEXT("EDQUOT") },
{ WSAESTALE, TEXT("ESTALE") },
{ WSAEREMOTE, TEXT("EREMOTE") },
{ WSAEDISCON, TEXT("EDISCON") },
{ WSASYSNOTREADY, TEXT("SYSNOTREADY") },
{ WSAVERNOTSUPPORTED, TEXT("VERNOTSUPPORTED") },
{ WSANOTINITIALISED, TEXT("NOTINITIALISED") },
{ WSAHOST_NOT_FOUND, TEXT("HOST_NOT_FOUND") },
{ WSATRY_AGAIN, TEXT("TRY_AGAIN") },
{ WSANO_RECOVERY, TEXT("NO_RECOVERY") },
{ WSANO_DATA, TEXT("NO_DATA") },
};
const TCHAR *PszFromSocError(int nError)
{
static TCHAR szError[80];
TCHAR *pszError = TEXT("Unknown Socket error!");
for (int i = 0; i < sizeof(aSocErrors) / (sizeof(int) + sizeof(char *));
i++) {
if (nError == aSocErrors[i].nError) {
pszError = aSocErrors[i].pszError;
break;
}
}
wsprintf(szError, TEXT("%s (%d)"), pszError, nError);
return szError;
}
#endif