Merge lp:projetrpgorleans into lp:~jordan-smagghe/projetrpgorleans/branche-jordan

Proposed by magnamaitre
Status: Merged
Approved by: magnamaitre
Approved revision: 7
Merged at revision: 12
Proposed branch: lp:projetrpgorleans
Merge into: lp:~jordan-smagghe/projetrpgorleans/branche-jordan
Diff against target: 3585 lines (+3314/-0) (has conflicts)
51 files modified
build/lib.linux-i686-2.7/pynetez/ADict.py (+54/-0)
build/lib.linux-i686-2.7/pynetez/ActiveObject.py (+45/-0)
build/lib.linux-i686-2.7/pynetez/ActiveObjectBase.py (+46/-0)
build/lib.linux-i686-2.7/pynetez/Activity.py (+61/-0)
build/lib.linux-i686-2.7/pynetez/Agent.py (+51/-0)
build/lib.linux-i686-2.7/pynetez/Client.py (+45/-0)
build/lib.linux-i686-2.7/pynetez/IBuffer.py (+64/-0)
build/lib.linux-i686-2.7/pynetez/Protocol.py (+180/-0)
build/lib.linux-i686-2.7/pynetez/Reader.py (+42/-0)
build/lib.linux-i686-2.7/pynetez/Server.py (+43/-0)
build/lib.linux-i686-2.7/pynetez/Session.py (+222/-0)
build/lib.linux-i686-2.7/pynetez/Signal.py (+54/-0)
build/lib.linux-i686-2.7/pynetez/Socket.py (+324/-0)
build/lib.linux-i686-2.7/pynetez/Writer.py (+37/-0)
build/lib.linux-i686-2.7/pynetez/__init__.py (+17/-0)
examples/calc/client.py (+64/-0)
examples/calc/proto.py (+10/-0)
examples/calc/server.py (+23/-0)
examples/date/async/client.py (+15/-0)
examples/date/async/proto.py (+5/-0)
examples/date/async/server.py (+12/-0)
examples/date/sync/client.py (+15/-0)
examples/date/sync/proto.py (+5/-0)
examples/date/sync/server.py (+12/-0)
examples/nim-agent/client.py (+39/-0)
examples/nim-agent/proto.py (+13/-0)
examples/nim-agent/server.py (+91/-0)
examples/nim/client.py (+39/-0)
examples/nim/proto.py (+13/-0)
examples/nim/server.py (+88/-0)
examples/pingpong/client.py (+15/-0)
examples/pingpong/proto.py (+5/-0)
examples/pingpong/server.py (+12/-0)
proto.py (+33/-0)
pynetez/ADict.py (+54/-0)
pynetez/ActiveObject.py (+45/-0)
pynetez/ActiveObjectBase.py (+46/-0)
pynetez/Activity.py (+61/-0)
pynetez/Agent.py (+51/-0)
pynetez/Client.py (+45/-0)
pynetez/IBuffer.py (+64/-0)
pynetez/Protocol.py (+180/-0)
pynetez/Reader.py (+42/-0)
pynetez/Server.py (+43/-0)
pynetez/Session.py (+222/-0)
pynetez/Signal.py (+54/-0)
pynetez/Socket.py (+324/-0)
pynetez/Writer.py (+37/-0)
pynetez/__init__.py (+17/-0)
server.py (+227/-0)
setup.py (+8/-0)
Conflict adding file client.py.  Moved existing file to client.py.moved.
Conflict adding file proto.py.  Moved existing file to proto.py.moved.
Conflict adding file server.py.  Moved existing file to server.py.moved.
To merge this branch: bzr merge lp:projetrpgorleans
Reviewer Review Type Date Requested Status
magnamaitre Approve
Sami Hernandez (community) Approve
Review via email: mp+110495@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sami Hernandez (oceansbleus) wrote :

ok

