Esempio n. 1
0
 def bm_command_version(self):
     self.remoteProtocolVersion, self.services, self.timestamp, self.sockNode, self.peerNode, self.nonce, \
         self.userAgent, self.streams = self.decode_payload_content("IQQiiQlsLv")
     self.nonce = struct.pack('>Q', self.nonce)
     self.timeOffset = self.timestamp - int(time.time())
     logger.debug("remoteProtocolVersion: %i", self.remoteProtocolVersion)
     logger.debug("services: 0x%08X", self.services)
     logger.debug("time offset: %i", self.timestamp - int(time.time()))
     logger.debug("my external IP: %s", self.sockNode.host)
     logger.debug("remote node incoming address: %s:%i", self.destination.host, self.peerNode.port)
     logger.debug("user agent: %s", self.userAgent)
     logger.debug("streams: [%s]", ",".join(map(str,self.streams)))
     if not self.peerValidityChecks():
         # TODO ABORT
         return True
     #shared.connectedHostsList[self.destination] = self.streams[0]
     self.append_write_buf(protocol.CreatePacket('verack'))
     self.verackSent = True
     if not self.isOutbound:
         self.append_write_buf(protocol.assembleVersionMessage(self.destination.host, self.destination.port, \
                 network.connectionpool.BMConnectionPool().streams, True, nodeid=self.nodeid))
         #print "%s:%i: Sending version"  % (self.destination.host, self.destination.port)
     if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
             protocol.haveSSL(not self.isOutbound)):
         self.isSSL = True
     if self.verackReceived:
         if self.isSSL:
             self.set_state("tls_init", length=self.payloadLength, expectBytes=0)
             return False
         self.set_state("connection_fully_established", length=self.payloadLength, expectBytes=0)
         return False
     return True
