-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Gagandeep
authored and
Gagandeep
committed
Aug 17, 2022
1 parent
21d9ccb
commit 6f8a2cc
Showing
8 changed files
with
294 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.idea/ | ||
|
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,3 @@ | ||
simple-websocket-server===0.4.2 | ||
websockets===10.3 | ||
streamlit |
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,98 @@ | ||
import asyncio | ||
import json | ||
import ssl | ||
import time | ||
import uuid | ||
|
||
import certifi | ||
import streamlit as st | ||
import streamlit.components.v1 as components | ||
import websockets | ||
|
||
|
||
def getOrCreateUID(): | ||
if 'uid' not in st.session_state: | ||
st.session_state['uid'] = '' | ||
st.session_state['uid'] = st.session_state['uid'] or str(uuid.uuid1()) | ||
print ('getOrCreateUID: ', st.session_state['uid']) | ||
return st.session_state['uid'] | ||
|
||
|
||
# Generate a unique uid that gets embedded in components.html for frontend | ||
# Both frontend and server connect to ws using the same uid | ||
# server sends commands like localStorage_get_key, localStorage_set_key, localStorage_clear_key etc. to the WS server, | ||
# which relays the commands to the other connected endpoint (the frontend), and back | ||
def injectWebsocketCode(hostPort, uid): | ||
code = '<script>function connect() { console.log("in connect uid: ", "' + uid + '"); var ws = new WebSocket("wss://' + hostPort + '/?uid=' + uid + '");' + """ | ||
ws.onopen = function() { | ||
// subscribe to some channels | ||
// ws.send(JSON.stringify({ status: 'connected' })); | ||
console.log("onopen"); | ||
}; | ||
ws.onmessage = function(e) { | ||
console.log('Message:', e.data); | ||
var obj = JSON.parse(e.data); | ||
if (obj.cmd == 'localStorage_get_key') { | ||
var val = localStorage[obj.key] || ''; | ||
ws.send(JSON.stringify({ status: 'success', val })); | ||
console.log('returning: ', val); | ||
} else if (obj.cmd == 'localStorage_set_key') { | ||
localStorage[obj.key] = obj.val; | ||
ws.send(JSON.stringify({ status: 'success' })); | ||
console.log('set: ', obj.key, obj.val); | ||
} | ||
}; | ||
ws.onclose = function(e) { | ||
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason); | ||
setTimeout(function() { | ||
connect(); | ||
}, 1000); | ||
}; | ||
ws.onerror = function(err) { | ||
console.error('Socket encountered error: ', err.message, 'Closing socket'); | ||
ws.close(); | ||
}; | ||
} | ||
connect(); | ||
</script> | ||
""" | ||
components.html(code, height=0) | ||
time.sleep(1) # Without sleep there are problems | ||
return WebsocketClient(hostPort, uid) | ||
|
||
|
||
class WebsocketClient: | ||
def __init__(self, hostPort, uid): | ||
self.hostPort = hostPort | ||
self.uid = uid | ||
self.loop = asyncio.new_event_loop() | ||
asyncio.set_event_loop(self.loop) | ||
|
||
def sendCommand(self, value): | ||
ssl_context = ssl.create_default_context() | ||
ssl_context.load_verify_locations(certifi.where()) | ||
|
||
async def query(future): | ||
async with websockets.connect("wss://" + self.hostPort + "/?uid=" + self.uid, ssl=ssl_context) as ws: | ||
await ws.send(value) | ||
response = await ws.recv() | ||
print('response: ', response) | ||
future.set_result(response) | ||
|
||
future1 = asyncio.Future() | ||
self.loop.run_until_complete(query(future1)) | ||
print('future1.result: ', future1.result()) | ||
return future1.result() | ||
|
||
def getLocalStorageVal(self, key): | ||
result = self.sendCommand(json.dumps({ 'cmd': 'localStorage_get_key', 'key': key })) | ||
return json.loads(result)['val'] | ||
|
||
def setLocalStorageVal(self, key, val): | ||
result = self.sendCommand(json.dumps({ 'cmd': 'localStorage_set_key', 'key': key, 'val': val })) | ||
return result | ||
|
Empty file.
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,108 @@ | ||
<!DOCTYPE html> | ||
|
||
<meta charset="utf-8" /> | ||
|
||
<title>WebSocket Test</title> | ||
|
||
<script language="javascript" type="text/javascript"> | ||
|
||
|
||
function init() | ||
{ | ||
document.myform.url.value = "ws://localhost:8000/" | ||
document.myform.inputtext.value = "Hello World!" | ||
document.myform.disconnectButton.disabled = true; | ||
} | ||
|
||
function doConnect() | ||
{ | ||
websocket = new WebSocket(document.myform.url.value); | ||
websocket.onopen = function(evt) { onOpen(evt) }; | ||
websocket.onclose = function(evt) { onClose(evt) }; | ||
websocket.onmessage = function(evt) { onMessage(evt) }; | ||
websocket.onerror = function(evt) { onError(evt) }; | ||
} | ||
|
||
function onOpen(evt) | ||
{ | ||
writeToScreen("connected\n"); | ||
document.myform.connectButton.disabled = true; | ||
document.myform.disconnectButton.disabled = false; | ||
} | ||
|
||
function onClose(evt) | ||
{ | ||
writeToScreen("disconnected\n"); | ||
document.myform.connectButton.disabled = false; | ||
document.myform.disconnectButton.disabled = true; | ||
} | ||
|
||
function onMessage(evt) | ||
{ | ||
writeToScreen("response: " + evt.data + '\n'); | ||
} | ||
|
||
function onError(evt) | ||
{ | ||
writeToScreen('error: ' + evt.data + '\n'); | ||
|
||
websocket.close(); | ||
|
||
document.myform.connectButton.disabled = false; | ||
document.myform.disconnectButton.disabled = true; | ||
|
||
} | ||
|
||
function doSend(message) | ||
{ | ||
writeToScreen("sent: " + message + '\n'); | ||
websocket.send(message); | ||
} | ||
|
||
function writeToScreen(message) | ||
{ | ||
document.myform.outputtext.value += message | ||
document.myform.outputtext.scrollTop = document.myform.outputtext.scrollHeight; | ||
|
||
} | ||
|
||
window.addEventListener("load", init, false); | ||
|
||
|
||
function sendText() { | ||
doSend( document.myform.inputtext.value ); | ||
} | ||
|
||
function clearText() { | ||
document.myform.outputtext.value = ""; | ||
} | ||
|
||
function doDisconnect() { | ||
websocket.close(); | ||
} | ||
|
||
|
||
</script> | ||
|
||
<div id="output"></div> | ||
|
||
<form name="myform"> | ||
<p> | ||
<textarea name="outputtext" rows="20" cols="50"></textarea> | ||
</p> | ||
<p> | ||
<textarea name="inputtext" cols="50"></textarea> | ||
</p> | ||
<p> | ||
<textarea name="url" cols="50"></textarea> | ||
</p> | ||
<p> | ||
<input type="button" name=sendButton value="Send" onClick="sendText();"> | ||
<input type="button" name=clearButton value="Clear" onClick="clearText();"> | ||
<input type="button" name=disconnectButton value="Disconnect" onClick="doDisconnect();"> | ||
<input type="button" name=connectButton value="Connect" onClick="doConnect();"> | ||
</p> | ||
|
||
|
||
</form> | ||
</html> |
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,24 @@ | ||
import asyncio | ||
import ssl | ||
|
||
import certifi | ||
import websockets | ||
|
||
|
||
def main(): | ||
ssl_context = ssl.create_default_context() | ||
ssl_context.load_verify_locations(certifi.where()) | ||
|
||
async def query(future): | ||
async with websockets.connect("wss://linode.liquidco.in/?uid=21", ssl=ssl_context) as ws: | ||
await ws.send('{"cmd":"echo","msg":"hi4"}') | ||
response = await ws.recv() | ||
print ('response: ', response) | ||
future.set_result(response) | ||
|
||
future1 = asyncio.Future() | ||
asyncio.run(query(future1)) | ||
print ('future1.result: ', future1.result()) | ||
|
||
|
||
main() |
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,58 @@ | ||
import json | ||
from urllib.parse import urlparse, parse_qs | ||
|
||
from simple_websocket_server import WebSocketServer, WebSocket | ||
|
||
|
||
# Generate a unique uid that gets embedded in components.html for frontend | ||
# Both frontend and server connect to ws using the same uid | ||
# server sends commands like localStorage_get_key, localStorage_set_key, localStorage_clear_key etc. | ||
class SimpleChat(WebSocket): | ||
uid: str = None | ||
|
||
def handle(self): | ||
print ('handle: ', self.uid, self.data, self.address) | ||
|
||
# Echo back | ||
try: | ||
obj = json.loads(self.data) | ||
if 'cmd' in obj and obj['cmd'] == 'echo': | ||
self.send_message(self.data) | ||
except: | ||
print ('exception in handle, ignoring') | ||
|
||
for client in clients[self.uid]: | ||
if client != self: | ||
client.send_message(self.data) | ||
|
||
def connected(self): | ||
print('connected: ', self.address, self.request.path) | ||
self.uid = self.request.path | ||
try: | ||
parsed_url = urlparse(self.request.path) | ||
d = parse_qs(parsed_url.query) | ||
if 'uid' in d and len(d['uid']) > 0: | ||
self.uid = d['uid'][0] | ||
else: | ||
self.send_message('No uid found') | ||
self.close(1, 'No uid found') | ||
return | ||
except: | ||
self.send_message('Exception') | ||
self.close(2, 'Exception') | ||
return | ||
|
||
if self.uid not in clients: | ||
clients[self.uid] = [] | ||
clients[self.uid].append(self) | ||
|
||
def handle_close(self): | ||
print ('handle_close: ', self.uid, self.address) | ||
clients[self.uid].remove(self) | ||
print(self.address, 'closed') | ||
|
||
|
||
clients = dict() | ||
|
||
server = WebSocketServer('0.0.0.0', 8001, SimpleChat) | ||
server.serve_forever() |