ASC_requestAssociation(T_ASC_Network * network,
                       T_ASC_Parameters * params,
                       T_ASC_Association ** assoc,
                       void **associatePDU,
                       unsigned long *associatePDUlength,
                       DUL_BLOCKOPTIONS block,
                       int timeout)
{
    OFCondition cond = EC_Normal;
    long sendLen;
    int retrieveRawPDU = 0;
    if (associatePDU && associatePDUlength) retrieveRawPDU = 1;

    if (network == NULL) return ASC_NULLKEY;
    if (params == NULL) return ASC_NULLKEY;

    if (ASC_countPresentationContexts(params) == 0)
    {
      return makeDcmnetCondition(ASCC_CODINGERROR, OF_error, "ASC Coding error in ASC_requestAssociation: missing presentation contexts");
    }

    *assoc = (T_ASC_Association *) malloc(sizeof(**assoc));
    if (*assoc == NULL) return EC_MemoryExhausted;
    memset((char*)*assoc, 0, sizeof(**assoc));

    (*assoc)->params = params;
    (*assoc)->nextMsgID = 1;
    (*assoc)->sendPDVLength = 0;
    (*assoc)->sendPDVBuffer = NULL;

    params->DULparams.maxPDU = params->ourMaxPDUReceiveSize;
    OFStandard::strlcpy(params->DULparams.callingImplementationClassUID,
        params->ourImplementationClassUID, DICOM_UI_LENGTH + 1);
    OFStandard::strlcpy(params->DULparams.callingImplementationVersionName,
        params->ourImplementationVersionName, 16+1);

    cond = DUL_RequestAssociation(&network->network, block, timeout,
                                  &(*assoc)->params->DULparams,
                                  &(*assoc)->DULassociation,
                                  retrieveRawPDU);


    if (retrieveRawPDU && assoc && ((*assoc)->DULassociation))
    {
      DUL_returnAssociatePDUStorage((*assoc)->DULassociation, *associatePDU, *associatePDUlength);
    }

    if (cond.good())
    {
       /*
        * The params->DULparams.peerMaxPDU parameter contains the
        * max-pdu-length value in the a-associate-ac (i.e. the max-pdu-length
        * that the remote AE is prepared to accept).
        */
        params->theirMaxPDUReceiveSize = params->DULparams.peerMaxPDU;

        if (!((params->theirMaxPDUReceiveSize & DUL_MAXPDUCOMPAT) ^ DUL_DULCOMPAT))
        {
          /* activate compatibility with DCMTK releases prior to 3.0 */
          DUL_activateCompatibilityMode((*assoc)->DULassociation, dcmEnableBackwardCompatibility.get() | DUL_DULCOMPAT | DUL_DIMSECOMPAT);
          if (params->modeCallback) params->modeCallback->callback(params->theirMaxPDUReceiveSize);
        }

        /* create a sendPDVBuffer */
        sendLen = params->theirMaxPDUReceiveSize;
        if (sendLen < 1) {
            /* the length is unlimited, choose a suitable buffer len */
            sendLen = ASC_MAXIMUMPDUSIZE;
        } else if (sendLen > ASC_MAXIMUMPDUSIZE) {
            sendLen = ASC_MAXIMUMPDUSIZE;
        }
        /* make sure max pdv length is even */
        if ((sendLen % 2) != 0)
        {
          DCMNET_WARN("ASSOC: PDV send length " << sendLen
                << " is odd (using " << (sendLen-1) << ")");
          sendLen--;
        }
        /* length is minus PDU and PDV header bytes */
        sendLen -= 12;
        if (sendLen < 1)
        {
            DCMNET_WARN("ASSOC: PDV send length " << sendLen << " (using default)");
            sendLen = ASC_MINIMUMPDUSIZE - 12;
        }
        if (sendLen < 12)
        {
            /* if sendLen is < 12, dcmdata will fail because it needs to put
             * up to 12 bytes into the send PDV buffer at once (tag header).
             * We use a larger value on this level and let the Upper Layer FSM
             * split the buffer for us into many small PDVs.
             */
            DCMNET_WARN("ASSOC: PDV send length too small, using DUL to split larger PDVs.");
            sendLen = ASC_MINIMUMPDUSIZE - 12;
        }
        (*assoc)->sendPDVLength = sendLen;
        (*assoc)->sendPDVBuffer = (unsigned char*)malloc(size_t(sendLen));
        if ((*assoc)->sendPDVBuffer == NULL) return EC_MemoryExhausted;
        OFStandard::strlcpy(params->theirImplementationClassUID,
           params->DULparams.calledImplementationClassUID, sizeof(params->theirImplementationClassUID));
        OFStandard::strlcpy(params->theirImplementationVersionName,
           params->DULparams.calledImplementationVersionName, sizeof(params->theirImplementationVersionName));

        /* make sure accepted PCs are marked as such in the requested PC list */
        cond = updateRequestedPCListFromAcceptedPCList(&params->DULparams);
    }
    return cond;
}