Esempio n. 2
0
 def bm_command_version(self):
     self.remoteProtocolVersion, self.services, self.timestamp, self.sockNode, self.peerNode, self.nonce, \
         self.userAgent, self.streams = self.decode_payload_content("IQQiiQlsLv")
     self.nonce = struct.pack('>Q', self.nonce)
     self.timeOffset = self.timestamp - int(time.time())
     logger.debug("remoteProtocolVersion: %i", self.remoteProtocolVersion)
     logger.debug("services: 0x%08X", self.services)
     logger.debug("time offset: %i", self.timestamp - int(time.time()))
     logger.debug("my external IP: %s", self.sockNode.host)
     logger.debug("remote node incoming address: %s:%i", self.destination.host, self.peerNode.port)
     logger.debug("user agent: %s", self.userAgent)
     logger.debug("streams: [%s]", ",".join(map(str,self.streams)))
     if not self.peerValidityChecks():
         # TODO ABORT
         return True
     #shared.connectedHostsList[self.destination] = self.streams[0]
     self.append_write_buf(protocol.CreatePacket('verack'))
     self.verackSent = True
     if not self.isOutbound:
         self.append_write_buf(protocol.assembleVersionMessage(self.destination.host, self.destination.port, \
                 network.connectionpool.BMConnectionPool().streams, True, nodeid=self.nodeid))
         #print "%s:%i: Sending version"  % (self.destination.host, self.destination.port)
     if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
             protocol.haveSSL(not self.isOutbound)):
         self.isSSL = True
     if self.verackReceived:
         if self.isSSL:
             self.set_state("tls_init", length=self.payloadLength, expectBytes=0)
             return False
         self.set_state("connection_fully_established", length=self.payloadLength, expectBytes=0)
         return False
     return True
 def sslHandshake(self):
     self.sslSock = self.sock
     if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
         protocol.haveSSL(not self.initiatedConnection)):
         logger.debug("Initialising TLS")
         if sys.version_info >= (2,7,9):
             context = ssl.SSLContext(protocol.sslProtocolVersion)
             context.set_ciphers(protocol.sslProtocolCiphers)
             context.set_ecdh_curve("secp256k1")
             context.check_hostname = False
             context.verify_mode = ssl.CERT_NONE
             # also exclude TLSv1 and TLSv1.1 in the future
             context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE | ssl.OP_CIPHER_SERVER_PREFERENCE
             self.sslSock = context.wrap_socket(self.sock, server_side = not self.initiatedConnection, do_handshake_on_connect=False)
         else:
             self.sslSock = ssl.wrap_socket(self.sock, keyfile = os.path.join(paths.codePath(), 'sslkeys', 'key.pem'), certfile = os.path.join(paths.codePath(), 'sslkeys', 'cert.pem'), server_side = not self.initiatedConnection, ssl_version=protocol.sslProtocolVersion, do_handshake_on_connect=False, ciphers=protocol.sslProtocolCiphers)
         self.sendDataThreadQueue.join()
         while True:
             try:
                 self.sslSock.do_handshake()
                 logger.debug("TLS handshake success")
                 if sys.version_info >= (2, 7, 9):
                     logger.debug("TLS protocol version: %s", self.sslSock.version())
                 break
             except ssl.SSLError as e:
                 if sys.hexversion >= 0x02070900:
                     if isinstance (e, ssl.SSLWantReadError):
                         logger.debug("Waiting for SSL socket handhake read")
                         select.select([self.sslSock], [], [], 10)
                         continue
                     elif isinstance (e, ssl.SSLWantWriteError):
                         logger.debug("Waiting for SSL socket handhake write")
                         select.select([], [self.sslSock], [], 10)
                         continue
                 else:
                     if e.args[0] == ssl.SSL_ERROR_WANT_READ:
                         logger.debug("Waiting for SSL socket handhake read")
                         select.select([self.sslSock], [], [], 10)
                         continue
                     elif e.args[0] == ssl.SSL_ERROR_WANT_WRITE:
                         logger.debug("Waiting for SSL socket handhake write")
                         select.select([], [self.sslSock], [], 10)
                         continue
                 logger.error("SSL socket handhake failed: shutting down connection, %s", str(e))
                 self.sendDataThreadQueue.put((0, 'shutdown','tls handshake fail %s' % (str(e))))
                 return False
             except socket.error as err:
                 logger.debug('SSL socket handshake failed, shutting down connection, %s', str(err))
                 self.sendDataThreadQueue.put((0, 'shutdown','tls handshake fail'))
                 return False
             except Exception:
                 logger.error("SSL socket handhake failed, shutting down connection", exc_info=True)
                 self.sendDataThreadQueue.put((0, 'shutdown','tls handshake fail'))
                 return False
         # SSL in the background should be blocking, otherwise the error handling is difficult
         self.sslSock.settimeout(None)
         return True
     # no SSL
     return True
