mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-23 22:13:35 +00:00
781 lines
22 KiB
C++
781 lines
22 KiB
C++
/// \file
|
|
/// \brief SocketLayer class implementation
|
|
///
|
|
/// This file is part of RakNet Copyright 2003 Kevin Jenkins.
|
|
///
|
|
/// Usage of RakNet is subject to the appropriate license agreement.
|
|
/// Creative Commons Licensees are subject to the
|
|
/// license found at
|
|
/// http://creativecommons.org/licenses/by-nc/2.5/
|
|
/// Single application licensees are subject to the license found at
|
|
/// http://www.jenkinssoftware.com/SingleApplicationLicense.html
|
|
/// Custom license users are subject to the terms therein.
|
|
/// GPL license users are subject to 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.
|
|
|
|
#include "SocketLayer.h"
|
|
#include <assert.h>
|
|
#include "MTUSize.h"
|
|
|
|
#ifdef _WIN32
|
|
typedef int socklen_t;
|
|
#elif !defined(_PS3)
|
|
#include <string.h> // memcpy
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <arpa/inet.h>
|
|
#include <errno.h> // error numbers
|
|
#include <stdio.h> // printf
|
|
#endif
|
|
|
|
#if defined(_PS3)
|
|
#if defined (_PS3_LOBBY)
|
|
// OK this is lame but you need to know the app port when sending to the external IP.
|
|
// I'm just assuming it's the same as our own because it would break the interfaces to pass it to SendTo directly.
|
|
static unsigned short HACK_APP_PORT;
|
|
#include "np/common.h"
|
|
#include <netdb.h>
|
|
#include <string.h>
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#elif defined(_PS3)
|
|
#define closesocket socketclose
|
|
#else
|
|
#define closesocket close
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "ExtendedOverlappedPool.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( push )
|
|
#endif
|
|
|
|
bool SocketLayer::socketLayerStarted = false;
|
|
#ifdef _WIN32
|
|
WSADATA SocketLayer::winsockInfo;
|
|
#endif
|
|
SocketLayer SocketLayer::I;
|
|
|
|
extern void ProcessNetworkPacket( const unsigned int binaryAddress, const unsigned short port, const char *data, const int length, RakPeer *rakPeer, unsigned connectionSocketIndex );
|
|
extern void ProcessPortUnreachable( const unsigned int binaryAddress, const unsigned short port, RakPeer *rakPeer );
|
|
|
|
#ifdef _DEBUG
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
SocketLayer::SocketLayer()
|
|
{
|
|
if ( socketLayerStarted == false )
|
|
{
|
|
#ifdef _WIN32
|
|
|
|
if ( WSAStartup( MAKEWORD( 2, 2 ), &winsockInfo ) != 0 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "WSAStartup failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
socketLayerStarted = true;
|
|
}
|
|
}
|
|
|
|
SocketLayer::~SocketLayer()
|
|
{
|
|
if ( socketLayerStarted == true )
|
|
{
|
|
#ifdef _WIN32
|
|
WSACleanup();
|
|
#endif
|
|
|
|
socketLayerStarted = false;
|
|
}
|
|
}
|
|
|
|
SOCKET SocketLayer::Connect( SOCKET writeSocket, unsigned int binaryAddress, unsigned short port )
|
|
{
|
|
assert( writeSocket != (SOCKET) -1 );
|
|
sockaddr_in connectSocketAddress;
|
|
|
|
connectSocketAddress.sin_family = AF_INET;
|
|
connectSocketAddress.sin_port = htons( port );
|
|
connectSocketAddress.sin_addr.s_addr = binaryAddress;
|
|
|
|
if ( connect( writeSocket, ( struct sockaddr * ) & connectSocketAddress, sizeof( struct sockaddr ) ) != 0 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) &messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "WSAConnect failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
}
|
|
|
|
return writeSocket;
|
|
}
|
|
bool SocketLayer::IsPortInUse(unsigned short port)
|
|
{
|
|
SOCKET listenSocket;
|
|
sockaddr_in listenerSocketAddress;
|
|
// Listen on our designated Port#
|
|
listenerSocketAddress.sin_port = htons( port );
|
|
listenSocket = socket( AF_INET, SOCK_DGRAM, 0 );
|
|
if ( listenSocket == (SOCKET) -1 )
|
|
return true;
|
|
// bind our name to the socket
|
|
// Fill in the rest of the address structure
|
|
listenerSocketAddress.sin_family = AF_INET;
|
|
listenerSocketAddress.sin_addr.s_addr = INADDR_ANY;
|
|
int ret = bind( listenSocket, ( struct sockaddr * ) & listenerSocketAddress, sizeof( listenerSocketAddress ) );
|
|
closesocket(listenSocket);
|
|
return ret <= -1;
|
|
}
|
|
SOCKET SocketLayer::CreateBoundSocket( unsigned short port, bool blockingSocket, const char *forceHostAddress )
|
|
{
|
|
(void) blockingSocket;
|
|
|
|
int ret;
|
|
SOCKET listenSocket;
|
|
#if defined(_PS3) && defined (_PS3_LOBBY)
|
|
sockaddr_in_p2p listenerSocketAddress;
|
|
memset(&listenerSocketAddress, 0, sizeof(listenerSocketAddress));
|
|
|
|
// Lobby version
|
|
listenerSocketAddress.sin_port = htons(SCE_NP_PORT);
|
|
HACK_APP_PORT = port; // Save the locally bound port
|
|
listenerSocketAddress.sin_vport = htons(port);
|
|
listenSocket = socket( AF_INET, SOCK_DGRAM_P2P, 0 );
|
|
|
|
// Normal version as below
|
|
#else
|
|
sockaddr_in listenerSocketAddress;
|
|
// Listen on our designated Port#
|
|
listenerSocketAddress.sin_port = htons( port );
|
|
#if 0 // defined(_WIN32)
|
|
listenSocket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
|
|
#else
|
|
listenSocket = socket( AF_INET, SOCK_DGRAM, 0 );
|
|
#endif
|
|
#endif
|
|
|
|
if ( listenSocket == (SOCKET) -1 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "socket(...) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
|
|
return (SOCKET) -1;
|
|
}
|
|
|
|
int sock_opt = 1;
|
|
if ( setsockopt( listenSocket, SOL_SOCKET, SO_REUSEADDR, ( char * ) & sock_opt, sizeof ( sock_opt ) ) == -1 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "setsockopt(SO_REUSEADDR) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
}
|
|
|
|
|
|
// This doubles the max throughput rate
|
|
sock_opt=1024*256;
|
|
setsockopt(listenSocket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
|
|
|
#ifndef _PS3
|
|
// This doesn't make much difference: 10% maybe
|
|
// Not supported on console 2
|
|
sock_opt=1024*16;
|
|
setsockopt(listenSocket, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
unsigned long nonblocking = 1;
|
|
ioctlsocket( listenSocket, FIONBIO, &nonblocking );
|
|
#elif defined(_PS3)
|
|
sock_opt=1;
|
|
setsockopt(listenSocket, SOL_SOCKET, SO_NBIO, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
|
#else
|
|
fcntl( listenSocket, F_SETFL, O_NONBLOCK );
|
|
#endif
|
|
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
// If this assert hit you improperly linked against WSock32.h
|
|
assert(IP_DONTFRAGMENT==14);
|
|
#endif
|
|
|
|
// TODO - I need someone on dialup to test this with :(
|
|
// Path MTU Detection
|
|
|
|
// if ( setsockopt( listenSocket, IPPROTO_IP, IP_DONTFRAGMENT, ( char * ) & sock_opt, sizeof ( sock_opt ) ) == -1 )
|
|
// {
|
|
//#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
// DWORD dwIOError = GetLastError();
|
|
// LPVOID messageBuffer;
|
|
// FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
// NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
// ( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
// printf( "setsockopt(IP_DONTFRAGMENT) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
// LocalFree( messageBuffer );
|
|
//#endif
|
|
// }
|
|
|
|
// Set broadcast capable
|
|
sock_opt=1;
|
|
if ( setsockopt( listenSocket, SOL_SOCKET, SO_BROADCAST, ( char * ) & sock_opt, sizeof( sock_opt ) ) == -1 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "setsockopt(SO_BROADCAST) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
|
|
}
|
|
|
|
// Fill in the rest of the address structure
|
|
listenerSocketAddress.sin_family = AF_INET;
|
|
|
|
if (forceHostAddress && forceHostAddress[0])
|
|
{
|
|
listenerSocketAddress.sin_addr.s_addr = inet_addr( forceHostAddress );
|
|
}
|
|
else
|
|
{
|
|
listenerSocketAddress.sin_addr.s_addr = INADDR_ANY;
|
|
}
|
|
|
|
// bind our name to the socket
|
|
ret = bind( listenSocket, ( struct sockaddr * ) & listenerSocketAddress, sizeof( listenerSocketAddress ) );
|
|
|
|
if ( ret <= -1 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "bind(...) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#elif (defined(__GNUC__) || defined(__GCCXML__) || defined(_PS3)) && !defined(__WIN32)
|
|
switch (ret)
|
|
{
|
|
case EBADF:
|
|
printf("bind(): sockfd is not a valid descriptor.\n"); break;
|
|
#ifndef _PS3
|
|
case ENOTSOCK:
|
|
printf("bind(): Argument is a descriptor for a file, not a socket.\n"); break;
|
|
#endif
|
|
case EINVAL:
|
|
printf("bind(): The addrlen is wrong, or the socket was not in the AF_UNIX family.\n"); break;
|
|
case EROFS:
|
|
printf("bind(): The socket inode would reside on a read-only file system.\n"); break;
|
|
case EFAULT:
|
|
printf("bind(): my_addr points outside the user's accessible address space.\n"); break;
|
|
case ENAMETOOLONG:
|
|
printf("bind(): my_addr is too long.\n"); break;
|
|
case ENOENT:
|
|
printf("bind(): The file does not exist.\n"); break;
|
|
case ENOMEM:
|
|
printf("bind(): Insufficient kernel memory was available.\n"); break;
|
|
case ENOTDIR:
|
|
printf("bind(): A component of the path prefix is not a directory.\n"); break;
|
|
case EACCES:
|
|
printf("bind(): Search permission is denied on a component of the path prefix.\n"); break;
|
|
#ifndef _PS3
|
|
case ELOOP:
|
|
printf("bind(): Too many symbolic links were encountered in resolving my_addr.\n"); break;
|
|
#endif
|
|
default:
|
|
printf("Unknown bind() error %i.\n", ret); break;
|
|
}
|
|
#endif
|
|
|
|
return (SOCKET) -1;
|
|
}
|
|
|
|
return listenSocket;
|
|
}
|
|
|
|
#if !defined(_XBOX360)
|
|
const char* SocketLayer::DomainNameToIP( const char *domainName )
|
|
{
|
|
struct hostent * phe = gethostbyname( domainName );
|
|
|
|
if ( phe == 0 || phe->h_addr_list[ 0 ] == 0 )
|
|
{
|
|
//cerr << "Yow! Bad host lookup." << endl;
|
|
return 0;
|
|
}
|
|
|
|
struct in_addr addr;
|
|
if (phe->h_addr_list[ 0 ]==0)
|
|
return 0;
|
|
|
|
memcpy( &addr, phe->h_addr_list[ 0 ], sizeof( struct in_addr ) );
|
|
return inet_ntoa( addr );
|
|
}
|
|
#endif
|
|
|
|
|
|
void SocketLayer::Write( const SOCKET writeSocket, const char* data, const int length )
|
|
{
|
|
#ifdef _DEBUG
|
|
assert( writeSocket != (SOCKET) -1 );
|
|
#endif
|
|
|
|
send( writeSocket, data, length, 0 );
|
|
}
|
|
|
|
int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode, unsigned connectionSocketIndex )
|
|
{
|
|
int len;
|
|
char data[ MAXIMUM_MTU_SIZE ];
|
|
|
|
#if defined(_PS3) && defined (_PS3_LOBBY)
|
|
sockaddr_in_p2p sa;
|
|
#else
|
|
sockaddr_in sa;
|
|
#endif
|
|
|
|
|
|
socklen_t len2 = sizeof( sa );
|
|
sa.sin_family = AF_INET;
|
|
|
|
#ifdef _DEBUG
|
|
data[ 0 ] = 0;
|
|
len = 0;
|
|
sa.sin_addr.s_addr = 0;
|
|
#endif
|
|
|
|
if ( s == (SOCKET) -1 )
|
|
{
|
|
*errorCode = -1;
|
|
return -1;
|
|
}
|
|
|
|
#if defined (_WIN32) || !defined(MSG_DONTWAIT)
|
|
const int flag=0;
|
|
#else
|
|
const int flag=MSG_DONTWAIT;
|
|
#endif
|
|
|
|
len = recvfrom( s, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );
|
|
|
|
// if (len>0)
|
|
// printf("Got packet on port %i\n",ntohs(sa.sin_port));
|
|
|
|
if ( len == 0 )
|
|
{
|
|
#ifdef _DEBUG
|
|
printf( "Error: recvfrom returned 0 on a connectionless blocking call\non port %i. This is a bug with Zone Alarm. Please turn off Zone Alarm.\n", ntohs( sa.sin_port ) );
|
|
assert( 0 );
|
|
#endif
|
|
|
|
//*errorCode = -1;
|
|
#ifdef __linux__
|
|
char str[INET_ADDRSTRLEN];
|
|
inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);
|
|
printf("[RakNet] SocketLayer::RecvFrom: empty datagram from %s", str);
|
|
#endif
|
|
//return -1;
|
|
return 0;
|
|
}
|
|
|
|
if ( len > 0 )
|
|
// if ( len != SOCKET_ERROR )
|
|
{
|
|
unsigned short portnum;
|
|
//#if defined(_PS3) && defined (_PS3_LOBBY)
|
|
// portnum = ntohs( sa.sin_vport );
|
|
//#else
|
|
portnum = ntohs( sa.sin_port );
|
|
//#endif
|
|
//strcpy(ip, inet_ntoa(sa.sin_addr));
|
|
//if (strcmp(ip, "0.0.0.0")==0)
|
|
// strcpy(ip, "127.0.0.1");
|
|
ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, data, len, rakPeer, connectionSocketIndex );
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
*errorCode = 0;
|
|
|
|
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
|
|
DWORD dwIOError = WSAGetLastError();
|
|
|
|
if ( dwIOError == WSAEWOULDBLOCK )
|
|
{
|
|
return SOCKET_ERROR;
|
|
}
|
|
if ( dwIOError == WSAECONNRESET )
|
|
{
|
|
#if defined(_DEBUG)
|
|
// printf( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
|
|
#endif
|
|
|
|
|
|
unsigned short portnum=0;
|
|
ProcessPortUnreachable(sa.sin_addr.s_addr, portnum, rakPeer);
|
|
// *errorCode = dwIOError;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
#if defined(_DEBUG)
|
|
if ( dwIOError != WSAEINTR )
|
|
{
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
}
|
|
#endif
|
|
}
|
|
#elif defined(__linux__)
|
|
if (len < -1)
|
|
{
|
|
printf("[RakNet] SocketLayer::RecvFrom: Unexpected return value.");
|
|
return -1;
|
|
}
|
|
|
|
int local_errno = errno;
|
|
if (local_errno == EAGAIN || local_errno == EWOULDBLOCK)
|
|
{
|
|
return 0; // no data
|
|
}
|
|
|
|
if (local_errno == EINTR)
|
|
{
|
|
printf("[RakNet] SocketLayer::RecvFrom: The receive was interrupted by delivery of a signal before any data were available.");
|
|
return 0; // log, but ignore
|
|
}
|
|
|
|
char str[INET_ADDRSTRLEN];
|
|
inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);
|
|
printf("[RakNet] SocketLayer::RecvFrom: Error receiving data from %s", str);
|
|
|
|
switch (local_errno) {
|
|
case EINVAL:
|
|
printf("[RakNet] SocketLayer::RecvFrom: Invalid argument passed."); break;
|
|
case ENOMEM:
|
|
case ENOBUFS:
|
|
printf("[RakNet] SocketLayer::RecvFrom: Could not allocate memory for recvmsg()."); break;
|
|
case EFAULT:
|
|
printf("[RakNet] SocketLayer::RecvFrom: The receive buffer pointer(s) point outside the process's address space."); break;
|
|
case EBADF:
|
|
printf("[RakNet] SocketLayer::RecvFrom: The argument sockfd is an invalid descriptor."); break;
|
|
case ENOTSOCK:
|
|
printf("[RakNet] SocketLayer::RecvFrom: The argument sockfd does not refer to a socket."); break;
|
|
case EPIPE:
|
|
printf("[RakNet] SocketLayer::RecvFrom: The connection was unexpectedly closed or shut down by the other end. "); break;
|
|
default:
|
|
printf("[RakNet] SocketLayer::RecvFrom: Unknown Error %d", local_errno); break;
|
|
}
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
return 0; // no data
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable : 4702 ) // warning C4702: unreachable code
|
|
#endif
|
|
int SocketLayer::SendTo( SOCKET s, const char *data, int length, unsigned int binaryAddress, unsigned short port )
|
|
{
|
|
if ( s == (SOCKET) -1 )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int len;
|
|
|
|
#if defined(_PS3) && defined (_PS3_LOBBY)
|
|
sockaddr_in_p2p sa;
|
|
memset(&sa, 0, sizeof(sa));
|
|
// LAME!!!! You have to know the behind-nat port on the recipient! Just guessing it is the same as our own
|
|
sa.sin_vport = htons(HACK_APP_PORT);
|
|
sa.sin_port = htons(port); // Port returned from signaling
|
|
#else
|
|
sockaddr_in sa;
|
|
sa.sin_port = htons( port ); // User port
|
|
#endif
|
|
|
|
sa.sin_addr.s_addr = binaryAddress;
|
|
sa.sin_family = AF_INET;
|
|
|
|
#if 1 // !defined(_WIN32)
|
|
do
|
|
{
|
|
len = sendto( s, data, length, 0, ( const sockaddr* ) & sa, sizeof( sa ) );
|
|
}
|
|
while ( len == 0 );
|
|
#else
|
|
WSABUF DataBuf;
|
|
DataBuf.len = length;
|
|
DataBuf.buf = (char*) data;
|
|
DWORD bytesSent;
|
|
int WSASendToResult = WSASendTo(s,
|
|
&DataBuf,
|
|
1,
|
|
&bytesSent,
|
|
0,
|
|
(SOCKADDR*) &sa,
|
|
sizeof( sa ),
|
|
0,
|
|
NULL);
|
|
len=bytesSent;
|
|
if (WSASendToResult!=0)
|
|
{
|
|
DWORD dwIOError = WSAGetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "sendto failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
}
|
|
#endif
|
|
|
|
if ( len != -1 )
|
|
return 0;
|
|
|
|
#if defined(_WIN32)
|
|
|
|
DWORD dwIOError = WSAGetLastError();
|
|
|
|
if ( dwIOError == WSAECONNRESET )
|
|
{
|
|
#if defined(_DEBUG)
|
|
printf( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
|
|
#endif
|
|
|
|
}
|
|
else if ( dwIOError != WSAEWOULDBLOCK )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "sendto failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
|
|
}
|
|
|
|
return dwIOError;
|
|
#endif
|
|
|
|
return 1; // error
|
|
}
|
|
|
|
int SocketLayer::SendTo( SOCKET s, const char *data, int length, const char ip[ 16 ], unsigned short port )
|
|
{
|
|
unsigned int binaryAddress;
|
|
binaryAddress = inet_addr( ip );
|
|
return SendTo( s, data, length, binaryAddress, port );
|
|
}
|
|
int SocketLayer::SendToTTL( SOCKET s, const char *data, int length, const char ip[ 16 ], unsigned short port, int ttl )
|
|
{
|
|
#if !defined(_XBOX360)
|
|
int oldTTL;
|
|
socklen_t opLen=sizeof(oldTTL);
|
|
// Get the current TTL
|
|
if (getsockopt(s, IPPROTO_IP, IP_TTL, ( char * ) & oldTTL, &opLen ) == -1)
|
|
{
|
|
#if defined(_WIN32) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "getsockopt(IPPROTO_IP,IP_TTL) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
}
|
|
|
|
// Set to TTL
|
|
int newTTL=ttl;
|
|
if (setsockopt(s, IPPROTO_IP, IP_TTL, ( char * ) & newTTL, sizeof ( newTTL ) ) == -1)
|
|
{
|
|
|
|
#if defined(_WIN32) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "setsockopt(IPPROTO_IP,IP_TTL) failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
}
|
|
|
|
// Send
|
|
int res = SendTo(s,data,length,ip,port);
|
|
|
|
// Restore the old TTL
|
|
setsockopt(s, IPPROTO_IP, IP_TTL, ( char * ) & oldTTL, opLen );
|
|
|
|
return res;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if !defined(_XBOX360)
|
|
void SocketLayer::GetMyIP( char ipList[ 10 ][ 16 ] )
|
|
{
|
|
#if !defined(_PS3)
|
|
char ac[ 80 ];
|
|
if ( gethostname( ac, sizeof( ac ) ) == -1 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "gethostname failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
|
|
return ;
|
|
}
|
|
|
|
struct hostent *phe = gethostbyname( ac );
|
|
|
|
|
|
if ( phe == 0 )
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "gethostbyname failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
|
|
return ;
|
|
}
|
|
|
|
for ( int i = 0; phe->h_addr_list[ i ] != 0 && i < 10; ++i )
|
|
{
|
|
|
|
struct in_addr addr;
|
|
|
|
memcpy( &addr, phe->h_addr_list[ i ], sizeof( struct in_addr ) );
|
|
//cout << "Address " << i << ": " << inet_ntoa(addr) << endl;
|
|
strcpy( ipList[ i ], inet_ntoa( addr ) );
|
|
}
|
|
#else
|
|
union CellNetCtlInfo info;
|
|
int errCode;
|
|
if((errCode=cellNetCtlGetInfo(CELL_NET_CTL_INFO_IP_ADDRESS, &info)) >= 0){
|
|
memcpy(ipList[0], info.ip_address, sizeof(info.ip_address));
|
|
ipList[1][0]=0;
|
|
}
|
|
return;
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
unsigned short SocketLayer::GetLocalPort ( SOCKET s )
|
|
{
|
|
sockaddr_in sa;
|
|
socklen_t len = sizeof(sa);
|
|
if (getsockname(s, (sockaddr*)&sa, &len)!=0)
|
|
{
|
|
#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)
|
|
DWORD dwIOError = GetLastError();
|
|
LPVOID messageBuffer;
|
|
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
|
( LPTSTR ) & messageBuffer, 0, NULL );
|
|
// something has gone wrong here...
|
|
printf( "getsockname failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
|
|
|
//Free the buffer.
|
|
LocalFree( messageBuffer );
|
|
#endif
|
|
return 0;
|
|
}
|
|
return ntohs(sa.sin_port);
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( pop )
|
|
#endif
|