]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/RMxCommon.h
mDNSResponder-66.3.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / RMxCommon.h
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: RMxCommon.h,v $
28 Revision 1.1 2004/01/30 02:35:13 bradley
29 Rendezvous Message Exchange implementation for DNS-SD IPC on Windows.
30
31 */
32
33 //---------------------------------------------------------------------------------------------------------------------------
34 /*! @header RMxCommon.h
35
36 @abstract Common code between the RMxClient and RMxServer.
37
38 @discussion
39
40 This handles establishing and accepting connections, the underying message sending and receiving, portable data
41 packing an unpacking, and shared utility routines.
42 */
43
44 #ifndef __RMx_COMMON__
45 #define __RMx_COMMON__
46
47 #include "CommonServices.h"
48 #include "DebugServices.h"
49
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53
54 #if 0
55 #pragma mark == Documentation ==
56 #endif
57
58 //---------------------------------------------------------------------------------------------------------------------------
59 /*! @header RMxCommon
60
61 @abstract Rendezvous Message Exchange (RMx) protocol.
62
63 @discussion
64
65 Data Type Notes
66 ===============
67
68 All multi-byte data types are transmitted in network byte order (i.e. big endian).
69
70 Data types requiring the use of specific values (e.g. opcodes) are typedef'd to an abstract type. Data types used
71 in this manner can be easily searched to determine the appropriate values for the data type. Modern development
72 environments can jump directly to a type and therefore the appropriate constants, which speeds up development.
73
74 Naming Conventions
75 ==================
76
77 All data types and related constants are named to make it easy to associate them. The general scheme is:
78
79 Data Types: RMx<type>
80
81 <type> Describes the data type (e.g. "OpCode" is used for operation codes).
82
83 For example: RMxOpCode
84
85 Constants: kRMx<type><name>
86
87 <type> Describes the data type (e.g. "OpCode" is used for operation codes in RMx messages).
88 <name> Symbolic name for the constant (e.g. "Browse" for browse messages).
89
90 For example: kRMxOpCodeBrowse
91
92 These conventions make it easier for users to associate data types with their values and to find places where
93 these data types and constants are used. You can always search for the base portion of symbolic name (e.g.
94 "RMxOpCode" in kRMxOpCodeBrowse) and find all the data types and constants associated with it. Modern
95 development environments also allow you to jump directly to the data type or constant.
96
97 Packet Format
98 =============
99
100 All data exchanged between client and server is encapsulated in packets of a specific format. There is a
101 generic header followed by an optional, opcode-specific data section:
102
103 1 2 3
104 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
105 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 | signature (RMx1) |
107 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 | opcode |
109 8 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 | flags |
111 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 | xid |
113 16 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 | status |
115 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 | size |
117 24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 | data ("size" octets) |
119 \ \
120 \ \
121 | |
122 n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123
124 The packet format uses implicit typing, which means the sender and receiver must know the types and ordering of the
125 data based on the opcode of the message. There are standard primitive data types defined that all data structures
126 are built on:
127
128 Byte - 8-bit value. Uses the "b" pack/unpack format specifier.
129 Half-Word - 16-bit value. Uses the "h" pack/unpack format specifier.
130 Word - 32-bit value. Uses the "w" pack/unpack format specifier.
131 String - UTF-8 string, null-terminated. Uses the "s" pack/unpack format specifier.
132 Raw Bytes - 32-bit length-prefixed block of data. Uses the "n" pack/unpack format specifier.
133
134 The String and Raw Byte data types are designed to support directly referencing the raw packet data without
135 copying them into a temporary buffer for efficiency, easy of use, and to reduce the possibility of resource
136 leaks. The String data type contains a null terminator in the packet data so it can be treated as a normal
137 C-style string (e.g. strcpy works on it). The Raw Bytes data type can be used via a pointer and size. The data
138 packing and unpacking routines are designed around the packet format to allow for efficient packet handling.
139
140 Protocol
141 ========
142
143 The RMx protocol is a TCP-based client/server protocol. The server listens on a well-known TCP port. The client
144 connects to the server port and a session of message exchange begins. The client drives the session by sending
145 the initial message describing the action it wants performed by the server. The server performs operations
146 requested by the client and asynchronously sends reply messages as specified by the type of request.
147
148 The general operation of the RMx server is as follows:
149
150 1) Initialize server (set up synchronization support, etc.).
151 2) Run server by creating socket(s) for listening and wait until a connection is accepted.
152 3) If a connection is accepted:
153 3a) Accept session (allocate, link into session list, create session thread, etc.).
154
155 The general operation of the RMx client is as follows:
156
157 1) Initialize client (set up synchronization support, etc.).
158 2) Start a session to the server.
159
160 The general operation of the RMx session thread (used by the client and server) is as follows:
161
162 1) Initialize session (set up synchronization support, etc.).
163 2) Wait for a message to be received.
164 3) If a message is received:
165 3a) Process the message.
166 */
167
168 #if 0
169 #pragma mark == Versions ==
170 #endif
171
172 //---------------------------------------------------------------------------------------------------------------------------
173 /*! @typedef kRMxCurrentVersion
174
175 @abstract Current version of the RMx implementation.
176 */
177
178 #define kRMxCurrentVersion NumVersionBuild( 1, 0, 0, kVersionStageFinal, 0 )
179
180 //---------------------------------------------------------------------------------------------------------------------------
181 /*! @typedef kRMxOldestClientVersion
182
183 @abstract Oldest version of the RMx client that works with this server.
184 */
185
186 #define kRMxOldestClientVersion NumVersionBuild( 1, 0, 0, kVersionStageFinal, 0 )
187
188 //---------------------------------------------------------------------------------------------------------------------------
189 /*! @typedef kRMxOldestServerVersion
190
191 @abstract Oldest version of the RMx server that works with this client.
192 */
193
194 #define kRMxOldestServerVersion NumVersionBuild( 1, 0, 0, kVersionStageFinal, 0 )
195
196 #if 0
197 #pragma mark == General ==
198 #endif
199
200 //---------------------------------------------------------------------------------------------------------------------------
201 /*! @defined kRMxServerPort
202
203 @abstract TCP port of DNS-SD server in host byte order.
204 */
205
206 #define kRMxServerPort 5354
207 #define kRMxServerPortString "5354"
208
209 //---------------------------------------------------------------------------------------------------------------------------
210 /*! @defined kRMxClientTimeout
211
212 @abstract Default client timeout.
213 */
214
215 #define kRMxClientTimeout ( 5 * 1000 ) // 5 seconds
216
217 //---------------------------------------------------------------------------------------------------------------------------
218 /*! @defined kDNSRecordIndexDefault
219
220 @abstract Record index for the default TXT record.
221 */
222
223 #define kDNSRecordIndexDefaultTXT 0
224
225 //---------------------------------------------------------------------------------------------------------------------------
226 /*! @enum RMxState
227
228 @abstract State of the RMx engine.
229
230 @constant kRMxStateInvalid Not in a valid state.
231 @constant kRMxStateStop Stopped.
232 @constant kRMxStateRun Running.
233 */
234
235 typedef enum
236 {
237 kRMxStateInvalid,
238 kRMxStateStop,
239 kRMxStateRun
240
241 } RMxState;
242
243 //---------------------------------------------------------------------------------------------------------------------------
244 /*! @var gRMxState
245
246 @abstract Global state of the RMx engine.
247 */
248
249 extern RMxState gRMxState;
250
251 //---------------------------------------------------------------------------------------------------------------------------
252 /*! @var gRMxState
253
254 @abstract Global state change event associated with the RMx engine.
255 */
256
257 extern HANDLE gRMxStateChangeEvent;
258
259 //---------------------------------------------------------------------------------------------------------------------------
260 /*! @function RMxInitialize
261
262 @abstract Initializes the RMx engine.
263 */
264
265 OSStatus RMxInitialize( void );
266
267 //---------------------------------------------------------------------------------------------------------------------------
268 /*! @function RMxFinalize
269
270 @abstract Finalizes the RMx engine.
271 */
272
273 void RMxFinalize( void );
274
275 //---------------------------------------------------------------------------------------------------------------------------
276 /*! @function RMxLock
277
278 @abstract Locks the RMx engine.
279 */
280
281 void RMxLock( void );
282
283 //---------------------------------------------------------------------------------------------------------------------------
284 /*! @function RMxUnlock
285
286 @abstract Unlocks the RMx engine.
287 */
288
289 void RMxUnlock( void );
290
291 #if 0
292 #pragma mark == Messages ==
293 #endif
294
295 //---------------------------------------------------------------------------------------------------------------------------
296 /*! @typedef RMxSignature
297
298 @abstract Signature for RMx messages.
299
300 @constant kRMxSignatureVersion1 Version 1 message.
301 */
302
303 typedef uint32_t RMxSignature;
304
305 #define kRMxSignatureVersion1 0x524D7831 // 'RMx1' Version 1 message.
306
307 //---------------------------------------------------------------------------------------------------------------------------
308 /*! @typedef RMxFlags
309
310 @abstract Flags for RMx messages.
311
312 @constant kRMxFlagsNone No flags.
313 */
314
315 typedef uint32_t RMxFlags;
316
317 #define kRMxFlagsNone 0
318
319 //---------------------------------------------------------------------------------------------------------------------------
320 /*! @typedef RMxOpCode
321
322 @abstract Operation code for RMx messages.
323
324 @constant kRMxOpCodeInvalid Invalid message.
325 @constant kRMxOpCodeCheckVersion DNSServiceCheckVersion message.
326 @constant kRMxOpCodeCopyProperty DNSServiceCopyProperty message.
327 @constant kRMxOpCodeEnumerateDomains DNSServiceEnumerateDomains message.
328 @constant kRMxOpCodeRegister DNSServiceRegister message.
329 @constant kRMxOpCodeAddRecord DNSServiceAddRecord message.
330 @constant kRMxOpCodeUpdateRecord DNSServiceUpdateRecord message.
331 @constant kRMxOpCodeRemoveRecord DNSServiceRemoveRecord message.
332 @constant kRMxOpCodeBrowse DNSServiceBrowse message.
333 @constant kRMxOpCodeResolve DNSServiceResolve message.
334 @constant kRMxOpCodeCreateConnection DNSServiceCreateConnection message.
335 @constant kRMxOpCodeRegisterRecord DNSServiceRegisterRecord message.
336 @constant kRMxOpCodeQueryRecord DNSServiceQueryRecord message.
337 @constant kRMxOpCodeReconfirmRecord DNSServiceReconfirmRecord message.
338 */
339
340 typedef uint32_t RMxOpCode;
341
342 #define kRMxOpCodeInvalid 0
343
344 #define kRMxOpCodeCheckVersion 10
345 // Request: <w:clientCurrentVersion> <w:clientOldestClientVersion> <w:clientOldestServerVersion>
346 // Reply: <w:errorCode> <w:serverCurrentVersion> <w:serverOldestClientVersion> <w:serverOldestServerVersion>
347
348 #define kRMxOpCodeCopyProperty 11
349 // Request: <w:propertyCode>
350 // Reply: <w:errorCode> <w:propertyCode> <n:propertyData>
351
352 #define kRMxOpCodeEnumerateDomains 100
353 // Request: <w:flags> <w:interfaceIndex>
354 // Reply: <w:flags> <w:interfaceIndex> <w:errorCode> <s:domain>
355
356 #define kRMxOpCodeRegister 200
357 // Request: <w:flags> <w:interfaceIndex> <s:name> <s:type> <s:domain> <s:host> <h:port> <n:txt>
358 // Reply: <w:flags> <w:errorCode> <s:name> <s:type> <s:domain>
359
360 #define kRMxOpCodeAddRecord 201
361 // Request: <w:id> <w:flags> <h:rrType> <n:rrData> <w:ttl>
362 // Reply: no reply
363
364 #define kRMxOpCodeUpdateRecord 202
365 // Request: <w:id> <w:flags> <n:rrData> <w:ttl>
366 // Reply: no reply
367
368 #define kRMxOpCodeRemoveRecord 203
369 // Request: <w:id> <w:flags>
370 // Reply: no reply
371
372 #define kRMxOpCodeBrowse 300
373 // Request: <w:flags> <w:interfaceIndex> <s:type> <s:domain>
374 // Reply: <w:flags> <w:interfaceIndex> <w:errorCode> <s:name> <s:type> <s:domain>
375
376 #define kRMxOpCodeResolve 400
377 // Request: <w:flags> <w:interfaceIndex> <s:name> <s:type> <s:domain>
378 // Reply: <w:flags> <w:interfaceIndex> <w:errorCode> <s:fullName> <n:addr> <s:hostName> <h:port> <n:txtRecord>
379
380 #define kRMxOpCodeCreateConnection 500
381 // Request: no data
382 // Reply: no reply
383
384 #define kRMxOpCodeRegisterRecord 510
385 // Request: <w:flags> <w:interfaceIndex> <s:name> <h:rrType> <h:rrClass> <n:rrData> <w:ttl>
386 // Reply: <w:flags> <w:errorCode> <w:recordID>
387
388 #define kRMxOpCodeQueryRecord 511
389 // Request: <w:flags> <w:interfaceIndex> <s:name> <h:rrType> <h:rrClass>
390 // Reply: <w:flags> <w:interfaceIndex> <w:errorCode> <s:name> <h:rrType> <h:rrClass> <n:rrData> <w:ttl>
391
392 #define kRMxOpCodeReconfirmRecord 512
393 // Request: <w:flags> <w:interfaceIndex> <s:name> <h:rrType> <h:rrClass> <n:rrData>
394 // Reply: no reply
395
396 //---------------------------------------------------------------------------------------------------------------------------
397 /*! @typedef RMxMessageCallBack
398
399 @abstract Callback function for a message.
400 */
401
402 typedef struct RMxMessage RMxMessage;
403
404 typedef void ( *RMxMessageCallBack )( RMxMessage *inMessage );
405
406 //---------------------------------------------------------------------------------------------------------------------------
407 /*! @typedef RMxSessionRef
408
409 @abstract References to a session.
410 */
411
412 typedef struct RMxSession * RMxSessionRef;
413
414 //---------------------------------------------------------------------------------------------------------------------------
415 /*! @struct RMxMessage
416
417 @abstract RMx message.
418
419 @field signature Signature identifying message as an RMx message (and for future versioning).
420 @field opcode Operation code of the message.
421 @field flags Flags for the message.
422 @field xid Transaction ID. WARNING: Must be unique within execution environment (e.g. process).
423 @field status Status of the message (used to return error replies).
424
425 @field sendSize Size of data to send.
426 @field sendData Data to send.
427 @field recvSize Size of received data.
428 @field recvData Received data.
429
430 @field context Context for the completion callback (specified when session started).
431 @field session Session where the message is sent/received.
432
433 @field bufferSize PRIVATE: Size of entire message buffer or 0 if message not constructed.
434 @field buffer PRIVATE: Ptr to entire message buffer or NULL if message not constructed.
435 @field storage PRIVATE: Local storage for small messages.
436
437 @constant kRMxMessageSynchronous Meta-message indicating operation should be performed synchronously.
438 @constant kRMxMessageHeaderSize Size of the header section of an RMx message packet.
439 @constant kRMxMessageInlineBufferSize Size of the inline message buffer.
440
441 @discussion
442
443 Meanings of the field descriptions:
444
445 PRIVATE - Indicates field is private and should not be touched.
446 IN - Input field that must be set up before passing the message to RMx.
447 OUT - Output field that whose value on input will be ignore and replaced with a new value on completion.
448
449 When a message is passed to RMx, the message becomes the ownership of RMx until completion of the message.
450 No fields of the messages should be touched while a message is in use by RMx.
451
452 When sending messages asynchronously, the underlying storage for the message must be valid for the duration
453 of the message. This means stack-based storage cannot be for asynchronous messages because when the function
454 that allocated the stack-based variable returns, the message storage will go out of scope and become invalid.
455 */
456
457 #define kRMxMessageHeaderSize 24 // <w:signature> <w:opcode> <w:flags> <w:xid> <w:status> <w:size>
458 #define kRMxMessageInlineBufferSize 1024
459
460 check_compile_time( kRMxMessageHeaderSize <= kRMxMessageInlineBufferSize );
461
462 struct RMxMessage
463 {
464 RMxSignature signature;
465 RMxOpCode opcode;
466 RMxFlags flags;
467 uint32_t xid;
468 OSStatus status;
469
470 uint32_t sendSize;
471 uint8_t * sendData;
472 uint32_t recvSize;
473 uint8_t * recvData;
474
475 void * context;
476 RMxSessionRef session;
477
478 // PRIVATE (internal use only)
479
480 uint32_t bufferSize;
481 uint8_t * buffer;
482 uint8_t storage[ kRMxMessageInlineBufferSize ];
483 };
484
485 //---------------------------------------------------------------------------------------------------------------------------
486 /*! @function RMxMessageInitialize
487
488 @abstract Initializes an RMx message structure. Must be called before the message structure can be used.
489 */
490
491 void RMxMessageInitialize( RMxMessage *inMessage );
492
493 //---------------------------------------------------------------------------------------------------------------------------
494 /*! @function RMxMessageRelease
495
496 @abstract Releases the resources used by an RMx message.
497 */
498
499 void RMxMessageRelease( RMxMessage *inMessage );
500
501 #if 0
502 #pragma mark == Sessions ==
503 #endif
504
505 //---------------------------------------------------------------------------------------------------------------------------
506 /*! @typedef RMxSessionFlags
507
508 @abstract Session flags.
509
510 @constant kRMxSessionFlagsNone No flags.
511 @constant kRMxSessionFlagServer Session is operating in server mode (replying to requests).
512 @constant kRMxSessionFlagsNoThread Do not create a thread to process messages (i.e. one-shot sync session).
513 @constant kRMxSessionFlagsThreadDone Thread is no longer active.
514 @constant kRMxSessionFlagsNoClose Do not close the session when the thread exits.
515 */
516
517 typedef uint32_t RMxSessionFlags;
518
519 #define kRMxSessionFlagsNone 0
520 #define kRMxSessionFlagsServer ( 1 << 0 )
521 #define kRMxSessionFlagsNoThread ( 1 << 1 )
522 #define kRMxSessionFlagsThreadDone ( 1 << 2 )
523 #define kRMxSessionFlagsNoClose ( 1 << 3 )
524
525 //---------------------------------------------------------------------------------------------------------------------------
526 /*! @struct RMxSession
527
528 @abstract Data structure for a session.
529 */
530
531 typedef struct RMxSession RMxSession;
532 struct RMxSession
533 {
534 RMxSessionRef next;
535 RMxSessionFlags flags;
536 SocketRef sock;
537 HANDLE sockEvent;
538 HANDLE closeEvent;
539 HANDLE thread;
540 unsigned threadID;
541 DWORD waitCount;
542 HANDLE waitHandles[ 3 ];
543 bool quit;
544
545 RMxMessageCallBack callback;
546 RMxMessage message;
547 uint8_t * messageRecvBuffer;
548 uint8_t * messageRecvBufferPtr;
549 int messageRecvRemaining;
550 bool messageRecvHeaderDone;
551 };
552
553 //---------------------------------------------------------------------------------------------------------------------------
554 /*! @function RMxSessionOpen
555
556 @abstract Opens a session and optionally sends a formatted message.
557 */
558
559 OSStatus
560 RMxSessionOpen(
561 const char * inServer,
562 RMxSessionFlags inFlags,
563 SocketRef inSock,
564 RMxMessageCallBack inCallBack,
565 void * inContext,
566 RMxSessionRef * outSession,
567 RMxOpCode inMessageOpCode,
568 const char * inMessageFormat,
569 ... );
570
571 //---------------------------------------------------------------------------------------------------------------------------
572 /*! @function RMxSessionClose
573
574 @abstract Closes a session.
575 */
576
577 OSStatus RMxSessionClose( RMxSessionRef inSession, OSStatus inReason );
578
579 //---------------------------------------------------------------------------------------------------------------------------
580 /*! @function RMxSessionSendMessage
581
582 @abstract Sends a formatted message.
583 */
584
585 OSStatus RMxSessionSendMessage( RMxSessionRef inSession, RMxOpCode inOpCode, OSStatus inStatus, const char *inFormat, ... );
586
587 //---------------------------------------------------------------------------------------------------------------------------
588 /*! @function RMxSessionRecvMessage
589
590 @abstract Synchronously receives a message.
591 */
592
593 OSStatus RMxSessionRecvMessage( RMxSessionRef inSession, DWORD inTimeout );
594
595 #if 0
596 #pragma mark == Utilities ==
597 #endif
598
599 //---------------------------------------------------------------------------------------------------------------------------
600 /*! @function RMxCheckVersion
601
602 @abstract Compares client and server version information and returns if they are compatible.
603 */
604
605 OSStatus
606 RMxCheckVersion(
607 uint32_t inClientCurrentVersion, uint32_t inClientOldestClientVersion, uint32_t inClientOldestServerVersion,
608 uint32_t inServerCurrentVersion, uint32_t inServerOldestClientVersion, uint32_t inServerOldestServerVersion );
609
610 //---------------------------------------------------------------------------------------------------------------------------
611 /*! @function RMxPackedSize
612
613 @abstract Determines the number of bytes required to pack data using the specified format string and arguments.
614 */
615
616 OSStatus RMxPackedSize( size_t *outSize, const char *inFormat, ... );
617
618 //---------------------------------------------------------------------------------------------------------------------------
619 /*! @function RMxPackedSizeVAList
620
621 @abstract Determines the number of bytes required to pack data using the format string and argument list.
622 */
623
624 OSStatus RMxPackedSizeVAList( size_t *outSize, const char *inFormat, va_list inArgs );
625
626 //---------------------------------------------------------------------------------------------------------------------------
627 /*! @function RMxPack
628
629 @abstract Packs data into a buffer using the format string and arguments.
630 */
631
632 OSStatus RMxPack( void *inBuffer, size_t inMaxSize, size_t *outSize, const char *inFormat, ... );
633
634 //---------------------------------------------------------------------------------------------------------------------------
635 /*! @function RMxPackVAList
636
637 @abstract Packs data into a buffer using the format string and argument list.
638 */
639
640 OSStatus RMxPackVAList( void *inBuffer, size_t inMaxSize, size_t *outSize, const char *inFormat, va_list inArgs );
641
642 //---------------------------------------------------------------------------------------------------------------------------
643 /*! @function RMxUnpack
644
645 @abstract Unpacks data from a buffer using the format string and arguments.
646 */
647
648 OSStatus RMxUnpack( const void *inData, size_t inSize, const char *inFormat, ... );
649
650 //---------------------------------------------------------------------------------------------------------------------------
651 /*! @function RMxUnpackVAList
652
653 @abstract Unpacks data from a buffer using the format string and argument list.
654 */
655
656 OSStatus RMxUnpackVAList( const void *inData, size_t inSize, const char *inFormat, va_list inArgs );
657
658 #ifdef __cplusplus
659 }
660 #endif
661
662 #endif // __RMx_COMMON__