McIDAS Programmer's Manual
Version 2003

[Search Manual] [Table of Contents] [Go to Previous] [Go to Next]

Building your ADDE server

Whether you're creating primary or secondary ADDE servers, they must perform these seven steps:

  1. Initialize the McIDAS-X file system to recognize MCPATH and file redirection.
  2. Read the ADDE client request.
  3. Read the server mapping table.
  4. Interpret the client request.
  5. Retrieve the requested data from disk.
  6. Send the data to the client.
  7. End the transaction.

Steps 1, 2, 3 and 7 are the same for all data types; steps 4, 5 and 6 are different among the data types. All seven steps are described in this section, along with the function calls required to perform them.

This section is organized into these parts:

McIDAS library functions

The McIDAS-X library functions that you will use when creating an ADDE server are listed alphabetically in the table below.

C function Fortran function Description



initializes the McIDAS-X environment for the server



determines if the dataset requested was flagged as a real-time dataset



given a client request, activates tracing if TRACE=nonzero value



conditionally flips 4-byte data buffers



conditionally flips 2-byte data buffers



extracts the server mapping table information



ends the ADDE transaction



reads the request header and request string sent from the client



reads data sent from the client to the server



appends information from the server mapping table to the client request



sends data from the server to the client



turns tracing off



turns tracing on



writes tracing information to a trace file



initializes the environment for secondary servers



writes tracing information to a trace file

Initializing the McIDAS-X file system

Your server must be able to access McIDAS-X disk files, since most servers are built using disk file utilities. Use the initblok function to initialize the McIDAS-X disk file system so the server can recognize MCPATH and the redirection table, as shown below. Note that the parameter passed into initblok must be a 2-byte integer.

In Fortran:

integer*2 init_stat
ok = initblok (init_stat)

In C:

short     init_stat;
ok = initblok_ (&init_stat);



For more information about disk files, see the section titled McIDAS disk files in Chapter 5, Accessing Data. For more information about file redirection and MCPATH, see the section titled McIDAS user applications in Chapter 2, Learning the Basics.

Reading the ADDE client request

Each ADDE client request received by the server contains a 160-byte request header, which contains system-level information built for the server.

The table below shows the input components included in the request header. The third column contains the starting word locations if the server is written in Fortran; the fourth column contains the variable names for the C structure, servacct, if the server is written in C.


Request header components Length, in bytes Word number in Fortran servacct structure names in C

server IP address




server port




client IP address




user initials




project number





12 (ASCII)

6 - 8


service name




input data length



input_length in excess of 160 bytes

request string

120 (ASCII)

11 - 40


The last 120 characters of the request header is a buffer that may hold the client request string. The request string contains the group and descriptor names, and any selection conditions the server may need to fulfill the client request. If the request string is too long to fit in this buffer, the request string variable will contain a value of zero in bytes 4-7; bytes 0-3 will contain the actual length of the request string, which the server then must read from stdin.

The process for reading the ADDE client request is performed with one of two functions, depending on whether the server reading the request is a primary or secondary server.

Words 41 to 64 are for sending a return packet. The section Ending the transaction in this chapter provides more information.

Using a primary server

To read the client request from a primary server, call M0sxGetClientRequest or m0sxgetclientrequest, as shown in the code fragments below.

In Fortran:

include ''
character*(MAXPATHLENGTH) request
integer                   request_block(64)
ok = m0sxgetclientrequest(request_block, request)

In C:

#include "mcidas.h"
servacct request_block;
char     *request;
int       ok;

ok = M0sxGetClientRequest (&request_block, &request);

Upon successful completion, request_block contains the request header information sent to the server, and request contains the request string, including the group and descriptor names and selection conditions specified.

Using a secondary server

To read the client request from a secondary server, call the function M0InitLocalServer, as shown in the code fragment below.

const char Server[] = {"TESTSERV"};
servacct   request_block;
char      *request;
ok = M0InitLocalServer (Server, &request_block, &request);

Upon successful completion, request_block contains the request header information sent to the server, and request contains the request string, including the group and descriptor names and selection conditions specified.

If the dataset requested by the client is stored in a non-standard McIDAS-X format on the server, the primary server starts the secondary server with a call to m0subserv. m0subserv builds an argument list for the secondary server and starts it with a call to execlp. The argument list contains both information from the client request block and the actual client request string. The M0InitLocalServer function extracts values from the secondary server's argument list and puts them in the client request block.

Reading the server mapping table

Once the server successfully receives the client's request, it must extract information from the server mapping table, which is a database that provides the server with information needed to fulfill a user request. The server mapping table is manipulated by the DSSERVE command and contains information about the location and format of the data on the server machine. This information is accessed by the server based on the group and descriptor names included in the client request.

The function M0sxdatasetinfo or m0sxdatasetinfo extracts information that the server needs from the server mapping table, including:

The code fragment below demonstrates the use of M0sxdatasetinfo. It assumes that the server administrator entered the following DSSERVE command, which created the ADDE dataset GMS/IR:

Type:  DSSERVE ADD GMS /IR AUST 3 8 TYPE=IMAGE INFO=east_ir.cfg "GMS Infrared Imagery

char *request;
char *group;
char *dataset;
char *type;
char *format;
char *info;
char *comment;
int   min_range;
int   max_range;
int   real_time;


ok = M0sxdatasetinfo (request, &group, &dataset, &type, &format,
                 &info, &comment, &min_range, &max_range, &real_time);

