class P2p2::PairdWorker
Public Class Methods
new( paird_port, infod_port )
click to toggle source
initialize
# File lib/p2p2/paird_worker.rb, line 7 def initialize( paird_port, infod_port ) @reads = [] @roles = {} # :paird / :infod @room_infos = {} # title => { p1_paird, p1_addrinfo, p2_paird, p2_addrinfo, updated_at } new_pairds( paird_port ) new_a_infod( infod_port ) end
Public Instance Methods
looping()
click to toggle source
looping
# File lib/p2p2/paird_worker.rb, line 18 def looping puts "#{ Time.new } looping" loop do rs, _ = IO.select( @reads ) rs.each do | sock | role = @roles[ sock ] case role when :paird read_paird( sock ) when :infod read_infod( sock ) else puts "#{ Time.new } read unknown role #{ role }" end end end rescue Interrupt => e puts e.class quit! end
quit!()
click to toggle source
quit!
# File lib/p2p2/paird_worker.rb, line 45 def quit! exit end
Private Instance Methods
add_read( sock, role = nil )
click to toggle source
add read
# File lib/p2p2/paird_worker.rb, line 54 def add_read( sock, role = nil ) return if sock.nil? || sock.closed? || @reads.include?( sock ) @reads << sock if role then @roles[ sock ] = role end end
new_a_infod( infod_port )
click to toggle source
new a infod
# File lib/p2p2/paird_worker.rb, line 66 def new_a_infod( infod_port ) infod = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 ) infod.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) infod.bind( Socket.sockaddr_in( infod_port, '127.0.0.1' ) ) puts "#{ Time.new } infod bind on #{ infod_port }" add_read( infod, :infod ) end
new_pairds( begin_port )
click to toggle source
new pairds
# File lib/p2p2/paird_worker.rb, line 78 def new_pairds( begin_port ) 10.times do | i | paird_port = begin_port + i paird = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 ) paird.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) paird.bind( Socket.sockaddr_in( paird_port, '0.0.0.0' ) ) puts "#{ Time.new } paird bind on #{ paird_port }" add_read( paird, :paird ) end end
read_infod( infod )
click to toggle source
read infod
# File lib/p2p2/paird_worker.rb, line 144 def read_infod( infod ) data, addrinfo, rflags, *controls = infod.recvmsg data2 = @room_infos.sort_by{ | _, info | info[ :updated_at ] }.reverse.map do | title, info | [ info[ :updated_at ], title + ' ' * ( ROOM_TITLE_LIMIT - title.size ), info[ :p1_addrinfo ].ip_unpack.join( ':' ) ].join( ' ' ) end.join( "\n" ) send_data( infod, data2, addrinfo ) end
read_paird( paird )
click to toggle source
read paird
# File lib/p2p2/paird_worker.rb, line 103 def read_paird( paird ) data, addrinfo, rflags, *controls = paird.recvmsg return if data =~ /\r|\n/ is_p2 = ( data[ 0 ] == TO ) title = is_p2 ? data[ 1..-1 ] : data return if title.empty? || ( title.size > ROOM_TITLE_LIMIT ) room_info = @room_infos[ title ] unless is_p2 then if room_info then room_info[ :p1_paird ] = paird room_info[ :p1_addrinfo ] = addrinfo room_info[ :updated_at ] = Time.new else @room_infos[ title ] = { p1_paird: paird, p1_addrinfo: addrinfo, p2_paird: nil, p2_addrinfo: nil, updated_at: Time.new } end return end return unless room_info room_info[ :p2_paird ] = paird room_info[ :p2_addrinfo ] = addrinfo puts "#{ Time.new } paired #{ room_info[ :p1_addrinfo ].inspect } #{ room_info[ :p2_addrinfo ].inspect }" send_data( room_info[ :p1_paird ], room_info[ :p2_addrinfo ].to_sockaddr, room_info[ :p1_addrinfo ] ) send_data( room_info[ :p2_paird ], room_info[ :p1_addrinfo ].to_sockaddr, room_info[ :p2_addrinfo ] ) end
send_data( sock, data, target_addr )
click to toggle source
send data
# File lib/p2p2/paird_worker.rb, line 92 def send_data( sock, data, target_addr ) begin sock.sendmsg_nonblock( data, 0, target_addr ) rescue Exception => e puts "#{ Time.new } sendmsg #{ e.class }" end end