3. EXTERNAL Data
Prev | Chapter 5. The Z39.50 ASN.1 Module | Next

## 3. 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 Z39.50 ASN.1 module defines a specialized version of the EXTERNAL construct, called `Z_External`.It is defined thus:

    typedef struct Z_External
    {
        Odr_oid *direct_reference;
        int *indirect_reference;
        char *descriptor;
        enum
        {
            /* Generic types */
            Z_External_single = 0,
            Z_External_octet,
            Z_External_arbitrary,

            /* Specific types */
            Z_External_SUTRS,
            Z_External_explainRecord,
            Z_External_resourceReport1,
            Z_External_resourceReport2

        ...

        } which;
        union
        {
            /* Generic types */
            Odr_any *single_ASN1_type;
            Odr_oct *octet_aligned;
            Odr_bitmask *arbitrary;

            /* Specific types */
            Z_SUTRS *sutrs;
            Z_ExplainRecord *explainRecord;
            Z_ResourceReport1 *resourceReport1;
            Z_ResourceReport2 *resourceReport2;

            ...

        } u;
    } Z_External;

When decoding, the Z39.50 ASN.1 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 (e.g. 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(const oid *oid);

can be used to retrieve information about the known, external data types. The function returns 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
    {
        int oid[OID_SIZE]; /* the direct-reference OID. */
        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).

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 2, “Using ODR” ).

If you want to send EXTERNALs containing ASN.1-structured values in the octet-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` array and the list `type_table`, which drives the CHOICE biasing that is necessary to tell the different, structured types apart on decoding.

### Note

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.

Prev | Up | Next
2. Preparing PDUs | Home | 4. PDU Contents Table