private void SendNextMessage() { while (true) { DicomMessage msg; lock (_lock) { if (_msgQueue.Count == 0) { if (_pending.Count == 0) OnSendQueueEmpty(); return; } if (_sending) return; if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) return; _sending = true; msg = _msgQueue.Dequeue(); } if (msg is DicomRequest) _pending.Add(msg as DicomRequest); DicomPresentationContext pc = null; if (msg is DicomCStoreRequest) { pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax); if (pc == null) pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } else { pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } if (pc == null) { pc = msg.PresentationContext; } if (pc == null) { _pending.Remove(msg as DicomRequest); try { if (msg is DicomCStoreRequest) (msg as DicomCStoreRequest).PostResponse( this, new DicomCStoreResponse(msg as DicomCStoreRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCEchoRequest) (msg as DicomCEchoRequest).PostResponse( this, new DicomCEchoResponse(msg as DicomCEchoRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCFindRequest) (msg as DicomCFindRequest).PostResponse( this, new DicomCFindResponse(msg as DicomCFindRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCMoveRequest) (msg as DicomCMoveRequest).PostResponse( this, new DicomCMoveResponse( msg as DicomCMoveRequest, DicomStatus.SOPClassNotSupported)); //TODO: add N services } catch { } Logger.Error( "No accepted presentation context found for abstract syntax: {sopClassUid}", msg.SOPClassUID); } else { var dimse = new Dimse { Message = msg, PresentationContext = pc }; // force calculation of command group length as required by standard msg.Command.RecalculateGroupLengths(); if (msg.HasDataset) { // remove group lengths as recommended in PS 3.5 7.2 // // 2. It is recommended that Group Length elements be removed during storage or transfer // in order to avoid the risk of inconsistencies arising during coercion of data // element values and changes in transfer syntax. msg.Dataset.RemoveGroupLengths(); if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax) msg.Dataset = msg.Dataset.ChangeTransferSyntax(dimse.PresentationContext.AcceptedTransferSyntax); } Logger.Info("{logId} -> {dicomMessage}", LogID, msg.ToString(Options.LogDimseDatasets)); try { dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength); var writer = new DicomWriter( DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(msg.Command); dimse.Walker.Walk(writer); if (dimse.Message.HasDataset) { dimse.Stream.IsCommand = false; writer = new DicomWriter( dimse.PresentationContext.AcceptedTransferSyntax, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(dimse.Message.Dataset); dimse.Walker.Walk(writer); } } catch (Exception e) { Logger.Error("Exception sending DIMSE: {@error}", e); } finally { dimse.Stream.Flush(true).Wait(); dimse.Stream.Dispose(); } } lock (_lock) _sending = false; } }
private void SendNextMessage() { DicomMessage msg; lock (_lock) { if (_msgQueue.Count == 0) { if (_pending.Count == 0) { OnSendQueueEmpty(); } return; } if (_sending) { return; } if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) { return; } _sending = true; msg = _msgQueue.Dequeue(); } if (msg is DicomRequest) { _pending.Add(msg as DicomRequest); } DicomPresentationContext pc = null; if (msg is DicomCStoreRequest) { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax); if (pc == null) { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } } else { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } if (pc == null) { pc = msg.PresentationContext; } if (pc == null) { _pending.Remove(msg as DicomRequest); try { if (msg is DicomCStoreRequest) { (msg as DicomCStoreRequest).PostResponse(this, new DicomCStoreResponse(msg as DicomCStoreRequest, DicomStatus.SOPClassNotSupported)); } else if (msg is DicomCEchoRequest) { (msg as DicomCEchoRequest).PostResponse(this, new DicomCEchoResponse(msg as DicomCEchoRequest, DicomStatus.SOPClassNotSupported)); } else if (msg is DicomCFindRequest) { (msg as DicomCFindRequest).PostResponse(this, new DicomCFindResponse(msg as DicomCFindRequest, DicomStatus.SOPClassNotSupported)); } else if (msg is DicomCMoveRequest) { (msg as DicomCMoveRequest).PostResponse(this, new DicomCMoveResponse(msg as DicomCMoveRequest, DicomStatus.SOPClassNotSupported)); } //TODO: add N services } catch { } Logger.Error("No accepted presentation context found for abstract syntax: {0}", msg.SOPClassUID); lock (_lock) _sending = false; SendNextMessage(); return; } var dimse = new Dimse(); dimse.Message = msg; dimse.PresentationContext = pc; // force calculation of command group length as required by standard msg.Command.RecalculateGroupLengths(); if (msg.HasDataset) { // remove group lengths as recommended in PS 3.5 7.2 // // 2. It is recommended that Group Length elements be removed during storage or transfer // in order to avoid the risk of inconsistencies arising during coercion of data // element values and changes in transfer syntax. msg.Dataset.RemoveGroupLengths(); if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax) { msg.Dataset = msg.Dataset.ChangeTransferSyntax(dimse.PresentationContext.AcceptedTransferSyntax); } } Logger.Info("{0} -> {1}", LogID, msg.ToString(Options.LogDimseDatasets)); dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength); var writer = new DicomWriter(DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(msg.Command); if (dimse.Message.HasDataset) { dimse.Walker.BeginWalk(writer, OnEndSendCommand, dimse); } else { dimse.Walker.BeginWalk(writer, OnEndSendMessage, dimse); } }
private void SendNextMessage() { DicomMessage msg; lock (_lock) { if (_msgQueue.Count == 0) { if (_pending.Count == 0) { OnSendQueueEmpty(); } return; } if (_sending) { return; } if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) { return; } _sending = true; msg = _msgQueue.Dequeue(); } Logger.Log(LogLevel.Info, "{0} -> {1}", LogID, msg); if (msg is DicomRequest) { _pending.Add(msg as DicomRequest); } DicomPresentationContext pc = null; if (msg is DicomCStoreRequest) { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.AffectedSOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax); if (pc == null) { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.AffectedSOPClassUID); } } else { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.AffectedSOPClassUID); } if (pc == null) { throw new DicomNetworkException("No accepted presentation context found for abstract syntax: {0}", msg.AffectedSOPClassUID); } var dimse = new Dimse(); dimse.Message = msg; dimse.PresentationContext = pc; dimse.Stream = new PDataTFStream(this, pc.ID, (int)Association.MaximumPDULength); var writer = new DicomWriter(DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(msg.Command); dimse.Walker.BeginWalk(writer, OnEndSendCommand, dimse); }
private void SendNextMessage() { DicomMessage msg; lock (_lock) { if (_msgQueue.Count == 0) { if (_pending.Count == 0) OnSendQueueEmpty(); return; } if (_sending) return; if (Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) return; _sending = true; msg = _msgQueue.Dequeue(); } if (msg is DicomRequest) _pending.Add(msg as DicomRequest); DicomPresentationContext pc = null; if (msg is DicomCStoreRequest) { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax); if (pc == null) pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } else { pc = Association.PresentationContexts.FirstOrDefault(x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } if (pc == null) { Logger.Error("No accepted presentation context found for abstract syntax: {0}", msg.SOPClassUID); lock (_lock) _sending = false; SendNextMessage(); return; } var dimse = new Dimse(); dimse.Message = msg; dimse.PresentationContext = pc; // force calculation of command group length as required by standard msg.Command.RecalculateGroupLengths(); if (msg.HasDataset) { // remove group lengths as recommended in PS 3.5 7.2 // // 2. It is recommended that Group Length elements be removed during storage or transfer // in order to avoid the risk of inconsistencies arising during coercion of data // element values and changes in transfer syntax. msg.Dataset.RemoveGroupLengths(); if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax) msg.Dataset = msg.Dataset.ChangeTransferSyntax(dimse.PresentationContext.AcceptedTransferSyntax); } Logger.Info("{0} -> {1}", LogID, msg.ToString(Options.LogDimseDatasets)); dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength); var writer = new DicomWriter(DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(msg.Command); if (dimse.Message.HasDataset) dimse.Walker.BeginWalk(writer, OnEndSendCommand, dimse); else dimse.Walker.BeginWalk(writer, OnEndSendMessage, dimse); }
internal void FireReceived(Dimse dimse) { if (Logger.IsInfoEnabled) { Logger.Info("received " + dimse); } if (assocListener != null) { assocListener.Received(assoc, dimse); } }
private void SendNextMessage() { while (true) { DicomMessage msg; lock (_lock) { if (_sending) { return; } if (_msgQueue.Count == 0) { if (_pending.Count == 0) OnSendQueueEmpty(); return; } if (!Options.IgnoreAsyncOps && Association.MaxAsyncOpsInvoked > 0 && _pending.Count >= Association.MaxAsyncOpsInvoked) { Logger.Debug("Cannot send messages since pending: {pending} would exceed max async ops invoked: {invoked}", _pending.Count, Association.MaxAsyncOpsInvoked); return; // Cannot easily recover from this unwanted state, so better to throw. throw new DicomNetworkException( "Cannot send messages since pending: {0} would exceed max async ops invoked: {1}", _pending.Count, Association.MaxAsyncOpsInvoked); } _sending = true; msg = _msgQueue.Dequeue(); if (msg is DicomRequest) { _pending.Add(msg as DicomRequest); } } DicomPresentationContext pc = null; if (msg is DicomCStoreRequest) { pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID && x.AcceptedTransferSyntax == (msg as DicomCStoreRequest).TransferSyntax); if (pc == null) pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } else if (msg is DicomResponse) { //the presentation context should be set already from the request object pc = msg.PresentationContext; //fail safe if no presentation context is already assigned to the response (is this going to happen) if (pc == null) { pc = this.Association.PresentationContexts.FirstOrDefault<DicomPresentationContext>(x => (x.Result == DicomPresentationContextResult.Accept) && (x.AbstractSyntax == msg.SOPClassUID)); } } else { pc = Association.PresentationContexts.FirstOrDefault( x => x.Result == DicomPresentationContextResult.Accept && x.AbstractSyntax == msg.SOPClassUID); } if (pc == null) { pc = msg.PresentationContext; } if (pc == null) { lock (_lock) { _pending.Remove(msg as DicomRequest); } try { if (msg is DicomCStoreRequest) (msg as DicomCStoreRequest).PostResponse( this, new DicomCStoreResponse(msg as DicomCStoreRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCEchoRequest) (msg as DicomCEchoRequest).PostResponse( this, new DicomCEchoResponse(msg as DicomCEchoRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCFindRequest) (msg as DicomCFindRequest).PostResponse( this, new DicomCFindResponse( msg as DicomCFindRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCGetRequest) (msg as DicomCGetRequest).PostResponse( this, new DicomCGetResponse( msg as DicomCGetRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomCMoveRequest) (msg as DicomCMoveRequest).PostResponse( this, new DicomCMoveResponse( msg as DicomCMoveRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNActionRequest) (msg as DicomNActionRequest).PostResponse( this, new DicomNActionResponse( msg as DicomNActionRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNCreateRequest) (msg as DicomNCreateRequest).PostResponse( this, new DicomNCreateResponse( msg as DicomNCreateRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNDeleteRequest) (msg as DicomNDeleteRequest).PostResponse( this, new DicomNDeleteResponse( msg as DicomNDeleteRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNEventReportRequest) (msg as DicomNEventReportRequest).PostResponse( this, new DicomNEventReportResponse( msg as DicomNEventReportRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNGetRequest) (msg as DicomNGetRequest).PostResponse( this, new DicomNGetResponse( msg as DicomNGetRequest, DicomStatus.SOPClassNotSupported)); else if (msg is DicomNSetRequest) (msg as DicomNSetRequest).PostResponse( this, new DicomNSetResponse( msg as DicomNSetRequest, DicomStatus.SOPClassNotSupported)); else { Logger.Warn("Unknown message type: {type}", msg.Type); } } catch { } Logger.Error( "No accepted presentation context found for abstract syntax: {sopClassUid}", msg.SOPClassUID); } else { var dimse = new Dimse { Message = msg, PresentationContext = pc }; // force calculation of command group length as required by standard msg.Command.RecalculateGroupLengths(); if (msg.HasDataset) { // remove group lengths as recommended in PS 3.5 7.2 // // 2. It is recommended that Group Length elements be removed during storage or transfer // in order to avoid the risk of inconsistencies arising during coercion of data // element values and changes in transfer syntax. msg.Dataset.RemoveGroupLengths(); if (msg.Dataset.InternalTransferSyntax != dimse.PresentationContext.AcceptedTransferSyntax) { Logger.Debug("{logId} Changing Transfer Syntax from {0} to {1}", LogID, msg.Dataset.InternalTransferSyntax, dimse.PresentationContext.AcceptedTransferSyntax); msg.Dataset = msg.Dataset.Clone(dimse.PresentationContext.AcceptedTransferSyntax); } } Logger.Info("{logId} -> {dicomMessage}", LogID, msg.ToString(Options.LogDimseDatasets)); try { dimse.Stream = new PDataTFStream(this, pc.ID, Association.MaximumPDULength); var writer = new DicomWriter( DicomTransferSyntax.ImplicitVRLittleEndian, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(msg.Command); dimse.Walker.Walk(writer); if (dimse.Message.HasDataset) { dimse.Stream.SetIsCommandAsync(false).Wait(); writer = new DicomWriter( dimse.PresentationContext.AcceptedTransferSyntax, DicomWriteOptions.Default, new StreamByteTarget(dimse.Stream)); dimse.Walker = new DicomDatasetWalker(dimse.Message.Dataset); dimse.Walker.Walk(writer); } } catch (Exception e) { Logger.Error("Exception sending DIMSE: {@error}", e); } finally { dimse.Stream.FlushAsync(true).Wait(); dimse.Stream.Dispose(); } } lock (_lock) _sending = false; } }