Upon successful completion, the output variables will contain the following values:

Variable Value












GMS Infrared Imagery






0 (default)

Interpreting the client request

After the server reads the client request and extracts the dataset information from the server mapping table, it parses the client request so the data can be located and the request fulfilled.

Since client requests are similar in form to a McIDAS-X command, it is easiest to use the McIDAS-X command line parsing routines to extract information from the request. To use common command line data retrievers, such as Mccmdstr and Mccmdint, you must initialize the command line subsystem. You only need to do this for primary servers. The M0InitLocalServer function automatically performs these steps for secondary servers.

The code fragments below demonstrate how to initialize the command line subsystem in both Fortran and C.

In Fortran:

    character*256    request
    integer          len_req

c---    request already contains the request string to be parsed

    call m0cmdput (m0cmdparse (request, len_req))

In C:

char *request;
int   len_req;
int   stat;

/* request already contains the request string to be parsed */

stat = M0cmdput (M0cmdparse (request, &len_req)) ;

Once the request string is parsed by the command line subsystem, it is your job, as the server developer, to find the data matching the request. The section titled Request syntax and data transmission formats later in this chapter explains the request syntax for each of the McIDAS-X data types.

Retrieving the requested data from disk

The method of retrieving data matching the client request will vary from file format to file format.

When determining the location of data files, you should be aware that the server mapping table may not have enough entries available for an individual dataset to fully explain the filing format. If this happens, use a configuration file and store the name of that file in the INFO field of the server mapping table. Then the server can get additional file location information there.

Sending the data to the client

When the request is parsed and the appropriate data is located, it can be sent back to the client. All data transactions are done in pairs (count + data) using the function M0sxsend or m0sxsend. First, a 4-byte value containing the length of the data being sent to the client is transmitted. Then that many bytes of data are transmitted.

To ensure that data sent between the server and the client is in network-byte-order (big-endian), include calls to M0swbyt4 or swbyt4 for all integer values. This function flips 4-byte memory segments on little-endian machines; it has no effect on big-endian machines.

The first value sent from the server to the client is read internally by the client function M0cxreq or m0cxreq before any API-level reading routines are called. For example, when serving image data, this value is the total number of bytes the server will send to completely transmit the data object. Some ADDE clients expect a dummy, nonzero value in this location. If a zero is sent back, M0cxreq or m0cxreq assumes the server was unable to fulfill the request. The complete transmission format for each McIDAS-X data type is described later in this chapter in the section titled Request syntax and data transmission formats.

The code fragment below demonstrates the appropriate way to send data from the server to the client. It assumes the client wants to receive a 4-byte dummy value of one, which will be read by m0cxreq, followed by two 40-byte records. Words 2 through 4 in the record are character values; the remainder of the record contains integer values.

    integer n_bytes      ! number of bytes to send  
    integer n_bytes_nbo  ! number of bytes in network byte order
    integer dum_val
    integer buffer(10)

c---    send the value 4 to the client indicating that it is to read an 
c---    additional 4 bytes; the additional 4 bytes will contain the 
c---    value 1; this pair is read on the client in m0cxreq.

    n_bytes     = 4
    n_bytes_nbo = n_bytes
    call swbyt4(n_bytes_nbo, 1)
       call m0sxsend (4, n_bytes_nbo)

       dum_val = 1
       call swbyt4(dum_val, 1)
       call m0sxsend (n_bytes, dum_val)

c---    now we will loop 2 times, getting new data and sending it
c---    back to the client; remember that words 2 through 4 are
c---    character strings.

    do 10 I = 1 , 2

c---    get the data

    ok = datareader (buffer)   ! fictitious function

c---    send the record length back
        n_bytes     = 40
        n_bytes_nbo = n_bytes
        call swbyt4(n_bytes_nbo, 1)
        call m0sxsend (4, n_bytes_nbo)

c---    convert the appropriate locations in the buffer to
c---    network byte order

        call swbyt4(buffer(1), 1)
          call swbyt4(buffer(5), 6) 

c---    send the data back to the client

        call m0sxsend (n_bytes, buffer) 

10  continue

Ending the transaction

After the data is transmitted to the client, the server ends the transaction by calling M0sxdone or m0sxdone. This function sends a 96-byte trailer, which is filled on the server and sent to the client at the end of the transaction. Its contents are described in the table below.

Trailer description Length, in bytes Word number in Fortran servacct structure names in C

total reply length




cpu used




return status code




error messages


44 - 61






start time




end time




Before the transaction ends, you must set the return status code and any error messages that may have voided the transaction. The only successful return code is zero, which appears in word 43 of the client request block. If you send a nonzero value to the client, also put an error string in words 44-61 so the client API will print a message telling the user why the request couldn't be fulfilled. If your site uses the ADDE accounting software, also fill word 41 with the total number of bytes transmitted to the client.

The code fragment below shows the calling sequence that a server should include for a request that can't be fulfilled.

    integer       request_block(64)
    logical       syntax_error

c---there is a syntax error in the client request

    if (syntax_error)then
       comm_block(43) = -1001
        call movcw (request_block(44),'Syntax error in the user

    call m0sxdone (request_block)

Using this example, the message below is printed by the function m0cxreq if the server encounters a syntax error.

COMMAND: Syntax error in the user request -1001

[Search Manual] [Table of Contents] [Go to Previous] [Go to Next]