void IDicomServerHandler.OnReceiveRequestMessage(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomMessage message) { Task.Factory.StartNew(delegate { try { IDicomScp <TContext> scp = _extensionList[presentationId]; bool ok = scp.OnReceiveRequest(server, association, presentationId, message); if (!ok) { LogAdapter.Logger.Error("Unexpected error processing message of type {0}. Aborting association.", message.SopClass.Name); server.SendAssociateAbort(DicomAbortSource.ServiceProvider, DicomAbortReason.NotSpecified); } else if (_complete != null) { // Only save C-STORE-RQ messages if (message.CommandField == DicomCommandField.CStoreRequest) { _instances.Add(new StorageInstance(message)); } } } catch (Exception x) { LogAdapter.Logger.Error("Unexpected exception in OnReceiveImageLevelQuery."); server.SendAssociateAbort(DicomAbortSource.ServiceProvider, DicomAbortReason.NotSpecified); } }); }
void IDicomServerHandler.OnReceiveDimseCommand(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomAttributeCollection command) { IDicomScp <TContext> scp = _extensionList[presentationId]; scp.ReceiveMessageAsFileStream(server, association, presentationId, new DicomMessage(command, new DicomAttributeCollection())); }
IDicomFilestreamHandler IDicomServerHandler.OnStartFilestream(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomMessage message) { IDicomScp <TContext> scp = _extensionList[presentationId]; if (message.CommandField == DicomCommandField.CStoreRequest) { _instances.Add(new StorageInstance(message)); } return(scp.OnStartFilestream(server, association, presentationId, message)); }
/// <summary> /// Constructor. /// </summary> /// <remarks> /// The constructor creates a dictionary of each presentation context negotiated for the /// association, and the plugin that will handle it. This is used later when incoming request /// messages are processed. /// </remarks> /// <param name="server">The server.</param> /// <param name="parameters">Association parameters for the negotiated association.</param> /// <param name="userParms">User parameters to be passed to the plugins called by the class.</param> /// <param name="verifier">Delegate to call to verify an association before its accepted.</param> /// <param name="complete">Delegate to call when the association is closed/complete. Can be null.</param> public DicomScpHandler(DicomServer server, ServerAssociationParameters parameters, TContext userParms, DicomScp <TContext> .AssociationVerifyCallback verifier, DicomScp <TContext> .AssociationComplete complete) { _context = userParms; _verifier = verifier; _complete = complete; DicomScpExtensionPoint <TContext> ep = new DicomScpExtensionPoint <TContext>(); object[] scps = ep.CreateExtensions(); // First set the user parms for each of the extensions before we do anything with them. foreach (object obj in scps) { IDicomScp <TContext> scp = obj as IDicomScp <TContext>; scp.SetContext(_context); } // Now, create a dictionary with the extension to be used for each presentation context. foreach (byte pcid in parameters.GetPresentationContextIDs()) { if (parameters.GetPresentationContextResult(pcid) == DicomPresContextResult.Accept) { SopClass acceptedSop = SopClass.GetSopClass(parameters.GetAbstractSyntax(pcid).UID); TransferSyntax acceptedSyntax = parameters.GetAcceptedTransferSyntax(pcid); foreach (object obj in scps) { IDicomScp <TContext> scp = obj as IDicomScp <TContext>; IList <SupportedSop> sops = scp.GetSupportedSopClasses(); foreach (SupportedSop sop in sops) { if (sop.SopClass.Equals(acceptedSop)) { if (sop.SyntaxList.Contains(acceptedSyntax)) { if (!_extensionList.ContainsKey(pcid)) { _extensionList.Add(pcid, scp); break; } else { Platform.Log(LogLevel.Error, "SOP Class {0} supported by more than one extension", sop.SopClass.Name); } } } } } } } _statsRecorder = new AssociationStatisticsRecorder(server); }
/// <summary> /// Constructor. /// </summary> /// <remarks> /// The constructor creates a dictionary of each presentation context negotiated for the /// association, and the plugin that will handle it. This is used later when incoming request /// messages are processed. /// </remarks> /// <param name="server">The server.</param> /// <param name="parameters">Association parameters for the negotiated association.</param> /// <param name="userParms">User parameters to be passed to the plugins called by the class.</param> /// <param name="verifier">Delegate to call to verify an association before its accepted.</param> /// <param name="complete">Delegate to call when the association is closed/complete. Can be null.</param> public DicomScpHandler(DicomServer server, ServerAssociationParameters parameters, TContext userParms, DicomScp <TContext> .AssociationVerifyCallback verifier, DicomScp <TContext> .AssociationComplete complete) { _context = userParms; _verifier = verifier; _complete = complete; List <IDicomScp <TContext> > scps = Platform.Instance.CompositionContainer.GetExportedValues <IDicomScp <TContext> >().Select(scp => scp). ToList(); // First set the user parms for each of the extensions before we do anything with them. foreach (object obj in scps) { IDicomScp <TContext> scp = obj as IDicomScp <TContext>; scp.SetContext(_context); } // Now, create a dictionary with the extension to be used for each presentation context. foreach (byte pcid in parameters.GetPresentationContextIDs()) { if (parameters.GetPresentationContextResult(pcid) == DicomPresContextResult.Accept) { SopClass acceptedSop = SopClass.GetSopClass(parameters.GetAbstractSyntax(pcid).UID); TransferSyntax acceptedSyntax = parameters.GetAcceptedTransferSyntax(pcid); foreach (object obj in scps) { IDicomScp <TContext> scp = obj as IDicomScp <TContext>; IList <SupportedSop> sops = scp.GetSupportedSopClasses(); foreach (SupportedSop sop in sops) { if (sop.SopClass.Equals(acceptedSop)) { if (sop.SyntaxList.Contains(acceptedSyntax)) { if (!_extensionList.ContainsKey(pcid)) { _extensionList.Add(pcid, scp); break; } else { LogAdapter.Logger.ErrorWithFormat("SOP Class {0} supported by more than one extension", sop.SopClass.Name); } } } } } } } }
void IDicomServerHandler.OnReceiveAssociateRequest(DicomServer server, ServerAssociationParameters association) { if (_verifier != null) { DicomRejectResult result; DicomRejectReason reason; bool verified = _verifier(_context, association, out result, out reason); if (verified == false) { server.SendAssociateReject(result, DicomRejectSource.ServiceUser, reason); LogAdapter.Logger.Info("Association rejected from {0} to {1}", association.CallingAE, association.CalledAE); return; } } // Let the extensions have its say on whether a presentation context is really acceptable. // bool atLeastOneAccepted = false; foreach (byte pcid in association.GetPresentationContextIDs()) { if (association.GetPresentationContextResult(pcid) == DicomPresContextResult.Accept) { IDicomScp <TContext> scp = _extensionList[pcid]; DicomPresContextResult res = scp.VerifyAssociation(association, pcid); if (res != DicomPresContextResult.Accept) { association.GetPresentationContext(pcid).ClearTransfers(); association.SetPresentationContextResult(pcid, res); } else { atLeastOneAccepted = true; } } } if (!atLeastOneAccepted) { LogAdapter.Logger.Info("None of the proposed presentation context is accepted. Rejecting association from {0} to {1}", association.CallingAE, association.CalledAE); server.SendAssociateReject(DicomRejectResult.Permanent, DicomRejectSource.ServiceUser, DicomRejectReason.NoReasonGiven); return; } server.SendAssociateAccept(association); // Optimization to speed query performance Task.Factory.StartNew(() => LogAdapter.Logger.Info("Received association:\r\n{0}", association.ToString())); }
void IDicomServerHandler.OnReceiveRequestMessage(DicomServer server, ServerAssociationParameters association, byte presentationID, DicomMessage message) { IDicomScp <TContext> scp = _extensionList[presentationID]; bool ok = scp.OnReceiveRequest(server, association, presentationID, message); if (!ok) { Platform.Log(LogLevel.Error, "Unexpected error processing message of type {0}. Aborting association.", message.SopClass.Name); server.SendAssociateAbort(DicomAbortSource.ServiceProvider, DicomAbortReason.NotSpecified); } else if (_complete != null) { // Only save C-STORE-RQ messages if (message.CommandField == DicomCommandField.CStoreRequest) { _instances.Add(new StorageInstance(message)); } } }
/// <summary> /// Create the list of presentation contexts for the DICOM SCP. /// </summary> /// <remarks> /// The method loads the DICOM Scp plugins, and then queries them /// to construct a list of presentation contexts that are supported. /// </remarks> private void CreatePresentationContexts() { DicomScpExtensionPoint <TContext> ep = new DicomScpExtensionPoint <TContext>(); object[] scps = ep.CreateExtensions(); foreach (object obj in scps) { IDicomScp <TContext> scp = obj as IDicomScp <TContext>; scp.SetContext(_context); IList <SupportedSop> sops = scp.GetSupportedSopClasses(); foreach (SupportedSop sop in sops) { byte pcid = _assocParameters.FindAbstractSyntax(sop.SopClass); if (pcid == 0) { pcid = _assocParameters.AddPresentationContext(sop.SopClass); } // Now add all the transfer syntaxes, if necessary foreach (TransferSyntax syntax in sop.SyntaxList) { // Check if the syntax is registered already if (0 == _assocParameters.FindAbstractSyntaxWithTransferSyntax(sop.SopClass, syntax)) { _assocParameters.AddTransferSyntax(pcid, syntax); } } } } // Sort the presentation contexts, and put them in the order that we prefer them. // Favor Explicit over Implicit transfer syntaxes, lossless compression over lossy // compression, and lossless compressed over uncompressed. foreach (DicomPresContext serverContext in _assocParameters.GetPresentationContexts()) { serverContext.SortTransfers(delegate(TransferSyntax s1, TransferSyntax s2) { if (s1.Equals(s2)) { return(0); } if (s1.ExplicitVr && !s2.ExplicitVr) { return(-1); } if (!s1.ExplicitVr && s2.ExplicitVr) { return(1); } if (s1.Encapsulated && s2.Encapsulated) { if (s1.LosslessCompressed == s2.LosslessCompressed) { return(0); } if (s1.LosslessCompressed && s2.LossyCompressed) { return(-1); } return(1); } if (s1.Encapsulated) { if (s1.LossyCompressed) { return(1); } return(-1); } if (s2.Encapsulated) { if (s2.LossyCompressed) { return(-1); } return(1); } return(0); } ); } }