 |
Crossfire JXClient, Trunk
|
Go to the documentation of this file.
23 package com.realtime.crossfire.jxclient.server.socket;
28 import java.io.EOFException;
29 import java.io.IOException;
30 import java.net.InetSocketAddress;
31 import java.net.SocketAddress;
32 import java.net.SocketException;
33 import java.nio.Buffer;
34 import java.nio.BufferOverflowException;
35 import java.nio.ByteBuffer;
36 import java.nio.ByteOrder;
37 import java.nio.channels.SelectableChannel;
38 import java.nio.channels.SelectionKey;
39 import java.nio.channels.Selector;
40 import java.nio.channels.SocketChannel;
41 import java.nio.channels.UnresolvedAddressException;
42 import java.util.Collection;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
197 private final Thread
thread =
new Thread(this::process,
"JXClient:ClientSocket");
226 public void stop() throws InterruptedException {
233 }
catch (
final IOException ex) {
270 if (this.host ==
null || this.port == 0 || !this.host.equals(
host) || this.port !=
port) {
286 public void disconnect(@NotNull
final String reason,
final boolean isError) {
307 while (!
thread.isInterrupted()) {
313 }
catch (
final EOFException ex) {
314 final String tmp = ex.getMessage();
315 final String message = tmp ==
null ?
"EOF" : tmp;
320 }
catch (
final IOException ex) {
321 final String tmp = ex.getMessage();
322 final String message = tmp ==
null ?
"I/O error" : tmp;
336 final boolean notifyConnected;
339 notifyConnected =
false;
345 notifyConnected =
true;
347 notifyConnected =
false;
351 if (notifyConnected) {
353 clientSocketListener.connected();
363 assert Thread.currentThread() ==
thread;
366 final boolean doDisconnect;
367 @Nullable
final String disconnectReason;
368 final boolean disconnectIsError;
374 doDisconnect =
false;
375 disconnectReason =
"reconnect to "+
host+
":"+
port;
376 disconnectIsError =
false;
385 doDisconnect =
false;
386 disconnectReason =
null;
387 disconnectIsError =
false;
391 assert disconnectReason !=
null;
393 final String connectHost;
394 final int connectPort;
400 if (connectHost !=
null) {
415 if (Thread.currentThread().isInterrupted()) {
418 final Collection<SelectionKey> selectedKeys =
selector.selectedKeys();
427 assert selectedKeys.isEmpty();
437 assert Thread.currentThread() ==
thread;
443 clientSocketListener.connecting();
446 final SocketAddress socketAddress =
new InetSocketAddress(
host,
port);
456 }
catch (
final UnresolvedAddressException ex) {
457 throw new IOException(
"Cannot resolve address: "+socketAddress, ex);
458 }
catch (
final IllegalArgumentException ex) {
459 throw new IOException(ex.getMessage(), ex);
463 }
catch (
final SocketException ex) {
487 assert Thread.currentThread() ==
thread;
492 final boolean notifyListeners;
497 if (notifyListeners) {
512 }
catch (
final IOException ignored) {
519 }
catch (
final IOException ignored) {
528 if (notifyListeners) {
531 clientSocketListener.disconnected(reason);
548 throw new EOFException(
"EOF");
578 packet.order(ByteOrder.BIG_ENDIAN);
581 clientSocketListener.packetReceived(packet);
610 }
catch (
final BufferOverflowException ex) {
611 throw new IOException(
"buffer overflow", ex);
613 }
catch (
final IOException ignored) {
616 }
catch (
final IOException ignore) {
625 clientSocketListener.packetSent(monitor);
659 final int newInterestOps;
662 newInterestOps =
interestOps|SelectionKey.OP_WRITE;
664 newInterestOps =
interestOps&~SelectionKey.OP_WRITE;
final Object syncOutput
Synchronization object for outputBuffer, selectionKey, interestOps, and socketChannel.
void start()
Starts operation.
A socket that processes incoming data.
final EventListenerList2< ClientSocketListener > clientSocketListeners
The ClientSocketListeners to notify.
final DebugWriter debugProtocol
The appender to write state changes to.
void connect(@NotNull final String host, final int port)
Connects to a server.
void processReadCommand()
Parses data from inputBuffer into commands.
void process()
Reads/writes data from/to the socket.
int port
The port to connect to.
void doTransceive()
Processes pending data to receive of transmit.
void writePacket(final byte @NotNull[] buf, final int len, @NotNull final ClientSocketMonitorCommand monitor)
Writes a packet.
void processDisconnect(@NotNull final String reason, final boolean isError)
Disconnects the socket.
void processRead()
Reads data from the socket and parses the data into commands.
void disconnecting(@NotNull final String reason, final boolean isError)
Called when the connection is being torn down.
void doConnect()
Processes pending connect requests.
A list of event listeners.
int interestOps
The currently set interest ops for selectionKey.
final GuiStateManager guiStateManager
The GuiStateManager instance that is updated.
void updateInterestOps()
Updates selectionKey's interest ops to match interestOps.
void updateWriteInterestOps()
Updates interestOps's OP_WRITE according to whether outputBuffer has pending data.
void debugProtocolWrite(@NotNull final CharSequence str)
Writes a message to the debug protocol.
SocketChannel socketChannel
The SocketChannel when connected.
Maintains the current GuiState.
SelectionKey selectionKey
The SelectionKey registered to selectableChannel.
void doReconnect()
Processes pending re- or disconnect requests.
final byte[] inputBuf
The receive buffer.
final Selector selector
The Selector used for waiting.
boolean isConnected
Whether socketChannel is connected.
static final int MAXIMUM_PACKET_SIZE
The maximum payload size of a Crossfire protocol packet.
boolean disconnectPending
If set, notify listeners.
String reconnectReason
Only valid if reconnect is set.
SelectableChannel selectableChannel
The SelectableChannel of socketChannel.
final Object syncConnect
Synchronization object for reconnect, host, port, and disconnectPending.
void processWrite()
Writes some pending data to the socket.
Interface for listeners interested in ClientSocket related events.
void processConnect(@NotNull final String host, final int port)
Connects the socket.
void disconnect(@NotNull final String reason, final boolean isError)
Terminates the connection.
final ByteBuffer inputBuffer
The receive buffer.
void disconnected()
Called after the connection has been closed.
An UnknownCommandException is generated whenever an unknown message packet is received from the serve...
Interface for querying monitor commands for script processes.
final byte[] packetHeader
A buffer for sending packets.
Writer debug information to a log file.
ClientSocket(@NotNull final GuiStateManager guiStateManager, @Nullable final DebugWriter debugProtocol)
Creates a new instance.
boolean reconnect
Set if host or port has changed and thus a reconnect is needed.
boolean reconnectIsError
Only valid if reconnect is set.
final ByteBuffer outputBuffer
The output buffer.
void stop()
Stops operation.
final Thread thread
The Thread used to operate the socket.
void addClientSocketListener(@NotNull final ClientSocketListener clientSocketListener)
Adds a ClientSocketListener to be notified.
void removeClientSocketListener(@NotNull final ClientSocketListener clientSocketListener)
Removes a ClientSocketListener to be notified.
String host
The host to connect to.