Statistics
| Branch: | Tag: | Revision:

root / ncclient / transport / session.py @ efed7d4c

History | View | Annotate | Download (4.1 kB)

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