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(' '))
|