-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Preliminary WS server implementation. - Minor version bump.
- Loading branch information
Showing
12 changed files
with
512 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package io.vacco.tokoeka; | ||
|
||
import io.vacco.tokoeka.spi.TkSocketHdl; | ||
import io.vacco.tokoeka.util.*; | ||
import org.slf4j.*; | ||
import java.io.*; | ||
import java.net.*; | ||
import java.util.concurrent.*; | ||
import java.util.function.*; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
import static io.vacco.tokoeka.util.TkSockets.*; | ||
|
||
public class TkSocketServer implements Closeable { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(TkSocketServer.class); | ||
|
||
private final int port; | ||
private final TkSocketHdl socketHdl; | ||
private final Supplier<TkSocketState> stateFn; | ||
private final ExecutorService clientThreadPool = Executors.newCachedThreadPool(); | ||
|
||
private ServerSocket serverSocket; | ||
|
||
public TkSocketServer(int port, TkSocketHdl socketHdl, Supplier<TkSocketState> stateFn) { | ||
this.port = port; | ||
this.stateFn = requireNonNull(stateFn); | ||
this.socketHdl = requireNonNull(socketHdl); | ||
} | ||
|
||
public void start() { | ||
try { | ||
serverSocket = new ServerSocket(port); | ||
log.info("WebSocket server started on port {}", port); | ||
while (!serverSocket.isClosed()) { | ||
var clientSocket = serverSocket.accept(); | ||
clientThreadPool.submit(() -> handleClient(clientSocket)); | ||
} | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Unable to start websocket server", e); | ||
} | ||
} | ||
|
||
private void handleClient(Socket clientSocket) { | ||
log.debug("Incoming connection: {}", clientSocket); | ||
try { | ||
var inputStream = clientSocket.getInputStream(); | ||
var outputStream = clientSocket.getOutputStream(); | ||
var socketState = this.stateFn.get(); | ||
var handShake = wsServerHandShakeOf(inputStream); | ||
var handshakeResponse = performHandshake(handShake, outputStream); | ||
if (handshakeResponse != null) { | ||
var conn = new TkConnAdapter( | ||
clientSocket, socketState, | ||
msg -> send(msg, outputStream), | ||
(code, msg) -> { | ||
|
||
} | ||
); | ||
this.socketHdl.onOpen(conn, handshakeResponse); | ||
while (!clientSocket.isClosed()) { | ||
var stop = handleMessage(this.socketHdl, socketState, conn, inputStream, outputStream); | ||
if (stop) { | ||
break; | ||
} | ||
} | ||
} else { | ||
throw new IllegalStateException("Incoming connection - missing handshake response " + clientSocket); | ||
} | ||
} catch (Exception e) { | ||
log.error("Incoming connection handler error - {}", clientSocket.getRemoteSocketAddress(), e); | ||
} finally { | ||
try { | ||
clientSocket.close(); | ||
} catch (IOException e) { | ||
log.warn("Incoming connection close error - {}", e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
@Override public void close() { | ||
clientThreadPool.shutdown(); | ||
if (serverSocket != null) { | ||
try { | ||
serverSocket.close(); | ||
} catch (Exception e) { | ||
log.warn("Websocket server close error - {}", e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package io.vacco.tokoeka.spi; | ||
|
||
import java.io.Closeable; | ||
import java.net.Socket; | ||
import java.util.function.Consumer; | ||
|
||
public interface TkConn extends Consumer<String>, Closeable { | ||
void setAttachment(Object attachment); | ||
<T> T getAttachment(); | ||
Socket getSocket(); | ||
void close(int code); | ||
void close(int code, String msg); | ||
} |
Oops, something went wrong.