Partial work on client protobuf-ization

main
Mari 3 years ago
parent 44b2813922
commit 54b9112546
  1. 1
      .idea/hexmap.iml
  2. 2
      client/src/actions/ClientAction.ts
  3. 6
      client/src/actions/ServerAction.ts
  4. 3
      client/src/state/NetworkState.ts
  5. 6
      client/src/websocket/ClientToPb.ts
  6. 96
      client/src/websocket/WebsocketTranslator.ts

@ -13,7 +13,6 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/mage" />
<excludeFolder url="file://$MODULE_DIR$/buildtools" />
<excludeFolder url="file://$MODULE_DIR$/client/src/proto" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

@ -58,7 +58,7 @@ export function isClientCommand(action: AppAction): action is ClientCommand {
return isClientHelloCommand(action) || isClientRefreshCommand(action) || isClientActCommand(action)
}
export type ClientAction = ClientHelloCommand | ClientRefreshCommand | ClientPendingAction | ClientActCommand
export type ClientAction = ClientCommand | ClientPendingAction
export function isClientAction(action: AppAction): action is ClientAction {
return isClientCommand(action) || isClientPendingAction(action)
}

@ -20,10 +20,10 @@ export const SERVER_GOODBYE = "SERVER_GOODBYE"
/** Synthesized out of the close message when the server closes the connection. */
export interface ServerGoodbyeCommand extends BaseAction {
readonly type: typeof SERVER_GOODBYE
/** The error code sent with the close message by the server, or -1 if our side crashed.*/
/** The exit code sent with the close message by the server. */
readonly code: number
/** The text of the server's goodbye message, or the exception if our side crashed. */
readonly reason: string|Error
/** The text of the server's goodbye message. */
readonly reason: string
/** The current time when this close message was received. */
readonly currentTime: Date
}

@ -50,14 +50,13 @@ export interface NetworkState {
/**
* The error code of the close message.
* Non-null if and only if the current state is OFFLINE or REJECTED.
* -1 means no onClose was called, and the reason is a stringized error from onError instead.
*/
readonly goodbyeCode: number | null
/**
* The error reason of the close message.
* Non-null if and only if the current state is OFFLINE or REJECTED.
*/
readonly goodbyeReason: string | Error | null
readonly goodbyeReason: string | null
/** The time the client will attempt to reconnect, if at all. */
readonly autoReconnectAt: Date | null
/** The number of attempts at reconnecting. */

@ -0,0 +1,6 @@
import {ClientCommand} from "../actions/ClientAction";
import {ClientCommandPB} from "../proto/client";
export function clientToPb(message: ClientCommand): ClientCommandPB {
}

@ -0,0 +1,96 @@
/** Translates between websocket messages and Commands. */
import {ClientCommand} from "../actions/ClientAction";
import {
SERVER_GOODBYE,
SERVER_SOCKET_STARTUP,
ServerCommand,
ServerGoodbyeCommand,
ServerSocketStartupAction,
SocketState
} from "../actions/ServerAction";
class WebsocketTranslator {
readonly url: string
readonly protocols: readonly string[]
readonly onStartup: (startup: ServerSocketStartupAction) => void
readonly onMessage: (command: ServerCommand) => void
readonly onGoodbye: (goodbye: ServerGoodbyeCommand) => void
private socket: WebSocket|null
constructor({
url,
protocols,
onStartup,
onMessage,
onGoodbye
}: {
url: string,
protocols: readonly string[],
onStartup: (startup: ServerSocketStartupAction) => void,
onMessage: (command: ServerCommand) => void,
onGoodbye: (goodbye: ServerGoodbyeCommand) => void
}) {
this.url = url
this.protocols = protocols.slice()
this.onStartup = onStartup
this.onMessage = onMessage
this.onGoodbye = onGoodbye
this.socket = null
}
connect() {
if (this.socket != null) {
throw Error("Already running")
}
this.socket = new WebSocket(this.url, this.protocols.slice())
this.socket.addEventListener("open", this.handleOpen)
this.socket.addEventListener("message", this.handleMessage)
this.socket.addEventListener("close", this.handleClose)
this.socket.addEventListener("error", WebsocketTranslator.handleError)
this.onStartup({
type: SERVER_SOCKET_STARTUP,
state: SocketState.CONNECTING,
})
}
send(message: ClientCommand) {
// TODO: Protoitize the client message and send() it.
}
close(code: number, reason: string) {
this.socket?.close(code, reason)
}
private handleOpen(e: Event) {
this.onStartup({
type: SERVER_SOCKET_STARTUP,
state: SocketState.OPEN,
})
}
private handleMessage(e: MessageEvent) {
// TODO: Parse the server message and pass it to onMessage.
}
private handleClose(e: CloseEvent) {
this.onGoodbye({
type: SERVER_GOODBYE,
code: e.code,
reason: e.reason,
currentTime: new Date(),
})
this.clearSocket()
}
private static handleError(e: Event) {
console.log("Websocket error: ", e)
}
private clearSocket() {
this.socket?.removeEventListener("open", this.handleOpen)
this.socket?.removeEventListener("message", this.handleMessage)
this.socket?.removeEventListener("close", this.handleClose)
this.socket?.removeEventListener("error", WebsocketTranslator.handleError)
this.socket = null
}
}
Loading…
Cancel
Save