Esempio n. 4
0
    def connectionFullyEstablished(self):
        if self.connectionIsOrWasFullyEstablished:
            # there is no reason to run this function a second time
            return

        if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
            protocol.haveSSL(not self.initiatedConnection)):
            try:
                self.sslHandshake()
            except socket.error as ex:
                logger.error("SSL socket handshake failed, shutting down connection", exc_info=(type(ex), ex, None))
                self.sendDataThreadQueue.put((0, 'shutdown', None))
                return

        self.connectionIsOrWasFullyEstablished = True
        shared.timeOffsetWrongCount = 0

        # Command the corresponding sendDataThread to set its own connectionIsOrWasFullyEstablished variable to True also
        self.sendDataThreadQueue.put((0, 'connectionIsOrWasFullyEstablished', (self.services, self.sock)))

        if not self.initiatedConnection:
            shared.clientHasReceivedIncomingConnections = True
            queues.UISignalQueue.put(('setStatusIcon', 'green'))
        self.sock.settimeout(
            600)  # We'll send out a ping every 5 minutes to make sure the connection stays alive if there has been no other traffic to send lately.
        queues.UISignalQueue.put(('updateNetworkStatusTab', 'no data'))
        logger.debug('Connection fully established with ' + str(self.peer) + "\n" + \
            'The size of the connectedHostsList is now ' + str(len(shared.connectedHostsList)) + "\n" + \
            'The length of sendDataQueues is now: ' + str(len(state.sendDataQueues)) + "\n" + \
            'broadcasting addr from within connectionFullyEstablished function.')

        if self.initiatedConnection:
            state.networkProtocolAvailability[protocol.networkType(self.peer.host)] = True

        # we need to send our own objects to this node
        PendingUpload().add()

        self.sendaddr()  # This is one large addr message to this one peer.
        if len(shared.connectedHostsList) > \
            BMConfigParser().safeGetInt("bitmessagesettings", "maxtotalconnections", 200):
            logger.info ('We are connected to too many people. Closing connection.')
            if self.initiatedConnection:
                self.sendDataThreadQueue.put((0, 'sendRawData', protocol.assembleErrorMessage(fatal=2, errorText="Thank you for providing a listening node.")))
            else:
                self.sendDataThreadQueue.put((0, 'sendRawData', protocol.assembleErrorMessage(fatal=2, errorText="Server full, please try again later.")))
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            return
        self.sendBigInv()
    def sendBytes(self, data=""):
        self.buffer += data
        if len(self.buffer) < throttle.SendThrottle(
        ).chunkSize and self.sendDataThreadQueue.qsize() > 1:
            return True

        while self.buffer and state.shutdown == 0:
            isSSL = False
            try:
                if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL)
                        and self.connectionIsOrWasFullyEstablished
                        and protocol.haveSSL(not self.initiatedConnection)):
                    isSSL = True
                    amountSent = self.sslSock.send(
                        self.buffer[:throttle.SendThrottle().chunkSize])
                else:
                    amountSent = self.sock.send(
                        self.buffer[:throttle.SendThrottle().chunkSize])
            except socket.timeout:
                continue
            except SSLError as e:
                if e.errno == SSL_ERROR_WANT_WRITE:
                    select.select([], [self.sslSock], [], 10)
                    logger.debug('sock.recv retriable SSL error')
                    continue
                logger.debug('Connection error (SSL)')
                return False
            except socket.error as e:
                if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK) or \
                    (sys.platform.startswith('win') and \
                    e.errno == errno.WSAEWOULDBLOCK):
                    select.select([], [self.sslSock if isSSL else self.sock],
                                  [], 10)
                    logger.debug('sock.recv retriable error')
                    continue
                if e.errno in (errno.EPIPE, errno.ECONNRESET,
                               errno.EHOSTUNREACH, errno.ETIMEDOUT):
                    logger.debug(
                        'Connection error (EPIPE/ECONNRESET/EHOSTUNREACH/ETIMEDOUT)'
                    )
                    return False
                raise
            throttle.SendThrottle().wait(amountSent)
            self.lastTimeISentData = int(time.time())
            self.buffer = self.buffer[amountSent:]
        return True
