Преглед на файлове

cleanup and ip-address lookup (reverse)

Paul Klumpp преди 12 години
родител
ревизия
ffc7d6fe86
променени са 2 файла, в които са добавени 150 реда и са изтрити 109 реда
  1. 1 0
      Gemfile
  2. 149 109
      em_server.rb

+ 1 - 0
Gemfile

@@ -2,4 +2,5 @@ source 'https://rubygems.org'
 
 gem 'stomp'
 gem 'eventmachine'
+gem 'em-resolv-replace'
 

+ 149 - 109
em_server.rb

@@ -2,6 +2,7 @@
 
 require 'eventmachine'
 require 'digest/md5'
+require 'fiber'
 
 
 
@@ -57,26 +58,26 @@ module InterconnectionPointProtocolHandler
 	
 	@@connected_clients = Array.new
 	@@broadcasts = Hash.new
-	
+
 	# default method that is being run on connection!
 	def post_init # connection of someone starts here...
 		@username = nil
 	end
-	
-	
+
+
 	### getters
 	def entered_username?
 		!@username.nil? && !@username.empty? # then it's true
 	end
-	
+
 	def username
 		@username
 	end
-	
+
 	def my_roles
 		return $user_roles[@username]
 	end
-	
+
 	def my_cmds
 		return my_roles.collect {|v| $role_commands[v]}.flatten
 	end
@@ -87,7 +88,7 @@ module InterconnectionPointProtocolHandler
 		@@connected_clients.each {|c| users.push(c.username)}
 		return users
 	end # of ousers
-	
+
 	### checkers
 	def allowed_cmd(inputmessage)
 		my_cmds.each{|c|
@@ -106,17 +107,17 @@ module InterconnectionPointProtocolHandler
 			return false
 		end
 	end
-	
-	
+
+
 
 	### actions
 	def put_log(msg)
 		puts "#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}"
 	end
-	
+
 	# searches through our hash of saved connections and writes them a messages.
 	def	write_user(input, username = nil)
-		if not username 
+		if not username
 			username = @username
 		end
 		if connection = @@connected_clients.find { |c| c.username == username }
@@ -125,7 +126,7 @@ module InterconnectionPointProtocolHandler
 			connection.send_data line
 		end
 	end # of write_user
-		
+
 	# searches through roles and writes those users on their connections
 	def write_role(role, input, *exempts)
 		#find users with role
@@ -134,16 +135,16 @@ module InterconnectionPointProtocolHandler
 		                 if v.include? role
 			                 users.push(k)
 		                 end
-		                 } 
-		
+		                 }
+
 		# find users that are online and inside Array "users"
 		lala = Array.new
