Question

Im trying to programming a simplest client-server application with SSL, and i have some issues with this:
1) How i can decrease time for serialization at JSON?
2) Maybe something exists for better than LineReciver, for creating communication between server and client? Or i can increase length of received lines?

Source code:
a) ServerSLL

import server  
from twisted.internet.protocol import Factory  
from twisted.internet import reactor  
from OpenSSL import SSL   

class ServerSSL(object):
    def getContext(self):
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.use_certificate_file('server_cert.pem')
        ctx.use_privatekey_file('server_key.pem')
        return ctx


if __name__ == '__main__':
    factory = Factory()
    factory.protocol = server.Server
    reactor.listenSSL(8000, factory, ServerSSL())
    reactor.run()

b) Server

from json import dumps, loads 
import sqlalchemy
from sqlalchemy.orm import sessionmaker
from db.create_db import Users
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor

engine = sqlalchemy.create_engine('postgresql://user:test@localhost/csan', pool_size=20, max_overflow=0)


class Server(Protocol):
    def __init__(self):
        self.Session = sessionmaker(bind=engine)

    def __del__(self):
        self.session.close()

    def authorization(self, data):
        """
            Checking user with DB
        """
        session = self.Session()
        result = session.execute(sqlalchemy.select([Users]).where(Users.name == data['user']))
        result = result.fetchone()
        if result is None:
            data['error'] = 404
        else:
            if result['name'] == data['user']:
                # correct users info --> real user
                if result['password'] == data['pswd']:
                    data['auth'] = 1
                # incorrect password --> fake user
                else:
                    data['error'] = 403
        session.close()
        return data

    def dataReceived(self, data):
        """
            Processing request from user and send response
        """
        new_data = loads(data)
        if new_data['cmd'] == 'AUTH':
            response = self.authorization(new_data)
        self.transport.write(str(dumps(new_data)))


if __name__ == '__main__':
    f = Factory()
    f.protocol = Server
    reactor.listenTCP(8000, f)
    reactor.run()

c) client_console

from json import dumps, loads
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet import ssl, reactor

class ServerClientSSL(LineReceiver):
    """
        Basic client for talking with server under SSL
    """

    def connectionMade(self):
        """
        Send auth request to serverSLL.py
        """
        login = raw_input('Login:')
        password = raw_input('Password:')
        hash_password = str(hash(password))
        data = dumps({'cmd': 'AUTH', 'user': login, 'pswd': hash_password, 'auth': 0, 'error': 0})
        self.sendLine(str(data))

    def connectionLost(self, reason):
        """
            Says to client, why we are close connection
        """
        print 'connection lost (protocol)'

    def lineReceived(self, data):
        """
            Processing responses from serverSSL.py and send new requests to there
        """
        new_data = loads(data)
        if new_data['cmd'] == 'BBYE':
            self.transport.loseConnection()
        else:
            print new_data


class ServerClientSLLFactory(ClientFactory):
    protocol = ServerClientSSL

    def clientConnectionFailed(self, connector, reason):
        print 'connection failed:', reason.getErrorMessage()
        reactor.stop()

    def clientConnectionLost(self, connector, reason):
        print 'connection lost:', reason.getErrorMessage()
        reactor.stop()

if __name__ == '__main__':
    import sys
    if len(sys.argv) < 3:
        print 'Using: python client_console.py [IP] [PORT] '
    else:
        ip = sys.argv[1]
        port = sys.argv[2]
        factory = ServerClientSLLFactory()
        reactor.connectSSL(ip, int(port), factory, ssl.ClientContextFactory())
        reactor.run()
Was it helpful?

Solution

class ServerSSL(object):
    ...

Don't write your own context factory. Use twisted.internet.ssl.CertificateOptions instead. It has fewer problems than what you have here.

def __del__(self):
    self.session.close()

First rule of __del__: don't use __del__. Adding this method doesn't give you automatic session cleanup. Instead, it almost certainly guarantees your session will never be be cleaned up. Protocols have a method that gets called when they're done - it's called connectionLost. Use that instead.

result = session.execute(sqlalchemy.select([Users]).where(Users.name == data['user']))
result = result.fetchone()

Twisted is a single-threaded multi-tasking system. These statements block on network I/O and database operations. While they're running your server isn't doing anything else.

Use twisted.enterprise.adbapi or twext.enterprise.adbapi2 or alchimiato perform database interactions asynchronously instead.

class ServerClientSSL(LineReceiver):
    ...

There are lots of protocols better than LineReceiver. The simplest improvement you can make is to switch to Int32StringReceiver. A more substantial improvement would be to switch to twisted.protocols.amp.

1) How i can decrease time for serialization at JSON?

Use a faster JSON library. After you fix the blocking database code in your application, though, I doubt you'll still need a faster JSON library.

2) Maybe something exists for better than LineReciver, for creating communication between server and client? Or i can increase length of received lines?

LineReceiver.MAX_LENGTH. After you switch to Int32StringReceiver or AMP you won't need this anymore though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top