Esempio n. 6
0
 def bm_command_version(self):
     """
     Incoming version.
     Parse and log, remember important things, like streams, bitfields, etc.
     """
     decoded = self.decode_payload_content("IQQiiQlslv")
     (self.remoteProtocolVersion, self.services, self.timestamp,
      self.sockNode, self.peerNode, self.nonce,
      self.userAgent) = decoded[:7]
     self.streams = decoded[7:]
     self.nonce = struct.pack('>Q', self.nonce)
     self.timeOffset = self.timestamp - int(time.time())
     logger.debug('remoteProtocolVersion: %i', self.remoteProtocolVersion)
     logger.debug('services: 0x%08X', self.services)
     logger.debug('time offset: %i', self.timeOffset)
     logger.debug('my external IP: %s', self.sockNode.host)
     logger.debug('remote node incoming address: %s:%i',
                  self.destination.host, self.peerNode.port)
     logger.debug('user agent: %s', self.userAgent)
     logger.debug('streams: [%s]', ','.join(map(str, self.streams)))
     if not self.peerValidityChecks():
         # ABORT afterwards
         return True
     self.append_write_buf(protocol.CreatePacket('verack'))
     self.verackSent = True
     if not self.isOutbound:
         self.append_write_buf(
             protocol.assembleVersionMessage(
                 self.destination.host,
                 self.destination.port,
                 connectionpool.BMConnectionPool().streams,
                 True,
                 nodeid=self.nodeid))
         logger.debug('%(host)s:%(port)i sending version',
                      self.destination._asdict())
     if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL)
             and protocol.haveSSL(not self.isOutbound)):
         self.isSSL = True
     if not self.verackReceived:
         return True
     self.set_state(
         "tls_init" if self.isSSL else "connection_fully_established",
         length=self.payloadLength,
         expectBytes=0)
     return False
    def sendBytes(self, data = ""):
        self.buffer += data
        if len(self.buffer) < throttle.SendThrottle().chunkSize and self.sendDataThreadQueue.qsize() > 1:
            return True

        while self.buffer and state.shutdown == 0:
            isSSL = False
            try:
                if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
                    self.connectionIsOrWasFullyEstablished and
                    protocol.haveSSL(not self.initiatedConnection)):
                    isSSL = True
                    amountSent = self.sslSock.send(self.buffer[:throttle.SendThrottle().chunkSize])
                else:
                    amountSent = self.sock.send(self.buffer[:throttle.SendThrottle().chunkSize])
            except socket.timeout:
                continue
            except SSLError as e:
                if e.errno == SSL_ERROR_WANT_WRITE:
                    select.select([], [self.sslSock], [], 10)
                    logger.debug('sock.recv retriable SSL error')
                    continue
                logger.debug('Connection error (SSL)')
                return False
            except socket.error as e:
                if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK) or \
                    (sys.platform.startswith('win') and \
                    e.errno == errno.WSAEWOULDBLOCK):
                    select.select([], [self.sslSock if isSSL else self.sock], [], 10)
                    logger.debug('sock.recv retriable error')
                    continue
                if e.errno in (errno.EPIPE, errno.ECONNRESET, errno.EHOSTUNREACH, errno.ETIMEDOUT, errno.ECONNREFUSED):
                    logger.debug('Connection error: %s', str(e))
                    return False
                raise
            throttle.SendThrottle().wait(amountSent)
            self.lastTimeISentData = int(time.time())
            self.buffer = self.buffer[amountSent:]
        return True
