Skip to content

Instantly share code, notes, and snippets.

@skinnyjames
Last active February 15, 2022 16:03
Show Gist options
  • Save skinnyjames/ec272fd525c10d60f0affeca402385a1 to your computer and use it in GitHub Desktop.
Save skinnyjames/ec272fd525c10d60f0affeca402385a1 to your computer and use it in GitHub Desktop.
chat
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