knowm / XChange

XChange is a Java library providing a streamlined API for interacting with 60+ Bitcoin and Altcoin exchanges providing a consistent interface for trading and accessing market data.
http://knowm.org/open-source/xchange/
MIT License
3.85k stars 1.94k forks source link

Binance "invalid WebSocket Extension handshake" #3907

Closed feelus closed 3 years ago

feelus commented 3 years ago

Hello,

I'm suddenly experiencing issues connecting to Binance streaming API, since 13:20 UTC today. I checked their changelog and there seem to have been some changes today to the API, see https://binance-docs.github.io/apidocs/spot/en/

It can be reproduced with this example

    StreamingExchange exchange = StreamingExchangeFactory.INSTANCE.createExchange(BinanceStreamingExchange.class);

    ProductSubscription streamSubscription = ProductSubscription.create()
    .addOrderbook(CurrencyPair.BTC_EUR)
    .build();

    exchange.connect(streamSubscription).blockingAwait();

    Disposable subscription1 = exchange.getStreamingMarketDataService()
        .getOrderBook(CurrencyPair.BTC_EUR)
        .subscribe(
            book -> System.out.println(book),
            throwable -> System.out.println(throwable));

The error I'm getting is

Exception in thread "main" io.netty.handler.codec.CodecException: invalid WebSocket Extension handshake for "permessage-deflate; server_no_context_takeover; client_max_window_bits=15"
        at io.netty.handler.codec.http.websocketx.extensions.WebSocketClientExtensionHandler.channelRead(WebSocketClientExtensionHandler.java:110)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
        at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:832)

Could anyone help? Was there a Binance API change that introduced some incompatible changes?

ajutzeler commented 3 years ago

Hi,

I am experiencing the exact same thing.

It is relevant to mention that Binance has been suffering from major availability issues since that massive BTC surge (around 13:00 UTC today).

Could this error be the result of a maneuver from Binance as an attempt to reduce the traffic?

makarid commented 3 years ago

I am getting the same thing too.

Στις Δευ, 8 Φεβ 2021 στις 5:17 μ.μ., ο/η ajutzeler notifications@github.com έγραψε:

Hi,

I am experiencing the exact same thing.

It is relevant to mention that Binance has been suffering from major availability issues since that massive BTC surge (around 13:00 UTC today).

Could this error be the result of a maneuver from Binance as an attempt to reduce the traffic?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/knowm/XChange/issues/3907#issuecomment-775220759, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHIWQ77WMUYMCNVREPAMRGTS576AZANCNFSM4XJEVLTA .

VadimsGrusas commented 3 years ago

Same here.

ajutzeler commented 3 years ago

All the people I know of who are not currently being impacted by this gather the two following conditions:

Could anyone here confirm that it is either

to invalidate my hypothesis?

paolo-rendano commented 3 years ago

same for me. What is happening? VIP0 - not working Authenticated - not working

VadimsGrusas commented 3 years ago

VIP0 - not working. Without authorization not working. This js example works - https://github.com/binance-exchange/binance-websocket-examples

VadimsGrusas commented 3 years ago

That issue looks similar to: https://github.com/netty/netty/issues/10191 https://github.com/knowm/XChange/pull/3803

feelus commented 3 years ago

That issue looks similar to: netty/netty#10191

3803

I thought so too, I tried to fix it as it was used here https://github.com/knowm/XChange/pull/3803 but did not seem to help. I'm not a Java guy so I'm not sure if maybe I accidentally messed something up, so maybe someone else can confirm

earce commented 3 years ago

@feelus it is related to https://github.com/knowm/XChange/pull/3803, what probably happened is that Binance upgraded the websocket and changed this flag. We need to update the library to be able to properly hand-shake with the websocket, I can approve a PR if someone submits it.

earce commented 3 years ago

Also in the future Discord is better for faster engagement about ongoing issues.

feelus commented 3 years ago

Also in the future Discord is better for faster engagement about ongoing issues.

I agree, but couldn't a mention of it anywhere

earce commented 3 years ago

@feelus search for discord on this projects readme

paolo-rendano commented 3 years ago

my 10c$. just made some experiments and now it works again. What I have done: 1 - get the code from coinbase private WebSocketClientCompressionAllowClientNoContextHandler() { super( new PerMessageDeflateClientExtensionHandshaker( 6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE, true, true), new DeflateFrameClientExtensionHandshaker(false), new DeflateFrameClientExtensionHandshaker(true)); } 2 - override BinanceStreamingService: @Override protected WebSocketClientExtensionHandler getWebSocketClientExtensionHandler() { return WebSocketClientCompressionAllowClientNoContextHandler.INSTANCE; }

Look at the code at 1. I had to set both parameters to true to get it work. The second is "requestedServerNoContext" that I had to set to true.

Hope it helps, maybe this is only a workaround. I don't know what Binance changed.

feelus commented 3 years ago

@feelus search for discord on this projects readme

Oh damn, it's an image, can't find it with search. Ok!

Greekcc commented 3 years ago

