Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
Morningstar
Arcturus Morningstar
Commits
0bbe249c
Commit
0bbe249c
authored
Feb 09, 2021
by
skeletor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed pinging to send every 30 seconds, regardless of idle state
parent
5531c206
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
122 additions
and
18 deletions
+122
-18
src/main/java/com/eu/habbo/networking/gameserver/GameServer.java
...n/java/com/eu/habbo/networking/gameserver/GameServer.java
+1
-4
src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java
...bo/networking/gameserver/handlers/IdleTimeoutHandler.java
+121
-14
No files found.
src/main/java/com/eu/habbo/networking/gameserver/GameServer.java
View file @
0bbe249c
...
...
@@ -32,9 +32,6 @@ public class GameServer extends Server {
public
void
initChannel
(
SocketChannel
ch
)
throws
Exception
{
ch
.
pipeline
().
addLast
(
"logger"
,
new
LoggingHandler
());
ch
.
pipeline
().
addLast
(
"idleStateHandler"
,
new
IdleStateHandler
(
60
,
30
,
0
));
ch
.
pipeline
().
addAfter
(
"idleStateHandler"
,
"idleEventHandler"
,
new
IdleTimeoutHandler
());
// Decoders.
ch
.
pipeline
().
addLast
(
new
GamePolicyDecoder
());
ch
.
pipeline
().
addLast
(
new
GameByteFrameDecoder
());
...
...
@@ -43,7 +40,7 @@ public class GameServer extends Server {
if
(
PacketManager
.
DEBUG_SHOW_PACKETS
)
{
ch
.
pipeline
().
addLast
(
new
GameClientMessageLogger
());
}
ch
.
pipeline
().
addLast
(
"idleEventHandler"
,
new
IdleTimeoutHandler
(
30
,
60
));
ch
.
pipeline
().
addLast
(
new
GameMessageRateLimit
());
ch
.
pipeline
().
addLast
(
new
GameMessageHandler
());
...
...
src/main/java/com/eu/habbo/networking/gameserver/handlers/IdleTimeoutHandler.java
View file @
0bbe249c
package
com.eu.habbo.networking.gameserver.handlers
;
import
com.eu.habbo.habbohotel.gameclients.GameClient
;
import
com.eu.habbo.messages.ClientMessage
;
import
com.eu.habbo.messages.incoming.Incoming
;
import
com.eu.habbo.messages.outgoing.handshake.PingComposer
;
import
com.eu.habbo.networking.gameserver.GameServerAttributes
;
import
io.netty.channel.ChannelDuplexHandler
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.handler.timeout.IdleState
;
import
io.netty.handler.timeout.IdleStateEvent
;
import
java.util.concurrent.ScheduledFuture
;
import
java.util.concurrent.TimeUnit
;
public
class
IdleTimeoutHandler
extends
ChannelDuplexHandler
{
private
static
final
long
MIN_TIMEOUT_NANOS
=
TimeUnit
.
MILLISECONDS
.
toNanos
(
1
);
private
final
long
pingScheduleNanos
;
private
final
long
pongTimeoutNanos
;
volatile
ScheduledFuture
<?>
pingScheduleFuture
;
volatile
long
lastPongTime
;
// in nanoseconds
private
volatile
int
state
;
// 0 - none, 1 - initialized, 2 - destroyed
public
IdleTimeoutHandler
(
int
pingScheduleSeconds
,
int
pongTimeoutSeconds
)
{
this
.
pingScheduleNanos
=
Math
.
max
(
MIN_TIMEOUT_NANOS
,
TimeUnit
.
SECONDS
.
toNanos
(
pingScheduleSeconds
));
this
.
pongTimeoutNanos
=
Math
.
max
(
MIN_TIMEOUT_NANOS
,
TimeUnit
.
SECONDS
.
toNanos
(
pongTimeoutSeconds
));
}
private
void
initialize
(
ChannelHandlerContext
ctx
)
{
// Avoid the case where destroy() is called before scheduling timeouts.
// See: https://github.com/netty/netty/issues/143
switch
(
state
)
{
case
1
:
case
2
:
return
;
}
state
=
1
;
lastPongTime
=
System
.
nanoTime
();
if
(
pingScheduleNanos
>
0
)
{
pingScheduleFuture
=
ctx
.
executor
().
schedule
(
new
PingScheduledTask
(
ctx
),
pingScheduleNanos
,
TimeUnit
.
NANOSECONDS
);
}
}
private
void
destroy
()
{
state
=
2
;
if
(
pingScheduleFuture
!=
null
)
{
pingScheduleFuture
.
cancel
(
false
);
pingScheduleFuture
=
null
;
}
}
@Override
public
void
userEventTriggered
(
ChannelHandlerContext
ctx
,
Object
evt
)
throws
Exception
{
if
(
evt
instanceof
IdleStateEvent
)
{
IdleStateEvent
e
=
(
IdleStateEvent
)
evt
;
if
(
e
.
state
()
==
IdleState
.
READER_IDLE
)
{
ctx
.
close
();
}
else
if
(
e
.
state
()
==
IdleState
.
WRITER_IDLE
)
{
GameClient
client
=
ctx
.
channel
().
attr
(
GameServerAttributes
.
CLIENT
).
get
();
if
(
client
!=
null
)
{
client
.
sendResponse
(
new
PingComposer
());
}
}
public
void
handlerAdded
(
ChannelHandlerContext
ctx
)
throws
Exception
{
if
(
ctx
.
channel
().
isActive
()
&&
ctx
.
channel
().
isRegistered
())
{
// channelActvie() event has been fired already, which means this.channelActive() will
// not be invoked. We have to initialize here instead.
initialize
(
ctx
);
}
else
{
super
.
userEventTriggered
(
ctx
,
evt
);
// channelActive() event has not been fired yet. this.channelActive() will be invoked
// and initialization will occur there.
}
}
@Override
public
void
handlerRemoved
(
ChannelHandlerContext
ctx
)
throws
Exception
{
destroy
();
}
@Override
public
void
channelRegistered
(
ChannelHandlerContext
ctx
)
throws
Exception
{
// Initialize early if channel is active already.
if
(
ctx
.
channel
().
isActive
())
{
initialize
(
ctx
);
}
super
.
channelRegistered
(
ctx
);
}
@Override
public
void
channelActive
(
ChannelHandlerContext
ctx
)
throws
Exception
{
// This method will be invoked only if this handler was added
// before channelActive() event is fired. If a user adds this handler
// after the channelActive() event, initialize() will be called by beforeAdd().
initialize
(
ctx
);
super
.
channelActive
(
ctx
);
}
@Override
public
void
channelInactive
(
ChannelHandlerContext
ctx
)
throws
Exception
{
destroy
();
super
.
channelInactive
(
ctx
);
}
@Override
public
void
channelRead
(
ChannelHandlerContext
ctx
,
Object
msg
)
throws
Exception
{
// check if its a pong message
if
(
msg
instanceof
ClientMessage
)
{
ClientMessage
packet
=
(
ClientMessage
)
msg
;
if
(
packet
.
getMessageId
()
==
Incoming
.
PongEvent
)
{
this
.
lastPongTime
=
System
.
nanoTime
();
}
}
super
.
channelRead
(
ctx
,
msg
);
}
private
final
class
PingScheduledTask
implements
Runnable
{
private
final
ChannelHandlerContext
ctx
;
public
PingScheduledTask
(
ChannelHandlerContext
ctx
)
{
this
.
ctx
=
ctx
;
}
@Override
public
void
run
()
{
if
(!
ctx
.
channel
().
isOpen
())
{
return
;
}
long
currentTime
=
System
.
nanoTime
();
if
(
currentTime
-
lastPongTime
>
pongTimeoutNanos
)
{
ctx
.
close
();
// add a promise here ?
return
;
}
GameClient
client
=
ctx
.
channel
().
attr
(
GameServerAttributes
.
CLIENT
).
get
();
if
(
client
!=
null
)
{
client
.
sendResponse
(
new
PingComposer
());
}
pingScheduleFuture
=
ctx
.
executor
().
schedule
(
this
,
pingScheduleNanos
,
TimeUnit
.
NANOSECONDS
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment