home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / msn / MSNSocket.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  13.8 KB  |  472 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import socket
  6. import threading
  7. import logging
  8. import collections
  9. import common
  10. import util
  11. import util.Events as Events
  12. log = logging.getLogger('msn.sock')
  13. import msn
  14. import msn.Msnifier as msn
  15.  
  16. dummy = lambda *a, **k: pass
  17.  
  18. def trid(max = 2147483647, i = 0):
  19.     while True:
  20.         i += 1
  21.         yield i
  22.         if i == max:
  23.             i = 0
  24.             continue
  25.  
  26.  
  27. class MSNSocketBase(Events.EventMixin):
  28.     events = Events.EventMixin.events | set(('on_connect', 'on_send', 'on_conn_error', 'on_close', 'on_message'))
  29.     delim = '\r\n'
  30.     payload_commands = 'MSG UUX UBX PAG IPG NOT GCF ADL UUN UBN RML FQY 241 508 UBM UUM'.split()
  31.     
  32.     def __init__(self):
  33.         Events.EventMixin.__init__(self)
  34.         self.trid = trid()
  35.         self.callbacks = collections.defaultdict(list)
  36.         if not hasattr(self, '_lock'):
  37.             self._lock = threading.RLock()
  38.         
  39.         self.timeouts = { }
  40.  
  41.     
  42.     def set_trid(self, msgobj, trid):
  43.         if trid is True:
  44.             msgobj.trid = self.trid.next()
  45.         
  46.  
  47.     
  48.     def set_callbacks(self, msgobj, callback):
  49.         if callback is sentinel:
  50.             callback = None
  51.         
  52.         if msgobj.is_trid:
  53.             self.set_timeout(msgobj)
  54.             self.callbacks[msgobj.trid].append(callback)
  55.         else:
  56.             self.callbacks[msgobj.cmd].append(callback)
  57.  
  58.     
  59.     def set_timeout(self, msgobj):
  60.         timeout = getattr(msgobj, 'timeout', None)
  61.         if timeout is not None and common.pref('msn.socket.use_timeout', type = bool, default = False):
  62.             log.info('Starting timeout for %r', msgobj)
  63.             timer = util.Timer(timeout, self.timeout_handler(msgobj))
  64.             self.timeouts[msgobj.trid] = timer
  65.             timer.start()
  66.         
  67.  
  68.     
  69.     def timeout_handler(self, msgobj):
  70.         
  71.         def handler():
  72.             log.debug('This message has timed out: %r', msgobj)
  73.             msgcopy = msgobj.copy()
  74.             msgcopy.timeout = msgobj.timeout
  75.             msgcopy.retries = msgobj.retries - 1
  76.             msgcopy.trid = 0
  77.             if msgcopy.retries == 0:
  78.                 return None
  79.             
  80.             log.debug('Retrying this message that timed out: %r', msgcopy)
  81.             self._lock.__enter__()
  82.             
  83.             try:
  84.                 callback = self.callbacks.pop(msgobj.trid, None)
  85.             finally:
  86.                 pass
  87.  
  88.             self.send(msgcopy, trid = True, callback = callback)
  89.  
  90.         return handler
  91.  
  92.     
  93.     def unset_timeout(self, msgobj, include_previous = True):
  94.         if not msgobj.is_trid:
  95.             return None
  96.         
  97.         if include_previous:
  98.             for i in range(msgobj.trid):
  99.                 self.unset_timeout_single(i)
  100.             
  101.         
  102.         self.unset_timeout_single(msgobj.trid)
  103.  
  104.     
  105.     def unset_timeout_single(self, key):
  106.         
  107.         try:
  108.             timer = self.timeouts.pop(key, None)
  109.             if timer is not None:
  110.                 timer.stop()
  111.         except (IndexError, KeyError):
  112.             pass
  113.  
  114.  
  115.     
  116.     def pause(self):
  117.         pass
  118.  
  119.     
  120.     def unpause(self):
  121.         pass
  122.  
  123.     
  124.     def on_connect(self):
  125.         return self
  126.  
  127.     on_connect = Events.event(on_connect)
  128.     
  129.     def on_send(self, data):
  130.         pass
  131.  
  132.     on_send = Events.event(on_send)
  133.     
  134.     def on_conn_error(self, e = None):
  135.         log.info('%r had a connection error: %r', self, e)
  136.         return (self, e)
  137.  
  138.     on_conn_error = Events.event(on_conn_error)
  139.     
  140.     def on_close(self):
  141.         return self
  142.  
  143.     on_close = Events.event(on_close)
  144.     
  145.     def unset_callbacks(self, msg):
  146.         callback = None
  147.         
  148.         try:
  149.             if not msg.trid:
  150.                 pass
  151.             callback = self.callbacks[msg.cmd][0]
  152.         except (KeyError, IndexError):
  153.             e = None
  154.             pop = False
  155.  
  156.         pop = True
  157.         if pop:
  158.             if msg.is_trid:
  159.                 self.unset_timeout(msg, include_previous = True)
  160.                 for i in range(msg.trid):
  161.                     
  162.                     try:
  163.                         self.callbacks.pop(i, None)
  164.                     continue
  165.                     except (IndexError, KeyError):
  166.                         continue
  167.                     
  168.  
  169.                 
  170.             elif not msg.trid:
  171.                 self.callbacks[msg.cmd].pop(0)
  172.             
  173.         
  174.         return callback
  175.  
  176.     unset_callbacks = util.lock(unset_callbacks)
  177.     
  178.     def adjust_message(self, msg):
  179.         if msg.cmd == 'QNG':
  180.             msg.cmd = 'PNG'
  181.             msg.trid = 0
  182.         
  183.         return msg
  184.  
  185.     
  186.     def on_message(self, msg):
  187.         self.event('on_message', msg)
  188.         msg = self.adjust_message(msg)
  189.         callback = self.unset_callbacks(msg)
  190.         if callback is None:
  191.             return None
  192.         
  193.         
  194.         try:
  195.             if msg.is_error:
  196.                 f = callback.error
  197.             else:
  198.                 f = callback.success
  199.         except AttributeError:
  200.             e = None
  201.             log.error('AttributeError in msnsocket.on_message: %r\ncallback was: %r', e, callback)
  202.  
  203.         log.debug('MSNSocket calling %r', f)
  204.         
  205.         try:
  206.             f(self, msg)
  207.         except Exception:
  208.             e = None
  209.             log.error('Error in callback')
  210.             import traceback
  211.             traceback.print_exc()
  212.  
  213.  
  214.     
  215.     def close(self):
  216.         while self.timeouts:
  217.             
  218.             try:
  219.                 (k, v) = self.timeouts.popitem()
  220.             except KeyError:
  221.                 break
  222.                 continue
  223.  
  224.             if v is not None:
  225.                 v.stop()
  226.                 continue
  227.  
  228.  
  229.  
  230. class MSNSocket(MSNSocketBase, common.socket):
  231.     speed_limit = 2000
  232.     speed_window = 0.25
  233.     
  234.     def __init__(self):
  235.         common.socket.__init__(self)
  236.         MSNSocketBase.__init__(self)
  237.         self.set_terminator(self.delim)
  238.         self.data = ''
  239.         self.expecting = 'command'
  240.         self._server = None
  241.         self.rater = msn.Msnifier.Msnifier(self)
  242.         self.rater.start()
  243.         self._bc_lock = threading.RLock()
  244.         self.bytecount = [
  245.             (0, util.default_timer())]
  246.         log.debug('%r created', self)
  247.  
  248.     
  249.     def get_local_sockname(self):
  250.         return self.socket.getsockname()
  251.  
  252.     
  253.     def connect_args_for(self, type, addr):
  254.         return (type, addr)
  255.  
  256.     
  257.     def connect(self, type, host_port):
  258.         self._scktype = type
  259.         
  260.         try:
  261.             (host, port) = host_port
  262.         except (ValueError, TypeError):
  263.             raise TypeError("%r address must be <type 'tuple'> (host, port) not %r (%r)", type(self).__name__, type(host_port), host_port)
  264.  
  265.         if self._server is not None:
  266.             raise ValueError("Don't know which server to use! self._server = %r, host_port = %r.", self._server, host_port)
  267.         
  268.         self._server = host_port
  269.         log.info('connecting socket to %r', self._server)
  270.         
  271.         try:
  272.             common.socket.connect(self, self._server, error = self.on_conn_error)
  273.         except Exception:
  274.             e = None
  275.             self.on_conn_error(e)
  276.             return None
  277.  
  278.         self.bind_event('on_message', (lambda msg: log.debug('Received %r', msg)))
  279.  
  280.     _connect = connect
  281.     
  282.     def _disconnect(self):
  283.         self.close_when_done()
  284.  
  285.     
  286.     def _closed(self):
  287.         return not getattr(self.socket, 'connected', False)
  288.  
  289.     _closed = property(_closed)
  290.     
  291.     def __repr__(self):
  292.         
  293.         try:
  294.             s = 'connected to %r' % (self.socket.getpeername(),)
  295.         except socket.error:
  296.             s = 'not connected'
  297.  
  298.         return '<%s %s>' % (type(self).__name__, s)
  299.  
  300.     
  301.     def test_connection(self, callback = None):
  302.         if self._scktype == 'NS':
  303.             self.send(msn.Message('PNG'), callback = callback)
  304.         else:
  305.             log.info('Not testing connection because this is not an NS socket.')
  306.             callback.success()
  307.  
  308.     test_connection = util.callsback(test_connection)
  309.     
  310.     def handle_connect(self):
  311.         log.debug('connection established')
  312.         self.on_connect()
  313.  
  314.     
  315.     def handle_expt(self):
  316.         log.warning('OOB data. self.data = %r', self.data)
  317.         self.close()
  318.  
  319.     
  320.     def collect_incoming_data(self, data):
  321.         self.data += data
  322.  
  323.     collect_incoming_data = util.lock(collect_incoming_data)
  324.     
  325.     def set_terminator(self, term):
  326.         common.socket.set_terminator(self, term)
  327.  
  328.     
  329.     def found_terminator(self):
  330.         self.data += self.delim
  331.         
  332.         try:
  333.             self._lock.__enter__()
  334.             
  335.             try:
  336.                 self.data = ''
  337.                 data = self.data
  338.                 log.debug_s('IN  : %r', data)
  339.                 dlist = data.split(' ')
  340.                 cmd = dlist[0]
  341.                 if self.expecting == 'command' and dlist[0] in self.payload_commands:
  342.                     self.expecting = 'payload'
  343.                     self.data = data
  344.                     
  345.                     try:
  346.                         new_term = int(dlist[-1])
  347.                     except ValueError:
  348.                         self._lock
  349.                         self._lock
  350.                         self
  351.                         new_term = 0
  352.                     except:
  353.                         self._lock
  354.  
  355.                     return self.set_terminator(new_term)
  356.                 elif self.expecting == 'payload':
  357.                     self.expecting = 'command'
  358.                     data = data[:-len(self.delim)]
  359.                     payload = True
  360.                 else:
  361.                     payload = False
  362.                 self.set_terminator(self.delim)
  363.                 msg = msn.Message.from_net(data, payload)
  364.             finally:
  365.                 pass
  366.  
  367.         except Exception:
  368.             self
  369.             e = self
  370.             log.info('error parsing message, testing connection\nError was %r', e)
  371.             self.test_connection(success = self.conn_ok, error = self.conn_error)
  372.             import traceback
  373.             traceback.print_exc()
  374.         except:
  375.             self
  376.  
  377.         self.on_message(msg)
  378.  
  379.     
  380.     def handle_close(self):
  381.         log.warning('socket closed, self.data = %r', self.data)
  382.         self.rater.stop()
  383.         self.close()
  384.  
  385.     
  386.     def close(self):
  387.         log.warning('socket closing, self.data = %r', self.data)
  388.         MSNSocketBase.close(self)
  389.         common.socket.close(self)
  390.         self.on_close()
  391.  
  392.     
  393.     def send_gen(self, gen, priority = 5):
  394.         self.rater.send_pkt(gen, priority)
  395.  
  396.     
  397.     def send(self, msgobj, trid = sentinel, callback = None, **kw):
  398.         self.set_trid(msgobj, trid)
  399.         self.set_callbacks(msgobj, callback)
  400.         log.debug('Sending %r', msgobj)
  401.         self.rater.send_pkt(str(msgobj), **kw)
  402.  
  403.     send = util.callsback(send)
  404.     
  405.     def conn_ok(self):
  406.         log.info('connection test passed')
  407.  
  408.     
  409.     def conn_error(self):
  410.         log.warning('connection test failed')
  411.         self.close_when_done()
  412.         self.on_conn_error()
  413.  
  414.     
  415.     def _send(self, data, *a, **k):
  416.         log.log_s(0, 'sent: %s' % data)
  417.         self._lock.__enter__()
  418.         
  419.         try:
  420.             log.debug_s('OUT : %r' % (data,))
  421.             if not common.socket.send(self, data, *a, **k):
  422.                 log.critical('Message dropped in MSNSocket: <%s>' % data)
  423.         finally:
  424.             pass
  425.  
  426.         self.on_send(data)
  427.         now = util.default_timer()
  428.         self._bc_lock.__enter__()
  429.         
  430.         try:
  431.             self.bytecount.append((len(data), now))
  432.         finally:
  433.             pass
  434.  
  435.  
  436.     
  437.     def time_to_send(self, data):
  438.         now = util.default_timer()
  439.         self._bc_lock.__enter__()
  440.         
  441.         try:
  442.             self.bytecount = (self._bc_lock, filter)((lambda t: now - t[1] < self.speed_window), self.bytecount)
  443.         finally:
  444.             pass
  445.  
  446.         send_rate = sum((lambda .0: for b in .0:
  447. b[0])(self.bytecount))
  448.         if send_rate < self.speed_limit:
  449.             return 0
  450.         
  451.         log.debug('sending too fast')
  452.         bytes = dlen = len(data)
  453.         for size, tstamp in reversed(self.bytecount):
  454.             bytes += size
  455.             interval = now - tstamp
  456.             if (bytes / interval) * self.speed_window > self.speed_limit:
  457.                 break
  458.                 continue
  459.         
  460.         tts = (bytes / self.speed_limit) * self.speed_window + interval
  461.         log.log(5, 'currently sending at %d bytes/sec', send_rate)
  462.         log.debug('sleeping for %r seconds' % tts)
  463.         return tts
  464.  
  465.     
  466.     def close_when_done(self):
  467.         self.send(msn.Message('OUT'))
  468.         self.rater.stop()
  469.         common.socket.close_when_done(self)
  470.  
  471.  
  472.