Statistics
| Branch: | Tag: | Revision:

root / ncclient / session / session.py @ a956ef07

History | View | Annotate | Download (4.5 kB)

1 589b23e4 Shikhar Bhushan
# Copyright 2009 Shikhar Bhushan
2 589b23e4 Shikhar Bhushan
#
3 589b23e4 Shikhar Bhushan
# Licensed under the Apache License, Version 2.0 (the "License");
4 589b23e4 Shikhar Bhushan
# you may not use this file except in compliance with the License.
5 589b23e4 Shikhar Bhushan
# You may obtain a copy of the License at
6 589b23e4 Shikhar Bhushan
#
7 589b23e4 Shikhar Bhushan
#    http://www.apache.org/licenses/LICENSE-2.0
8 589b23e4 Shikhar Bhushan
#
9 589b23e4 Shikhar Bhushan
# Unless required by applicable law or agreed to in writing, software
10 589b23e4 Shikhar Bhushan
# distributed under the License is distributed on an "AS IS" BASIS,
11 589b23e4 Shikhar Bhushan
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 589b23e4 Shikhar Bhushan
# See the License for the specific language governing permissions and
13 589b23e4 Shikhar Bhushan
# limitations under the License.
14 589b23e4 Shikhar Bhushan
15 589b23e4 Shikhar Bhushan
import logging
16 589b23e4 Shikhar Bhushan
from threading import Thread, Event
17 589b23e4 Shikhar Bhushan
from Queue import Queue
18 589b23e4 Shikhar Bhushan
19 2acc860a Shikhar Bhushan
from capabilities import Capabilities, CAPABILITIES
20 589b23e4 Shikhar Bhushan
21 a956ef07 Shikhar Bhushan
logger = logging.getLogger('ncclient.session.session')
22 589b23e4 Shikhar Bhushan
23 a956ef07 Shikhar Bhushan
class SessionError(Exception):
24 a956ef07 Shikhar Bhushan
    
25 a956ef07 Shikhar Bhushan
    pass
26 a956ef07 Shikhar Bhushan
27 a956ef07 Shikhar Bhushan
class SessionCloseError(SessionError):
28 a956ef07 Shikhar Bhushan
    
29 a956ef07 Shikhar Bhushan
    def __str__(self):
30 a956ef07 Shikhar Bhushan
        return 'RECEIVED: %s | UNSENT: %s' % (self._in_buf, self._out_buf)
31 a956ef07 Shikhar Bhushan
    
32 a956ef07 Shikhar Bhushan
    def __init__(self, in_buf, out_buf=None):
33 a956ef07 Shikhar Bhushan
        SessionError.__init__(self)
34 a956ef07 Shikhar Bhushan
        self._in_buf, self._out_buf = in_buf, out_buf
35 589b23e4 Shikhar Bhushan
36 a956ef07 Shikhar Bhushan
class Session(Thread):
37 589b23e4 Shikhar Bhushan
    
38 589b23e4 Shikhar Bhushan
    def __init__(self):
39 589b23e4 Shikhar Bhushan
        Thread.__init__(self, name='session')
40 589b23e4 Shikhar Bhushan
        self._client_capabilities = CAPABILITIES
41 589b23e4 Shikhar Bhushan
        self._server_capabilities = None # yet
42 589b23e4 Shikhar Bhushan
        self._id = None # session-id
43 589b23e4 Shikhar Bhushan
        self._q = Queue()
44 8024f8b5 Shikhar Bhushan
        self._connected = False # to be set/cleared by subclass implementation
45 a956ef07 Shikhar Bhushan
        self._listeners = set(listeners)
46 a956ef07 Shikhar Bhushan
        self._lock = Lock()
47 ee4bb099 Shikhar Bhushan
    
48 ee4bb099 Shikhar Bhushan
    def _post_connect(self):
49 a956ef07 Shikhar Bhushan
        from ncclient.content.builders import HelloBuilder
50 ee4bb099 Shikhar Bhushan
        # queue client's hello message for sending
51 a956ef07 Shikhar Bhushan
        self.send(HelloBuilder.build(self._client_capabilities))
52 a956ef07 Shikhar Bhushan
        
53 a956ef07 Shikhar Bhushan
        error = None
54 a956ef07 Shikhar Bhushan
        proceed = Event()
55 a956ef07 Shikhar Bhushan
        def ok_cb(id, capabilities):
56 a956ef07 Shikhar Bhushan
            self._id, self._capabilities = id, Capabilities(capabilities)
57 a956ef07 Shikhar Bhushan
            proceed.set()
58 a956ef07 Shikhar Bhushan
        def err_cb(err):
59 a956ef07 Shikhar Bhushan
            error = err
60 a956ef07 Shikhar Bhushan
            proceed.set()
61 a956ef07 Shikhar Bhushan
        listener = HelloListener(ok_cb, err_cb)
62 a956ef07 Shikhar Bhushan
        self.add_listener(listener)
63 a956ef07 Shikhar Bhushan
        
64 a956ef07 Shikhar Bhushan
        # start the subclass' main loop
65 a956ef07 Shikhar Bhushan
        self.start()        
66 a956ef07 Shikhar Bhushan
        # we expect server's hello message
67 a956ef07 Shikhar Bhushan
        proceed.wait()
68 a956ef07 Shikhar Bhushan
        # received hello message or an error happened
69 8024f8b5 Shikhar Bhushan
        self.remove_listener(listener)
70 ee4bb099 Shikhar Bhushan
        if self._error:
71 ee4bb099 Shikhar Bhushan
            self._close()
72 ee4bb099 Shikhar Bhushan
            raise self._error
73 589b23e4 Shikhar Bhushan
    
74 589b23e4 Shikhar Bhushan
    def send(self, message):
