NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

SocketGPS.py (25113B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\net\SocketGPS.py
      2 import errno
      3 import iocp
      4 import logging
      5 import socket
      6 import sys
      7 import log
      8 import blue
      9 import stackless
     10 import uthread
     11 import bluepy
     12 import locks
     13 import localization
     14 from carbon.common.script.net import GPS, machobase, machoRunTimeStats
     15 from carbon.common.script.net.GPSExceptions import GPSAddressOccupied, GPSBadAddress, GPSException, GPSRemoteTransportClosed, GPSTransportClosed
     16 from eveprefs import prefs
     17 import monolithconfig
     18 import monolithmetrics
     19 import carbon.common.script.net.machoNet as macho
     20 if sys.platform == 'darwin':
     21     ADDRESS_OCCUPIED_ERRORCODES = (errno.EADDRINUSE,)
     22     SOFT_CONNECTION_ERRORS = (errno.ECONNRESET, errno.ENOBUFS)
     23     NOBUF_ERRORS = (errno.ENOBUFS,)
     24     CLOSE_SOCKET_ERRNOS = (errno.ECONNABORTED, errno.ECONNREFUSED, errno.ECONNRESET)
     25 elif sys.platform == 'win32':
     26     ADDRESS_OCCUPIED_ERRORCODES = (errno.EADDRINUSE, errno.WSAEADDRINUSE)
     27     SOFT_CONNECTION_ERRORS = (errno.ECONNRESET,
     28      errno.ENOBUFS,
     29      errno.WSAECONNRESET,
     30      errno.WSAENOBUFS)
     31     NOBUF_ERRORS = (errno.ENOBUFS, errno.WSAENOBUFS)
     32     CLOSE_SOCKET_ERRNOS = (errno.ECONNABORTED,
     33      errno.ECONNREFUSED,
     34      errno.ECONNRESET,
     35      errno.WSAECONNABORTED,
     36      errno.WSAECONNREFUSED,
     37      errno.WSAECONNRESET)
     38 stdlog = logging.getLogger(__name__)
     39 mylog = log.Channel('GPS', 'socket')
     40 gai = socket.getaddrinfo
     41 
     42 @locks.SingletonCall
     43 def mygai(*args):
     44     return gai(*args)
     45 
     46 
     47 socket.getaddrinfo = mygai
     48 usingIOCP = iocp.UsingIOCP()
     49 if not usingIOCP:
     50     import stacklessio
     51     usesmartwakeup = bool(prefs.GetValue('useSmartWakeup', 0))
     52     usependingcalls = bool(prefs.GetValue('usePendingCalls', 0))
     53     usethreaddispatch = bool(prefs.GetValue('useThreadDispatch', 0))
     54     stacklessio.ApplySettings({'useSmartWakeup': usesmartwakeup,
     55      'usePendingCalls': usependingcalls,
     56      'useThreadDispatch': usethreaddispatch})
     57 blue.os.CarbonIoFastWakeup(prefs.GetValue('carbonIoFastWakeup', 0))
     58 stacklessioVersion = prefs.GetValue('stacklessioVersion', 0)
     59 stacklessioNobufProb = prefs.GetValue('stacklessioNobufProb', 0.0)
     60 stacklessioUseNoblock = prefs.GetValue('stacklessioUseNoblock', 1)
     61 stacklessioAllocChunkSize = prefs.GetValue('stacklessioAllocChunkSize', 1048576)
     62 socket.apply_settings({'version': stacklessioVersion,
     63  'nobufProb': stacklessioNobufProb,
     64  'useNoblock': stacklessioUseNoblock,
     65  'allocChunkSize': stacklessioAllocChunkSize})
     66 GPSSTATS_TIME_SAMPLING_PERIODS = [1,
     67  5,
     68  60,
     69  600]
     70 GPSSTATS_PACKETSREAD_PERIODS = GPSSTATS_TIME_SAMPLING_PERIODS
     71 GPSSTATS_BYTESREAD_PERIODS = GPSSTATS_TIME_SAMPLING_PERIODS
     72 GPSSTATS_PACKETSWRITTEN_PERIODS = GPSSTATS_TIME_SAMPLING_PERIODS
     73 GPSSTATS_BYTESWRITTEN_PERIODS = GPSSTATS_TIME_SAMPLING_PERIODS
     74 GPSSTATS_COUNT_SAMPLING_PERIODS = [1,
     75  5,
     76  50,
     77  500]
     78 GPSSTATS_BYTESREADPERPACKET_PERIODS = GPSSTATS_COUNT_SAMPLING_PERIODS
     79 GPSSTATS_BYTESWRITTENPERPACKET_PERIODS = GPSSTATS_COUNT_SAMPLING_PERIODS
     80 GPSSTATS_FAILED_TO_CLOSE_SOCKET_COUNTER = 'gps.failed_to_close_socket'
     81 
     82 class SocketTransportFactory(GPS.GPSTransportFactory):
     83     __guid__ = 'gps.SocketTransportFactory'
     84     reuseAddress = False
     85 
     86     def __init__(self, *args, **kwds):
     87         super(SocketTransportFactory, self).__init__(*args, **kwds)
     88         self.MaxPacketSize = None
     89         self.MaxPacketSize = 10485760
     90 
     91     @staticmethod
     92     def Transport():
     93         return SocketTransport
     94 
     95     @staticmethod
     96     def Acceptor():
     97         return SocketTransportAcceptor
     98 
     99     def _PreSocketConnectOperations(self, socket):
    100         pass
    101 
    102     def Listen(self, port, address = ''):
    103         try:
    104             port = int(port)
    105         except Exception as e:
    106             raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/SpecifiedAddressBogus'), e)
    107 
    108         if port < 1 or port > 65535:
    109             raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/SpecifiedPortNotvalid'))
    110         s = None
    111         try:
    112             s = socket.socket()
    113             self._PreSocketConnectOperations(s)
    114             if self.reuseAddress:
    115                 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    116             s.bind((address, port))
    117             s.listen(socket.SOMAXCONN)
    118             result = self.Acceptor()(self.useACL, s)
    119             result.MaxPacketSize = self.MaxPacketSize
    120             return result
    121         except socket.error as e:
    122             self._closeSocket(s)
    123             if e[0] in ADDRESS_OCCUPIED_ERRORCODES:
    124                 raise GPSAddressOccupied('Cannot listen', e)
    125             raise e
    126         except Exception as e:
    127             self._closeSocket(s)
    128             raise e
    129 
    130     def Connect(self, address):
    131         if stackless.getcurrent().is_main:
    132             raise RuntimeError("Can't do a Connect() on the main thread")
    133         address = address.encode('ascii')
    134         try:
    135             host, port = address.split(':')
    136             port = int(port)
    137             if port < 1 or port > 65535:
    138                 raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/SpecifiedPortNotvalid'))
    139         except ValueError as e:
    140             raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/SpecifiedPortNotValidNotInt'), e)
    141         except Exception as e:
    142             raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/SpecifiedAddressBogus'), e)
    143 
    144         s = None
    145         try:
    146             s = socket.socket()
    147             self._PreSocketConnectOperations(s)
    148             s.connect((host, port))
    149             if self.MaxPacketSize:
    150                 s.setmaxpacketsize(self.MaxPacketSize)
    151             return self.Transport()(s)
    152         except socket.gaierror as e:
    153             self._closeSocket(s)
    154             raise GPSBadAddress(localization.GetByLabel('/Carbon/MachoNet/CouldNotConnectToAddress'), e)
    155         except socket.error as e:
    156             self._closeSocket(s)
    157             raise GPSTransportClosed(localization.GetByLabel('/Carbon/MachoNet/CouldNotConnectToAddress'), exception=e)
    158         except Exception as e:
    159             self._closeSocket(s)
    160             raise e
    161 
    162     def _closeSocket(self, s):
    163         if s is None:
    164             return
    165         try:
    166             s.shutdown(socket.SHUT_RDWR)
    167         except Exception:
    168             pass
    169 
    170         try:
    171             s.close()
    172         except Exception:
    173             monolithmetrics.increment(metric=GPSSTATS_FAILED_TO_CLOSE_SOCKET_COUNTER, value=1, tags=None, sample_rate=1, prometheus_only=True)
    174 
    175 
    176 class SocketTransportAcceptor(GPS.GPSTransportAcceptor):
    177     __guid__ = 'gps.SocketTransportAcceptor'
    178 
    179     def __init__(self, *args, **kwds):
    180         super(SocketTransportAcceptor, self).__init__(*args, **kwds)
    181         self.MaxPacketSize = None
    182 
    183     @staticmethod
    184     def Transport():
    185         return SocketTransport
    186 
    187     @property
    188     def address(self):
    189         return self._address
    190 
    191     def __repr__(self):
    192         if self.socket:
    193             return '<%s at addr %s:%s>' % ((self.__guid__,) + self.socket.getsockname())
    194         else:
    195             return '<%s (closed)>' % self.__guid__
    196 
    197     def __init__(self, useACL, sock):
    198         super(SocketTransportAcceptor, self).__init__(useACL)
    199         self.socket = sock
    200         self._address = '%s:%s' % (socket.gethostname(), sock.getsockname()[1])
    201 
    202     def Accept(self):
    203         if self.socket is None:
    204             raise GPSTransportClosed('Listen socket closed.')
    205         if stackless.getcurrent().is_main:
    206             raise RuntimeError("Can't do an Accept() on the main thread")
    207         while True:
    208             s = None
    209             t = None
    210             try:
    211                 s, address = self.socket.accept()
    212                 if self.MaxPacketSize:
    213                     s.setmaxpacketsize(self.MaxPacketSize)
    214                 t = self.Transport()(s)
    215                 acl = self.CheckACL('%s:%d' % address)
    216                 if acl is not None:
    217                     t.Close(*acl)
    218                     continue
    219                 return t
    220             except socket.error as e:
    221                 if t is not None:
    222                     t.Close()
    223                 else:
    224                     self._closeSocket(s)
    225                 if e[0] in SOFT_CONNECTION_ERRORS:
    226                     sys.exc_clear()
    227                 else:
    228                     raise GPSException('accept failed: ', e)
    229             except Exception as e:
    230                 if t is not None:
    231                     t.Close()
    232                 else:
    233                     self._closeSocket(s)
    234                 raise e
    235 
    236     def close(self, reason = None):
    237         try:
    238             self.socket.close()
    239         except socket.error as e:
    240             sys.exc_clear()
    241 
    242         self.socket = None
    243 
    244     def _closeSocket(self, s):
    245         if s is None:
    246             return
    247         try:
    248             s.shutdown(socket.SHUT_RDWR)
    249         except Exception:
    250             pass
    251 
    252         try:
    253             s.close()
    254         except Exception:
    255             monolithmetrics.increment(metric=GPSSTATS_FAILED_TO_CLOSE_SOCKET_COUNTER, value=1, tags=None, sample_rate=1, prometheus_only=True)
    256 
    257 
    258 class SocketTransport(GPS.GPSTransport):
    259     __guid__ = 'gps.SocketTransport'
    260 
    261     def __init__(self, socket):
    262         super(SocketTransport, self).__init__()
    263         self.address = '%s:%s' % socket.getpeername()
    264         self.localaddress = '%s:%s' % socket.getsockname()
    265         self.socket = socket
    266         self.closeReason = None
    267         self.socketStatsEnabled = prefs.GetValue('socketStatsEnabled', False)
    268         self.statsBytesReadPerPacket = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_BYTESREADPERPACKET_PERIODS)
    269         self.statsBytesWrittenPerPacket = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_BYTESWRITTENPERPACKET_PERIODS)
    270         self.statsBytesRead = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_BYTESREAD_PERIODS)
    271         self.statsBytesWritten = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_BYTESWRITTEN_PERIODS)
    272         self.statsPacketsRead = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_PACKETSREAD_PERIODS)
    273         self.statsPacketsWritten = machoRunTimeStats.EWMA.FromSampleCounts(GPSSTATS_PACKETSWRITTEN_PERIODS)
    274         self.lastSocketActivityTimestamp = blue.os.GetWallclockTime()
    275 
    276     def StatsRepr(self):
    277         if self.socketStatsEnabled:
    278             return '([bs][pkts][bpp] RD [%s][%s][%s] WR [%s][%s][%s])' % (self.statsBytesRead,
    279              self.statsPacketsRead,
    280              self.statsBytesReadPerPacket,
    281              self.statsBytesWritten,
    282              self.statsPacketsWritten,
    283              self.statsBytesWrittenPerPacket)
    284         else:
    285             return '[Socket Stats Disabled]'
    286 
    287     def __repr__(self):
    288         if self.socket:
    289             return '<%s at addr %s:%s %s:%s, %s>' % ((self.__guid__,) + self.socket.getsockname() + self.socket.getpeername() + (self.StatsRepr(),))
    290         else:
    291             return '<%s (closed)>' % self.__guid__
    292 
    293     def GetSocket(self):
    294         return self.socket.getSocket()
    295 
    296     def GetIdleTime(self):
    297         return blue.os.TimeDiffInMs(self.lastSocketActivityTimestamp, blue.os.GetWallclockTime()) / 1000
    298 
    299     def Write(self, packet):
    300         if stackless.getcurrent().is_main:
    301             raise RuntimeError("You can't Write to a socket in a synchronous manner without blocking, dude.")
    302         try:
    303             self.socket.send(packet)
    304             self.lastSocketActivityTimestamp = blue.os.GetWallclockTime()
    305         except socket.error as e:
    306             idleTime = self.GetIdleTime()
    307             log.LogWarn('Write: Socket closed, idle time is %d seconds' % idleTime)
    308             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/ConnectionWasClosed'), 'Write() failed with socket.error'), exception=e)
    309             raise GPSTransportClosed(**self.closeReason)
    310         except Exception as e:
    311             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/SocketWasClosed'), 'Write() failed with Exception'), exception=e)
    312             log.LogTraceback()
    313             raise GPSTransportClosed(**self.closeReason)
    314 
    315         if self.socketStatsEnabled:
    316             self.statsBytesWrittenPerPacket.AddSample(len(packet))
    317             self.statsBytesWritten.Add(len(packet))
    318             self.statsPacketsWritten.Add()
    319 
    320     def Read(self, bufsize = 4096, flags = 0):
    321         if stackless.getcurrent().is_main:
    322             raise RuntimeError("You can't Read from a socket in a synchronous manner without blocking, dude.")
    323         try:
    324             r = self.socket.recv(bufsize, flags)
    325             self.lastSocketActivityTimestamp = blue.os.GetWallclockTime()
    326         except socket.error as e:
    327             idleTime = self.GetIdleTime()
    328             log.LogWarn('Read: Socket closed, idle time is %d seconds' % idleTime)
    329             clientError = localization.GetByLabel('/Carbon/MachoNet/SomethingHappenedSocketWasClosed')
    330             if e[0] in (10053, 10054, 995):
    331                 clientError = localization.GetByLabel('/Carbon/MachoNet/SocketWasClosed')
    332             else:
    333                 log.LogException()
    334             self.Close(SocketCloseReason(clientError, 'Read() failed with socket.error'), exception=e)
    335             raise GPSTransportClosed(**self.closeReason)
    336         except Exception as e:
    337             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/SomethingHappenedSocketWasClosed'), 'Read() failed with Exception'), exception=e)
    338             raise
    339 
    340         if not r:
    341             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/ConnectionWasClosed'), 'Read() returned nothing'))
    342             raise GPSTransportClosed(**self.closeReason)
    343         if self.socketStatsEnabled:
    344             self.statsBytesReadPerPacket.AddSample(len(r))
    345             self.statsBytesRead.Add(len(r))
    346             self.statsPacketsRead.Add()
    347         return r
    348 
    349     def Close(self, reason = None, reasonCode = None, reasonArgs = {}, exception = None, noSend = False):
    350         with bluepy.Timer('Socket::GPS::Close'):
    351             if not self.socket:
    352                 return
    353             if exception and monolithconfig.on_client():
    354                 stdlog.warning('Socket closed with Exception', exc_info=1)
    355             if not reason:
    356                 reason = 'Disconnected'
    357             if not self.closeReason:
    358                 self.closeReason = {'reason': reason,
    359                  'reasonCode': reasonCode,
    360                  'reasonArgs': reasonArgs,
    361                  'exception': exception}
    362             s, self.socket = self.socket, None
    363             if s:
    364                 self.Nerf()
    365                 self._Close(s, noSend)
    366 
    367     def _Close(self, s, noSend):
    368         try:
    369             s.shutdown(socket.SHUT_WR)
    370         except socket.error:
    371             pass
    372 
    373         try:
    374             s.close()
    375         except socket.error:
    376             monolithmetrics.increment(metric=GPSSTATS_FAILED_TO_CLOSE_SOCKET_COUNTER, value=1, tags=None, sample_rate=1, prometheus_only=True)
    377             log.LogException()
    378 
    379     def IsClosed(self):
    380         return self.socket is None
    381 
    382     def Nerf(self):
    383         self.Read = self.Write = self.NerfFunc(self.closeReason)
    384 
    385     @staticmethod
    386     def NerfFunc(reason):
    387 
    388         def Helper(*args):
    389             raise GPSTransportClosed(reason)
    390 
    391         return Helper
    392 
    393     def SetKeepalive(self, timeout, interval = None):
    394         if interval is None:
    395             interval = timeout
    396         try:
    397             self.socket.ioctl(socket.SIO_KEEPALIVE_VALS, (timeout > 0, int(timeout * 1000), int(interval * 1000)))
    398         except AttributeError:
    399             mylog.Log("socket doesn't support ioctl() ", log.LGWARN)
    400         except socket.error:
    401             log.LogException('socket.ioctl')
    402 
    403 
    404 class SocketPacketTransportFactory(SocketTransportFactory):
    405     __guid__ = 'gps.SocketPacketTransportFactory'
    406 
    407     @staticmethod
    408     def Transport():
    409         return SocketPacketTransport
    410 
    411     @staticmethod
    412     def Acceptor():
    413         return SocketPacketTransportAcceptor
    414 
    415 
    416 class SocketPacketTransportAcceptor(SocketTransportAcceptor):
    417     __guid__ = 'gps.SocketPacketTransportAcceptor'
    418 
    419     @staticmethod
    420     def Transport():
    421         return SocketPacketTransport
    422 
    423 
    424 class SocketPacketTransport(SocketTransport):
    425     __guid__ = 'gps.SocketPacketTransport'
    426 
    427     def __init__(self, sock):
    428         SocketTransport.__init__(self, sock)
    429         sock.setblockingsend(False)
    430         sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    431         self.packetQueue = {}
    432         self.packetNumber = -1
    433         self.numReorderedPackets = 0
    434 
    435     def Write(self, packet, header = None):
    436         global usingIOCP
    437         try:
    438             if header and usingIOCP:
    439                 self.socket.sendpacket(packet, header)
    440             else:
    441                 self.socket.sendpacket(packet)
    442             self.lastSocketActivityTimestamp = blue.os.GetWallclockTime()
    443         except socket.error as e:
    444             idleTime = self.GetIdleTime()
    445             log.LogInfo('Socket closed, idle time is %d seconds' % idleTime)
    446             if e[0] in NOBUF_ERRORS:
    447                 log.LogException()
    448             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/ConnectionWasClosed'), 'Write() failed with socket.error'), exception=e)
    449             raise GPSTransportClosed(**self.closeReason)
    450         except Exception as e:
    451             self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/SocketWasClosed'), 'Write() failed with socket.error'), exception=e)
    452             raise
    453 
    454         if self.socketStatsEnabled:
    455             self.statsBytesWrittenPerPacket.AddSample(len(packet))
    456             self.statsBytesWritten.Add(len(packet))
    457             self.statsPacketsWritten.Add()
    458 
    459     def Read(self, *args, **keywords):
    460         with bluepy.Timer('Socket::GPS::Read'):
    461             if stackless.getcurrent().is_main:
    462                 raise RuntimeError("You can't Read from a socket in a synchronous manner without blocking, dude.")
    463             try:
    464                 while True:
    465                     if self.packetNumber in self.packetQueue:
    466                         r = self.packetQueue[self.packetNumber]
    467                         serial = self.packetNumber
    468                         del self.packetQueue[self.packetNumber]
    469                         log.LogInfo('[Packet Order] address:', self.address, 'removed packet', self.packetNumber, 'from reordering map (queue:', len(self.packetQueue), 'elems)')
    470                         break
    471                     else:
    472                         value = self.socket.recvpacketoob()
    473                         self.lastSocketActivityTimestamp = blue.os.GetWallclockTime()
    474                     if value is not None:
    475                         r, oob, serial = value
    476                         if r is None and oob is None and serial == 0:
    477                             break
    478                         if self.packetNumber == -1:
    479                             self.packetNumber = serial
    480                         if self.packetNumber < serial:
    481                             log.LogInfo('[Packet Order] address:', self.address, 'got', serial, 'expected', self.packetNumber, ', adding to map (queue:', len(self.packetQueue), ' elems)')
    482                             self.packetQueue[serial] = r
    483                             self.numReorderedPackets += 1
    484                             if len(self.packetQueue) > 1024:
    485                                 raise RuntimeError('We seem to be indefinitely waiting for a packet.')
    486                             continue
    487                         elif self.packetNumber > serial:
    488                             log.LogError('[Packet Order] address:', self.address, 'got', serial, 'expected', self.packetNumber, ', dropping old packet (queue:', len(self.packetQueue), ' elems)')
    489                             continue
    490                         break
    491                     else:
    492                         r = None
    493                         break
    494 
    495                 self.packetNumber += 1
    496             except socket.error as e:
    497                 idleTime = self.GetIdleTime()
    498                 log.LogInfo('Socket closed, idle time is %d seconds' % idleTime)
    499                 if e[0] in NOBUF_ERRORS:
    500                     log.LogException()
    501                 self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/SocketWasClosed'), 'Read() failed with socket.error'), exception=e)
    502                 raise GPSTransportClosed(**self.closeReason)
    503             except Exception as e:
    504                 if isinstance(e, RuntimeError) and e.args and 'too large a packet' in e.args[0]:
    505                     self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/ConnectionWasClosed'), 'Read() failed with Exception'), exception=e)
    506                     raise GPSTransportClosed(**self.closeReason)
    507                 self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/SomethingHappenedSocketWasClosed'), 'Read() failed with Exception'), exception=e)
    508                 log.LogTraceback()
    509                 raise
    510 
    511             if r is None:
    512                 self.Close(SocketCloseReason(localization.GetByLabel('/Carbon/MachoNet/ConnectionWasClosed'), 'Read() returned nothing'))
    513                 raise GPSTransportClosed(**self.closeReason)
    514             if self.socketStatsEnabled:
    515                 self.statsBytesReadPerPacket.AddSample(len(r))
    516                 self.statsBytesRead.Add(len(r))
    517                 self.statsPacketsRead.Add()
    518             return r
    519 
    520     def _Close(self, s, noSend):
    521         flag = log.LGWARN
    522         exception = self.closeReason.get('exception', None)
    523         if self.closeReason and exception is None:
    524             flag = log.LGINFO
    525         mylog.Log('Closing connection to ' + self.address + ': ' + repr(self.closeReason), flag)
    526         if noSend or exception and exception[0] in CLOSE_SOCKET_ERRNOS:
    527             SocketTransport._Close(self, s, noSend)
    528         else:
    529             uthread.worker('Socket::DelayedClose', self._DelayedClose, s)
    530 
    531     def _DelayedClose(self, s):
    532         with bluepy.Timer('Socket::GPS::__DelayedClose'):
    533             try:
    534                 s.setblockingsend(True)
    535                 s.sendpacket(self.CreateClosedPacket(**self.closeReason))
    536             except socket.error as e:
    537                 mylog.Log("Couldn't send close packet, rhe socket is probably already closed. " + str(e), log.LGINFO)
    538             except AttributeError:
    539                 pass
    540             finally:
    541                 SocketTransport._Close(self, s, False)
    542 
    543 
    544 class SecureSocketPacketTransportFactory(SocketPacketTransportFactory):
    545     __guid__ = 'gps.SecureSocketPacketTransportFactory'
    546 
    547     @staticmethod
    548     def Transport():
    549         return SecureSocketPacketTransport
    550 
    551     @staticmethod
    552     def Acceptor():
    553         return SecureSocketPacketTransportAcceptor
    554 
    555 
    556 class SecureSocketPacketTransportAcceptor(SocketPacketTransportAcceptor):
    557     __guid__ = 'gps.SecureSocketPacketTransportAcceptor'
    558 
    559     @staticmethod
    560     def Transport():
    561         return SecureSocketPacketTransport
    562 
    563 
    564 class SecureSocketPacketTransport(SocketPacketTransport):
    565     __guid__ = 'gps.SecureSocketPacketTransport'
    566     __mandatory_fields__ = ['macho_version',
    567      'boot_version',
    568      'boot_build',
    569      'boot_codename',
    570      'boot_region',
    571      'user_name',
    572      'user_password',
    573      'user_password_hash',
    574      'user_languageid',
    575      'user_affiliateid']
    576 
    577     def __init__(self, *args, **keywords):
    578         SocketPacketTransport.__init__(self, *args, **keywords)
    579 
    580     UnEncryptedRead = SocketPacketTransport.Read
    581     UnEncryptedWrite = SocketPacketTransport.Write
    582     Read = SocketPacketTransport.EncryptedRead
    583     Write = SocketPacketTransport.EncryptedWrite
    584 
    585 
    586 class SSLSocketTransportFactory(SocketTransportFactory):
    587     __guid__ = 'gps.SSLSocketTransportFactory'
    588 
    589     def _PreSocketConnectOperations(self, socket):
    590         socket._sock.enableSSL()
    591 
    592 
    593 class SSLSocketPacketTransportFactory(SocketPacketTransportFactory):
    594     __guid__ = 'gps.SSLSocketPacketTransportFactory'
    595 
    596     def _PreSocketConnectOperations(self, socket):
    597         socket._sock.enableSSL()
    598 
    599     @staticmethod
    600     def Transport():
    601         return SSLSocketPacketTransport
    602 
    603     @staticmethod
    604     def Acceptor():
    605         return SSLSocketPacketTransportAcceptor
    606 
    607 
    608 class SSLSocketPacketTransportAcceptor(SocketPacketTransportAcceptor):
    609     __guid__ = 'gps.SSLSocketPacketTransportAcceptor'
    610 
    611     @staticmethod
    612     def Transport():
    613         return SSLSocketPacketTransport
    614 
    615 
    616 class SSLSocketPacketTransport(SocketPacketTransport):
    617     __guid__ = 'gps.SSLSocketPacketTransport'
    618     EncryptedRead = SocketPacketTransport.Read
    619     EncryptedWrite = SocketPacketTransport.Write
    620     UnEncryptedRead = SocketPacketTransport.Read
    621     UnEncryptedWrite = SocketPacketTransport.Write
    622 
    623     def CreateClosedPacket(self, reason, reasonCode = None, reasonArgs = {}, exception = None):
    624         msg = 'Creating Closed Packet: ' + reason
    625         if exception:
    626             msg += ' exception:' + repr(exception)
    627         log.general.Log(msg, log.LGINFO)
    628         etype = GPSRemoteTransportClosed
    629         etype = GPSTransportClosed
    630         exception = None
    631         packet = machobase.Dumps(etype(reason, reasonCode, reasonArgs, exception=exception))
    632         return packet
    633 
    634 
    635 def SocketCloseReason(clientReason, serverReason):
    636     if macho.mode in ('server', 'proxy'):
    637         return serverReason
    638     else:
    639         return clientReason