Esempio n. 8
0
    def run(self):
        logger.debug('receiveDataThread starting. ID ' + str(id(self)) +
                     '. The size of the shared.connectedHostsList is now ' +
                     str(len(shared.connectedHostsList)))

        while state.shutdown == 0:
            dataLen = len(self.data)
            try:
                isSSL = False
                if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL)
                        and self.connectionIsOrWasFullyEstablished
                        and protocol.haveSSL(not self.initiatedConnection)):
                    isSSL = True
                    dataRecv = self.sslSock.recv(
                        throttle.ReceiveThrottle().chunkSize)
                else:
                    dataRecv = self.sock.recv(
                        throttle.ReceiveThrottle().chunkSize)
                self.data += dataRecv
                throttle.ReceiveThrottle().wait(len(dataRecv))
            except socket.timeout:
                if self.connectionIsOrWasFullyEstablished:
                    self.sendping("Still around!")
                    continue
                logger.error("Timeout during protocol initialisation")
                break
            except ssl.SSLError as err:
                if err.errno == ssl.SSL_ERROR_WANT_READ:
                    select.select([self.sslSock], [], [], 10)
                    logger.debug('sock.recv retriable SSL error')
                    continue
                if err.errno is None and 'timed out' in str(err):
                    if self.connectionIsOrWasFullyEstablished:
                        self.sendping("Still around!")
                        continue
                logger.error('SSL error: %i/%s', err.errno if err.errno else 0,
                             str(err))
                break
            except socket.error as err:
                if err.errno in (errno.EAGAIN, errno.EWOULDBLOCK) or \
                    (sys.platform.startswith('win') and \
                    err.errno == errno.WSAEWOULDBLOCK):
                    select.select([self.sslSock if isSSL else self.sock], [],
                                  [], 10)
                    logger.debug('sock.recv retriable error')
                    continue
                logger.error('sock.recv error. Closing receiveData thread (' +
                             str(self.peer) + ', Thread ID: ' + str(id(self)) +
                             ').' + str(err.errno) + "/" + str(err))
                break
            # print 'Received', repr(self.data)
            if len(self.data
                   ) == dataLen:  # If self.sock.recv returned no data:
                logger.debug('Connection to ' + str(self.peer) +
                             ' closed. Closing receiveData thread. (ID: ' +
                             str(id(self)) + ')')
                break
            else:
                self.processData()

        try:
            for stream in self.streamNumber:
                try:
                    del self.selfInitiatedConnections[stream][self]
                except KeyError:
                    pass
            logger.debug(
                'removed self (a receiveDataThread) from selfInitiatedConnections'
            )
        except:
            pass
        self.sendDataThreadQueue.put(
            (0, 'shutdown', 'no data')
        )  # commands the corresponding sendDataThread to shut itself down.
        try:
            del shared.connectedHostsList[self.hostIdent]
        except Exception as err:
            logger.error('Could not delete ' + str(self.hostIdent) +
                         ' from shared.connectedHostsList.' + str(err))

        PendingDownload().threadEnd()
        queues.UISignalQueue.put(('updateNetworkStatusTab', 'no data'))
        self.checkTimeOffsetNotification()
        logger.debug('receiveDataThread ending. ID ' + str(id(self)) +
                     '. The size of the shared.connectedHostsList is now ' +
                     str(len(shared.connectedHostsList)))
