Atlas 0.7.0
Networking protocol for the Worldforge system.
bridge.py
1#bridge: combine negotiation and codecs
2
3#Copyright 2002 by AIR-IX SUUNNITTELU/Ahiplan Oy
4
5#This library is free software; you can redistribute it and/or
6#modify it under the terms of the GNU Lesser General Public
7#License as published by the Free Software Foundation; either
8#version 2.1 of the License, or (at your option) any later version.
9
10#This library is distributed in the hope that it will be useful,
11#but WITHOUT ANY WARRANTY; without even the implied warranty of
12#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13#Lesser General Public License for more details.
14
15#You should have received a copy of the GNU Lesser General Public
16#License along with this library; if not, write to the Free Software
17#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20from atlas.transport.negotiation import NegotiationClient
21import atlas
22from atlas.util.debug import debug
23
24debug_flag = 0
25
26class BridgeException(Exception): pass
27
28class Bridge:
29 """includes negotiation at start and codecs when sending/receiving
30 translation from Object to string: return string to be transmitted
31 (or at begin negotiation strings)
32 transltaion from string to Object: return Object received
33 (or at begin nothing until negotiation done)
34 raise bridge error on negotiation (TODO: or syntax error in encoding)
35 operations send before codec if negotiated is either stored to queue or discarded
36
37 Usage: replace send_string, operation_received, connection_ok, log
38 with your own functions/methods
39 Process incoming strings with process_string method:
40 returns string to send, operations received
41 (also calls 'Usage: methods' as needed)
42 Process outgoing operations with process_operation:
43 returns string to send
44 (also calls 'Usage: methods' as needed)
45 """
46 def __init__(self, negotiation=NegotiationClient, store_operations = 1, functions=None):
47 self.codec = None
48 self.negotiation = negotiation
49 self.store_operations = store_operations
50 self.operations_to_send = []
51 if functions:
52 if hasattr(functions, "send_string"):
53 self.send_stringsend_string = functions.send_string
54 if hasattr(functions, "operation_received"):
55 self.operation_receivedoperation_received = functions.operation_received
56 if hasattr(functions, "connection_ok"):
57 self.connection_okconnection_ok = functions.connection_ok
58 if hasattr(functions, "log"):
59 self.loglog = functions.log
60
61 #replace these 4 functions with your own
62 def send_string(self, data):
63 """send string using transport specific method: specify your own"""
64 if debug_flag:
65 print("send_string:", data)
66
67 def operation_received(self, op):
68 """this is called for eac decoded operation"""
69 if debug_flag:
70 print("operation_received:", op)
71
72 def connection_ok(self):
73 """this is called after negotiation is done"""
74 if debug_flag:
75 print("connection_ok")
76
77 def log(self, type, data):
78 """various debug things"""
79 s = "\n%s:\n%s" % (type, data)
80 debug(s)
81
82 #externally usable methods
83
84 def setup(self):
85 return self.process_operation()
86
87 def close(self):
88 if self.codec:
89 self.internal_send_string(self.codec.close())
90
91 def process_string(self, data):
92 res_str, res_op = ("", atlas.Messages())
93 self.loglog("process_string", data)
94 if self.codec:
95 return res_str, self.decode_string(data)
96 else:
97 self.loglog("Negotiation", str(self.negotiation.state))
98 if self.negotiation.state:
99 self.negotiation(data)
100 res_str = res_str + self.negotiation.get_send_str()
101 self.internal_send_string(res_str)
102 if not self.negotiation.state:
103 self.process_string("")
104 elif self.negotiation.result_code=="fail":
105 raise BridgeException("Negotiation failed")
106 elif self.negotiation.result_code=="found":
107 self.loglog("Codec negotiated", self.negotiation.selected_codec)
108 self.codec = self.negotiation.get_codec()
110 objects = self.decode_string(self.negotiation.str+data)
111 res_str2, objects2 = self.process_operation()
112 return res_str+res_str2, objects+objects2
113 return res_str, res_op
114
115 def process_operation(self, op=None):
116 if self.codec:
117 res_str = ""
118 if self.operations_to_send:
120 self.operations_to_send = []
121 res_str = res_str + self.internal_send_string(self.codec.encode(msg))
122 if op!=None:
123 res_str = res_str + self.internal_send_string(self.codec.encode(op))
124 return res_str, atlas.Messages()
125 if self.store_operations and op!=None:
126 self.operations_to_send.append(op)
127 return self.process_string("")
128
129 #internal methids
130
131 def internal_send_string(self, data):
132 if not data: return ""
133 self.loglog("send_string", data)
134 self.send_stringsend_string(data)
135 return data
136
137 def decode_string(self, data):
138 try:
139 objects = self.codec.decode(data)
140 self.loglog("decode_string", objects)
141 except:
142 self.loglog("exception in decoding", data)
143 raise
144 #raise BridgeException("Decoding failed")
145 for op in objects:
147 return objects
def process_operation(self, op=None)
Definition: bridge.py:115
def log(self, type, data)
Definition: bridge.py:77
def decode_string(self, data)
Definition: bridge.py:137
def send_string(self, data)
Definition: bridge.py:62
def process_string(self, data)
Definition: bridge.py:91
def operation_received(self, op)
Definition: bridge.py:67
def internal_send_string(self, data)
Definition: bridge.py:131