1717import java .io .*;
1818import java .net .Socket ;
1919import java .net .SocketTimeoutException ;
20+ import net .rptools .clientserver .ActivityListener ;
2021import org .apache .logging .log4j .LogManager ;
2122import org .apache .logging .log4j .Logger ;
2223
@@ -27,32 +28,29 @@ public class SocketConnection extends AbstractConnection implements Connection {
2728 /** Instance used for log messages. */
2829 private static final Logger log = LogManager .getLogger (SocketConnection .class );
2930
30- private final String id ;
31+ // Only valid for open connections.
3132 private SendThread send ;
3233 private ReceiveThread receive ;
3334 private Socket socket ;
35+
36+ // Only valid for pending connections before #open() is called.
3437 private String hostName ;
3538 private int port ;
3639
3740 public SocketConnection (String id , String hostName , int port ) {
38- this . id = id ;
41+ super ( id ) ;
3942 this .hostName = hostName ;
4043 this .port = port ;
4144 }
4245
4346 public SocketConnection (String id , Socket socket ) {
44- this .id = id ;
45- this .socket = socket ;
46-
47- initialize (socket );
47+ super (id );
48+ connect (socket );
4849 }
4950
50- @ Override
51- public String getId () {
52- return id ;
53- }
51+ private void connect (Socket socket ) {
52+ assert this .socket != null : "Should only call #connect() not already open" ;
5453
55- private void initialize (Socket socket ) {
5654 this .socket = socket ;
5755 this .send = new SendThread (socket );
5856 this .receive = new ReceiveThread (socket );
@@ -63,7 +61,11 @@ private void initialize(Socket socket) {
6361
6462 @ Override
6563 public void open () throws IOException {
66- initialize (new Socket (hostName , port ));
64+ if (this .socket != null ) {
65+ throw new IOException ("The connection has already been opened." );
66+ }
67+
68+ connect (new Socket (hostName , port ));
6769 }
6870
6971 @ Override
@@ -73,6 +75,11 @@ public void sendMessage(Object channel, byte[] message) {
7375
7476 @ Override
7577 protected void onClose () {
78+ if (socket == null ) {
79+ // Not open, so nothing to do.
80+ return ;
81+ }
82+
7683 receive .interrupt ();
7784 send .interrupt ();
7885
@@ -85,7 +92,7 @@ protected void onClose() {
8592
8693 @ Override
8794 public boolean isAlive () {
88- return !socket .isClosed ();
95+ return socket != null && !socket .isClosed ();
8996 }
9097
9198 @ Override
@@ -124,7 +131,7 @@ public void run() {
124131 }
125132
126133 try {
127- SocketConnection . this . writeMessage (out , message );
134+ writeMessage (out , message );
128135 } catch (IOException e ) {
129136 log .error ("Error while writing message. Closing connection." , e );
130137 return ;
@@ -134,6 +141,29 @@ public void run() {
134141 SocketConnection .this .close ();
135142 }
136143 }
144+
145+ protected final void writeMessage (OutputStream out , byte [] message ) throws IOException {
146+ int length = message .length ;
147+
148+ notifyListeners (ActivityListener .Direction .Outbound , ActivityListener .State .Start , length , 0 );
149+
150+ out .write (length >> 24 );
151+ out .write (length >> 16 );
152+ out .write (length >> 8 );
153+ out .write (length );
154+
155+ for (int i = 0 ; i < message .length ; i ++) {
156+ out .write (message [i ]);
157+
158+ if (i != 0 && i % ActivityListener .CHUNK_SIZE == 0 ) {
159+ notifyListeners (
160+ ActivityListener .Direction .Outbound , ActivityListener .State .Progress , length , i );
161+ }
162+ }
163+ out .flush ();
164+ notifyListeners (
165+ ActivityListener .Direction .Outbound , ActivityListener .State .Complete , length , length );
166+ }
137167 }
138168
139169 // /////////////////////////////////////////////////////////////////////////
@@ -160,7 +190,7 @@ public void run() {
160190
161191 while (!SocketConnection .this .isClosed () && SocketConnection .this .isAlive ()) {
162192 try {
163- byte [] message = SocketConnection . this . readMessage (in );
193+ byte [] message = readMessage (in );
164194 SocketConnection .this .dispatchCompressedMessage (message );
165195 } catch (SocketTimeoutException e ) {
166196 log .warn ("Lost client {}" , SocketConnection .this .getId (), e );
@@ -178,5 +208,32 @@ public void run() {
178208 fireDisconnect ();
179209 }
180210 }
211+
212+ private byte [] readMessage (InputStream in ) throws IOException {
213+ int b32 = in .read ();
214+ int b24 = in .read ();
215+ int b16 = in .read ();
216+ int b8 = in .read ();
217+
218+ if (b32 < 0 ) {
219+ throw new IOException ("Stream closed" );
220+ }
221+ int length = (b32 << 24 ) + (b24 << 16 ) + (b16 << 8 ) + b8 ;
222+
223+ notifyListeners (ActivityListener .Direction .Inbound , ActivityListener .State .Start , length , 0 );
224+
225+ byte [] ret = new byte [length ];
226+ for (int i = 0 ; i < length ; i ++) {
227+ ret [i ] = (byte ) in .read ();
228+
229+ if (i != 0 && i % ActivityListener .CHUNK_SIZE == 0 ) {
230+ notifyListeners (
231+ ActivityListener .Direction .Inbound , ActivityListener .State .Progress , length , i );
232+ }
233+ }
234+ notifyListeners (
235+ ActivityListener .Direction .Inbound , ActivityListener .State .Complete , length , length );
236+ return ret ;
237+ }
181238 }
182239}
0 commit comments