1- /*
2- * Copyright (c) 2021-2024 Osiris-Team.
3- * All rights reserved.
4- *
5- * This software is copyrighted work, licensed under the terms
6- * of the MIT-License. Consult the "LICENSE" file for details.
7- */
8-
91package com .osiris .autoplug .client .network .online ;
102
113import com .osiris .autoplug .client .network .online .connections .*;
124import com .osiris .jlib .logger .AL ;
5+ import io .netty .buffer .ByteBuf ;
6+ import io .netty .channel .ChannelHandlerContext ;
7+ import io .netty .handler .codec .ReplayingDecoder ;
8+ import io .netty .handler .timeout .IdleStateHandler ;
139
14- import java .io .IOException ;
1510import java .security .InvalidKeyException ;
11+ import java .util .List ;
12+ import java .util .concurrent .TimeUnit ;
1613import java .util .concurrent .atomic .AtomicBoolean ;
1714
18- /**
19- * This is the main connection to AutoPlugs online server/website.
20- * It stays active all the time and sends/receives true/false values, regarding the users login status.
21- * When the user is logged in, it creates the secondary connections and holds them until the user logs out.
22- * The main connection authenticates using the server_key.
23- * If it receives a true boolean it means that the user is logged in and opens new connections.
24- */
2515public class ConMain extends DefaultConnection {
2616 public final ConSendPublicDetails CON_PUBLIC_DETAILS = new ConSendPublicDetails ();
27-
28-
29- // Secondary connections:
3017 public final ConAutoPlugConsoleReceive CON_CONSOLE_RECEIVE = new ConAutoPlugConsoleReceive ();
3118 public final ConAutoPlugConsoleSend CON_CONSOLE_SEND = new ConAutoPlugConsoleSend ();
3219 public final ConSystemConsoleSend CON_SYSTEM_CONSOLE_SEND = new ConSystemConsoleSend ();
3320 public final ConSystemConsoleReceive CON_SYSTEM_CONSOLE_RECEIVE = new ConSystemConsoleReceive ();
3421 public final ConSendPrivateDetails CON_PRIVATE_DETAILS = new ConSendPrivateDetails ();
3522 public final ConFileManager CON_FILE_MANAGER = new ConFileManager ();
23+
3624 public boolean isDone = false ; // So that the log isn't a mess because of the processes which start right after this.
3725 public AtomicBoolean isUserActive = new AtomicBoolean (false );
38- public boolean isUserActiveOld = false ; // Local variable that holds the auth boolean before the current one
39-
26+ public boolean isUserActiveOld = false ;
4027 public int msUntilRetry = 30000 ;
4128
4229 public ConMain () {
@@ -49,97 +36,83 @@ public boolean open() {
4936 AL .info ("Authenticating server..." );
5037 super .open ();
5138 AL .info ("Authentication success!" );
52- socket .setSoTimeout (60000 ); // 60 seconds for when AP-Web is overloaded
5339 CON_PUBLIC_DETAILS .open ();
40+ msUntilRetry = 30000 ;
5441 isDone = true ;
5542 } catch (Exception e ) {
56- AL .warn (e );
5743 isDone = true ;
58- if (e instanceof InvalidKeyException )
59- return false ; // Abort directly since no valid key exists
60- // else we continue below and retry the connection
44+ AL .warn (e );
45+ if (e instanceof InvalidKeyException ) return false ;
46+ scheduleReconnect ();
47+ return false ;
6148 }
62- super .setAndStartAsync (() -> {
63- try {
64- if (!super .isConnected ()) {
65- AL .info ("Authenticating server..." );
66- super .open ();
67- AL .info ("Authentication success!" );
68- CON_PUBLIC_DETAILS .open ();
69- msUntilRetry = 30000 ;
70- }
71-
72- isDone = true ;
73- while (true ) {
74- isUserActive .set (super .in .readBoolean ()); // Ping
75- super .out .writeBoolean (true ); // Pong true/false doesn't matter
76-
77- if (isUserActive .get ()) {
78- if (!isUserActiveOld ) {
79- AL .debug (this .getClass (), "Owner/Staff is online/active." );
80- // User is online, so open secondary connections if they weren't already
81- if (CON_CONSOLE_RECEIVE .isConnected ()) CON_CONSOLE_RECEIVE .close ();
82- CON_CONSOLE_RECEIVE .open ();
83- if (CON_CONSOLE_SEND .isConnected ()) CON_CONSOLE_SEND .close ();
84- CON_CONSOLE_SEND .open ();
85- if (CON_SYSTEM_CONSOLE_RECEIVE .isConnected ()) CON_SYSTEM_CONSOLE_RECEIVE .close ();
86- CON_SYSTEM_CONSOLE_RECEIVE .open ();
87- if (CON_SYSTEM_CONSOLE_SEND .isConnected ()) CON_SYSTEM_CONSOLE_SEND .close ();
88- CON_SYSTEM_CONSOLE_SEND .open ();
89- if (CON_FILE_MANAGER .isConnected ()) CON_FILE_MANAGER .close ();
90- CON_FILE_MANAGER .open ();
91- if (CON_PRIVATE_DETAILS .isConnected ()) CON_PRIVATE_DETAILS .close ();
92- CON_PRIVATE_DETAILS .open ();
93- //if (!CON_PLUGINS_UPDATER.isConnected()) CON_PLUGINS_UPDATER.open(); Only is used at restarts!
94- }
95- } else {
96- if (isUserActiveOld ) {
97- AL .debug (this .getClass (), "Owner/Staff is offline/inactive." );
98- // Close secondary connections when user is offline/logged out
99- if (CON_CONSOLE_RECEIVE .isConnected ()) CON_CONSOLE_RECEIVE .close ();
100- if (CON_CONSOLE_SEND .isConnected ()) CON_CONSOLE_SEND .close ();
101- if (CON_SYSTEM_CONSOLE_RECEIVE .isConnected ()) CON_SYSTEM_CONSOLE_RECEIVE .close ();
102- if (CON_SYSTEM_CONSOLE_SEND .isConnected ()) CON_SYSTEM_CONSOLE_SEND .close ();
103- if (CON_FILE_MANAGER .isConnected ()) CON_FILE_MANAGER .close ();
104- if (CON_PRIVATE_DETAILS .isConnected ()) CON_PRIVATE_DETAILS .close ();
105- //if (CON_PLUGINS_UPDATER.isConnected()) CON_PLUGINS_UPDATER.close(); Only is used at restarts!
106- }
107- }
108- isUserActiveOld = isUserActive .get ();
109- Thread .sleep (3000 );
110- }
111- } catch (Exception e ) {
112- isDone = true ;
113- if (isClosing .get ()) {
114- AL .info ("Closed main connection to AutoPlug-Web." );
115- return ;
116- }
11749
118- // Since we didn't meant to close, create a new thread that tries to reconnect
119- new Thread (() -> {
120- try {
121- while (true ) {
122- AL .warn ("Connection problems! Reconnecting in " + msUntilRetry / 1000 + " seconds..." , e );
123- Thread .sleep (msUntilRetry );
50+ // Add IdleStateHandler FIRST: Wait some seconds for a read. (0 means disable write/all idle checking)
51+ channel .pipeline ().addLast (new IdleStateHandler (30 , 0 , 0 , TimeUnit .SECONDS ));
52+ channel .pipeline ().addLast (new ReplayingDecoder <Void >() {
53+ @ Override
54+ protected void decode (ChannelHandlerContext ctx , ByteBuf in , List <Object > out ) {
55+ boolean active = in .readBoolean ();
56+ isUserActive .set (active );
57+
58+ ByteBuf pong = ctx .alloc ().buffer (1 );
59+ pong .writeBoolean (true );
60+ ctx .writeAndFlush (pong );
61+
62+ try {
63+ if (active && !isUserActiveOld ) {
64+ AL .debug (ConMain .class , "Owner/Staff is online/active." );
65+ // Offload to a virtual thread so Netty can keep working
66+ Thread .startVirtualThread (() -> {
12467 try {
125- if (open ())
126- break ;
127- else
128- AL .warn ("Failed to reconnect!" );
129- } catch (Exception ex ) {
130- AL .warn ("Failed to reconnect!" , ex );
68+ if (!CON_CONSOLE_RECEIVE .isConnected ()) CON_CONSOLE_RECEIVE .open ();
69+ if (!CON_CONSOLE_SEND .isConnected ()) CON_CONSOLE_SEND .open ();
70+ if (!CON_SYSTEM_CONSOLE_RECEIVE .isConnected ()) CON_SYSTEM_CONSOLE_RECEIVE .open ();
71+ if (!CON_SYSTEM_CONSOLE_SEND .isConnected ()) CON_SYSTEM_CONSOLE_SEND .open ();
72+ if (!CON_FILE_MANAGER .isConnected ()) CON_FILE_MANAGER .open ();
73+ if (!CON_PRIVATE_DETAILS .isConnected ()) CON_PRIVATE_DETAILS .open ();
74+ } catch (Exception e ) {
75+ AL .warn (e );
13176 }
132- msUntilRetry += 30000 ;
133- }
134- } catch ( Exception exception ) {
135- AL . warn ( "Connection problems, unexpected error! Reconnect manually by entering '.con reload'." , exception );
77+ }) ;
78+ } else if (! active && isUserActiveOld ) {
79+ AL . debug ( ConMain . class , "Owner/Staff is offline/inactive." );
80+ closeTempCons ( );
13681 }
137- }).start ();
82+ isUserActiveOld = active ;
83+ } catch (Exception e ) {
84+ AL .warn (e );
85+ }
86+ checkpoint ();
87+ }
13888
139- close ();
89+ @ Override
90+ public void channelInactive (ChannelHandlerContext ctx ) {
91+ if (!isClosing .get ()) scheduleReconnect ();
92+ }
93+
94+ @ Override
95+ public void exceptionCaught (ChannelHandlerContext ctx , Throwable cause ) {
96+ if (!isClosing .get ()) scheduleReconnect ();
14097 }
14198 });
142- return true ; // Success
99+
100+ return true ;
101+ }
102+
103+ private void scheduleReconnect () {
104+ if (isClosing .get ()) return ;
105+ new Thread (() -> {
106+ try {
107+ AL .warn ("Connection problems! Reconnecting in " + msUntilRetry / 1000 + " seconds..." );
108+ Thread .sleep (msUntilRetry );
109+ msUntilRetry += 30000 ;
110+ if (!open ()) scheduleReconnect ();
111+ } catch (Exception e ) {
112+ AL .warn ("Reconnect error" , e );
113+ }
114+ }).start ();
115+ close ();
143116 }
144117
145118 @ Override
@@ -148,58 +121,19 @@ public void close() {
148121 closePermCons ();
149122 }
150123
151- /**
152- * Close connections that are alive all the time.
153- */
154124 public void closePermCons () {
155- try {
156- // Reset booleans
157- isUserActiveOld = false ;
158- isUserActive .set (false );
159- super .close ();
160- } catch (Exception e ) {
161- AL .warn (e );
162- }
163-
164- try {
165- if (CON_PUBLIC_DETAILS .isConnected ())
166- CON_PUBLIC_DETAILS .close ();
167- } catch (Exception e1 ) {
168- AL .warn (e1 );
169- }
125+ isUserActiveOld = false ;
126+ isUserActive .set (false );
127+ super .close ();
128+ try { if (CON_PUBLIC_DETAILS .isConnected ()) CON_PUBLIC_DETAILS .close (); } catch (Exception ignored ) {}
170129 }
171130
172- /**
173- * Close connections that are online alive when the user is logged in.
174- */
175131 public void closeTempCons () {
176- try {
177- if (CON_CONSOLE_RECEIVE .isConnected ())
178- CON_CONSOLE_RECEIVE .close ();
179- } catch (Exception e1 ) {
180- AL .warn (e1 );
181- }
182-
183- try {
184- if (CON_CONSOLE_SEND .isConnected ())
185- CON_CONSOLE_SEND .close ();
186- } catch (IOException e1 ) {
187- AL .warn (e1 );
188- }
189-
190- try {
191- if (CON_PRIVATE_DETAILS .isConnected ())
192- CON_PRIVATE_DETAILS .close ();
193- } catch (Exception e1 ) {
194- AL .warn (e1 );
195- }
196-
197- try {
198- if (CON_FILE_MANAGER .isConnected ())
199- CON_FILE_MANAGER .close ();
200- } catch (Exception e1 ) {
201- AL .warn (e1 );
202- }
132+ try { if (CON_CONSOLE_RECEIVE .isConnected ()) CON_CONSOLE_RECEIVE .close (); } catch (Exception ignored ) {}
133+ try { if (CON_CONSOLE_SEND .isConnected ()) CON_CONSOLE_SEND .close (); } catch (Exception ignored ) {}
134+ try { if (CON_PRIVATE_DETAILS .isConnected ()) CON_PRIVATE_DETAILS .close (); } catch (Exception ignored ) {}
135+ try { if (CON_FILE_MANAGER .isConnected ()) CON_FILE_MANAGER .close (); } catch (Exception ignored ) {}
136+ try { if (CON_SYSTEM_CONSOLE_RECEIVE .isConnected ()) CON_SYSTEM_CONSOLE_RECEIVE .close (); } catch (Exception ignored ) {}
137+ try { if (CON_SYSTEM_CONSOLE_SEND .isConnected ()) CON_SYSTEM_CONSOLE_SEND .close (); } catch (Exception ignored ) {}
203138 }
204-
205- }
139+ }
0 commit comments