added rtmt

This commit is contained in:
jhalitaksoy 2021-06-27 19:28:55 +03:00
parent c3d8f5377d
commit c18469ac7d
8 changed files with 200 additions and 35 deletions

View File

@ -1,6 +1,9 @@
import * as React from 'react';
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'));

View File

@ -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
View 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
View 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
View 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)
}

View 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
View 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
}

View 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);
}
}
}