annotate rpc.py @ 79:84f96c5fe791

Use different message ID that does not result in "Query UNTERMINATE" messages in the error log. Fix testsrq. Rename queryrsb to querystb as that matches the operating manual.
author Daniel O'Connor <doconnor@gsoft.com.au>
date Fri, 27 Sep 2024 16:53:43 +0930
parents 91b476ebc0f2
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 "A an RPC module, with optimizations for VXI-11 rpc calls"
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2 _rcsid="$Id: rpc.py 323 2011-04-06 19:10:03Z marcus $"
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 #this module is 99% from the python distribution, Demo/rpc/rpc.py, with a few modifications
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 #by Marcus Mendenhall to improve timeout handling, etc. It probably should follow any licensing
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 #intent of whoever originated it.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 # Sun RPC version 2 -- RFC1057.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 # XXX There should be separate exceptions for the various reasons why
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11 # XXX an RPC can fail, rather than using RuntimeError for everything
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 # XXX The UDP version of the protocol resends requests when it does
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14 # XXX not receive a timely reply -- use only for idempotent calls!
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16 # XXX There is no provision for call timeout on TCP connections
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17 # Now there is, on receives. 2003.02.20 Marcus Mendenhall, Vanderbilt University marcus.h.mendenhall@vanderbilt.edu
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19 import xdrlib as xdr
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20 import socket
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21 import os
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22 from exceptions import *
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 RPCVERSION = 2
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 CALL = 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 REPLY = 1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 AUTH_NULL = 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 AUTH_UNIX = 1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 AUTH_SHORT = 2
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 AUTH_DES = 3
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34 MSG_ACCEPTED = 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 MSG_DENIED = 1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 SUCCESS = 0 # RPC executed successfully
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38 PROG_UNAVAIL = 1 # remote hasn't exported program
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 PROG_MISMATCH = 2 # remote can't support version #
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40 PROC_UNAVAIL = 3 # program can't support procedure
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41 GARBAGE_ARGS = 4 # procedure can't decode params
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 RPC_MISMATCH = 0 # RPC version number != 2
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44 AUTH_ERROR = 1 # remote can't authenticate caller
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 AUTH_BADCRED = 1 # bad credentials (seal broken)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47 AUTH_REJECTEDCRED = 2 # client must begin new session
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 AUTH_BADVERF = 3 # bad verifier (seal broken)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 AUTH_REJECTEDVERF = 4 # verifier expired or replayed
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 AUTH_TOOWEAK = 5 # rejected for security reasons
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 class Packer(xdr.Packer):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55 def pack_auth(self, auth):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56 flavor, stuff = auth
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 self.pack_enum(flavor)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58 self.pack_opaque(stuff)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60 def pack_auth_unix(self, stamp, machinename, uid, gid, gids):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61 self.pack_uint(stamp)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 self.pack_string(machinename)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 self.pack_uint(uid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 self.pack_uint(gid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 self.pack_uint(len(gids))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66 for i in gids:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67 self.pack_uint(i)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 def pack_callheader(self, xid, prog, vers, proc, cred, verf):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70 self.pack_uint(xid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 self.pack_enum(CALL)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 self.pack_uint(RPCVERSION)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73 self.pack_uint(prog)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 self.pack_uint(vers)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 self.pack_uint(proc)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76 self.pack_auth(cred)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 self.pack_auth(verf)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78 # Caller must add procedure-specific part of call
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
79
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
80 def pack_replyheader(self, xid, verf):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 self.pack_uint(xid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
82 self.pack_enum(REPLY)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
83 self.pack_uint(MSG_ACCEPTED)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84 self.pack_auth(verf)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85 self.pack_enum(SUCCESS)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 # Caller must add procedure-specific part of reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89 # Exceptions
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 BadRPCFormat = 'rpc.BadRPCFormat'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 BadRPCVersion = 'rpc.BadRPCVersion'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92 GarbageArgs = 'rpc.GarbageArgs'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 class Unpacker(xdr.Unpacker):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96 def unpack_auth(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97 flavor = self.unpack_enum()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 stuff = self.unpack_opaque()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 return (flavor, stuff)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 def unpack_callheader(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102 xid = self.unpack_uint(xid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103 temp = self.unpack_enum()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
104 if temp != CALL:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
105 raise BadRPCFormat('no CALL but ' + repr(temp))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
106 temp = self.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
107 if temp != RPCVERSION:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
108 raise BadRPCVerspion('bad RPC version ' + repr(temp))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109 prog = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110 vers = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 proc = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112 cred = self.unpack_auth()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 verf = self.unpack_auth()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 return xid, prog, vers, proc, cred, verf
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115 # Caller must add procedure-specific part of call
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 def unpack_replyheader(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118 xid = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119 mtype = self.unpack_enum()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
120 if mtype != REPLY:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
121 raise RuntimeError('no REPLY but ' + repr(mtype))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 stat = self.unpack_enum()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 if stat == MSG_DENIED:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 stat = self.unpack_enum()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
125 if stat == RPC_MISMATCH:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
126 low = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 high = self.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
128 raise RuntimeError('MSG_DENIED: RPC_MISMATCH: ' + repr((low, high)))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 if stat == AUTH_ERROR:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 stat = self.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
131 raise RuntimeError('MSG_DENIED: AUTH_ERROR: ' + repr(stat))
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
132 raise RuntimeError('MSG_DENIED: ' + repr(stat))
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
133 if stat != MSG_ACCEPTED:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
134 raise RuntimeError('Neither MSG_DENIED nor MSG_ACCEPTED: ' + repr(stat))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135 verf = self.unpack_auth()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 stat = self.unpack_enum()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137 if stat == PROG_UNAVAIL:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
138 raise RuntimeError('call failed: PROG_UNAVAIL')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139 if stat == PROG_MISMATCH:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 low = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141 high = self.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
142 raise RuntimeError('call failed: PROG_MISMATCH: ' + repr((low, high)))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 if stat == PROC_UNAVAIL:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
144 raise RuntimeError('call failed: PROC_UNAVAIL')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 if stat == GARBAGE_ARGS:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
146 raise RuntimeError('call failed: GARBAGE_ARGS')
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
147 if stat != SUCCESS:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
148 raise RuntimeError('call failed: ' + repr(stat))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149 return xid, verf
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 # Caller must get procedure-specific part of reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153 # Subroutines to create opaque authentication objects
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155 def make_auth_null():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 return ''
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
158 def make_auth_unix(seed, host, uid, gid, groups):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
159 p = Packer()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 p.pack_auth_unix(seed, host, uid, gid, groups)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161 return p.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163 def make_auth_unix_default():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165 from os import getuid, getgid
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 uid = getuid()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 gid = getgid()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168 except ImportError:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 uid = gid = 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170 import time
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171 return make_auth_unix(int(time.time()-unix_epoch()), \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172 socket.gethostname(), uid, gid, [])
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 _unix_epoch = -1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 def unix_epoch():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176 """Very painful calculation of when the Unix Epoch is.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 This is defined as the return value of time.time() on Jan 1st,
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 1970, 00:00:00 GMT.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181 On a Unix system, this should always return 0.0. On a Mac, the
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182 calculations are needed -- and hard because of integer overflow
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 and other limitations.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185 """
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 global _unix_epoch
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 if _unix_epoch >= 0: return _unix_epoch
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188 import time
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
189 now = time.time()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
190 localt = time.localtime(now) # (y, m, d, hh, mm, ss, ..., ..., ...)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 gmt = time.gmtime(now)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192 offset = time.mktime(localt) - time.mktime(gmt)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193 y, m, d, hh, mm, ss = 1970, 1, 1, 0, 0, 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 offset, ss = divmod(ss + offset, 60)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 offset, mm = divmod(mm + offset, 60)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196 offset, hh = divmod(hh + offset, 24)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197 d = d + offset
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 _unix_epoch = time.mktime((y, m, d, hh, mm, ss, 0, 0, 0))
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
199 print("Unix epoch:", time.ctime(_unix_epoch))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200 return _unix_epoch
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 # Common base class for clients
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205 class Client:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207 def __init__(self, host, prog, vers, port):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208 self.host = host
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 self.prog = prog
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210 self.vers = vers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 self.port = port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212 self.makesocket() # Assigns to self.sock
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 self.bindsocket()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214 self.connsocket()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215 self.lastxid = 0 # XXX should be more random?
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216 self.addpackers()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217 self.cred = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 self.verf = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220 def close(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221 self.sock.close()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 # This MUST be overridden
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
225 raise RuntimeError('makesocket not defined')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227 def connsocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 # Override this if you don't want/need a connection
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 self.sock.connect((self.host, self.port))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 def bindsocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232 # Override this to bind to a different port (e.g. reserved)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 self.sock.bind(('', 0))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
235 def addpackers(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
236 # Override this to use derived classes from Packer/Unpacker
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 self.packer = Packer()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238 self.unpacker = Unpacker('')
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240 def make_call(self, proc, args, pack_func, unpack_func):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241 #print "make_call() args = " + str(args)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 # Don't normally override this (but see Broadcast)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 if pack_func is None and args is not None:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
244 raise TypeError('non-null args with null pack_func')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245 #print "packed args"
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
246 self.start_call(proc)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
247 if pack_func:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
248 pack_func(args)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
249 self.do_call()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
250 if unpack_func:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
251 result = unpack_func()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
252 else:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
253 result = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
254 #print "result = " + str(result)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
255 self.unpacker.done()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
256 return result
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
257
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
258 def start_call(self, proc):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
259 # Don't override this
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
260 self.lastxid = xid = self.lastxid + 1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
261 cred = self.mkcred()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
262 verf = self.mkverf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
263 p = self.packer
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
264 p.reset()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
265 p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
266
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
267 def do_call(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
268 # This MUST be overridden
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
269 raise RuntimeError('do_call not defined')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
270
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
271 def mkcred(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
272 # Override this to use more powerful credentials
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
273 if self.cred == None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
274 self.cred = (AUTH_NULL, make_auth_null())
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
275 return self.cred
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
276
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
277 def mkverf(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
278 # Override this to use a more powerful verifier
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
279 if self.verf == None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
280 self.verf = (AUTH_NULL, make_auth_null())
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
281 return self.verf
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
282
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
283 def call_0(self): # Procedure 0 is always like this
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
284 return self.make_call(0, None, None, None)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
285
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
286
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
287 # Record-Marking standard support
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
288
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
289 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
290 from select import select as _select
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
291 except:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
292 _select=None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
293
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
294 def sendfrag_with_timeout(sock, last, frag, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
295 x = len(frag)
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
296 if last: x = x | 0x80000000
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
297 header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
298 chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
299 block=header+frag
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
300 n=len(block)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
301 nsent=0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
302 while(nsent<n):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
303 if _select and timeout_seconds:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
304 rlist, wlist, xlist=_select([],[sock],[], timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
305 if not wlist:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
306 raise EOFError("Blocked write in sendfrag()")
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
307 nsent+=sock.send(block[nsent:])
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
308
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
309 def recvfrag_with_timeout(sock, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
310 #print "receiving from ", sock
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
311 if _select and timeout_seconds:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
312 #print "Selecting with timeout...", timeout_seconds
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
313 rlist, wlist, xlist=_select([sock],[],[], timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
314 if not rlist:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
315 raise EOFError("No header at all in recvfrag()")
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
316
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
317 header = sock.recv(4)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
318 if len(header) < 4:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
319 raise EOFError
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
320 x = int(ord(header[0]))<<24 | ord(header[1])<<16 | \
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
321 ord(header[2])<<8 | ord(header[3])
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
322 last = ((x & 0x80000000) != 0)
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
323 n = int(x & 0x7fffffff)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
324
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
325 frag=''
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
326
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
327 while(len(frag) < n):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
328 if _select and timeout_seconds:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
329 #print "Selecting with timeout...", timeout_seconds
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
330 rlist, wlist, xlist=_select([sock],[],[], timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
331 if not rlist:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
332 raise EOFError("No data after header in recvfrag()")
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
333 frag += sock.recv(n-len(frag))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
334
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
335 return last, frag
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
336
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
337
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
338 def recvrecord(sock, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
339 record = ''
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
340 last = 0
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
341 while not last:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
342 last, frag = recvfrag_with_timeout(sock, timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
343 record = record + frag
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
344 return record
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
345
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
346 def sendrecord(sock, record, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
347 sendfrag_with_timeout(sock, 1, record, timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
348
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
349
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
350
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
351 # Try to bind to a reserved port (must be root)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
352
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
353 last_resv_port_tried = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
354 def bindresvport(sock, host):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
355 global last_resv_port_tried
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
356 FIRST, LAST = 600, 1024 # Range of ports to try
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
357 if last_resv_port_tried == None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
358 import os
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
359 last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST)
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
360 for i in list(range(last_resv_port_tried, LAST)) + \
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
361 list(range(FIRST, last_resv_port_tried)):
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
362 last_resv_port_tried = i
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
363 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
364 sock.bind((host, i))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
365 return last_resv_port_tried
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
366 except socket.error as xxx_todo_changeme:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
367 (errno, msg) = xxx_todo_changeme.args
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
368 if errno != 114:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
369 raise socket.error(errno, msg)
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
370 raise RuntimeError('can\'t assign reserved port')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
371
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
372
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
373 # Client using TCP to a specific port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
374
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
375 class RawTCPClient(Client):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
376
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
377 select_timeout_seconds=None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
378
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
379 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
380 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
381
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
382 def do_call(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
383 call = self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
384 sendrecord(self.sock, call, self.select_timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
385 reply = recvrecord(self.sock, self.select_timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
386 u = self.unpacker
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
387 u.reset(reply)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
388 xid, verf = u.unpack_replyheader()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
389 if xid != self.lastxid:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
390 # Can't really happen since this is TCP...
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
391 raise RuntimeError('wrong xid in reply ' + repr(xid) + \
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
392 ' instead of ' + repr(self.lastxid))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
393
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
394
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
395 # Client using UDP to a specific port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
396
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
397 class RawUDPClient(Client):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
398
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
399 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
400 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
401
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
402 def do_call(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
403 call = self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
404 self.sock.send(call)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
405 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
406 from select import select
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
407 except ImportError:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
408 print('WARNING: select not found, RPC may hang')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
409 select = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
410 BUFSIZE = 8192 # Max UDP buffer size
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
411 timeout = 1
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
412 count = 5
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
413 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
414 r, w, x = [self.sock], [], []
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
415 if select:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
416 r, w, x = select(r, w, x, timeout)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
417 if self.sock not in r:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
418 count = count - 1
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
419 if count < 0: raise RuntimeError('timeout')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
420 if timeout < 25: timeout = timeout *2
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
421 ## print 'RESEND', timeout, count
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
422 self.sock.send(call)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
423 continue
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
424 reply = self.sock.recv(BUFSIZE)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
425 u = self.unpacker
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
426 u.reset(reply)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
427 xid, verf = u.unpack_replyheader()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
428 if xid != self.lastxid:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
429 ## print 'BAD xid'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
430 continue
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
431 break
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
432
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
433
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
434 # Client using UDP broadcast to a specific port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
435
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
436 class RawBroadcastUDPClient(RawUDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
437
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
438 def __init__(self, bcastaddr, prog, vers, port):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
439 RawUDPClient.__init__(self, bcastaddr, prog, vers, port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
440 self.reply_handler = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
441 self.timeout = 30
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
442
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
443 def connsocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
444 # Don't connect -- use sendto
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
445 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
446
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
447 def set_reply_handler(self, reply_handler):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
448 self.reply_handler = reply_handler
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
449
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
450 def set_timeout(self, timeout):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
451 self.timeout = timeout # Use None for infinite timeout
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
452
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
453 def make_call(self, proc, args, pack_func, unpack_func):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
454 if pack_func is None and args is not None:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
455 raise TypeError('non-null args with null pack_func')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
456 self.start_call(proc)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
457 if pack_func:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
458 pack_func(args)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
459 call = self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
460 self.sock.sendto(call, (self.host, self.port))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
461 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
462 from select import select
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
463 except ImportError:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
464 print('WARNING: select not found, broadcast will hang')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
465 select = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
466 BUFSIZE = 8192 # Max UDP buffer size (for reply)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
467 replies = []
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
468 if unpack_func is None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
469 def dummy(): pass
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
470 unpack_func = dummy
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
471 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
472 r, w, x = [self.sock], [], []
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
473 if select:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
474 if self.timeout is None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
475 r, w, x = select(r, w, x)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
476 else:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
477 r, w, x = select(r, w, x, self.timeout)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
478 if self.sock not in r:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
479 break
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
480 reply, fromaddr = self.sock.recvfrom(BUFSIZE)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
481 u = self.unpacker
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
482 u.reset(reply)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
483 xid, verf = u.unpack_replyheader()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
484 if xid != self.lastxid:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
485 ## print 'BAD xid'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
486 continue
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
487 reply = unpack_func()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
488 self.unpacker.done()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
489 replies.append((reply, fromaddr))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
490 if self.reply_handler:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
491 self.reply_handler(reply, fromaddr)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
492 return replies
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
493
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
494
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
495 # Port mapper interface
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
496
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
497 # Program number, version and (fixed!) port number
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
498 PMAP_PROG = 100000
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
499 PMAP_VERS = 2
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
500 PMAP_PORT = 111
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
501
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
502 # Procedure numbers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
503 PMAPPROC_NULL = 0 # (void) -> void
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
504 PMAPPROC_SET = 1 # (mapping) -> bool
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
505 PMAPPROC_UNSET = 2 # (mapping) -> bool
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
506 PMAPPROC_GETPORT = 3 # (mapping) -> unsigned int
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
507 PMAPPROC_DUMP = 4 # (void) -> pmaplist
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
508 PMAPPROC_CALLIT = 5 # (call_args) -> call_result
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
509
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
510 # A mapping is (prog, vers, prot, port) and prot is one of:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
511
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
512 IPPROTO_TCP = 6
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
513 IPPROTO_UDP = 17
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
514
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
515 # A pmaplist is a variable-length list of mappings, as follows:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
516 # either (1, mapping, pmaplist) or (0).
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
517
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
518 # A call_args is (prog, vers, proc, args) where args is opaque;
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
519 # a call_result is (port, res) where res is opaque.
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
520
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
521
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
522 class PortMapperPacker(Packer):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
523
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
524 def pack_mapping(self, mapping):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
525 prog, vers, prot, port = mapping
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
526 self.pack_uint(prog)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
527 self.pack_uint(vers)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
528 self.pack_uint(prot)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
529 self.pack_uint(port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
530
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
531 def pack_pmaplist(self, list):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
532 self.pack_list(list, self.pack_mapping)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
533
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
534 def pack_call_args(self, ca):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
535 prog, vers, proc, args = ca
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
536 self.pack_uint(prog)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
537 self.pack_uint(vers)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
538 self.pack_uint(proc)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
539 self.pack_opaque(args)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
540
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
541
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
542 class PortMapperUnpacker(Unpacker):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
543
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
544 def unpack_mapping(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
545 prog = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
546 vers = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
547 prot = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
548 port = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
549 return prog, vers, prot, port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
550
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
551 def unpack_pmaplist(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
552 return self.unpack_list(self.unpack_mapping)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
553
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
554 def unpack_call_result(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
555 port = self.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
556 res = self.unpack_opaque()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
557 return port, res
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
558
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
559
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
560 class PartialPortMapperClient:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
561
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
562 def addpackers(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
563 self.packer = PortMapperPacker()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
564 self.unpacker = PortMapperUnpacker('')
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
565
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
566 def Set(self, mapping):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
567 return self.make_call(PMAPPROC_SET, mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
568 self.packer.pack_mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
569 self.unpacker.unpack_uint)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
570
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
571 def Unset(self, mapping):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
572 return self.make_call(PMAPPROC_UNSET, mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
573 self.packer.pack_mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
574 self.unpacker.unpack_uint)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
575
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
576 def Getport(self, mapping):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
577 return self.make_call(PMAPPROC_GETPORT, mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
578 self.packer.pack_mapping, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
579 self.unpacker.unpack_uint)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
580
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
581 def Dump(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
582 return self.make_call(PMAPPROC_DUMP, None, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
583 None, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
584 self.unpacker.unpack_pmaplist)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
585
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
586 def Callit(self, ca):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
587 return self.make_call(PMAPPROC_CALLIT, ca, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
588 self.packer.pack_call_args, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
589 self.unpacker.unpack_call_result)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
590
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
591
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
592 class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
593
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
594 def __init__(self, host, port=PMAP_PORT, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
595 RawTCPClient.__init__(self, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
596 host, PMAP_PROG, PMAP_VERS, port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
597 self.select_timeout_seconds=timeout_seconds
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
598
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
599
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
600 class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
601
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
602 def __init__(self, host, port=PMAP_PORT):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
603 RawUDPClient.__init__(self, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
604 host, PMAP_PROG, PMAP_VERS, port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
605
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
606 class BroadcastUDPPortMapperClient(PartialPortMapperClient, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
607 RawBroadcastUDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
608
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
609 def __init__(self, bcastaddr):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
610 RawBroadcastUDPClient.__init__(self, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
611 bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
612
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
613
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
614 # Generic clients that find their server through the Port mapper
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
615
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
616 class TCPClient(RawTCPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
617
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
618 def __init__(self, host, prog, vers, portmap_proxy_host=None, portmap_proxy_port=PMAP_PORT, timeout_seconds=None):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
619
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
620 self.select_timeout_seconds=timeout_seconds
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
621 if portmap_proxy_host is None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
622 portmap_proxy_host=host #use a proxy to get around firewalled portmappers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
623 pmap = TCPPortMapperClient(portmap_proxy_host, portmap_proxy_port,timeout_seconds)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
624 port = pmap.Getport((prog, vers, IPPROTO_TCP, 0))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
625 pmap.close()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
626 if port == 0:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
627 raise RuntimeError('program not registered')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
628 RawTCPClient.__init__(self, host, prog, vers, port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
629
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
630
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
631 class UDPClient(RawUDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
632
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
633 def __init__(self, host, prog, vers, portmap_proxy_host=None, portmap_proxy_port=PMAP_PORT):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
634 if portmap_proxy_host is None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
635 portmap_proxy_host=host #use a proxy to get around firewalled portmappers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
636 pmap = UDPPortMapperClient(portmap_proxy_host, portmap_proxy_port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
637 port = pmap.Getport((prog, vers, IPPROTO_UDP, 0))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
638 pmap.close()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
639 if port == 0:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
640 raise RuntimeError('program not registered')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
641 RawUDPClient.__init__(self, host, prog, vers, port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
642
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
643
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
644 class BroadcastUDPClient(Client):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
645
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
646 def __init__(self, bcastaddr, prog, vers):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
647 self.pmap = BroadcastUDPPortMapperClient(bcastaddr)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
648 self.pmap.set_reply_handler(self.my_reply_handler)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
649 self.prog = prog
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
650 self.vers = vers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
651 self.user_reply_handler = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
652 self.addpackers()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
653
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
654 def close(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
655 self.pmap.close()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
656
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
657 def set_reply_handler(self, reply_handler):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
658 self.user_reply_handler = reply_handler
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
659
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
660 def set_timeout(self, timeout):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
661 self.pmap.set_timeout(timeout)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
662
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
663 def my_reply_handler(self, reply, fromaddr):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
664 port, res = reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
665 self.unpacker.reset(res)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
666 result = self.unpack_func()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
667 self.unpacker.done()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
668 self.replies.append((result, fromaddr))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
669 if self.user_reply_handler is not None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
670 self.user_reply_handler(result, fromaddr)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
671
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
672 def make_call(self, proc, args, pack_func, unpack_func):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
673 self.packer.reset()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
674 if pack_func:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
675 pack_func(args)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
676 if unpack_func is None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
677 def dummy(): pass
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
678 self.unpack_func = dummy
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
679 else:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
680 self.unpack_func = unpack_func
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
681 self.replies = []
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
682 packed_args = self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
683 dummy_replies = self.pmap.Callit( \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
684 (self.prog, self.vers, proc, packed_args))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
685 return self.replies
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
686
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
687
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
688 # Server classes
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
689
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
690 # These are not symmetric to the Client classes
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
691 # XXX No attempt is made to provide authorization hooks yet
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
692
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
693 class Server:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
694
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
695 def __init__(self, host, prog, vers, port):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
696 self.host = host # Should normally be '' for default interface
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
697 self.prog = prog
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
698 self.vers = vers
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
699 self.port = port # Should normally be 0 for random port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
700 self.makesocket() # Assigns to self.sock and self.prot
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
701 self.bindsocket()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
702 self.host, self.port = self.sock.getsockname()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
703 self.addpackers()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
704
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
705 def handle(self, call):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
706 # Don't use unpack_header but parse the header piecewise
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
707 # XXX I have no idea if I am using the right error responses!
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
708 self.unpacker.reset(call)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
709 self.packer.reset()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
710 xid = self.unpacker.unpack_uint()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
711 self.packer.pack_uint(xid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
712 temp = self.unpacker.unpack_enum()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
713 if temp != CALL:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
714 return None # Not worthy of a reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
715 self.packer.pack_uint(REPLY)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
716 temp = self.unpacker.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
717 if temp != RPCVERSION:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
718 self.packer.pack_uint(MSG_DENIED)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
719 self.packer.pack_uint(RPC_MISMATCH)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
720 self.packer.pack_uint(RPCVERSION)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
721 self.packer.pack_uint(RPCVERSION)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
722 return self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
723 self.packer.pack_uint(MSG_ACCEPTED)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
724 self.packer.pack_auth((AUTH_NULL, make_auth_null()))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
725 prog = self.unpacker.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
726 if prog != self.prog:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
727 self.packer.pack_uint(PROG_UNAVAIL)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
728 return self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
729 vers = self.unpacker.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
730 if vers != self.vers:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
731 self.packer.pack_uint(PROG_MISMATCH)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
732 self.packer.pack_uint(self.vers)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
733 self.packer.pack_uint(self.vers)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
734 return self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
735 proc = self.unpacker.unpack_uint()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
736 methname = 'handle_' + repr(proc)
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
737 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
738 meth = getattr(self, methname)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
739 except AttributeError:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
740 self.packer.pack_uint(PROC_UNAVAIL)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
741 return self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
742 cred = self.unpacker.unpack_auth()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
743 verf = self.unpacker.unpack_auth()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
744 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
745 meth() # Unpack args, call turn_around(), pack reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
746 except (EOFError, GarbageArgs):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
747 # Too few or too many arguments
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
748 self.packer.reset()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
749 self.packer.pack_uint(xid)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
750 self.packer.pack_uint(REPLY)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
751 self.packer.pack_uint(MSG_ACCEPTED)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
752 self.packer.pack_auth((AUTH_NULL, make_auth_null()))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
753 self.packer.pack_uint(GARBAGE_ARGS)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
754 return self.packer.get_buf()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
755
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
756 def turn_around(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
757 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
758 self.unpacker.done()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
759 except RuntimeError:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
760 raise GarbageArgs
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
761 self.packer.pack_uint(SUCCESS)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
762
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
763 def handle_0(self): # Handle NULL message
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
764 self.turn_around()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
765
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
766 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
767 # This MUST be overridden
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
768 raise RuntimeError('makesocket not defined')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
769
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
770 def bindsocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
771 # Override this to bind to a different port (e.g. reserved)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
772 self.sock.bind((self.host, self.port))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
773
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
774 def addpackers(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
775 # Override this to use derived classes from Packer/Unpacker
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
776 self.packer = Packer()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
777 self.unpacker = Unpacker('')
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
778
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
779
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
780 class TCPServer(Server):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
781
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
782 def register(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
783 mapping = self.prog, self.vers, self.prot, self.port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
784 p = TCPPortMapperClient(self.host)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
785 if not p.Set(mapping):
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
786 raise RuntimeError('register failed')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
787
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
788 def unregister(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
789 mapping = self.prog, self.vers, self.prot, self.port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
790 p = TCPPortMapperClient(self.host)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
791 if not p.Unset(mapping):
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
792 raise RuntimeError('unregister failed')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
793
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
794 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
795 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
796 self.prot = IPPROTO_TCP
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
797
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
798 def loop(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
799 self.sock.listen(0)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
800 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
801 self.session(self.sock.accept())
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
802
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
803 def session(self, connection):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
804 sock, (host, port) = connection
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
805 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
806 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
807 call = recvrecord(sock)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
808 except EOFError:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
809 break
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
810 except socket.error as msg:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
811 print('socket error:', msg)
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
812 break
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
813 reply = self.handle(call)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
814 if reply is not None:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
815 sendrecord(sock, reply)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
816
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
817 def forkingloop(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
818 # Like loop but uses forksession()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
819 self.sock.listen(0)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
820 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
821 self.forksession(self.sock.accept())
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
822
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
823 def forksession(self, connection):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
824 # Like session but forks off a subprocess
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
825 import os
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
826 # Wait for deceased children
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
827 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
828 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
829 pid, sts = os.waitpid(0, 1)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
830 except os.error:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
831 pass
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
832 pid = None
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
833 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
834 pid = os.fork()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
835 if pid: # Parent
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
836 connection[0].close()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
837 return
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
838 # Child
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
839 self.session(connection)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
840 finally:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
841 # Make sure we don't fall through in the parent
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
842 if pid == 0:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
843 os._exit(0)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
844
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
845
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
846 class UDPServer(Server):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
847
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
848 def register(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
849 mapping = self.prog, self.vers, self.prot, self.port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
850 p = UDPPortMapperClient(self.host)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
851 if not p.Set(mapping):
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
852 raise RuntimeError('register failed')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
853
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
854 def unregister(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
855 mapping = self.prog, self.vers, self.prot, self.port
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
856 p = UDPPortMapperClient(self.host)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
857 if not p.Unset(mapping):
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
858 raise RuntimeError('unregister failed')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
859
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
860 def makesocket(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
861 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
862 self.prot = IPPROTO_UDP
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
863
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
864 def loop(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
865 while 1:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
866 self.session()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
867
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
868 def session(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
869 call, host_port = self.sock.recvfrom(8192)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
870 reply = self.handle(call)
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
871 if reply != None:
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
872 self.sock.sendto(reply, host_port)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
873
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
874
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
875 # Simple test program -- dump local portmapper status
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
876
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
877 def test():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
878 pmap = UDPPortMapperClient('')
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
879 list = pmap.Dump()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
880 list.sort()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
881 for prog, vers, prot, port in list:
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
882 print(prog, vers, end=' ')
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
883 if prot == IPPROTO_TCP: print('tcp', end=' ')
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
884 elif prot == IPPROTO_UDP: print('udp', end=' ')
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
885 else: print(prot, end=' ')
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
886 print(port)
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
887
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
888
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
889 # Test program for broadcast operation -- dump everybody's portmapper status
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
890
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
891 def testbcast():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
892 import sys
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
893 if sys.argv[1:]:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
894 bcastaddr = sys.argv[1]
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
895 else:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
896 bcastaddr = '<broadcast>'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
897 def rh(reply, fromaddr):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
898 host, port = fromaddr
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
899 print(host + '\t' + repr(reply))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
900 pmap = BroadcastUDPPortMapperClient(bcastaddr)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
901 pmap.set_reply_handler(rh)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
902 pmap.set_timeout(5)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
903 replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0))
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
904
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
905
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
906 # Test program for server, with corresponding client
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
907 # On machine A: python -c 'import rpc; rpc.testsvr()'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
908 # On machine B: python -c 'import rpc; rpc.testclt()' A
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
909 # (A may be == B)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
910
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
911 def testsvr():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
912 # Simple test class -- proc 1 doubles its string argument as reply
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
913 class S(UDPServer):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
914 def handle_1(self):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
915 arg = self.unpacker.unpack_string()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
916 self.turn_around()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
917 print('RPC function 1 called, arg', repr(arg))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
918 self.packer.pack_string(arg + arg)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
919 #
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
920 s = S('', 0x20000000, 1, 0)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
921 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
922 s.unregister()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
923 except RuntimeError as msg:
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
924 print('RuntimeError:', msg, '(ignored)')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
925 s.register()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
926 print('Service started...')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
927 try:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
928 s.loop()
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
929 finally:
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
930 s.unregister()
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
931 print('Service interrupted.')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
932
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
933
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
934 def testclt():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
935 import sys
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
936 if sys.argv[1:]: host = sys.argv[1]
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
937 else: host = ''
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
938 # Client for above server
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
939 class C(UDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
940 def call_1(self, arg):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
941 return self.make_call(1, arg, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
942 self.packer.pack_string, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
943 self.unpacker.unpack_string)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
944 c = C(host, 0x20000000, 1)
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
945 print('making call...')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
946 reply = c.call_1('hello, world, ')
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
947 print('call returned', repr(reply))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
948
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
949 def testclt2():
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
950 import sys
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
951 host = '127.0.0.1'
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
952 # Client for above server
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
953 class C(UDPClient):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
954 def call_1(self, arg):
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
955 return self.make_call(1, arg, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
956 self.packer.pack_string, \
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
957 self.unpacker.unpack_string)
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
958 c = C(host, 0x20000000, 1)
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
959 print('making call...')
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
960 reply = c.call_1('hello, world, ')
56
91b476ebc0f2 Run through 2to3
Daniel O'Connor <doconnor@gsoft.com.au>
parents: 19
diff changeset
961 print('call returned', repr(reply))
19
cba1c44060f5 Copied from
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
962