review: Approve
Revision history for this message
magnamaitre (jordan-smagghe) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'build'
2=== added directory 'build/lib.linux-i686-2.7'
3=== added directory 'build/lib.linux-i686-2.7/pynetez'
4=== added file 'build/lib.linux-i686-2.7/pynetez/ADict.py'
5--- build/lib.linux-i686-2.7/pynetez/ADict.py 1970-01-01 00:00:00 +0000
6+++ build/lib.linux-i686-2.7/pynetez/ADict.py 2012-06-15 10:11:52 +0000
7@@ -0,0 +1,54 @@
8+#==============================================================================
9+# Copyright (C) 2011 by Denys Duchier
10+#
11+# This program is free software; you can redistribute it and/or modify it under
12+# the terms of the GNU General Public License as published by the Free Software
13+# Foundation; either version 2 of the License, or (at your option) any later
14+# version.
15+#
16+# This program is distributed in the hope that it will be useful, but WITHOUT
17+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19+# details.
20+#
21+# You should have received a copy of the GNU General Public License along with
22+# this program; if not, write to the Free Software Foundation, Inc., 51
23+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24+#==============================================================================
25+
26+class ADict(object):
27+
28+ __slots__ = ('_table_',)
29+
30+ def __init__(self):
31+ ADict._table_.__set__(self, {})
32+
33+ def __getattr__(self, name):
34+ return self[name]
35+
36+ def __setattr__(self, name, value):
37+ self[name] = value
38+
39+ def __delattr__(self, name):
40+ del self[name]
41+
42+ def __getitem__(self, name):
43+ return self._table_[name]
44+
45+ def __setitem__(self, name, value):
46+ self._table_[name] = value
47+
48+ def __delitem__(self, name):
49+ del self._table_[name]
50+
51+ def values(self):
52+ return self._table_.values()
53+
54+ def keys(self):
55+ return self._table_.keys()
56+
57+ def items(self):
58+ return self._table_.items()
59+
60+ def __contains__(self, key):
61+ return key in self._table_
62
63=== added file 'build/lib.linux-i686-2.7/pynetez/ActiveObject.py'
64--- build/lib.linux-i686-2.7/pynetez/ActiveObject.py 1970-01-01 00:00:00 +0000
65+++ build/lib.linux-i686-2.7/pynetez/ActiveObject.py 2012-06-15 10:11:52 +0000
66@@ -0,0 +1,45 @@
67+#==============================================================================
68+# Copyright (C) 2011 by Denys Duchier
69+#
70+# This program is free software; you can redistribute it and/or modify it under
71+# the terms of the GNU General Public License as published by the Free Software
72+# Foundation; either version 2 of the License, or (at your option) any later
73+# version.
74+#
75+# This program is distributed in the hope that it will be useful, but WITHOUT
76+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
77+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
78+# details.
79+#
80+# You should have received a copy of the GNU General Public License along with
81+# this program; if not, write to the Free Software Foundation, Inc., 51
82+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
83+#==============================================================================
84+
85+from ActiveObjectBase import ActiveObjectBase
86+from Queue import Queue
87+
88+class ActiveObject(ActiveObjectBase):
89+ """reacts to messages received on its queue."""
90+
91+ def __init__(self, *args, **kargs):
92+ self._queue = Queue(-1)
93+ super(ActiveObject, self).__init__(*args, **kargs)
94+
95+ def recv(self, msg):
96+ if not self.closed:
97+ self._queue.put(msg)
98+
99+ def do(self):
100+ while not self.closed:
101+ msg = self._queue.get()
102+ # None causes the active object to close
103+ if msg is None:
104+ return self.close()
105+ self.react(msg)
106+
107+ def react(self, msg):
108+ raise NotImplementedError()
109+
110+ def close(self):
111+ super(ActiveObject, self).close()
112
113=== added file 'build/lib.linux-i686-2.7/pynetez/ActiveObjectBase.py'
114--- build/lib.linux-i686-2.7/pynetez/ActiveObjectBase.py 1970-01-01 00:00:00 +0000
115+++ build/lib.linux-i686-2.7/pynetez/ActiveObjectBase.py 2012-06-15 10:11:52 +0000
116@@ -0,0 +1,46 @@
117+#==============================================================================
118+# Copyright (C) 2011 by Denys Duchier
119+#
120+# This program is free software; you can redistribute it and/or modify it under
121+# the terms of the GNU General Public License as published by the Free Software
122+# Foundation; either version 2 of the License, or (at your option) any later
123+# version.
124+#
125+# This program is distributed in the hope that it will be useful, but WITHOUT
126+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
127+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
128+# details.
129+#
130+# You should have received a copy of the GNU General Public License along with
131+# this program; if not, write to the Free Software Foundation, Inc., 51
132+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
133+#==============================================================================
134+
135+from Activity import Activity
136+from Signal import Signal
137+from threading import RLock
138+
139+class ActiveObjectBase(Activity):
140+ """almost an ActiveObject, but without the queue."""
141+
142+ def __init__(self, *args, **kargs):
143+ self.eof = Signal()
144+ self._rlock = RLock()
145+ self._closed = False
146+ super(ActiveObjectBase, self).__init__(*args, **kargs)
147+
148+ @property
149+ def closed(self):
150+ return self._closed
151+
152+ def close(self):
153+ sig = False
154+ with self._rlock:
155+ if not self._closed:
156+ sig = True
157+ self._closed = True
158+ if sig:
159+ self.eof()
160+
161+ def __del__(self):
162+ self.close()
163
164=== added file 'build/lib.linux-i686-2.7/pynetez/Activity.py'
165--- build/lib.linux-i686-2.7/pynetez/Activity.py 1970-01-01 00:00:00 +0000
166+++ build/lib.linux-i686-2.7/pynetez/Activity.py 2012-06-15 10:11:52 +0000
167@@ -0,0 +1,61 @@
168+#==============================================================================
169+# Copyright (C) 2011 by Denys Duchier
170+#
171+# This program is free software; you can redistribute it and/or modify it under
172+# the terms of the GNU General Public License as published by the Free Software
173+# Foundation; either version 2 of the License, or (at your option) any later
174+# version.
175+#
176+# This program is distributed in the hope that it will be useful, but WITHOUT
177+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
178+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
179+# details.
180+#
181+# You should have received a copy of the GNU General Public License along with
182+# this program; if not, write to the Free Software Foundation, Inc., 51
183+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
184+#==============================================================================
185+
186+from Signal import Signal
187+from threading import Thread
188+
189+class Activity(object):
190+ """abstraction for doing things on a thread."""
191+
192+ def __init__(self, *args, **kw):
193+ self._thread = None
194+ self.begin = Signal()
195+ self.end = Signal()
196+ self.begin.connect(self.on_begin)
197+ self.end.connect(self.on_end)
198+
199+ def on_begin(self):
200+ pass
201+
202+ def on_end(self):
203+ pass
204+
205+ daemon = True
206+
207+ def start(self, *args, **kw):
208+ """create and start a thread for doing things."""
209+ self._thread = Thread(target=self._do, args=args, kwargs=kw)
210+ self._thread.daemon = self.daemon
211+ self._thread.start()
212+
213+ def _do(self, *args, **kargs):
214+ self.begin()
215+ try:
216+ self.do(*args, **kargs)
217+ finally:
218+ self.end()
219+
220+ def do(self, *args, **kargs):
221+ """method for doing things
222+
223+ it is invoked with whatever arguments were passed to start().
224+ """
225+ raise NotImplementedError()
226+
227+ def join(self):
228+ self._thread.join()
229
230=== added file 'build/lib.linux-i686-2.7/pynetez/Agent.py'
231--- build/lib.linux-i686-2.7/pynetez/Agent.py 1970-01-01 00:00:00 +0000
232+++ build/lib.linux-i686-2.7/pynetez/Agent.py 2012-06-15 10:11:52 +0000
233@@ -0,0 +1,51 @@
234+#==============================================================================
235+# Copyright (C) 2012 by Denys Duchier
236+#
237+# This program is free software; you can redistribute it and/or modify it under
238+# the terms of the GNU General Public License as published by the Free Software
239+# Foundation; either version 2 of the License, or (at your option) any later
240+# version.
241+#
242+# This program is distributed in the hope that it will be useful, but WITHOUT
243+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
244+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
245+# details.
246+#
247+# You should have received a copy of the GNU General Public License along with
248+# this program; if not, write to the Free Software Foundation, Inc., 51
249+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
250+#==============================================================================
251+
252+#==============================================================================
253+# For the moment, an agent is an ActiveObject associated with a Protocol and
254+# with methods for reacting to messages. Methods implementing reactions for
255+# messages are also called do_XXX (where XXX is the message name).
256+#==============================================================================
257+
258+from ActiveObject import ActiveObject
259+from ADict import ADict
260+
261+class Agent(ActiveObject):
262+
263+ def __init__(self, proto, *args, **kargs):
264+ super(Agent, self).__init__(*args, **kargs)
265+ self._proto = proto
266+ self._recv = qfun = self.recv
267+ self.recv = vtable = ADict()
268+ def mkmsg(mt, qfun):
269+ def msg(*args):
270+ qfun(mt(*args))
271+ return msg
272+ for mt in proto.msgtypes:
273+ vtable[mt.name] = mkmsg(mt, qfun)
274+
275+ def react(self, msg):
276+ doname = "do_%s" % msg.name
277+ try:
278+ dofun = getattr(self, doname)
279+ except AttributeError:
280+ raise NotImplementedError(doname)
281+ dofun(*msg.args)
282+
283+ def finish(self):
284+ self._recv(None)
285
286=== added file 'build/lib.linux-i686-2.7/pynetez/Client.py'
287--- build/lib.linux-i686-2.7/pynetez/Client.py 1970-01-01 00:00:00 +0000
288+++ build/lib.linux-i686-2.7/pynetez/Client.py 2012-06-15 10:11:52 +0000
289@@ -0,0 +1,45 @@
290+#==============================================================================
291+# Copyright (C) 2011 by Denys Duchier
292+#
293+# This program is free software; you can redistribute it and/or modify it under
294+# the terms of the GNU General Public License as published by the Free Software
295+# Foundation; either version 2 of the License, or (at your option) any later
296+# version.
297+#
298+# This program is distributed in the hope that it will be useful, but WITHOUT
299+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
300+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
301+# details.
302+#
303+# You should have received a copy of the GNU General Public License along with
304+# this program; if not, write to the Free Software Foundation, Inc., 51
305+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
306+#==============================================================================
307+
308+from Socket import Socket
309+
310+class Client(object):
311+
312+ def __init__(self, protocol, sessiontype):
313+ self.session = sessiontype(protocol)
314+
315+ def run(self, host, port, wait=True):
316+ socket = Socket()
317+ socket.socket()
318+ socket.connect((host, port))
319+ self.session.pluginto(socket)
320+ self.send = self.session.send
321+ self.recv = self.session.recv
322+ self.finish = self.session.finish
323+ self.wait = self.session.wait
324+ self.session.start()
325+ if wait:
326+ self.session.wait()
327+
328+ def run_argv(self, wait=True):
329+ from optparse import OptionParser
330+ parser = OptionParser("usage: %prog [options]")
331+ parser.add_option("--host","-H",dest="host",default="localhost")
332+ parser.add_option("--port","-p",dest="port",type=int,default=9999)
333+ options, args = parser.parse_args()
334+ self.run(options.host, options.port, wait=wait)
335
336=== added file 'build/lib.linux-i686-2.7/pynetez/IBuffer.py'
337--- build/lib.linux-i686-2.7/pynetez/IBuffer.py 1970-01-01 00:00:00 +0000
338+++ build/lib.linux-i686-2.7/pynetez/IBuffer.py 2012-06-15 10:11:52 +0000
339@@ -0,0 +1,64 @@
340+#==============================================================================
341+# Copyright (C) 2011 by Denys Duchier
342+#
343+# This program is free software; you can redistribute it and/or modify it under
344+# the terms of the GNU General Public License as published by the Free Software
345+# Foundation; either version 2 of the License, or (at your option) any later
346+# version.
347+#
348+# This program is distributed in the hope that it will be useful, but WITHOUT
349+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
350+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
351+# details.
352+#
353+# You should have received a copy of the GNU General Public License along with
354+# this program; if not, write to the Free Software Foundation, Inc., 51
355+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
356+#==============================================================================
357+
358+class IBuffer(object):
359+ """abstraction for buffered input."""
360+
361+ def __init__(self, refill):
362+ self._data = "" # buffered data
363+ self._offset = 0 # how much of it we have already used
364+ self._refill = refill # how to get more data
365+ self._eof = False
366+
367+ @property
368+ def size(self):
369+ """how many bytes are still available in the buffer."""
370+ return len(self._data) - self._offset
371+
372+ def _read(self, n):
373+ if self._eof:
374+ raise IOError("EOF")
375+ m = self.size
376+ if m <= 0:
377+ return None
378+ elif m >= n:
379+ off = self._offset
380+ nxt = off + n
381+ self._offset = nxt
382+ return self._data[off:nxt]
383+ else:
384+ data = self._data[self._offset:]
385+ self._data = ""
386+ self._offset = 0
387+ return data
388+
389+ def read(self, n):
390+ """read and return exactly n bytes from the stream."""
391+ daten = []
392+ while n:
393+ data = self._read(n)
394+ if not data:
395+ self._offset = 0
396+ self._data = self._refill()
397+ if not self._data:
398+ self._eof = True
399+ raise IOError("EOF")
400+ else:
401+ daten.append(data)
402+ n -= len(data)
403+ return "".join(daten)
404
405=== added file 'build/lib.linux-i686-2.7/pynetez/Protocol.py'
406--- build/lib.linux-i686-2.7/pynetez/Protocol.py 1970-01-01 00:00:00 +0000
407+++ build/lib.linux-i686-2.7/pynetez/Protocol.py 2012-06-15 10:11:52 +0000
408@@ -0,0 +1,180 @@
409+#==============================================================================
410+# Copyright (C) 2011 by Denys Duchier
411+#
412+# This program is free software; you can redistribute it and/or modify it under
413+# the terms of the GNU General Public License as published by the Free Software
414+# Foundation; either version 2 of the License, or (at your option) any later
415+# version.
416+#
417+# This program is distributed in the hope that it will be useful, but WITHOUT
418+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
419+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
420+# details.
421+#
422+# You should have received a copy of the GNU General Public License along with
423+# this program; if not, write to the Free Software Foundation, Inc., 51
424+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
425+#==============================================================================
426+
427+#===============================================================================
428+# possible types of message fields. each type knows how to un/marshal itself
429+#===============================================================================
430+
431+class FieldType(object): pass
432+
433+class _uint8(FieldType):
434+ def marshal(self, sock, i):
435+ sock.put_uint8(i)
436+ def unmarshal(self, sock):
437+ return sock.get_uint8()
438+uint8 = _uint8()
439+
440+class _uint16(FieldType):
441+ def marshal(self, sock, i):
442+ sock.put_int16(i)
443+ def unmarshal(self, sock):
444+ return sock.get_uint16()
445+uint16 = _uint16()
446+
447+class _uint32(FieldType):
448+ def marshal(self, sock, i):
449+ sock.put_int32(i)
450+ def unmarshal(self, sock):
451+ return sock.get_uint32()
452+uint32 = _uint32()
453+
454+class _int8(FieldType):
455+ def marshal(self, sock, i):
456+ sock.put_int8(i)
457+ def unmarshal(self, sock):
458+ return sock.get_int8()
459+int8 = _int8()
460+
461+class _int16(FieldType):
462+ def marshal(self, sock, i):
463+ sock.put_int16(i)
464+ def unmarshal(self, sock):
465+ return sock.get_int16()
466+int16 = _int16()
467+
468+class _int32(FieldType):
469+ def marshal(self, sock, i):
470+ sock.put_int32(i)
471+ def unmarshal(self, sock):
472+ return sock.get_int32()
473+int32 = _int32()
474+
475+class listof(FieldType):
476+ def __init__(self, typ):
477+ self.elemtype = typ
478+ def __cmp__(self, other):
479+ return isinstance(other, listof) and \
480+ self.elemtype == other.elemtype
481+ def marshal(self, sock, l):
482+ sock.put_uint32(len(l))
483+ for x in l:
484+ self.elemtype.marshal(sock, x)
485+ def unmarshal(self, sock):
486+ n = sock.get_uint32()
487+ l = []
488+ while n:
489+ l.append(self.elemtype.unmarshal(sock))
490+ n -= 1
491+ return tuple(l)
492+
493+class _binary(FieldType):
494+ def marshal(self, sock, b):
495+ sock.put_bytes(b)
496+ def unmarshal(self, sock):
497+ return sock.get_bytes()
498+binary = _binary()
499+string = binary
500+
501+#===============================================================================
502+# M1 = MessageType("send",0,dict(portsrc=int16,portdst=int16,data=binary))
503+# m1 = M1(portsrc=2345,portdst=80,data="hello world")
504+# m1.marshal(socket)
505+# m2 = M1.unmarshal(socket)
506+#===============================================================================
507+
508+class Message(object):
509+
510+ def __init__(self, msgtype, args):
511+ self.type = msgtype
512+ self.args = args
513+
514+ def marshal(self, sock):
515+ self.type.marshal(sock, self.args)
516+
517+ @property
518+ def name(self):
519+ return self.type.name
520+
521+ def __getitem__(self, i):
522+ return self.args[i]
523+
524+class MessageType(object):
525+
526+ def __init__(self, name, code, args):
527+ self.name = name
528+ self.code = code
529+ if not isinstance(args, tuple):
530+ args = tuple(args)
531+ self.args = args
532+
533+ def __call__(self, *args):
534+ return Message(self, args)
535+
536+ def marshal(self, sock, args):
537+ sock.put_uint8(self.code)
538+ for t,v in zip(self.args, args):
539+ t.marshal(sock, v)
540+
541+ def unmarshal(self, sock):
542+ return Message(self, tuple(t.unmarshal(sock) for t in self.args))
543+
544+ def writer(self, sock):
545+ def msgwriter(*args):
546+ self(*args).marshal(sock)
547+ return msgwriter
548+
549+#===============================================================================
550+# proto = Protocol()
551+# proto.defmsgtype("send", int16, int16, binary)
552+# proto.defmsgtype("ping", int32)
553+# m1 = proto.message.send(2345, 80, "hello world")
554+# m2 = proto.message.ping(23)
555+# m1.marshal(sock)
556+# m2.marshal(sock)
557+# m3 = proto.unmarshal(sock)
558+#===============================================================================
559+
560+from ADict import ADict
561+
562+class Protocol(object):
563+
564+ def __init__(self):
565+ self._code = 0
566+ self.message = ADict()
567+
568+ def defmsgtype(self, name, *args):
569+ if name in self.message:
570+ raise Exception("message type '%s' is already defined" % name)
571+ code = self._code
572+ self._code += 1
573+ self.message[code] = MessageType(name, code, args)
574+
575+ define = defmsgtype
576+
577+ @property
578+ def msgtypes(self):
579+ return self.message.values()
580+
581+ def unmarshal(self, sock):
582+ return self.message[sock.get_uint8()].unmarshal(sock)
583+
584+ def writer(self, sock):
585+ protowriter = ADict()
586+ for mt in self.msgtypes:
587+ protowriter[mt.name] = mt.writer(sock)
588+ return protowriter
589
590=== added file 'build/lib.linux-i686-2.7/pynetez/Reader.py'
591--- build/lib.linux-i686-2.7/pynetez/Reader.py 1970-01-01 00:00:00 +0000
592+++ build/lib.linux-i686-2.7/pynetez/Reader.py 2012-06-15 10:11:52 +0000
593@@ -0,0 +1,42 @@
594+#==============================================================================
595+# Copyright (C) 2011 by Denys Duchier
596+#
597+# This program is free software; you can redistribute it and/or modify it under
598+# the terms of the GNU General Public License as published by the Free Software
599+# Foundation; either version 2 of the License, or (at your option) any later
600+# version.
601+#
602+# This program is distributed in the hope that it will be useful, but WITHOUT
603+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
604+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
605+# details.
606+#
607+# You should have received a copy of the GNU General Public License along with
608+# this program; if not, write to the Free Software Foundation, Inc., 51
609+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
610+#==============================================================================
611+
612+from ActiveObjectBase import ActiveObjectBase
613+from Signal import Signal
614+
615+class Reader(ActiveObjectBase):
616+ """emits a signal for every message read on a socket."""
617+
618+ def __init__(self, socket):
619+ super(Reader, self).__init__()
620+ self.socket = socket
621+ self.send = Signal()
622+
623+ def do(self):
624+ while not self.closed:
625+ try:
626+ msg = self.read()
627+ except IOError:
628+ self.close()
629+ return
630+ self.send(msg)
631+
632+ # you need to reimplement this method
633+ # to deserialize a message from the socket
634+ def read(self):
635+ raise NotImplementedError()
636
637=== added file 'build/lib.linux-i686-2.7/pynetez/Server.py'
638--- build/lib.linux-i686-2.7/pynetez/Server.py 1970-01-01 00:00:00 +0000
639+++ build/lib.linux-i686-2.7/pynetez/Server.py 2012-06-15 10:11:52 +0000
640@@ -0,0 +1,43 @@
641+#==============================================================================
642+# Copyright (C) 2011 by Denys Duchier
643+#
644+# This program is free software; you can redistribute it and/or modify it under
645+# the terms of the GNU General Public License as published by the Free Software
646+# Foundation; either version 2 of the License, or (at your option) any later
647+# version.
648+#
649+# This program is distributed in the hope that it will be useful, but WITHOUT
650+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
651+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
652+# details.
653+#
654+# You should have received a copy of the GNU General Public License along with
655+# this program; if not, write to the Free Software Foundation, Inc., 51
656+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
657+#==============================================================================
658+
659+from Socket import Socket
660+
661+class Server(object):
662+
663+ def __init__(self, protocol, sessiontype):
664+ self._protocol = protocol
665+ self._sessiontype = sessiontype
666+
667+ def run(self, port):
668+ self._socket = Socket()
669+ self._socket.socket()
670+ self._socket.bind(("", port))
671+ self._socket.listen(10)
672+ while True:
673+ sock = self._socket.accept()
674+ session = self._sessiontype(self._protocol)
675+ session.pluginto(sock)
676+ session.start()
677+
678+ def run_argv(self):
679+ from optparse import OptionParser
680+ parser = OptionParser(usage="usage: %prog [options]")
681+ parser.add_option("--port","-p",type=int,dest="port",default=9999)
682+ options, args = parser.parse_args()
683+ self.run(options.port)
684
685=== added file 'build/lib.linux-i686-2.7/pynetez/Session.py'
686--- build/lib.linux-i686-2.7/pynetez/Session.py 1970-01-01 00:00:00 +0000
687+++ build/lib.linux-i686-2.7/pynetez/Session.py 2012-06-15 10:11:52 +0000
688@@ -0,0 +1,222 @@
689+#==============================================================================
690+# Copyright (C) 2011 by Denys Duchier
691+#
692+# This program is free software; you can redistribute it and/or modify it under
693+# the terms of the GNU General Public License as published by the Free Software
694+# Foundation; either version 2 of the License, or (at your option) any later
695+# version.
696+#
697+# This program is distributed in the hope that it will be useful, but WITHOUT
698+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
699+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
700+# details.
701+#
702+# You should have received a copy of the GNU General Public License along with
703+# this program; if not, write to the Free Software Foundation, Inc., 51
704+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
705+#==============================================================================
706+
707+from Reader import Reader
708+from Writer import Writer
709+from Signal import Signal
710+from socket import SHUT_RD, SHUT_WR, SHUT_RDWR
711+from threading import Lock
712+from Queue import Queue
713+from ActiveObjectBase import ActiveObjectBase
714+
715+class SessionReader(Reader):
716+
717+ def __init__(self, socket, protocol, react):
718+ super(SessionReader, self).__init__(socket)
719+ self.protocol = protocol
720+ self.send.connect(react)
721+
722+ def read(self):
723+ return self.protocol.unmarshal(self.socket)
724+
725+ def close(self):
726+ super(SessionReader, self).close()
727+ try:
728+ self.socket.shutdown(SHUT_RD)
729+ except:
730+ pass
731+
732+#===============================================================================
733+
734+from ADict import ADict
735+
736+def message_and_queue(mkfun, qfun):
737+ def msg(*kargs):
738+ qfun(mkfun(*kargs))
739+ return msg
740+
741+class SessionWriter(Writer):
742+
743+ def __init__(self, socket, protocol):
744+ super(SessionWriter, self).__init__(socket)
745+ self.protocol = protocol
746+ self.protocolwriter = protocol.writer(socket)
747+ self.message = ADict()
748+ qfun = self.recv
749+ for mt in protocol.msgtypes:
750+ self.message[mt.name] = message_and_queue(mt, qfun)
751+
752+ def write(self, msg):
753+ self.protocolwriter[msg.name](*msg.args)
754+
755+ def close(self):
756+ super(SessionWriter, self).close()
757+ try:
758+ self.socket.shutdown(SHUT_WR)
759+ except:
760+ pass
761+
762+#===============================================================================
763+
764+class SessionStarter(ActiveObjectBase):
765+
766+ def __init__(self, onstart):
767+ super(SessionStarter, self).__init__()
768+ self._onstart = onstart
769+
770+ def do(self):
771+ self._onstart()
772+
773+#===============================================================================
774+# s = Session(sock, proto)
775+# s.message.send(portsrc=2345,portdst=80,data="hello world")
776+# s.message.ping(ttl=10)
777+#===============================================================================
778+
779+class Session(object):
780+
781+ async = True
782+
783+ def __init__(self, protocol):
784+ self._protocol = protocol
785+ self._lock = Lock()
786+ self._reader_done = False
787+ self._writer_done = False
788+ self._starter_done = False
789+ self._finished = False
790+ self.done = Signal()
791+ if not self.async:
792+ self._queue = Queue(-1)
793+
794+ daemon = True
795+
796+ def pluginto(self, socket):
797+ if self.async:
798+ react = self.react
799+ else:
800+ react = self._queue.put
801+ self._reader = SessionReader(socket, self._protocol, react)
802+ self._writer = SessionWriter(socket, self._protocol)
803+ self._starter = SessionStarter(self._on_start)
804+ self._reader.daemon = self.daemon
805+ self._writer.daemon = self.daemon
806+ self._starter.daemon = self.daemon
807+ self.message = self._writer.message
808+ self.send = self.message
809+ self._writer.eof.connect(self._reader.close)
810+ def closing():
811+ self._writer.recv(None)
812+ self._reader.eof.connect(closing)
813+ self._reader.end.connect(self._set_reader_done)
814+ self._writer.end.connect(self._set_writer_done)
815+ self._starter.end.connect(self._set_starter_done)
816+ self.done.connect(socket.close)
817+ #self._reader.end.connect(self.say_reader_done)
818+ #self._writer.end.connect(self.say_writer_done)
819+ #self._starter.end.connect(self.say_starter_done)
820+ #self.done.connect(self.say_done)
821+
822+ #def say_done(self):
823+ # print "DONE"
824+
825+ #def say_reader_done(self):
826+ # print "READER DONE"
827+
828+ #def say_writer_done(self):
829+ # print "WRITER DONE"
830+
831+ #def say_starter_done(self):
832+ # print "STARTER DONE"
833+
834+ def _all_done(self):
835+ # should only be invoked under self._lock
836+ return self._reader_done and self._writer_done and self._starter_done
837+
838+ def _set_reader_done(self):
839+ all_done = False
840+ with self._lock:
841+ if not self._reader_done:
842+ self._reader_done = True
843+ all_done = self._all_done()
844+ if all_done:
845+ self.done()
846+
847+ def _set_writer_done(self):
848+ all_done = False
849+ with self._lock:
850+ if not self._writer_done:
851+ self._writer_done = True
852+ all_done = self._all_done()
853+ if all_done:
854+ self.done()
855+
856+ def _set_starter_done(self):
857+ all_done = False
858+ with self._lock:
859+ if not self._starter_done:
860+ self._starter_done = True
861+ all_done = self._all_done()
862+ if all_done:
863+ self.done()
864+
865+ def start(self):
866+ self._reader.start()
867+ self._writer.start()
868+ self._starter.start()
869+
870+ def _on_start(self):
871+ self.on_start()
872+ if not self.async:
873+ self.finish()
874+
875+ def on_start(self):
876+ pass
877+
878+ def finish(self):
879+ doit = False
880+ with self._lock:
881+ if not self._finished:
882+ self._finished = True
883+ doit = True
884+ if doit:
885+ self._writer.recv(None)
886+ self._reader.close()
887+
888+ def close(self):
889+ self._reader.close()
890+ self._writer.recv(None)
891+ self._writer.close()
892+
893+ def wait(self):
894+ self._starter.join()
895+ self._reader.join()
896+ self._writer.join()
897+
898+ def react(self, msg):
899+ doname = "do_%s" % msg.name
900+ try:
901+ dofun = getattr(self, doname)
902+ except AttributeError:
903+ raise NotImplementedError(doname)
904+ dofun(*msg.args)
905+
906+ def recv(self):
907+ return self._queue.get()
908+
909+ # you must implement all the do_FOO methods for the
910+ # messages (e.g. FOO) in your protocol
911
912=== added file 'build/lib.linux-i686-2.7/pynetez/Signal.py'
913--- build/lib.linux-i686-2.7/pynetez/Signal.py 1970-01-01 00:00:00 +0000
914+++ build/lib.linux-i686-2.7/pynetez/Signal.py 2012-06-15 10:11:52 +0000
915@@ -0,0 +1,54 @@
916+#==============================================================================
917+# Copyright (C) 2011 by Denys Duchier
918+#
919+# This program is free software; you can redistribute it and/or modify it under
920+# the terms of the GNU General Public License as published by the Free Software
921+# Foundation; either version 2 of the License, or (at your option) any later
922+# version.
923+#
924+# This program is distributed in the hope that it will be useful, but WITHOUT
925+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
926+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
927+# details.
928+#
929+# You should have received a copy of the GNU General Public License along with
930+# this program; if not, write to the Free Software Foundation, Inc., 51
931+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
932+#==============================================================================
933+
934+from threading import RLock
935+
936+class Signal(object):
937+ """a Signal can be connected to slots: whenever the signal is called, all
938+ the connected slots are invoked with the same arguments as the signal.
939+ """
940+
941+ def __init__(self):
942+ self._rlock = RLock()
943+ self._closed = False
944+ self._slots = ()
945+
946+ def __call__(self, *args, **kargs):
947+ for s in self._slots:
948+ s(*args, **kargs)
949+
950+ def connect(self, slot):
951+ with self._rlock:
952+ if not self._closed and \
953+ slot not in self._slots:
954+ # update with a new tuple so that ongoing
955+ # iterations don't get messed up
956+ self._slots = self._slots + (slot,)
957+
958+ def disconnect(self, slot):
959+ with self._rlock:
960+ if slot in self._slots:
961+ l = list(self._slots)
962+ l.remove(slot)
963+ self._slots = tuple(l)
964+
965+ def close(self):
966+ with self._rlock:
967+ if not self._closed:
968+ self._closed = True
969+ self._slots = ()
970
971=== added file 'build/lib.linux-i686-2.7/pynetez/Socket.py'
972--- build/lib.linux-i686-2.7/pynetez/Socket.py 1970-01-01 00:00:00 +0000
973+++ build/lib.linux-i686-2.7/pynetez/Socket.py 2012-06-15 10:11:52 +0000
974@@ -0,0 +1,324 @@
975+#==============================================================================
976+# Copyright (C) 2011 by Denys Duchier
977+#
978+# This program is free software; you can redistribute it and/or modify it under
979+# the terms of the GNU General Public License as published by the Free Software
980+# Foundation; either version 2 of the License, or (at your option) any later
981+# version.
982+#
983+# This program is distributed in the hope that it will be useful, but WITHOUT
984+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
985+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
986+# details.
987+#
988+# You should have received a copy of the GNU General Public License along with
989+# this program; if not, write to the Free Software Foundation, Inc., 51
990+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
991+#==============================================================================
992+
993+import socket, struct
994+from IBuffer import IBuffer
995+
996+class Socket(object):
997+ """socket abstraction with buffering and un/marshaling methods."""
998+
999+ BUFSIZE = 4096
1000+
1001+ def __init__(self, sock=None):
1002+ self._socket = sock
1003+ self._buffer = IBuffer(self._refill)
1004+
1005+ def socket(self, dom=socket.AF_INET, typ=socket.SOCK_STREAM):
1006+ sock = socket.socket(dom, typ)
1007+ self._socket = sock
1008+
1009+ def accept(self):
1010+ return Socket(self._socket.accept()[0])
1011+
1012+ def bind(self, addr):
1013+ self._socket.bind(addr)
1014+
1015+ def close(self):
1016+ self._socket.close()
1017+
1018+ def connect(self, addr):
1019+ self._socket.connect(addr)
1020+
1021+ def connect_ex(self, addr):
1022+ return self._socket.connect_ex(addr)
1023+
1024+ def fileno(self):
1025+ return self._socket.fileno()
1026+
1027+ def getpeername(self):
1028+ return self._socket.getpeername()
1029+
1030+ def getsockname(self):
1031+ return self._socket.getsockname()
1032+
1033+ def getsockopt(self, *args, **kw):
1034+ return self._socket.getsockopt(*args, **kw)
1035+
1036+ def ioctl(self, control, option):
1037+ return self._socket.ioctl(control, option)
1038+
1039+ def listen(self, backlog):
1040+ self._socket.listen(backlog)
1041+
1042+ def makefile(self, *args, **kw):
1043+ return self._socket.makefile(*args, **kw)
1044+
1045+ def recv(self, bufsize, flags=0):
1046+ return self._socket.recv(bufsize, flags)
1047+
1048+ def recvfrom(self, bufsize, flags=0):
1049+ return self._socket.recv(bufsize, flags)
1050+
1051+ def recvfrom_into(self, *args, **kw):
1052+ return self._socket.recvfrom_into(*args, **kw)
1053+
1054+ def recv_into(self, *args, **kw):
1055+ return self._socket.recv_into(*args, **kw)
1056+
1057+ def send(self, string, flags=0):
1058+ return self._socket.send(string, flags)
1059+
1060+ def sendall(self, string, flags=0):
1061+ self._socket.sendall(string, flags)
1062+
1063+ def sendto(self, *args, **kw):
1064+ return self._socket.sendto(*args, **kw)
1065+
1066+ def setblocking(self, flag):
1067+ self._socket.setblocking(flag)
1068+
1069+ def settimeout(self, value):
1070+ self._socket.settimeout(value)
1071+
1072+ def gettimeout(self):
1073+ return self._socket.gettimeout()
1074+
1075+ def setsockopt(self, level, optname, value):
1076+ self._socket.setsockopt(level, optname, value)
1077+
1078+ def shutdown(self, how):
1079+ self._socket.shutdown(how)
1080+
1081+ @property
1082+ def family(self):
1083+ return self._socket.family
1084+
1085+ @property
1086+ def type(self):
1087+ return self._socket.type
1088+
1089+ @property
1090+ def proto(self):
1091+ return self._socket.proto
1092+
1093+ def _refill(self):
1094+ return self.recv(self.BUFSIZE)
1095+
1096+ def read(self, n):
1097+ return self._buffer.read(n)
1098+
1099+ def write(self, buf):
1100+ self.sendall(buf)
1101+
1102+ def get_uint8(self):
1103+ return struct.unpack("B", self.read(1))[0]
1104+
1105+ def get_uint16(self):
1106+ return struct.unpack("!H", self.read(2))[0]
1107+
1108+ def get_uint32(self):
1109+ return struct.unpack("!I", self.read(4))[0]
1110+
1111+ get_uint = get_uint32
1112+
1113+ def get_int8(self):
1114+ return struct.unpack("b", self.read(1))[0]
1115+
1116+ def get_int16(self):
1117+ return struct.unpack("!h", self.read(2))[0]
1118+
1119+ def get_int32(self):
1120+ return struct.unpack("!i", self.read(4))[0]
1121+
1122+ get_int = get_int32
1123+
1124+ def put_uint8(self, i):
1125+ self.write(struct.pack("B", i))
1126+
1127+ def put_uint16(self, i):
1128+ self.write(struct.pack("!H", i))
1129+
1130+ def put_uint32(self, i):
1131+ self.write(struct.pack("!I", i))
1132+
1133+ put_uint = put_uint32
1134+
1135+ def put_int8(self, i):
1136+ self.write(struct.pack("b", i))
1137+
1138+ def put_int16(self, i):
1139+ self.write(struct.pack("!h", i))
1140+
1141+ def put_int32(self, i):
1142+ self.write(struct.pack("!i", i))
1143+
1144+ def put_bytes(self, s):
1145+ self.put_uint32(len(s))
1146+ self.write(s)
1147+
1148+ def get_bytes(self):
1149+ n = self.get_uint32()
1150+ return self.read(n)
1151+
1152+
1153+class SocketProxy(object):
1154+ """abstraction for creating objects that delegate to an existing socket."""
1155+
1156+ def __init__(self, sock=None):
1157+ self._socket = sock
1158+
1159+ def socket(self, dom=socket.AF_INET, typ=socket.SOCK_STREAM):
1160+ self._socket.socket(dom, typ)
1161+
1162+ def accept(self):
1163+ return self._socket.accept()
1164+
1165+ def bind(self, addr):
1166+ self._socket.bind(addr)
1167+
1168+ def close(self):
1169+ self._socket.close()
1170+
1171+ def connect(self, addr):
1172+ self._socket.connect(addr)
1173+
1174+ def connect_ex(self, addr):
1175+ return self._socket.connect_ex(addr)
1176+
1177+ def fileno(self):
1178+ return self._socket.fileno()
1179+
1180+ def getpeername(self):
1181+ return self._socket.getpeername()
1182+
1183+ def getsockname(self):
1184+ return self._socket.getsockname()
1185+
1186+ def getsockopt(self, *args, **kw):
1187+ return self._socket.getsockopt(*args, **kw)
1188+
1189+ def ioctl(self, control, option):
1190+ return self._socket.ioctl(control, option)
1191+
1192+ def listen(self, backlog):
1193+ self._socket.listen(backlog)
1194+
1195+ def makefile(self, *args, **kw):
1196+ return self._socket.makefile(*args, **kw)
1197+
1198+ def recv(self, bufsize, flags=0):
1199+ return self._socket.recv(bufsize, flags)
1200+
1201+ def recvfrom(self, bufsize, flags=0):
1202+ return self._socket.recv(bufsize, flags)
1203+
1204+ def recvfrom_into(self, *args, **kw):
1205+ return self._socket.recvfrom_into(*args, **kw)
1206+
1207+ def recv_into(self, *args, **kw):
1208+ return self._socket.recv_into(*args, **kw)
1209+
1210+ def send(self, string, flags=0):
1211+ return self._socket.send(string, flags)
1212+
1213+ def sendall(self, string, flags=0):
1214+ self._socket.sendall(string, flags)
1215+
1216+ def sendto(self, *args, **kw):
1217+ return self._socket.sendto(*args, **kw)
1218+
1219+ def setblocking(self, flag):
1220+ self._socket.setblocking(flag)
1221+
1222+ def settimeout(self, value):
1223+ self._socket.settimeout(value)
1224+
1225+ def gettimeout(self):
1226+ return self._socket.gettimeout()
1227+
1228+ def setsockopt(self, level, optname, value):
1229+ self._socket.setsockopt(level, optname, value)
1230+
1231+ def shutdown(self, how):
1232+ self._socket.shutdown(how)
1233+
1234+ @property
1235+ def family(self):
1236+ return self._socket.family
1237+
1238+ @property
1239+ def type(self):
1240+ return self._socket.type
1241+
1242+ @property
1243+ def proto(self):
1244+ return self._socket.proto
1245+
1246+ def read(self, n):
1247+ return self._socket.read(n)
1248+
1249+ def write(self, buf):
1250+ self._socket.write(buf)
1251+
1252+ def get_uint8(self):
1253+ return self._socket.get_uint8()
1254+
1255+ def get_uint16(self):
1256+ return self._socket.get_uint16()
1257+
1258+ def get_uint32(self):
1259+ return self._socket.get_uint32()
1260+
1261+ get_uint = get_uint32
1262+
1263+ def get_int8(self):
1264+ return self._socket.get_int8()
1265+
1266+ def get_int16(self):
1267+ return self._socket.get_int16()
1268+
1269+ def get_int32(self):
1270+ return self._socket.get_int32()
1271+
1272+ get_int = get_int32
1273+
1274+ def put_uint8(self, i):
1275+ self._socket.put_uint8(i)
1276+
1277+ def put_uint16(self, i):
1278+ self._socket.put_uint16(i)
1279+
1280+ def put_uint32(self, i):
1281+ self._socket.put_uint32(i)
1282+
1283+ put_uint = put_uint32
1284+
1285+ def put_int8(self, i):
1286+ self._socket.put_int8(i)
1287+
1288+ def put_int16(self, i):
1289+ self._socket.put_int16(i)
1290+
1291+ def put_int32(self, i):
1292+ self._socket.put_int32(i)
1293+
1294+ def put_bytes(self, s):
1295+ self._socket.put_bytes(s)
1296+
1297+ def get_bytes(self):
1298+ return self._socket.get_bytes()
1299
1300=== added file 'build/lib.linux-i686-2.7/pynetez/Writer.py'
1301--- build/lib.linux-i686-2.7/pynetez/Writer.py 1970-01-01 00:00:00 +0000
1302+++ build/lib.linux-i686-2.7/pynetez/Writer.py 2012-06-15 10:11:52 +0000
1303@@ -0,0 +1,37 @@
1304+#==============================================================================
1305+# Copyright (C) 2011 by Denys Duchier
1306+#
1307+# This program is free software; you can redistribute it and/or modify it under
1308+# the terms of the GNU General Public License as published by the Free Software
1309+# Foundation; either version 2 of the License, or (at your option) any later
1310+# version.
1311+#
1312+# This program is distributed in the hope that it will be useful, but WITHOUT
1313+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1314+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1315+# details.
1316+#
1317+# You should have received a copy of the GNU General Public License along with
1318+# this program; if not, write to the Free Software Foundation, Inc., 51
1319+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1320+#==============================================================================
1321+
1322+from ActiveObject import ActiveObject
1323+
1324+class Writer(ActiveObject):
1325+ """an active object that serializes to a socket all the messages that it receives."""
1326+
1327+ def __init__(self, socket):
1328+ self.socket = socket
1329+ super(Writer, self).__init__()
1330+
1331+ def react(self, msg):
1332+ try:
1333+ self.write(msg)
1334+ except IOError:
1335+ self.close()
1336+
1337+ # you need to reimplement this method
1338+ # to serialize a message to the socket
1339+ def write(self, msg):
1340+ raise NotImplementedError()
1341
1342=== added file 'build/lib.linux-i686-2.7/pynetez/__init__.py'
1343--- build/lib.linux-i686-2.7/pynetez/__init__.py 1970-01-01 00:00:00 +0000
1344+++ build/lib.linux-i686-2.7/pynetez/__init__.py 2012-06-15 10:11:52 +0000
1345@@ -0,0 +1,17 @@
1346+#==============================================================================
1347+# Copyright (C) 2011 by Denys Duchier
1348+#
1349+# This program is free software; you can redistribute it and/or modify it under
1350+# the terms of the GNU General Public License as published by the Free Software
1351+# Foundation; either version 2 of the License, or (at your option) any later
1352+# version.
1353+#
1354+# This program is distributed in the hope that it will be useful, but WITHOUT
1355+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1356+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1357+# details.
1358+#
1359+# You should have received a copy of the GNU General Public License along with
1360+# this program; if not, write to the Free Software Foundation, Inc., 51
1361+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1362+#==============================================================================
1363
1364=== added file 'client.py'
1365Binary files client.py 1970-01-01 00:00:00 +0000 and client.py 2012-06-15 10:11:52 +0000 differ
1366=== renamed file 'client.py' => 'client.py.moved'
1367=== added directory 'examples'
1368=== added directory 'examples/calc'
1369=== added file 'examples/calc/client.py'
1370--- examples/calc/client.py 1970-01-01 00:00:00 +0000
1371+++ examples/calc/client.py 2012-06-15 10:11:52 +0000
1372@@ -0,0 +1,64 @@
1373+from proto import proto
1374+from pynetez.Session import Session
1375+from pynetez.Client import Client
1376+
1377+#===============================================================================
1378+# session and client
1379+#===============================================================================
1380+
1381+class SessionOnClient(Session):
1382+
1383+ def do_err(self):
1384+ print "ERROR"
1385+
1386+ def do_okint(self, result):
1387+ print result
1388+
1389+ def do_okstr(self, result):
1390+ print repr(result)
1391+
1392+client = Client(proto, SessionOnClient)
1393+client.run_argv(wait=False)
1394+
1395+#===============================================================================
1396+# command shell to control the above
1397+#===============================================================================
1398+
1399+from cmd import Cmd
1400+
1401+class Shell(Cmd):
1402+
1403+ def do_add(self, line):
1404+ a1, a2 = line.strip().split()
1405+ a1 = int(a1)
1406+ a2 = int(a2)
1407+ client.send.add(a1, a2)
1408+
1409+ def do_sub(self, line):
1410+ a1, a2 = line.strip().split()
1411+ a1 = int(a1)
1412+ a2 = int(a2)
1413+ client.send.sub(a1, a2)
1414+
1415+ def do_mul(self, line):
1416+ a1, a2 = line.strip().split()
1417+ a1 = int(a1)
1418+ a2 = int(a2)
1419+ client.send.mul(a1, a2)
1420+
1421+ def do_substr(self, line):
1422+ a1, a2, a3 = line.strip().split()
1423+ a2 = int(a2)
1424+ a3 = int(a3)
1425+ client.send.substr(a1, a2, a3)
1426+
1427+ def do_quit(self, line):
1428+ client.finish()
1429+ return True
1430+
1431+ def do_EOF(self, line):
1432+ return self.do_quit()
1433+
1434+shell = Shell()
1435+shell.cmdloop()
1436+client.wait()
1437
1438=== added file 'examples/calc/proto.py'
1439--- examples/calc/proto.py 1970-01-01 00:00:00 +0000
1440+++ examples/calc/proto.py 2012-06-15 10:11:52 +0000
1441@@ -0,0 +1,10 @@
1442+from pynetez.Protocol import Protocol, int32, string
1443+
1444+proto = Protocol()
1445+proto.define("add", int32, int32)
1446+proto.define("sub", int32, int32)
1447+proto.define("mul", int32, int32)
1448+proto.define("substr", string, int32, int32)
1449+proto.define("err")
1450+proto.define("okint", int32)
1451+proto.define("okstr", string)
1452
1453=== added file 'examples/calc/server.py'
1454--- examples/calc/server.py 1970-01-01 00:00:00 +0000
1455+++ examples/calc/server.py 2012-06-15 10:11:52 +0000
1456@@ -0,0 +1,23 @@
1457+from proto import proto
1458+from pynetez.Session import Session
1459+from pynetez.Server import Server
1460+
1461+class SessionOnServer(Session):
1462+
1463+ def do_add(self, x, y):
1464+ self.send.okint(x+y)
1465+
1466+ def do_sub(self, x, y):
1467+ self.send.okint(x-y)
1468+
1469+ def do_mul(self, x, y):
1470+ self.send.okint(x*y)
1471+
1472+ def do_substr(self, s, i, j):
1473+ if i>=len(s) or j>len(s):
1474+ self.send.err()
1475+ else:
1476+ self.send.okstr(s[i:j])
1477+
1478+server = Server(proto, SessionOnServer)
1479+server.run_argv()
1480
1481=== added directory 'examples/date'
1482=== added directory 'examples/date/async'
1483=== added file 'examples/date/async/client.py'
1484--- examples/date/async/client.py 1970-01-01 00:00:00 +0000
1485+++ examples/date/async/client.py 2012-06-15 10:11:52 +0000
1486@@ -0,0 +1,15 @@
1487+from proto import proto
1488+from pynetez.Session import Session
1489+from pynetez.Client import Client
1490+
1491+class SessionOnClient(Session):
1492+
1493+ def do_tell(self, date):
1494+ print date
1495+ self.finish()
1496+
1497+ def on_start(self):
1498+ self.send.ask()
1499+
1500+client = Client(proto, SessionOnClient)
1501+client.run_argv()
1502
1503=== added file 'examples/date/async/proto.py'
1504--- examples/date/async/proto.py 1970-01-01 00:00:00 +0000
1505+++ examples/date/async/proto.py 2012-06-15 10:11:52 +0000
1506@@ -0,0 +1,5 @@
1507+from pynetez.Protocol import Protocol, string
1508+
1509+proto = Protocol()
1510+proto.define("ask")
1511+proto.define("tell", string)
1512
1513=== added file 'examples/date/async/server.py'
1514--- examples/date/async/server.py 1970-01-01 00:00:00 +0000
1515+++ examples/date/async/server.py 2012-06-15 10:11:52 +0000
1516@@ -0,0 +1,12 @@
1517+from proto import proto
1518+from pynetez.Session import Session
1519+from pynetez.Server import Server
1520+import time
1521+
1522+class SessionOnServer(Session):
1523+
1524+ def do_ask(self):
1525+ self.send.tell(time.asctime())
1526+
1527+server = Server(proto, SessionOnServer)
1528+server.run_argv()
1529
1530=== added directory 'examples/date/sync'
1531=== added file 'examples/date/sync/client.py'
1532--- examples/date/sync/client.py 1970-01-01 00:00:00 +0000
1533+++ examples/date/sync/client.py 2012-06-15 10:11:52 +0000
1534@@ -0,0 +1,15 @@
1535+from proto import proto
1536+from pynetez.Session import Session
1537+from pynetez.Client import Client
1538+
1539+class SessionOnClient(Session):
1540+
1541+ async = False
1542+
1543+ def on_start(self):
1544+ self.send.ask()
1545+ m=self.recv()
1546+ print m[0]
1547+
1548+client = Client(proto, SessionOnClient)
1549+client.run_argv()
1550
1551=== added file 'examples/date/sync/proto.py'
1552--- examples/date/sync/proto.py 1970-01-01 00:00:00 +0000
1553+++ examples/date/sync/proto.py 2012-06-15 10:11:52 +0000
1554@@ -0,0 +1,5 @@
1555+from pynetez.Protocol import Protocol, string
1556+
1557+proto = Protocol()
1558+proto.define("ask")
1559+proto.define("tell", string)
1560
1561=== added file 'examples/date/sync/server.py'
1562--- examples/date/sync/server.py 1970-01-01 00:00:00 +0000
1563+++ examples/date/sync/server.py 2012-06-15 10:11:52 +0000
1564@@ -0,0 +1,12 @@
1565+from proto import proto
1566+from pynetez.Session import Session
1567+from pynetez.Server import Server
1568+import time
1569+
1570+class SessionOnServer(Session):
1571+
1572+ def do_ask(self):
1573+ self.send.tell(time.asctime())
1574+
1575+server = Server(proto, SessionOnServer)
1576+server.run_argv()
1577
1578=== added directory 'examples/nim'
1579=== added directory 'examples/nim-agent'
1580=== added file 'examples/nim-agent/client.py'
1581--- examples/nim-agent/client.py 1970-01-01 00:00:00 +0000
1582+++ examples/nim-agent/client.py 2012-06-15 10:11:52 +0000
1583@@ -0,0 +1,39 @@
1584+from proto import proto
1585+from pynetez.Session import Session
1586+from pynetez.Client import Client
1587+
1588+class SessionOnClient(Session):
1589+
1590+ def do_go(self):
1591+ n = int(raw_input("Your move: "))
1592+ self.send.take(n)
1593+
1594+ def do_err(self):
1595+ print "illegal move"
1596+
1597+ def do_left(self, n):
1598+ print "Left:", n
1599+
1600+ def do_won(self):
1601+ print "You won!"
1602+ self.finish()
1603+
1604+ def do_lost(self):
1605+ print "You lost!"
1606+ self.finish()
1607+
1608+ def do_abort(self):
1609+ print "Game aborted!"
1610+ self.finish()
1611+
1612+ def do_pending(self):
1613+ print "Waiting for an opponent"
1614+
1615+ def do_connected(self):
1616+ print "Connected to an opponent"
1617+
1618+ def do_wait(self):
1619+ print "Wait for your opponent's move"
1620+
1621+client = Client(proto, SessionOnClient)
1622+client.run_argv()
1623
1624=== added file 'examples/nim-agent/proto.py'
1625--- examples/nim-agent/proto.py 1970-01-01 00:00:00 +0000
1626+++ examples/nim-agent/proto.py 2012-06-15 10:11:52 +0000
1627@@ -0,0 +1,13 @@
1628+from pynetez.Protocol import Protocol, int8
1629+
1630+proto = Protocol()
1631+proto.define("pending") # waiting to be connected to an opponent
1632+proto.define("connected") # just connected to an opponent
1633+proto.define("go") # your turn to play
1634+proto.define("wait") # your turn to wait
1635+proto.define("take", int8) # how many tokens you take
1636+proto.define("err") # illegal move
1637+proto.define("abort") # game aborted
1638+proto.define("left", int8) # how many tokens are left
1639+proto.define("won") # you just won
1640+proto.define("lost") # you just lost
1641
1642=== added file 'examples/nim-agent/server.py'
1643--- examples/nim-agent/server.py 1970-01-01 00:00:00 +0000
1644+++ examples/nim-agent/server.py 2012-06-15 10:11:52 +0000
1645@@ -0,0 +1,91 @@
1646+from proto import proto
1647+from pynetez.Session import Session
1648+from pynetez.Server import Server
1649+from threading import Lock
1650+from pynetez.Agent import Agent
1651+
1652+from pynetez.Protocol import Protocol
1653+masterproto = Protocol()
1654+masterproto.define("play", None, None) # agent, n
1655+
1656+class GameMaster(Agent):
1657+
1658+ def __init__(self, player1, player2):
1659+ super(GameMaster, self).__init__(masterproto)
1660+ self.player1 = player1
1661+ self.player2 = player2
1662+ self.left = 21
1663+ self.begin.connect(self.connected)
1664+
1665+ def connected(self):
1666+ self.player1.send.connected()
1667+ self.player2.send.connected()
1668+ self.player1.send.go()
1669+ self.player2.send.wait()
1670+
1671+ def finish(self):
1672+ super(GameMaster, self).finish()
1673+ self.player1.finish()
1674+ self.player2.finish()
1675+
1676+ def do_play(self, player, n):
1677+ if player is not self.player1:
1678+ # out of turn: abort game
1679+ self.player1.send.abort()
1680+ self.player2.send.abort()
1681+ self.finish()
1682+ elif n > self.left or n > 3:
1683+ # trying to take too much: return error and ask for new move
1684+ self.player1.send.err()
1685+ self.player1.send.go()
1686+ else:
1687+ # take n off
1688+ self.left -= n
1689+ # inform players of what's left
1690+ self.player1.send.left(self.left)
1691+ self.player2.send.left(self.left)
1692+ if self.left == 0:
1693+ # if it's a win: end game
1694+ self.player1.send.won()
1695+ self.player2.send.lost()
1696+ self.finish()
1697+ else:
1698+ # else switch players
1699+ self.switch()
1700+ self.player1.send.go()
1701+ self.player2.send.wait()
1702+
1703+ def switch(self):
1704+ self.player1, self.player2 = self.player2, self.player1
1705+
1706+lock = Lock()
1707+waiting = None
1708+
1709+class SessionOnServer(Session):
1710+
1711+ def __init__(self, *args, **kargs):
1712+ super(SessionOnServer, self).__init__(*args, **kargs)
1713+ with lock:
1714+ global waiting
1715+ if waiting is None:
1716+ waiting = self
1717+ self.startmaster = False
1718+ else:
1719+ player1 = waiting
1720+ waiting = None
1721+ player2 = self
1722+ gamemaster = GameMaster(player1, player2)
1723+ player1.master = gamemaster
1724+ player2.master = gamemaster
1725+ self.startmaster = True
1726+
1727+ def on_start(self):
1728+ self.send.pending()
1729+ if self.startmaster:
1730+ self.master.start()
1731+
1732+ def do_take(self, n):
1733+ self.master.recv.play(self, n)
1734+
1735+server = Server(proto, SessionOnServer)
1736+server.run_argv()
1737
1738=== added file 'examples/nim/client.py'
1739--- examples/nim/client.py 1970-01-01 00:00:00 +0000
1740+++ examples/nim/client.py 2012-06-15 10:11:52 +0000
1741@@ -0,0 +1,39 @@
1742+from proto import proto
1743+from pynetez.Session import Session
1744+from pynetez.Client import Client
1745+
1746+class SessionOnClient(Session):
1747+
1748+ def do_go(self):
1749+ n = int(raw_input("Your move: "))
1750+ self.send.take(n)
1751+
1752+ def do_err(self):
1753+ print "illegal move"
1754+
1755+ def do_left(self, n):
1756+ print "Left:", n
1757+
1758+ def do_won(self):
1759+ print "You won!"
1760+ self.finish()
1761+
1762+ def do_lost(self):
1763+ print "You lost!"
1764+ self.finish()
1765+
1766+ def do_abort(self):
1767+ print "Game aborted!"
1768+ self.finish()
1769+
1770+ def do_pending(self):
1771+ print "Waiting for an opponent"
1772+
1773+ def do_connected(self):
1774+ print "Connected to an opponent"
1775+
1776+ def do_wait(self):
1777+ print "Wait for your opponent's move"
1778+
1779+client = Client(proto, SessionOnClient)
1780+client.run_argv()
1781
1782=== added file 'examples/nim/proto.py'
1783--- examples/nim/proto.py 1970-01-01 00:00:00 +0000
1784+++ examples/nim/proto.py 2012-06-15 10:11:52 +0000
1785@@ -0,0 +1,13 @@
1786+from pynetez.Protocol import Protocol, int8
1787+
1788+proto = Protocol()
1789+proto.define("pending") # waiting to be connected to an opponent
1790+proto.define("connected") # just connected to an opponent
1791+proto.define("go") # your turn to play
1792+proto.define("wait") # your turn to wait
1793+proto.define("take", int8) # how many tokens you take
1794+proto.define("err") # illegal move
1795+proto.define("abort") # game aborted
1796+proto.define("left", int8) # how many tokens are left
1797+proto.define("won") # you just won
1798+proto.define("lost") # you just lost
1799
1800=== added file 'examples/nim/server.py'
1801--- examples/nim/server.py 1970-01-01 00:00:00 +0000
1802+++ examples/nim/server.py 2012-06-15 10:11:52 +0000
1803@@ -0,0 +1,88 @@
1804+from proto import proto
1805+from pynetez.Session import Session
1806+from pynetez.Server import Server
1807+from threading import Lock
1808+from pynetez.ActiveObject import ActiveObject
1809+
1810+class GameMaster(ActiveObject):
1811+
1812+ def __init__(self, player1, player2):
1813+ super(GameMaster, self).__init__()
1814+ self.player1 = player1
1815+ self.player2 = player2
1816+ self.left = 21
1817+ self.begin.connect(self.connected)
1818+
1819+ def connected(self):
1820+ self.player1.send.connected()
1821+ self.player2.send.connected()
1822+ self.player1.send.go()
1823+ self.player2.send.wait()
1824+
1825+ def finish(self):
1826+ self.recv(None)
1827+ self.player1.finish()
1828+ self.player2.finish()
1829+
1830+ def react(self, msg):
1831+ player, n = msg
1832+ if player is not self.player1:
1833+ # out of turn: abort game
1834+ self.player1.send.abort()
1835+ self.player2.send.abort()
1836+ self.finish()
1837+ elif n > self.left or n > 3:
1838+ # trying to take too much: return error and ask for new move
1839+ self.player1.send.err()
1840+ self.player1.send.go()
1841+ else:
1842+ # take n off
1843+ self.left -= n
1844+ # inform players of what's left
1845+ self.player1.send.left(self.left)
1846+ self.player2.send.left(self.left)
1847+ if self.left == 0:
1848+ # if it's a win: end game
1849+ self.player1.send.won()
1850+ self.player2.send.lost()
1851+ self.finish()
1852+ else:
1853+ # else switch players
1854+ self.switch()
1855+ self.player1.send.go()
1856+ self.player2.send.wait()
1857+
1858+ def switch(self):
1859+ self.player1, self.player2 = self.player2, self.player1
1860+
1861+lock = Lock()
1862+waiting = None
1863+
1864+class SessionOnServer(Session):
1865+
1866+ def __init__(self, *args, **kargs):
1867+ super(SessionOnServer, self).__init__(*args, **kargs)
1868+ with lock:
1869+ global waiting
1870+ if waiting is None:
1871+ waiting = self
1872+ self.startmaster = False
1873+ else:
1874+ player1 = waiting
1875+ waiting = None
1876+ player2 = self
1877+ gamemaster = GameMaster(player1, player2)
1878+ player1.master = gamemaster
1879+ player2.master = gamemaster
1880+ self.startmaster = True
1881+
1882+ def on_start(self):
1883+ self.send.pending()
1884+ if self.startmaster:
1885+ self.master.start()
1886+
1887+ def do_take(self, n):
1888+ self.master.recv((self, n))
1889+
1890+server = Server(proto, SessionOnServer)
1891+server.run_argv()
1892
1893=== added directory 'examples/pingpong'
1894=== added file 'examples/pingpong/client.py'
1895--- examples/pingpong/client.py 1970-01-01 00:00:00 +0000
1896+++ examples/pingpong/client.py 2012-06-15 10:11:52 +0000
1897@@ -0,0 +1,15 @@
1898+from proto import proto
1899+from pynetez.Session import Session
1900+from pynetez.Client import Client
1901+
1902+class SessionOnClient(Session):
1903+
1904+ def do_pong(self):
1905+ print "PONG"
1906+ self.finish()
1907+
1908+ def on_start(self):
1909+ self.send.ping()
1910+
1911+client = Client(proto, SessionOnClient)
1912+client.run_argv()
1913
1914=== added file 'examples/pingpong/proto.py'
1915--- examples/pingpong/proto.py 1970-01-01 00:00:00 +0000
1916+++ examples/pingpong/proto.py 2012-06-15 10:11:52 +0000
1917@@ -0,0 +1,5 @@
1918+from pynetez.Protocol import Protocol
1919+
1920+proto = Protocol()
1921+proto.define("ping")
1922+proto.define("pong")
1923
1924=== added file 'examples/pingpong/server.py'
1925--- examples/pingpong/server.py 1970-01-01 00:00:00 +0000
1926+++ examples/pingpong/server.py 2012-06-15 10:11:52 +0000
1927@@ -0,0 +1,12 @@
1928+from proto import proto
1929+from pynetez.Session import Session
1930+from pynetez.Server import Server
1931+
1932+class SessionOnServer(Session):
1933+
1934+ def do_ping(self):
1935+ print "PING"
1936+ self.send.pong()
1937+
1938+server = Server(proto, SessionOnServer)
1939+server.run_argv()
1940
1941=== added file 'proto.py'
1942--- proto.py 1970-01-01 00:00:00 +0000
1943+++ proto.py 2012-06-15 10:11:52 +0000
1944@@ -0,0 +1,33 @@
1945+from pynetez.Protocol import Protocol, int8
1946+
1947+proto = Protocol()
1948+proto.define("pending") # waiting to be connected to an opponent
1949+proto.define("connected") # just connected to an opponent
1950+proto.define("go") # your turn to play
1951+proto.define("wait") # your turn to wait
1952+proto.define("take", int8, int8, int8) # how many tokens you take
1953+proto.define("err") # illegal move
1954+proto.define("abort") # game aborted
1955+proto.define("left", int8) # how many tokens are left
1956+proto.define("won") # you just won
1957+proto.define("lost") # you just lost
1958+proto.define("countStory") # counting the beginning of the story
1959+proto.define("action", int8, int8)
1960+proto.define("entree1")
1961+proto.define("entree2")
1962+proto.define("couloir")
1963+proto.define("fuite")
1964+proto.define("salleGauche")
1965+proto.define("salleDroite")
1966+proto.define("erreur")
1967+proto.define("salle2Droite")
1968+proto.define("salle1Droite")
1969+proto.define("Gameover")
1970+proto.define("salle2gauche")
1971+proto.define("escalier")
1972+proto.define("escalierMonte")
1973+proto.define("erreur")
1974+
1975+
1976+
1977+
1978
1979=== renamed file 'proto.py' => 'proto.py.moved'
1980=== added directory 'pynetez'
1981=== added file 'pynetez/ADict.py'
1982--- pynetez/ADict.py 1970-01-01 00:00:00 +0000
1983+++ pynetez/ADict.py 2012-06-15 10:11:52 +0000
1984@@ -0,0 +1,54 @@
1985+#==============================================================================
1986+# Copyright (C) 2011 by Denys Duchier
1987+#
1988+# This program is free software; you can redistribute it and/or modify it under
1989+# the terms of the GNU General Public License as published by the Free Software
1990+# Foundation; either version 2 of the License, or (at your option) any later
1991+# version.
1992+#
1993+# This program is distributed in the hope that it will be useful, but WITHOUT
1994+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1995+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1996+# details.
1997+#
1998+# You should have received a copy of the GNU General Public License along with
1999+# this program; if not, write to the Free Software Foundation, Inc., 51
2000+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2001+#==============================================================================
2002+
2003+class ADict(object):
2004+
2005+ __slots__ = ('_table_',)
2006+
2007+ def __init__(self):
2008+ ADict._table_.__set__(self, {})
2009+
2010+ def __getattr__(self, name):
2011+ return self[name]
2012+
2013+ def __setattr__(self, name, value):
2014+ self[name] = value
2015+
2016+ def __delattr__(self, name):
2017+ del self[name]
2018+
2019+ def __getitem__(self, name):
2020+ return self._table_[name]
2021+
2022+ def __setitem__(self, name, value):
2023+ self._table_[name] = value
2024+
2025+ def __delitem__(self, name):
2026+ del self._table_[name]
2027+
2028+ def values(self):
2029+ return self._table_.values()
2030+
2031+ def keys(self):
2032+ return self._table_.keys()
2033+
2034+ def items(self):
2035+ return self._table_.items()
2036+
2037+ def __contains__(self, key):
2038+ return key in self._table_
2039
2040=== added file 'pynetez/ActiveObject.py'
2041--- pynetez/ActiveObject.py 1970-01-01 00:00:00 +0000
2042+++ pynetez/ActiveObject.py 2012-06-15 10:11:52 +0000
2043@@ -0,0 +1,45 @@
2044+#==============================================================================
2045+# Copyright (C) 2011 by Denys Duchier
2046+#
2047+# This program is free software; you can redistribute it and/or modify it under
2048+# the terms of the GNU General Public License as published by the Free Software
2049+# Foundation; either version 2 of the License, or (at your option) any later
2050+# version.
2051+#
2052+# This program is distributed in the hope that it will be useful, but WITHOUT
2053+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2054+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2055+# details.
2056+#
2057+# You should have received a copy of the GNU General Public License along with
2058+# this program; if not, write to the Free Software Foundation, Inc., 51
2059+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2060+#==============================================================================
2061+
2062+from ActiveObjectBase import ActiveObjectBase
2063+from Queue import Queue
2064+
2065+class ActiveObject(ActiveObjectBase):
2066+ """reacts to messages received on its queue."""
2067+
2068+ def __init__(self, *args, **kargs):
2069+ self._queue = Queue(-1)
2070+ super(ActiveObject, self).__init__(*args, **kargs)
2071+
2072+ def recv(self, msg):
2073+ if not self.closed:
2074+ self._queue.put(msg)
2075+
2076+ def do(self):
2077+ while not self.closed:
2078+ msg = self._queue.get()
2079+ # None causes the active object to close
2080+ if msg is None:
2081+ return self.close()
2082+ self.react(msg)
2083+
2084+ def react(self, msg):
2085+ raise NotImplementedError()
2086+
2087+ def close(self):
2088+ super(ActiveObject, self).close()
2089
2090=== added file 'pynetez/ActiveObjectBase.py'
2091--- pynetez/ActiveObjectBase.py 1970-01-01 00:00:00 +0000
2092+++ pynetez/ActiveObjectBase.py 2012-06-15 10:11:52 +0000
2093@@ -0,0 +1,46 @@
2094+#==============================================================================
2095+# Copyright (C) 2011 by Denys Duchier
2096+#
2097+# This program is free software; you can redistribute it and/or modify it under
2098+# the terms of the GNU General Public License as published by the Free Software
2099+# Foundation; either version 2 of the License, or (at your option) any later
2100+# version.
2101+#
2102+# This program is distributed in the hope that it will be useful, but WITHOUT
2103+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2104+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2105+# details.
2106+#
2107+# You should have received a copy of the GNU General Public License along with
2108+# this program; if not, write to the Free Software Foundation, Inc., 51
2109+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2110+#==============================================================================
2111+
2112+from Activity import Activity
2113+from Signal import Signal
2114+from threading import RLock
2115+
2116+class ActiveObjectBase(Activity):
2117+ """almost an ActiveObject, but without the queue."""
2118+
2119+ def __init__(self, *args, **kargs):
2120+ self.eof = Signal()
2121+ self._rlock = RLock()
2122+ self._closed = False
2123+ super(ActiveObjectBase, self).__init__(*args, **kargs)
2124+
2125+ @property
2126+ def closed(self):
2127+ return self._closed
2128+
2129+ def close(self):
2130+ sig = False
2131+ with self._rlock:
2132+ if not self._closed:
2133+ sig = True
2134+ self._closed = True
2135+ if sig:
2136+ self.eof()
2137+
2138+ def __del__(self):
2139+ self.close()
2140
2141=== added file 'pynetez/Activity.py'
2142--- pynetez/Activity.py 1970-01-01 00:00:00 +0000
2143+++ pynetez/Activity.py 2012-06-15 10:11:52 +0000
2144@@ -0,0 +1,61 @@
2145+#==============================================================================
2146+# Copyright (C) 2011 by Denys Duchier
2147+#
2148+# This program is free software; you can redistribute it and/or modify it under
2149+# the terms of the GNU General Public License as published by the Free Software
2150+# Foundation; either version 2 of the License, or (at your option) any later
2151+# version.
2152+#
2153+# This program is distributed in the hope that it will be useful, but WITHOUT
2154+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2155+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2156+# details.
2157+#
2158+# You should have received a copy of the GNU General Public License along with
2159+# this program; if not, write to the Free Software Foundation, Inc., 51
2160+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2161+#==============================================================================
2162+
2163+from Signal import Signal
2164+from threading import Thread
2165+
2166+class Activity(object):
2167+ """abstraction for doing things on a thread."""
2168+
2169+ def __init__(self, *args, **kw):
2170+ self._thread = None
2171+ self.begin = Signal()
2172+ self.end = Signal()
2173+ self.begin.connect(self.on_begin)
2174+ self.end.connect(self.on_end)
2175+
2176+ def on_begin(self):
2177+ pass
2178+
2179+ def on_end(self):
2180+ pass
2181+
2182+ daemon = True
2183+
2184+ def start(self, *args, **kw):
2185+ """create and start a thread for doing things."""
2186+ self._thread = Thread(target=self._do, args=args, kwargs=kw)
2187+ self._thread.daemon = self.daemon
2188+ self._thread.start()
2189+
2190+ def _do(self, *args, **kargs):
2191+ self.begin()
2192+ try:
2193+ self.do(*args, **kargs)
2194+ finally:
2195+ self.end()
2196+
2197+ def do(self, *args, **kargs):
2198+ """method for doing things
2199+
2200+ it is invoked with whatever arguments were passed to start().
2201+ """
2202+ raise NotImplementedError()
2203+
2204+ def join(self):
2205+ self._thread.join()
2206
2207=== added file 'pynetez/Agent.py'
2208--- pynetez/Agent.py 1970-01-01 00:00:00 +0000
2209+++ pynetez/Agent.py 2012-06-15 10:11:52 +0000
2210@@ -0,0 +1,51 @@
2211+#==============================================================================
2212+# Copyright (C) 2012 by Denys Duchier
2213+#
2214+# This program is free software; you can redistribute it and/or modify it under
2215+# the terms of the GNU General Public License as published by the Free Software
2216+# Foundation; either version 2 of the License, or (at your option) any later
2217+# version.
2218+#
2219+# This program is distributed in the hope that it will be useful, but WITHOUT
2220+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2221+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2222+# details.
2223+#
2224+# You should have received a copy of the GNU General Public License along with
2225+# this program; if not, write to the Free Software Foundation, Inc., 51
2226+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2227+#==============================================================================
2228+
2229+#==============================================================================
2230+# For the moment, an agent is an ActiveObject associated with a Protocol and
2231+# with methods for reacting to messages. Methods implementing reactions for
2232+# messages are also called do_XXX (where XXX is the message name).
2233+#==============================================================================
2234+
2235+from ActiveObject import ActiveObject
2236+from ADict import ADict
2237+
2238+class Agent(ActiveObject):
2239+
2240+ def __init__(self, proto, *args, **kargs):
2241+ super(Agent, self).__init__(*args, **kargs)
2242+ self._proto = proto
2243+ self._recv = qfun = self.recv
2244+ self.recv = vtable = ADict()
2245+ def mkmsg(mt, qfun):
2246+ def msg(*args):
2247+ qfun(mt(*args))
2248+ return msg
2249+ for mt in proto.msgtypes:
2250+ vtable[mt.name] = mkmsg(mt, qfun)
2251+
2252+ def react(self, msg):
2253+ doname = "do_%s" % msg.name
2254+ try:
2255+ dofun = getattr(self, doname)
2256+ except AttributeError:
2257+ raise NotImplementedError(doname)
2258+ dofun(*msg.args)
2259+
2260+ def finish(self):
2261+ self._recv(None)
2262
2263=== added file 'pynetez/Client.py'
2264--- pynetez/Client.py 1970-01-01 00:00:00 +0000
2265+++ pynetez/Client.py 2012-06-15 10:11:52 +0000
2266@@ -0,0 +1,45 @@
2267+#==============================================================================
2268+# Copyright (C) 2011 by Denys Duchier
2269+#
2270+# This program is free software; you can redistribute it and/or modify it under
2271+# the terms of the GNU General Public License as published by the Free Software
2272+# Foundation; either version 2 of the License, or (at your option) any later
2273+# version.
2274+#
2275+# This program is distributed in the hope that it will be useful, but WITHOUT
2276+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2277+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2278+# details.
2279+#
2280+# You should have received a copy of the GNU General Public License along with
2281+# this program; if not, write to the Free Software Foundation, Inc., 51
2282+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2283+#==============================================================================
2284+
2285+from Socket import Socket
2286+
2287+class Client(object):
2288+
2289+ def __init__(self, protocol, sessiontype):
2290+ self.session = sessiontype(protocol)
2291+
2292+ def run(self, host, port, wait=True):
2293+ socket = Socket()
2294+ socket.socket()
2295+ socket.connect((host, port))
2296+ self.session.pluginto(socket)
2297+ self.send = self.session.send
2298+ self.recv = self.session.recv
2299+ self.finish = self.session.finish
2300+ self.wait = self.session.wait
2301+ self.session.start()
2302+ if wait:
2303+ self.session.wait()
2304+
2305+ def run_argv(self, wait=True):
2306+ from optparse import OptionParser
2307+ parser = OptionParser("usage: %prog [options]")
2308+ parser.add_option("--host","-H",dest="host",default="localhost")
2309+ parser.add_option("--port","-p",dest="port",type=int,default=9999)
2310+ options, args = parser.parse_args()
2311+ self.run(options.host, options.port, wait=wait)
2312
2313=== added file 'pynetez/IBuffer.py'
2314--- pynetez/IBuffer.py 1970-01-01 00:00:00 +0000
2315+++ pynetez/IBuffer.py 2012-06-15 10:11:52 +0000
2316@@ -0,0 +1,64 @@
2317+#==============================================================================
2318+# Copyright (C) 2011 by Denys Duchier
2319+#
2320+# This program is free software; you can redistribute it and/or modify it under
2321+# the terms of the GNU General Public License as published by the Free Software
2322+# Foundation; either version 2 of the License, or (at your option) any later
2323+# version.
2324+#
2325+# This program is distributed in the hope that it will be useful, but WITHOUT
2326+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2327+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2328+# details.
2329+#
2330+# You should have received a copy of the GNU General Public License along with
2331+# this program; if not, write to the Free Software Foundation, Inc., 51
2332+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2333+#==============================================================================
2334+
2335+class IBuffer(object):
2336+ """abstraction for buffered input."""
2337+
2338+ def __init__(self, refill):
2339+ self._data = "" # buffered data
2340+ self._offset = 0 # how much of it we have already used
2341+ self._refill = refill # how to get more data
2342+ self._eof = False
2343+
2344+ @property
2345+ def size(self):
2346+ """how many bytes are still available in the buffer."""
2347+ return len(self._data) - self._offset
2348+
2349+ def _read(self, n):
2350+ if self._eof:
2351+ raise IOError("EOF")
2352+ m = self.size
2353+ if m <= 0:
2354+ return None
2355+ elif m >= n:
2356+ off = self._offset
2357+ nxt = off + n
2358+ self._offset = nxt
2359+ return self._data[off:nxt]
2360+ else:
2361+ data = self._data[self._offset:]
2362+ self._data = ""
2363+ self._offset = 0
2364+ return data
2365+
2366+ def read(self, n):
2367+ """read and return exactly n bytes from the stream."""
2368+ daten = []
2369+ while n:
2370+ data = self._read(n)
2371+ if not data:
2372+ self._offset = 0
2373+ self._data = self._refill()
2374+ if not self._data:
2375+ self._eof = True
2376+ raise IOError("EOF")
2377+ else:
2378+ daten.append(data)
2379+ n -= len(data)
2380+ return "".join(daten)
2381
2382=== added file 'pynetez/Protocol.py'
2383--- pynetez/Protocol.py 1970-01-01 00:00:00 +0000
2384+++ pynetez/Protocol.py 2012-06-15 10:11:52 +0000
2385@@ -0,0 +1,180 @@
2386+#==============================================================================
2387+# Copyright (C) 2011 by Denys Duchier
2388+#
2389+# This program is free software; you can redistribute it and/or modify it under
2390+# the terms of the GNU General Public License as published by the Free Software
2391+# Foundation; either version 2 of the License, or (at your option) any later
2392+# version.
2393+#
2394+# This program is distributed in the hope that it will be useful, but WITHOUT
2395+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2396+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2397+# details.
2398+#
2399+# You should have received a copy of the GNU General Public License along with
2400+# this program; if not, write to the Free Software Foundation, Inc., 51
2401+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2402+#==============================================================================
2403+
2404+#===============================================================================
2405+# possible types of message fields. each type knows how to un/marshal itself
2406+#===============================================================================
2407+
2408+class FieldType(object): pass
2409+
2410+class _uint8(FieldType):
2411+ def marshal(self, sock, i):
2412+ sock.put_uint8(i)
2413+ def unmarshal(self, sock):
2414+ return sock.get_uint8()
2415+uint8 = _uint8()
2416+
2417+class _uint16(FieldType):
2418+ def marshal(self, sock, i):
2419+ sock.put_int16(i)
2420+ def unmarshal(self, sock):
2421+ return sock.get_uint16()
2422+uint16 = _uint16()
2423+
2424+class _uint32(FieldType):
2425+ def marshal(self, sock, i):
2426+ sock.put_int32(i)
2427+ def unmarshal(self, sock):
2428+ return sock.get_uint32()
2429+uint32 = _uint32()
2430+
2431+class _int8(FieldType):
2432+ def marshal(self, sock, i):
2433+ sock.put_int8(i)
2434+ def unmarshal(self, sock):
2435+ return sock.get_int8()
2436+int8 = _int8()
2437+
2438+class _int16(FieldType):
2439+ def marshal(self, sock, i):
2440+ sock.put_int16(i)
2441+ def unmarshal(self, sock):
2442+ return sock.get_int16()
2443+int16 = _int16()
2444+
2445+class _int32(FieldType):
2446+ def marshal(self, sock, i):
2447+ sock.put_int32(i)
2448+ def unmarshal(self, sock):
2449+ return sock.get_int32()
2450+int32 = _int32()
2451+
2452+class listof(FieldType):
2453+ def __init__(self, typ):
2454+ self.elemtype = typ
2455+ def __cmp__(self, other):
2456+ return isinstance(other, listof) and \
2457+ self.elemtype == other.elemtype
2458+ def marshal(self, sock, l):
2459+ sock.put_uint32(len(l))
2460+ for x in l:
2461+ self.elemtype.marshal(sock, x)
2462+ def unmarshal(self, sock):
2463+ n = sock.get_uint32()
2464+ l = []
2465+ while n:
2466+ l.append(self.elemtype.unmarshal(sock))
2467+ n -= 1
2468+ return tuple(l)
2469+
2470+class _binary(FieldType):
2471+ def marshal(self, sock, b):
2472+ sock.put_bytes(b)
2473+ def unmarshal(self, sock):
2474+ return sock.get_bytes()
2475+binary = _binary()
2476+string = binary
2477+
2478+#===============================================================================
2479+# M1 = MessageType("send",0,dict(portsrc=int16,portdst=int16,data=binary))
2480+# m1 = M1(portsrc=2345,portdst=80,data="hello world")
2481+# m1.marshal(socket)
2482+# m2 = M1.unmarshal(socket)
2483+#===============================================================================
2484+
2485+class Message(object):
2486+
2487+ def __init__(self, msgtype, args):
2488+ self.type = msgtype
2489+ self.args = args
2490+
2491+ def marshal(self, sock):
2492+ self.type.marshal(sock, self.args)
2493+
2494+ @property
2495+ def name(self):
2496+ return self.type.name
2497+
2498+ def __getitem__(self, i):
2499+ return self.args[i]
2500+
2501+class MessageType(object):
2502+
2503+ def __init__(self, name, code, args):
2504+ self.name = name
2505+ self.code = code
2506+ if not isinstance(args, tuple):
2507+ args = tuple(args)
2508+ self.args = args
2509+
2510+ def __call__(self, *args):
2511+ return Message(self, args)
2512+
2513+ def marshal(self, sock, args):
2514+ sock.put_uint8(self.code)
2515+ for t,v in zip(self.args, args):
2516+ t.marshal(sock, v)
2517+
2518+ def unmarshal(self, sock):
2519+ return Message(self, tuple(t.unmarshal(sock) for t in self.args))
2520+
2521+ def writer(self, sock):
2522+ def msgwriter(*args):
2523+ self(*args).marshal(sock)
2524+ return msgwriter
2525+
2526+#===============================================================================
2527+# proto = Protocol()
2528+# proto.defmsgtype("send", int16, int16, binary)
2529+# proto.defmsgtype("ping", int32)
2530+# m1 = proto.message.send(2345, 80, "hello world")
2531+# m2 = proto.message.ping(23)
2532+# m1.marshal(sock)
2533+# m2.marshal(sock)
2534+# m3 = proto.unmarshal(sock)
2535+#===============================================================================
2536+
2537+from ADict import ADict
2538+
2539+class Protocol(object):
2540+
2541+ def __init__(self):
2542+ self._code = 0
2543+ self.message = ADict()
2544+
2545+ def defmsgtype(self, name, *args):
2546+ if name in self.message:
2547+ raise Exception("message type '%s' is already defined" % name)
2548+ code = self._code
2549+ self._code += 1
2550+ self.message[code] = MessageType(name, code, args)
2551+
2552+ define = defmsgtype
2553+
2554+ @property
2555+ def msgtypes(self):
2556+ return self.message.values()
2557+
2558+ def unmarshal(self, sock):
2559+ return self.message[sock.get_uint8()].unmarshal(sock)
2560+
2561+ def writer(self, sock):
2562+ protowriter = ADict()
2563+ for mt in self.msgtypes:
2564+ protowriter[mt.name] = mt.writer(sock)
2565+ return protowriter
2566
2567=== added file 'pynetez/Reader.py'
2568--- pynetez/Reader.py 1970-01-01 00:00:00 +0000
2569+++ pynetez/Reader.py 2012-06-15 10:11:52 +0000
2570@@ -0,0 +1,42 @@
2571+#==============================================================================
2572+# Copyright (C) 2011 by Denys Duchier
2573+#
2574+# This program is free software; you can redistribute it and/or modify it under
2575+# the terms of the GNU General Public License as published by the Free Software
2576+# Foundation; either version 2 of the License, or (at your option) any later
2577+# version.
2578+#
2579+# This program is distributed in the hope that it will be useful, but WITHOUT
2580+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2581+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2582+# details.
2583+#
2584+# You should have received a copy of the GNU General Public License along with
2585+# this program; if not, write to the Free Software Foundation, Inc., 51
2586+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2587+#==============================================================================
2588+
2589+from ActiveObjectBase import ActiveObjectBase
2590+from Signal import Signal
2591+
2592+class Reader(ActiveObjectBase):
2593+ """emits a signal for every message read on a socket."""
2594+
2595+ def __init__(self, socket):
2596+ super(Reader, self).__init__()
2597+ self.socket = socket
2598+ self.send = Signal()
2599+
2600+ def do(self):
2601+ while not self.closed:
2602+ try:
2603+ msg = self.read()
2604+ except IOError:
2605+ self.close()
2606+ return
2607+ self.send(msg)
2608+
2609+ # you need to reimplement this method
2610+ # to deserialize a message from the socket
2611+ def read(self):
2612+ raise NotImplementedError()
2613
2614=== added file 'pynetez/Server.py'
2615--- pynetez/Server.py 1970-01-01 00:00:00 +0000
2616+++ pynetez/Server.py 2012-06-15 10:11:52 +0000
2617@@ -0,0 +1,43 @@
2618+#==============================================================================
2619+# Copyright (C) 2011 by Denys Duchier
2620+#
2621+# This program is free software; you can redistribute it and/or modify it under
2622+# the terms of the GNU General Public License as published by the Free Software
2623+# Foundation; either version 2 of the License, or (at your option) any later
2624+# version.
2625+#
2626+# This program is distributed in the hope that it will be useful, but WITHOUT
2627+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2628+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2629+# details.
2630+#
2631+# You should have received a copy of the GNU General Public License along with
2632+# this program; if not, write to the Free Software Foundation, Inc., 51
2633+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2634+#==============================================================================
2635+
2636+from Socket import Socket
2637+
2638+class Server(object):
2639+
2640+ def __init__(self, protocol, sessiontype):
2641+ self._protocol = protocol
2642+ self._sessiontype = sessiontype
2643+
2644+ def run(self, port):
2645+ self._socket = Socket()
2646+ self._socket.socket()
2647+ self._socket.bind(("", port))
2648+ self._socket.listen(10)
2649+ while True:
2650+ sock = self._socket.accept()
2651+ session = self._sessiontype(self._protocol)
2652+ session.pluginto(sock)
2653+ session.start()
2654+
2655+ def run_argv(self):
2656+ from optparse import OptionParser
2657+ parser = OptionParser(usage="usage: %prog [options]")
2658+ parser.add_option("--port","-p",type=int,dest="port",default=9999)
2659+ options, args = parser.parse_args()
2660+ self.run(options.port)
2661
2662=== added file 'pynetez/Session.py'
2663--- pynetez/Session.py 1970-01-01 00:00:00 +0000
2664+++ pynetez/Session.py 2012-06-15 10:11:52 +0000
2665@@ -0,0 +1,222 @@
2666+#==============================================================================
2667+# Copyright (C) 2011 by Denys Duchier
2668+#
2669+# This program is free software; you can redistribute it and/or modify it under
2670+# the terms of the GNU General Public License as published by the Free Software
2671+# Foundation; either version 2 of the License, or (at your option) any later
2672+# version.
2673+#
2674+# This program is distributed in the hope that it will be useful, but WITHOUT
2675+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2676+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2677+# details.
2678+#
2679+# You should have received a copy of the GNU General Public License along with
2680+# this program; if not, write to the Free Software Foundation, Inc., 51
2681+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2682+#==============================================================================
2683+
2684+from Reader import Reader
2685+from Writer import Writer
2686+from Signal import Signal
2687+from socket import SHUT_RD, SHUT_WR, SHUT_RDWR
2688+from threading import Lock
2689+from Queue import Queue
2690+from ActiveObjectBase import ActiveObjectBase
2691+
2692+class SessionReader(Reader):
2693+
2694+ def __init__(self, socket, protocol, react):
2695+ super(SessionReader, self).__init__(socket)
2696+ self.protocol = protocol
2697+ self.send.connect(react)
2698+
2699+ def read(self):
2700+ return self.protocol.unmarshal(self.socket)
2701+
2702+ def close(self):
2703+ super(SessionReader, self).close()
2704+ try:
2705+ self.socket.shutdown(SHUT_RD)
2706+ except:
2707+ pass
2708+
2709+#===============================================================================
2710+
2711+from ADict import ADict
2712+
2713+def message_and_queue(mkfun, qfun):
2714+ def msg(*kargs):
2715+ qfun(mkfun(*kargs))
2716+ return msg
2717+
2718+class SessionWriter(Writer):
2719+
2720+ def __init__(self, socket, protocol):
2721+ super(SessionWriter, self).__init__(socket)
2722+ self.protocol = protocol
2723+ self.protocolwriter = protocol.writer(socket)
2724+ self.message = ADict()
2725+ qfun = self.recv
2726+ for mt in protocol.msgtypes:
2727+ self.message[mt.name] = message_and_queue(mt, qfun)
2728+
2729+ def write(self, msg):
2730+ self.protocolwriter[msg.name](*msg.args)
2731+
2732+ def close(self):
2733+ super(SessionWriter, self).close()
2734+ try:
2735+ self.socket.shutdown(SHUT_WR)
2736+ except:
2737+ pass
2738+
2739+#===============================================================================
2740+
2741+class SessionStarter(ActiveObjectBase):
2742+
2743+ def __init__(self, onstart):
2744+ super(SessionStarter, self).__init__()
2745+ self._onstart = onstart
2746+
2747+ def do(self):
2748+ self._onstart()
2749+
2750+#===============================================================================
2751+# s = Session(sock, proto)
2752+# s.message.send(portsrc=2345,portdst=80,data="hello world")
2753+# s.message.ping(ttl=10)
2754+#===============================================================================
2755+
2756+class Session(object):
2757+
2758+ async = True
2759+
2760+ def __init__(self, protocol):
2761+ self._protocol = protocol
2762+ self._lock = Lock()
2763+ self._reader_done = False
2764+ self._writer_done = False
2765+ self._starter_done = False
2766+ self._finished = False
2767+ self.done = Signal()
2768+ if not self.async:
2769+ self._queue = Queue(-1)
2770+
2771+ daemon = True
2772+
2773+ def pluginto(self, socket):
2774+ if self.async:
2775+ react = self.react
2776+ else:
2777+ react = self._queue.put
2778+ self._reader = SessionReader(socket, self._protocol, react)
2779+ self._writer = SessionWriter(socket, self._protocol)
2780+ self._starter = SessionStarter(self._on_start)
2781+ self._reader.daemon = self.daemon
2782+ self._writer.daemon = self.daemon
2783+ self._starter.daemon = self.daemon
2784+ self.message = self._writer.message
2785+ self.send = self.message
2786+ self._writer.eof.connect(self._reader.close)
2787+ def closing():
2788+ self._writer.recv(None)
2789+ self._reader.eof.connect(closing)
2790+ self._reader.end.connect(self._set_reader_done)
2791+ self._writer.end.connect(self._set_writer_done)
2792+ self._starter.end.connect(self._set_starter_done)
2793+ self.done.connect(socket.close)
2794+ #self._reader.end.connect(self.say_reader_done)
2795+ #self._writer.end.connect(self.say_writer_done)
2796+ #self._starter.end.connect(self.say_starter_done)
2797+ #self.done.connect(self.say_done)
2798+
2799+ #def say_done(self):
2800+ # print "DONE"
2801+
2802+ #def say_reader_done(self):
2803+ # print "READER DONE"
2804+
2805+ #def say_writer_done(self):
2806+ # print "WRITER DONE"
2807+
2808+ #def say_starter_done(self):
2809+ # print "STARTER DONE"
2810+
2811+ def _all_done(self):
2812+ # should only be invoked under self._lock
2813+ return self._reader_done and self._writer_done and self._starter_done
2814+
2815+ def _set_reader_done(self):
2816+ all_done = False
2817+ with self._lock:
2818+ if not self._reader_done:
2819+ self._reader_done = True
2820+ all_done = self._all_done()
2821+ if all_done:
2822+ self.done()
2823+
2824+ def _set_writer_done(self):
2825+ all_done = False
2826+ with self._lock:
2827+ if not self._writer_done:
2828+ self._writer_done = True
2829+ all_done = self._all_done()
2830+ if all_done:
2831+ self.done()
2832+
2833+ def _set_starter_done(self):
2834+ all_done = False
2835+ with self._lock:
2836+ if not self._starter_done:
2837+ self._starter_done = True
2838+ all_done = self._all_done()
2839+ if all_done:
2840+ self.done()
2841+
2842+ def start(self):
2843+ self._reader.start()
2844+ self._writer.start()
2845+ self._starter.start()
2846+
2847+ def _on_start(self):
2848+ self.on_start()
2849+ if not self.async:
2850+ self.finish()
2851+
2852+ def on_start(self):
2853+ pass
2854+
2855+ def finish(self):
2856+ doit = False
2857+ with self._lock:
2858+ if not self._finished:
2859+ self._finished = True
2860+ doit = True
2861+ if doit:
2862+ self._writer.recv(None)
2863+ self._reader.close()
2864+
2865+ def close(self):
2866+ self._reader.close()
2867+ self._writer.recv(None)
2868+ self._writer.close()
2869+
2870+ def wait(self):
2871+ self._starter.join()
2872+ self._reader.join()
2873+ self._writer.join()
2874+
2875+ def react(self, msg):
2876+ doname = "do_%s" % msg.name
2877+ try:
2878+ dofun = getattr(self, doname)
2879+ except AttributeError:
2880+ raise NotImplementedError(doname)
2881+ dofun(*msg.args)
2882+
2883+ def recv(self):
2884+ return self._queue.get()
2885+
2886+ # you must implement all the do_FOO methods for the
2887+ # messages (e.g. FOO) in your protocol
2888
2889=== added file 'pynetez/Signal.py'
2890--- pynetez/Signal.py 1970-01-01 00:00:00 +0000
2891+++ pynetez/Signal.py 2012-06-15 10:11:52 +0000
2892@@ -0,0 +1,54 @@
2893+#==============================================================================
2894+# Copyright (C) 2011 by Denys Duchier
2895+#
2896+# This program is free software; you can redistribute it and/or modify it under
2897+# the terms of the GNU General Public License as published by the Free Software
2898+# Foundation; either version 2 of the License, or (at your option) any later
2899+# version.
2900+#
2901+# This program is distributed in the hope that it will be useful, but WITHOUT
2902+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2903+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2904+# details.
2905+#
2906+# You should have received a copy of the GNU General Public License along with
2907+# this program; if not, write to the Free Software Foundation, Inc., 51
2908+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2909+#==============================================================================
2910+
2911+from threading import RLock
2912+
2913+class Signal(object):
2914+ """a Signal can be connected to slots: whenever the signal is called, all
2915+ the connected slots are invoked with the same arguments as the signal.
2916+ """
2917+
2918+ def __init__(self):
2919+ self._rlock = RLock()
2920+ self._closed = False
2921+ self._slots = ()
2922+
2923+ def __call__(self, *args, **kargs):
2924+ for s in self._slots:
2925+ s(*args, **kargs)
2926+
2927+ def connect(self, slot):
2928+ with self._rlock:
2929+ if not self._closed and \
2930+ slot not in self._slots:
2931+ # update with a new tuple so that ongoing
2932+ # iterations don't get messed up
2933+ self._slots = self._slots + (slot,)
2934+
2935+ def disconnect(self, slot):
2936+ with self._rlock:
2937+ if slot in self._slots:
2938+ l = list(self._slots)
2939+ l.remove(slot)
2940+ self._slots = tuple(l)
2941+
2942+ def close(self):
2943+ with self._rlock:
2944+ if not self._closed:
2945+ self._closed = True
2946+ self._slots = ()
2947
2948=== added file 'pynetez/Socket.py'
2949--- pynetez/Socket.py 1970-01-01 00:00:00 +0000
2950+++ pynetez/Socket.py 2012-06-15 10:11:52 +0000
2951@@ -0,0 +1,324 @@
2952+#==============================================================================
2953+# Copyright (C) 2011 by Denys Duchier
2954+#
2955+# This program is free software; you can redistribute it and/or modify it under
2956+# the terms of the GNU General Public License as published by the Free Software
2957+# Foundation; either version 2 of the License, or (at your option) any later
2958+# version.
2959+#
2960+# This program is distributed in the hope that it will be useful, but WITHOUT
2961+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2962+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2963+# details.
2964+#
2965+# You should have received a copy of the GNU General Public License along with
2966+# this program; if not, write to the Free Software Foundation, Inc., 51
2967+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2968+#==============================================================================
2969+
2970+import socket, struct
2971+from IBuffer import IBuffer
2972+
2973+class Socket(object):
2974+ """socket abstraction with buffering and un/marshaling methods."""
2975+
2976+ BUFSIZE = 4096
2977+
2978+ def __init__(self, sock=None):
2979+ self._socket = sock
2980+ self._buffer = IBuffer(self._refill)
2981+
2982+ def socket(self, dom=socket.AF_INET, typ=socket.SOCK_STREAM):
2983+ sock = socket.socket(dom, typ)
2984+ self._socket = sock
2985+
2986+ def accept(self):
2987+ return Socket(self._socket.accept()[0])
2988+
2989+ def bind(self, addr):
2990+ self._socket.bind(addr)
2991+
2992+ def close(self):
2993+ self._socket.close()
2994+
2995+ def connect(self, addr):
2996+ self._socket.connect(addr)
2997+
2998+ def connect_ex(self, addr):
2999+ return self._socket.connect_ex(addr)
3000+
3001+ def fileno(self):
3002+ return self._socket.fileno()
3003+
3004+ def getpeername(self):
3005+ return self._socket.getpeername()
3006+
3007+ def getsockname(self):
3008+ return self._socket.getsockname()
3009+
3010+ def getsockopt(self, *args, **kw):
3011+ return self._socket.getsockopt(*args, **kw)
3012+
3013+ def ioctl(self, control, option):
3014+ return self._socket.ioctl(control, option)
3015+
3016+ def listen(self, backlog):
3017+ self._socket.listen(backlog)
3018+
3019+ def makefile(self, *args, **kw):
3020+ return self._socket.makefile(*args, **kw)
3021+
3022+ def recv(self, bufsize, flags=0):
3023+ return self._socket.recv(bufsize, flags)
3024+
3025+ def recvfrom(self, bufsize, flags=0):
3026+ return self._socket.recv(bufsize, flags)
3027+
3028+ def recvfrom_into(self, *args, **kw):
3029+ return self._socket.recvfrom_into(*args, **kw)
3030+
3031+ def recv_into(self, *args, **kw):
3032+ return self._socket.recv_into(*args, **kw)
3033+
3034+ def send(self, string, flags=0):
3035+ return self._socket.send(string, flags)
3036+
3037+ def sendall(self, string, flags=0):
3038+ self._socket.sendall(string, flags)
3039+
3040+ def sendto(self, *args, **kw):
3041+ return self._socket.sendto(*args, **kw)
3042+
3043+ def setblocking(self, flag):
3044+ self._socket.setblocking(flag)
3045+
3046+ def settimeout(self, value):
3047+ self._socket.settimeout(value)
3048+
3049+ def gettimeout(self):
3050+ return self._socket.gettimeout()
3051+
3052+ def setsockopt(self, level, optname, value):
3053+ self._socket.setsockopt(level, optname, value)
3054+
3055+ def shutdown(self, how):
3056+ self._socket.shutdown(how)
3057+
3058+ @property
3059+ def family(self):
3060+ return self._socket.family
3061+
3062+ @property
3063+ def type(self):
3064+ return self._socket.type
3065+
3066+ @property
3067+ def proto(self):
3068+ return self._socket.proto
3069+
3070+ def _refill(self):
3071+ return self.recv(self.BUFSIZE)
3072+
3073+ def read(self, n):
3074+ return self._buffer.read(n)
3075+
3076+ def write(self, buf):
3077+ self.sendall(buf)
3078+
3079+ def get_uint8(self):
3080+ return struct.unpack("B", self.read(1))[0]
3081+
3082+ def get_uint16(self):
3083+ return struct.unpack("!H", self.read(2))[0]
3084+
3085+ def get_uint32(self):
3086+ return struct.unpack("!I", self.read(4))[0]
3087+
3088+ get_uint = get_uint32
3089+
3090+ def get_int8(self):
3091+ return struct.unpack("b", self.read(1))[0]
3092+
3093+ def get_int16(self):
3094+ return struct.unpack("!h", self.read(2))[0]
3095+
3096+ def get_int32(self):
3097+ return struct.unpack("!i", self.read(4))[0]
3098+
3099+ get_int = get_int32
3100+
3101+ def put_uint8(self, i):
3102+ self.write(struct.pack("B", i))
3103+
3104+ def put_uint16(self, i):
3105+ self.write(struct.pack("!H", i))
3106+
3107+ def put_uint32(self, i):
3108+ self.write(struct.pack("!I", i))
3109+
3110+ put_uint = put_uint32
3111+
3112+ def put_int8(self, i):
3113+ self.write(struct.pack("b", i))
3114+
3115+ def put_int16(self, i):
3116+ self.write(struct.pack("!h", i))
3117+
3118+ def put_int32(self, i):
3119+ self.write(struct.pack("!i", i))
3120+
3121+ def put_bytes(self, s):
3122+ self.put_uint32(len(s))
3123+ self.write(s)
3124+
3125+ def get_bytes(self):
3126+ n = self.get_uint32()
3127+ return self.read(n)
3128+
3129+
3130+class SocketProxy(object):
3131+ """abstraction for creating objects that delegate to an existing socket."""
3132+
3133+ def __init__(self, sock=None):
3134+ self._socket = sock
3135+
3136+ def socket(self, dom=socket.AF_INET, typ=socket.SOCK_STREAM):
3137+ self._socket.socket(dom, typ)
3138+
3139+ def accept(self):
3140+ return self._socket.accept()
3141+
3142+ def bind(self, addr):
3143+ self._socket.bind(addr)
3144+
3145+ def close(self):
3146+ self._socket.close()
3147+
3148+ def connect(self, addr):
3149+ self._socket.connect(addr)
3150+
3151+ def connect_ex(self, addr):
3152+ return self._socket.connect_ex(addr)
3153+
3154+ def fileno(self):
3155+ return self._socket.fileno()
3156+
3157+ def getpeername(self):
3158+ return self._socket.getpeername()
3159+
3160+ def getsockname(self):
3161+ return self._socket.getsockname()
3162+
3163+ def getsockopt(self, *args, **kw):
3164+ return self._socket.getsockopt(*args, **kw)
3165+
3166+ def ioctl(self, control, option):
3167+ return self._socket.ioctl(control, option)
3168+
3169+ def listen(self, backlog):
3170+ self._socket.listen(backlog)
3171+
3172+ def makefile(self, *args, **kw):
3173+ return self._socket.makefile(*args, **kw)
3174+
3175+ def recv(self, bufsize, flags=0):
3176+ return self._socket.recv(bufsize, flags)
3177+
3178+ def recvfrom(self, bufsize, flags=0):
3179+ return self._socket.recv(bufsize, flags)
3180+
3181+ def recvfrom_into(self, *args, **kw):
3182+ return self._socket.recvfrom_into(*args, **kw)
3183+
3184+ def recv_into(self, *args, **kw):
3185+ return self._socket.recv_into(*args, **kw)
3186+
3187+ def send(self, string, flags=0):
3188+ return self._socket.send(string, flags)
3189+
3190+ def sendall(self, string, flags=0):
3191+ self._socket.sendall(string, flags)
3192+
3193+ def sendto(self, *args, **kw):
3194+ return self._socket.sendto(*args, **kw)
3195+
3196+ def setblocking(self, flag):
3197+ self._socket.setblocking(flag)
3198+
3199+ def settimeout(self, value):
3200+ self._socket.settimeout(value)
3201+
3202+ def gettimeout(self):
3203+ return self._socket.gettimeout()
3204+
3205+ def setsockopt(self, level, optname, value):
3206+ self._socket.setsockopt(level, optname, value)
3207+
3208+ def shutdown(self, how):
3209+ self._socket.shutdown(how)
3210+
3211+ @property
3212+ def family(self):
3213+ return self._socket.family
3214+
3215+ @property
3216+ def type(self):
3217+ return self._socket.type
3218+
3219+ @property
3220+ def proto(self):
3221+ return self._socket.proto
3222+
3223+ def read(self, n):
3224+ return self._socket.read(n)
3225+
3226+ def write(self, buf):
3227+ self._socket.write(buf)
3228+
3229+ def get_uint8(self):
3230+ return self._socket.get_uint8()
3231+
3232+ def get_uint16(self):
3233+ return self._socket.get_uint16()
3234+
3235+ def get_uint32(self):
3236+ return self._socket.get_uint32()
3237+
3238+ get_uint = get_uint32
3239+
3240+ def get_int8(self):
3241+ return self._socket.get_int8()
3242+
3243+ def get_int16(self):
3244+ return self._socket.get_int16()
3245+
3246+ def get_int32(self):
3247+ return self._socket.get_int32()
3248+
3249+ get_int = get_int32
3250+
3251+ def put_uint8(self, i):
3252+ self._socket.put_uint8(i)
3253+
3254+ def put_uint16(self, i):
3255+ self._socket.put_uint16(i)
3256+
3257+ def put_uint32(self, i):
3258+ self._socket.put_uint32(i)
3259+
3260+ put_uint = put_uint32
3261+
3262+ def put_int8(self, i):
3263+ self._socket.put_int8(i)
3264+
3265+ def put_int16(self, i):
3266+ self._socket.put_int16(i)
3267+
3268+ def put_int32(self, i):
3269+ self._socket.put_int32(i)
3270+
3271+ def put_bytes(self, s):
3272+ self._socket.put_bytes(s)
3273+
3274+ def get_bytes(self):
3275+ return self._socket.get_bytes()
3276
3277=== added file 'pynetez/Writer.py'
3278--- pynetez/Writer.py 1970-01-01 00:00:00 +0000
3279+++ pynetez/Writer.py 2012-06-15 10:11:52 +0000
3280@@ -0,0 +1,37 @@
3281+#==============================================================================
3282+# Copyright (C) 2011 by Denys Duchier
3283+#
3284+# This program is free software; you can redistribute it and/or modify it under
3285+# the terms of the GNU General Public License as published by the Free Software
3286+# Foundation; either version 2 of the License, or (at your option) any later
3287+# version.
3288+#
3289+# This program is distributed in the hope that it will be useful, but WITHOUT
3290+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3291+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3292+# details.
3293+#
3294+# You should have received a copy of the GNU General Public License along with
3295+# this program; if not, write to the Free Software Foundation, Inc., 51
3296+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3297+#==============================================================================
3298+
3299+from ActiveObject import ActiveObject
3300+
3301+class Writer(ActiveObject):
3302+ """an active object that serializes to a socket all the messages that it receives."""
3303+
3304+ def __init__(self, socket):
3305+ self.socket = socket
3306+ super(Writer, self).__init__()
3307+
3308+ def react(self, msg):
3309+ try:
3310+ self.write(msg)
3311+ except IOError:
3312+ self.close()
3313+
3314+ # you need to reimplement this method
3315+ # to serialize a message to the socket
3316+ def write(self, msg):
3317+ raise NotImplementedError()
3318
3319=== added file 'pynetez/__init__.py'
3320--- pynetez/__init__.py 1970-01-01 00:00:00 +0000
3321+++ pynetez/__init__.py 2012-06-15 10:11:52 +0000
3322@@ -0,0 +1,17 @@
3323+#==============================================================================
3324+# Copyright (C) 2011 by Denys Duchier
3325+#
3326+# This program is free software; you can redistribute it and/or modify it under
3327+# the terms of the GNU General Public License as published by the Free Software
3328+# Foundation; either version 2 of the License, or (at your option) any later
3329+# version.
3330+#
3331+# This program is distributed in the hope that it will be useful, but WITHOUT
3332+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3333+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3334+# details.
3335+#
3336+# You should have received a copy of the GNU General Public License along with
3337+# this program; if not, write to the Free Software Foundation, Inc., 51
3338+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3339+#==============================================================================
3340
3341=== added file 'server.py'
3342--- server.py 1970-01-01 00:00:00 +0000
3343+++ server.py 2012-06-15 10:11:52 +0000
3344@@ -0,0 +1,227 @@
3345+from proto import proto
3346+from pynetez.Session import Session
3347+from pynetez.Server import Server
3348+from threading import Lock
3349+from pynetez.Agent import Agent
3350+
3351+from pynetez.Protocol import Protocol
3352+masterproto = Protocol()
3353+masterproto.define("play", None, None) # agent, n
3354+
3355+variable = 0
3356+variable2 = 0
3357+
3358+class GameMaster(Agent):
3359+
3360+ def __init__(self, player1, player2):
3361+ super(GameMaster, self).__init__(masterproto)
3362+ self.player1 = player1
3363+ self.player2 = player2
3364+ self.begin.connect(self.connected)
3365+
3366+ def connected(self):
3367+ self.player1.send.connected()
3368+ self.player2.send.connected()
3369+ self.player1.send.countStory()
3370+ self.player2.send.countStory()
3371+ self.player1.send.action(1, 1)
3372+ self.player2.send.action(1, 2)
3373+
3374+ def finish(self):
3375+ super(GameMaster, self).finish()
3376+ self.player1.finish()
3377+ self.player2.finish()
3378+
3379+ def do_play(self, numeroAction, player, n):
3380+ global variable
3381+ global variable2
3382+ if numeroAction == 1:
3383+ if n == 1 or n == 2:
3384+ if variable == 2:
3385+ self.player1.send.entree2()
3386+ self.player2.send.entree2()
3387+ self.player1.send.couloir()
3388+ self.player2.send.couloir()
3389+ variable = 0
3390+ self.player1.send.action(2, 1)
3391+ self.player2.send.action(2, 2)
3392+ elif variable == 1:
3393+ if n == 1:
3394+ if player == 1:
3395+ self.player1.send.entree1()
3396+ else:
3397+ self.player2.send.entree1()
3398+ else:
3399+ if player == 1:
3400+ self.player1.send.fuite()
3401+ self.player1.finish()
3402+ else:
3403+ self.player2.send.fuite()
3404+ self.player2.finish()
3405+ else:
3406+ if player == 1:
3407+ self.player1.send.erreur()
3408+ self.player1.send.action(1, 1)
3409+ else:
3410+ self.player2.send.erreur()
3411+ self.player2.send.action(1, 2)
3412+ elif numeroAction == 2:
3413+ if n == 1 or n == 2:
3414+ if n == 1:
3415+ if player == 1:
3416+ if variable2 == 1:
3417+ self.player1.send.salle2gauche()
3418+ self.player1.send.escalier()
3419+ self.player1.send.action(5, 1)
3420+ else:
3421+ self.player1.send.salleGauche()
3422+ self.player1.send.action(2, 1)
3423+ else:
3424+ if variable2 == 1:
3425+ self.player2.send.salle2gauche()
3426+ self.player2.send.escalier()
3427+ self.player2.send.action(5, 2)
3428+ else:
3429+ self.player2.send.salleGauche()
3430+ self.player2.send.action(2, 2)
3431+ elif n == 2:
3432+ if player == 1:
3433+ self.player1.send.salleDroite()
3434+ self.player1.send.action(3, 1)
3435+ else:
3436+ self.player2.send.salleDroite()
3437+ self.player2.send.action(3, 2)
3438+ else:
3439+ if player == 1:
3440+ self.player1.send.erreur()
3441+ self.player1.send.action(2, 1)
3442+ else:
3443+ self.player2.send.erreur()
3444+ self.player2.send.action(2, 2)
3445+ elif numeroAction == 3:
3446+ if n == 1 or n == 2 or n == 3:
3447+ if player == 1:
3448+ if n == 1:
3449+ self.player1.send.salle1Droite()
3450+ self.player1.send.Gameover()
3451+ self.player1.finish()
3452+ elif n == 2:
3453+ variable2 = 1
3454+ self.player1.send.salle2Droite()
3455+ elif n == 3:
3456+ self.player1.send.salleGauche()
3457+ self.player1.send.action(2, 1)
3458+ elif player == 2:
3459+ if n == 1:
3460+ self.player2.send.salle1Droite()
3461+ self.player2.send.Gameover()
3462+ self.player2.finish()
3463+ elif n == 2:
3464+ variable2 = 1
3465+ self.player2.send.salle2Droite()
3466+ elif n == 3:
3467+ self.player2.send.salleGauche()
3468+ self.player2.send.action(2, 2)
3469+ else:
3470+ if player == 1:
3471+ self.player1.send.erreur()
3472+ self.player1.send.action(3, 1)
3473+ else:
3474+ self.player2.send.erreur()
3475+ self.player2.send.action(3, 2)
3476+ elif numeroAction == 4:
3477+ if n == 1 and n == 2:
3478+ if player == 1:
3479+ if n == 1:
3480+ self.player1.send.salleGauche()
3481+ self.player1.send.action(2, 1)
3482+ else:
3483+ self.player1.send.levierEnfonce()
3484+ else:
3485+ if n == 1:
3486+ self.player2.send.salleGauche()
3487+ self.player2.send.action(2, 1)
3488+ else:
3489+ self.player2.send.levierEnfonce()
3490+ else:
3491+ if player == 1:
3492+ self.player1.send.erreur()
3493+ self.player1.send.action(4, 1)
3494+ else:
3495+ self.player2.send.erreur()
3496+ self.player2.send.action(4, 2)
3497+ elif numeroAction == 5:
3498+ if n == 1 or n == 2:
3499+ if player == 1:
3500+ if n == 1:
3501+ self.player1.send.escalierMonte()
3502+ self.player1.finish()
3503+ self.player2.finish()
3504+ else:
3505+ self.player1.finish()
3506+ self.player2.finish()
3507+ else:
3508+ if n == 1:
3509+ self.player2.send.escalierMonte()
3510+ self.player1.finish()
3511+ self.player2.finish()
3512+ else:
3513+ self.player2.finish()
3514+ self.player1.finish()
3515+ else:
3516+ if player == 1:
3517+ self.player1.send.erreur()
3518+ self.player1.send.action(5, 1)
3519+ else:
3520+ self.player2.send.erreur()
3521+ self.player2.send.action(5, 2)
3522+
3523+ def switch(self):
3524+ self.player1, self.player2 = self.player2, self.player1
3525+
3526+lock = Lock()
3527+waiting = None
3528+
3529+class SessionOnServer(Session):
3530+
3531+ def __init__(self, *args, **kargs):
3532+ super(SessionOnServer, self).__init__(*args, **kargs)
3533+ with lock:
3534+ global waiting
3535+ if waiting is None:
3536+ waiting = self
3537+ self.startmaster = False
3538+ else:
3539+ player1 = waiting
3540+ waiting = None
3541+ player2 = self
3542+ gamemaster = GameMaster(player1, player2)
3543+ player1.master = gamemaster
3544+ player2.master = gamemaster
3545+ self.startmaster = True
3546+
3547+ def on_start(self):
3548+ self.send.pending()
3549+ if self.startmaster:
3550+ self.master.start()
3551+
3552+ def do_take(self, numeroAction, player, n):
3553+ global variable
3554+ if numeroAction == 1 and n == 2:
3555+ variable = 0
3556+ else:
3557+ if numeroAction == 1 and n == 1:
3558+ variable = variable + 1
3559+ if numeroAction == 1:
3560+ self.master.recv.play(numeroAction, player, n)
3561+ elif numeroAction == 2:
3562+ self.master.recv.play(numeroAction, player, n)
3563+ elif numeroAction == 3:
3564+ self.master.recv.play(numeroAction, player, n)
3565+ elif numeroAction == 4:
3566+ self.master.recv.play(numeroAction, player, n)
3567+ elif numeroAction == 5:
3568+ self.master.recv.play(numeroAction, player, n)
3569+
3570+server = Server(proto, SessionOnServer)
3571+server.run_argv()
3572
3573=== renamed file 'server.py' => 'server.py.moved'
3574=== added file 'setup.py'
3575--- setup.py 1970-01-01 00:00:00 +0000
3576+++ setup.py 2012-06-15 10:11:52 +0000
3577@@ -0,0 +1,8 @@
3578+from distutils.core import setup
3579+
3580+setup(name="pynetez",
3581+ description="A Python client/server library",
3582+ author="Denys Duchier",
3583+ author_email="denys.duchier@univ-orleans.fr",
3584+ version="2.1",
3585+ packages=["pynetez"])

Subscribers

People subscribed via source and target branches

to all changes: