added rtmt
This commit is contained in:
parent
c3d8f5377d
commit
c18469ac7d
@ -1,6 +1,9 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
|
import { initContext } from './context';
|
||||||
|
|
||||||
import Counter from './Counter';
|
import Home from './Home';
|
||||||
|
|
||||||
render(<Counter />, document.getElementById('main'));
|
initContext();
|
||||||
|
|
||||||
|
render(<Home />, document.getElementById('main'));
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
export default class Counter extends React.Component {
|
|
||||||
state = {
|
|
||||||
count: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
increment = () => {
|
|
||||||
this.setState({
|
|
||||||
count: (this.state.count + 1)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
startConnection = () => {
|
|
||||||
const ws = new WebSocket("ws://localhost:5000");
|
|
||||||
ws.onopen = (event : Event)=>{
|
|
||||||
console.log("onopen");
|
|
||||||
ws.send("Messgage from client");
|
|
||||||
}
|
|
||||||
ws.onmessage = (event : MessageEvent) =>{
|
|
||||||
console.log(event.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>{this.state.count}</h1>
|
|
||||||
<button onClick={this.startConnection}>Start Connection</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
src/Home.tsx
Normal file
35
src/Home.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { FunctionComponent, useState } from 'react';
|
||||||
|
import {context} from './context'
|
||||||
|
import { RTMTWS } from './rtmt/rtmt_websocket';
|
||||||
|
|
||||||
|
const Home:FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
||||||
|
const [clicks, setClicks] = useState(initial);
|
||||||
|
|
||||||
|
React.useEffect(()=>{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const rtmtws = context.rtmt as RTMTWS
|
||||||
|
if(rtmtws){
|
||||||
|
rtmtws.initWebSocket(onConnectionDone)
|
||||||
|
}else{
|
||||||
|
console.log("context.rtmt is not RTMTWS");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onConnectionDone = ()=>{
|
||||||
|
context.rtmt.sendMessage("new_game", "")
|
||||||
|
context.rtmt.listenMessage("new_game", (message)=>{
|
||||||
|
console.log("new message");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<p>Clicks: {clicks}</p>
|
||||||
|
<button onClick={() => setClicks(clicks+1)}>+</button>
|
||||||
|
<button onClick={() => setClicks(clicks-1)}>-</button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home
|
||||||
19
src/context.tsx
Normal file
19
src/context.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { RTMT } from "./rtmt/rtmt"
|
||||||
|
import { RTMTWS } from "./rtmt/rtmt_websocket"
|
||||||
|
import { UserKeyStore, UserKeyStoreImpl } from "./store/key_store"
|
||||||
|
|
||||||
|
type Context = {
|
||||||
|
rtmt : RTMT
|
||||||
|
userKeyStore : UserKeyStore
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initContext = ()=> {
|
||||||
|
const rtmt = new RTMTWS()
|
||||||
|
const userKeyStore = new UserKeyStoreImpl()
|
||||||
|
return {
|
||||||
|
rtmt : rtmt,
|
||||||
|
userKeyStore : userKeyStore,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const context : Context = initContext()
|
||||||
12
src/rtmt/byte_util.ts
Normal file
12
src/rtmt/byte_util.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Bytes } from "./rtmt"
|
||||||
|
const textEncoder = new TextEncoder()
|
||||||
|
const textDecoder = new TextDecoder("utf-8")
|
||||||
|
|
||||||
|
export function encodeText(text : string) {
|
||||||
|
const bytes = textEncoder.encode(text)
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decodeText(bytes : Bytes) {
|
||||||
|
return textDecoder.decode(bytes)
|
||||||
|
}
|
||||||
52
src/rtmt/encode_decode_message.ts
Normal file
52
src/rtmt/encode_decode_message.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { decodeText, encodeText } from "./byte_util";
|
||||||
|
import { Bytes } from "./rtmt";
|
||||||
|
|
||||||
|
const headerLenght = 4
|
||||||
|
//
|
||||||
|
// channel is string, message is byte array
|
||||||
|
//
|
||||||
|
export function encode(channel : string, message : Bytes) {
|
||||||
|
const channelLenght = channel.length
|
||||||
|
const messageLenght = message.length
|
||||||
|
const totalLenght = headerLenght + channelLenght + messageLenght
|
||||||
|
|
||||||
|
const buffer = new ArrayBuffer(totalLenght);
|
||||||
|
const view = new DataView(buffer);
|
||||||
|
|
||||||
|
view.setUint32(0, channelLenght);
|
||||||
|
|
||||||
|
const channelBytes = encodeText(channel)
|
||||||
|
|
||||||
|
let count = headerLenght
|
||||||
|
channelBytes.forEach((byte)=>{
|
||||||
|
view.setUint8(count, byte)
|
||||||
|
count++
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const byte of message) {
|
||||||
|
view.setUint8(count, byte)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// return { channel : string, message : byte array}
|
||||||
|
//
|
||||||
|
export function decode(bytes : Bytes) {
|
||||||
|
const view = new DataView(bytes);
|
||||||
|
|
||||||
|
const channelLenght = view.getUint32(0)
|
||||||
|
|
||||||
|
|
||||||
|
const channel = decodeText(
|
||||||
|
bytes.slice(headerLenght, headerLenght + channelLenght))
|
||||||
|
|
||||||
|
const message = bytes.slice(headerLenght + channelLenght)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"channel": channel,
|
||||||
|
"message": message,
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/rtmt/rtmt.ts
Normal file
7
src/rtmt/rtmt.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export type Bytes = UInt8Array
|
||||||
|
export type OnMessage = (message : Bytes) => any
|
||||||
|
|
||||||
|
export interface RTMT{
|
||||||
|
sendMessage : (channel : string, message : Bytes) => any
|
||||||
|
listenMessage : (channel : string, callback : OnMessage) => any
|
||||||
|
}
|
||||||
70
src/rtmt/rtmt_websocket.ts
Normal file
70
src/rtmt/rtmt_websocket.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { decode, encode } from "./encode_decode_message"
|
||||||
|
import { OnMessage, RTMT } from "./rtmt"
|
||||||
|
import { context } from '../context';
|
||||||
|
import { wsServerAdress } from "../service/http_service";
|
||||||
|
|
||||||
|
export class RTMTWS implements RTMT{
|
||||||
|
|
||||||
|
private messageChannels : Map<String,OnMessage>
|
||||||
|
private ws : WebSocket
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.messageChannels = new Map<String, OnMessage>()
|
||||||
|
}
|
||||||
|
|
||||||
|
initWebSocket(onopen : ()=>any) {
|
||||||
|
context.userKeyStore.getUserKey((userKey : string)=>{
|
||||||
|
const url = wsServerAdress + '?userKey=' + userKey
|
||||||
|
const ws = new WebSocket(url)
|
||||||
|
ws.binaryType = "arraybuffer"; //for firefox
|
||||||
|
ws.onopen = () => {
|
||||||
|
console.log('ws has opened')
|
||||||
|
this.ws = ws
|
||||||
|
onopen()
|
||||||
|
}
|
||||||
|
ws.onclose = () => {
|
||||||
|
console.log('ws has closed')
|
||||||
|
//this.ws = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onmessage = (event : MessageEvent)=>{
|
||||||
|
this.onWebSocketMessage(this, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.addEventListener("error", ev => {
|
||||||
|
console.log({ ws_error: ev });
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(channel : string, message : Int8Array) {
|
||||||
|
if(this.ws === undefined){
|
||||||
|
console.log('ws is undefined')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data = encode(channel, message)
|
||||||
|
console.log("(RTMT) Sending message to channel " + channel);
|
||||||
|
this.ws.send(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
listenMessage(channel : string, callback : OnMessage) {
|
||||||
|
this.messageChannels.set(channel, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
onWebSocketMessage(rtmt : RTMTWS, event : MessageEvent) {
|
||||||
|
console.log(event);
|
||||||
|
|
||||||
|
const { channel, message } = decode(event.data)
|
||||||
|
rtmt.onMessage(channel, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(channel : string, message : Int8Array){
|
||||||
|
const callback = this.messageChannels.get(channel)
|
||||||
|
|
||||||
|
if(callback){
|
||||||
|
callback(message)
|
||||||
|
}else{
|
||||||
|
console.log("Channel callback not found!" + channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user