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 
20 from atlas.transport.negotiation import NegotiationClient
21 import atlas
22 from atlas.util.debug import debug
23 
24 debug_flag = 0
25 
26 class BridgeException(Exception): pass
27 
28 class 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.codeccodec = None
48  self.negotiationnegotiation = negotiation
49  self.store_operationsstore_operations = store_operations
50  self.operations_to_sendoperations_to_send = []
51  if functions:
52  if hasattr(functions, "send_string"):
53  self.send_stringsend_stringsend_string = functions.send_string
54  if hasattr(functions, "operation_received"):
55  self.operation_receivedoperation_receivedoperation_received = functions.operation_received
56  if hasattr(functions, "connection_ok"):
57  self.connection_okconnection_okconnection_ok = functions.connection_ok
58  if hasattr(functions, "log"):
59  self.logloglog = 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_operationprocess_operation()
86 
87  def close(self):
88  if self.codeccodec:
89  self.internal_send_stringinternal_send_string(self.codeccodec.close())
90 
91  def process_string(self, data):
92  res_str, res_op = ("", atlas.Messages())
93  self.logloglog("process_string", data)
94  if self.codeccodec:
95  return res_str, self.decode_stringdecode_string(data)
96  else:
97  self.logloglog("Negotiation", str(self.negotiationnegotiation.state))
98  if self.negotiationnegotiation.state:
99  self.negotiationnegotiation(data)
100  res_str = res_str + self.negotiationnegotiation.get_send_str()
101  self.internal_send_stringinternal_send_string(res_str)
102  if not self.negotiationnegotiation.state:
103  self.process_stringprocess_string("")
104  elif self.negotiationnegotiation.result_code=="fail":
105  raise BridgeException("Negotiation failed")
106  elif self.negotiationnegotiation.result_code=="found":
107  self.logloglog("Codec negotiated", self.negotiationnegotiation.selected_codec)
108  self.codeccodec = self.negotiationnegotiation.get_codec()
109  self.connection_okconnection_okconnection_ok()
110  objects = self.decode_stringdecode_string(self.negotiationnegotiation.str+data)
111  res_str2, objects2 = self.process_operationprocess_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.codeccodec:
117  res_str = ""
118  if self.operations_to_sendoperations_to_send:
119  msg = atlas.Messages(*self.operations_to_sendoperations_to_send)
120  self.operations_to_sendoperations_to_send = []
121  res_str = res_str + self.internal_send_stringinternal_send_string(self.codeccodec.encode(msg))
122  if op!=None:
123  res_str = res_str + self.internal_send_stringinternal_send_string(self.codeccodec.encode(op))
124  return res_str, atlas.Messages()
125  if self.store_operationsstore_operations and op!=None:
126  self.operations_to_sendoperations_to_send.append(op)
127  return self.process_stringprocess_string("")
128 
129  #internal methids
130 
131  def internal_send_string(self, data):
132  if not data: return ""
133  self.logloglog("send_string", data)
134  self.send_stringsend_stringsend_string(data)
135  return data
136 
137  def decode_string(self, data):
138  try:
139  objects = self.codeccodec.decode(data)
140  self.logloglog("decode_string", objects)
141  except:
142  self.logloglog("exception in decoding", data)
143  raise
144  #raise BridgeException("Decoding failed")
145  for op in objects:
146  self.operation_receivedoperation_receivedoperation_received(op)
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