Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ffd50245689ef51b70682b7e1f26734bb71099d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# *****************************************************************************
# * Copyright (c) 2011, 2013 Wind River Systems, Inc. and others.
# * All rights reserved. This program and the accompanying materials
# * are made available under the terms of the Eclipse Public License v1.0
# * which accompanies this distribution, and is available at
# * http://www.eclipse.org/legal/epl-v10.html
# *
# * Contributors:
# *     Wind River Systems - initial API and implementation
# *****************************************************************************

"""
ChannelProxy implements forwarding of TCF messages between two channels.
The class is used to implement Locator service "redirect" command.
"""

from .. import channel


class ProxyCommandListener(channel.CommandListener):
    def __init__(self, ch, tokens):
        self.ch = ch
        self.tokens = tokens

    def progress(self, token, data):
        self.ch.sendProgress(self.tokens.get(token), data)

    def result(self, token, data):
        self.ch.sendResult(self.tokens.pop(token, None), data)

    def terminated(self, token, error):
        self.ch.rejectCommand(self.tokens.pop(token, None))


class ChannelProxy(object):
    def __init__(self, x, y):
        # assert not isinstance(x, ChannelLoop)
        # assert not isinstance(y, ChannelLoop)
        self.ch_x = x
        self.ch_y = y
        assert self.ch_x.getState() == channel.STATE_OPEN
        assert self.ch_y.getState() == channel.STATE_OPENING
        self.tokens_x = {}
        self.tokens_y = {}
        cmd_listener_x = ProxyCommandListener(self.ch_x, self.tokens_x)
        cmd_listener_y = ProxyCommandListener(self.ch_y, self.tokens_y)
        proxy = self

        class ProxyX(channel.Proxy):
            def onChannelClosed(self, error):
                proxy.closed_x = True
                if proxy.closed_y:
                    return
                if error is None:
                    proxy.ch_y.close()
                else:
                    proxy.ch_y.terminate(error)

            def onCommand(self, token, service, name, data):
                if proxy.closed_y:
                    return
                assert proxy.ch_y.getState() == channel.STATE_OPEN
                s = proxy.ch_y.getRemoteService(service)
                if not s:
                    proxy.ch_x.terminate(IOError("Invalid service name"))
                else:
                    key = proxy.ch_y.sendCommand(s, name, data, cmd_listener_x)
                    proxy.tokens_x[key] = token

            def onEvent(self, service, name, data):
                s = proxy.ch_x.getRemoteService(service)
                if not s:
                    proxy.ch_x.terminate(IOError("Invalid service name"))
                elif not proxy.closed_y:
                    proxy.ch_y.sendEvent(s, name, data)

        class ProxyY(channel.Proxy):
            def onChannelClosed(self, error):
                proxy.closed_y = True
                if proxy.closed_x:
                    return
                if error is None:
                    proxy.ch_x.close()
                else:
                    proxy.ch_x.terminate(error)

            def onCommand(self, token, service, name, data):
                if proxy.closed_x:
                    return
                assert proxy.ch_x.getState() == channel.STATE_OPEN
                s = proxy.ch_x.getRemoteService(service)
                if not s:
                    proxy.ch_y.terminate(IOError("Invalid service name"))
                else:
                    key = proxy.ch_x.sendCommand(s, name, data, cmd_listener_y)
                    proxy.tokens_y[key] = token

            def onEvent(self, service, name, data):
                s = proxy.ch_y.getRemoteService(service)
                if not s:
                    proxy.ch_y.terminate(IOError("Invalid service name"))
                elif not proxy.closed_x:
                    proxy.ch_x.sendEvent(s, name, data)

        proxy_x = ProxyX()
        proxy_y = ProxyY()

        try:
            self.ch_y.setProxy(proxy_y, self.ch_x.getRemoteServices())

            class ChannelListener(channel.ChannelListener):
                def onChannelClosed(self, error):
                    proxy.ch_y.removeChannelListener(self)
                    if error is None:
                        error = Exception("Channel closed")

                def onChannelOpened(self):
                    proxy.ch_y.removeChannelListener(self)
                    try:
                        proxy.ch_x.setProxy(proxy_x,
                                            proxy.ch_y.getRemoteServices())
                    except IOError as e:
                        proxy.ch_x.terminate(e)
                        proxy.ch_y.terminate(e)
            self.ch_y.addChannelListener(ChannelListener())
        except IOError as e:
            self.ch_x.terminate(e)
            self.ch_y.terminate(e)

Back to the top