File: proxy.doc

package info (click to toggle)
slashem 0.0.7E7F3-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 23,552 kB
  • ctags: 22,410
  • sloc: ansic: 263,188; cpp: 7,180; yacc: 2,154; sh: 738; lex: 440; makefile: 154; awk: 97; sed: 11
file content (326 lines) | stat: -rw-r--r-- 13,365 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
Introduction

This file documents the proxy windowing interface. It is far from complete.

Contents:
	I.    An overview of the components
	II.   Adding a standard procedure
	III.  Adding a standard callback
	IV.   Adding an extension

I.   An overview of the components

The proxy window interface is made up of a number of components. This is
because it is intended to be used both as a standard window interface to
be linked with the game executable and as a library that can be linked
with an external window port to handle the communication with the game.
The modules can be broken down into the following types:

A.  Common modules used in both processes (proxycom)
B.  The proxy window interface (winproxy)
C.  Utility modules used in the game executable (proxyutl)
D.  Client modules used only by the external process (proxyclnt)

The main game executable is built with the winproxy, proxyutl and proxycom
modules; external interfaces are built with the nhproxy library which
consists of the proxyclnt and proxycom modules.

When building a window interface as an external port, the proxyutl modules
are just a special case of the winproxy modules. However, if a window
interface is designed to be built as either an external port or as an
internal window interface then the code can normally be simplified by
using the proxyutl modules in the internal window interface.

The proxy window interface has a number of include files which are used
as follows:

A.  Common include files:

nhxdr.h
proxycom.h

B.  Proxy window interface include files:

winproxy.h

C.  External process include files:

proxyclnt.h
proxycb.h

II.  Adding a standard procedure

First choose a name for the new procedure. We will use ${name} to refer to
the lowercase version of the chosen name in this document and ${NAME} to
refer to the uppercase version.

Modify the source as follows:

A.  win/proxy/ext_protocol.html

 o Add a new procedure ID to the list using the next unused ID number.
 o Add a new section describing the procedure, its parameters and result.
 o Bump the version of the protocol, NhExt, if necessary.
 o Note the formal description of parameters and results must follow
   the syntax of Sun's XDR language so that the test procedure laid
   out in win/proxy/Makefile.* will be valid. Formal descriptions must
   be enclosed in a <pre>...</pre> pair. These html tags must be on a
   line by themselves.
 o If you have access to rpcgen then you can use the relevant makefile
   to build rpcgen-nhext_xdr.c and so check your syntax.

B.  include/prxyclnt.h

 o Add a new field to the end of struct window_ext_procs to hold a pointer
   to a function which takes the relevant parameters and returns the
   relevant result. The field should be named winext_${name}.

