Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
teeworlds_srvbrowse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
minus
teeworlds_srvbrowse
Commits
c2dd84c0
Commit
c2dd84c0
authored
Mar 02, 2012
by
m!nus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first release version
parent
12659053
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
561 additions
and
0 deletions
+561
-0
example.py
example.py
+37
-0
find_by_ip.py
find_by_ip.py
+37
-0
listall.py
listall.py
+26
-0
teeworlds.py
teeworlds.py
+461
-0
No files found.
example.py
0 → 100644
View file @
c2dd84c0
#!/usr/bin/python
from
__future__
import
print_function
from
teeworlds
import
Teeworlds
# set up stuff
tw
=
Teeworlds
(
timeout
=
2
)
# ask the masters for servers
tw
.
query_masters
()
# query servers, wait for responses
# stops if no packet is received for `timeout` seconds
tw
.
run_loop
()
# filter the serverlist
servers
=
tw
.
serverlist
.
find
(
name
=
"^C"
,
# Server whose name begins with "C", regex style
gametype
=
"CTF"
,
# gametype contains "CTF"
maxping
=
0.1
)
# ping is lower or equal to 100ms
# sort by ping
servers
.
sort
(
key
=
lambda
s
:
s
.
latency
)
# display a nice list
for
server
in
servers
:
print
(
"{server: <64} [{gametype: ^16}] on {master}: {clients: >2}/{max_clients: <2} - {latency: >4.0f} ms"
\
.
format
(
server
=
server
.
name
,
gametype
=
server
.
gametype
,
master
=
server
.
master
.
name
,
clients
=
server
.
clients
,
\
max_clients
=
server
.
max_clients
,
latency
=
server
.
latency
*
1000
))
# check if m!nus is currently playing
minus_list
=
tw
.
playerlist
.
find
(
name
=
"^m!nus$"
)
if
minus_list
.
players
:
minus
=
minus_list
.
players
[
0
]
print
(
"m!nus is currently playing on {server} ({address}) with {players} other player(s)."
.
format
(
server
=
minus
.
server
.
name
,
address
=
minus
.
server
.
address
,
players
=
(
minus
.
server
.
players
-
1
)))
else
:
print
(
"m!nus isn't playing at the moment."
)
find_by_ip.py
0 → 100644
View file @
c2dd84c0
#!/usr/bin/python
from
__future__
import
print_function
from
teeworlds
import
Teeworlds
import
sys
# set up stuff
tw
=
Teeworlds
(
timeout
=
2
)
# ask the masters for servers
tw
.
query_masters
()
# query servers, wait for responses
# stops if no packet is received for `timeout` seconds
tw
.
run_loop
()
# filter the serverlist
ip_filter
=
"^"
+
sys
.
argv
[
1
].
replace
(
"."
,
"
\\
."
)
servers
=
tw
.
serverlist
.
find
(
address
=
ip_filter
)
# sort by ping
servers
.
sort
(
key
=
lambda
s
:
s
.
address
)
# display a nice list
for
server
in
servers
:
print
(
"{server: <64} {address: <15} [{gametype: ^16}] on {master}: {clients: >2}/{max_clients: <2} - {latency: >4.0f} ms"
\
.
format
(
server
=
server
.
name
,
address
=
server
.
address
,
gametype
=
server
.
gametype
,
master
=
server
.
master
.
name
,
clients
=
server
.
clients
,
\
max_clients
=
server
.
max_clients
,
latency
=
server
.
latency
*
1000
))
# check if m!nus is currently playing
#minus_list = tw.playerlist.find(name="^m!nus$")
#if minus_list.players:
# minus = minus_list.players[0]
# print("m!nus is currently playing on {server} ({address}) with {players} other player(s)."
# .format(server=minus.server.name, address=minus.server.address, players=(minus.server.players-1)))
#else:
# print("m!nus isn't playing at the moment.")
listall.py
0 → 100644
View file @
c2dd84c0
#!/usr/bin/python
from
__future__
import
print_function
from
teeworlds
import
Teeworlds
import
sys
# set up stuff
tw
=
Teeworlds
(
timeout
=
2
)
# ask the masters for servers
tw
.
query_masters
()
# query servers, wait for responses
# stops if no packet is received for `timeout` seconds
tw
.
run_loop
()
servers
=
tw
.
serverlist
# sort by ping
servers
.
sort
(
key
=
lambda
s
:
s
.
address
)
# display a nice list
for
server
in
servers
:
print
(
"{server: <64} {address: <15} [{gametype: ^16}] on {master}: {clients: >2}/{max_clients: <2} - {latency: >4.0f} ms"
\
.
format
(
server
=
server
.
name
,
address
=
server
.
address
,
gametype
=
server
.
gametype
,
master
=
server
.
master
.
name
,
clients
=
server
.
clients
,
\
max_clients
=
server
.
max_clients
,
latency
=
server
.
latency
*
1000
))
TeeworldsMaster
.py
→
teeworlds
.py
View file @
c2dd84c0
#!/usr/bin/python
# A library to get the serverlist & information for Teeworlds servers
# Copyright (C) 2011 m!nus <m1nus@online.de>
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
from
__future__
import
print_function
import
sys
import
socket
...
...
@@ -6,8 +27,10 @@ import time
from
random
import
randint
from
struct
import
unpack
import
select
import
Queue
as
queue
import
re
#
fuck you i need UTF-8
#
UTF-8 is required as default encoding
reload
(
sys
)
sys
.
setdefaultencoding
(
'utf8'
)
...
...
@@ -17,54 +40,72 @@ def log(level, str):
print
(
"[{0: <5}] {1}"
.
format
(
level
,
str
),
file
=
sys
.
stderr
)
def
is_ipv6
(
address
):
if
isinstance
(
address
,
tuple
):
address
=
address
[
0
]
return
True
if
':'
in
address
else
False
class
MultiSocket
(
object
):
READ
=
1
WRITE
=
2
EXCEPTION
=
4
def
__init__
(
self
,
timeout
=
None
):
def
__init__
(
self
,
timeout
=
None
,
interval
=
0
):
self
.
sockets
=
{}
self
.
families
=
{}
self
.
queue_out
=
queue
.
Queue
()
self
.
timeout
=
timeout
def
get
(
self
,
family
):
if
not
self
.
sockets
.
has_key
(
family
):
self
.
sockets
[
family
]
=
socket
.
socket
(
family
,
socket
.
SOCK_DGRAM
)
fileno
=
self
.
sockets
[
family
].
fileno
()
self
.
families
[
fileno
]
=
family
#self.sockets[family].settimeout(self.timeout)
return
self
.
sockets
[
family
]
def
getfamily
(
self
,
socket
):
fileno
=
socket
.
fileno
()
if
fileno
in
self
.
families
:
return
self
.
families
[
fileno
]
else
:
raise
Exception
(
'No family found for socket'
)
def
select
(
self
,
type
=
None
):
self
.
interval
=
interval
self
.
sockets
[
socket
.
AF_INET
]
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_DGRAM
,
socket
.
SOL_UDP
)
self
.
has_ipv6
=
socket
.
has_ipv6
if
self
.
has_ipv6
:
self
.
sockets
[
socket
.
AF_INET6
]
=
socket
.
socket
(
socket
.
AF_INET6
,
socket
.
SOCK_DGRAM
,
socket
.
SOL_UDP
)
def
select
(
self
,
type
=
None
,
timeout
=
None
):
timeout
=
self
.
timeout
if
timeout
==
None
else
timeout
list_r
=
self
.
sockets
.
values
()
if
(
type
&
self
.
READ
or
type
==
None
)
else
[]
list_w
=
self
.
sockets
.
values
()
if
type
&
self
.
WRITE
else
[]
list_x
=
self
.
sockets
.
values
()
if
type
&
self
.
EXCEPTION
else
[]
return
select
.
select
(
list_r
,
list_w
,
list_x
,
self
.
timeout
)
ret
=
select
.
select
(
list_r
,
list_w
,
list_x
,
timeout
)
if
ret
==
([],
[],
[]):
raise
socket
.
timeout
(
'select timed out'
)
else
:
return
ret
def
sendto
(
self
,
data
,
address
):
self
.
get
(
address
[
0
]).
sendto
(
data
,
address
[
1
])
if
is_ipv6
(
address
):
if
not
self
.
has_ipv6
:
return
0
return
self
.
sockets
[
socket
.
AF_INET6
].
sendto
(
data
,
address
)
else
:
return
self
.
sockets
[
socket
.
AF_INET
].
sendto
(
data
,
address
)
def
recvfrom
(
self
,
len
=
1492
):
def
sendto_q
(
self
,
data
,
address
,
callback
=
None
):
self
.
queue_out
.
put
((
data
,
address
,
callback
))
def
recvfrom
(
self
,
len
):
try
:
(
r
,
w
,
x
)
=
select
.
select
([
self
.
sockets
],
[],
[],
self
.
timeout
)
s
=
self
.
sockets
.
values
()
(
r
,
w
,
x
)
=
select
.
select
(
s
,
[],
[],
self
.
timeout
)
if
not
r
and
not
w
and
not
x
:
r
eturn
None
r
aise
socket
.
timeout
(
'select timed out'
)
for
sock
in
r
:
(
data
,
address
)
=
sock
.
recvfrom
(
len
)
return
(
data
,
(
self
.
sockets
.
getfamily
(
sock
),
address
))
except
socket
.
timeout
:
return
None
return
sock
.
recvfrom
(
len
)
except
socket
.
error
as
e
:
# Errno 10054 happens when we get ICMP port unreachable, we don't care about that
if
e
.
errno
!=
10054
:
raise
# in case if error 10054 just retry
# TODO: might reach maximum recursion
return
self
.
recvfrom
(
len
)
def
process_queue
(
self
,
amount
):
for
_
in
range
(
amount
):
if
not
self
.
queue_out
.
empty
():
(
data
,
address
,
callback
)
=
self
.
queue_out
.
get
()
if
self
.
sendto
(
data
,
address
)
==
len
(
data
):
if
hasattr
(
callback
,
'__call__'
):
callback
(
time
.
time
())
else
:
log
(
'warning'
,
'failed to send whole packet, requeuing'
)
self
.
queue_out
.
put
((
data
,
address
,
callback
))
class
Handler
(
object
):
...
...
@@ -110,8 +151,10 @@ class MasterServer(Handler):
_serveraddr_size
=
18
def
__init__
(
self
,
parent
,
address
,
name
=
'none given'
):
self
.
address
=
address
self
.
_parent
=
parent
self
.
_address
=
address
self
.
address
=
(
"[{host}]:{port}"
if
is_ipv6
(
address
)
else
"{host}:{port}"
)
\
.
format
(
host
=
address
[
0
],
port
=
address
[
1
])
#self.data = self._packet_list_response
self
.
name
=
name
self
.
latency
=
-
1
...
...
@@ -120,9 +163,12 @@ class MasterServer(Handler):
def
request
(
self
):
self
.
request_time
=
time
.
time
()
self
.
_parent
.
socket
s
.
get
(
self
.
address
[
0
]).
sendto
(
10
*
b'
\xff
'
+
b'req2'
,
self
.
address
[
1
]
)
self
.
_parent
.
socket
.
sendto_q
(
10
*
b'
\xff
'
+
b'req2'
,
self
.
_address
,
self
.
request_callback
)
self
.
server_count
=
0
def
request_callback
(
self
,
request_time
):
self
.
request_time
=
request_time
def
add_from_serverlist
(
self
,
data
):
if
len
(
data
)
%
self
.
_serveraddr_size
!=
0
:
raise
Exception
(
"Address packet's size not multiple of the server "
+
\
...
...
@@ -132,14 +178,13 @@ class MasterServer(Handler):
data
=
' '
.
join
([
"{0:2x}"
.
format
(
ord
(
x
))
for
x
in
data
])))
for
i
in
xrange
(
0
,
len
(
data
),
self
.
_serveraddr_size
):
if
data
[
0
:
12
]
==
b"
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff
"
:
# ::ffff:... == IPv4
serverAddress
=
(
socket
.
AF_INET
,
(
socket
.
inet_ntoa
(
data
[
i
+
12
:
i
+
16
]),
unpack
(
"!H"
,
data
[
i
+
16
:
i
+
18
])[
0
])
)
serverAddress
=
(
socket
.
inet_ntoa
(
data
[
i
+
12
:
i
+
16
]),
unpack
(
"!H"
,
data
[
i
+
16
:
i
+
18
])[
0
]
)
else
:
# TODO: workaround for windows as inet_ntop doesn't exist there
if
sys
.
platform
==
"win32"
:
log
(
'warning'
,
"Can't make IPv6 address on windows from binary: {0!r}"
.
format
(
data
[
i
:
i
+
16
]))
continue
address_family
=
socket
.
AF_INET6
serverAddress
=
(
address_family
(
socket
.
inet_ntop
(
address_family
,
data
[
i
:
i
+
16
]),
unpack
(
"!H"
,
data
[
i
+
16
:
i
+
18
])[
0
]))
serverAddress
=
(
socket
.
inet_ntop
(
socket
.
AF_INET6
,
data
[
i
:
i
+
16
]),
unpack
(
"!H"
,
data
[
i
+
16
:
i
+
18
])[
0
])
server
=
Server
(
self
.
_parent
,
serverAddress
,
master
=
self
)
server
.
request
()
self
.
_parent
.
serverlist
.
add
(
server
)
...
...
@@ -153,17 +198,15 @@ class MasterServer(Handler):
self
.
add_from_serverlist
(
data
[
len
(
self
.
_packet_list_response
):])
def
match
(
self
,
**
kwargs
):
if
not
kwargs
.
has_key
(
"
address"
)
or
kwargs
[
"address"
]
!=
self
.
address
:
if
not
kwargs
.
has_key
(
"
_address"
)
or
kwargs
[
"_address"
]
!=
self
.
_
address
:
return
False
if
not
kwargs
.
has_key
(
"
data"
)
or
kwargs
[
"
data"
][
0
:
len
(
self
.
_packet_list_response
)]
!=
self
.
_packet_list_response
:
if
not
kwargs
.
has_key
(
"
_data"
)
or
kwargs
[
"_
data"
][
0
:
len
(
self
.
_packet_list_response
)]
!=
self
.
_packet_list_response
:
return
False
return
True
def
__repr__
(
self
):
address
=
(
"[{host}]:{port}"
if
self
.
address
[
0
]
==
socket
.
AF_INET6
else
"{host}:{port}"
)
\
.
format
(
host
=
self
.
address
[
1
][
0
],
port
=
self
.
address
[
1
][
1
])
return
"<MasterServer name='{name}' address='{address}' servers='{servers}'>"
\
.
format
(
name
=
self
.
name
,
address
=
address
,
servers
=
self
.
server_count
)
.
format
(
name
=
self
.
name
,
address
=
self
.
address
,
servers
=
self
.
server_count
)
class
Server
(
Handler
):
...
...
@@ -171,15 +214,19 @@ class Server(Handler):
_packet_response
=
10
*
b'
\xff
'
+
b'inf3'
def
__init__
(
self
,
parent
,
address
,
master
=
None
):
self
.
address
=
address
self
.
_address
=
address
self
.
address
=
(
"[{host}]:{port}"
if
is_ipv6
(
address
)
else
"{host}:{port}"
)
\
.
format
(
host
=
address
[
0
],
port
=
address
[
1
])
self
.
_parent
=
parent
self
.
data
=
None
self
.
master
=
master
self
.
data
=
None
self
.
reset
()
def
reset
(
self
):
self
.
latency
=
-
1
self
.
playerlist
=
PlayerList
()
self
.
version
=
None
self
.
name
=
(
"[{host}]:{port}"
if
self
.
address
[
0
]
==
socket
.
AF_INET6
else
"{host}:{port}"
)
\
.
format
(
host
=
self
.
address
[
1
][
0
],
port
=
self
.
address
[
1
][
1
])
self
.
name
=
self
.
address
self
.
map
=
None
self
.
gametype
=
None
self
.
password
=
None
...
...
@@ -189,25 +236,28 @@ class Server(Handler):
self
.
max_clients
=
-
1
def
request
(
self
):
#log('debug', "Server-ping to " + s
tr(self.address)
)
#log('debug', "Server-ping to " + s
elf.address
)
self
.
token
=
chr
(
randint
(
1
,
255
))
self
.
data
=
self
.
_packet_response
+
str
(
ord
(
self
.
token
))
+
b'
\x00
'
self
.
request_time
=
time
.
time
()
self
.
_parent
.
socket
s
.
get
(
self
.
address
[
0
]).
sendto
(
self
.
_packet_request
+
self
.
token
,
self
.
address
[
1
]
)
self
.
_parent
.
socket
.
sendto_q
(
self
.
_packet_request
+
self
.
token
,
self
.
_address
,
self
.
request_callback
)
self
.
_parent
.
add_handler
(
self
)
def
request_callback
(
self
,
request_time
):
self
.
request_time
=
request_time
def
call
(
self
,
address
,
data
):
#log('debug', "Server-callback hit from " +
str(address)
)
#log('debug', "Server-callback hit from " +
address
)
self
.
parse
(
data
[
len
(
self
.
data
):])
def
parse
(
self
,
data
):
self
.
latency
=
time
.
time
()
-
self
.
request_time
data
=
iter
(
data
.
split
(
b'
\x00
'
))
try
:
self
.
version
=
data
.
next
().
decode
(
'utf8'
)
self
.
name
=
data
.
next
().
decode
(
'utf8'
)
self
.
map
=
data
.
next
().
decode
(
'utf8'
)
self
.
gametype
=
data
.
next
().
decode
(
'utf8'
)
self
.
version
=
data
.
next
()
#
.decode('utf8')
self
.
name
=
data
.
next
()
#
.decode('utf8')
self
.
map
=
data
.
next
()
#
.decode('utf8')
self
.
gametype
=
data
.
next
()
#
.decode('utf8')
self
.
password
=
(
data
.
next
()
==
'1'
)
self
.
players
=
int
(
data
.
next
())
self
.
max_players
=
int
(
data
.
next
())
...
...
@@ -215,28 +265,39 @@ class Server(Handler):
self
.
max_clients
=
int
(
data
.
next
())
for
_
in
range
(
self
.
clients
):
player
=
Player
()
player
.
name
=
data
.
next
().
decode
(
'utf8'
)
player
.
clan
=
data
.
next
().
decode
(
'utf8'
)
player
.
name
=
data
.
next
()
#
.decode('utf8')
player
.
clan
=
data
.
next
()
#
.decode('utf8')
player
.
country
=
int
(
data
.
next
())
player
.
score
=
int
(
data
.
next
())
player
.
playing
=
(
data
.
next
()
==
'1'
)
player
.
server
=
self
self
.
playerlist
.
add
(
player
)
except
StopIteration
:
self
.
reset
()
log
(
'warning'
,
'unexpected end of data for server '
+
str
(
self
))
for
player
in
self
.
playerlist
:
self
.
_parent
.
playerlist
.
add
(
player
)
def
match
(
self
,
**
kwargs
):
if
not
kwargs
.
has_key
(
"address"
)
or
kwargs
[
"address"
]
!=
self
.
address
:
if
kwargs
.
has_key
(
"hideInvalid"
)
and
kwargs
[
"invalid"
]
and
self
.
latency
==
-
1
:
return
False
if
kwargs
.
has_key
(
"_address"
)
and
kwargs
[
"_address"
]
!=
self
.
_address
:
return
False
if
kwargs
.
has_key
(
"_data"
)
and
kwargs
[
"_data"
][
0
:
len
(
self
.
data
)]
!=
self
.
data
:
return
False
if
kwargs
.
has_key
(
"name"
)
and
not
re
.
search
(
kwargs
[
"name"
],
self
.
name
):
return
False
if
not
kwargs
.
has_key
(
"data"
)
or
kwargs
[
"data"
][
0
:
len
(
self
.
data
)]
!=
self
.
data
:
if
kwargs
.
has_key
(
"address"
)
and
not
re
.
search
(
kwargs
[
"address"
],
self
.
address
):
return
False
if
kwargs
.
has_key
(
"gametype"
)
and
not
re
.
search
(
kwargs
[
"gametype"
],
self
.
gametype
):
return
False
if
kwargs
.
has_key
(
"maxping"
)
and
self
.
ping
>
kwargs
[
"maxping"
]:
return
False
return
True
def
__repr__
(
self
):
address
=
(
"[{host}]:{port}"
if
self
.
address
[
0
]
==
socket
.
AF_INET6
else
"{host}:{port}"
)
\
.
format
(
host
=
self
.
address
[
1
][
0
],
port
=
self
.
address
[
1
][
1
])
return
"<MasterServer name='{name}' address='{address}'>"
\
.
format
(
name
=
self
.
name
,
address
=
address
)
return
"<Server name='{name}' address='{address}'>"
\
.
format
(
name
=
self
.
name
,
address
=
self
.
address
)
class
Player
(
object
):
...
...
@@ -261,16 +322,22 @@ class ServerList(object):
raise
Exception
(
'Trying to add non-Server object'
)
self
.
servers
.
append
(
server
)
def
find
(
self
,
name
=
None
,
gametype
=
None
,
maxping
=
None
):
output
=
[]
def
find
(
self
,
**
kwargs
):
output
=
ServerList
()
for
server
in
self
.
servers
:
if
(
server
.
latency
!=
-
1
)
and
\
(
name
==
None
or
server
.
name
==
name
)
and
\
(
maxping
==
None
or
server
.
ping
<=
maxping
)
and
\
(
gametype
==
None
or
server
.
gametype
==
gametype
):
output
.
append
(
server
)
if
server
.
match
(
**
kwargs
):
output
.
add
(
server
)
return
output
def
sort
(
self
,
cmp
=
None
,
key
=
None
,
reverse
=
False
):
self
.
servers
=
sorted
(
self
.
servers
,
cmp
,
key
,
reverse
)
def
reverse
(
self
):
self
.
players
.
reverse
()
def
__iter__
(
self
):
return
iter
(
self
.
servers
)
def
__repr__
(
self
):
return
str
(
self
.
servers
)
...
...
@@ -284,16 +351,28 @@ class PlayerList(object):
raise
Exception
(
'Trying to add non-Player-object'
)
self
.
players
.
append
(
player
)
def
find
(
self
,
name
=
None
,
clan
=
None
,
country
=
None
,
playing
=
None
):
output
=
[]
def
find
(
self
,
name
=
None
,
clan
=
None
,
country
=
None
,
playing
=
None
,
server
=
None
):
output
=
PlayerList
()
if
name
:
name
=
re
.
compile
(
name
,
re
.
IGNORECASE
)
if
clan
:
clan
=
re
.
compile
(
clan
,
re
.
IGNORECASE
)
for
player
in
self
.
players
:
if
(
name
==
None
or
player
.
name
==
name
)
and
\
(
clan
==
None
or
player
.
clan
==
clan
)
and
\
if
(
name
==
None
or
name
.
search
(
player
.
name
)
)
and
\
(
clan
==
None
or
clan
.
search
(
player
.
clan
)
)
and
\
(
country
==
None
or
player
.
country
==
country
)
and
\
(
server
==
None
or
player
.
server
==
server
)
and
\
(
playing
==
None
or
player
.
playing
==
playing
):
output
.
a
ppen
d
(
player
)
output
.
a
d
d
(
player
)
return
output
def
sort
(
self
,
cmp
=
None
,
key
=
None
,
reverse
=
False
):
self
.
players
=
sorted
(
self
.
players
,
cmp
,
key
,
reverse
)
def
reverse
(
self
):
self
.
players
.
reverse
()
def
__iter__
(
self
):
return
iter
(
self
.
players
)
def
__repr__
(
self
):
return
str
(
self
.
players
)
...
...
@@ -303,22 +382,24 @@ class Teeworlds(object):
#self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#self.socket.setblocking(0)
#self._socket.settimeout(2)
self
.
timeout
=
timeout
self
.
handlers
=
HandlerStorage
()
self
.
serverlist
=
ServerList
()
self
.
playerlist
=
PlayerList
()
self
.
masterlist
=
[]
self
.
socket
s
=
MultiSocket
(
timeout
)
self
.
socket
=
MultiSocket
(
timeout
=
0.001
)
def
query_masters
(
self
):
masters
=
[
'master3.teeworlds.com'
]
#[
"master{0}.teeworlds.com".format(i) for i in range(2, 4+1)]
masters
=
[
"master{0}.teeworlds.com"
.
format
(
i
)
for
i
in
range
(
2
,
4
+
1
)]
for
mastername
in
masters
:
# resolves host and picks the first address
try
:
info
=
socket
.
getaddrinfo
(
mastername
,
8300
,
0
,
socket
.
SOCK_DGRAM
)
except
socket
.
gaierror
as
e
:
log
(
'warning'
,
'
[GAIError '
+
e
.
errno
+
'] '
+
e
.
strerror
)
log
(
'warning'
,
'
getaddrinfo failed: '
+
str
(
e
)
)
continue
else
:
master_addr
=
(
info
[
0
][
0
],
info
[
0
][
4
])
master_addr
=
info
[
0
][
4
]
log
(
'debug'
,
"requesting "
+
mastername
+
" "
+
str
(
master_addr
))
master
=
MasterServer
(
self
,
master_addr
,
mastername
.
partition
(
"."
)[
0
])
master
.
request
()
...
...
@@ -326,24 +407,40 @@ class Teeworlds(object):
self
.
masterlist
.
append
(
master
)
def
run_loop
(
self
):
last_recv
=
time
.
time
()
last_send
=
0
while
True
:
try
:
(
r
,
w
,
x
)
=
self
.
sockets
.
select
(
MultiSocket
.
READ
)
if
not
r
and
not
w
and
not
x
:
break
for
sock
in
r
:
(
data
,
address
)
=
sock
.
recvfrom
(
1500
)
address
=
(
self
.
sockets
.
getfamily
(
sock
),
address
)
log
(
'debug'
,
"received data from socket: byteslen="
+
str
(
len
(
data
))
+
" bytes="
+
' '
.
join
([
"{0:2x}"
.
format
(
ord
(
x
))
for
x
in
data
[
0
:
20
]
]))
for
handler
in
self
.
handlers
.
find
(
data
=
data
,
address
=
address
):
log
(
'debug'
,
"calling handler "
+
repr
(
handler
)
+
"with address="
+
str
(
address
))
handler
.
call
(
address
,
data
)
#(data, address) = self.socket.recvfrom(1492)
#log('debug', "received data from socket: byteslen=" + str(len(data)) + " bytes=" + ' '.join([ "{0:2x}".format(ord(x)) for x in data[0:20] ]))
#for handler in self.handlers.find(data=data, address=address):
# log('debug', "calling handler " + repr(handler) + "with address=" + str(address))
# handler.call(address, data)
#self.socket.process_queue()
(
r
,
w
,
x
)
=
self
.
socket
.
select
(
MultiSocket
.
READ
|
MultiSocket
.
WRITE
)
cur_time
=
time
.
time
()
if
w
and
cur_time
>
last_send
+
0.005
:
last_send
=
cur_time
self
.
socket
.
process_queue
(
1
)
if
not
r
:
if
cur_time
>
last_recv
+
self
.
timeout
:
break
time
.
sleep
(
0.001
)
else
:
last_recv
=
cur_time
for
sock
in
r
:
try
:
(
data
,
address
)
=
sock
.
recvfrom
(
1492
)
log
(
'debug'
,
"received data from socket: byteslen="
+
str
(
len
(
data
))
+
" bytes="
+
' '
.
join
([
"{0:2x}"
.
format
(
ord
(
x
))
for
x
in
data
[
0
:
20
]
]))
for
handler
in
self
.
handlers
.
find
(
_data
=
data
,
_address
=
address
):
log
(
'debug'
,
"calling handler "
+
repr
(
handler
)
+
" with address="
+
str
(
address
))
handler
.
call
(
address
,
data
)
except
socket
.
error
as
e
:
# Errno 10054 happens when we get ICMP port unreachable, we don't care about that
if
e
.
errno
!=
10054
:
raise
except
socket
.
timeout
:
break
except
socket
.
error
as
e
:
# Errno 10054 happens when we get ICMP port unreachable, we don't care about that
if
e
.
errno
!=
10054
:
raise
def
add_handler
(
self
,
handler
):
# improve this
...
...
@@ -355,12 +452,10 @@ class Teeworlds(object):
if
__name__
==
"__main__"
:
tw
=
Teeworlds
(
timeout
=
2
)
tw
.
query_masters
()
#s = Server(tw, (2, ('178.63.226.59', 8303)))
#tw.serverlist.add(s)
#s.request()
tw
.
run_loop
()
for
server
in
tw
.
serverlist
.
find
():
print
(
"{server: <64} on {master}: {clients: >2}/{max_clients: >2} - {latency: >4.0f} ms"
\
.
format
(
server
=
server
.
name
,
master
=
server
.
master
.
name
,
clients
=
server
.
clients
,
\
servers
=
tw
.
serverlist
.
find
(
name
=
"^C"
,
gametype
=
"CTF"
,
maxping
=
0.1
)
servers
.
sort
(
key
=
lambda
s
:
s
.
latency
)
for
server
in
servers
:
print
(
"{server: <64} [{gametype: ^16}] on {master}: {clients: >2}/{max_clients: >2} - {latency: >4.0f} ms"
\
.
format
(
server
=
server
.
name
,
gametype
=
server
.
gametype
,
master
=
server
.
master
.
name
,
clients
=
server
.
clients
,
\
max_clients
=
server
.
max_clients
,
latency
=
server
.
latency
*
1000
))
#print(str(tw.handlers))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment