Atlas  0.7.0
Networking protocol for the Worldforge system.
negotiation.py
1 #negotiation of codec
2 
3 #Copyright 2000, 2001 by Aloril
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 #initialization:
21 #server:
22 #neg = NegotiationServer(("Packed", "XML"), id="Joe server")
23 #or with filepointer (socket or normal file):
24 #neg = NegotiationServer(("Packed", "XML"), input_fp, id="foo")
25 #client same as above, except mode is different:
26 #neg = NegotiationClient(("Packed", "XML"), id="Joe's text client")
27 
28 #feeding data and getting result:
29 #feed it input...
30 #neg(input_string)
31 #.. and send replies if any ...
32 # (first check neg() return value, see after next line)
33 #neg.get_send_str() returns what should be sent to other side
34 #...until you get non empty result:
35 #either "found" or "fail":
36 #neg.str contains what is left over of negotiation
37 #in case when "found", then neg.selected_codec contains selected codec
38 # (string: currently only "XML" supported by Atlas-Python)
39 #get_codec() returns codec object that can be used to
40 # encode(obj) outgoing objects and decode(str) incoming objects
41 # see codec.py for more docs
42 
43 #other info:
44 #neg.other_codecs: list of codecs other side supports
45 #neg.other_id: id -string of other side
46 
47 import string
48 import atlas.codecs
49 
51  state_done = 0
52  state_id = "id"
53  state_negotiation = "negotiation"
54  state_found = "found"
55  #when result to __call__ is:
56  #"": than state is one of above "string" states
57 
58  #when result to __call__ is:
59  #"fail" or "found": then state is state_done
60  #and further calls are undefined
61  def __init__(self, mode, codecs_lst, fp=None, id=""):
62  #args stuff
63  self.mode = mode
64  if codecs_lst:
65  self.codecs = codecs_lst
66  else:
67  self.codecs = atlas.codecs.ids
68  self.fp = fp
69  if id: self.id = id
70  else: self.id = mode
71 
72  #result stuff:
73  #reply to send: use get_send_str() to access
74  self.send_str = "ATLAS %s\n" % self.id
75  self.selected_codec = "" #what codec was selected
76  self.other_codecs = [] #list of codecs other side supports
77  #"found"/"fail" when result has been achieved
78  #result of __call__
79  self.result_code = ""
80  self.other_id = "" #id -string of other side
81 
82  #internal state stuff:
83  self.str = ""
84  self.state = self.state_id
85 
86  def get_send_str(self):
87  res = self.send_str
88  self.send_str = ""
89  return res
90 
91  def __call__(self, str=""):
92  if str: self.str = self.str + str
93  if self.state == self.state_done: return self.result_code
94  line = self.collect_until_newline()
95  while line!=None:
96  res = self.process_line(line)
97  if res: return res
98  line = self.collect_until_newline()
99  return self.result_code
100 
101  def process_line(self, line):
102  raise AttributeError("User NegotiationClient or NegotiationServer instead")
103 
104  def collect_until_newline(self):
105  if self.fp:
106  ok = string.find(self.str, "\n")<0
107  while ok:
108  ok = read_str = self.fp.recv(1) # silence-py depends on this /Demitar
109  self.str = self.str + read_str
110  ok = read_str and string.find(self.str, "\n")<0
111  #print "neg:cun", `self.str`
112  newline_pos = string.find(self.str, "\n")
113  if newline_pos >= 0:
114  res = self.str[:newline_pos]
115  self.str = self.str[newline_pos+1:]
116  return res
117 
118  def iwill(self, codecs):
119  return string.join(["IWILL %s\n" % c for c in codecs], "") + '\n' # Fixes negotiation /Demitar
120 
121  def ican(self, codecs):
122  return string.join(["ICAN %s\n" % c for c in codecs], "") + '\n' # Fixes negotiation /Demitar
123 
124  def analyse_line_codecs(self, line):
125  modes = string.split(line)
126  if len(modes)>=2 and modes[0]=="ICAN":
127  self.other_codecs.append(modes[1])
128  return modes
129 
130  def fail(self, msg):
131  self.send_str = self.send_str + msg
132  self.state = self.state_done
133  self.result_code = "fail"
134  #print "neg:fail", msg
135  return self.result_code
136 
137  def get_codec(self):
139  co.set_stream_mode()
140  return co
141 
143  def __init__(self, codecs=(), fp=None, id=""):
144  Negotiation.__init__(self, "server", codecs, fp, id)
145 
146  def process_line(self, line):
147  if self.state == self.state_id:
148  if line[:5]!="ATLAS":
149  return self.fail("Huh?\n\n")
150  self.other_id = line[6:]
151  self.state = self.state_negotiation
152  elif self.state == self.state_negotiation:
153  if not line:
154  return self.fail(self.ican(self.codecs))
155  modes = self.analyse_line_codecs(line)
156  if len(modes)>=2 and modes[0]=="ICAN" and \
157  modes[1] in self.codecs:
158  self.selected_codec = modes[1]
159  #print "neg:found"
160  self.state = self.state_found
161  else: #negotiation_found
162  self.analyse_line_codecs(line)
163  if not line or line=="\r":
164  #print "neg:ok"
165  self.send_str = self.send_str + \
166  self.iwill([self.selected_codec])
167  self.state = self.state_done
168  self.result_code = "found"
169  return self.result_code
170 
171 
173  def __init__(self, codecs=(), fp=None, id=""):
174  Negotiation.__init__(self, "client", codecs, fp, id)
175 
176  def process_line(self, line):
177  if self.state == self.state_id:
178  if line[:5]!="ATLAS":
179  return self.fail("Huh?\n\n")
180  self.other_id = line[6:]
181  self.state = self.state_negotiation
182  self.send_str = self.send_str + self.ican(self.codecs)
183  elif self.state == self.state_negotiation:
184  if not line:
185  return self.fail("")
186  modes = self.analyse_line_codecs(line)
187  if len(modes)>=2 and modes[0]=="IWILL" and \
188  modes[1] in self.codecs:
189  self.other_codecs.append(modes[1])
190  self.selected_codec = modes[1]
191  #print "neg:found"
192  self.state = self.state_found
193  else: #negotiation_found
194  self.analyse_line_codecs(line)
195  if not line:
196  #print "neg:ok"
197  self.state = self.state_done
198  self.result_code = "found"
199  return self.result_code
atlas.transport.negotiation.Negotiation.state_done
int state_done
Definition: negotiation.py:51
atlas.transport.negotiation.Negotiation.process_line
def process_line(self, line)
Definition: negotiation.py:101
atlas.transport.negotiation.Negotiation.str
str
Definition: negotiation.py:83
atlas.transport.negotiation.Negotiation.ican
def ican(self, codecs)
Definition: negotiation.py:121
atlas.transport.negotiation.Negotiation
Definition: negotiation.py:50
atlas.transport.negotiation.Negotiation.result_code
result_code
Definition: negotiation.py:79
atlas.transport.negotiation.Negotiation.other_codecs
other_codecs
Definition: negotiation.py:76
atlas.transport.negotiation.Negotiation.fp
fp
Definition: negotiation.py:68
atlas.transport.negotiation.Negotiation.state_found
string state_found
Definition: negotiation.py:54
atlas.transport.negotiation.NegotiationServer
Definition: negotiation.py:142
atlas.transport.negotiation.Negotiation.selected_codec
selected_codec
Definition: negotiation.py:75
atlas.transport.negotiation.Negotiation.id
id
Definition: negotiation.py:69
atlas.transport.negotiation.Negotiation.analyse_line_codecs
def analyse_line_codecs(self, line)
Definition: negotiation.py:124
atlas.transport.negotiation.Negotiation.iwill
def iwill(self, codecs)
Definition: negotiation.py:118
atlas.transport.negotiation.Negotiation.codecs
codecs
Definition: negotiation.py:65
atlas.transport.negotiation.Negotiation.fail
def fail(self, msg)
Definition: negotiation.py:130
atlas.transport.negotiation.Negotiation.state_negotiation
string state_negotiation
Definition: negotiation.py:53
atlas.codecs.get_codec
def get_codec(name)
Definition: codecs/__init__.py:95
atlas.transport.negotiation.Negotiation.state
state
Definition: negotiation.py:84
atlas.transport.negotiation.Negotiation.other_id
other_id
Definition: negotiation.py:80
atlas.transport.negotiation.Negotiation.send_str
send_str
Definition: negotiation.py:74
atlas.transport.negotiation.NegotiationClient
Definition: negotiation.py:172
atlas.transport.negotiation.Negotiation.mode
mode
Definition: negotiation.py:63
atlas.transport.negotiation.Negotiation.collect_until_newline
def collect_until_newline(self)
Definition: negotiation.py:104
atlas.transport.negotiation.Negotiation.state_id
string state_id
Definition: negotiation.py:52
atlas.codecs
Definition: codecs/__init__.py:1