private bool CheckNSetDataSetConformance(DicomServer server, ServerAssociationParameters association, byte presentationID, ModalityPerformedProcedureStepIod cachedMppsIod, ModalityPerformedProcedureStepIod receivedMppsIod, bool logFirstAnomalyOnly) { bool anomaly = false; string comments = ""; try { do { // We are not going to verify sop instance UID neither status - those 2 tests will be done in main processing. #region Character Set if (cachedMppsIod.SopCommon.SpecificCharacterSet != null) { if (receivedMppsIod.SopCommon.SpecificCharacterSet == null) { anomaly = true; comments += string.Format("Received MPPS Sop instance has no SpecificCharacterSet while it was cached with {0}.\n", cachedMppsIod.SopCommon.SpecificCharacterSet); if (logFirstAnomalyOnly) break; } if (cachedMppsIod.SopCommon.SpecificCharacterSet != receivedMppsIod.SopCommon.SpecificCharacterSet) { anomaly = true; comments += "Received MPPS Sop instance has a different SpecificCharacterSet from the one cached .\n"; if (logFirstAnomalyOnly) break; } } else { if (receivedMppsIod.SopCommon.SpecificCharacterSet != null) { anomaly = true; comments += "Received MPPS Sop instance has a SpecificCharacterSet while it was cached without.\n"; if (logFirstAnomalyOnly) break; } } #endregion } while (false); if (anomaly) { Platform.Log(LogLevel.Warn, "Invalid Modality Performed Procedute Step SOP N-SET data received from {0} .", server.AssociationParams.CallingAE); Platform.Log(LogLevel.Warn, "-- Details : {0}," + comments); } return anomaly; } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Exception Occured while checking the the SOPN-SET data received from {0} .", server.AssociationParams.CallingAE); anomaly = true; return anomaly; } }
private static void CacheMppsEntity(ServerAssociationParameters association, string key, ModalityPerformedProcedureStepIod ie, out bool alreadyCached) { alreadyCached = false; ListDictionary mppsAssociationList; if (_mppsCache.TryGetValue(association.GetHashCode(), out mppsAssociationList)) { if (mppsAssociationList.Contains(key)) alreadyCached = true; else mppsAssociationList.Add(key, ie); } else { ListDictionary newList = new ListDictionary(); newList.Add(key, ie); _mppsCache.Add(association.GetHashCode(), newList); } }
private bool CheckNCreateDataSetConformance(DicomServer server, ServerAssociationParameters association, byte presentationID, ModalityPerformedProcedureStepIod mppsIod, bool logFirstAnomalyOnly) { bool anomaly = false; string comments = ""; try { do { #region Checking Type 1 Attributes (existance and values) if (mppsIod.PerformedProcedureStepRelationship == null) { anomaly = true; comments += "Performed Procedure Step Relationship Sequence Absent.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepRelationship.ScheduledStepAttributesSequenceList == null) { anomaly = true; comments += "Scheduled Step Attributes Sequence Absent.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepRelationship.ScheduledStepAttributesSequenceList.FirstSequenceItem == null) { anomaly = true; comments += "Scheduled Step Attributes Sequence Empty.\n"; if (logFirstAnomalyOnly) break; } if (string.IsNullOrEmpty(mppsIod.PerformedProcedureStepRelationship. ScheduledStepAttributesSequenceList. FirstSequenceItem.StudyInstanceUid.Trim())) {// we can add more control here (to check the id root for exmaple). anomaly = true; comments += "Invalid Study Instance Uid.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepInformation == null) { anomaly = true; comments += "Performed Procedure Step Information module missing.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepId == null) { anomaly = true; comments += "Performed Procedure StepId missing.\n"; if (logFirstAnomalyOnly) break; } if (string.IsNullOrEmpty(mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepId)) { anomaly = true; comments += "Performed Procedure Step Information attribute invalid value.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepInformation.PerformedStationAeTitle == null) { anomaly = true; comments += "Performed Station Ae Title missing.\n"; if (logFirstAnomalyOnly) break; } if (string.IsNullOrEmpty(mppsIod.PerformedProcedureStepInformation.PerformedStationAeTitle)) { anomaly = true; comments += "Performed Station Ae Title attribute invalid value.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepStartDate == null) { anomaly = true; comments += "Performed Procedure Step Start Date missing.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.DicomAttributeProvider[DicomTags.PerformedProcedureStepStartDate].GetDateTime(0).HasValue) { anomaly = true; comments += "Performed Procedure Step Start Date invalid value.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.DicomAttributeProvider[DicomTags.PerformedProcedureStepStartTime] == null) { anomaly = true; comments += "Performed Procedure Step Start Time missing.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.DicomAttributeProvider[DicomTags.PerformedProcedureStepStartTime].GetDateTime(0).HasValue) { anomaly = true; comments += "Performed Procedure Step Start Time invalid value.\n"; if (logFirstAnomalyOnly) break; } //checking only the status existance if (mppsIod.DicomAttributeProvider[DicomTags.PerformedProcedureStepStatus]== null) { anomaly = true; comments += "Performed Procedure Step Status Missing.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.DicomAttributeProvider[DicomTags.Modality] == null) { anomaly = true; comments += "Modlity Missing.\n"; if (logFirstAnomalyOnly) break; } if (mppsIod.DicomAttributeProvider[DicomTags.Modality].GetString(0,"") =="") { anomaly = true; comments += "Modlity invalid value.\n"; if (logFirstAnomalyOnly) break; } #endregion #region Check Type 2 attributes // TODO to check all other attributes. if (mppsIod.PerformedProcedureStepRelationship. ScheduledStepAttributesSequenceList. FirstSequenceItem.DicomSequenceItem[DicomTags.ReferencedStudySequence] == null) {// we can add more control here anomaly = true; comments += "Referenced Study Sequence Abscent.\n"; if (logFirstAnomalyOnly) break; } //TODO : ReferencedStudySequence FirstItem checking { } if (mppsIod.PerformedProcedureStepRelationship.PatientsName == null) { anomaly = true; comments += "Referenced Study Sequence Abscent.\n"; if (logFirstAnomalyOnly) break; } //etc.. #endregion } while (false); if (anomaly) { Platform.Log(LogLevel.Warn, "Invalid Modality Performed Procedute Step SOP N-CREATE data received from {0} .", server.AssociationParams.CallingAE); Platform.Log(LogLevel.Warn, "-- Details : {0}," + comments); } return anomaly; } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "Exception Occured while checking the mppsIod", mppsIod); anomaly = true; return anomaly; } }
void IDicomServerHandler.OnReceiveRequestMessage(DicomServer server, ServerAssociationParameters association, byte presentationID, DicomMessage message) { //_sessionDebug.SetAssociationDumpString(association); //_sessionDebug._request = message.Dump(); #region CEcho request if (message.CommandField == DicomCommandField.CEchoRequest) { server.SendCEchoResponse(presentationID, message.MessageId, DicomStatuses.Success); Platform.Log(LogLevel.Info, "Received ECHO-RQ message from {0}.", association.CallingAE); return; } #endregion #region MPPS NCreate Request if (message.CommandField == DicomCommandField.NCreateRequest) { // june -1st-2009 : // Unlike the "ModalityWorklistIod" class, the 'partially' implemented ModalityPerformedProcedureStepIod class could // be usefull here. ModalityPerformedProcedureStepIod mppsIod = new ModalityPerformedProcedureStepIod(message.DataSet); Platform.Log(LogLevel.Info, "Message Dumped :\n" + message.Dump("", DicomDumpOptions.KeepGroupLengthElements)); // checking message for error and anomalies bool conform = CheckNCreateDataSetConformance(server, association, presentationID, mppsIod, true); if (!conform) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.InvalidAttributeValue); Platform.Log(LogLevel.Error, "Sending Invalid Attributes Response."); return; } // wrong status if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepStatus != ClearCanvas.Dicom.Iod.Modules.PerformedProcedureStepStatus.InProgress) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.InvalidAttributeValue); Platform.Log(LogLevel.Error, "Recieved N-Create Request with bad status."); return; } // pps already in cache (duplicated step) string cacheKeyId = message.DataSet[DicomTags.AffectedSopInstanceUid].GetString(0, string.Empty); bool alreadyCached; MPPSScp.CacheMppsEntity(association, cacheKeyId, mppsIod, out alreadyCached); if (alreadyCached) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.DuplicateSOPInstance); Platform.Log(LogLevel.Error, "Recieved duplicated N-Create Request."); return; } if (!ProcessNCreateRequest(server, presentationID, message)) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.ProcessingFailure); Platform.Log(LogLevel.Error, "Sending Processing due to NCreate request Failure."); return; } server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.Success); return; } #endregion #region MPPS NSet Request if (message.CommandField == DicomCommandField.NSetRequest) { // june -1st-2009 : // Unlike the "ModalityWorklistIod" class, the ModalityPerformedProcedureStepIod is fully implemented // we can use it here. ModalityPerformedProcedureStepIod mppsIod = new ModalityPerformedProcedureStepIod(message.DataSet); Platform.Log(LogLevel.Info, "Message Dumped :\n" + message.Dump("", DicomDumpOptions.KeepGroupLengthElements)); // check if pps already in cache (duplicated step) string cacheKeyId = message.DataSet[DicomTags.AffectedSopInstanceUid].GetString(0, string.Empty); if (!IsMppsEntitycached(association, cacheKeyId)) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.NoSuchObjectInstance); Platform.Log(LogLevel.Error, "Received Unknown NSset SOP."); return; } // status diffrent from in progress if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepStatus == ClearCanvas.Dicom.Iod.Modules.PerformedProcedureStepStatus.InProgress) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.InvalidAttributeValue); Platform.Log(LogLevel.Error, "Recieved N-Set Request with In Progress status."); return; } // checking the received mppsiod against cached one ModalityPerformedProcedureStepIod cachedMppsIod = GetCachedMppsIod(association, cacheKeyId); //assuming cachedMppsIod not null. bool conform = CheckNSetDataSetConformance(server, association, presentationID, cachedMppsIod, mppsIod, true); if (!conform) { server.SendNCreateResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.InvalidAttributeValue); Platform.Log(LogLevel.Error, "Sending Failure Response."); return; } string studyInstanceUID = mppsIod. PerformedProcedureStepRelationship. DicomAttributeProvider[DicomTags.StudyInstanceUid]. GetString(0,""); XmlElement performedSeriesSQ = GenerateXmlForPerformedSeriesSQ(message,studyInstanceUID); bool success = true; if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepStatus == ClearCanvas.Dicom.Iod.Modules.PerformedProcedureStepStatus.Completed) { success = ProcessNSetRequestForCompleted(server, presentationID, message, performedSeriesSQ); } if (mppsIod.PerformedProcedureStepInformation.PerformedProcedureStepStatus == ClearCanvas.Dicom.Iod.Modules.PerformedProcedureStepStatus.Discontinued) { success = ProcessNSetRequestForDiscontinued(server, presentationID, message, performedSeriesSQ); } if (success) server.SendNSetResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.Success); else server.SendNSetResponse(presentationID, message.MessageId, new DicomMessage(), DicomStatuses.ProcessingFailure); MPPSScp.RemoveMppsEntityFromCache(association, cacheKeyId); return; } #endregion //ignore all unsupported request server.SendAssociateAbort(DicomAbortSource.ServiceProvider, DicomAbortReason.UnexpectedPDU); Platform.Log(LogLevel.Info, "Unexpected Command. Send Associate Abort message from server to {0}.", association.CallingAE); return; }