Last active
February 15, 2022 16:03
-
-
Save skinnyjames/ec272fd525c10d60f0affeca402385a1 to your computer and use it in GitHub Desktop.
chat
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
require "socket" | |
module Chat | |
def self.init(url : String, port : Int32 = 80) | |
tcp = TCPSocket.new | |
tcp.reuse_address = true | |
tcp.reuse_port = true | |
tcp.connect url, port | |
tcp << "GET /connect HTTP/1.1\r\nHost: #{url}\r\nUser-Agent: curl/1.0\r\nConnection: Keep-Alive\r\nAccept: */*\r\nContent-Length: 0\r\n\r\n" | |
me = tcp.local_address.address | |
me_port = tcp.local_address.port | |
body = nil | |
addresses = [] of String | |
while res = tcp.gets | |
puts res | |
if addresses.size >= 1 | |
tcp.close | |
puts tcp.closed? | |
break | |
end | |
if md = res.match /Peer-Address: (.*)$/ | |
addresses << md[1] | |
end | |
# if md = res.match /My-Address: (.*)$/ | |
# addresses << md[1] | |
# end | |
end | |
if data = addresses[0]? | |
peer, peer_port = data.split /:(\d*$)/, remove_empty: true | |
#if new_data = addresses[1]? | |
#me, me_port = data.split(/:(\d*$)/, remove_empty: true) | |
Connection.new(me, me_port.to_i32, peer, peer_port.to_i32) | |
else | |
raise "whoops" | |
end | |
end | |
class Connection | |
def initialize(@my_address : String, @my_port : Int32, @peer_address : String, @peer_port : Int32) | |
spawn do | |
retry(20, backoff: 0.5) do | |
connect | |
end | |
end | |
retry(20, backoff: 0.5) do | |
listen | |
end | |
end | |
def listen | |
server = TCPSocket.new#(@my_address, @my_port) | |
server.reuse_address = true | |
server.reuse_port = true | |
server.flush_on_newline = true | |
STDOUT.puts "listening on #{@my_address}:#{@my_port}" | |
server.bind @my_address, @my_port | |
server.listen | |
puts "listening" | |
loop do | |
while conn = server.accept | |
conn.puts "Hello from #{@my_address}" | |
spawn do | |
STDOUT.puts conn.gets | |
end | |
end | |
end | |
end | |
def connect | |
socket = TCPSocket.new | |
socket.reuse_address = true | |
socket.reuse_port = true | |
puts "Connection to #{@peer_address}:#{@peer_port}" | |
socket.connect @peer_address, @peer_port, connect_timeout: 4 | |
puts "connection established" | |
while line = STDIN.gets | |
puts "from me: #{line}" | |
break if line == "exit" | |
socket.puts line | |
end | |
end | |
def retry(limit, *, backoff=nil) | |
attempts = 1 | |
loop do | |
begin | |
break if yield | |
rescue error | |
raise error if attempts == limit | |
sleep backoff*attempts if backoff | |
attempts += 1 | |
end | |
end | |
end | |
end | |
end | |
if url = ARGV[0]? | |
puts "Connecting to rendevous @ #{url}" | |
Chat.init(url) | |
else | |
puts "need a url" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment