Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wsmc/Java] HTTP server returns 'Not implemented' on non-localhost hostnames #30

Closed
deathcap opened this issue Feb 8, 2016 · 9 comments
Assignees
Labels

Comments

@deathcap
Copy link
Owner

deathcap commented Feb 8, 2016

http://localhost:24444/ - ok
http://127.0.0.1:24444/ - Not implemented
http://anythingelse:24444/ - Not implemented

voxel-clientmc $ curl -v 'http://127.0.0.1:24444/'
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 24444 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:24444
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Mon, 08 Feb 2016 10:00:09 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
* Connection #0 to host 127.0.0.1 left intact
Not implemented

Non-localhost hosts are very important so that the service can be reachable externally

@deathcap
Copy link
Owner Author

deathcap commented Feb 9, 2016

Figured this was caused by the Host header, but seems to be binding to only IPv6 not IPv4(?!):

wsmc $ perl -e'print "GET / HTTP/1.0\r\n\r\n"'|nc -vv localhost 24444
found 0 associations
found 1 connections:
     1: flags=82<CONNECTED,PREFERRED>
    outif lo0
    src ::1 port 49606
    dst ::1 port 24444
    rank info not available
    TCP aux info available

Connection to localhost port 24444 [tcp/*] succeeded!
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 633

<!DOCTYPE HTML>
<html>
<head>
<title>voxel-clientmc</title>
<style>
body {
    background-color: lightgray;
}
</style>
</head>
<body>
<a href="https://github.com/voxel/voxel-clientmc"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://camo.githubusercontent.com/121cd7cbdc3e4855075ea8b558508b91ac463ac2/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f677265656e5f3030373230302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_green_007200.png"></a>
<script src="bundle.js"></script>
</body>
</html>
wsmc $ perl -e'print "GET / HTTP/1.0\r\n\r\n"'|nc -vv 127.0.0.1 24444
found 0 associations
found 1 connections:
     1: flags=82<CONNECTED,PREFERRED>
    outif lo0
    src 127.0.0.1 port 49607
    dst 127.0.0.1 port 24444
    rank info not available
    TCP aux info available

Connection to 127.0.0.1 port 24444 [tcp/*] succeeded!
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Tue, 09 Feb 2016 09:10:43 GMT
Connection: close

Not implementedwsmc $ 

passing to ServerBootstrap bind, "0.0.0.0" wsAddress by default:

            Channel channel = bootstrap.bind(this.wsAddress, this.wsPort)

@deathcap
Copy link
Owner Author

deathcap commented Feb 9, 2016

bind(SocketAddress) : ChannelFuture
bind(int) : ChannelFuture
bind(InetAddress, int) : ChannelFuture
bind(String, int) : ChannelFuture

all call into InetSocketAddress() constructor: http://docs.oracle.com/javase/7/docs/api/java/net/InetSocketAddress.html - "A null address will assign the wildcard address."

Testing this:

            ChannelFuture channelFuture;
            if (this.wsAddress == null || this.wsAddress.equals("0.0.0.0") || this.wsAddress.equals("")) {
                channelFuture = bootstrap.bind(this.wsPort);
            } else {
                channelFuture = bootstrap.bind(this.wsAddress, this.wsPort);
            }

but no difference. Doesn't seem to be a problem in binding but in handling?
netty/netty#4770?

@deathcap deathcap self-assigned this Feb 9, 2016
@deathcap
Copy link
Owner Author

ServerHandler pipeline is:

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast("codec-http", new HttpServerCodec());
        pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
        pipeline.addLast("handler", new HTTPHandler(this.webThread.wsPort));
        pipeline.addLast("websocket", new WebSocketServerProtocolHandler("/server"));
        pipeline.addLast("websocket-handler", new WebSocketHandler(webThread, this.mcAddress, this.mcPort, this.users, this.filter, this.verbose));
    }

first my code runs in HTTPHandler, but none of the `@Override'en methods in HTTPHandler are called when accessing over IPv4 (ok over IPv6).

    protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest msg)
            throws Exception {
        System.out.println("HTTPHANDLER MESSAGERECEIVED");

    private static void copyStream(InputStream in, OutputStream out) throws IOException {
        System.out.println("HTTPHANDLER COPYSTREAM");

    public void httpRequest(ChannelHandlerContext context, FullHttpRequest request) throws IOException {
        System.out.println("HTTPHANDLER HTTPREQUEST");

    public void sendHttpResponse(ChannelHandlerContext context, FullHttpRequest request, FullHttpResponse response) {
        System.out.println("HTTPHANDLER SENDHTTPRESPONSE");

need to find out where and what is returning the "Not implemented" response before I get it

@deathcap deathcap reopened this Feb 10, 2016
@deathcap
Copy link
Owner Author

https://github.com/netty/netty/search?utf8=✓&q=%22Not+implemented%22 shows there are "501 Not Implemented" (notice capital "I") HttpResponseStatus.NOT_IMPLEMENTED responses, but this is a HTTP/1.1 200 OK with body "Not implemented"

@deathcap
Copy link
Owner Author

--- a/src/main/java/deathcap/wsmc/web/WebThread.java
+++ b/src/main/java/deathcap/wsmc/web/WebThread.java
@@ -27,6 +27,7 @@ import io.netty.channel.group.ChannelGroup;
 import io.netty.channel.group.DefaultChannelGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.util.NetUtil;
 import io.netty.util.ResourceLeakDetector;
 import io.netty.util.concurrent.GlobalEventExecutor;

@@ -72,7 +73,7 @@ public class WebThread extends Thread {
             SocketAddress socketAddress;

             if (this.wsAddress == null || this.wsAddress.equals("")) {
-                socketAddress = new InetSocketAddress((InetAddress) null, this.wsPort);
+                socketAddress = new InetSocketAddress(NetUtil.LOCALHOST4, this.wsPort);
             } else {
                 socketAddress = new InetSocketAddress(this.wsAddress, this.wsPort);
             }

Using NetUtil.LOCALHOST4 (per netty/netty#4770, which was "Cherry-picked into 4.0 (52ba4f4) and 4.1 (3616d9e)" in Netty 13 days ago) correctly allows accessing the server over IPv4 at these URLs: http://127.0.0.1:24444/#testuser:VXVbHahf http://localhost:24444/ http://0.0.0.0:24444/ - but not my local (RFC1918) IP, nor the IPv6 local http://[::1]:24444/ nor the IPv6 global address. What I'm looking for is not a localhost IPv4 but "wildcard IPv4" (and/or wildcard IPv4+IPv6)

@deathcap
Copy link
Owner Author

+                    socketAddress = new InetSocketAddress(Inet4Address.getLocalHost(), this.wsPort);

allows using my IPv4 RFC1918 local network address, but not localhost, 127.0.0.1, 0.0.0.0, ::1, anything else. Am I really going to have to listen multiple servers for each interface?

@deathcap
Copy link
Owner Author

Turns out "Not implemented" is from wsmc/JavaScript (wsmc.js). Related: #31 [Broken] Update all dependencies (ws/websocket-stream) 🌴

@deathcap
Copy link
Owner Author

Always something simple... (InetAddress) null = wildcard works correctly for both IPv4 and IPv6, lo0 and en1. Why I was seeing different behavior is that wsmc.js was erroneously running (user error, nonetheless non-informative error message) but only bound to IPv4 (bug/missing feature?), and wsmc.jar tried to bind everywhere but silently failed on IPv4 since the port was occupied so it only bound to IPv6 (missing error message?).

deathcap added a commit that referenced this issue Feb 10, 2016
Doesn't fix #30 either, but seems
like a good idea
deathcap added a commit that referenced this issue Feb 10, 2016
@deathcap
Copy link
Owner Author

Fixed wsmc.js to bind to '' instead of '0.0.0.0' by default (IPv4+IPv6), now wsmc.jar gives a more informative binding error message:

[23:49:41 WARN]: java.net.BindException: Address already in use
[23:49:41 INFO]: Cactus Growth Modifier: 100%
[23:49:41 WARN]:    at sun.nio.ch.Net.bind0(Native Method)
[23:49:41 WARN]:    at sun.nio.ch.Net.bind(Net.java:344)
[23:49:41 WARN]:    at sun.nio.ch.Net.bind(Net.java:336)
[23:49:41 INFO]: Cane Growth Modifier: 100%
[23:49:41 WARN]:    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:199)
[23:49:41 WARN]:    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:104)
[23:49:41 INFO]: Melon Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:464)
[23:49:41 INFO]: Mushroom Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.DefaultChannelPipeline$HeadHandler.bind(DefaultChannelPipeline.java:1032)
[23:49:41 INFO]: Pumpkin Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.ChannelHandlerInvokerUtil.invokeBindNow(ChannelHandlerInvokerUtil.java:99)
[23:49:41 INFO]: Sapling Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.DefaultChannelHandlerInvoker.invokeBind(DefaultChannelHandlerInvoker.java:196)
[23:49:41 INFO]: Wheat Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:366)
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:898)
[23:49:41 INFO]: NetherWart Growth Modifier: 100%
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.AbstractChannel.bind(AbstractChannel.java:189)
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:309)
[23:49:41 INFO]: Entity Activation Range: An 32 / Mo 32 / Mi 16
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:318)
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353)
[23:49:41 WARN]:    at deathcap.wsmc.lib.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:794)
[23:49:41 INFO]: Entity Tracking Range: Pl 48 / An 48 / Mo 48 / Mi 32 / Other 64
[23:49:41 WARN]:    at java.lang.Thread.run(Thread.java:724)
[23:49:41 INFO]: Hopper Transfer: 8 Hopper Check: 8 Hopper Amount: 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant