"""RPC Server module."""

import sys
import socket
import pickle
from fnmatch import fnmatch
from repr import repr


# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
VERBOSE = 1


class Server:

    """RPC Server class.  Derive a class to implement a particular service."""

    def __init__(self, address, verbose = VERBOSE):
        if type(address) == type(0):
            address = ('', address)
        self._address = address
        self._verbose = verbose
        self._socket = None
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.bind(address)
        self._socket.listen(1)
        self._listening = 1

    def _setverbose(self, verbose):
        self._verbose = verbose

    def __del__(self):
        self._close()

    def _close(self):
        self._listening = 0
        if self._socket:
            self._socket.close()
        self._socket = None

    def _serverloop(self):
        while self._listening:
            self._serve()

    def _serve(self):
        if self._verbose: print "Wait for connection ..."
        conn, address = self._socket.accept()
        if self._verbose: print "Accepted connection from %s" % repr(address)
        if not self._verify(conn, address):
            print "*** Connection from %s refused" % repr(address)
            conn.close()
            return
        rf = conn.makefile('r')
        wf = conn.makefile('w')
        ok = 1
        while ok:
            wf.flush()
            if self._verbose > 1: print "Wait for next request ..."
            ok = self._dorequest(rf, wf)

    _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*']

    def _verify(self, conn, address):
        host, port = address
        for pat in self._valid:
            if fnmatch(host, pat): return 1
        return 0

    def _dorequest(self, rf, wf):
        rp = pickle.Unpickler(rf)
        try:
            request = rp.load()
        except EOFError:
            return 0
        if self._verbose > 1: print "Got request: %s" % repr(request)
        try:
            methodname, args, id = request
            if '.' in methodname:
                reply = (None, self._special(methodname, args), id)
            elif methodname[0] == '_':
                raise NameError, "illegal method name %s" % repr(methodname)
            else:
                method = getattr(self, methodname)
                reply = (None, apply(method, args), id)
        except:
            reply = (sys.exc_type, sys.exc_value, id)
        if id < 0 and reply[:2] == (None, None):
            if self._verbose > 1: print "Suppress reply"
            return 1
        if self._verbose > 1: print "Send reply: %s" % repr(reply)
        wp = pickle.Pickler(wf)
        wp.dump(reply)
        return 1

    def _special(self, methodname, args):
        if methodname == '.methods':
            if not hasattr(self, '_methods'):
                self._methods = tuple(self._listmethods())
            return self._methods
        raise NameError, "unrecognized special method name %s" % repr(methodname)

    def _listmethods(self, cl=None):
        if not cl: cl = self.__class__
        names = cl.__dict__.keys()
        names = filter(lambda x: x[0] != '_', names)
        names.sort()
        for base in cl.__bases__:
            basenames = self._listmethods(base)
            basenames = filter(lambda x, names=names: x not in names, basenames)
            names[len(names):] = basenames
        return names


from security import Security


class SecureServer(Server, Security):

    def __init__(self, *args):
        apply(Server.__init__, (self,) + args)
        Security.__init__(self)

    def _verify(self, conn, address):
        import string
        challenge = self._generate_challenge()
        conn.send("%d\n" % challenge)
        response = ""
        while "\n" not in response and len(response) < 100:
            data = conn.recv(100)
            if not data:
                break
            response = response + data
        try:
            response = string.atol(string.strip(response))
        except string.atol_error:
            if self._verbose > 0:
                print "Invalid response syntax", repr(response)
            return 0
        if not self._compare_challenge_response(challenge, response):
            if self._verbose > 0:
                print "Invalid response value", repr(response)
            return 0
        if self._verbose > 1:
            print "Response matches challenge.  Go ahead!"
        return 1
