readPDUHeadTCP(PRIVATE_ASSOCIATIONKEY ** association,
               unsigned char *buffer, unsigned long maxLength,
               DUL_BLOCKOPTIONS block, int timeout,
     unsigned char *type, unsigned char *reserved, unsigned long *pduLength)
{
    unsigned long
        length;
    static const unsigned char
        legalPDUTypes[] = {
        DUL_TYPEASSOCIATERQ, DUL_TYPEASSOCIATEAC,
        DUL_TYPEASSOCIATERJ, DUL_TYPEDATA,
        DUL_TYPERELEASERQ, DUL_TYPERELEASERP,
        DUL_TYPEABORT
    };
    int
        found;
    unsigned long
        idx;

    /* check if the buffer is too small to capture the PDU head we are about to receive */
    if (maxLength < 6)
    {
        return makeDcmnetCondition(DULC_CODINGERROR, OF_error, "Coding Error in DUL routine: buffer too small in readPDUTCPHead");
    }

    /* (for non-blocking reading) if the timeout refers to */
    /* the default timeout, set timeout correspondingly */
    if (timeout == PRV_DEFAULTTIMEOUT)
        timeout = (*association)->timeout;

    /* try to receive PDU header (6 bytes) over the network, mind blocking */
    /* options; in the end, buffer will contain the 6 bytes that were read. */
    OFCondition cond = defragmentTCP((*association)->connection, block, (*association)->timerStart, timeout, buffer, 6, &length);

    /* if receiving was not successful, return the corresponding error value */
    if (cond.bad()) return cond;

    DCMNET_TRACE("Read PDU HEAD TCP:" << STD_NAMESPACE hex << STD_NAMESPACE setfill('0')
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[0])
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[1])
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[2])
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[3])
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[4])
              << " " << STD_NAMESPACE setw(2) << (unsigned short)(buffer[5]));

    /* determine PDU type (captured in byte 0 of buffer) and assign it to reference parameter */
    *type = *buffer++;

    /* determine value in the PDU header's reserved field (captured */
    /* in byte 1 of buffer) and assign it to reference parameter */
    *reserved = *buffer++;

    /* check if the PDU which was received shows a legal PDU type */
    for (idx = found = 0; !found && idx < sizeof(legalPDUTypes); idx++) {
        found = (*type == legalPDUTypes[idx]);
    }

    /* if the PDU's type was not legal, return a corresponding message */
    if (!found)
    {
        char buf[256];
        sprintf(buf, "Unrecognized PDU type: %2x", *type);
        return makeDcmnetCondition(DULC_UNRECOGNIZEDPDUTYPE, OF_error, buf);
    }

    /* determine the value in the PDU length field of the PDU */
    /* which was received and assign it to reference parameter */
    EXTRACT_LONG_BIG(buffer, length);
    buffer += 4;
    *pduLength = length;

    DCMNET_TRACE("Read PDU HEAD TCP: type: "
              << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(2) << (unsigned short)(*type)
              << ", length: " << STD_NAMESPACE dec << (*pduLength) << " ("
              << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(2) << (unsigned int)*pduLength
              << ")");

    /* return ok */
    return EC_Normal;
}