hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
10.98k stars 2.14k forks source link

Tunnel adhoc traffic through a single port - possible? #7268

Open hrydgard opened 9 years ago

hrydgard commented 9 years ago

Currently, to play adhoc multiplayer in many games you have to forward ports and stuff, and follow complicated guides that people have written in the forum. It would be good to simplify this. Using the original ports is of course necessary if you want to play against a real PSP, but having the option to avoid much of the hassle would be nice.

Also I think there's more in the networking setup that can be automated, but I haven't really looked into it much yet.

anr2me commented 9 years ago

It's possible but a bit complicated to tunnels all the ports using a single port, it's much easier to map the port to a certain range of ports and send these port information (original port & it's replacement) to other players through AdhocServer. Current AdhocServer only broadcast the IP address without port information.

unknownbrackets commented 9 years ago

Well, mapping to a fixed port would make it significantly easier to:

  1. Simulate separate IPs for a single remote device. This has limited usefulness and would require mapping ports to virtualized IP addresses, though. The primary use case (local) is covered by #7276 already.
  2. Manually open ports. If the game doesn't pick, we could just have a port you had to open rather than dealing with VPNs or etc. A range is hard in some routers, which is why a single one has benefits. (note that an alternative might be using UPnP or something, where supported, and I guess there are server proxies out there to arbitrate otherwise.)

Anyway, I will throw out there that if we really want network to work well in PPSSPP, then besides testing, we also need some sort of debugger for it. sceNet shouldn't be using the raw apis either way, it should go through some interface that can allow various simulation or mocking for testing, at least imho.

-[Unknown]

sum2012 commented 9 years ago

Some games use sceNetUpnp to map port.

ernestbone commented 9 years ago

can this tunneling all communication through one port be done using an external app?

adenovan commented 8 years ago

if this upnp implemented can 2 client connect to the server using one public ip ? AFAIK only 1 client can use the public ip for playing in coldbird.net , thats why a vpn is still usable to use because its assign ip to the client. or maybe ppsspp want to implement builtin vpn client using something like openvpn ?

anr2me commented 8 years ago

@adenovan Not with upnp alone, but when tunneled to a single port Yes it's possible, by assigning each players a different port (that need to be forwarded) Adhoc Server will need to be modified also to store assigned port information for each player (and the protocol each player used), while on client side packet data from/to the game will need to be enveloped with info like assigned port (so receiver will be able to know from which player it came from) and the actual port the game supposed to use before/after sending/receiving (which can be mapped to any random port to communicate with the tunneler locally), and probably also need to have protocol info so the tunneler will know it need to pass the data using udp/tcp to the actual port, while the tunneler assigned single port can always use tcp for stability or udp for performance.

adenovan commented 7 years ago

im planning to work on this feature and solve some problem with nat by relaying the adhoc traffic through public server. there is several technique to make P2P connection over the internet described here http://www.brynosaurus.com/pub/net/p2pnat/ . the safest way is relay it. its doesn't need to much bandwith because im already analyze the packet on the server when tunneled and relayed over openvpn.

@ANR2ME the part is im confused is simulate the tunneler to communicate locally with the actual port information (PTP Listen and PDP Recv on actual port used by the game). there is many socket opened when the game tried to connect to other peer. example on MHFU (port 20000, 20001, 20004 is used). if we use the loopback address from the tunneler to communitcate with local port how can we simulate the connection from outside ip not the local one?

im trying tunnel the connection to adhoc server on port 27312 but it make more buggy behavior because its increase the latency when user need an peer information immediately. it will affect the entire adhoc network matchmaking system if we tunnel it on TCP 27312 used by adhoc server. do we really need to listen on different port as a tunneler relay on the server? the functon need to be tunneled look like only PTPSEND and PDPSEND because its the most often HLE function called by the game.

@Hydroque did you want to join implement this feature? so we can stop using VPN to play

anr2me commented 7 years ago

Actually instead of PTPSEND/PDPSEND, HLE functions that need to be modified is mostlikely the one that connect/bind the socket (including the one that deals with adhoc server), instead of connecting directly to other peer/player it connects to the tunneler socket and pass any data being received/sent locally (you'll need to wrap the data to add actual socket info so the tunneler knows which game socket that data belong to)

I think you'll need 2 tunneler sockets, one for TCP and one for UDP for performance reason, but tunneling UDP through TCP might be more stable for long distance (internet) communication. And i don't recommend using the same port with adhoc server (27312) for tunneling/relaying game data (for compatibility reason) And adhoc server might need to be modified to contains tunneler sockets info (so each tunneler will know the other player's tunneler), so players using same IP (shared internet) as long they use different tunneler port can play together.

Direct Tunneling:

game sockets <--> local tunneler socket(s) [Player1] <- LAN/WAN -> [Player2] local tunneler socket(s) <--> game sockets

Relayed Tunneling:

game sockets <--> local tunneler socket(s) [Player1] <- Relay Server [WAN] -> [Player2] local tunneler socket(s) <--> game sockets *Relay server to solves issue on shared internet where users unable to forward any port to WAN (ie. 3G/4G connection)

adenovan commented 7 years ago

thanks for the reply @ANR2ME looks like its clear enough for me to started working on this feature.

anr2me commented 7 years ago

Btw, if later you need to modify adhoc server to be compatible with tunneling, you may want to keep the old functionality for compatibility with PSP/other psp emulator.

You can create a different way (ie. different packet format) to connect to adhoc server when using tunneler, also have a separate group with normal players playing the same game, so they won't mixed up.

adenovan commented 7 years ago

yeah that is on my plan already. the old functionality is better on lan network and it will not have much issues in the futher when ipv6 is globally implemented and many isp support it.

most of my work will be modified the adhocserver and bind a tunneler relay port for the tunneler wrapper used by the client. after much digging on the source code and coldbird forum looks like we can wrap most of the game packet because its transported using mac address on the original infrastructure. hydroque is still digging on how its work on mac layer.

the part need to be done first its the tunneler wrapper locally because its the hardest part. i can simulate it on lan first as an experiment and make sure not breaking the game compability.

adenovan commented 7 years ago

i can wrap the PDP data send by the game on scenetadhoc to the udp tunneler but im stucked on dynamic struct allocation memory in the tunneler side https://github.com/adenovan/ppsspp/commit/03a9c31c99386a6b74a9a89c87b67da34b69be91#diff-e0babd00f2cd10a9339f283471194e5fR2231

any ideas how to allocate it?

screenshot 222

tilkinsc commented 7 years ago

I need to read this thread 5 times before I can reply. I am trying to wrap my head around the specific goals creating a tunneler will solve and why we need to modify the system when we can just create a new virtual network interface, like hamachi, tungle, and evolve does. That way the system can map IPs - which is kinda what the UPnP would help bring to the table. I am not sure what you guys are getting at with the 'need a VPN to play'. I am still trying to understand what was wrote.

// okay done //

From what hrydgard said, There should be a total of 1 port open, which is for the lobby. The lobby then delegates the IPs to others to everyone so they can connect and operate. This is easy to do with a tunneler engine such as evolve, hamachi, and tungle. They use a virtual network interface to do such that - making port forwarding to all but one port really necessary. It also allows the tunneler to handle IP connections. The range of 128.0.0.0-128.255.255.255 would talk to the tunneler to transmit the data, for example. This does involve an overhead, which is bad for gaming. It is also cancer to write. A little play demonstrating: 'I am 128.0.0.1 and I am the matchmaker. Hello 128.0.0.2! Hello 128.0.0.3! You guys are ready to start the game? Hello, 128.0.0.2 and 128.0.0.3, I am 129.0.0.1 and I will be the data transmitter for you guys today so you don't have to open ports.' The variant of coldbird adhoc, that the person I was talking to on evolve, relied on such a UPnP methodology. This way multiple people on a network could play together.

However, I think what unknownbrackets came up with in the following post was a really good suggestion. Just open up 5 ports - 1 for matchmaking if you are the host and up to 4 players all incrementing. Have the matchmaking force the people to claim a unique port so that 192.168.0.1:2001 and 192.168.0.1:2001 doesn't happen as well as 192.168.0.1:2001 and 192.168.0.2:2001 doesn't happen - as the player would probably receive the wrong data from the wrong player. This is actually a widely support thing in router configuration interfaces to say 'hey lets port forward this port range'.

ernestbone brought up a good point about using one, external app to handle everything. Matchmaking servers are a thing and this is definitely an example of one, highlevel emulation (This is a PSP hardware thing). If a matchmaking server would be used, it would be like gamespy. Gamespy used UPnP for connections to people, however, the people only had to port forward to gamespy's server if needbe and was much more than just a matchmaking service - as it was integrated into the games. Currently, this is just built into PPSSPP as there is no need to have an external server for such small parties. Per gamespy, it would be an improvement only if the matchmaking server would also show different games to be able to connect to (oh hey someone wants to play twisted metal), which would definitely be a neat feature, but for as small as it is now - we know what game we want to connect to and the IP of the people.

From what adenovan said after ARN2ME taught them what UPnP was about, he brought up trying to tackle it. Evidently there is using a loopback address in use? How is that done and why? I am confused on this.

I agree with ARN2ME bringing up the fact that the only thing needing modifying are the connection methods. I seriously think that all that should happen is X amount of open ports (1 for matchmaking), Y of them that the players use to connect to each other and PPSSPP to listen to these ports to delegate them to the program. It is a high level hack - and there is no reason to actually open specific ports that the game requests. If there is an issue we can probably find a way to work around this. A program can decide what ports it wants to open. If you want to not use this method, disable it in the settings menu - which is a quick workaround for games that might break for some reason.

Correct me on anything please. I am an insane programmer.

//

For me discovering how PSP interface with each-other over AD HOC, I haven't really been discovering too much let alone working on it. I work and have been working with OS development so I can learn more about kernel-mode drivers, which could bring me some knowledge on how exactly I could interface two devices together seemlessly. For example, this link states something that seems like it would be relevant: http://blog.atollic.com/device-driver-development-the-ultimate-guide-for-embedded-system-developers

The PSP is an embedded system with a network chip that has drivers in the kernel, which interface with the API exposed. What the kernel does to interface with the chip is beyond anyone - it is hidden like a closed source video driver. What I need to know is how two devices establish IPs with each other - as it is definitely a valid network waiting to connect to each other. My first thought is that the PSP broadcasts something that another PSP will catch and handle - with respect to if the AD HOC network is already booted. I used microsoft's network capture tool thingy to just prove that but I have not deciphered the data collected to see if there is any sort of 'ping and wait for a reply to interface to agree on a ip' or 'say hey this is my ip and you should remember me until you can't find me'. There are so many unknowns that I can't quite put it in brackets.

MrColdbird commented 6 years ago

@hrydgard Here's the summary of my findings and the reason I implemented netplay / adhoc tunneling the way I did on Prometheus:

  1. The initial version of Prometheus, aka. the coldbird.net Adhoc Tunnel Service for PSP, was actually an indirect implementation. Which means the very first internal build of the software I programmed is exactly what you are asking for here.

It ran all of its traffic through the adhoc tunnel server, and delivery of the data was dealt with by the server. Also, due to running on port 443, the initial revision of the software was easily able to circumvent any firewall or router / nat limitations... however...

  1. The introduced latency killed game connections. And even after manually patching a few game timeout values on God Eater Burst (my go-to test game at the time while implementing the code), it caused unbelievable lag-spikes / game engine frame interpolation issues.

Long story short, PSP games on adhoc-mode expect low-latency data transmission and...

  1. Back in the day, before PPSSPP was a thing, I had to work with real hardware, thus I was limited by what that hardware could do. In the case of the Playstation Portable this meant I had to deal with its crappy wireless adapter and Sony's horrible reimplementation of the TCP Berkeley network stack, which brought ridiculous latency issues to the table simply by using TCP.

Which means, the choices I've made in designing the system to be this way were all related to the limitations of the hardware and the physical inability to reliably use TCP because of a bad / bugged TCP stack and a dodgy wireless adapter.

UDP was the only way to go as that stack was, unlike the TCP one, working reliably and on top of that had less overhead to deal with, allowing for faster transmission of data.

Now, to the actually interesting part... Yes, it is possible on PC / Android / anything else that can run PPSSPP, to actually implement what you are asking, however, real hardware compatiblity / cross play will get lost in the process. Android and PC actually have reliable network stacks, which means transmission via TCP, while adding overhead and latency, should still be fast enough to get the data where it has to be in time.

While I would love to implement this myself, as PSP netplay is one of my lovechilds, I know for a fact that I won't be having enough time to actually do this.

However, should someone else decide to implement this, and add the new protocol to the pspnet_adhocctl_server project of mine as a separately listening port / protocol, I'll gladly host a matching master server on coldbird.net.

adenovan commented 6 years ago

@MrColdbird the interesting part is that adhoc tunnel server running on port 443 on the initial version, looks like the server code not included on initial commit, i just finished reading your aemu source on the first commit some client code is there but there is no server code at all , actually this issues is want to reimplement that C2S infrastructure rather than using vpn to transfer all the game adhoc traffic that user make in the forum (relay that PDP and PTP traffic).

can i look at that server tunnel implementation? working from there is better than working from scratch ( i make a pull request to tunnel that traffic which is not good enough because its add an extra packet header to tunnel the traffic). now i am stuck on simulate that PTP connect and listen function when relayed.

if that initial version working on PSP even with spiked lag , i think there is no problem on reimplement that on PPSSPP we can just split the adhoc module into 2 version by option the first one is adhoc mode (cross play with public ip and lan use) , and the second one is C2S infrastructure mode (ppsspp only) and tunnel that traffic into the public server. if that server is already implemented with UDP stack , UDP Hole punching might can help decrease the latency and see if it works or not use an UDP hole punching technique to transfer the traffic. this is very interesting to work on i up to works on it when having spare time.

even when the adhoc traffic is relayed by vpn network its still pretty damn fast with today internet latency (4G or Fiber connection). most common problem to playing adhoc over internet is that nat restriction with people behind router or user playing with android mobile data. because how hard to setup the current implementation many user just give up to play over internet.

this is a relayed traffic dump using TCP transmission by using vpn software , image

it still pretty damn fast and some games that have non blocking flag on data transmission works well ( Monster Hunter , GEB , GE2 , PSP2) , games that have blocking flag like TEKKEN 6 , METAL SLUG is very slow when relayed but still playable. blocking game may need a latency below 50ms which is standart for wifi that is my finding.

on initial vpn configuration i tunnel it with UDP transmission, yeah its faster but cause a very bad teleportation on some games. the PTP traffic asked by the game not arrived into the destination and potentiallly cause matching function to crash this weird behavior can easily produced on PSP2 games.

MrColdbird commented 6 years ago

I'm sorry to say that I no longer possess copies of the early revisions, as I've discarded them the instant I realized that indirect tunneling wasn't an option on original hardware.

So there really is no other way than re-implementing it from scratch.

adenovan commented 6 years ago

ah ok no problem then i will implement it for scratch again. can you point me in the right direction relaying that traffic , i just need the general overview how many socket is used by client to connect to that adhoc tunneling server. like the data dumped above the game actually create many socket for just a single game on ptp create and pdp create . did the initial implementation just using single socket per one client and combined with the current adhocctlserver. or it run two different socket one for ctl server , and one or many socket to the adhoc tunneling server?

on my first attempt to relay that traffic i use the current adhocctl protocol on port 27312, but it makes more buggy behavior because the peer info needed on emu not arrived on time. the socket and thread become more busy processing the game data, that instant tcp connection and should be never fail needed by the game becoming so slow because more job added to them. its have some issues on chat also. if many user flooding the chat the process of friendfinder thread and the main job of that adhocctl server become so slow that cause many games to break even crash or not seeing the peer in time.

so i refactor your code, write it on C++ wrap them in class to be used for multi adhocctl server. and then run a chat server separately on different socket and thread. the issues is resolved , user can flood the chat without breaking the friend finding process. i implement the global chat and simulate a group chat on that chat server also.

the main purpose i wrap it on class is to do a multithreaded ctl server because one single instance of ctl server is just not enough to cover the needed game room for online play on some games. we should make it like adhoc party on PS3. the other reason is make a chat server for easy meetup on top of the ctl server logic without interrupting the adhocctl process, the chat server run independently and be able to chat cross ctlserver and cross games. but it have a virtual group room also when entering the adhoc group , the rewrite of that ctlserver and chat server is done just need some cleanup, the source code is available on my github repository and my ppsspp branch.

now i just need to implement a relay server to relay that game traffic on top adhocctl logic and run separately from the ctlserver to be able eliminate the needed of vpn used for playing. its very hard to find documentation on what is that adhoc module do in the real hardware. so tunneling the traffic is some hard task for me. im just a beginner at hacking and reverse engineering thing to observe PSP API on real hardware never touched that psp test.py but i guess its really needed to test some function on the adhocmodule and decide what is the best way to relay it, i have 2 psp for experimenting.

my go to test server and community to help me debugging and improving the server code is available under amultios.net , we host the server on asia region to minimize latency to play. we cannot play to US server from asia its too far and the latency is very bad. its a very bad adhoc experience 400ms ++ to US server average. if all of my job is done its up to the ppsspp owner want to merge it or not.. i just want to simplify the adhoc process over internet and have some friend to play when want to have fun. even the adhoc games is almost 10 years old i never get bored playing on it , its my loves childs also. i just need to make that adhoc experience like many games online today easy to play , easy to setup , easy to connect , easy to communicate..

basicly what i want to develop is simulate the psp adhoc to online gaming server infrastructure. and one thing really hate when playing adhoc is user cheating on multiplayer. that cheat is eliminate the purpose of multiplayer.. like one hit kill cheat its really destroying the community, any active cheat while playing is killing the fun of adhoc multiplayer. to cover the community from suffering from cheater. i already implement some of authentication logic on entering adhoc mode, and the chat server, it will be managed with a game master that have instant ban command on chat protocol if found any cheater on game or some user report it.

JacobMrox commented 6 years ago

@adenovan this is a bad idea if you're going to implement a function which auto bans players with cheats turned on, because many of us use cheats to enable 30/60 fps hacks/cheats and fixes, so scratch that.

How about actually making adhoc pro plugin more stable and adding a upnp option instead of all that hassle people have to go through? and I'm still waiting for infrastructure support (Not Adhoc to infrastructure, I mean real infrastructure... perhaps I will just do it myself one day when I know how).

MrColdbird commented 6 years ago

Can't talk for adenovan here but the reason I focused on adhoc tunneling in my days of active development was that it could support a wider range of games than infrastructure and because it was p2p based, meaning it would work way beyond the official lifetime of the games' online servers, essentially doubling as a way to archive the multiplayer aspects of games.

My upnp plugin for PSP actually is based on miniupnc, which works great for this.

So I definitely vouch for having that one implemented in PPSSPP. It's easy to port and does what it has to do, however it shouldn't be treated as a replacement for this ticket, as it won't allow for multiple players behind a single external IP address.

tilkinsc commented 6 years ago

We converted ad hoc to infrastructure with the cfw plug-in, but could we do the reverse for ppsspp and fake ad hoc for infrastructure. I think this topic goes back to my gigantic post as well. I wonder the packet similarity. ColdBird has been talking about this at #9882

JacobMrox commented 6 years ago

Infrastructure on PSP just connects to an access point and then its just connected to the internet, everything else depends on what the game is trying to access, now if this was added it would make my job much easier in debugging the infrastructure mode in MPO+ since I've come so far, but I've hit a snag which is ssl, on PC I could patch this easily if only we could access infrastructure.

As for ports, we really need a UPNP option in networking, if I knew how I would've added it myself...

adenovan commented 5 years ago

lately i have been experimenting alot on relay server, one fixed port on server can relay every game traffic depend on how fast the packet is processed (Asynchronous Socket is needed on relay side) , it can be relayed through single external ip port for some games. but it will break game that connect to itself like Phantasy Star 2 Portable, Tekken 6 , Monster Hunter game is fine on relay mode

anr2me commented 5 years ago

Are you also relaying local traffic that connects to itself through internet? You shouldn't do that.

adenovan commented 5 years ago

im relaying all opened socket into server , there is no listening socket , every listen and accept connect to the server side and the handshake is simulated on the server side. the problem if we did not relay that we did not have listen socket on the ptpindex because all ptp socket is not a listen socket on relay mode.

the data that connect to itself is trasmited to relay successfully and send back to user successfully, the problem is the game expecting that data to arrive super fast when the relay is still processing the data. event at local connection the timeout still occured when in relay mode.

anr2me commented 5 years ago

Well adhoc games was designed to works with super low latency, so some games may implement a short timeout while looping to check non-blocking sockets (for blocking sockets we can just tamper the timeout value given as parameters, since the game may not check the time on blocking sockets), these timeout values may need to be patched. And giving a higher timeout or high latency communication may affect the game performance.

adenovan commented 5 years ago

yeah phantasy star portable set the timeout on local socket 0ms , it will always get disconnected if we relay that loopback , even if we did not relay it when playing on local Router WIfi still can trigger the timeout. well if i have more spare time i can try to simulate that loopback connection by checking the local mac an ptp open destination. the hard part is on ptp accept because we must accept local connection and relay connection at once without knowing how to differ the accept call by mac address.

have 2 ptpstat local and relay maybe can help , but not sure if the game can proceed with a relayed connection. at least some game has been proven can be relayed without problem.

tilkinsc commented 5 years ago

If a timeout occurs do these programs not attempt to reconnect?

adenovan commented 5 years ago

Its try to reconnect , the game also spamming ptp accept (tcp accept) call , every 1 ms when succesfully connected to lobby. The local loopback connect only happen once on that short time we must make sure the connect hit the listen function or the game will not synchronize.

On later version i can sucessfully relay that handshake on local network. But the socket that connect to itself also relayed.

Its not suitable for internet play i guess. Need very fast connection for that to work

anr2me commented 5 years ago

LOL even a very fast connection still won't be getting 0ms, only localhost can do that :D

Anyway, if the game is using 0 as timeout parameter, it's probably a non-blocking sockets which doesn't use the socket's builtin timeout implementation.

And yes, most games will attempts to retry for a few times before giving up, but it's no use because high possibility all of their retries ended getting timeout due to the latencty is larger than the game expected it. The only way to solve this is by patching the timeout (like a cheat code) to gives higher value on each games that have this issue. Even if raising the timeout might worked you will probably seeing a staggering/lagging UI, due to most of the time games are using non-blocking sockets because they need to update the UI while waiting for connection.

adenovan commented 5 years ago

Yep and there is a recent commit that disable connect hack to make gundam work but broke this game , the proper way to handle that we must use loopback address when open hit same local mac . Its can solve the issue