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

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import sys
  6. import logging
  7. import struct
  8. import socket
  9. import collections
  10. import time
  11. from threading import RLock
  12. from traceback import print_exc
  13. import hub
  14. import common
  15. import oscar
  16. from oscar.Snactivator import Snactivator
  17. from util import lock, unpack_named, Storage, to_hex, try_this, callsback, isgeneratormethod
  18. log = logging.getLogger('oscar.sock')
  19. from struct import pack, unpack
  20. from common import netcall
  21.  
  22. def flap_sequence_number():
  23.     i = 1
  24.     while None:
  25.         yield i
  26.         i += 1
  27.         if i >= 32768:
  28.             i = 1
  29.             continue
  30.         continue
  31.         return None
  32.  
  33.  
  34. def default_cb(*a, **kw):
  35.     log.debug_s('Socket ignoring (%s, %s)', a, kw)
  36.  
  37.  
  38. class OscarSocket(common.socket):
  39.     flap_hdr_size = 6
  40.     snac_hdr_size = 10
  41.     id = 42
  42.     func_templ = '\n    def %(name)s (self):\n        print "%(name)s is not implemented!"\n        print self.hdr\n        print self.data\n    '
  43.     
  44.     def __repr__(self):
  45.         
  46.         try:
  47.             return '<OscarSocket %r>' % (self._OscarSocket__oserver,)
  48.         except Exception:
  49.             return '<OscarSocket ??>'
  50.  
  51.  
  52.     
  53.     def __init__(self):
  54.         common.socket.__init__(self)
  55.         self.on_connect = default_cb
  56.         self.on_incoming = default_cb
  57.         self.on_close = default_cb
  58.         self.cookie = None
  59.         self.bos = False
  60.         self.callbacks = collections.defaultdict(list)
  61.         self.rate_lock = RLock()
  62.         self.hdr = None
  63.         self.buf = ''
  64.         self.data = ''
  65.         self.seq = flap_sequence_number()
  66.         self.req = flap_sequence_number()
  67.         self.rate_classes = []
  68.         self.rates = { }
  69.         self.rate_lvl_incr = False
  70.         self.snactivate = self._send_snac
  71.         self.snactivator = None
  72.  
  73.     
  74.     def connect(self, server, cookie = None, incoming = None, close = None, callback = None, bos = False):
  75.         if not callback:
  76.             pass
  77.         self.on_connect = default_cb
  78.         if not incoming:
  79.             pass
  80.         self.on_incoming = default_cb
  81.         if not close:
  82.             pass
  83.         self.on_close = default_cb
  84.         self.cookie = cookie
  85.         self.bos = bos
  86.         self.set_terminator(self.flap_hdr_size)
  87.         log.info('oscar socket connecting to %s', server)
  88.         self._OscarSocket__oserver = server
  89.         common.socket.connect(self, server, error = callback.error)
  90.  
  91.     connect = callsback(connect)
  92.     
  93.     def handle_error(self, e = None):
  94.         if isinstance(e, socket.error):
  95.             if self.on_close is not None:
  96.                 log.error('Socket error for %r, calling on_close (= %r): %r', self, self.on_close, e)
  97.                 self.on_close(self)
  98.             else:
  99.                 log.info('handle_error in %r but on_close is None' % self)
  100.         
  101.         common.socket.handle_error(self, e)
  102.  
  103.     
  104.     def test_connection(self):
  105.         
  106.         try:
  107.             self.send_flap(5)
  108.         except Exception:
  109.             e = None
  110.             print_exc()
  111.             if not self.on_close:
  112.                 pass
  113.             default_cb(self)
  114.  
  115.  
  116.     
  117.     def apply_rates(self, rate_classes, rate_groups):
  118.         if not self.rate_classes:
  119.             self.rate_classes = rate_classes
  120.         else:
  121.             for rates in rate_classes:
  122.                 id = rates[0]
  123.                 self.rate_classes[id - 1] = rates
  124.             
  125.         self.rates.update(rate_groups)
  126.         if self.snactivator is None:
  127.             self.snactivator = Snactivator(self)
  128.             self.snactivator.start()
  129.         
  130.         self.snactivate = self.snactivator.send_snac
  131.  
  132.     apply_rates = lock(apply_rates)
  133.     
  134.     def calc_rate_level(self, rate_class):
  135.         old_level = rate_class.current_level
  136.         window = rate_class.window
  137.         now = int(time.time())
  138.         time_diff = (now - rate_class.last_time) * 1000
  139.         new_level = min(int(((window - 1) * old_level + time_diff) / window), rate_class.max_level)
  140.         return (new_level, now)
  141.  
  142.     
  143.     def snac_rate_class(self, fam, sub, *a):
  144.         
  145.         try:
  146.             return self.rate_classes[self.rates[(fam, sub)] - 1]
  147.         except KeyError:
  148.             return None
  149.  
  150.  
  151.     
  152.     def _get_rate_lvls(self, rclass):
  153.         return (rclass.max_level, rclass.current_level, rclass.alert_level, rclass.clear_level, rclass.window)
  154.  
  155.     
  156.     def time_to_send(self, s):
  157.         fam = s[0]
  158.         sub = s[1]
  159.         rclass = self.snac_rate_class(fam, sub)
  160.         (ml, curl, al, clrl, w) = self._get_rate_lvls(rclass)
  161.         threshold = min(ml, al + (clrl - al) * 2)
  162.         self.rate_lock.__enter__()
  163.         
  164.         try:
  165.             if (curl < al or self.rate_lvl_incr) and curl < threshold:
  166.                 self.rate_lvl_incr = True
  167.             else:
  168.                 self.rate_lvl_incr = False
  169.                 return 0
  170.         finally:
  171.             pass
  172.  
  173.         k = 500
  174.         step = ml / k
  175.         wait = w * step + curl
  176.         delta = rclass.last_time - int(time.time())
  177.         to_send = delta + wait / 1000
  178.         return max(0, to_send)
  179.  
  180.     
  181.     def handle_connect(self):
  182.         log.debug('connected')
  183.  
  184.     
  185.     def handle_close(self):
  186.         log.info('closed. calling on_close=%r', self.on_close)
  187.         if not self.on_close:
  188.             pass
  189.         default_cb(self)
  190.         self.close()
  191.  
  192.     
  193.     def handle_expt(self):
  194.         log.warning('oob data')
  195.         self.handle_close()
  196.  
  197.     
  198.     def collect_incoming_data(self, data):
  199.         pass
  200.  
  201.     
  202.     def set_terminator(self, term):
  203.         common.socket.set_terminator(self, term)
  204.  
  205.     
  206.     def found_terminator(self):
  207.         
  208.         try:
  209.             if self.hdr is None:
  210.                 self._lock.__enter__()
  211.                 
  212.                 try:
  213.                     self.hdr = unpack_named('!BBHH', 'id', 'chan', 'seq', 'size', self.buf)
  214.                     self.buf = ''
  215.                     if self.hdr.size == 0:
  216.                         self.found_terminator()
  217.                     else:
  218.                         self.set_terminator(self.hdr.size)
  219.                 finally:
  220.                     pass
  221.  
  222.             else:
  223.                 
  224.                 try:
  225.                     getattr(self, 'channel_%d' % self.hdr.chan, self.unknown_channel)()
  226.                 except oscar.errors:
  227.                     e = None
  228.                     hub.get_instance().on_error(e)
  229.                 except Exception:
  230.                     log.critical('Error handling FLAP 0x%x (DATA: %s) ' % (self.hdr.seq, repr(self.data)))
  231.                     raise 
  232.                 finally:
  233.                     self._lock.__enter__()
  234.                     
  235.                     try:
  236.                         (self.hdr, self.data) = (None, '')
  237.                         self.set_terminator(self.flap_hdr_size)
  238.                     finally:
  239.                         pass
  240.  
  241.  
  242.         except socket.error:
  243.             raise 
  244.         except Exception:
  245.             e = None
  246.             log.critical('%r had a non-socket error', self)
  247.             print_exc()
  248.         finally:
  249.             if self.terminator == 0:
  250.                 log.critical('terminator was 0, closing socket!')
  251.                 self.handle_close()
  252.             
  253.  
  254.  
  255.     
  256.     def close(self):
  257.         self._cleanup()
  258.         common.socket.close(self)
  259.  
  260.     
  261.     def _cleanup(self):
  262.         self.on_incoming = None
  263.         self.on_close = None
  264.         if self.snactivator:
  265.             self.snactivator.stop()
  266.             del self.snactivator
  267.             self.snactivator = None
  268.         
  269.  
  270.     
  271.     def close_when_done(self):
  272.         self._cleanup()
  273.         
  274.         try:
  275.             self.send_flap(4)
  276.         except socket.error:
  277.             (errno, desc) = None
  278.             if errno not in (9, 10054, 10057):
  279.                 raise 
  280.             
  281.         except:
  282.             errno not in (9, 10054, 10057)
  283.         finally:
  284.             common.socket.close_when_done(self)
  285.  
  286.  
  287.     
  288.     def send_flap(self, chan, data = ''):
  289.         log.debug_s('Sending FLAP on channel %d, data is < %r >', chan, data)
  290.         (None, None, netcall)((lambda : common.socket.push(self, pack('!BBHH', self.id, chan, self.seq.next(), len(data)) + data)))
  291.  
  292.     
  293.     def send_snac(self, fam, sub, data = '', priority = 5, req = False, cb = None, *args, **kwargs):
  294.         req_id = self.req.next()
  295.         if req:
  296.             for k, v in list(self.callbacks.iteritems()):
  297.                 if not v:
  298.                     self.callbacks.pop(k)
  299.                     continue
  300.             
  301.             self.callbacks[req_id].append((cb, args, kwargs))
  302.         
  303.         snac = (fam, sub, req_id, data)
  304.         if self.snactivator is None:
  305.             self._send_snac(snac, priority)
  306.         else:
  307.             self.snactivator.send_snac(snac, priority)
  308.  
  309.     
  310.     def _send_snac(self, .1, priority = None):
  311.         (fam, sub, req_id, data) = .1
  312.         server_version = getattr(self, 'server_snac_versions', { }).get(fam, None)
  313.         if server_version is None:
  314.             version = None
  315.         else:
  316.             my_version = getattr(getattr(oscar.snac, 'family_x%02x' % fam, None), 'version', None)
  317.             if my_version == server_version or my_version is None:
  318.                 version = None
  319.             else:
  320.                 version = my_version
  321.         flags = None if version is None else 32768
  322.         if version:
  323.             ver_tlv = oscar.util.tlv(1, 2, version)
  324.             ver_tlv = pack('!H', len(ver_tlv)) + ver_tlv
  325.         else:
  326.             ver_tlv = ''
  327.         log.debug('sending snac: fam=0x%02x, sub=0x%02x, req=0x%04x', fam, sub, req_id)
  328.         log.debug_s('\t\tdata=%r', data)
  329.         to_send = pack('!HHHI', fam, sub, flags, req_id) + ver_tlv + data
  330.         self.send_flap(2, to_send)
  331.         if (fam, sub) in self.rates:
  332.             rclass = self.snac_rate_class(fam, sub)
  333.             (rclass.current_level, rclass.last_time) = self.calc_rate_level(rclass)
  334.             clevel = rclass.current_level
  335.             i = sorted(list(self._get_rate_lvls(rclass)) + [
  336.                 clevel]).index(clevel)
  337.             (hi, lo) = ('disconnect', 'limit', 'alert', 'clear', 'max')[i:i + 2]
  338.             if not hi == 'clear' and lo == 'max':
  339.                 log.debug('current rate level is: %s < %d < %s', hi, clevel, lo)
  340.             
  341.         
  342.  
  343.     
  344.     def channel_1(self):
  345.         log.info('got channel 1 (new connection) flap')
  346.         to_send = pack('!I', 1)
  347.         if self.cookie is not None:
  348.             to_send += oscar.util.tlv(6, self.cookie)
  349.             self._lock.__enter__()
  350.             
  351.             try:
  352.                 self.cookie = None
  353.             finally:
  354.                 pass
  355.  
  356.         
  357.         self.send_flap(1, to_send)
  358.         
  359.         try:
  360.             if not self.on_connect:
  361.                 pass
  362.             default_cb(self)
  363.         except StopIteration:
  364.             pass
  365.  
  366.         del self.on_connect
  367.         self.on_connect = None
  368.  
  369.     
  370.     def channel_2(self):
  371.         hdr = unpack_named('!HHHI', 'fam', 'sub', 'flags', 'req', self.data[:self.snac_hdr_size])
  372.         data = self.data[self.snac_hdr_size:]
  373.         log.debug('got channel 2 (snac data) flap. fam=0x%02x, sub=0x%02x, req=0x%04x', hdr.fam, hdr.sub, hdr.req)
  374.         log.debug_s('\t\tdata=%r', data)
  375.         snac = Storage(hdr = hdr, data = data)
  376.         if snac.hdr.flags & 32768:
  377.             log.debug('got version data for snac, trimming')
  378.             snac_ver_fmt = (('tlvs_len', 'H'), ('tlvs', 'tlv_list_len', 'tlvs_len'))
  379.             (tlvs_len, ver, snac.data) = oscar.util.apply_format(snac_ver_fmt, snac.data)
  380.         
  381.         if self.is_ignored(snac):
  382.             log.debug('Ignored snac: %r', snac)
  383.             return None
  384.         
  385.         cbs = self.callbacks
  386.         
  387.         try:
  388.             if snac.hdr.req in cbs:
  389.                 call_later = []
  390.                 for func, args, kwargs in cbs[snac.hdr.req]:
  391.                     if snac.hdr.flags & 1:
  392.                         call_later.append((func, args, kwargs))
  393.                     
  394.                     if isgeneratormethod(func):
  395.                         
  396.                         try:
  397.                             func((self, snac) + args)
  398.                         except StopIteration:
  399.                             pass
  400.                         except:
  401.                             None<EXCEPTION MATCH>StopIteration
  402.                         
  403.  
  404.                     None<EXCEPTION MATCH>StopIteration
  405.                     func(self, snac, *args, **kwargs)
  406.                 
  407.                 self._lock.__enter__()
  408.                 
  409.                 try:
  410.                     if not call_later:
  411.                         cbs.pop(snac.hdr.req)
  412.                     else:
  413.                         cbs[snac.hdr.req] = call_later
  414.                 finally:
  415.                     pass
  416.  
  417.             elif self.on_incoming is None:
  418.                 default_cb(self, snac)
  419.             elif isgeneratormethod(self.on_incoming):
  420.                 
  421.                 try:
  422.                     self.on_incoming((self, snac))
  423.                 except StopIteration:
  424.                     pass
  425.                 except Exception:
  426.                     print repr(snac)
  427.                     raise 
  428.                 except:
  429.                     None<EXCEPTION MATCH>StopIteration
  430.                 
  431.  
  432.             None<EXCEPTION MATCH>StopIteration
  433.             self.on_incoming(self, snac)
  434.         except oscar.snac.SnacError:
  435.             e = None
  436.             (fam, _) = ()
  437.             (sub, _) = e.args[:2]
  438.             if (fam, sub) in self.ignored_errors:
  439.                 log.error('SNAC error occured: %r', snac)
  440.             else:
  441.                 hub.get_instance().on_error(e)
  442.         except:
  443.             (fam, sub) in self.ignored_errors
  444.  
  445.  
  446.     
  447.     def is_ignored(self, snac):
  448.         if (snac.hdr.fam, snac.hdr.sub) in self.ignored_snacs:
  449.             return True
  450.         
  451.  
  452.     ignored_snacs = [
  453.         (1, 19)]
  454.     ignored_errors = [
  455.         (1, 13),
  456.         (21, 2),
  457.         (19, 1),
  458.         (21, 5)]
  459.     
  460.     def channel_4(self):
  461.         log.info('got channel 4 (close connection) flap')
  462.         fmt = (('tlvs', 'tlv_dict'),)
  463.         (tlvs, data) = oscar.unpack(fmt, self.data)
  464.         if (try_this,)((lambda : ord(tlvs[9][-1])), False):
  465.             if not self.on_close:
  466.                 pass
  467.             default_cb(self, oscar.protocol.Reasons.OTHER_USER)
  468.         elif not self.on_close:
  469.             pass
  470.         default_cb(self)
  471.         del self.on_close
  472.         self.on_close = None
  473.         self.close_when_done()
  474.  
  475.     
  476.     def unknown_channel(self):
  477.         log.warning('Unknown channel for data: %r', self.data)
  478.  
  479.  
  480.