* * * $Header: //depot/C++/TATUNNEL_v2_UPnP/documentation/TATunnel_v2_distribution_4_Readme.txt#2 $ * * Contents ======== I. Purpose of TATunnel II. Development environment and restrictions 1. Development enviornment 2. Known restrictions III. How does TATunnel work? 1. Overview 2. TATunnelServer.exe endpoint command line parameters 3. TATunnelClient.exe endpoint command line parameters 4. Command line parameters: An overview on how they fit into the big picture. 5. Start sequence for all involved programs IV. Configuration examples 1. Running the TATunnel server endpoint in a sole Internet environment 2. Running the TATunnel server endpoint together with a ta instance in a NAT environenet on two differnt computers V. Code documentation 1. Compiler and Operating system support 2. Important C++ classes and their tasks 2.1 Thread classes handling the network traffic between the inner ta client and the ta server instance 2.2 Thread classes handling the network traffic between the inner ta client and an outer ta client instance 2.3 Diagram showing how the bridge thread classes fit into the big picture 2.4 Bridge thread start sequences and the tunnel link tie up process 3. Adapting the TaTunnelClient Microsoft VC++ project for your needs 4. Compiling the x64 bit version of the TATunnel programs 4.1 Prerequisites 4.2 build_x64.cmd usage 4.3 Restrictions VI. Planned changes, tests and enhancements. I. Purpose of TATunnel =================== TA Tunnel allows you to join a TA game hosted on the Internet from within a restricted network. Restricted in this context translates into the following possible sceanrios: a) A network is sharing a single IP address for multiple computers to communicate with the Internet and a Network Address Translation (NAT) entity (which can be a hardware router built into a DLS/cable modem or a 'software router' like f.ex. a Linux box) is mapping this single IP address to the private IP addresses of the respective network computer. Due to TA's peer to peer connection approach in such a NATed environment you would need to have access to the configuration of the NAT entity in order to configure it properly for TA's network traffic needs. b) The TA computer got a valid IP address assigned but the traffic is restricted by a firewall sitting somewehere in between your TA computer and the other TA instances on the Internet. For example, the firewall might be configured in way that only outgoing connections on the HTTP network port (80) are allowed which means you can to browse the Internet but won't allow any Internet computer to make a connection to your computer (which is required for a TA game). In either case it's not likely that you will have the required access to configure the NAT entity or the firewall so it could suit the needs of TA if your TA runs on a computer located in a college, university or company network. II. Development environment and restrictions ======================================== 1. Development enviornment ----------------------- The program is based on an analysis of the the TA network traffic generated by a TA game running in a Local Area Network (LAN). Although the DirectPlay protocol analysis has been conducted in a LAN enviornment I have tested the actual tunneling functions in a realistic environment with all ta instances joining from different Internet Service Providers (ISPs). Both tunnel endpoint programms have been tested on Windows 2000 and Windows 95. The DirectX version running on the Windows 95 computer is 8.x which is the last version available for this operating system. The Windows 2000 machines run DirectX version 9.x. So far I have tested games with up to four ta instances involved. Both tunnel endpoint programms make heavy use of multithreading so I have tested them both on a dual CPU machine in order to detect problems possibly related to thread synchronization/lock ups. With multithreading timings play a great role so there are very likely a lot of bugs lurking in the current version I simply could not trigger yet because a single person can never produce the same timings as f.ex. four independent acting entities (like four people trying to join a game at the same time). So don't expect the current version to be bug free in that regard. It'll need the feedback from people who actually encounter those lurking beasts to get them fixed. 2. Known restrictions ------------------ - TATunnel allows only to JOIN a TA game. You CAN'T HOST a game from behind the tunnel. - A single tunnel server side endpoint does not not support to join the SAME TA game instance with more than one ta client from behind a client side tunnel endpoint. Right now there is no check against such a unsupported join up scenario implemented in server side tunnel endpoint program so it will act pretty weired if you actully screw things up this way. You can still join DIFFERENT TA game instances over the same tunnel server side endpoint though. - TATunnel requires all computers participating in a TA game to have DirectX 8.x or higher installed. - The tunnel client side endpoint program HAS to bind TCP port 47624 in order to incarnate a ta server for the restricted ta client. There is no way to change this so you have to make sure that the port is not already used by DirectX's DirectPlay proxy process dplaysvr.exe when you start the tunnel client side endpoint program. TATunnelClient.exe will abort with an error message if another process is already listening on that TCP port. - TATunnel is not supported by TA game services. This is not a restriction within the programm itself but more a problem of the game service launcher that had to report two differnt ta server IPs to the ta client instances involved into a game hosted there: The ta client residing behind the tunnel client side endpoint had to be fed with the same value used for the parameter -flip when starting TATunnelclient.exe rather the real ta server IP while the other ta clients instances had to be fed with the real ta server IP. Solving this 'dual ta server IP' problem would require that the ta game service provides a configuration option for an additional 'fake ta server IP' (the listening IP of the local tunnel end program incarnating the ta server). - The following point is only of interest for people who think of using the program sources to enhance the functionality of TAtunnel or who plan to use it as a template for their own program: TATunnel can't be used to modify any data at the context level of a TA game itself. It modifies packets below the level of the DirectPlay API by overwriting IP and port number information to be found at certain postions in the raw data stream. So you can't use it to modify the TA game data stream in way that would for example allow you to inject *new* chat messages from within a tunnel endpoint program or change battleroom options automatically. III. How does TATunnel work? ======================= 1. Overview -------- As the name implies a tunnel has always two endpoints: In the case of TATunnel the 'server side' endpoint is running on an IP address that is not restricted in any way (thus its possible to make connections to and from that IP) and which incarnates the ta client residing in the restricted network for all other ta client instances and the ta server instance in a TA game. The 'client side' endpoint runs in the restricted network and incarnates the ta server instance and the other ta client instances actually located on the Internet and therefore creates the impression for the ta client in the restricted network that the whole game would take place there rather than on the Internet. The diagram below shows how TA client instance 3 residing in a restricted network 'sees' the game and how it looks from the view point of the ta server instance and the other ta client instances on the Internet. To keep things simple the graphic doesn't show the connections between the ta instances and the tunnel endpoints. * denotes the endpoint that opened a network connection o denotes the endpoint that accepted a network connection +---------------------------+ +---------------------------+ +---------------------------+ | | | | | | | TA host instance | | TA client instance 1 | | TA client instance 2 | | | | | | | +---------------------------+ +---------------------------+ +---------------------------+ +---------------------------+ | | | fake TA client instance 3 | | | +-------------------------------------+...........................+-------------------------------------+ | | | | | tunnel server side endpoint | | | | | +---------------------------------------------------o---------------------------------------------------+ | | | | / / | | | | +---------------------------------------------------*---------------------------------------------------+ | | | | | tunnel client side endpoint | | | | | +...........................+---------+...........................+---------+...........................+ | | | | | | | fake TA host instance | | fake TA client instance 1 | | fake TA client instance 2 | | | | | | | +---------------------------+ +---------------------------+ +---------------------------+ +---------------------------+ | | | TA client instance 3 | | | +---------------------------+ 2. TATunnelServer.exe endpoint command line parameters --------------------------------------------------- TATunnelServer.exe implements the tunnel server side endpoint of the tunnel. Required parameters: -tlip: (TunnelLocalIP) Determines the IP of the interface to bind for the tunnel endpoint to tunnel endpoint communication at the server side of the tunnel in format of a dotted IP. Use this value for the value -trip at the tunnel client side end to tie up the two tunnel endpoints. OR -tlhn: (TunnelLocalHostName) Same as -tlip above only you determine the interface to bind by a host name. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the server side tunnel end program is restarted. -flip: (FakeLocalIP) Sets the IP of the interface to use for the fake ta instance running in the server side tunnel endpoint. The real ta server and ta client instances on the Internet will reconize the restricted client actually residing behind the remote tunnel end by this IP. OR -flhn: (FakeLocalHostName) Same as -flip above only you determine the interface to bind by a host name. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the server side tunnel end program is restarted. Optional parameters: -tlpt: (TunelLocalPortnumberTcp) Sets the port number to use for the TCP conenction lanes between the two tunnel ends. If the parameter is not set then the tunnel end to tunnel end lanes will be established on the HTTP protocol standard port (80). -flpu: (FakeLocalPortUdp) Sets the lower boundary for the fake instance UDP port pool. -flpU: (FakeLocalPortUdp) Sets the upper boundary for the fake instance UDP port pool. If you don't set these two parameters then the port manager will use ports from within the range 20000-20999 to incarnate a fake ta's instance UDP sending/receiving socket. At the server side of the tunnel you will need one UDP port number for each TA game tunneled thru the tunnel server side endpoint. -flpt: (FakeLocalPortnumberTcp) Sets the lower boundary for the fake instance TCP port pool. -flpT: (FakeLocalPortnumberTcp) Sets the upper boundary for the fake isntance TCP port pool. If you don't set these two parameters then the port manager will use ports from within the range 21000-21999 to incarnate a fake ta's instance TCP sending/receiving socket. At the server side of the tunnel you will need one TCP port number for each TA game tunneled thru the tunnel server side endpoint. 3. TATunnelClient.exe endpoint command line parameters --------------------------------------------------- TATunnelClient.exe implements the tunnel client side endpoint of the tunnel. Required parameters: -taip: (TAIP) Determines the IP of the real ta host located on the Internet in format of a dotted IP. The server side tunnel endpoint needs this information in order to initiate the join process with the ta server. OR -tahn: (TAHostName) Same as -taip above only you determine the interface to bind by a host name. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the client side tunnel endpoint program is restarted. -trip: (TunnelRemoteIP) Tells the program the IP of interface the tunel server side endpoint program is expecting tunnel connection request on in form of a dotted IP. This is the counterpart to the tunnel server side endpoint program's switch -tlip. OR -trhn: (TunnelRemoteHostName) Same as -trip above but the IP to connect is determined by resolving the host name given. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the client side tunnel endpoint program is restarted. -tlip: (TunnelLocalIP) Determines the IP of the interface to bind for the tunnel endpoint to tunnel endpoint communication at the client side endpoint of the tunnel in format of a dotted IP. OR -tlhn: (TunnelLocalHostName) Same as -tlip above only you determine the interface to bind by a host name. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the client side tunnel end program is restarted. -flip: (FakeLocalIP) Sets the IP of the interface to use for the fake ta instances running in the client side tunnel endpoint. The real ta client in the restricted network will reconize the ta server instance and the other ta client instances actually located on the Internet by this IP. OR -flhn: (FakeLocalHostName) Same as -flip above only you determine the interface to bind by a host name. The name gets resolved only once when the program starts so don't expect a change in the DNS server settings to have an impact until the server side tunnel end program is restarted. Optional parameters: -trpt: (TunnelRemotePortnumberTcp) Sets the port number on which the server side tunnel endpoint program is listening for tunnel connection requests. This is the counterpart to the tunnel server side endpoint program's parameter -tlpt. If the parameter is not set then the program will try to contact the tunnel server side endpoint program on the HTTP protocol standard port (80). -flpu: (FakeLocalPortnumberUdp) Sets the lower boundary for the fake instance UDP port pool. -flpU: (FakeLocalPortnumberUdp) Sets the uper boundary for the fake isntance UDP port pool. If you don't set these two parameters then the port manager will use ports from within the range 20000-20999 to incarnate a fake ta's instance UDP sending/receiving socket. At the client side of the tunnel you will need (1 + ) UDP port numbers (where is number of join processes of ta client instances from the internet) Note that denotes the number of join processes and not the number of Internet ta clients in a game. If f.ex. client 1 joins, leaves and join's again then two and not only one fake ports will be wasted. -flpt: (FakeLocalPortnumberTcp) Sets the lower boundary for the fake instance TCP port pool. -flpT: (FakeLocalPortnumberTcp) Sets the uper boundary for the fake isntance TCP port pool. If you don't set these two parameters then the port manager will use ports from within the range 21000-21999 to incarnate a fake ta's instance TCP sending/receiving socket. At the client side of the tunnel you will need (1 + ) TCP port numbers for a TA game (where is number of join processes of ta client instances from the internet). Note that denotes the number of join processes and not the number of Internet ta clients in a game. If f.ex. client 1 joins, leaves and join's again then two and not only one fake ports will be wasted. 4. Command line parameters: An overview on how they fit into the big picture ------------------------------------------------------------------------- In order to show how the command line switches fit into the big picture we need to go a bit more into detail. Principle every ta instance has two TCP connections to each other ta instance in a game: - One TCP connection to receive data from the peer instance. - One TCP connection to send data to the peer instance Additionaly each ta instance is using a single UDP socket: - One UDP socket to receive and send data from/to ALL peer instances. TATunnel is imitating the above behavior but there are some additional points to consider too: A TATunnel fake ta instance is never exchanging data with another fake ta instance. For example, the fake ta server instance and fake ta client instances 1 and 2 at the client side tunnel endpoint don't exchange data with each other while the real ta instances on top of the server side tunnel endpoint they incarnate actually do. Furthermore both tunnel endpoints allow to bind two different IPs for the network traffic transfered between them and the network traffic between them and the ta instances they face. This does effectively allow each tunnel endpoint to bridge two network interfaces on a multihomed computer which might be especially of interest for the server side tunnel endpoint that is designed to run as a server application on a dedicated server, supporting multiple tunnel sessions at the same time. Using different interfaces for the two sides of each tunnel endpoint is optional, the tunnel endpoint programs will run just fine on a single IP interface (usually found on home computers) too. Special symbols usesd in the diagram below are: Parameters in {} denote their counterpart in the other tunnel endpoint. For TCP connections: * denotes an endpoint that opened a network connection o denotes an endpoint that accepted a network connection For UDP connections: * denotes an endpoint that sends data o denotes an endpoint that receives data (*) denotes an endpoint sends and receives data +------------------------------+ +------------------------------+ | | | | | | | | | | | | | TA host instance | | TA client instance 1 | | | | | | {-taip:47624} | | | | | | | +------*-----o------------(*)--+ +--(*)------------o-----*------+ | | | | | | | | | | | | | | | | | | | | | | | | | | +--------------------+---------------------+ | | | | | | | | | | | | | | | | | +----------o-----*----------+----------------------(*)------------------------+---------*-----o-----------+ | | | | | | | | | TCP bridges for TA host | UDP deMultiplexer for all ta instances |TCP bridges for TA client 1| | | | | | | | | +---------------------------+-------------------------------------------------+---------------------------+ | | | | | IP:TCP port | IP:UDP port | IP:TCP port | | | | | | -flip:[-flpt...-flpT] | -flip:[-flpu...-flp] | -flip:[-flpt...-flpT] | | | | | +---------------------------+-------------------------------------------------+---------------------------+ | | | | | | | | | | | | | | | tunnel server side endpoint | | | | | | | | | | | | | | | +---------------------------------------------------------------------------------------------------------+ | | | IP:TCP port | | | | -tlip:-tlpt {-trip:-trpt} | | | +------------------------+---------------------------+---------------------------+------------------------+ | | | | | | | | | | | TCP bridges for | UDP bridges for | UDP bridges for | TCP bridges for | | | | | | | TA host | TA host | TA client 1 | TA client 1 | | | | | | +-----o------------o-----+------o--------------o-----+-----o--------------o------+-----o------------o-----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | / / / / / / / / / / / / / / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-----*------------*-----+------*--------------*-----+-----*--------------*------+-----*------------*-----+ | | | | | | | | | | | TCP bridges for | UDP bridges for | UDP bridges for | TCP bridges for | | | | | | | TA host | TA host | TA client 1 | TA client 1 | | | | | | +---------------------------------------------------------------------------------------------------------+ | | | IP:TCP port | | | | -tlip:-tlpt | | | +---------------------------------------------------------------------------------------------------------+ | | | | | | | | | | | | | | | tunnel client side endpoint | | | | | | | | | | | | | | | +------------------------+-------------------------------------------------------+------------------------+ | | | | | IP:TCP port | IP:UDP port | IP:TCP port | | | | | | -flip:[-flpt...-flpT] | -flip:[-flpu...-flp] | -flip:[-flpt...-flpT] | | | | | +------------------------+---------------------------+---------------------------+------------------------+ | | | | | | | | | | | TCP bridges for | UDP traffic handler for | UDP traffic handler for | TCP bridges for | | | | | | | TA host | TA host | TA client 1 | TA client 1 | | | | | | +----*------------o------+------------(*)------------+------------(*)------------+------o------------*----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------------+-------------+ | | | | | | | | | | | | | | | | | | | | | | | | +--------------(*)--------------+ | | | | | | | | | | | | | | | +------------------* *------------------+ | | | TA client instance 2 | | +-------------------------------o o-------------------------------+ | | | | +-------------------------------+ 5. Start sequence for all involved programs ---------------------------------------- (1) Start TATunnelServer.exe. (2) Start the TA host instance and proceesd to the battleroom screen. (3) Start TATunnelClient.exe. (4) Join the game with either the ta client in the restricted network or any ta client on the Internet in any order. If you join with the inner ta client you have to enter the IP you used for the parameter -flip in the TATunnelClient.exe call for the IP of the ta host. All outer ta clients just have to use the real ta host's IP in order to connect to the game. You can leave the game with any joined ta client and you can join again without restarting TATunnelServer.exe. If the ta client at the tunnel client side endpoint leaves the battleroom/running game you have to start over at (3) though. After a TA game terminated you can keep TATunnelServer.exe running. To create a new game using the still running TATunnelServer.exe instance just start over with step (2). IV. Configuration examples ====================== For TCP connections: * denotes the endpoint that opened a network connection o denotes the endpoint that accepted a network connection For UDP connections: * denotes the endpoint the sends data o denotes the endpoint that receives data (*) denotes that the endpoint sends and receives data For the examples we assume that the computers running the tunnel endpoint programs are not multihomed, ie. don't sport more than one IP interface which simplifies setting the parameters since then the switches -flip and -tlip take always the same values. 1. Running the TATunnel server endpoint in a sole Internet environment ------------------------------------------------------------------- ______Internet__________________________________________________________________________________________ +--------------------------------+ | | | TA host (60.132.4.80) | | | +------*-------------------o-----+ | | | | 20000-20999[TCP], 21000-21999[UDP] | | 2300-2400[TCP/UDP], 47624[TCP] | | | | +------o-------------------*-----+ | | | TATunnelServer (217.80.1.45) | | | +----------------o---------------+ | | | / / 80[TCP] | | | +----------------*---------------+ | | ______Internet_________________ | | ______________________________________ | | | | | Router of restricted network | | | ______restricted network_______ | | ______________________________________ | | | | +----------------o---------------+ | | | 80[TCP] | | +----------------*---------------+ | | | tatunnelclient (192.168.201.4) | | | +------*-------------------o-----+ | | | | 2300-2400[TCP/UDP] | | 47624[TCP], 20000-20999[TCP], 21000-21999[UDP] | | | | +------o-------------------*-----+ | | | TA client (192.168.201.4) | | | +--------------------------------+ ______restricted network__________________________________________________________________________________ With this setup you would have launched TAtunnelServer.exe as follows: TATunnelServer -tlip 217.80.1.45 -flip 217.80.1.45 TATunnelClient.exe would have been launched as follows: TATunnelClient -taip 60.132.4.80 -trip 217.80.1.45 -tlip 192.168.201.4 -flip 192.168.201.4 2. Running the TATunnel server endpoint together with a ta instance in a NAT environment on two differnt computers --------------------------------------------------------------------------------------------------------------- I M P O R T A N T THIS SCENARIO WILL ONLY WORK OUT IF YOUR NAT ENTITY SUPPORTS FULL FLEDGED U-BEND FORWARDING. BEFORE YOU BOTHER WITH TRYING THIS SETUP OUT TEST THE U-BEND FORWARDING CAPABILITIES OF YOUR NAT ENTITY WITH THE TOOL UBENDCHECK WHICH CAN BE FOUND HERE. http://www.tcbw.net/ta/idxS19TA.html IF THE TEST FAILS FOR THE TCP AND/OR UDP TRAFFIC THEN THE SCENARIO DESCRIBED BELOW IS NO CHOICE FOR YOU. ______NAT LAN ____________________________________________________________________________________________ +--------------------------------+ +--------------------------------+ | | | | | TA host (10.0.0.2) | | TATunnelServer (10.0.0.3) | | | | | +-----------*---------o----------+ +---o--*---------------------o---+ | | | | | 20000-20999[TCP],| | 2300-2400[TCP/UDP] | | | 21000-21999[UDP] | | 47624[TCP] | | | 80[TCP] | | | | | | | 20000-20999[TCP],| | 2300-2400[TCP/UDP], | | | 21000-21999[UDP] | | 47624[TCP] | | | | | | | | | | | +--o---------*---------------------------*--o---------------------*---+ | | | | | | | ______NAT LAN __ | | | | | | | _______________ | | | | | | | | #=========#===========================#==# | | | U-bend forwarding bus | | | | | | | | | | | | NAT solution (Internet IP 188.12.15.30) | | | | | | | | | | | | | | | +---------------------------------+ | | | | ______Internet__ | | | _______________ | | | | | | +-------------------------------o-------------------------------------+ | | | / / 80[TCP] | | | +----------------*---------------+ | | ______Internet_________________ | | ______________________________________ | | | | | Router of restricted network | | | ______restricted network_______ | | ______________________________________ | | | | +----------------o---------------+ | | | 80[TCP] | | +----------------*---------------+ | | | TATunnelClient (192.168.201.4) | | | +------*-------------------o-----+ | | | | 2300-2400[TCP/UDP] | | 47624[TCP], 20000-20999[TCP], 21000-21999[UDP] | | | | +------o-------------------*-----+ | | | TA client (192.168.201.4) | | | +--------------------------------+ ______restricted network_________________________________________________________________________________ With this setup you would have launched TAtunnelServer.exe as follows: TATunnelServer -tlip 10.0.0.2 -flip 10.0.0.2 TATunnelClient.exe would have been launched as follows: TATunnelClient -taip 188.12.15.30 -trip 188.12.15.30 -tlip 192.168.201.4 -flip 192.168.201.4 It's important to NOT use the the NAT LAN IP 10.0.0.2 for the switch -taip because that would lead to the fatal effect that the ta host would reconize the fake ta client running at IP 10.0.0.3 (the tunnel server end) under its LAN IP. While that was not a problem as far as the network traffic between the ta host and the fake ta client behind the NAT is concerned it would lead to a LAN IP spoiled host info list in the ta server instance: As soon as the first outer ta client joins the game it would try to connect the fake ta client under IP 10.0.0.2 (which is unreachable from the Internet) rather then under IP 188.12.15.30. The required NAT forwarding rules for the example above are: 47624[TCP] --> 10.0.0.2 2300-2400[TCP/UDP] --> 10.0.0.2 20000-20999[TCP] --> 10.0.0.3 21000-21999[UDP] --> 10.0.0.3 80[TCP] --> 10.0.0.3 V. Code documentation ================== 1. Compiler and Operating system support ------------------------------------- The code has been developed in a Microsoft Visual C++ 6.0 IDE. Thus there are no makefiles but only project files suited for that development enviornment available. The code is clearly streamlined for Windows operating systems and no efforts have been taken to support communication between two tunnel endpoints possibly running on different operating systems. For example, the NetworkLink classes don't support a data transfer mechanism independent from the CPU byte order of the machine the tunnel endpoint program is executed on. Extensive use of Windows API specific functions may also make it difficult to port the programs to another operating system platform. 2. Important C++ clases and their tasks ------------------------------------- The indexes in square brackets [] in front of each class name denote its position in the diagram in section 2.3. In the following text the term 'inner ta client' referrs to the ta client running in the restricted network behind the tunnel. the term 'outer' referrs to ta clients and the ta server located on the internet on the other side of the tunnel (see section III. 1.). 2.1 Thread classes handling the network traffic between the inner ta client and the ta server instance -------------------------------------------------------------------------------------------------- In the tunnel server endpoint: [1] TunnelServerEndToTaServerJoinBridge Incarnates the inner ta clients 47624 join up TCP connection for the ta server. This connection lives only a short time, its main purpose is to tell the ta server the joining ta client's instances TCP listen portnumber. Together with thread [8] in the tunnel client side endpoint this thread implements the inner ta client --> ta server port 47624 TCP join traffic bridge. [2] TaServerToTunnelServerEndTCPBridge Incarnates the TCP input lane of the inner ta client for the ta server. This thread will handle all the TCP traffic sent by the ta server and directed to the inner ta client. Together with thread [9] in the tunnel client endpoint this implements the ta server --> inner ta client TCP traffic bridge. [3] TunnelServerEndToTaServerTCPBridge Fakes the output TCP lane of the inner ta client for the ta server. This thread will forward all TCP traffic sent by the inner ta client to the ta server. Together with thread [10] in the tunnel client side endpoint this implements the inner ta client --> ta server TCP traffic bridge. [4] TunnelServerEndToTaServerUDPBridge This thread forwards the UDP traffic sent by the inner ta client to the ta server. Note that the thread itself does not run a sender UDP socket. Instead it enques the DirectPlay UDP packets in the command queue of the UDP deMultiplexer [6] which takes care of the actual UDP send operation. While it's possible to split sending and receiving the UDP traffic between two seperate UDP socket instances (it had been done that way in previous versions of TA tunnel) this approach would require to bind two different socket port numbers, resulting in a traffic signature pretty different from original TA where a single UDP socket instance handles all the incomming and outgoing traffic for a single ta instance. So for the sake of compatibility with original TA the old split approach has been replaced by the new, single sender/receiver approach. Together with threads [12], [21a] and [6] thread [4] does implement the inner ta client --> ta server UDP traffic bridge. [5] TaServerToTunnelServerEndUDPBridge Provides the tunnel server side endpoint transport mechanism for UDP packets sent by the ta server and directed to the inner ta client. Note that the thread itself doesn't run an UDP listen socket. Instead the UDP deMultiplexer thread [6] (see below) is forwarding the UDP DirectPlay packets received from the ta server to this thread's command queue. Together with threads [11], [21a] and [6] this implements the ta server --> inner ta client UDP traffic bridge. [6] UdpDeMultiplexer This thread impersonates the inner ta client's UDP socket handling all its UDP traffic (ingoing and outgoing). In contrast to the tunnel client end side there is only a single instance of this class up and running handling the traffic for ALL incarnation thread groups, no mattter whether ta server or outer ta clients. This is required to keep the traffic signature identical to the orginal TA traffic signature. [7a] GameManagerAtServer In the context of bridging ta game data this thread is only responsible for accepting and deMultiplexing TCP connection request made by outer ta instances. In contrast to UDP traffic where there is no such thing as an accpet()ed socket object an accept()ed TCP socket can be handed over to the thread responsible for the tunnel transport so there is no deMultiplexing of the TCP traffic itself required, only the connction requests have to be deMultiplexed. The reason why we have to implement TCP connection deMultiplexing at all is the same as for the UDP traffic directd to our fake ta client: We don't have control over the server info packet contents send to outer ta instances by the ta server and thus we can't modify the listen portnumber we are supposed to wait on for connection request made by outer ta clients. Thus listen portnumber and IP address wise outer ta clients will always reconize the inner ta client in the same way as the ta server does. The game manager in the server side tunnel endpoint has also a counterpart thread [7b] (see below) running in the tunnel client side endpoint. Both threads are connected via a dedicated TCP connection which is used to transfer commands forth back between them (f.ex. requests to launch additional thread groups, stage switch acknowledgements etc.) In the tunnel client endpoint: [7b] GameManagerAtClient Initiates the tie up with the tunnel server endpoint and implements the counter part for the server side game manager instance [7a] in the tunnel client side endpoint. Its main purpose is to carry out requests in the tunnel client side endpoint on behalf of its server side counter part. [8] TaClientToTunnelClientEndJoinBridge Incarnates the ta server's port 47624 TCP listener at the client end of the tunnel. This connection lives only a short time, its main purpose is to forward the information carrying the joining inner ta client's TCP listen portnumber to the ta server. Together with thread [1] in the tunnel server side endpoint this thread implements the inner ta client --> ta server port 47624 TCP join traffic bridge. [9] TunnelClientEndForTaServerToTaClientTCPBridge Fakes the ta server's TCP output lane for the inner ta client at the client side endpoint of the tunnel. Together with thread [2] in the tunnel server side endpoint this implements the ta server --> inner ta client TCP traffic bridge. [10] TaClientToTunnelClientEndForTaServerTCPBridge Incarnates the ta server's TCP input lane for the inner ta client at the client endpoint of the tunnel. Together with thread [3] in the tunnel server endpoint this implements the inner ta client --> ta server TCP traffic bridge. [11] TunnelClientEndForTaServerToTaClientUDPBridge Forwards DiretPlay UDP packets from the ta server to the UDP traffic handler of the ta server incarnation thread group [21a] by enqueuing them into the UDP traffic handler's command queue. Again, while it's technically possible to split the UDP traffic between two differnt socket instances - one for sending and one for receiving - for the sake of compatibilty with original TA a single UDP socket is used for both directions by detouring the UDP packets via the UDP traffic handler [21a]. Together with threads [5], [6] and [21a] this implements the ta server --> inner ta client UDP traffic bridge. [12] TaClientToTunnelClientEndForTaServerUDPBridge Forwards DirectPlay UDP packets from the inner ta client to the other tunnel endpoint for further processing. The packes are enqueued by the UDP traffic handler thread [21a] responsible for handling the actual UDP socket. The reason why the thread doesn't run its own UDP socket instance to receive the traffic from the inner ta client directly (like it was done in previous versions of TA tunnel) is again the effort to keep the traffic signature as identical with original TA as possible. Together with threads [4], [6] and [21a] this implements the inner ta client --> ta server UDP traffic bridge. 2.2 Thread classes handling the network traffic between the inner ta client and an outer ta client instance ------------------------------------------------------------------------------------------------------- In contrast to the two ta server bridge thread groups [1] .. [5] and [8] .. [12] + [21a] which exist only once per ta game instance in the tunnel endpoints each outer ta client instance in a single ta game is represented by its own instance of the two thread groups [13] .. [16] and [17] .. [21b]. In the tunnel server endpoint: [6] UdpDeMultiplexer (see section 2.1) [7a] GameManagerAtServer (see section 2.1) [13] TaClientToTunnelServerEndTCPBridge Incarnates the TCP input lane of the inner ta client for an outer ta client instance. This thread will handle all the TCP traffic sent by a particular outer ta client instance and directed to the inner ta client. Together with thread [17] in the tunnel client endpoint this implements an outer ta client instance --> inner ta client TCP traffic bridge. [14] TunnelServerEndToTaClientTCPBridge Incarantes the output TCP lane of the inner ta client for a particular outer ta client instance. This thread will forward all TCP traffic sent by the inner ta client to an outer ta client instance. Together with thread [18] in the tunnel client endpoint this implements an inner ta client --> outer ta client instance TCP traffic bridge. [15] TaClientToTunnelServerEndUDPBridge This thread forwards UDP packets originally sent by a particular outer ta client instance and directed to the inner ta client instance to the client endpoint side of the tunnel. The thread doesn't run its own UDP socket instance. Instead the packets are enqueued into its command queue by the UDP deMultiplexer [6]. Again, detouring via the deMultiplexer is done for the sake of keeping the network traffic signature identical to original TA. Together with threads [6], [19] and [21b] this implements an outer ta client instance --> inner ta client UDP traffic bridge. [16] TunnelServerEndToTaClientUDPBridge This thread forwards the UDP traffic sent by the inner ta client to an particular outer ta client instance into the UDP deMultiplexer's [6] command queue. Although the thread could as well run its own sender UDP socket to send the data directly to the outer ta client instance this task is left to the deMultiplexer in order to have all UDP traffic of the faked inner ta instance going over the same unique UDP socket.Together with threads [21b], [20] and [6] this implements an inner ta client --> outer ta client instance UDP traffic bridge. In the tunnel client endpoint: [7b] GameManagerAtClient (see section 2.1) [17] TunnelClientEndForTaClientToTaClientTCPBridge Incarantes an outer ta client instance's TCP output lane for the inner ta client at the client side endpoint of the tunnel. Together with thread [13] in the tunnel server endpoint this implements an outer ta client instance --> inner ta client TCP traffic bridge. [18] TaClientToTunnelClientEndForTaClientTCPBridge Incarnates an outer ta client instance's TCP input lane for the inner ta client at the client side endpoint of the tunnel. Together with thread [14] in the tunnel server endpoint this implements an inner ta client --> outer ta client instance TCP traffic bridge. [19] TunnelClientEndForTaClientToTaClientUDPBridge Forwards UDP packets sent by an particular outer ta instance and directed to the inner ta client instance to the UDP traffic handler thread instnace [21b] in charge for handling all UDP traffic between the inner ta client and the thread group faking that outer ta client at the client side tunnel endpoint. Again, detouring the traffic via the UDP traffic handler rather than running a own UDP sender socket is only done for the sake of traffic signature compatibilty with original TA. Together with threads [6], [15] and [21b] this implements an outer ta client instance --> inner ta client UDP traffic bridge. [20] TaClientToTunnelClientEndForTaClientUDPBridge Receives UDP packets sent by the inner ta client and directed to a particular outer ta client instance from the client tunnel endpoint side UDP traffic handler thread and forwards the data to its remote counterpart in the server side tunnel endpoint. The same consideration as for all other threads involved into UDP traffic apply here too: The thread is not running its own UDP listen socket (which would allow to receive the UDP traffic directly from the inner ta client) in order to avoid to have two differnt UDP sockets involved in the UDP traffic exchange between the fake ta client instance and the inner ta client. Together with threads [16], [6] and [21b] this implements an inner ta client --> outer ta client instance UDP traffic bridge. [21a/b] UdpTrafficHandler Runs the UDP sender/receiver socket at the tunnel client side endpoint for the thread group incaranting the ta server or a thread group incarnating a particular outer ta client instance for the inner ta client. 2.3 Diagram showing how the bridge thread classes fit into the big picture ---------------------------------------------------------------------- Special symbols usesd in the diagram below are: For TCP connections (T): * denotes an endpoint that opened a network connection o denotes an endpoint that accepted a network connection For UDP connections (U): * denotes an endpoint that sends data o denotes an endpoint that receives data (*) denotes an endpoint sends and receives data +-----------------------------+ +-----------------------------+ | | | | | | | | | | | | | TA host instance | | TA client instance 1 | | | | | | | | | | | | | +-o--*-----o------------(*)---+ +---(*)------------o-----*----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | +--(T)-+ (T) (T) +--------------------+--------------------+ (T) (T) | | | | | | | | | | | | | | | (U) | | | | | | | | | | | | | | +-----*--+------o--+--*------+---------+----------------(*)----------------+---------+------*--+--o------+ | | | | | | | | | | | | | -------> <------- | | | | | | | | | [6] | | | | | | | | | | | | | | | | | | | | +----|----+---------------+----|----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | V | | V | | | | | | | | | | | | | | | | | | | | | | | | | | | [1] | [2] | [3] | [4] | [5] | tunnel server | [15] | [16] | [14] | [13] | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------+ | | | | | | | | | | | | | | | | | | | | | [7a] | | | | | | | | | | | | | | | | +---o----+----o----+----o----+----o----+----o----+-------o-------+----o----+----o----+----o----+----o----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | / / / / / | / / / / / / / / / / / / / / | | | | | / | | | | | | | | | | | | | | | | | | | | | | | | (T) (T) (T) (T) (T) (T) (T) (T) (T) (T) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---*----+----*----+----*----+----*----+----*----+-------*-------+----*----+----*----+----*----+----*----+ | | | | | | | | | | | | | | | | | [7b] | | | | | | | | | | | | | | | | | | | | | +---------------+ | | | | | | | | [12] | [11] | | [19] | [20] | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [8] | [9] | [10] | A | | | tunnel client | | | A | [18] | [17] | | | | | | | | | | | | | | | | | | | |-------------------| |----|---------|----| | | | | | | | | | | | | | | | | | | | | V | | V | | | | | | | | [21a] | | [21b] | | | | | | | | | | | | | | | | | | | | | +---o----+----*----+----o----+--------(*)--------+---------------+--------(*)--------+----o----+----*----+ | | | | | | | | | | | | | | | | | | | | | (T) (T) (T) +-----------------+-----------------+ (T) (T) | | | | | | | | | | | | | | +---------------------------+ (U) +---------------------------+ | | | | | | | | | | | | | | +---------------------------------+ | | | +---------------------------------+ | | | | | | | | | | | | | | | | | | +--------------------------------------+ | | | | | | | | | | | | | | | | | | | | | | | +---*----o---*---(*)---*---o--------+ | | | | | | | TA client instance 2 | | | | | | | +-----------------------------------+ 2.4 Bridge thread start sequences and the tunnel link tie up process ---------------------------------------------------------------- The tunnel server side endpoint thread group [1] .. [7a], the tunnel server side UDP deMultiplexer [6], the tunnel client side thread group [7b] .. [12] and the client side UDP traffic handler for the ta server instance incarnation thread group are launched as soon as the tunnel client side endpoint program TATunnelClient.exe connects the tunnel server side endpoint program TATunnelServer.exe. The server side thread group of a fake ta instance is always launched first. Immediatly after starting such a group a 'launch mirror thread group' request is sent by the server side game manager [7a] to the client side game manager [7b]. The client side game manager will then start the counter part threads in the client side endpoint of the tunnel. Tunnel link tie ups are done on a per thread pair base: As soon as a client side bridge thread has started in response to a mirror request it will contact the tunnel link manager (which is not shown in the diagram above) on the tunnel server side endpoint's TCP tunnel listen portnumber. This will result in a new TCP tunnel link. The first command the client side thread puts on the newly established link gives the tunnel link manager all information required to figure out which of the server side game manager instances has launched the local coutner part thread. It then forwards the accept()ed tunnel link to that game manager instance. Once the newly tunnel link object arrives at the game manager instance it forwards it to the counter part thread running in the server which finalizes the tunnel link tie up process between the local and remote thread. After launching the ta server bridge thread groups in both tunnel ends and tying them up with each other the tunnel is done with its initialization taks. Until the inner ta client starts and tries to contact the fake ta server (the client side endpoint of the tunnel) it'll just idle in hibernate mode. In contrast to the ta server bridge thread groups outer ta client instance bridge thread groups are launched on demand: For each outer ta client already on the ta server's info list when the inner ta clients joins a ta game an additional thread group gets launched in the server and the client side endpoint. An outer ta client instance joining after the inner ta client has joined the game will also lead to an on demand start of additional bridge thread groups. 3. Adapting the TaTunnelClient Microsoft VC++ project to your needs ---------------------------------------------------------------- The project file for the TATunnelClient binary as it's shipped now won't compile without errors because it contains source files for a lexical scanner (html.l) and a parser (html.y). You have two choices here: 1) You exclude the files html.l and html.y from the project build by setting the respective property flag in the project node for the two files. With this approach a 'static' version of the scanner and parser is compiled into the binary every time the project is build. This 'static' state is reflected in the three files html_y.cpp, html_y.h and html_l.cpp. 2) You install the third party software required to generate the scanner (html_l.cpp) and parser (html_y.cpp, html_y.h) from the source files html.l and html.y. I'm using the GNU Bison/Flex gnerators which can be found here: http://gnuwin32.sourceforge.net/packages/flex.htm http://gnuwin32.sourceforge.net/packages/bison.htm Both software packages are distributed under the GNU Public Licence (GPL) which is also the reason why I didn't bother to add add both tools to the TATunnel source packet. The generated parser file itself does NOT fall under the GPL thus it's legit to ship a 'static' scanner in form of the html_y.cpp and html_y.h files without adding the gnerator itself. Once you have installed Flex and Bison you need to change the two command script files bison_run.cmd and felx_run.cmd in the TATunnelClient project root folder: Let the variable FLEX_AND_BISON_FOLDER in the header of each file point to the folder where the binaries flex.exe and bison.exe reside. If you are using the GNU packages for both tools then their installers should have copied both tools into a shared folder. As long as you don't need to/want to change the HTML scanner/parser used to analyze a UPnP entity's info packets option 1) will be the best choice. 4. Compiling the x64 (AMD64) version of the TATunnel programs ---------------------------------------------------------- The following instructions assume that you try to compile the 64bit version of TATunnel in an development environment before Microsoft Visual Studio 2005 (which comes with built in support for generating x64 executables). In case you wonder why I didn't have just added x64 configurations to the existing 32bit VC++ 6.0 project file: I ran into a couple of problems with 32bit version compiler and linker options that are obviously not supported anymore by the 64bit tools comming with the Windows Server 2003 SP1 platform SDK. So in order to have full control over the tool command line switches I decided to take the makefile approach for the 64bit build. 4.1 Prerequisites -------------- As mentioned above, in a pre Visual Studio 2005 enviornment you have to install the 64bit tools required to create 64bit Windows applications first. Microsoft provides those 64bit tools and C/C++ libraries in their Windows Server 2003 SP1 Software Development Kit (SDK). Don't let the term 'server' in the label of the SDK fool you: The 'server' SDK is also suitable for WindowsXP x64 (the client version of the Microsoft 64bit operating system branch). build_x64.cmd won't work correctly without having installed the SDK beforehand because it calls the SDK's script 'setenv.cmd' to switch to the 64bit versions of the development tools and libraries pathes before starting the actual build process. Before you run 'build_x64.cmd' the first time you have to edit the value assignment to the variable 'SDKPATH' in the header of the file so it points to the root folder of the platform SDK installation. 4.2 build_x64.cmd usage ------------------- Folder layout for the 64bit build: The source folders are obiously shared with the 32bit version but the intermediate files go into separate sub folders beneath the server respective client end point project root folder: Release build files go to 'Release_x64' and debug build files go to 'Debug_x64'. The '*.pdb', '*.exe' and '*.ilk' files go into a folder named 'bin', located in TATunnel's root folder. The build process will create those folders on demand if required. 'build_x64.cmd' can be called with the following options: buildall - Builds the debug and release version. debug - Builds the debug version. release - Builds the release version. cleanupall - Removes the '*.exe', '*.pdb' and '*.ilk' files from the folder 'bin' and purges the 'Debug_x64' respectively the 'Release_x64' sub folders. cleanupdebug - Removes the '*.exe', '*.pdb' and '*.ilk' files of the debug build from the 'bin' folder and purges the 'Debug_x64' sub folders. cleanuprelease - Removes the '*.exe', '*.pdb' and '*.ilk' files of the release build from the 'bin' folder and purges the 'Release_x64' sub folders. The include file dependencies policy implemented in the makefile 'makefile_x64' is quite lazy and simple: Any change in any include file will lead to a rebuild of all object files of the repective project. I wrote the x64 makefile with the idea in mind that you do your actual development in the 32bit enviornment and run the x64 makefile only to generate the 64bit binaries. 4.3 Restrictions ------------- I didn't bother with integrating the flex/bison calls in the 32bit TAtunnelClient project into the x64 makefile. So only a 'static' representation of the grammer for interacting with UPnP devices in the files 'html_y.cpp', 'html_y.h' and 'html_l.cpp' will make it into the 64bit build. In case you actually bothered with installing a 32bit version of the felx/bison environment as described in section V., chapter 3: Those three files will be updated with the current state of the grammer anyways once you built the 32bit version of the TATunnelClient project. VI. Planned changes, tests and enhancements ======================================= - Utilising auto pointer templates to simplify the code (especially Command* instance handling). - Add the possibilty to launch TA as a sub process of the tunnel client endpoint program. This would allow to reconize additional shutdown scenarios simply by adding the sub proces handle to the appropriate event arrays.