AE_3_AssociateConfirmationAccept(PRIVATE_NETWORKKEY ** /*network*/,
         PRIVATE_ASSOCIATIONKEY ** association, int nextState, void *params)
{
    DUL_ASSOCIATESERVICEPARAMETERS
    * service;
    unsigned char
        * buffer = NULL,
        pduType,
        pduReserve;
    unsigned long
        pduLength;
    PRV_ASSOCIATEPDU
        assoc;
    PRV_PRESENTATIONCONTEXTITEM
        * prvCtx;
    DUL_PRESENTATIONCONTEXT
        * userPresentationCtx,
        * requestedPresentationCtx;
    DUL_SUBITEM
        * subItem;
    PRV_SCUSCPROLE
        * scuscpRole;

    service = (DUL_ASSOCIATESERVICEPARAMETERS *) params;
    OFCondition cond = readPDU(association, DUL_BLOCK, 0, &buffer, &pduType, &pduReserve, &pduLength);

    if (cond.bad())
    {
       if (buffer) free(buffer);
       return cond;
    }

    /* cond is good so we know that buffer exists */

    DCMNET_DEBUG(dump_pdu("Associate Accept", buffer, pduLength + 6));

    if (pduType == DUL_TYPEASSOCIATEAC)
    {
        if ((*association)->associatePDUFlag)
        {
          // copy A-ASSOCIATE-AC PDU
          (*association)->associatePDU = new char[pduLength+6];
          if ((*association)->associatePDU)
          {
            memcpy((*association)->associatePDU, buffer, (size_t) pduLength+6);
            (*association)->associatePDULength = pduLength+6;
          }
        }

        cond = parseAssociate(buffer, pduLength, &assoc);
        free(buffer);
        if (cond.bad()) return makeDcmnetSubCondition(DULC_ILLEGALPDU, OF_error, "DUL Illegal or ill-formed PDU", cond);

        OFStandard::strlcpy(service->respondingAPTitle, assoc.calledAPTitle, sizeof(service->respondingAPTitle));
        OFStandard::strlcpy(service->callingAPTitle, assoc.callingAPTitle, sizeof(service->callingAPTitle));
        OFStandard::strlcpy(service->applicationContextName, assoc.applicationContext.data, sizeof(service->applicationContextName));

        if ((service->acceptedPresentationContext = LST_Create()) == NULL) return EC_MemoryExhausted;

        prvCtx = (PRV_PRESENTATIONCONTEXTITEM*)LST_Head(&assoc.presentationContextList);
        if (prvCtx != NULL)
            (void) LST_Position(&assoc.presentationContextList, (LST_NODE*)prvCtx);
        while (prvCtx != NULL) {
            userPresentationCtx = (DUL_PRESENTATIONCONTEXT*)malloc(sizeof(DUL_PRESENTATIONCONTEXT));
            if (userPresentationCtx == NULL) return EC_MemoryExhausted;

            (void) memset(userPresentationCtx, 0, sizeof(DUL_PRESENTATIONCONTEXT));
            userPresentationCtx->result = prvCtx->result;
            userPresentationCtx->presentationContextID = prvCtx->contextID;
            userPresentationCtx->proposedTransferSyntax = NULL;
            requestedPresentationCtx = findPresentationCtx(
                 &service->requestedPresentationContext, prvCtx->contextID);
            if (requestedPresentationCtx != NULL) {
                OFStandard::strlcpy(userPresentationCtx->abstractSyntax,
                    requestedPresentationCtx->abstractSyntax,
                    sizeof(userPresentationCtx->abstractSyntax));
                userPresentationCtx->proposedSCRole =
                    requestedPresentationCtx->proposedSCRole;
            }
            userPresentationCtx->acceptedSCRole = DUL_SC_ROLE_DEFAULT;
            scuscpRole = findSCUSCPRole(&assoc.userInfo.SCUSCPRoleList,
                                        userPresentationCtx->abstractSyntax);
            if (scuscpRole != NULL) {
                if ((scuscpRole->SCURole == 0) && (scuscpRole->SCPRole == 0))
                    userPresentationCtx->acceptedSCRole = DUL_SC_ROLE_NONE;
                else if ((scuscpRole->SCURole == 1) && (scuscpRole->SCPRole == 1))
                    userPresentationCtx->acceptedSCRole = DUL_SC_ROLE_SCUSCP;
                else if (scuscpRole->SCURole == 1)
                    userPresentationCtx->acceptedSCRole = DUL_SC_ROLE_SCU;
                else  // SCPRole == 1
                    userPresentationCtx->acceptedSCRole = DUL_SC_ROLE_SCP;
            }
            if (prvCtx->transferSyntaxList == NULL)
            {
              char buf1[256];
              sprintf(buf1, "DUL Peer supplied illegal number of transfer syntaxes (%d)", 0);
              free(userPresentationCtx);
              return makeDcmnetCondition(DULC_PEERILLEGALXFERSYNTAXCOUNT, OF_error, buf1);
            }

            if ((prvCtx->result == DUL_PRESENTATION_ACCEPT) && (LST_Count(&prvCtx->transferSyntaxList) != 1))
            {
              char buf2[256];
              sprintf(buf2, "DUL Peer supplied illegal number of transfer syntaxes (%ld)", LST_Count(&prvCtx->transferSyntaxList));
              free(userPresentationCtx);
              return makeDcmnetCondition(DULC_PEERILLEGALXFERSYNTAXCOUNT, OF_error, buf2);
            }
            subItem = (DUL_SUBITEM*)LST_Head(&prvCtx->transferSyntaxList);
            if (subItem != NULL)
                OFStandard::strlcpy(userPresentationCtx->acceptedTransferSyntax,
                              subItem->data, sizeof(userPresentationCtx->acceptedTransferSyntax));
            LST_Enqueue(&service->acceptedPresentationContext, (LST_NODE*)userPresentationCtx);

            prvCtx = (PRV_PRESENTATIONCONTEXTITEM*)LST_Next(&assoc.presentationContextList);

        }

        /* extended negotiation */
        if (assoc.userInfo.extNegList != NULL) {
            service->acceptedExtNegList = new SOPClassExtendedNegotiationSubItemList;
            if (service->acceptedExtNegList == NULL)  return EC_MemoryExhausted;
            appendList(*assoc.userInfo.extNegList, *service->acceptedExtNegList);
        }

        /* user identity negotiation */
        if (assoc.userInfo.usrIdent != NULL) {
          service->ackUserIdentNeg =
            new UserIdentityNegotiationSubItemAC( *(OFstatic_cast(UserIdentityNegotiationSubItemAC*, assoc.userInfo.usrIdent)));
          if (service->ackUserIdentNeg == NULL)  return EC_MemoryExhausted;

        }

        destroyPresentationContextList(&assoc.presentationContextList);
        destroyUserInformationLists(&assoc.userInfo);
        service->peerMaxPDU = assoc.userInfo.maxLength.maxLength;
        (*association)->maxPDV = assoc.userInfo.maxLength.maxLength;
        (*association)->maxPDVAcceptor =
            assoc.userInfo.maxLength.maxLength;
        OFStandard::strlcpy(service->calledImplementationClassUID,
               assoc.userInfo.implementationClassUID.data, DICOM_UI_LENGTH + 1);
        OFStandard::strlcpy(service->calledImplementationVersionName,
               assoc.userInfo.implementationVersionName.data, 16 + 1);

        (*association)->associationState = DUL_ASSOC_ESTABLISHED;
        (*association)->protocolState = nextState;
        return EC_Normal;
    }
    return DUL_UNEXPECTEDPDU;
}