Browse Source

added CMServerList object

pull/18/merge
Rossen Georgiev 9 years ago
parent
commit
287eae4d37
  1. 107
      steam/core/cm.py

107
steam/core/cm.py

@ -2,6 +2,8 @@ import struct
import binascii
import logging
import zipfile
from time import time
from collections import defaultdict
try:
from cStringIO import StringIO
@ -9,9 +11,8 @@ except ImportError:
from StringIO import StringIO
import gevent
from gevent import event
from gevent import queue
from Crypto.Random import random
from gevent import event, queue
from random import shuffle
from steam.steamid import SteamID
from steam.enums import EResult, EUniverse
@ -21,21 +22,8 @@ from steam.core.connection import TCPConnection
from steam.core.msg import is_proto, clear_proto_bit
from steam.core.msg import Msg, MsgProto
from steam.util.events import EventEmitter
from steam.util import ip_from_int
server_list = [
('162.254.196.41', '27020'), ('162.254.196.40', '27021'),
('162.254.196.43', '27019'), ('162.254.196.40', '27018'),
('162.254.196.43', '27020'), ('162.254.196.41', '27019'),
('162.254.196.41', '27018'), ('162.254.196.42', '27020'),
('162.254.196.41', '27017'), ('162.254.196.41', '27021'),
('146.66.152.10', '27017'), ('146.66.152.10', '27018'),
('146.66.152.11', '27019'), ('146.66.152.11', '27020'),
('146.66.152.10', '27019'), ('162.254.197.42', '27018'),
('162.254.197.41', '27019'), ('162.254.197.41', '27017'),
('208.78.164.14', '27017'), ('208.78.164.14', '27019'),
('208.78.164.9', '27019'), ('208.78.164.14', '27018'),
('208.78.164.9', '27018'), ('208.78.164.13', '27017'),
]
logger = logging.getLogger("CMClient")
@ -49,7 +37,7 @@ class CMClient(EventEmitter):
self._init_attributes()
self.registered_callbacks = {}
self.servers = CMServerList()
if protocol == CMClient.TCP:
self.connection = TCPConnection()
@ -61,6 +49,7 @@ class CMClient(EventEmitter):
self.on(EMsg.ChannelEncryptRequest, self._handle_encrypt_request),
self.on(EMsg.Multi, self._handle_multi),
self.on(EMsg.ClientLogOnResponse, self._handle_logon),
self.on(EMsg.ClientCMList, self._handle_cm_list),
def emit(self, event, *args):
if event is not None:
@ -70,14 +59,13 @@ class CMClient(EventEmitter):
def connect(self):
logger.debug("Connect initiated.")
while True:
server_addr = random.choice(server_list)
for server_addr in self.servers:
if self.connection.connect(server_addr):
break
logger.debug("Failed to connect. Retrying...")
self.current_server_addr = server_addr
self.connected = True
self.emit("connected")
self._recv_loop = gevent.spawn(self._recv_messages)
@ -104,6 +92,7 @@ class CMClient(EventEmitter):
gevent.spawn(self.connect)
def _init_attributes(self):
self.current_server_addr = None
self.connected = False
self.key = None
@ -261,6 +250,7 @@ class CMClient(EventEmitter):
if result in (EResult.TryAnotherCM,
EResult.ServiceUnavailable
):
self.servers.mark_bad(self.current_server_addr)
self.disconnect(True)
return
@ -277,3 +267,78 @@ class CMClient(EventEmitter):
interval = msg.body.out_of_game_heartbeat_seconds
self._heartbeat_loop = gevent.spawn(self._heartbeat, interval)
def _handle_cm_list(self, msg):
logger.debug("Updating CM list")
new_servers = zip(map(ip_from_int, msg.body.cm_addresses), msg.body.cm_ports)
self.servers.merge_list(new_servers)
class CMServerList(object):
Good = 1
Bad = 2
def __init__(self, bad_timespan=300):
self._log = logging.getLogger("CMServerList")
self.bad_timespan = bad_timespan
self.list = defaultdict(dict)
# build-in list
self.merge_list([("208.64.200.201", 27017), ("208.64.200.201", 27018),
("208.64.200.201", 27019), ("208.64.200.201", 27020),
("208.64.200.202", 27017), ("208.64.200.202", 27018),
("208.64.200.202", 27019), ("208.64.200.203", 27017),
("208.64.200.203", 27018), ("208.64.200.203", 27019),
("208.64.200.204", 27017), ("208.64.200.204", 27018),
("208.64.200.204", 27019), ("208.64.200.205", 27017),
("208.64.200.205", 27018), ("208.64.200.205", 27019),
("208.78.164.9", 27017), ("208.78.164.9", 27018),
("208.78.164.9", 27019), ("208.78.164.10", 27017),
("208.78.164.10", 27018), ("208.78.164.10", 27019),
("208.78.164.11", 27017), ("208.78.164.11", 27018),
("208.78.164.11", 27019), ("208.78.164.12", 27017),
("208.78.164.12", 27018), ("208.78.164.12", 27019),
("208.78.164.13", 27017), ("208.78.164.13", 27018),
("208.78.164.13", 27019), ("208.78.164.14", 27017),
("208.78.164.14", 27018), ("208.78.164.14", 27019),
])
def __iter__(self):
def genfunc():
while True:
good_servers = filter(lambda x: x[1]['quality'] == CMServerList.Good, self.list.items())
if len(good_servers) == 0:
self.reset_all()
continue
shuffle(good_servers)
for server_addr, meta in good_servers:
yield server_addr
return genfunc()
def reset_all(self):
self._log.debug("Marking all CMs as Good.")
for key in self.list:
self.mark_good(key)
def mark_good(self, server_addr):
self.list[server_addr].update({'quality': CMServerList.Good, 'timestamp': time()})
def mark_bad(self, server_addr):
self._log.debug("Marking %s as Bad." % repr(server_addr))
self.list[server_addr].update({'quality': CMServerList.Bad, 'timestamp': time()})
def merge_list(self, new_list):
total = len(self.list)
for ip, port in new_list:
self.mark_good((ip, port))
if total:
self._log.debug("Added %d new CM addresses." % (len(self.list) - total))

Loading…
Cancel
Save