From 8d698d7fef3c8dde33abf522e10df1385fbf1024 Mon Sep 17 00:00:00 2001 From: Yessiest Date: Fri, 12 May 2023 01:41:59 +0400 Subject: [PATCH] websocket events --- Gemfile | 9 ++++++ client.rb | 35 +++++++++++++++------ hyde | 2 +- proto.rb | 3 ++ server.rb | 92 +++++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 Gemfile diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..e946e86 --- /dev/null +++ b/Gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# gem "rails" +gem 'webrick' +gem 'mime-types' +gem 'webrick-websocket' + diff --git a/client.rb b/client.rb index a92bb46..b242e95 100755 --- a/client.rb +++ b/client.rb @@ -2,6 +2,7 @@ require 'readline' require 'net/http' require 'json' +require 'websocket-client-simple' require 'uri' puts "Connecting to server #{ARGV[0]} on port #{ARGV[1]}" def get(path) @@ -29,20 +30,34 @@ unless test.kind_of? Net::HTTPOK then exit end puts "Your id is: heimdall-#{nickname}" -Thread.new do - while true do - sleep 1 - messages = get("/user/read?protocol_id=#{"heimdall-"+nickname}") - if messages["error"] then - puts "Error: #{messages["error"]}" - next +puts "Establishing websocket connection..." +ws = WebSocket::Client::Simple.connect "ws://#{ARGV[0]}:#{ARGV[2]}" +ws.on :message do |msg| + data = JSON.parse(msg.data) + if data.has_key? "websocket" then + uid = data["websocket"] + response = post("/user/listen",{ + websocket: uid, + protocol_id: "heimdall-"+nickname + }) + unless response.kind_of? Net::HTTPOK then + puts "Something went wrong when initiating listening to user! Check server logs for info." end - messages["messages"].each { |x| - puts "#{x["user"]["username"]} says: #{x["content"]}" - } + elsif data.has_key? "error" then + puts "ERROR: #{data["error"]}" + else + puts "#{data["user"]["username"]}: #{data["content"]}" end end +ws.on :open do |msg| + puts "Websocket connection established" +end + +at_exit do + ws.close +end + target = nil at_exit do diff --git a/hyde b/hyde index f1f13fa..fd76422 160000 --- a/hyde +++ b/hyde @@ -1 +1 @@ -Subproject commit f1f13faddf0f4a454c0a13c28957e53146eb529c +Subproject commit fd76422b760e6c045581bcb11842ee42221d06e0 diff --git a/proto.rb b/proto.rb index 5d75cdb..2e63889 100644 --- a/proto.rb +++ b/proto.rb @@ -75,6 +75,9 @@ module Heimdall @messages.push(msg) @read = @read+1 end + def send_silent(msg) + @messages.push(msg) + end def get(n = 1) raise Heimdall::ProtocolError, "Invalid number of messages" if n < 0 return @messages.pull(n) diff --git a/server.rb b/server.rb index b505dde..dede92e 100644 --- a/server.rb +++ b/server.rb @@ -1,8 +1,11 @@ require_relative "proto" require_relative "hyde/hyde" +require 'webrick/websocket' require "json" Users = Heimdall::UserCache.new +SocketsMap = {} +NotifyList = {} def _require_keys(dict,key_dict) raise KeyError, "not a dict" unless dict.kind_of? Hash @@ -34,11 +37,6 @@ end server = Hyde::Server.new Port: 8000 do path "user" do - preprocess do |ctx| - puts ctx.request.query.inspect - puts ctx.request.body.inspect - end - path "find" do index ["by-username"] @@ -99,8 +97,9 @@ server = Hyde::Server.new Port: 8000 do new_user = Heimdall::User.new(data) Users.add(new_user) _send_json(res,{ - uid: new_user.UID + status: true }) + NotifyList[new_user.UID] = [] rescue JSON::ParserError => jsonerror _throw_error(res,jsonerror) rescue KeyError => keyerror @@ -117,9 +116,20 @@ server = Hyde::Server.new Port: 8000 do to: String }) new_message = Heimdall::Message.new(data) - Users.get(new_message.to).direct.send(new_message) + user = Users.get(new_message.to) + if NotifyList[user.UID].length != 0 then + NotifyList[user.UID].each { |sockid| + sock = SocketsMap[sockid] + msg = new_message.to_struct + msg["user"] = Users.get(msg["from"]).to_card + sock.puts(JSON::fast_generate(msg)) + } + user.direct.send_silent(new_message) + else + user.direct.send(new_message) + end _send_json(res,{ - uid: new_message.UID + status: true }) rescue JSON::ParserError => jsonerror _throw_error(res,jsonerror) @@ -174,6 +184,24 @@ server = Hyde::Server.new Port: 8000 do end end + post "listen" do |ctx| + req,res = ctx.request, ctx.response + begin + data = _parse_json(req.body, { + websocket: String, + protocol_id: String + }) + uid = Users.get(data["protocol_id"]).UID + raise KeyError, "websocket does not exist" unless SocketsMap.has_key? data["websocket"] + NotifyList[uid].append data["websocket"] + _send_json(res, { + status: true + }) + rescue KeyError => keyerror + _throw_error(res,keyerror) + end + end + post "delete" do |ctx| req,res = ctx.request, ctx.response begin @@ -182,8 +210,10 @@ server = Hyde::Server.new Port: 8000 do }) id = data["protocol_id"] _send_json(res, { - uid: Users.get(id).UID + status: true }) + user = Users.get(id) + NotifyList.delete(user.UID) Users.delete(id) rescue Heimdall::ProtocolError => protoerr _throw_error(res,protoerr) @@ -198,4 +228,48 @@ server = Hyde::Server.new Port: 8000 do end +at_exit do + server.shutdown +end + +class WebsocketUID < Heimdall::UID + def initialize + @UID_prefix = "websocket" + super + end +end + +class EventServlet < WEBrick::Websocket::Servlet + def socket_open(sock) + @UID = WebsocketUID.new + @connected_listeners = [] + SocketsMap[@UID.UID] = sock + sock.puts(JSON::fast_generate({ + websocket: @UID.UID.to_s + })) + end + + def socket_close(sock) + SocketsMap.delete @UID.UID + NotifyList.each do |k,v| + if v.include? @UID.UID + v.delete @UID.UID + end + end + end + + def socket_text(sock,text) + # do nothing + end +end + +Thread.new do + websocket_server = WEBrick::Websocket::HTTPServer.new Port:8001 + websocket_server.mount "/", EventServlet + websocket_server.start + at_exit do + websocket_server.shutdown + end +end + server.start