Re: Intercepting WebSocket ping messages

2017-03-31 Thread Robert Lewis
703826:1000491596
  java.lang.Thread.getStackTrace(Thread.java:1556)

org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:97)

org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:89)

org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)

org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341)

org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273)

org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPong(WsRemoteEndpointImplBase.java:186)

org.apache.tomcat.websocket.WsRemoteEndpointBase.sendPong(WsRemoteEndpointBase.java:62)

org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:351)
  org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:290)

org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)

org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)

org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)

org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)

org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)

org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664)

org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)

org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)

java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  java.lang.Thread.run(Thread.java:745)
http-nio-8443-exec-10: clearHandler (start) 909703826:1000491596
http-nio-8443-exec-10: clearHandler (end)
http-nio-8443-exec-10: onWritePossible (end)
http-nio-8443-exec-10: doWrite (end)


On Fri, Mar 31, 2017 at 9:01 AM, Mark Thomas <ma...@apache.org> wrote:

> On 30/03/17 21:13, Robert Lewis wrote:
> > Is there a way to intercept a ping message to send a pong?
>
> The API doesn't support this.
>
>
> > I need to do this synchronize sends to the endpoint.
>
> Could you clarify your requirement? Tomcat should handle pong messages
> automatically for you (as required by the spec).
>
> Mark
>
>
>
> -
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>


Intercepting WebSocket ping messages

2017-03-30 Thread Robert Lewis
Is there a way to intercept a ping message to send a pong? I need to do
this synchronize sends to the endpoint.

I tried

session.addMessageHandler(new
javax.websocket.MessageHandler.Whole() {

@Override
public void onMessage(PongMessage message) {
System.out.println("hi");
}

});


And

@OnMessage public void onPong(PongMessage message) {}


Re: Tracking down a Basic.sendBinary() issue

2017-03-30 Thread Robert Lewis
Ok. We do lock all our calls to Basic.sendBinary(), also it seems like
moving to Tomcat 8.5 fixes the issue. No proof yet why. Since it always
happens on our last write out to a client which should trigger a client
ack, the client will immediately send an ack back to us (which seems to
trigger the problem), and was thinking it was possibly because the read /
write on one thread happened before we were finished the onWritePossible
call at the container level.

"From experience, timing issues tend to be triggered by non-container
threads.":
Yes, but the fact that doWrite() was moved out of the sync block to fix a
deadlock situation indicates otherwise.

Ping on every call fixes the problem for us, and we will be working to move
to 8.5 soon anyway.

Thanks,
 -Rob


On Thu, Mar 30, 2017 at 1:09 PM, Mark Thomas <ma...@apache.org> wrote:

