X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=doc%2Fasn.xml;h=36da81284318300881ea8d0c01f021c4ef13af3d;hp=e1262676768825ab26e0079b2986d76bb4d97ab7;hb=3227202c561b3189378cba8318c7610aeae1421a;hpb=3d18b35078096b9fd1feb8e2d6fd7e9e48755ad5
diff --git a/doc/asn.xml b/doc/asn.xml
index e126267..36da812 100644
--- a/doc/asn.xml
+++ b/doc/asn.xml
@@ -1,139 +1,140 @@
-
- The ASN Module
- Introduction
-
- The &asn; module provides you with a set of C struct definitions for the
- various PDUs of the protocol, as well as for the complex types
- appearing within the PDUs. For the primitive data types, the C
- representation often takes the form of an ordinary C language type,
- such as int. For ASN.1 constructs that have no direct
- representation in C, such as general octet strings and bit strings,
- the &odr; module (see section The ODR Module)
- provides auxiliary definitions.
-
-
- Preparing PDUs
-
-
- A structure representing a complex ASN.1 type doesn't in itself contain the
- members of that type. Instead, the structure contains
- pointers to the members of the type.
- This is necessary, in part, to allow a mechanism for specifying which
- of the optional structure (SEQUENCE) members are present, and which
- are not. It follows that you will need to somehow provide space for
- the individual members of the structure, and set the pointers to
- refer to the members.
-
-
- The conversion routines don't care how you allocate and maintain your
- C structures - they just follow the pointers that you provide.
- Depending on the complexity of your application, and your personal
- taste, there are at least three different approaches that you may take
- when you allocate the structures.
-
-
-
- You can use static or automatic local variables in the function that
- prepares the PDU. This is a simple approach, and it provides the most
- efficient form of memory management. While it works well for flat
- PDUs like the InitReqest, it will generally not be sufficient for say,
- the generation of an arbitrarily complex RPN query structure.
-
-
- You can individually create the structure and its members using the
- malloc(2) function. If you want to ensure that
- the data is freed when it is no longer needed, you will have to
- define a function that individually releases each member of a
- structure before freeing the structure itself.
-
-
- You can use the odr_malloc() function (see section
- Using ODR for details). When you use
- odr_malloc(), you can release all of the
- allocated data in a single operation, independent of any pointers and
- relations between the data. odr_malloc() is based on a
- "nibble-memory"
- scheme, in which large portions of memory are allocated, and then
- gradually handed out with each call to odr_malloc().
- The next time you call odr_reset(), all of the
- memory allocated since the last call is recycled for future use (actually,
- it is placed on a free-list).
-
-
- You can combine all of the methods described here. This will often be
- the most practical approach. For instance, you might use
- odr_malloc() to allocate an entire structure and
- some of its elements, while you leave other elements pointing to global
- or per-session default variables.
-
-
-
- The &asn; module provides an important aid in creating new PDUs. For
- each of the PDU types (say, Z_InitRequest), a
- function is provided that allocates and initializes an instance of
- that PDU type for you. In the case of the InitRequest, the function is
- simply named zget_InitRequest(), and it sets up
- reasonable default value for all of the mandatory members. The optional
- members are generally initialized to null pointers. This last aspect
- is very important: it ensures that if the PDU definitions are
- extended after you finish your implementation (to accommodate
- new versions of the protocol, say), you won't get into trouble with
- uninitialized pointers in your structures. The functions use
- odr_malloc() to
- allocate the PDUs and its members, so you can free everything again with a
- single call to odr_reset(). We strongly recommend
- that you use the zget_*
- functions whenever you are preparing a PDU (in a C++ API, the
- zget_
- functions would probably be promoted to constructors for the
- individual types).
-
-
- The prototype for the individual PDU types generally look like this:
-
-
+
+The ASN Module
+ Introduction
+
+ The &asn; module provides you with a set of C struct definitions for the
+ various PDUs of the protocol, as well as for the complex types
+ appearing within the PDUs. For the primitive data types, the C
+ representation often takes the form of an ordinary C language type,
+ such as int. For ASN.1 constructs that have no direct
+ representation in C, such as general octet strings and bit strings,
+ the &odr; module (see section The ODR Module)
+ provides auxiliary definitions.
+
+
+ Preparing PDUs
+
+
+ A structure representing a complex ASN.1 type doesn't in itself contain the
+ members of that type. Instead, the structure contains
+ pointers to the members of the type.
+ This is necessary, in part, to allow a mechanism for specifying which
+ of the optional structure (SEQUENCE) members are present, and which
+ are not. It follows that you will need to somehow provide space for
+ the individual members of the structure, and set the pointers to
+ refer to the members.
+
+
+ The conversion routines don't care how you allocate and maintain your
+ C structures - they just follow the pointers that you provide.
+ Depending on the complexity of your application, and your personal
+ taste, there are at least three different approaches that you may take
+ when you allocate the structures.
+
+
+
+ You can use static or automatic local variables in the function that
+ prepares the PDU. This is a simple approach, and it provides the most
+ efficient form of memory management. While it works well for flat
+ PDUs like the InitReqest, it will generally not be sufficient for say,
+ the generation of an arbitrarily complex RPN query structure.
+
+
+ You can individually create the structure and its members using the
+ malloc(2) function. If you want to ensure that
+ the data is freed when it is no longer needed, you will have to
+ define a function that individually releases each member of a
+ structure before freeing the structure itself.
+
+
+ You can use the odr_malloc() function (see section
+ Using ODR for details). When you use
+ odr_malloc(), you can release all of the
+ allocated data in a single operation, independent of any pointers and
+ relations between the data. odr_malloc() is based on a
+ "nibble-memory"
+ scheme, in which large portions of memory are allocated, and then
+ gradually handed out with each call to odr_malloc().
+ The next time you call odr_reset(), all of the
+ memory allocated since the last call is recycled for future use (actually,
+ it is placed on a free-list).
+
+
+ You can combine all of the methods described here. This will often be
+ the most practical approach. For instance, you might use
+ odr_malloc() to allocate an entire structure and
+ some of its elements, while you leave other elements pointing to global
+ or per-session default variables.
+
+
+
+ The &asn; module provides an important aid in creating new PDUs. For
+ each of the PDU types (say, Z_InitRequest), a
+ function is provided that allocates and initializes an instance of
+ that PDU type for you. In the case of the InitRequest, the function is
+ simply named zget_InitRequest(), and it sets up
+ reasonable default value for all of the mandatory members. The optional
+ members are generally initialized to null pointers. This last aspect
+ is very important: it ensures that if the PDU definitions are
+ extended after you finish your implementation (to accommodate
+ new versions of the protocol, say), you won't get into trouble with
+ uninitialized pointers in your structures. The functions use
+ odr_malloc() to
+ allocate the PDUs and its members, so you can free everything again with a
+ single call to odr_reset(). We strongly recommend
+ that you use the zget_*
+ functions whenever you are preparing a PDU (in a C++ API, the
+ zget_
+ functions would probably be promoted to constructors for the
+ individual types).
+
+
+ The prototype for the individual PDU types generally look like this:
+
+
Z_<type> *zget_<type>(ODR o);
-
+
-
+
eg.:
-
+
-
+
Z_InitRequest *zget_InitRequest(ODR o);
-
-
-
- The &odr; handle should generally be your encoding stream, but it needn't be.
-
-
- As well as the individual PDU functions, a function
- zget_APDU() is
- provided, which allocates a toplevel Z-APDU of the type requested:
-
-
-
+
+
+
+ The &odr; handle should generally be your encoding stream, but it
+ needn't be.
+
+
+ As well as the individual PDU functions, a function
+ zget_APDU() is provided, which allocates
+ a toplevel Z-APDU of the type requested:
+
+
+
Z_APDU *zget_APDU(ODR o, int which);
-
-
-
- The which parameter is (of course) the discriminator
- belonging to the Z_APDUCHOICE type.
- All of the interface described here is provided by the &asn; module, and
- you access it through the proto.h header file.
-
-
-
- Object Identifiers
-
- When you refer to object identifiers in your application, you need to
- be aware that SR and Z39.50 use two different set of OIDs to refer to
- the same objects. To handle this easily, &yaz; provides a utility module
- to &asn; which provides an internal representation of the OIDs used in
- both protocols. Each oid is described by a structure:
-
-
-
+
+
+
+ The which parameter is (of course) the discriminator
+ belonging to the Z_APDUCHOICE type.
+ All of the interface described here is provided by the &asn; module, and
+ you access it through the proto.h header file.
+
+
+
+ Object Identifiers
+
+ When you refer to object identifiers in your application, you need to
+ be aware that SR and Z39.50 use two different set of OIDs to refer to
+ the same objects. To handle this easily, &yaz; provides a utility module
+ to &asn; which provides an internal representation of the OIDs used in
+ both protocols. Each oid is described by a structure:
+
+
+
typedef struct oident
{
enum oid_proto proto;
@@ -142,63 +143,63 @@ typedef struct oident
int oidsuffix[OID_SIZE];
char *desc;
} oident;
-
-
-
- The proto field can be set to either
- PROTO_SR or PROTO_Z3950.
- The class might be, say,
- CLASS_RECSYN, and the value might be
+
+
+
+ The proto field can be set to either
+ PROTO_SR or PROTO_Z3950.
+ The class might be, say,
+ CLASS_RECSYN, and the value might be
VAL_USMARC for the USMARC record format. Functions
-
-
-
+
+
+
int *oid_ent_to_oid(struct oident *ent, int *dst);
struct oident *oid_getentbyoid(int *o);
-
-
+
+
+
+ are provided to map between object identifiers and database entries.
+ If you store a member of the oid_proto type in
+ your association state information, it's a simple matter, at runtime,
+ to generate the correct OID when you need it. For decoding, you can
+ simply ignore the proto field, or if you're strict, you can verify
+ that your peer is using the OID family from the correct protocol.
+ The desc field is a short, human-readable name
+ for the PDU, useful mainly for diagnostic output.
+
+
+
- are provided to map between object identifiers and database entries.
- If you store a member of the oid_proto type in
- your association state information, it's a simple matter, at runtime,
- to generate the correct OID when you need it. For decoding, you can
- simply ignore the proto field, or if you're strict, you can verify
- that your peer is using the OID family from the correct protocol.
- The desc field is a short, human-readable name
- for the PDU, useful mainly for diagnostic output.
+ The old function oid_getoidbyent still exists but
+ is not thread safe. Use oid_ent_to_oid instead
+ and pass an array of size OID_SIZE.
-
-
-
- The old function oid_getoidbyent still exists but is
- not thread safe. Use oid_ent_to_oid instead
- and pass an array of size OID_SIZE.
-
-
-
-
-
- Plans are underway to merge the two protocols into a single
- definition, with one set of object identifiers. When this happens, the
- oid module will no longer be required to support protocol
- independence, but it should still be useful as a simple OID database.
-
-
-
-
- EXTERNAL Data
-
+
+
+
- In order to achieve extensibility and adaptability to different
- application domains, the new version of the protocol defines many
- structures outside of the main ASN.1 specification, referencing them
- through ASN.1 EXTERNAL constructs. To simplify the construction and access
- to the externally referenced data, the &asn; module defines a
- specialized version of the EXTERNAL construct, called
- Z_External.It is defined thus:
+ Plans are underway to merge the two protocols into a single
+ definition, with one set of object identifiers. When this happens, the
+ oid module will no longer be required to support protocol
+ independence, but it should still be useful as a simple OID database.
-
-
+
+
+
+ EXTERNAL Data
+
+
+ In order to achieve extensibility and adaptability to different
+ application domains, the new version of the protocol defines many
+ structures outside of the main ASN.1 specification, referencing them
+ through ASN.1 EXTERNAL constructs. To simplify the construction and
+ access to the externally referenced data, the &asn; module defines a
+ specialized version of the EXTERNAL construct, called
+ Z_External.It is defined thus:
+
+
+
typedef struct Z_External
{
Odr_oid *direct_reference;
@@ -237,501 +238,817 @@ typedef struct Z_External
} u;
} Z_External;
-
-
-
- When decoding, the &asn; module will attempt to determine which
- syntax describes the data by looking at the reference fields
- (currently only the direct-reference). For ASN.1 structured data, you
- need only consult the which field to determine the
- type of data. You can the access the data directly through the union.
- When constructing data for encoding, you set the union pointer to point
- to the data, and set the which field accordingly.
+
+
+
+ When decoding, the &asn; module will attempt to determine which
+ syntax describes the data by looking at the reference fields
+ (currently only the direct-reference). For ASN.1 structured data, you
+ need only consult the which field to determine the
+ type of data. You can the access the data directly through the union.
+ When constructing data for encoding, you set the union pointer to point
+ to the data, and set the which field accordingly.
Remember also to set the direct (or indirect) reference to the correct
- OID for the data type.
- For non-ASN.1 data such as MARC records, use the
- octet_aligned arm of the union.
-
-
-
- Some servers return ASN.1 structured data values (eg. database
- records) as BER-encoded records placed in the
- octet-aligned branch of the EXTERNAL CHOICE.
- The ASN-module will not automatically decode
- these records. To help you decode the records in the application, the
- function
-
-
-
- Z_ext_typeent *z_ext_gettypebyref(oid_value ref);
-
-
-
- Can be used to retrieve information about the known, external data
- types. The function return a pointer to a static area, or NULL, if no
- match for the given direct reference is found. The
- Z_ext_typeent
- is defined as:
-
-
-
+ OID for the data type.
+ For non-ASN.1 data such as MARC records, use the
+ octet_aligned arm of the union.
+
+
+
+ Some servers return ASN.1 structured data values (eg. database
+ records) as BER-encoded records placed in the
+ octet-aligned branch of the EXTERNAL CHOICE.
+ The ASN-module will not automatically decode
+ these records. To help you decode the records in the application, the
+ function
+
+
+
+ Z_ext_typeent *z_ext_gettypebyref(oid_value ref);
+
+
+
+ Can be used to retrieve information about the known, external data
+ types. The function return a pointer to a static area, or NULL, if no
+ match for the given direct reference is found. The
+ Z_ext_typeent
+ is defined as:
+
+
+
typedef struct Z_ext_typeent
{
oid_value dref; /* the direct-reference OID value. */
int what; /* discriminator value for the external CHOICE */
Odr_fun fun; /* decoder function */
} Z_ext_typeent;
-
-
-
- The what member contains the
- Z_External union discriminator value for the
- given type: For the SUTRS record syntax, the value would be
- Z_External_sutrs.
- The fun member contains a pointer to the
- function which encodes/decodes the given type. Again, for the SUTRS
- record syntax, the value of fun would be
- z_SUTRS (a function pointer).
+
+
+
+ The what member contains the
+ Z_External union discriminator value for the
+ given type: For the SUTRS record syntax, the value would be
+ Z_External_sutrs.
+ The fun member contains a pointer to the
+ function which encodes/decodes the given type. Again, for the SUTRS
+ record syntax, the value of fun would be
+ z_SUTRS (a function pointer).
-
-
- If you receive an EXTERNAL which contains an octet-string value that
- you suspect of being an ASN.1-structured data value, you can use
- z_ext_gettypebyref to look for the provided
- direct-reference.
- If the return value is different from NULL, you can use the provided
- function to decode the BER string (see section
- Using ODR).
-
-
+
+
+ If you receive an EXTERNAL which contains an octet-string value that
+ you suspect of being an ASN.1-structured data value, you can use
+ z_ext_gettypebyref to look for the provided
+ direct-reference.
+ If the return value is different from NULL, you can use the provided
+ function to decode the BER string (see section
+ Using ODR).
+
+
+
+ If you want to send EXTERNALs containing
+ ASN.1-structured values in the occtet-aligned branch of the CHOICE, this
+ is possible too. However, on the encoding phase, it requires a somewhat
+ involved juggling around of the various buffers involved.
+
+
+ If you need to add new, externally defined data types, you must update
+ the struct above, in the source file prt-ext.h, as
+ well as the encoder/decoder in the file prt-ext.c.
+ When changing the latter, remember to update both the
+ arm arrary and the list
+ type_table, which drives the CHOICE biasing that
+ is necessary to tell the different, structured types apart
+ on decoding.
+
+
+
- If you want to send EXTERNALs containing
- ASN.1-structured values in the occtet-aligned branch of the CHOICE, this
- is possible too. However, on the encoding phase, it requires a somewhat
- involved juggling around of the various buffers involved.
+ Eventually, the EXTERNAL processing will most likely
+ automatically insert the correct OIDs or indirect-refs. First,
+ however, we need to determine how application-context management
+ (specifically the presentation-context-list) should fit into the
+ various modules.
-
- If you need to add new, externally defined data types, you must update
- the struct above, in the source file prt-ext.h, as
- well as the encoder/decoder in the file prt-ext.c.
- When changing the latter, remember to update both the arm
- arrary and the list type_table, which drives the CHOICE
- biasing that is necessary to tell the different, structured types apart
- on decoding.
-
-
-
-
- Eventually, the EXTERNAL processing will most likely
- automatically insert the correct OIDs or indirect-refs. First,
- however, we need to determine how application-context management
- (specifically the presentation-context-list) should fit into the
- various modules.
-
-
-
-
- PDU Contents Table
-
-
- We include, for reference, a listing of the fields of each top-level
- PDU, as well as their default settings.
-
-
-