Esempio n. 9
0
 def sslHandshake(self):
     self.sslSock = self.sock
     if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL)
             and protocol.haveSSL(not self.initiatedConnection)):
         logger.debug("Initialising TLS")
         if sys.version_info >= (2, 7, 9):
             context = ssl.SSLContext(protocol.sslProtocolVersion)
             context.set_ciphers(protocol.sslProtocolCiphers)
             context.set_ecdh_curve("secp256k1")
             context.check_hostname = False
             context.verify_mode = ssl.CERT_NONE
             # also exclude TLSv1 and TLSv1.1 in the future
             context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE | ssl.OP_CIPHER_SERVER_PREFERENCE
             self.sslSock = context.wrap_socket(
                 self.sock,
                 server_side=not self.initiatedConnection,
                 do_handshake_on_connect=False)
         else:
             self.sslSock = ssl.wrap_socket(
                 self.sock,
                 keyfile=os.path.join(paths.codePath(), 'sslkeys',
                                      'key.pem'),
                 certfile=os.path.join(paths.codePath(), 'sslkeys',
                                       'cert.pem'),
                 server_side=not self.initiatedConnection,
                 ssl_version=protocol.sslProtocolVersion,
                 do_handshake_on_connect=False,
                 ciphers=protocol.sslProtocolCiphers)
         self.sendDataThreadQueue.join()
         while True:
             try:
                 self.sslSock.do_handshake()
                 logger.debug("TLS handshake success")
                 break
             except ssl.SSLError as e:
                 if sys.hexversion >= 0x02070900:
                     if isinstance(e, ssl.SSLWantReadError):
                         logger.debug(
                             "Waiting for SSL socket handhake read")
                         select.select([self.sslSock], [], [], 10)
                         continue
                     elif isinstance(e, ssl.SSLWantWriteError):
                         logger.debug(
                             "Waiting for SSL socket handhake write")
                         select.select([], [self.sslSock], [], 10)
                         continue
                 else:
                     if e.args[0] == ssl.SSL_ERROR_WANT_READ:
                         logger.debug(
                             "Waiting for SSL socket handhake read")
                         select.select([self.sslSock], [], [], 10)
                         continue
                     elif e.args[0] == ssl.SSL_ERROR_WANT_WRITE:
                         logger.debug(
                             "Waiting for SSL socket handhake write")
                         select.select([], [self.sslSock], [], 10)
                         continue
                 logger.error(
                     "SSL socket handhake failed: %s, shutting down connection",
                     str(e))
                 self.sendDataThreadQueue.put(
                     (0, 'shutdown', 'tls handshake fail %s' % (str(e))))
                 return False
             except Exception:
                 logger.error(
                     "SSL socket handhake failed, shutting down connection",
                     exc_info=True)
                 self.sendDataThreadQueue.put(
                     (0, 'shutdown', 'tls handshake fail'))
                 return False
         # SSL in the background should be blocking, otherwise the error handling is difficult
         self.sslSock.settimeout(None)
         return True
     # no SSL
     return True
    def run(self):
        logger.debug('receiveDataThread starting. ID ' + str(id(self)) + '. The size of the shared.connectedHostsList is now ' + str(len(shared.connectedHostsList)))

        while state.shutdown == 0:
            dataLen = len(self.data)
            try:
                isSSL = False
                if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
                    self.connectionIsOrWasFullyEstablished and
                    protocol.haveSSL(not self.initiatedConnection)):
                    isSSL = True
                    dataRecv = self.sslSock.recv(throttle.ReceiveThrottle().chunkSize)
                else:
                    dataRecv = self.sock.recv(throttle.ReceiveThrottle().chunkSize)
                self.data += dataRecv
                throttle.ReceiveThrottle().wait(len(dataRecv))
            except socket.timeout:
                if self.connectionIsOrWasFullyEstablished:
                    self.sendping("Still around!")
                    continue
                logger.error("Timeout during protocol initialisation")
                break
            except ssl.SSLError as err:
                if err.errno == ssl.SSL_ERROR_WANT_READ:
                    select.select([self.sslSock], [], [], 10)
                    logger.debug('sock.recv retriable SSL error')
                    continue
                if err.errno is None and 'timed out' in str(err):
                    if self.connectionIsOrWasFullyEstablished:
                        self.sendping("Still around!")
                        continue
                logger.error ('SSL error: %i/%s', err.errno if err.errno else 0, str(err))
                break
            except socket.error as err:
                if err.errno in (errno.EAGAIN, errno.EWOULDBLOCK) or \
                    (sys.platform.startswith('win') and \
                    err.errno == errno.WSAEWOULDBLOCK):
                    select.select([self.sslSock if isSSL else self.sock], [], [], 10)
                    logger.debug('sock.recv retriable error')
                    continue
                logger.error('sock.recv error. Closing receiveData thread, %s', str(err))
                break
            # print 'Received', repr(self.data)
            if len(self.data) == dataLen: # If self.sock.recv returned no data:
                logger.debug('Connection to ' + str(self.peer) + ' closed. Closing receiveData thread')
                break
            else:
                self.processData()

        try:
            for stream in self.streamNumber:
                try:
                    del self.selfInitiatedConnections[stream][self]
                except KeyError:
                    pass
            logger.debug('removed self (a receiveDataThread) from selfInitiatedConnections')
        except:
            pass
        self.sendDataThreadQueue.put((0, 'shutdown','no data')) # commands the corresponding sendDataThread to shut itself down.
        try:
            del shared.connectedHostsList[self.hostIdent]
        except Exception as err:
            logger.error('Could not delete ' + str(self.hostIdent) + ' from shared.connectedHostsList.' + str(err))

        queues.UISignalQueue.put(('updateNetworkStatusTab', 'no data'))
        self.checkTimeOffsetNotification()
        logger.debug('receiveDataThread ending. ID ' + str(id(self)) + '. The size of the shared.connectedHostsList is now ' + str(len(shared.connectedHostsList)))