GeyserMC / MCProtocolLib

A library for communication with a Minecraft client/server.
MIT License
728 stars 202 forks source link

Not loading SRV Records #85

Closed phase closed 9 years ago

phase commented 9 years ago

Whilst trying to run your example code, the program just stalled. I added printlns at various locations, only to find nothing was getting past client.getSession().connect(). I put in the correct values for the variables at the top, but I was unable to get the code working. Here's the source code, but it's remade in Kotlin (a Java version did the same thing).

Lukario45 commented 9 years ago

Is it possible that your host may be the issue? Try setting it to localhost or whatever your computers internal IP address is. For my software i tell the JVM to get the address but just typing your internal address should work

phase commented 9 years ago

But if I only use my internal address, then it's useless. I've tried it with many different servers with the same result.

Lukario45 commented 9 years ago

When hosting a server you must use your computers internal ip address and you port forward a port through your router/modem. The host option is referring to that IP. You can't set that to a host that your computer does not have. Did you port forward with those other servers? After assigning your internal ip users must connect through your external ip, which can be found on sites like ipchicken, and your port. You can then redirect a domain or subdomain to your external IP address. If you have multiple routers connected to each other (maybe wired to wireless etc) then I think you need to port forward on both routers but I am not sure.

On Apr 13, 2015, at 2:56 PM, phase notifications@github.com wrote:

But if I only use my internal address, then it's useless. I've tried it with many different servers with the same result.

— Reply to this email directly or view it on GitHub.

Johni0702 commented 9 years ago

If I recall correctly I've looked into this a week ago and it seems to be caused by some internal not handling Proxy.NO_PROXY correctly (it might even be caused by proxies in general; haven't tested that). Somewhere a UnknownHostException (or a similar exception) was thrown, silently caught, terminating the netty thread and leaving your main thread waiting for it indefinitely.

Using the TcpSessionFactory constructor without the proxy argument seemed to work as expected.

I haven't looked into it any further so I cannot tell where the actual problem lies nor how to fix it.

phase commented 9 years ago

@Lukario45 I'm not hosting a server, I'm making a client.

@Johni0702 Awesome, I'll check that out later.

phase commented 9 years ago

@Johni0702 Putting in no arguments didn't seem to fix the problem, it's still stalling.

Johni0702 commented 9 years ago

Ok, I've used the debugger once again. This is the exception swallowed somewhere in the code (using the java version of your code).

Taking a closer look it turns out that mc.openredstone.org uses SRV records to provide _minecraft at mort.openredstone.org:25569. There is no A record for mc.openredstone.org itself which probably caused this exception to be thrown.

Using the resolved address for the hostname and port resulted in the client being disconnected by the server: "Disconnected: Login failed: Authentication service unavailable." but I assume that's a server problem as I also tried to connect to a local (Glowstone) server which worked completely as expected.

So from here I see two options:

Either way there is still the issue of the exception being swallowed which has to be fixed in PacketLib. I suspect you could get this particular exception from the channel future here and would have to call the exceptionCaught method manually (though I haven't look into that) or maybe even rethow it.

Johni0702 commented 9 years ago

@Steveice10 Yes they did. The exception is now printed to the console as expected. Thanks!

Edit: And it no longer causes stalling.

Johni0702 commented 9 years ago

I'm actually not sure whether Java has built-in SRV record support. Either way the program would have to tell the service name to Java at some point (which I didn't find, so I assumed it isn't supported).

Feel free to correct me, I haven't made use of SRV records from anything other than python so I might have missed something.

Johni0702 commented 9 years ago

Ok, I've searched the decompiled minecraft source code and I believe I have found where minecraft looks up the SRV records. Searching for strings such as "srv" or "_minecraft" produced no results. However searching for the default port (which minecraft must append to the domain name at some point) was successful. (class bdd in minecraft 1.8.4) The decompiler I've been using (JD) failed to decompile one of the methods in that class and only dumped the bytecode of that method. Therefore it didn't resolve the string literals which caused all my searches to fail.

Minecraft forge with snapshot_nodoc_20141130 mcp mappings (and the IntelliJ decompiler) is able to decompile the method correctly. The corresponding class is net.minecraft.client.multiplayer.ServerAddress and the method used to resolve SRV records approximately looks like this:

try {
            Class.forName("com.sun.jndi.dns.DnsContextFactory");
            Hashtable<String, String> config = new Hashtable<>();
            config.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
            config.put("java.naming.provider.url", "dns:");
            config.put("com.sun.jndi.dns.timeout.retries", "1");
            String[] result = new InitialDirContext(config).getAttributes("_minecraft._tcp." + serverAddress, new String[]{"SRV"}).get("srv").get().toString().split(" ", 4);
            return new String[]{result[3], result[2]};
        } catch (Throwable t) {
            return new String[]{serverAddress, Integer.toString(25565)};
        }
phase commented 9 years ago

MCProtocolLib definitely isn't loading SRV Records for Client.