Skip to content

Commit

Permalink
made rooms on websocket server
Browse files Browse the repository at this point in the history
  • Loading branch information
denbite committed Jan 15, 2021
1 parent 594ef30 commit f55ee3c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 55 deletions.
59 changes: 40 additions & 19 deletions backend/websocket/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,76 @@


class Server:
clients = set()
# {
# 'board_url': set(...)
# }
clients = {}

async def register(self, ws: WebSocketServerProtocol) -> None:
self.clients.add(ws)
async def register(self, ws: WebSocketServerProtocol, board_url: str) -> None:
if board_url not in self.clients:
self.clients[board_url] = set()

self.clients[board_url].add(ws)
logging.info("{} connected".format(ws.remote_address))

async def unregister(self, ws: WebSocketServerProtocol) -> None:
async def unregister(self, ws: WebSocketServerProtocol, board_url: str) -> None:
await ws.close()
self.clients.remove(ws)
self.clients[board_url].remove(ws)
logging.info("{} disconnected".format(ws.remote_address))

if not self.clients[board_url]:
self.clients.pop(board_url)

async def main_handler(self, ws: WebSocketServerProtocol, uri: str) -> None:

logging.info("uri: {} handled from {}".format(uri, ws.remote_address))
if uri != "/board":

if not uri.startswith("/board/"):
await ws.close()

board_url = uri[7:]

if ws not in self.clients:
await self.register(ws)
await self.register(ws, board_url)

try:
await self.distribute(ws)
await self.distribute(ws, board_url)
except:
pass
finally:
await self.unregister(ws)
await self.unregister(ws, board_url)

async def distribute(self, ws: WebSocketServerProtocol) -> None:
async def distribute(self, ws: WebSocketServerProtocol, board_url: str) -> None:
async for message in ws:
await self.send_to_clients(message, ws)
await self.send_to_clients(message, ws, board_url)
logging.info(
"received message: {} from {}".format(message, ws.remote_address)
)

async def send_to_clients(
self, message: str, current_ws: WebSocketServerProtocol
self, message: str, current_ws: WebSocketServerProtocol, board_url: str
) -> None:
if self.clients and len(self.clients) > 1:
if (
board_url in self.clients
and self.clients[board_url]
and len(self.clients[board_url]) > 1
):
await asyncio.wait(
[
client.send(message)
for client in self.clients
for client in self.clients[board_url]
if client != current_ws
]
)


server = Server()
start_server = websockets.serve(server.main_handler, "0.0.0.0", 8001)
loop = asyncio.get_event_loop()
loop.run_until_complete(start_server)
loop.run_forever()
def start():
server = Server()
start_server = websockets.serve(server.main_handler, "0.0.0.0", 8001)
loop = asyncio.get_event_loop()
loop.run_until_complete(start_server)
loop.run_forever()


if __name__ == "__main__":
start()
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ services:
api:
build: ./backend/api
restart: always
# command: gunicorn entry:app --bind 0.0.0.0:8000 --reload
command: python3 entry.py
command: gunicorn entry:app --bind 0.0.0.0:8000 --reload
# command: python3 entry.py
ports:
- 8000:8000
volumes:
Expand Down
64 changes: 31 additions & 33 deletions frontend/components/Toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import {changeBrushColor, changeBrushWidth} from '../store/toolbar/actions';
import { clearBoard } from '../store/board/actions';
import * as actions from '../store/toolbar/constants';

class Toolbar extends React.Component{
saveCanvas = (event) => {
export const Toolbar = props => {
function saveCanvas (event) {
console.log('clicked!');
}

clearBoard = (event) => {
this.props.clearBoard();
function clearBoard (event) {
props.clearBoard();

if (!this.props.websocket || !this.props.url) return;
if (!props.websocket || !props.url) return;

fetch('http://192.168.0.100:8000/api/board', {
method:'PUT',
Expand All @@ -22,14 +22,14 @@ class Toolbar extends React.Component{
'Accept': 'application/json'
},
body: new URLSearchParams({
board_url: this.props.url,
board_url: props.url,
action: "BOARD_CLEAR"
})
})
.then(r => r.json())
.then(response => {
if (response.success){
this.props.websocket.send(JSON.stringify({
props.websocket.send(JSON.stringify({
action: 'clearBoard'
}))
} else {
Expand All @@ -38,33 +38,31 @@ class Toolbar extends React.Component{
})
}

render(){
return (
<div className={styles.toolbar}>
<div className={styles.toolbarBlock}>
- Операции -<br/>
<button className={styles.saveButton} id="saveButton" onClick={this.saveCanvas}>
Поделиться
</button>
<button className={styles.clearButton} id="clearButton" onClick={this.clearBoard}>
Очистить
</button>
</div>
<div className={styles.toolbarBlock}>
- Цвет -<br/>
<img onClick={e => this.props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_RED)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_red.gif" />
<img onClick={e => this.props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_GREEN)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_green.gif" />
<img onClick={e => this.props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_BLUE)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_blue.gif" />
</div>
<div className={styles.toolbarBlock}>
- Толщина -<br/>
<img onClick={e => this.props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_LOW)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_thin.gif" />
<img onClick={e => this.props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_MIDDLE)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_medium.gif" />
<img onClick={e => this.props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_BIG)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_thick.gif" />
</div>
return (
<div className={styles.toolbar}>
<div className={styles.toolbarBlock}>
- Операции -<br/>
<button className={styles.saveButton} id="saveButton" onClick={saveCanvas}>
Поделиться
</button>
<button className={styles.clearButton} id="clearButton" onClick={clearBoard}>
Очистить
</button>
</div>
)
}
<div className={styles.toolbarBlock}>
- Цвет -<br/>
<img onClick={e => props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_RED)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_red.gif" />
<img onClick={e => props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_GREEN)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_green.gif" />
<img onClick={e => props.changeBrushColor(actions.TOOLBAR_BRUSH_COLOR_BLUE)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_blue.gif" />
</div>
<div className={styles.toolbarBlock}>
- Толщина -<br/>
<img onClick={e => props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_LOW)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_thin.gif" />
<img onClick={e => props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_MIDDLE)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_medium.gif" />
<img onClick={e => props.changeBrushWidth(actions.TOOLBAR_BRUSH_WIDTH_BIG)} className={styles.toolbarImgButton} src="http://professorweb.ru/downloads/pen_thick.gif" />
</div>
</div>
)
}

const mapDispatchToProps = {
Expand Down
2 changes: 1 addition & 1 deletion frontend/pages/b/[board_url].js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function SyncBoard() {
}
})

const websocket = new WebSocket("ws://192.168.0.100:8001/board");
const websocket = new WebSocket("ws://192.168.0.100:8001/board/" + board_url);

websocket.onmessage = function (event) {

Expand Down

0 comments on commit f55ee3c

Please sign in to comment.