75 589b23e4 Shikhar Bhushan
        logger.debug('queueing message: \n%s' % message)
76 589b23e4 Shikhar Bhushan
        self._q.put(message)
77 38a9b062 Shikhar Bhushan
    
78 38a9b062 Shikhar Bhushan
    def connect(self):
79 38a9b062 Shikhar Bhushan
        raise NotImplementedError
80 589b23e4 Shikhar Bhushan
81 589b23e4 Shikhar Bhushan
    def run(self):
82 589b23e4 Shikhar Bhushan
        raise NotImplementedError
83 2acc860a Shikhar Bhushan
        
84 2acc860a Shikhar Bhushan
    def capabilities(self, whose='client'):
85 2acc860a Shikhar Bhushan
        if whose == 'client':
86 2acc860a Shikhar Bhushan
            return self._client_capabilities
87 2acc860a Shikhar Bhushan
        elif whose == 'server':
88 2acc860a Shikhar Bhushan
            return self._server_capabilities
89 589b23e4 Shikhar Bhushan
    
90 a956ef07 Shikhar Bhushan
    ### Session is a subject for arbitary listeners
91 a956ef07 Shikhar Bhushan
    
92 a956ef07 Shikhar Bhushan
    def has_listener(self, listener):
93 a956ef07 Shikhar Bhushan
        with self._lock:
94 a956ef07 Shikhar Bhushan
            return (listener in self._listeners)
95 a956ef07 Shikhar Bhushan
    
96 a956ef07 Shikhar Bhushan
    def add_listener(self, listener):
97 a956ef07 Shikhar Bhushan
        with self._lock:
98 a956ef07 Shikhar Bhushan
            self._listeners.add(listener)
99 a956ef07 Shikhar Bhushan
    
100 a956ef07 Shikhar Bhushan
    def remove_listener(self, listener):
101 a956ef07 Shikhar Bhushan
        with self._lock:
102 a956ef07 Shikhar Bhushan
            self._listeners.discard(listener)
103 a956ef07 Shikhar Bhushan
    
104 a956ef07 Shikhar Bhushan
    def dispatch(self, event, *args, **kwds):
105 a956ef07 Shikhar Bhushan
        # holding the lock while doing callbacks could lead to a deadlock
106 a956ef07 Shikhar Bhushan
        # if one of the above methods is called
107 a956ef07 Shikhar Bhushan
        with self._lock:
108 a956ef07 Shikhar Bhushan
            listeners = list(self._listeners)
109 a956ef07 Shikhar Bhushan
        for l in listeners:
110 a956ef07 Shikhar Bhushan
            try:
111 a956ef07 Shikhar Bhushan
                logger.debug('dispatching [%s] to [%s]' % (event, l))
112 a956ef07 Shikhar Bhushan
                getattr(l, event)(*args, **kwds)
113 a956ef07 Shikhar Bhushan
            except Exception as e:
114 a956ef07 Shikhar Bhushan
                logger.warning(e)
115 a956ef07 Shikhar Bhushan
    
116 589b23e4 Shikhar Bhushan
    ### Properties
117 2acc860a Shikhar Bhushan
    
118 589b23e4 Shikhar Bhushan
    @property
119 35ad9d81 Shikhar Bhushan
    def client_capabilities(self):
120 35ad9d81 Shikhar Bhushan
        return self._client_capabilities
121 589b23e4 Shikhar Bhushan
    
122 589b23e4 Shikhar Bhushan
    @property
123 ee4bb099 Shikhar Bhushan
    def server_capabilities(self):
124 35ad9d81 Shikhar Bhushan
        return self._server_capabilities
125 589b23e4 Shikhar Bhushan
    
126 589b23e4 Shikhar Bhushan
    @property
127 35ad9d81 Shikhar Bhushan
    def connected(self):
128 35ad9d81 Shikhar Bhushan
        return self._connected
129 589b23e4 Shikhar Bhushan
    
130 589b23e4 Shikhar Bhushan
    @property
131 35ad9d81 Shikhar Bhushan
    def id(self):
132 38a9b062 Shikhar Bhushan
        return self._id
133 a956ef07 Shikhar Bhushan
134 a956ef07 Shikhar Bhushan
135 a956ef07 Shikhar Bhushan
class HelloListener:
136 a956ef07 Shikhar Bhushan
    
137 a956ef07 Shikhar Bhushan
    def __init__(self, init_cb, error_cb):
138 a956ef07 Shikhar Bhushan
        self._init_cb, self._error_cb = reply_cb, error_cb
139 a956ef07 Shikhar Bhushan
    
140 a956ef07 Shikhar Bhushan
    def __str__(self):
141 a956ef07 Shikhar Bhushan
        return 'HelloListener'
142 a956ef07 Shikhar Bhushan
    
143 a956ef07 Shikhar Bhushan
    ### Events
144 a956ef07 Shikhar Bhushan
    
145 a956ef07 Shikhar Bhushan
    def reply(self, raw):
146 a956ef07 Shikhar Bhushan
        from ncclient.content.parsers import HelloParser
147 a956ef07 Shikhar Bhushan
        try:
148 a956ef07 Shikhar Bhushan
            id, capabilities = HelloParser.parse(raw)
149 a956ef07 Shikhar Bhushan
        except Exception as e:
150 a956ef07 Shikhar Bhushan
            self._error_cb(e)
151 a956ef07 Shikhar Bhushan
        else:
152 a956ef07 Shikhar Bhushan
            self._init_cb(id, capabilities)
153 a956ef07 Shikhar Bhushan
    
154 a956ef07 Shikhar Bhushan
    def error(self, err):
155 a956ef07 Shikhar Bhushan
        self._error_cb(err)