6 from .common
import encodeToBytes
,zero32
8 from dataclasses
import dataclass
11 class PxpRequest(object):
12 context
:'ServerContext'=None
17 parameter
:typing
.Any
=None
18 result
:typing
.Any
=None
19 callable:'PxpCallable'=None
23 async def readParameter(self
,req
:PxpRequest
):
26 async def call(self
,req
:PxpRequest
):
29 async def writeResult(self
,req
:PxpRequest
):
34 log1
=logging
.getLogger(__name__
)
36 class ServerContext(object):
39 self
.refSlots
:typing
.Dict
[int,typing
.Any
]=dict()
40 self
.writeLock
=asyncio
.locks
.Lock()
44 def backend1(self
,r
:asyncio
.StreamReader
,w
:asyncio
.StreamWriter
):
48 async def handle(self
):
51 session
=await self
.in2
.readexactly(4)
52 log1
.debug('get session:%s',session
)
56 req
.destAddr
,size
=struct
.unpack('<II',await self
.in2
.read(8))
57 req
.parameter
=await self
.in2
.read(size
)
58 self
.refSlots
[req
.destAddr
]=req
.parameter
59 log1
.debug('server get request:%s',req
)
60 await self
.writeLock
.acquire()
62 self
.out2
.write(session
)
64 self
.writeLock
.release()
68 req
.srcAddr
=struct
.unpack('<I',await self
.in2
.read(4))[0]
69 data
=self
.refSlots
.get(req
.srcAddr
,None)
70 log1
.debug('server get request:%s',req
)
71 await self
.writeLock
.acquire()
73 self
.out2
.write(session
)
74 if isinstance(data
,(bytes
,bytearray
)):
75 self
.out2
.write(struct
.pack('<I',len(data
)))
77 elif isinstance(data
,str):
78 data
=data
.encode('utf-8')
79 self
.out2
.write(struct
.pack('<I',len(data
)))
82 self
.out2
.write(bytes
.fromhex('FFFFFFFF'))
84 self
.writeLock
.release()
88 req
.destAddr
,req
.srcAddr
=struct
.unpack('<II',await self
.in2
.read(8))
89 self
.refSlots
[req
.destAddr
]=self
.refSlots
.get(req
.srcAddr
,None)
90 log1
.debug('server get request:%s',req
)
91 await self
.writeLock
.acquire()
93 self
.out2
.write(session
)
95 self
.writeLock
.release()
99 req
.destAddr
=struct
.unpack('<I',await self
.in2
.read(4))[0]
100 del self
.refSlots
[req
.destAddr
]
101 log1
.debug('server get request:%s',req
)
102 await self
.writeLock
.acquire()
104 self
.out2
.write(session
)
106 self
.writeLock
.release()
112 req
.destAddr
,req
.funcAddr
=struct
.unpack('<II',await self
.in2
.read(8))
113 t1
:PxpCallable
=self
.refSlots
.get(req
.funcAddr
,None)
115 await t1
.readParameter(req
)
116 log1
.debug('server get request:%s',req
)
117 asyncio
.create_task(self
.__callRoutine
(req
))
122 req
.destAddr
,req
.srcAddr
=struct
.unpack('<II',await self
.in2
.read(8))
123 funcName
=self
.refSlots
.get(req
.srcAddr
,None)
124 if type(funcName
)==bytes
or type(funcName
)==bytearray
:
125 funcName
=funcName
.decode('utf-8')
126 self
.refSlots
[req
.destAddr
]=PyCallableWrap(self
.funcMap
.get(funcName
,None))
127 log1
.debug('server get request:%s',req
)
128 await self
.writeLock
.acquire()
130 self
.out2
.write(session
)
132 self
.writeLock
.release()
134 for t1
,t2
in self
.refSlots
:
135 del self
.refSlots
[t1
]
139 log1
.debug('server get request:getInfo')
140 await self
.writeLock
.acquire()
142 self
.out2
.write(session
)
143 info1
=('server name:pxprpc for python3\n'+
145 'reference slots size:256\n').encode('utf-8')+bytes([0])
146 self
.out2
.write(struct
.pack('<i',len(info1
)))
147 self
.out2
.write(info1
)
149 self
.writeLock
.release()
152 for t1
,t2
in self
.refSlots
:
153 del self
.refSlots
[t1
]
157 async def __callRoutine(self
,req
:PxpRequest
):
158 result
=await req
.callable.call(req
)
160 self
.refSlots
[req
.destAddr
]=result
161 await self
.writeLock
.acquire()
163 self
.out2
.write(req
.session
)
164 await req
.callable.writeResult(req
)
166 self
.writeLock
.release()
171 class PyCallableWrap(PxpCallable
):
173 def __init__(self
,c
:typing
.Callable
):
174 self
._argsInfo
:inspect
.FullArgSpec
=inspect
.getfullargspec(c
)
177 if 'return' in self
._argsInfo
.annotations
:
178 self
.retType
=self
._argsInfo
.annotations
['return']
180 self
.retType
=type(None)
182 if hasattr(self
._argsInfo
,'args'):
183 for argName
in self
._argsInfo
.args
:
184 self
.argsType
.append(self
._argsInfo
.annotations
[argName
])
187 async def readParameter(self
,req
:PxpRequest
):
189 for t1
in self
.argsType
:
191 req
.parameter
.append(
192 struct
.unpack('<q',await req
.context
.in2
.read(8)))[0]
194 req
.parameter
.append(
195 struct
.unpack('<d',await req
.context
.in2
.read(8)))[0]
197 req
.parameter
.append(
198 bool(struct
.unpack('<I',await req
.context
.in2
.read(4))))[0]
200 t1
=struct
.unpack('<i',await req
.context
.in2
.read(4))[0]
201 t2
=req
.context
.refSlots
[t1
]
202 req
.parameter
.append(t2
)
204 async def call(self
,req
:PxpRequest
):
205 return await self
.callable(*req
.parameter
)
207 async def writeResult(self
,req
:PxpRequest
):
210 req
.context
.out2
.write(struct
.pack('<q',req
.result
))
212 req
.context
.out2
.write(struct
.pack('<d',req
.result
))
214 req
.context
.out2
.write(struct
.pack('<I',req
.result
))
215 elif req
.result
==None:
216 req
.context
.out2
.write(struct
.pack('<I',0))
218 req
.context
.out2
.write(struct
.pack('<I',req
.destAddr
))