File: rcon

package info (click to toggle)
alien-arena 7.71.3%2Bdfsg-3
  • links: PTS, VCS
  • area: contrib
  • in suites: bookworm
  • size: 12,284 kB
  • sloc: ansic: 111,223; cpp: 52,844; sh: 4,436; makefile: 627; ruby: 438; perl: 71
file content (119 lines) | stat: -rwxr-xr-x 3,827 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env ruby

=begin

    ALIEN ARENA RCON UTIL (for server admins) V1.0
    Copyright (C) 2007 Tony Jackson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    Tony Jackson can be contacted at tonyj@cooldark.com
	
=end
=begin
	This script has been patched from its original source for distribution
	with Debian systems.
=end

require 'socket'

# send rcon string to all servers in array and get responses(not yet implemented)
def send_rcon(servers, password, message)
	if servers == nil
		return []
	end

	query = 'rcon ' + password + ' ' + message + ' ' + "\x00"
	connections = Hash.new
	failed = Array.new
	
	# Get the time before sending any packets, to time server response time (ping)
	starttime = Time.now
	
	# send a UDP packet to each server in the array
	servers.each do
		| server |  # Here server is of form 'ip:port' string
		begin
			socket = UDPSocket.new  # open works in the same way
			socket.connect(server.split(':')[0], server.split(':')[1])
			socket.send(query, 0)
			#socket.send(nil, 0)  # Test failure case
			connections[socket] = server # hash keyed on socket resource, containing server string
		rescue
			puts 'Failed to send to server '+server
			# some failure making a socket or sending a message - add to list of failed servers
			#socket.close - can't use this - may not even be open
			failed << server
			next
		end
	end
	
	# remove servers from list if socket failed to create/send UDP packet
	servers -= failed
	
	# check that we have at least one open UDP socket
	if connections.length == 0
		return servers
	end
	
	selectsocketlist = connections.keys  # get list of sockets from hash
	while result = select(selectsocketlist, nil, nil, 0.5) # select() waits for one or more socket to get a read event, or times out
		ping = (Time.now - starttime)*1000
		# store the time at which this server (or multiple servers) responded, and store the replies in our array of buffers
		result[0].each do
			|socket|
			begin
				# here connections[socket] gives us the 'ip:port' string of the associated server
				puts 'Server '+connections[socket]+' replied in '+ping.to_s+'ms:'
				reply = socket.recv(2048) # big enough to cover both games server replies and master reply with 256 servers (payload 12+6*256 bytes)
				puts reply.split("\n")[1..-1]
				selectsocketlist.delete(socket) # delete from array  now that we have a reply
				socket.close
			rescue # catchs both socket errors and nils in the split :)
				next
			end
		end
	end
	
	# here selectsocketlist will contain an array of failed sockets
	selectsocketlist.each do
		|socket|
		servers -= [connections[socket]]
		socket.close
	end
	
	# return array of servers that responded to our queries
	return servers
end
	

# Program starts here

# $* is array of args
if $*.include?('--help') or ($*.length < 3) then
	puts ''
	puts 'RCon utility for Alien Arena servers'
	puts ''
	puts '  Usage:'
	puts '  alien-arena-server -r <server:port> password <commandstring>'
	puts '  Optional arguments:'
	puts ''
	puts '  alien-arena-server -r --help  This message'
	puts ''
	exit
end

send_rcon([$*[0]], $*[1], $*[2..-1].join(' '))