Statistics
| Branch: | Tag: | Revision:

root / ncclient / session.py @ 38a9b062

History | View | Annotate | Download (3.3 kB)

1
# Copyright 2009 Shikhar Bhushan
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
import logging
16

    
17
import content
18

    
19
from threading import Thread, Event
20
from Queue import Queue
21

    
22
from capability import CAPABILITIES
23
from error import ClientError
24
from subject import Subject
25

    
26
logger = logging.getLogger('ncclient.session')
27

    
28
class SessionError(ClientError):
29
    
30
    pass
31

    
32
class Session(Thread, Subject):
33
    
34
    def __init__(self):
35
        Thread.__init__(self, name='session')
36
        Subject.__init__(self, listeners=[Session.HelloListener(self)])
37
        self._client_capabilities = CAPABILITIES
38
        self._server_capabilities = None # yet
39
        self._id = None # session-id
40
        self._connected = False # subclasses should set this
41
        self._error = None
42
        self._init_event = Event()
43
        self._q = Queue()
44
    
45
    def send(self, message):
46
        message = (u'<?xml version="1.0" encoding="UTF-8"?>%s' % message).encode('utf-8')
47
        logger.debug('queueing message: \n%s' % message)
48
        self._q.put(message)
49
    
50
    def connect(self):
51
        raise NotImplementedError
52

    
53
    def run(self):
54
        raise NotImplementedError
55
    
56
    ### Properties
57

    
58
    @property
59
    def client_capabilities(self):
60
        return self._client_capabilities
61
    
62
    @property
63
    def serve_capabilities(self):
64
        return self._server_capabilities
65
    
66
    @property
67
    def connected(self):
68
        return self._connected
69
    
70
    @property
71
    def id(self):
72
        return self._id
73
    
74
    def _post_connect(self):
75
        # start the subclass' main loop
76
        self.start()
77
        # queue client's hello message for sending
78
        self.send(content.make_hello(self._client_capabilities))
79
        # we expect server's hello message, wait for _init_event to be set by HelloListener
80
        self._init_event.wait()
81
        # there may have been an error
82
        if self._error:
83
            self._close()
84
            raise self._error
85
    
86
    class HelloListener:
87
        
88
        def __str__(self):
89
            return 'HelloListener'
90
        
91
        def __init__(self, session):
92
            self._session = session
93
        
94
        def _done(self, err=None):
95
            if err is not None:
96
                self._session._error = err
97
            self._session.remove_listener(self)
98
            self._session._init_event.set()
99
        
100
        def reply(self, data):
101
            err = None
102
            try:
103
                id, capabilities = content.parse_hello(data)
104
                logger.debug('session_id: %s | capabilities: \n%s', id, capabilities)
105
                self._session._id, self._session.capabilities = id, capabilities
106
            except Exception as e:
107
                err = e
108
            finally:
109
                self._done(err)
110
        
111
        def error(self, err):
112
            self._done(err)