Skip to content

Commit d40f20b

Browse files
committed
Delay pong responses to reduce number of pings from WebSocket clients sitting in a loop
1 parent e88b532 commit d40f20b

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

lib/em-websocket/message_processor_06.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,22 @@ def message(message_type, extension_data, application_data)
3737
@connection.close_connection_after_writing
3838
end
3939
when :ping
40-
# Pong back the same data
41-
send_frame(:pong, application_data)
40+
# There are a couple of protections here against malicious/broken WebSocket abusing ping frames.
41+
#
42+
# 1. Delay 200ms before replying. This reduces the number of pings from WebSocket clients behaving as
43+
# `for (;;) { send_ping(conn); rcv_pong(conn); }`. The spec says we "SHOULD respond with Pong frame as soon
44+
# as is practical".
45+
# 2. Reply at most every 200ms. This reduces the number of pong frames sent to WebSocket clients behaving as
46+
# `for (;;) { send_ping(conn); }`. The spec says "If an endpoint receives a Ping frame and has not yet sent
47+
# Pong frame(s) in response to previous Ping frame(s), the endpoint MAY elect to send a Pong frame for only
48+
# the most recently processed Ping frame."
49+
@most_recent_pong_application_data = application_data
50+
if @pong_timer == nil then
51+
@pong_timer = EventMachine.add_timer(0.2) do
52+
@pong_timer = nil
53+
send_frame(:pong, @most_recent_pong_application_data)
54+
end
55+
end
4256
@connection.trigger_on_ping(application_data)
4357
when :pong
4458
@connection.trigger_on_pong(application_data)

0 commit comments

Comments
 (0)