# emacs-mode: -*- python-*-
from aosocket.async_socket import AsyncSocket
from aosocket.async_socket_exceptions import *
from aosocket.symbian.bt_utils import check_mac
from aosocket.symbian.symbian_socket import *
from aosocketnativenew import AoImmediate, AoPortDiscoverer
class SymbianNativeError(Exception,):
    __module__ = __name__

    def __init__(self, value):
        '\n        Records ``value``, which should be the error code\n        of the Symbian native error.\n        '
        self.value = value



    def __str__(self):
        return repr(self.value)



class SymbianAsyncSocket(AsyncSocket,):
    __module__ = __name__
    __doc__ = '\n    An abstract class intended to be used as a base class\n    in ``AsyncSocket`` interface implementations for Symbian OS.\n    '

    def __init__(self, socket_serv, **kw):
        self.socket_serv = socket_serv
        if kw.has_key('em_socket'):
            self.socket = kw['em_socket']
        else:
            self.socket = self.new_ll_socket()



    def new_ll_socket(self):
        '\n        Returns a new low-level socket object of the kind\n        used by the particular ``SymbianAsyncSocket``.\n\n        Subclassers must implement.\n        '
        raise NotImplementedError



    def close(self):
        self.socket.close()



    def recv(self, size, cb_func, cb_param):
        self.socket.recv(size, self._SymbianAsyncSocket__recv_cb, (cb_func,
         cb_param))



    def __recv_cb(self, error, data, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'recv', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'recv', None, data, cb_param)



    def sendall(self, data, cb_func, cb_param):
        self.socket.sendall(data, self._SymbianAsyncSocket__sendall_cb, (cb_func,
         cb_param))



    def __sendall_cb(self, error, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'sendall', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'sendall', None, None, cb_param)



class TcpSymbianAsyncSocket(SymbianAsyncSocket,):
    __module__ = __name__
    __doc__ = '\n    Implements the ``AsyncSocket`` interface utilizing\n    the lower-level operations provided by ``TcpSymbianSocket``.\n    '

    def __init__(self, socket_serv, **kw):
        SymbianAsyncSocket.__init__(self, socket_serv, **kw)
        self.immediate = AoImmediate()
        self.immediate.open()



    def close(self):
        self.immediate.close()
        SymbianAsyncSocket.close(self)



    def new_ll_socket(self):
        return TcpSymbianSocket()



    def listen(self, cb_func, cb_param, **kw):
        '\n        Binds the socket to the specified port at the specified\n        network interface. Also has the socket start listening for\n        connections. The maximum size of the backlog is optionally\n        specified by ``number``.\n        '
        host = kw['host']
        if (not host):
            raise TypeError, 'no host address given'
        port = kw['port']
        if (not port):
            raise TypeError, 'no port number given'
        address = (host,
         port)
        number = None
        if kw.has_key('number'):
            number = kw['number']
        if (not number):
            number = 5
        self.socket.listen(self.socket_serv, address, number)
        self.immediate.complete(self._TcpSymbianAsyncSocket__listen_cb, (cb_func,
         cb_param))



    def __listen_cb(self, error, param):
        (cb_func, cb_param,) = param
        cb_func(self, 'listen', None, None, cb_param)



    def accept(self, cb_func, cb_param):
        '\n        Once the socket is bound and listening, accepts a connection\n        asynchronously.\n        '
        bl_socket = self.new_ll_socket()
        bl_socket.blank(self.socket_serv)
        self.socket.accept(bl_socket, self._TcpSymbianAsyncSocket__accept_cb, (cb_func,
         cb_param))



    def __accept_cb(self, error, bl_socket, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'accept', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'accept', None, TcpSymbianAsyncSocket(self.socket_serv, em_socket=bl_socket), cb_param)



    def connect(self, cb_func, cb_param, **kw):
        '\n        Connects to the specified port of the specified host.\n        '
        host = kw['host']
        if (not host):
            raise TypeError, 'no host address given'
        port = kw['port']
        if (not port):
            raise TypeError, 'no port number given'
        address = (host,
         port)
        self.socket.connect(self.socket_serv, address, self._TcpSymbianAsyncSocket__connect_cb, (cb_func,
         cb_param))



    def __connect_cb(self, error, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'connect', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'connect', None, None, cb_param)