my 10c$. just made some experiments and now it works again. What I have done: 1 - get the code from coinbase private WebSocketClientCompressionAllowClientNoContextHandler() { super( new PerMessageDeflateClientExtensionHandshaker( 6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE, true, true), new DeflateFrameClientExtensionHandshaker(false), new DeflateFrameClientExtensionHandshaker(true)); } 2 - override BinanceStreamingService: @override protected WebSocketClientExtensionHandler getWebSocketClientExtensionHandler() { return WebSocketClientCompressionAllowClientNoContextHandler.INSTANCE; }

Look at the code at 1. I had to set both parameters to true to get it work. The second is "requestedServerNoContext" that I had to set to true.

Hope it helps, maybe this is only a workaround. I don't know what Binance changed.

Where did you found that code? On CoinbaseProSteamingService?

paolo-rendano commented 3 years ago

my 10c$. just made some experiments and now it works again. What I have done: 1 - get the code from coinbase private WebSocketClientCompressionAllowClientNoContextHandler() { super( new PerMessageDeflateClientExtensionHandshaker( 6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE, true, true), new DeflateFrameClientExtensionHandshaker(false), new DeflateFrameClientExtensionHandshaker(true)); } 2 - override BinanceStreamingService: @override protected WebSocketClientExtensionHandler getWebSocketClientExtensionHandler() { return WebSocketClientCompressionAllowClientNoContextHandler.INSTANCE; } Look at the code at 1. I had to set both parameters to true to get it work. The second is "requestedServerNoContext" that I had to set to true. Hope it helps, maybe this is only a workaround. I don't know what Binance changed.

Where did you found that code? On CoinbaseProSteamingService?

exactly. info.bitrich.xchangestream.coinbasepro.netty.WebSocketClientCompressionAllowClientNoContextHandler

earce commented 3 years ago

You guys can probably create a new class for this

paolo-rendano commented 3 years ago

You guys can probably create a new class for this

yes, I created a new class. You can copy the Coinbase one and change the parameter to true. and then reference it in the BinanceServiceStreaming to use that.

Greekcc commented 3 years ago

Can someone make a PR, i am still trying to make it work.

paolo-rendano commented 3 years ago

Sure I can, but as I said, not clear why the "true" solves the problem. It is "magic". I don't see anything on it in Binance API changelog. Maybe also the problem will be solved by them without changing anything.

Greekcc commented 3 years ago

I have done the same thing as you did, but i still getting the same error. Maybe they have done something with Geographic location or i don't know

ajutzeler commented 3 years ago

I did exactly what @paolo-rendano suggested as well, but it did not help.

@paolo-rendano Can you try again without your fix? Maybe it now works for you all the same?

paolo-rendano commented 3 years ago

@ajutzeler sure the old code does not work, since I have it in production in amazon AJP datacenter. Just restarted and still broken there. The same error here from Italy. Now I'm building the code with my change and I'll test it also in production. I'll update you.

VadimsGrusas commented 3 years ago

my 10c$. just made some experiments and now it works again. What I have done: 1 - get the code from coinbase private WebSocketClientCompressionAllowClientNoContextHandler() { super( new PerMessageDeflateClientExtensionHandshaker( 6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE, true, true), new DeflateFrameClientExtensionHandshaker(false), new DeflateFrameClientExtensionHandshaker(true)); } 2 - override BinanceStreamingService: @override protected WebSocketClientExtensionHandler getWebSocketClientExtensionHandler() { return WebSocketClientCompressionAllowClientNoContextHandler.INSTANCE; }

Look at the code at 1. I had to set both parameters to true to get it work. The second is "requestedServerNoContext" that I had to set to true.

Hope it helps, maybe this is only a workaround. I don't know what Binance changed.

Tried it locally, thank you. that helped

paolo-rendano commented 3 years ago

Ok, I confirm. Back to working in production as well. I'll open the PR for that, but you should wait some hours for that. I'm on a different branch, so I have to take some time to do that.

paolo-rendano commented 3 years ago

I pushed the fix. who will merge that in develop?

ajutzeler commented 3 years ago

I do not want to be a killjoy, but I built everything clean from @paolo-rendano branch and I am still getting the same error.

If I am the only one in this situation, I gladly accept my fate of being such a big noob.

earce commented 3 years ago

@ajutzeler noobs are welcome :) but did you try checking out from trunk?

paolo-rendano commented 3 years ago

I do not want to be a killjoy, but I built everything clean from @paolo-rendano branch and I am still getting the same error.

If I am the only one in this situation, I gladly accept my fate of being such a big noob.

I'm sure the point is solved since just after the change everything is running fine again both in local and on aws. Just to give you some hints, the xchange project is quite large and maybe the ide sometimes makes some jokes on maven artifacts. would be better if you reload the maven project (in IntelliJ) or if you are on CLI to run mvn clean install -U to be sure you are really running the updated project. Another hint: put a debug on the line I've added in the Binance service and run in debug to check this is passing from there.

marcohc commented 3 years ago

Hi guys, this might be a bit offtopic but, is there a way cloning the project to make use of the fix in a different project avoiding to wait for the next release? thanks!