-		users.each {|v|	
-		           if ousers.include? v	
+		users.each {|v|
+		           if ousers.include? v
 			           lala.push(v)
 		           end
 		           }
-		
+
 		# now write to them
 		lala.each {|user|
 		          if not exempts.include? user
@@ -151,51 +152,51 @@ module InterconnectionPointProtocolHandler
 		          end
 		          }
 	end	# of write_role()
-	
-	
-	
+
+
+
 	# what happens with what input?!
 	def inputting(input)
-		
+
 		write_user("SYS You typed: #{input}")
-		
+
 		if input =~ /^([A-Z_]+)/
 			cmd = $1
 		end
 		# now we have the cmd .. or not ;)
-		
+
 		if input =~ /^[A-Z_]+ (.+)/
 			payload = $1
 		end
 		# now we can use payload
 
 		if allowed_cmd(cmd)
-			
+
 			### typical system commands follow
 			if cmd == "PING"
 				write_user("PONG")
-				
+
 			elsif cmd == "C"
-				
+
 				if payload =~ /^(.+)$/
 					write_role($default_role, "C #{@username}: #{$1}")
-					
+
 				else
 					write_user("SYS Format is C <chattext>")
 				end
-				
+
 		  elsif cmd == "WHO"
 				ousers.each {|ouser| write_user("WHO_RE #{ouser} ROLES: #{$user_roles[ouser].join(", ")}")}
-				
-				
+
+
 			elsif cmd == "PART"
 				write_user("SYS Goodbye '#{@username}'.")
 				write_role($default_role, "PARTED User '#{@username}' just left the party.", @username)
 				return "bye"
-				
+
 			###now for the good stuff, broadcasting
 			elsif cmd == "REQ_BC"
-				
+
 				# help with format .. but send the raw payload
 				if payload =~ /^(.+),(.+),(.+),'(.+)','(.+)'$/
 					#              n    f    s     ni     txt
@@ -207,136 +208,174 @@ module InterconnectionPointProtocolHandler
 					source = $3
 					nickname = $4
 					text = $5
-					
+
 					if not network =~ /^(QWalt)|(QDEV)/
 						write_user("SYS Network name #{network} is unknown: QWalt or QDEV allowed.")
 						error = 1
 					end
-					
+
 					if not freqname =~ /^(-qw-)|(-spam-)|(-dev-)/
 						write_user("SYS Frequency name is unknown #{freqname}")
 						error = 1
 					end
-					
-					if not source =~ /^(#.+)|(qw:\/\/)|(http:\/\/)/
+
+					if source =~ /^(#.+)|(qw:\/\/)|(http:\/\/)/
+
+          else
 						write_user("SYS Source string is not in the form ^(#.+)|(qw:\/\/)|(http:\/\/)  was: #{source}")
 						error = 1
 					end
-					
-					if not nickname =~ /^.+/ 
+
+					if not nickname =~ /^.+/
 						write_user("SYS Nickname string is not in the form ^.+  #{nickname}")
 						error = 1
 					end
-					
+
 					if not text =~ /^.+/
 						write_user("SYS Message string is not in the form ^.+ #{text}")
 						error = 1
 					end
-					
+
 				else # of check syntax
 					write_user("SYS Command format is REQ_BC <network>,<frequency>,<source/channel>,'<nickname>','<message>'")
 					error = 1
 				end
-				
+
 				if error == 0
-					
+
 					# send REQ_BC to the corresponding role.
 					bcid = Digest::MD5.hexdigest("%d %s %s %s %s %s" % [Time.now.utc.to_i, network, freqname, source, nickname, text])
-					
+
 					# so it only reaches the issuer of REQ_BC
 					write_user("BC_ID #{bcid} for: #{network},#{freqname},#{source}")
 					@@broadcasts[bcid] = @username
-					
+
+          # qw:// ip resolving
+          if source =~ /^qw:\/\/(.+):(\d+)(.*)$/
+            # ip address is 15 in length
+            iphost = $1
+            ipport = $2
+            rest = $3
+
+            if iphost =~ /^\d+\.\d+\.\d+\.\d+/
+              # resolve it to a dns name
+
+              f = Fiber.new do
+                Fiber.yield Resolv.getname(iphost)
+              end
+              host_name = f.resume
+              #host_name = ""
+
+              if host_name.nil? || host_name.empty?
+                host_name = iphost
+              else
+                # if the resulting dns is too long, use ip-address instead.
+                # if the resulting dns has too many dots, use ip-address instead.
+                if host_name.length > 23 || host_name.split(".").size >= 4
+                  #put_log "cutting down host_name #{host_name} #{host_name.size} #{host_name.split(".").size}"
+                  host_name = iphost
+                end
+              end
+              source = "qw://#{host_name}:#{ipport}#{rest}"
+            end
+          end # of if source qw://x.x.x.x:portzzz
+
+          # resolve
 					finalmessage = "BC %s %s,%s,%s,'%s','%s'" % [bcid, network, freqname, source, nickname, text]
 					write_role("broadcast", finalmessage, @username) # write to the role with the exempt of myself.
-					
-					
-				end 
+
+
+				end
 				#end of REQ_BC here..
-				
+
 			elsif cmd == "BC_RE"
-					
+
 				if payload =~ /^(.+) (.+)=(\d+),(.+)=(\d+)$/
-					
+
 					bcid = $1
 					user_string = $2
 					user_count = $3
 					item_string = $4
 					item_count = $5
-					
+
 					payload = "%s %s=%d,%s=%d" % [bcid, user_string, user_count, item_string, item_count]
 					# according bcid it is possible to get the originating user.. so send only to his topic!
-					
+
 					if @@broadcasts[bcid]
 						to_user = @@broadcasts[bcid]
-						
+
 						write_user("SYS Broadcast reply bcid: #{bcid} underway to #{to_user}.")
 						write_user("#{cmd} #{payload}", to_user)
 					else
 						write_user("SYS Broadcast reply bcid: #{bcid} underway.")
 						write_role("broadcast", "#{cmd} #{payload}", @username)
 					end
-					
+
 				else # of bc_re format check
 					put_log "SYS Format is BC_RE <bcid> <userstring>=<usercount>,<itemstring>=<itemcount>"
 				end
-			
+
 			end
-			
-				
+
+
 		else  # of if allowed command
 			write_user("SYS Command #{input} not allowed, your commands are: #{my_cmds.join(", ")}.")
 		end  # of if allowed command
-		
+
 	end # of inputting!
-		
-	
-	
+
+
+
 	# default method that is being run on receiving data!
 	def receive_data(data) # connection receives a line on the server end
-		
-		if not entered_username? # oh, it seems, it's a new user
-			# this is the user name coming in!
-			username = data.chomp
-			
-			if online(username)
-				put_log "SYS User '#{username}' tried to double connect. Say bye bye."
-				send_data "SYS Hey '#{username}', only one connection allowed. Bye.\n"
-				EventMachine.add_timer 1, proc { close_connection }
-				
-				return false
-			end
-			
-			if not $user_roles.any? {|k, v| k.include? username} 
-				put_log "SYS User '#{username}' unknown to me. Saying bye."
-				send_data "SYS User '#{username}' unknown to me. Bye.\n"
-				
-				# disconnect him
-				close_connection
-			else
-					
-				@username = username
-				
-				@@connected_clients.push(self)
-				
-				put_log("SYS '#{@username}' connected. Online now: #{ousers.join(", ")}")
-				
-				write_user("HELLO Hi user '#{@username}'! How are you? I'm '#{$version}'")
-				write_user("ROLES #{my_roles.join(", ")}")
-				write_user("COMMANDS #{my_cmds.join(", ")}")
-				write_role($default_role, "JOINED User '#{@username}' just joined the party.", @username)
-				
-			end
-		else # of username not known (first connect)
-			# it's alive!
-			inputter = inputting(data.chomp)
-						
-			if inputter == "bye"
-				close_connection
-			end
-			
-		end # of username not known
-		
+
+    line = data.chomp unless data.chomp.nil?
+
+    if line
+
+      if entered_username? # oh, it's a known user
+        # it's alive!
+        inputter = inputting(line)
+
+        if inputter == "bye"
+          close_connection
+        end
+
+      else # of username known, then it seems to be the first connect
+
+        # and this line is the user name coming in!
+        username = line
+
+        if online(username)
+          put_log "SYS User '#{username}' tried to double connect. Say bye bye."
+          send_data "SYS Hey '#{username}', only one connection allowed. Bye.\n"
+          EventMachine.add_timer 1, proc { close_connection }
+
+          return false
+        end
+
+        if $user_roles.any? {|k| k.include? username}
+          @username = username
+
+          @@connected_clients.push(self)
+
+          put_log("SYS '#{@username}' connected. Online now: #{ousers.join(", ")}")
+
+          write_user("HELLO Hi user '#{@username}'! How are you? I'm '#{$version}'")
+          write_user("ROLES #{my_roles.join(", ")}")
+          write_user("COMMANDS #{my_cmds.join(", ")}")
+          write_role($default_role, "JOINED User '#{@username}' just joined the party.", @username)
+        else
+          put_log "SYS User '#{username}' unknown to me. Saying bye."
+          send_data "SYS User '#{username}' unknown to me. Bye.\n"
+
+          # disconnect him
+          close_connection
+        end
+
+      end # of username known
+    end # of line
+
 	end
 
 	# default method that is being run on disconnection!
@@ -345,18 +384,19 @@ module InterconnectionPointProtocolHandler
 			@@connected_clients.delete(self)
 			put_log "SYS '#{@username}' disconnected. Online now: #{ousers.join(", ")}"
 		end
-		
+
 	end
 end
 
 
 
 def main
-
 	# #run: Note that this will block current thread.
-	EventMachine.run {
-		EventMachine.start_server "0.0.0.0", 7337, InterconnectionPointProtocolHandler
-	}
+	EventMachine.run do
+
+    EventMachine.start_server("0.0.0.0", 7337, InterconnectionPointProtocolHandler)
+
+	end
 end
 
 main