class BtSymbianAsyncSocket(SymbianAsyncSocket,):
    __module__ = __name__
    __doc__ = '\n    Implements the ``AsyncSocket`` interface utilizing\n    the lower-level operations provided by ``BtSymbianSocket``.\n    '

    def __init__(self, socket_serv, **kw):
        SymbianAsyncSocket.__init__(self, socket_serv, **kw)
        self.discoverer = AoPortDiscoverer()
        self.discoverer.open()



    def close(self):
        self.discoverer.close()
        SymbianAsyncSocket.close(self)



    def new_ll_socket(self):
        return BtSymbianSocket()



    def listen(self, cb_func, cb_param, **kw):
        '\n        If you want, you may pass the "port" keyword argument to\n        specify which port to bind to--otherwise, a free one is\n        allocated automatically. Note that there is no need to specify\n        any local address other than the port--it is assumed that\n        there is only one Bluetooth interface, and that one will be\n        used automatically.\n\n        If you do not want to use the default value, use the "number"\n        keyword argument to specify the queue size for peer-initiated\n        connections.\n\n        For SDP advertising purposes, you must supply the "service_id"\n        and "service_name" keyword arguments.\n        '
        port = None
        if kw.has_key('port'):
            port = kw['port']
        address = (None,
         port)
        number = None
        if kw.has_key('number'):
            number = kw['number']
        if (not number):
            number = 5
        service_id = None
        if kw.has_key('service_id'):
            service_id = kw['service_id']
        if (not service_id):
            raise ValueError, 'service ID not given'
        service_name = None
        if kw.has_key('service_name'):
            service_name = kw['service_name']
        if (not service_name):
            raise ValueError, 'service name not given'
        self.socket.listen(self.socket_serv, address, number, service_id, service_name)
        self.socket.configure(self._BtSymbianAsyncSocket__config_cb, (cb_func,
         cb_param))



    def __config_cb(self, error, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'listen', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'listen', None, None, cb_param)



    def accept(self, cb_func, cb_param, **kw):
        bl_socket = self.new_ll_socket()
        bl_socket.blank(self.socket_serv)
        self.socket.accept(bl_socket, self._BtSymbianAsyncSocket__accept_cb, (cb_func,
         cb_param))



    def __accept_cb(self, error, bl_socket, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'accept', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'accept', None, BtSymbianAsyncSocket(self.socket_serv, em_socket=bl_socket), cb_param)



    def connect(self, cb_func, cb_param, **kw):
        '\n        You should specify either the "host" and "port" to connect to,\n        or the "host" and "service_id" to connect to. In the latter\n        case, an attempt is made to have the port discovered using\n        SDP.\n        '
        host = None
        if kw.has_key('host'):
            host = kw['host']
        if (not host):
            raise ValueError, 'host address not given'
        port = None
        if kw.has_key('port'):
            port = kw['port']
        if port:
            self.socket.connect(self.socket_serv, (host,
             port), self._BtSymbianAsyncSocket__connect_cb, (cb_func,
             cb_param))
        else:
            check_mac(host)
            service_id = None
            if kw.has_key('service_id'):
                service_id = kw['service_id']
            if (not service_id):
                raise TypeError, 'no port or service ID specified'
            self.discoverer.discover(unicode(host), service_id, self._BtSymbianAsyncSocket__discover_cb, (cb_func,
             cb_param,
             host))



    def __discover_cb(self, error, port, param):
        (cb_func, cb_param, host,) = param
        if error:
            cb_func(self, 'connect', SymbianNativeError(error), None, cb_param)
        else:
            try:
                self.socket.connect(self.socket_serv, (host,
                 port), self._BtSymbianAsyncSocket__connect_cb, (cb_func,
                 cb_param))
            except Exception, exc:
                cb_func(self, 'connect', exc, None, cb_param)



    def __connect_cb(self, error, param):
        (cb_func, cb_param,) = param
        if error:
            cb_func(self, 'connect', SymbianNativeError(error), None, cb_param)
        else:
            cb_func(self, 'connect', None, None, cb_param)




# local variables:
# tab-width: 4
