LAUREL BRIDGE

LaurelBridge.DCFExamples.MPPSSCP Namespace

DICOM Connectivity Framework V3.4
The MPPSSCP example demonstrates how to use DCF to implement a modality performed procedure step service class provider.
Classes

  ClassDescription
Public classProgram
Basic modality performed procedure step service class provider example should be run with MPPSSCU.
Public classProgramModalityPerformedProcedureStepSCP
An MMPS server that extends the AssociationListenerAdapter and implements the IAssociationConfigPolicyManager.
Remarks

Supported OS Platforms:

  • Windows - .Net Framework 4.7.2 64-bit and 32-bit
  • Windows - .Net Core 2.1 64-bit and 32-bit
  • Linux - .Net Core 2.1 64-bit

Examples

MPPSSCP Sample Code
public class Program
{
    private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

    /// <summary>
    /// Main entry point for MPPSSCP.
    /// </summary>
    [STAThread]
    public static void Main()
    {
        try
        {
            IList<AllowedPresentationContext> allowed = new List<AllowedPresentationContext>();
            allowed.Add(new AllowedPresentationContext(Uids.ModalityPerformedProcedureStepSOPClass,
                new[] { Uids.TransferSyntax.ExplicitVRLittleEndian, Uids.TransferSyntax.ImplicitVRLittleEndian }));
            ModalityPerformedProcedureStepSCP scp = new ModalityPerformedProcedureStepSCP(allowed);

            AssociationManager mgr = new AssociationManager();
            mgr.ServerTcpPort = 10104;
            mgr.AssociationConfigPolicyMgr = scp;
            mgr.AddAssociationListener(scp);

            // AssociationManager.run() blocks, so start him listening for connections on a separate thread
            Thread t = new Thread(mgr.Run);
            t.Start();
            if (!mgr.WaitForRunning(2000))
            {
                throw new TimeoutException("AssociationManager did not start in an acceptable amount of time");
            }

            Console.WriteLine("listening on 10104...");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception caught during execution: {0}", e);
            Environment.ExitCode = 1;
        }
    }

    /// <summary>
    /// An MMPS server that extends the <see cref="AssociationListenerAdapter"/> and implements the
    /// <see cref="IAssociationConfigPolicyManager"/>.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The <see cref="IAssociationConfigPolicyManager"/> allows us to get a callback to set our
    /// session settings for the association.
    /// </para>
    /// <para>
    /// This class overrides the <see cref="AssociationListenerAdapter.BeginAssociation"/> method
    /// to install a service class provider which negotiates the association, and delegates service
    /// class specific messages back to us for processing.  Other <see cref="AssociationListenerAdapter"/>
    /// methods may be overridden to implement additional functionality.
    /// </para>
    /// </remarks>
    public class ModalityPerformedProcedureStepSCP : AssociationListenerAdapter, IAssociationConfigPolicyManager
    {
        private readonly IList<AllowedPresentationContext> _presentationContexts;

        /// <summary>
        /// Constructs a Modality Performed Procedure Step SCP with the specified set of allowed presentation contexts.
        /// </summary>
        /// <param name="allowedPresentationContexts">The list of presentation contexts that will be allowed.</param>
        public ModalityPerformedProcedureStepSCP(IList<AllowedPresentationContext> allowedPresentationContexts)
        {
            _presentationContexts = allowedPresentationContexts;
        }

        #region IAssociationConfigPolicyManager Overrides
        /// <summary>
        /// Returns a DicomSessionSettings object to be used for the association.
        /// </summary>
        /// <param name="assoc">The AssociationAcceptor handling the association</param>
        /// <returns>The DicomSessionSettings for the given association.</returns>
        public DicomSessionSettings GetSessionSettings(AssociationAcceptor assoc)
        {
            return new DicomSessionSettings { SessionName = String.Format("MPPSSCP:{0}", assoc.DicomSocket.ConnectionID) };
        }
        #endregion

        #region AssociationListenerAdapter Overrides
        /// <summary>
        /// Creates the ModalityPerformedProcedureStepSCP object to handle the association that caused this method to be called.
        /// </summary>
        /// <param name="assoc">The AssociationAcceptor for the given association</param>
        public override void BeginAssociation(AssociationAcceptor assoc)
        {
            assoc.RegisterServiceClassProvider(new DCF.Dicom.ProcedureStep.MPPSSCP(assoc, _presentationContexts, NCreate, NSet));
        }
        #endregion

        #region Helper Delegates
        /// <summary>
        /// NCreate response handler to process the incoming NCreateRequest message. Once finished, 
        /// the NCreate response DIMSE message is returned to be sent to the SCP.
        /// </summary>
        /// <param name="acceptor">The association acceptor for this association.</param>
        /// <param name="request">The incoming NCreate request.</param>
        /// <returns>The NCreate response DIMSE message.</returns>
        private NCreateResponse NCreate(AssociationAcceptor acceptor, NCreateRequest request)
        {
            Logger.InfoFormat("Incoming NCreate Request:{0}{1}", Environment.NewLine, request);
            NCreateResponse rsp = new NCreateResponse(request);

            // TODO: insert code to create/store the procedure.
            rsp.Status = DimseStatus.DIMSE_SUCCESS;
            Logger.InfoFormat("Outgoing NCreate Response:{0}{1}", Environment.NewLine, rsp);
            return rsp;
        }

        /// <summary>
        /// NSet response handler to process the incoming NSetRequest message. Once finished,
        /// the NSet response DIMSE message is returned to be sent to the SCP.
        /// </summary>
        /// <param name="acceptor">The association acceptor for this association.</param>
        /// <param name="request">The incoming NSet request.</param>
        /// <returns>The NSet response DIMSE message.</returns>
        private NSetResponse NSet(AssociationAcceptor acceptor, NSetRequest request)
        {
            Logger.InfoFormat("Incoming NSet Request:{0}{1}", Environment.NewLine, request);
            NSetResponse rsp = new NSetResponse(request);

            // TODO: insert code to update an already existing procedure.
            rsp.Status = DimseStatus.DIMSE_SUCCESS;
            Logger.InfoFormat("Outgoing NSet Response:{0}{1}", Environment.NewLine, rsp);
            return rsp;
        }
        #endregion
    }
}