123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: 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 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "Precompiled.h"
- #include "globaldata.h"
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <string>
- #include <errno.h>
- // Sockets
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netex/errno.h>
- #include <netex/net.h>
- #include <arpa/inet.h>
- #include "i_system.h"
- #include "d_event.h"
- #include "d_net.h"
- #include "m_argv.h"
- #include "doomstat.h"
- #include "i_net.h"
- #include "doomlib.h"
- #include "../Main/Main.h"
- void NetSend (void);
- qboolean NetListen (void);
- namespace {
- bool IsValidSocket( int socketDescriptor );
- int GetLastSocketError();
- /*
- ========================
- Returns true if the socket is valid. I made this function to help abstract the differences
- between WinSock (used on Xbox) and BSD sockets, which the PS3 follows more closely.
- ========================
- */
- bool IsValidSocket( int socketDescriptor ) {
- return socketDescriptor >= 0;
- }
- /*
- ========================
- Returns the last error reported by the platform's socket library.
- ========================
- */
- int GetLastSocketError() {
- return sys_net_errno;
- }
- }
- //
- // NETWORKING
- //
- int DOOMPORT = 1002; // DHM - Nerve :: On original XBox, ports 1000 - 1255 saved you a byte on every packet. 360 too?
- unsigned long GetServerIP() {
- return ::g->sendaddress[::g->doomcom.consoleplayer].sin_addr.s_addr;
- }
- void (*netget) (void);
- void (*netsend) (void);
- //
- // UDPsocket
- //
- int UDPsocket (void)
- {
- int s;
- // allocate a socket
- s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if ( !IsValidSocket( s ) ) {
- int err = GetLastSocketError();
- I_Error( "can't create socket, error %d", err );
- }
- return s;
- }
- //
- // BindToLocalPort
- //
- void BindToLocalPort( int s, int port )
- {
- int v;
- struct sockaddr_in address;
- memset (&address, 0, sizeof(address));
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = INADDR_ANY;
- address.sin_port = port;
- v = bind (s, (sockaddr*)&address, sizeof(address));
- //if (v == -1)
- //I_Error ("BindToPort: bind: %s", strerror(errno));
- }
- //
- // PacketSend
- //
- void PacketSend (void)
- {
- int c;
- doomdata_t sw;
- // byte swap
- sw.checksum = htonl(::g->netbuffer->checksum);
- sw.sourceDest = DoomLib::BuildSourceDest(::g->doomcom.remotenode);
- sw.player = ::g->netbuffer->player;
- sw.retransmitfrom = ::g->netbuffer->retransmitfrom;
- sw.starttic = ::g->netbuffer->starttic;
- sw.numtics = ::g->netbuffer->numtics;
- for (c=0 ; c< ::g->netbuffer->numtics ; c++)
- {
- sw.cmds[c].forwardmove = ::g->netbuffer->cmds[c].forwardmove;
- sw.cmds[c].sidemove = ::g->netbuffer->cmds[c].sidemove;
- sw.cmds[c].angleturn = htons(::g->netbuffer->cmds[c].angleturn);
- sw.cmds[c].consistancy = htons(::g->netbuffer->cmds[c].consistancy);
- sw.cmds[c].buttons = ::g->netbuffer->cmds[c].buttons;
- }
- // Send Socket
- {
- //DWORD num_sent;
-
- //if ( globalNetworking ) {
- // c = WSASendTo(::g->sendsocket, &buffer, 1, &num_sent, 0, (sockaddr*)&::g->sendaddress[::g->doomcom.remotenode],
- // sizeof(::g->sendaddress[::g->doomcom.remotenode]), 0, 0);
- //} else {
- c = DoomLib::Send( (char*)&sw, ::g->doomcom.datalength, (sockaddr_in*)&::g->sendaddress[::g->doomcom.remotenode], ::g->doomcom.remotenode );
- //}
- }
- }
- //
- // PacketGet
- //
- void PacketGet (void)
- {
- int i;
- int c;
- struct sockaddr_in fromaddress;
- int fromlen;
- doomdata_t sw;
- DWORD num_recieved; //, flags = 0;
- // Try and read a socket
- //buffer.buf = (char*)&sw;
- //buffer.len = sizeof(sw);
- fromlen = sizeof(fromaddress);
- //if ( globalNetworking ) {
- // c = WSARecvFrom(::g->insocket, &buffer, 1, &num_recieved, &flags, (struct sockaddr*)&fromaddress, &fromlen, 0, 0);
- //} else {
- c = DoomLib::Recv( (char*)&sw, &num_recieved );
- //}
- if ( c < 0 )
- {
- /*if ( globalNetworking ) {
- int err = WSAGetLastError();
- if (err != WSAEWOULDBLOCK)
- I_Error ("GetPacket: %s",strerror(errno));
- }*/
- ::g->doomcom.remotenode = -1; // no packet
- return;
- }
-
- // find remote node number
- /*for (i=0 ; i<::g->doomcom.numnodes ; i++)
- if ( fromaddress.sin_addr.s_addr == ::g->sendaddress[i].sin_addr.s_addr )
- break;
- if (i == ::g->doomcom.numnodes)
- {
- // packet is not from one of the ::g->players (new game broadcast)
- ::g->doomcom.remotenode = -1; // no packet
- return;
- }*/
- //if ( ::g->consoleplayer == 1 ) {
- //int x = 0;
- //}
- int source;
- int dest;
- DoomLib::GetSourceDest( sw.sourceDest, &source, &dest );
- i = source;
- //if ( ::g->consoleplayer == 1 ) {
- //if ( i == 2 ) {
- //int suck = 0;
- //}
- //}
- ::g->doomcom.remotenode = i; // good packet from a game player
- ::g->doomcom.datalength = (short)num_recieved;
- // byte swap
- ::g->netbuffer->checksum = ntohl(sw.checksum);
- ::g->netbuffer->player = sw.player;
- ::g->netbuffer->retransmitfrom = sw.retransmitfrom;
- ::g->netbuffer->starttic = sw.starttic;
- ::g->netbuffer->numtics = sw.numtics;
- for ( c = 0; c < ::g->netbuffer->numtics; c++ )
- {
- ::g->netbuffer->cmds[c].forwardmove = sw.cmds[c].forwardmove;
- ::g->netbuffer->cmds[c].sidemove = sw.cmds[c].sidemove;
- ::g->netbuffer->cmds[c].angleturn = ntohs(sw.cmds[c].angleturn);
- ::g->netbuffer->cmds[c].consistancy = ntohs(sw.cmds[c].consistancy);
- ::g->netbuffer->cmds[c].buttons = sw.cmds[c].buttons;
- }
- }
- static int I_TrySetupNetwork(void)
- {
- // DHM - Moved to Session
- return 1;
- }
- //
- // I_InitNetwork
- //
- void I_InitNetwork (void)
- {
- //qboolean trueval = true;
- int i;
- int p;
- //int a = 0;
- // struct hostent* hostentry; // host information entry
- memset (&::g->doomcom, 0, sizeof(::g->doomcom) );
- // set up for network
- i = M_CheckParm ("-dup");
- if (i && i< ::g->myargc-1)
- {
- ::g->doomcom.ticdup = ::g->myargv[i+1][0]-'0';
- if (::g->doomcom.ticdup < 1)
- ::g->doomcom.ticdup = 1;
- if (::g->doomcom.ticdup > 9)
- ::g->doomcom.ticdup = 9;
- }
- else
- ::g->doomcom.ticdup = 1;
- if (M_CheckParm ("-extratic"))
- ::g->doomcom.extratics = 1;
- else
- ::g->doomcom.extratics = 0;
- p = M_CheckParm ("-port");
- if (p && p < ::g->myargc-1)
- {
- DOOMPORT = atoi (::g->myargv[p+1]);
- I_Printf ("using alternate port %i\n",DOOMPORT);
- }
- // parse network game options,
- // -net <::g->consoleplayer> <host> <host> ...
- i = M_CheckParm ("-net");
- if (!i || !I_TrySetupNetwork())
- {
- // single player game
- ::g->netgame = false;
- ::g->doomcom.id = DOOMCOM_ID;
- ::g->doomcom.numplayers = ::g->doomcom.numnodes = 1;
- ::g->doomcom.deathmatch = false;
- ::g->doomcom.consoleplayer = 0;
- return;
- }
- netsend = PacketSend;
- netget = PacketGet;
- ::g->netgame = true;
- {
- ++i; // skip the '-net'
- ::g->doomcom.numnodes = 0;
- ::g->doomcom.consoleplayer = atoi( ::g->myargv[i] );
- // skip the console number
- ++i;
- ::g->doomcom.numnodes = 0;
- for (; i < ::g->myargc; ++i)
- {
- ::g->sendaddress[::g->doomcom.numnodes].sin_family = AF_INET;
- ::g->sendaddress[::g->doomcom.numnodes].sin_port = htons(DOOMPORT);
-
- // Pull out the port number.
- const std::string ipAddressWithPort( ::g->myargv[i] );
- const std::size_t colonPosition = ipAddressWithPort.find_last_of(':');
- std::string ipOnly;
- if( colonPosition != std::string::npos && colonPosition + 1 < ipAddressWithPort.size() ) {
- const std::string portOnly( ipAddressWithPort.substr( colonPosition + 1 ) );
- ::g->sendaddress[::g->doomcom.numnodes].sin_port = htons( atoi( portOnly.c_str() ) );
- ipOnly = ipAddressWithPort.substr( 0, colonPosition );
- } else {
- // Assume the address doesn't include a port.
- ipOnly = ipAddressWithPort;
- }
- in_addr_t ipAddress = inet_addr( ipOnly.c_str() );
- if ( ipAddress == INADDR_NONE ) {
- I_Error( "Invalid IP Address: %s\n", ipOnly.c_str() );
- session->QuitMatch();
- common->AddDialog( GDM_OPPONENT_CONNECTION_LOST, DIALOG_ACCEPT, NULL, NULL, false );
- }
- ::g->sendaddress[::g->doomcom.numnodes].sin_addr.s_addr = ipAddress;
- ::g->doomcom.numnodes++;
- }
-
- ::g->doomcom.id = DOOMCOM_ID;
- ::g->doomcom.numplayers = ::g->doomcom.numnodes;
- }
- if ( globalNetworking ) {
- // Setup sockets
- ::g->insocket = UDPsocket ();
- BindToLocalPort (::g->insocket,htons(DOOMPORT));
-
- // PS3 call to enable non-blocking mode
- int nonblocking = 1; // Non-zero is nonblocking mode.
- setsockopt( ::g->insocket, SOL_SOCKET, SO_NBIO, &nonblocking, sizeof(nonblocking));
- ::g->sendsocket = UDPsocket ();
- I_Printf( "[+] Setting up sockets for player %d\n", DoomLib::GetPlayer() );
- }
- }
- // DHM - Nerve
- void I_ShutdownNetwork( void ) {
- if ( globalNetworking && gameLocal != NULL ) {
-
- int curPlayer = DoomLib::GetPlayer();
- for (int player = 0; player < gameLocal->Interface.GetNumPlayers(); ++player)
- {
- DoomLib::SetPlayer( player );
- if ( IsValidSocket( ::g->insocket ) ) {
- I_Printf( "[-] Shut down insocket for player %d\n", DoomLib::GetPlayer() );
- shutdown( ::g->insocket, SHUT_RDWR );
- socketclose( ::g->insocket );
- }
- if ( IsValidSocket( ::g->sendsocket ) ) {
- I_Printf( "[-] Shut down sendsocket for player %d\n", DoomLib::GetPlayer() );
- shutdown( ::g->sendsocket, SHUT_RDWR );
- socketclose( ::g->sendsocket );
- }
- }
- DoomLib::SetPlayer(curPlayer);
- globalNetworking = false;
- }
- }
- void I_NetCmd (void)
- {
- if (::g->doomcom.command == CMD_SEND)
- {
- netsend ();
- }
- else if (::g->doomcom.command == CMD_GET)
- {
- netget ();
- }
- else
- I_Error ("Bad net cmd: %i\n",::g->doomcom.command);
- }
|