> On 29/03/17 04:04, Robert Lewis wrote:
> > Thanks Mark. I will take a look at the test you linked in (seems like
> Clint
> > already is).
> >
> > I have a question regarding your previous note "The short version is that
> > it is possible that there are two threads". On 8.0.38, doWrite() sets
> it's
> > scoped handler and buffers to the class level instance, then proceeds to
> > call onWritePossible(true). onWritePossible creates a new local variable
> > that seems like it copies the class level buffers state (not sure if this
> > is a deep clone or not, i'll have to test this), but it does not
> replicate
> > the handler reference. If onWritePossible() is busy working writing the
> > buffers to the socket and another thread calls doWrite(), that class
> level
> > state will be swapped before onWritePossible is finished, resulting in a
> > possible race condition for a swapped out buffer or handler.
> >
> > Not claiming to know the code as well as those who maintain it, but it
> > would be nice to know if someone thinks this could happen resulting in
> > unexpected behavior (eg. we are writing to a socket and the the read
> thread
> > responds with a write on another thread).
>
> There are checks much higher up the stack that should throw an
> IllegalStateException (from memory) if you try and write two messages at
> once.
>
> From experience, timing issues tend to be triggered by non-container
> threads. A typical pattern is that the first thread has some unexpected
> side-effects that impact on the second thread - often because of
> unexpected execution order.
>
> > Curious why onWritePossible(true) is not called with the doWrite() state?
> > (eg. onWritePossible(true, buffers, handler))?
>
> The callers don't all have that information.
>
> > This is just an observation at this point so looking for an opinion on
> > whether or not something described above could happen. If what was stated
> > (that a write and a read / response write) can operate on two threads, I
> > don't see why not.
> >
> > Continuing to run off and play with the tests you have linked.
>
> Again from experience unless you have some clues to point you in the
> right direction, finding these issues via code inspection is hard.
> Equally, a reproducible test case is rare. What tends to happen is a
> more iterative approach that starts with an occasionally failing test
> case and a combination of debugging, logging and extra debug statements
> is used to narrow down the location of the problem.
>
> Mark
>
>
> -
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>


Re: need help with websocket

2017-03-29 Thread Robert Lewis
WSS will work if you enable and configure the HTTPS connector in server.xml.

This part of the configuration is not really wss specific and tomcat site 
contains a bunch of good docs on how to do this.

> On Mar 29, 2017, at 4:40 PM, Sharat Jagannath  wrote:
> 
> The code on the tomcat page does not have examples for wss. But I will look
> into his ngnix is configured
> 
> Thanks
> 
> On Mar 29, 2017 1:15 PM, "Mark Eggers" 
> wrote:
> 
>> Sharat,
>> 
>>> On 3/29/2017 9:23 AM, Sharat Jagannath wrote:
>>> I get a 404 error when I call my server endpoint with wss.
>>> I'm using tomcat 9 which sits behind ngnix. Does that make a difference?
>>> here's how my server.xml looks like-
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>>  > />
>>>  
>>>  
>>>  >> SSLEngine="on" />
>>>  
>>>  >> className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
>>>  >> className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"
>> />
>>>  >> className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"
>> />
>>> 
>>> 
>>>  
>>>  
>>>
>>>>>  type="org.apache.catalina.UserDatabase"
>>>  description="User database that can be updated and saved"
>>>  factory="org.apache.catalina.users.
>> MemoryUserDatabaseFactory"
>>>  pathname="conf/tomcat-users.xml" />
>>>  
>>> 
>>>  
>>>  
>>> 
>>>
>>>
>>> 
>>> 
>>>
>>> 
>>> 
>>>>>   connectionTimeout="2"
>>>   redirectPort="8443" URIEncoding="UTF-8"
>>> useBodyEncodingForURI="true" compression="on" compressionMinSize="2048"
>>> noCompressionUserAgents="gozilla, traviata"
>>> compressableMimeType="text/html,text/xml,text/plain,text/
>> css,text/javascript"
>>> />
>>> 
>>> 
>>>
>>>
>>>
>>>
>>>
>>>
>>> 
>>>
>>>
>>> 
>>> 
>>>
>>> 
>>>
>>>
>>> 
>>> 
>>>  
>>>  
>>> 
>>>  
>>>  
>>>
>>>>>   resourceName="UserDatabase"/>
>>>  
>>> 
>>>  >>unpackWARs="true" autoDeploy="true">
>>> 
>>>
>>>
>>> 
>>>
>>>>> directory="logs"
>>>   prefix="localHost_access_log" suffix=".txt"
>>>   pattern="%h %l %u %t %r %s %b" />
>>> 
>>>  
>>>
>>>  
>>> 
>>> 
>>> 
>>> 
 On Mar 29, 2017 6:24 AM, "calder"  wrote:
 
 On Tuesday, March 28, 2017, Sharat Jagannath 
>> wrote:
 
> how do i setup websocket on server side for using wss with tomcat
>> config?
> is there any config i need to do with tomcat? any certification to
>> setup?
 
 
> 
 
 Read up using the How-to:
 
 https://tomcat.apache.org/tomcat-8.0-doc/web-socket-howto.html
 
 
 http://tomcat-configure.blogspot.com/2014/05/tomcat-websock
 et-example.html
 
>>> 
>> 
>> Two things to try:
>> 
>> 1. Have you tried to connect without using NGINX as a front end proxy?
>> 
>> 2. Have you configured your NGINX server appropriately?
>> 
>> See the following for configuring NGINX to act as a websocket proxy:
>> 
>> http://nginx.org/en/docs/http/websocket.html
>> https://www.nginx.com/blog/websocket-nginx/
>> 
>> Also, see the following:
>> 
>> http://tomcat.apache.org/tomcat-9.0-doc/web-socket-howto.html
>> 
>> and follow the links to look at both the server and client side code.
>> 
>> Please note that I've not done any of this, since I have Tomcat sitting
>> behind Apache HTTPD 2.2. I have not ported the proxy_wstunnel module
>> from Apache HTTPD 2.4 to 2.2.
>> 
>> . . . just my two cents
>> /mde/
>> 
>> Please note that I've not done any of this.
>> 
>> 
>> 

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Tracking down a Basic.sendBinary() issue

2017-03-28 Thread Robert Lewis
Thanks Mark. I will take a look at the test you linked in (seems like Clint
already is).

I have a question regarding your previous note "The short version is that
it is possible that there are two threads". On 8.0.38, doWrite() sets it's
scoped handler and buffers to the class level instance, then proceeds to
call onWritePossible(true). onWritePossible creates a new local variable
that seems like it copies the class level buffers state (not sure if this
is a deep clone or not, i'll have to test this), but it does not replicate
the handler reference. If onWritePossible() is busy working writing the
buffers to the socket and another thread calls doWrite(), that class level
state will be swapped before onWritePossible is finished, resulting in a
possible race condition for a swapped out buffer or handler.

Not claiming to know the code as well as those who maintain it, but it
would be nice to know if someone thinks this could happen resulting in
unexpected behavior (eg. we are writing to a socket and the the read thread
responds with a write on another thread).

Based on the link I posted before (
http://tomcat.10.x6.nabble.com/Tomcat-WebSocket-does-not-always-send-asynchronous-messages-td5060965.html),
Harri mentions that in Tomcat 8.5, blocking sockets do not seem to exhibit
the same failure behavior as async sockets, which leads me to believe that
the else block (scoped state, write to socket, flush) fixes the problem,
and async may still have a race given class level state across two
functions that are not synchronized. We are using 8.0.38 and are seeing
async and sync cases not flushing in rare situations.

Curious why onWritePossible(true) is not called with the doWrite() state?
(eg. onWritePossible(true, buffers, handler))?

This is just an observation at this point so looking for an opinion on
whether or not something described above could happen. If what was stated
(that a write and a read / response write) can operate on two threads, I
don't see why not.

Continuing to run off and play with the tests you have linked.

Thanks,
  -Rob

On Tue, Mar 28, 2017 at 3:46 PM, Mark Thomas <ma...@apache.org> wrote:

> On 28/03/17 00:30, Robert Lewis wrote:
> > Hi,
> >
> > I am tracking down a fairly sporadic bug in our software that uses Tomcat
> > 8.0.38. Long story short, sometimes calls to Basic.sendBinary() to a full
> > buffer then to a small buffer (eg. 8192x3 then 444 bytes). The first 8192
> > sends will succeed and occasionally we see the last 444 byte send 'fail'
> in
> > a way that we never see it leave the network, resulting in the client
> > waiting for bytes and eventually timing out. We notice that if we close
> the
> > the connection remotely, the bytes immediately get sent.
> >
> > This led me to believe something was not getting flushed properly. This
> URL
> > indicates that there were some recent conversations about something
> similar:
> >
> > http://tomcat.10.x6.nabble.com/Tomcat-WebSocket-does-not-
> > always-send-asynchronous-messages-td5060965.html
> >
> > I decided to dig further and tried to send a ping between sending bytes,
> it
> > seems to alleviate the problem, but still doesn't tell me what is going
> on.
> > Taking a suggestion from Mark T.  \around a 'possible race condition in
> the
> > web socket code', I debugged through tomcat code looking for race
> > conditions, and immediately a source file and function (doWrite()) stood
> > out, it is modifying state then calling to another public function to act
> > on that state:
> >
> > https://github.com/apache/tomcat/blob/TOMCAT_8_0_0_RC10/
> > java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
>
> That is quite an old version of the code. You'd be better off looking at
> the master copy which is in svn at the ASF:
>
> https://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/
> apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java?view=log
>
> > Further up, the doWrite() caller in the endpoint was moved out of a sync
> > block to prevent a deadlock (there was a specific comment around this),
> > which leads me to believe that something was calling doWrite() on
> multiple
> > threads, but I have not tracked that down yet.
>
> This is part of the long story to do with trying to run on the Servlet
> 3.1 API (see below). For full details see:
> http://people.apache.org/~markt/presentations/2013-09-
> XX-WebSocket-on-Servlet31.pdf
>
> starting around slide 37.
>
> The short version is that it is possible that there are two threads
> trying to write in parallel:
> - one 'write' thread responding to the poller
> - one 'read' thread in application code that is trying to write a
>   response to what it has just read
>
>

Tracking down a Basic.sendBinary() issue

2017-03-27 Thread Robert Lewis
Hi,

I am tracking down a fairly sporadic bug in our software that uses Tomcat
8.0.38. Long story short, sometimes calls to Basic.sendBinary() to a full
buffer then to a small buffer (eg. 8192x3 then 444 bytes). The first 8192
sends will succeed and occasionally we see the last 444 byte send 'fail' in
a way that we never see it leave the network, resulting in the client
waiting for bytes and eventually timing out. We notice that if we close the
the connection remotely, the bytes immediately get sent.

This led me to believe something was not getting flushed properly. This URL
indicates that there were some recent conversations about something similar:

http://tomcat.10.x6.nabble.com/Tomcat-WebSocket-does-not-
always-send-asynchronous-messages-td5060965.html

I decided to dig further and tried to send a ping between sending bytes, it
seems to alleviate the problem, but still doesn't tell me what is going on.
Taking a suggestion from Mark T.  \around a 'possible race condition in the
web socket code', I debugged through tomcat code looking for race
conditions, and immediately a source file and function (doWrite()) stood
out, it is modifying state then calling to another public function to act
on that state:

https://github.com/apache/tomcat/blob/TOMCAT_8_0_0_RC10/
java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java

Further up, the doWrite() caller in the endpoint was moved out of a sync
block to prevent a deadlock (there was a specific comment around this),
which leads me to believe that something was calling doWrite() on multiple
threads, but I have not tracked that down yet.

Anyway, there was a recent code change on the 8.5.x series to the doWrite()
implementation which checks to see if it is a blocking call, then sends
immediately to the socket and flushes without class level state. I have not
tested this yet to see if it solves the issue as we are tied to 8.0.x for
now, but working on migrating our code to work with 8.5.x.

Most of the work on the files seem to be done by Mark T. (awesome work, we
rely on this functionality heavily!) so I figured I would reach out and ask
about the doWrite() change to have a else block for blocking sockets. Is
this intended to fix the issue I am describing above?

I would check the history but I cannot seem to find the source for the
initial commit that introduces the else block for 8.5.x.

Thanks,
  -Rob


Tracking down a Basic.sendBinary() issue

2017-03-27 Thread Robert Lewis
Hi,

I am tracking down a fairly sporadic bug in our software that uses Tomcat
8.0.38. Long story short, sometimes calls to Basic.sendBinary() to a full
buffer then to a small buffer (eg. 8192x3 then 444 bytes). The first 8192
sends will succeed and occasionally we see the last 444 byte send 'fail' in
a way that we never see it leave the network, resulting in the client
waiting for bytes and eventually timing out. We notice that if we close the
the connection remotely, the bytes immediately get sent.

This led me to believe something was not getting flushed properly. This URL
indicates that there were some recent conversations about something similar:

http://tomcat.10.x6.nabble.com/Tomcat-WebSocket-does-not-alw
ays-send-asynchronous-messages-td5060965.html

I decided to dig further and tried to send a ping between sending bytes, it
seems to alleviate the problem, but still doesn't tell me what is going on.
Taking a suggestion from Mark T.  \around a 'possible race condition in the
web socket code', I debugged through tomcat code looking for race
conditions, and immediately a source file and function (doWrite()) stood
out, it is modifying state then calling to another public function to act
on that state:

https://github.com/apache/tomcat/blob/TOMCAT_8_0_0_RC10/java
/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java

Further up the call stack, the doWrite() caller in the endpoint was moved
out of a sync block to prevent a deadlock (there was a specific comment
around this), which leads me to believe that something was calling
doWrite() on multiple threads, but I have not tracked that down yet.

Anyway, there was a recent code change on the 8.5.x series to the doWrite()
implementation which checks to see if it is a blocking call, then sends
immediately to the socket and flushes without class level state. I have not
tested this yet to see if it solves the issue as we are tied to 8.0.x for
now, but working on migrating our code to work with 8.5.x. Change for added
else here:
https://github.com/apache/tomcat/blob/TOMCAT_9_0_0_M19/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
)

Most of the work on the files seem to be done by Mark T. (awesome work, we
rely on this functionality heavily!) so I figured I would reach out and ask
about the doWrite() change to have a else block for blocking sockets. Is
this intended to fix the issue I am describing above?

I would check the history but I cannot seem to find the source for the
initial commit that introduces the else block for 8.5.x.

Thanks,
  -Rob