C.  include/proxycom.h

 o Add a new procedure ID to the list using the ID chosen above:
	#define EXT_FID_${NAME}		0x##
 o If any of the parameters or return value are too complex for nhext_rpc()
   then define a struct proxy_${name}_req and/or proxy_${name}_res
   and declare an XDR function to handle it (enclose the additions
   inside an #ifdef NHXDR_H ... #endif pair).
 o If you changed the NhExt protocol version above, then update the
   values here to match.

D.  win/proxy/compxdr.c

If you declared an XDR function in winproxy.h, then you need to define
it in this file. Many XDR functions consist simply of calling standard
XDR functions for each field of the aggregate type and returning the
bitwise AND of their return values. XDR functions should not return
early if an error occurs so the use of logical AND operators is
generally to be avoided.

E.  win/proxy/winproxy.c

Define the proxy_${name} function you declared above. This function will
be called by the game when it wants to perform the relevant procedure.
It should:

 o Do any preparation needed on the parameters (normally none).
 o Initialize any buffers that will be used to receive values back from
   the windowing interface. The XDR convention is that NULL pointers
   indicate that XDR should allocate memory whereas non-NULL pointers
   indicate that XDR should use the pre-allocated memory.
 o Call nhext_rpc() to send an RPC packet to the windowing interface and
   read back the reply.
 o Return the result (if any).

F.  win/proxy/proxysvc.c

This module implements the support in the windowing interface(s) for the
procedure. You should:

 o Declare a static function to handle the incoming request as follows:
	static void FDECL(proxy_svc_${name}, \
				(unsigned short, NhExtXdr *, NhExtXdr *));
 o Define the handling function. It should:
   - Decode the incoming parameters by calling nhext_rpc_params() and
     passing it the request XDR handle and parameters which describe the
     format of the parameters to your procedure.
   - Take whatever action the game is requesting.
   - Encode the result of that action ready to be sent back to the game
     by calling nhext_rpc_params() and passing it the reply XDR handler
     and parameters which describe the format of the results of your
     procedure.  Note: If this procedure has no result then you must
     still return an empty result to the game.
 o Add an entry to the services array as follows:
	EXT_FID_${NAME},		proxy_svc_${name},
 o If this is an asynchronous procedure (this is, if it returns no results
   and there is no need for the remote end to wait for the procedure to
   complete) then add an entry for the procedure in the async_procedures[]
   array. If there are already asynchronous procedures with IDs in the
   same range (1-32, 33-64, ...) then just add the bit corresponding to
   the new procedure to the mask for that range. If this is the first
   asynchronous procedure in the range then add a new mask as follows:
	1 << EXT_FID_$(NAME) - EXT_FID_$(BASE_NAME),
   where $(BASE_NAME) is the name of the first procedure in the range
   (whether asynchronous or not).

G.  external window interface(s)

Add an entry to the window_ext_procs structure for each external window
interface for the newly defined winext_${name} field. This should either
be a hook function that does nothing except return an appropriate result
(for window interfaces that do not wish to support the new procedure) or
a function to do the work for the new procedure as newly documented in
ext_protocol.html.

H.  game source

Add code to call proxy_${name} at the appropriate points in the game source.

III.  Adding a standard callback

First choose a name for the new callback. We will use ${name} to refer to
the lowercase version of the chosen name in this document and ${NAME} to
refer to the uppercase version.

Modify the source as follows:

A.  win/proxy/ext_protocol.html

 o Add a new callback ID to the list using the next unused ID number.
 o Add a new section describing the callback, its parameters and result.
 o Bump the version of the protocol, NhExt, if necessary.
 o Note the formal description of parameters and results must follow
   the syntax of Sun's XDR language so that the test procedure laid
   out in win/proxy/Makefile.* will be valid. Formal descriptions must
   be enclosed in a <pre>...</pre> pair. These html tags must be on a
   line by themselves.
 o If you have access to rpcgen then you can use the relevant makefile
   to build rpcgen-nhext_xdr.c and so check your syntax.

B.  include/proxycb.h

 o Declare proxy_cb_${name} as a function which takes the relevant
   parameters and returns the relevant result.

C.  include/proxycom.h

 o Add a new callback ID to the list using the ID chosen above:
	#define EXT_CID_${NAME}		0x##
 o If any of the parameters or return value are too complex for nhext_rpc()
   then define a struct proxycb_${name}_req and/or proxycb_${name}_res
   and declare an XDR function to handle it (enclose the additions
   inside an #ifdef NHXDR_H ... #endif pair).
 o If you changed the NhExt protocol version above, then update the
   values here to match.

D.  win/proxy/compxdr.c

If you declared an XDR function in proxycb.h, then you need to define
it in this file. Many XDR functions consist simply of calling standard
XDR functions for each field of the aggregate type and returning the
bitwise AND of their return values. XDR functions should not return
early if an error occurs so the use of logical AND operators is
generally to be avoided.

E.  win/proxy/proxycb.c

Define the proxy_cb_${name} function you declared above. This
function will be called by windowing interfaces when they want
to perform the relevant callback. It should:

 o Do any preparation needed on the parameters (normally none).
 o Initialize any buffers that will be used to receive values back
   from the game. The XDR convention is that NULL pointers indicate
   that XDR should allocate memory whereas non-NULL pointers indicate
   that XDR should use the pre-allocated memory.
 o Call nhext_rpc() to send an RPC packet to the game and read back
   the reply.
 o Return the result (if any).

F.  win/proxy/callback.c

This module implements the support in the game executable for the
call back. You should:

 o Declare a static function to handle the incoming request as follows:
	static void FDECL(callback_${name}, \
				(unsigned short, NhExtXdr *, NhExtXdr *));
 o Define the handling function. It should:
   - Decode the incoming parameters by calling nhext_rpc_params() and
     passing it the request XDR handle and parameters which describe the
     format of the parameters to your call back.
   - Take whatever action the calling windowing interface is requesting.
   - Encode the result of that action ready to be sent back to the
     windowing port by calling nhext_rpc_params() and passing it the
     reply XDR handler and parameters which describe the format of the
     results of your call back. Note: If this call back has no result
     then you must still return an empty result to the windowing port.
 o Add an entry to the proxy_callbacks array as follows:
	EXT_CID_${NAME},		callback_${name},

G.  win/proxy/winproxy.c

If this is an asynchronous callback (this is, if it returns no results
and there is no need for the remote end to wait for the callback to
complete) then add an entry for the callback in the async_callbacks[]
array. If there are already asynchronous callbacks with IDs in the
same range (1-32, 33-64, ...) then just add the bit corresponding to
the new callback to the mask for that range. If this is the first
asynchronous callback in the range then add a new mask as follows:
	1 << EXT_CID_$(NAME) - EXT_CID_$(BASE_NAME),
where $(BASE_NAME) is the name of the first callback in the range
(whether asynchronous or not).

H.  external window interface(s)

Add code to call proxy_cb_${name} to the external window interfaces which
need the new callback.

IV.  Adding an extension

Extensions are used to allow callbacks not detailed in the NhExt standard
to be provided by a game server and queried for by the client. Extensions
have names, version numbers and a set of callbacks. It is assumed that
by one means or another the name and version number is sufficient for the
client and server to agree on the meaning of each callback along with the
details of the various request and reply packets (the extension system
provides no means of querying these details).

First choose a name for the new extension. We will use ${name} to refer to
the chosen name in this document.

Modify the source as follows:

A.  server

Add code in some appropriate module (or create a new module) to handle the
extension. This code should include an initialization routine and a handler.
The initialization routine is called by proxy_init() during the initialization
of the proxy interface. It is passed one parameter - the base ID chosen for the
extension (this may vary as extensions are added or removed). The handler will
be called to handle a callback. It is passed the ID of the callback and pointers
to the request and reply packets. The following is an example of a trivial
extension with just one callback which takes one integer value and returns 
value + 1:

	static unsigned short xyzzy_base_id;

	void
	xyzzy_init(base_id)
	unsigned short base_id;
	{
	    xyzzy_base_id = base_id;
	}

	void
	xyzzy_handler(id, request, reply)
	unsigned short id;
	NhExtXdr *request, *reply;
	{
	    int i;
	    switch (id - xyzzy_base_id)
	    {
		case 0:
		    nhext_rpc_params(request, 1, EXT_INT_P(i));
		    i++;
		    nhext_rpc_params(reply, 1, EXT_INT(i));
		    break;
		default:
		    impossible("xyzzy_handler: Bad ID %u (base %u)",
		      id, xyzzy_base_id);
		    nhext_rpc_params(reply, 0);
	    }
	}

B.  win/proxy/winproxy.c

 o Declare the initialization and handler functions you defined above before
   the definition of proxy_extents[], as follows:
	extern void FDECL(${name}_init, (unsigned short));
	extern void FDECL(${name}_handler,
		(unsigned short, NhExtXdr *, NhExtXdr *));
 o Add an entry to proxy_extents[] as follows:
	{ "${name}", "1.0", ${name}_init, 2, ${name}_handler },
    - Replace 1.0 with the version number. If you need to support more than
      one version of an extension then you must supply seperate initialization
      functions although they can share the same handler function if desired.
      The prefered interface should be listed first.
    - Replace 2 with the number of callbacks included in this extension.