earce commented 3 years ago

The best way is using the snapshot jars as dependencies

ajutzeler commented 3 years ago

@paolo-rendano Yes, I completely removed my local maven repo before any attempt and used mvn clean install to build the project.

I checked and I am loading the correct binaries that have just been built.

Added a couple of debug lines just to be sure, and of course it does show.

Can we reasonably assume that Binance is using an heterogeneous pool of websocket servers? Which could explain why only certain user on certain market were impacted by this issue. And why I still am...

Can anyone try to reproduce it with MarketData trades on EGLD_USDT?

paolo-rendano commented 3 years ago

I’m receiving correctly EGLD_USDT (Just checked now). Anyway I tested with order book, not with trades.

Il giorno 8 feb 2021, alle ore 22:40, ajutzeler <notifications@github.com mailto:notifications@github.com > ha scritto:

@paolo-rendano Yes, I completely removed my local maven repo before any attempt and used mvn clean install to build the project.

I checked and I am loading the correct binaries that have just been built.

Added a couple of debug lines just to be sure, and of course it does show.

Can we reasonably assume that Binance is using an heterogeneous pool of websocket servers? Which could explain why only certain user on certain market were impacted by this issue. And why I still am...

Can anyone try to reproduce it with MarketData trades on EGLD_USDT?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

ajutzeler commented 3 years ago

Sorry, it is actually the UserTrade stream that crashes!

I can successfully receive market data (orderbook and trades) as well.

Please check it and tell me that you can reproduce it so I can clear my name ;)

paolo-rendano commented 3 years ago

Oh I understood the problem.  I think we have to reopen the issue since the same patch must be applied to BinanceUserDataStreamingService class.

Can you please confirm that adding these lines to that class your problem is solved?

@Override protected WebSocketClientExtensionHandler getWebSocketClientExtensionHandler() { return WebSocketClientCompressionAllowClientNoContextHandler.INSTANCE;

}

Thanks Paolo

Il giorno 8 feb 2021, alle ore 22:40, ajutzeler <notifications@github.com mailto:notifications@github.com > ha scritto:

@paolo-rendano Yes, I completely removed my local maven repo before any attempt and used mvn clean install to build the project.

I checked and I am loading the correct binaries that have just been built.

Added a couple of debug lines just to be sure, and of course it does show.

Can we reasonably assume that Binance is using an heterogeneous pool of websocket servers? Which could explain why only certain user on certain market were impacted by this issue. And why I still am...

Can anyone try to reproduce it with MarketData trades on EGLD_USDT?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

earce commented 3 years ago

If this fixes it submit another PR

paolo-rendano commented 3 years ago

Yes @ajutzeler pls do the test and give us feedback. The PR is ready to be sent.

Il giorno 8 feb 2021, alle ore 23:05, Erick Arce <notifications@github.com mailto:notifications@github.com > ha scritto:

If this fixes it submit another PR

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

makarid commented 3 years ago

It works i have test it

Στις Τρί, 9 Φεβ 2021 στις 12:22 π.μ., ο/η Paolo Rendano < notifications@github.com> έγραψε:

Yes @ajutzeler pls do the test and give us feedback. The PR is ready to be sent.

Il giorno 8 feb 2021, alle ore 23:05, Erick Arce <notifications@github.com mailto:notifications@github.com > ha scritto:

If this fixes it submit another PR

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/knowm/XChange/issues/3907#issuecomment-775503049, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHIWQ7ZHGWKQ32TXJOTX7BTS6BP25ANCNFSM4XJEVLTA .

paolo-rendano commented 3 years ago

sent. Just to simplify communication. I’ve discord. How to get in touch with this team? I’ve looked into the project but I cannot find reference to that.

Il giorno 8 feb 2021, alle ore 23:25, makarid <notifications@github.com mailto:notifications@github.com > ha scritto:

It works i have test it

Στις Τρί, 9 Φεβ 2021 στις 12:22 π.μ., ο/η Paolo Rendano < notifications@github.com mailto:notifications@github.com > έγραψε:

Yes @ajutzeler pls do the test and give us feedback. The PR is ready to be sent.

Il giorno 8 feb 2021, alle ore 23:05, Erick Arce <notifications@github.com mailto:notifications@github.com <mailto:notifications@github.com mailto:notifications@github.com > > ha scritto:

If this fixes it submit another PR

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/knowm/XChange/issues/3907#issuecomment-775503049, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHIWQ7ZHGWKQ32TXJOTX7BTS6BP25ANCNFSM4XJEVLTA .

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

ajutzeler commented 3 years ago

@paolo-rendano Yes, I confirm it works again thanks to your fix.

Thank you, Sir!

2pd commented 3 years ago

From the API document, https://binance-docs.github.io/apidocs/spot/en/#change-log there is nothing change related to Websocket service. Only a few new RESTful endpoints added.

earce commented 3 years ago

@paolo-rendano there isn't a team, it's a bunch of individual maintainers/contributors for the library @timmolter is the creator and owner of the library, discord usually has some fairly active developers on it