public void Write_AeWithNonAsciiCharacters_ShouldBeAsciified() { var notExpected = "GÖTEBORG"; var request = new AAssociateRQ(new DicomAssociation("MALMÖ", notExpected)); var writePdu = request.Write(); RawPDU readPdu; using (var stream = new MemoryStream()) { writePdu.WritePDU(stream); var length = (int)writePdu.Length; var buffer = new byte[length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(buffer, 0, length); readPdu = new RawPDU(buffer); } readPdu.Reset(); readPdu.SkipBytes("Unknown", 10); var actual = readPdu.ReadString("Called AE", 16); Assert.NotEqual(notExpected, actual); }
/// <summary> /// Writes A-ABORT to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x07); pdu.Write("Reserved", (byte)0x00); pdu.Write("Reserved", (byte)0x00); pdu.Write("Source", (byte)_s); pdu.Write("Reason", (byte)_r); return(pdu); }
/// <summary> /// Writes PDV to PDU buffer /// </summary> /// <param name="pdu">PDU buffer</param> public void Write(RawPDU pdu) { byte mch = (byte)((_last ? 2 : 0) + (_command ? 1 : 0)); pdu.MarkLength32("PDV-Length"); pdu.Write("Presentation Context ID", (byte)_pcid); pdu.Write("Message Control Header", (byte)mch); pdu.Write("PDV Value", _value); pdu.WriteLength32(); }
/// <summary> /// Writes P-DATA-TF to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x04); foreach (PDV pdv in _pdvs) { pdv.Write(pdu); } return(pdu); }
/// <summary> /// Writes P-DATA-TF to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { var pdu = new RawPDU(0x04); foreach (var pdv in _pdvs) { pdv.Write(pdu); } return(pdu); }
/// <summary> /// Writes A-ASSOCIATE-RJ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> /// <remarks>When writing the rejection reason to the <see cref="RawPDU"/> object, the <see cref="DicomRejectSource"/> /// specification in the underlying value is masked out, to ensure that the reason code matches the codes specified /// in Table 9-21 of DICOM Standard PS 3.8.</remarks> public RawPDU Write() { var pdu = new RawPDU(0x03); pdu.Write("Reserved", 0x00); pdu.Write("Result", (byte)_rt); pdu.Write("Source", (byte)_so); pdu.Write("Reason", (byte)((byte)_rn & 0xf)); return(pdu); }
/// <summary> /// Writes A-ASSOCIATE-RJ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x03); pdu.Write("Reserved", (byte)0x00); pdu.Write("Result", (byte)_rt); pdu.Write("Source", (byte)_so); pdu.Write("Reason", (byte)_rn); return(pdu); }
public void AssociateRJ_Read_ReasonGivenByContext(byte[] buffer, AAssociateRJ dummy, string expected) { using (var raw = new RawPDU(buffer)) { var reject = new AAssociateRJ(); reject.Read(raw); var actual = reject.Reason.ToString(); Assert.Equal(expected, actual); } }
public void Save_ToNonExistingDirectory_Succeeds() { var path = @".\Test Data\PDU Test"; var name = Path.Combine(path, "assoc.pdu"); if (Directory.Exists(path)) Directory.Delete(path, true); var pdu = new RawPDU(0x01); pdu.Save(name); Assert.True(File.Exists(name)); }
/// <summary> /// Reads PDV from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public uint Read(RawPDU raw) { uint len = raw.ReadUInt32("PDV-Length"); _pcid = raw.ReadByte("Presentation Context ID"); byte mch = raw.ReadByte("Message Control Header"); _value = raw.ReadBytes("PDV Value", (int)len - 2); _command = (mch & 0x01) != 0; _last = (mch & 0x02) != 0; return(len + 4); }
/// <summary> /// Reads P-DATA-TF from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { uint len = raw.Length - 6; uint read = 0; while (read < len) { PDV pdv = new PDV(); read += pdv.Read(raw); _pdvs.Add(pdv); } }
private RawPDU ConvertWriteToReadPdu(RawPDU writePdu) { using (MemoryStream stream = new MemoryStream()) { writePdu.WritePDU(stream); int length = (int)stream.Length; byte[] buffer = new byte[length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(buffer, 0, length); return(new RawPDU(buffer)); } }
public void Save_ToNonExistingDirectory_Succeeds() { var path = @".\Test Data\PDU Test"; var name = Path.Combine(path, "assoc.pdu"); if (Directory.Exists(path)) { Directory.Delete(path, true); } var pdu = new RawPDU(0x01); pdu.Save(name); Assert.True(File.Exists(name)); }
/// <summary> /// Write PDU. /// </summary> /// <param name="pdu">PDU to write.</param> public void Write(RawPDU pdu) { if (null != SubItem) { pdu.Write("Item-Type", (byte)0x56); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("SOP Class UID Length", (ushort)(SopClassUid.UID.Length)); pdu.Write("SOP Class UID", SopClassUid.UID); SubItem.Write(pdu); pdu.WriteLength16(); } }
public void WriteReadAAssociateRQExtendedNegotiation() { DicomAssociation association = new DicomAssociation("testCalling", "testCalled"); association.ExtendedNegotiations.Add( new DicomExtendedNegotiation( DicomUID.StudyRootQueryRetrieveInformationModelFIND, new RootQueryRetrieveInfoFind(1, 1, 1, 1, null))); AAssociateRQ rq = new AAssociateRQ(association); RawPDU writePdu = rq.Write(); RawPDU readPdu; using (MemoryStream stream = new MemoryStream()) { writePdu.WritePDU(stream); int length = (int)stream.Length; byte[] buffer = new byte[length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(buffer, 0, length); readPdu = new RawPDU(buffer); } DicomAssociation testAssociation = new DicomAssociation(); AAssociateRQ rq2 = new AAssociateRQ(testAssociation); rq2.Read(readPdu); Assert.True(testAssociation.ExtendedNegotiations.Count == 1); Assert.True( testAssociation.ExtendedNegotiations[0].SopClassUid == DicomUID.StudyRootQueryRetrieveInformationModelFIND); RootQueryRetrieveInfoFind info = testAssociation.ExtendedNegotiations[0].SubItem as RootQueryRetrieveInfoFind; Assert.True(null != info); Assert.True( (1 == info.DateTimeMatching) && (1 == info.FuzzySemanticMatching) && (1 == info.RelationalQueries) && (1 == info.TimezoneQueryAdjustment) && (false == info.EnhancedMultiFrameImageConversion.HasValue)); }
public void AssociateAC_Read_TransferSyntaxIdentifiedIfAccept(byte[] buffer, byte contextId, DicomPresentationContextResult result, DicomTransferSyntax syntax) { var association = new DicomAssociation(); association.PresentationContexts.Add( new DicomPresentationContext(contextId, DicomUID.Verification)); using (var raw = new RawPDU(buffer)) { var accept = new AAssociateAC(association); accept.Read(raw); var actual = association.PresentationContexts[contextId]; Assert.Equal(result, actual.Result); Assert.Equal(syntax, actual.AcceptedTransferSyntax); } }
private void WritePDU(bool last) { if (_pdu.PDVs.Count == 0 || ((CurrentPduSize() + 6) < _max && GetBufferLength() > 0)) { CreatePDV(); } if (_pdu.PDVs.Count > 0) { if (last) { _pdu.PDVs[_pdu.PDVs.Count - 1].IsLastFragment = true; } RawPDU raw = _pdu.Write(); raw.WritePDU(_network); if (OnPduSent != null) { OnPduSent(); } _pdu = new PDataTF(); } }
/// <summary> /// Factory method for creating <see cref="DicomExtendedNegotiation"/> instances. /// </summary> /// <param name="raw">Raw PDU.</param> /// <param name="length">Length.</param> /// <returns>A new <see cref="DicomExtendedNegotiation"/> instance.</returns> public static DicomExtendedNegotiation Create(RawPDU raw, ushort length) { var uidLen = raw.ReadUInt16("SOP Class UID Length"); var uidStr = raw.ReadString("SOP Class UID", uidLen); var uid = DicomUID.Parse(uidStr); IExtendedNegotiationSubItem subItem = null; var subItemSize = 0; var remaining = length - uidLen - 2; if (subItemCreators.ContainsKey(uid)) { subItem = subItemCreators[uid](raw, remaining, out subItemSize); } remaining -= subItemSize; if (remaining > 0) { raw.SkipBytes("Unread bytes", remaining); } return(new DicomExtendedNegotiation(uid, subItem)); }
/// <summary> /// Writes A-ABORT to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x07); pdu.Write("Reserved", (byte)0x00); pdu.Write("Reserved", (byte)0x00); pdu.Write("Source", (byte)_s); pdu.Write("Reason", (byte)_r); return pdu; }
/// <summary> /// Writes A-RELEASE-RP to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x06); pdu.Write("Reserved", (uint)0x00000000); return pdu; }
/// <summary> /// Writes A-ASSOCIATE-RJ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x03); pdu.Write("Reserved", (byte)0x00); pdu.Write("Result", (byte)_rt); pdu.Write("Source", (byte)_so); pdu.Write("Reason", (byte)_rn); return pdu; }
/// <summary> /// Writes A-ASSOCIATE-AC to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x02); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (var pc in _assoc.PresentationContexts) { // Presentation Context pdu.Write("Item-Type", (byte)0x21); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00); pdu.Write("Result", (byte)pc.Result); pdu.Write("Reserved", (byte)0x00); // Transfer Syntax pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", pc.AcceptedTransferSyntax.UID.UID); pdu.WriteLength16(); pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPDULength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", DicomImplementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.MaxAsyncOpsInvoked != 1 || _assoc.MaxAsyncOpsPerformed != 1) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.MaxAsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.MaxAsyncOpsPerformed); } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", DicomImplementation.Version); pdu.WriteLength16(); pdu.WriteLength16(); return pdu; }
/// <summary> /// Reads A-ASSOCIATE-AC from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { uint l = raw.Length; ushort c = 0; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 32); l -= 68; while (l > 0) { byte type = raw.ReadByte("Item-Type"); l -= 1; if (type == 0x10) { // Application Context raw.SkipBytes("Reserved", 1); c = raw.ReadUInt16("Item-Length"); raw.SkipBytes("Value", (int)c); l -= 3 + (uint)c; } else if (type == 0x21) { // Presentation Context raw.ReadByte("Reserved"); ushort pl = raw.ReadUInt16("Presentation Context Item-Length"); byte id = raw.ReadByte("Presentation Context ID"); raw.ReadByte("Reserved"); byte res = raw.ReadByte("Presentation Context Result/Reason"); raw.ReadByte("Reserved"); l -= (uint)pl + 3; pl -= 4; // Presentation Context Transfer Syntax raw.ReadByte("Presentation Context Item-Type (0x40)"); raw.ReadByte("Reserved"); ushort tl = raw.ReadUInt16("Presentation Context Item-Length"); string tx = raw.ReadString("Presentation Context Syntax UID", tl); pl -= (ushort)(tl + 4); _assoc.SetPresentationContextResult(id, (DcmPresContextResult)res); _assoc.SetAcceptedTransferSyntax(id, DicomTransferSyntax.Lookup(tx)); } else if (type == 0x50) { // User Information raw.ReadByte("Reserved"); ushort il = raw.ReadUInt16("User Information Item-Length"); l -= (uint)(il + 3); while (il > 0) { byte ut = raw.ReadByte("User Item-Type"); raw.ReadByte("Reserved"); ushort ul = raw.ReadUInt16("User Item-Length"); il -= (ushort)(ul + 4); if (ut == 0x51) { _assoc.MaximumPduLength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.ImplementationClass = DicomUID.Lookup(raw.ReadString("Implementation Class UID", ul)); } else if (ut == 0x53) { _assoc.AsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.AsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x55) { _assoc.ImplementationVersion = raw.ReadString("Implementation Version", ul); } else { raw.SkipBytes("User Item Value", (int)ul); } } } else { raw.SkipBytes("Reserved", 1); ushort il = raw.ReadUInt16("User Item-Length"); raw.SkipBytes("Unknown User Item", il); l -= (uint)(il + 3); } } }
/// <summary> /// Reads A-ASSOCIATE-RQ from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { uint l = raw.Length - 6; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); _assoc.CalledAE = raw.ReadString("Called AE", 16); _assoc.CallingAE = raw.ReadString("Calling AE", 16); raw.SkipBytes("Reserved", 32); l -= 2 + 2 + 16 + 16 + 32; while (l > 0) { byte type = raw.ReadByte("Item-Type"); raw.SkipBytes("Reserved", 1); ushort il = raw.ReadUInt16("Item-Length"); l -= 4 + (uint)il; if (type == 0x10) { // Application Context raw.SkipBytes("Application Context", il); } else if (type == 0x20) { // Presentation Context byte id = raw.ReadByte("Presentation Context ID"); raw.SkipBytes("Reserved", 3); il -= 4; while (il > 0) { byte pt = raw.ReadByte("Presentation Context Item-Type"); raw.SkipBytes("Reserved", 1); ushort pl = raw.ReadUInt16("Presentation Context Item-Length"); string sx = raw.ReadString("Presentation Context Syntax UID", pl); if (pt == 0x30) { var pc = new DicomPresentationContext(id, DicomUID.Parse(sx)); _assoc.PresentationContexts.Add(pc); } else if (pt == 0x40) { var pc = _assoc.PresentationContexts[id]; pc.AddTransferSyntax(DicomTransferSyntax.Parse(sx)); } il -= (ushort)(4 + pl); } } else if (type == 0x50) { // User Information while (il > 0) { byte ut = raw.ReadByte("User Information Item-Type"); raw.SkipBytes("Reserved", 1); ushort ul = raw.ReadUInt16("User Information Item-Length"); il -= (ushort)(4 + ul); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplementationClassUID = new DicomUID( raw.ReadString("Implementation Class UID", ul), "Implementation Class UID", DicomUidType.Unknown); } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x54) { var asul = raw.ReadUInt16("Abstract Syntax Item-Length"); var syntax = raw.ReadString("Abstract Syntax UID", asul); var userRole = raw.ReadByte("SCU role"); var providerRole = raw.ReadByte("SCP role"); var pc = _assoc.PresentationContexts.FirstOrDefault( context => context.AbstractSyntax.UID.Equals(syntax)); if (pc != null) { pc.UserRole = userRole == 0x01; pc.ProviderRole = providerRole == 0x01; } } else if (ut == 0x56) { _assoc.ExtendedNegotiations.Add(DicomExtendedNegotiation.Create(raw, ul)); } else { raw.SkipBytes("Unhandled User Item", ul); } } } } }
/// <summary> /// 扩展,向RawPDU中写入UserIdentity身份信息 /// </summary> /// <param name="userIdentity"></param> /// <returns></returns> public RawPDU WriteAddingUserIdentity(UserIdentity userIdentity) { RawPDU pdu = new RawPDU((byte)0x01); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (DcmPresContext pc in _assoc.GetPresentationContexts()) { // Presentation Context pdu.Write("Item-Type", (byte)0x20); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00, 3); // Abstract Syntax pdu.Write("Item-Type", (byte)0x30); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); // Transfer Syntax foreach (DicomTransferSyntax ts in pc.GetTransfers()) { pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", ts.UID.UID); pdu.WriteLength16(); } pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPduLength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", Implementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.NegotiateAsyncOps) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.AsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.AsyncOpsPerformed); } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", Implementation.Version); pdu.WriteLength16(); //User Indentity //http://medical.nema.org/medical/dicom/current/output/html/part07.html#sect_D.3.3.7 pdu.Write("Item-Type", (byte)0x58); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("User Identity Type", (byte)userIdentity.UserIdentityType); pdu.Write("Positive Response Requested", (userIdentity.bPositiveResponseRequested?(byte)0x01:(byte)0x00)); pdu.Write("Primary Field Length", (ushort)userIdentity.UserName.Length); pdu.Write("Primary Field", userIdentity.UserName); pdu.Write("Secondary Field Length", (ushort)userIdentity.PassCode.Length); pdu.Write("Secondary Field", userIdentity.PassCode); pdu.WriteLength16(); //zssure:end. pdu.WriteLength16(); return(pdu); }
/// <summary> /// Writes A-ASSOCIATE-RQ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x01); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (var pc in _assoc.PresentationContexts) { // Presentation Context pdu.Write("Item-Type", (byte)0x20); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00, 3); // Abstract Syntax pdu.Write("Item-Type", (byte)0x30); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); // Transfer Syntax foreach (DicomTransferSyntax ts in pc.GetTransferSyntaxes()) { pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", ts.UID.UID); pdu.WriteLength16(); } pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPDULength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", DicomImplementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.MaxAsyncOpsInvoked != 1 || _assoc.MaxAsyncOpsPerformed != 1) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.MaxAsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.MaxAsyncOpsPerformed); } foreach (var pc in _assoc.PresentationContexts) { if (pc.UserRole.HasValue || pc.ProviderRole.HasValue) { pdu.Write("Item-Type", (byte)0x54); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.MarkLength16("UID-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); pdu.Write("SCU Role", pc.UserRole.GetValueOrDefault() ? (byte)1 : (byte)0); pdu.Write("SCP Role", pc.ProviderRole.GetValueOrDefault() ? (byte)1 : (byte)0); pdu.WriteLength16(); } } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", DicomImplementation.Version); pdu.WriteLength16(); foreach (DicomExtendedNegotiation exNeg in _assoc.ExtendedNegotiations) { exNeg.Write(pdu); } pdu.WriteLength16(); return pdu; }
/// <summary> /// Writes P-DATA-TF to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x04); foreach (PDV pdv in _pdvs) { pdv.Write(pdu); } return pdu; }
/// <summary> /// Reads PDV from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public uint Read(RawPDU raw) { uint len = raw.ReadUInt32("PDV-Length"); _pcid = raw.ReadByte("Presentation Context ID"); byte mch = raw.ReadByte("Message Control Header"); _value = raw.ReadBytes("PDV Value", (int)len - 2); _command = (mch & 0x01) != 0; _last = (mch & 0x02) != 0; return len + 4; }
/// <summary> /// Writes A-ASSOCIATE-RQ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x01); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (DcmPresContext pc in _assoc.GetPresentationContexts()) { // Presentation Context pdu.Write("Item-Type", (byte)0x20); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00, 3); // Abstract Syntax pdu.Write("Item-Type", (byte)0x30); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); // Transfer Syntax foreach (DicomTransferSyntax ts in pc.GetTransfers()) { pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", ts.UID.UID); pdu.WriteLength16(); } pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPduLength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", Implementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.NegotiateAsyncOps) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.AsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.AsyncOpsPerformed); } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", Implementation.Version); pdu.WriteLength16(); pdu.WriteLength16(); return(pdu); }
/// <summary> /// Reads A-ASSOCIATE-RQ from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { uint l = raw.Length - 6; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); _assoc.CalledAE = raw.ReadString("Called AE", 16); _assoc.CallingAE = raw.ReadString("Calling AE", 16); raw.SkipBytes("Reserved", 32); l -= 2 + 2 + 16 + 16 + 32; while (l > 0) { byte type = raw.ReadByte("Item-Type"); raw.SkipBytes("Reserved", 1); ushort il = raw.ReadUInt16("Item-Length"); l -= 4 + (uint)il; if (type == 0x10) { // Application Context raw.SkipBytes("Application Context", il); } else if (type == 0x20) { // Presentation Context byte id = raw.ReadByte("Presentation Context ID"); raw.SkipBytes("Reserved", 3); il -= 4; while (il > 0) { byte pt = raw.ReadByte("Presentation Context Item-Type"); raw.SkipBytes("Reserved", 1); ushort pl = raw.ReadUInt16("Presentation Context Item-Length"); string sx = raw.ReadString("Presentation Context Syntax UID", pl); if (pt == 0x30) { var pc = new DicomPresentationContext(id, DicomUID.Parse(sx)); _assoc.PresentationContexts.Add(pc); } else if (pt == 0x40) { var pc = _assoc.PresentationContexts[id]; pc.AddTransferSyntax(DicomTransferSyntax.Parse(sx)); } il -= (ushort)(4 + pl); } } else if (type == 0x50) { // User Information while (il > 0) { byte ut = raw.ReadByte("User Information Item-Type"); raw.SkipBytes("Reserved", 1); ushort ul = raw.ReadUInt16("User Information Item-Length"); il -= (ushort)(4 + ul); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplemetationClassUID = new DicomUID(raw.ReadString("Implementation Class UID", ul), "Implementation Class UID", DicomUidType.Unknown); } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x54) { raw.SkipBytes("SCU/SCP Role Selection", ul); /* ushort rsul = raw.ReadUInt16(); if ((rsul + 4) != ul) { throw new DicomNetworkException("SCU/SCP role selection length (" + ul + " bytes) does not match uid length (" + rsul + " + 4 bytes)"); } raw.ReadChars(rsul); // Abstract Syntax raw.ReadByte(); // SCU role raw.ReadByte(); // SCP role */ } else { //Debug.Log.Error("Unhandled user item: 0x{0:x2} ({1} + 4 bytes)", ut, ul); raw.SkipBytes("Unhandled User Item", ul); } } } } }
private void EndReadPDU(IAsyncResult result) { try { byte[] buffer = (byte[])result.AsyncState; int count = _network.EndRead(result); if (count == 0) { // disconnected CloseConnection(0); return; } _readLength -= count; if (_readLength > 0) { _network.BeginRead(buffer, buffer.Length - _readLength, _readLength, EndReadPDU, buffer); return; } var raw = new RawPDU(buffer); switch (raw.Type) { case 0x01: { Association = new DicomAssociation(); var pdu = new AAssociateRQ(Association); pdu.Read(raw); LogID = Association.CallingAE; if (Options.UseRemoteAEForLogName) { Logger = LogManager.Default.GetLogger(LogID); } Logger.Info("{0} <- Association request:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAssociationRequest(Association); } break; } case 0x02: { var pdu = new AAssociateAC(Association); pdu.Read(raw); LogID = Association.CalledAE; Logger.Info("{0} <- Association accept:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationAccept(Association); } break; } case 0x03: { var pdu = new AAssociateRJ(); pdu.Read(raw); Logger.Info("{0} <- Association reject [result: {1}; source: {2}; reason: {3}]", LogID, pdu.Result, pdu.Source, pdu.Reason); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationReject(pdu.Result, pdu.Source, pdu.Reason); } break; } case 0x04: { var pdu = new PDataTF(); pdu.Read(raw); if (Options.LogDataPDUs) { Logger.Info("{0} <- {1}", LogID, pdu); } _processQueue.Queue(ProcessPDataTF, pdu); break; } case 0x05: { var pdu = new AReleaseRQ(); pdu.Read(raw); Logger.Info("{0} <- Association release request", LogID); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAssociationReleaseRequest(); } break; } case 0x06: { var pdu = new AReleaseRP(); pdu.Read(raw); Logger.Info("{0} <- Association release response", LogID); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationReleaseResponse(); } CloseConnection(0); break; } case 0x07: { var pdu = new AAbort(); pdu.Read(raw); Logger.Info("{0} <- Abort: {1} - {2}", LogID, pdu.Source, pdu.Reason); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAbort(pdu.Source, pdu.Reason); } else if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAbort(pdu.Source, pdu.Reason); } CloseConnection(0); break; } case 0xFF: { break; } default: throw new DicomNetworkException("Unknown PDU type"); } BeginReadPDUHeader(); } catch (IOException e) { int error = 0; if (e.InnerException is SocketException) { error = (e.InnerException as SocketException).ErrorCode; Logger.Error("Socket error while reading PDU: {0} [{1}]", (e.InnerException as SocketException).SocketErrorCode, (e.InnerException as SocketException).ErrorCode); } else if (!(e.InnerException is ObjectDisposedException)) { Logger.Error("IO exception while reading PDU: {0}", e.ToString()); } CloseConnection(error); } catch (NullReferenceException) { // connection already closed; silently ignore CloseConnection(0); } catch (Exception e) { Logger.Error("Exception processing PDU: {0}", e.ToString()); CloseConnection(0); } }
/// <summary> /// Reads A-ASSOCIATE-AC from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { // reset async ops in case remote end does not negotiate _assoc.MaxAsyncOpsInvoked = 1; _assoc.MaxAsyncOpsPerformed = 1; uint l = raw.Length - 6; ushort c = 0; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 32); l -= 68; while (l > 0) { byte type = raw.ReadByte("Item-Type"); l -= 1; if (type == 0x10) { // Application Context raw.SkipBytes("Reserved", 1); c = raw.ReadUInt16("Item-Length"); raw.SkipBytes("Value", (int)c); l -= 3 + (uint)c; } else if (type == 0x21) { // Presentation Context raw.ReadByte("Reserved"); ushort pl = raw.ReadUInt16("Presentation Context Item-Length"); byte id = raw.ReadByte("Presentation Context ID"); raw.ReadByte("Reserved"); byte res = raw.ReadByte("Presentation Context Result/Reason"); raw.ReadByte("Reserved"); l -= (uint)pl + 3; pl -= 4; // Presentation Context Transfer Syntax raw.ReadByte("Presentation Context Item-Type (0x40)"); raw.ReadByte("Reserved"); ushort tl = raw.ReadUInt16("Presentation Context Item-Length"); string tx = raw.ReadString("Presentation Context Syntax UID", tl); pl -= (ushort)(tl + 4); _assoc.PresentationContexts[id].SetResult((DicomPresentationContextResult)res, DicomTransferSyntax.Parse(tx)); } else if (type == 0x50) { // User Information raw.ReadByte("Reserved"); ushort il = raw.ReadUInt16("User Information Item-Length"); l -= (uint)(il + 3); while (il > 0) { byte ut = raw.ReadByte("User Item-Type"); raw.ReadByte("Reserved"); ushort ul = raw.ReadUInt16("User Item-Length"); il -= (ushort)(ul + 4); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplemetationClassUID = DicomUID.Parse(raw.ReadString("Implementation Class UID", ul)); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else { raw.SkipBytes("User Item Value", (int)ul); } } } else { raw.SkipBytes("Reserved", 1); ushort il = raw.ReadUInt16("User Item-Length"); raw.SkipBytes("Unknown User Item", il); l -= (uint)(il + 3); } } }
/// <summary> /// Reads A-ASSOCIATE-RQ from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { uint l = raw.Length - 6; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); _assoc.CalledAE = raw.ReadString("Called AE", 16); _assoc.CallingAE = raw.ReadString("Calling AE", 16); raw.SkipBytes("Reserved", 32); l -= 2 + 2 + 16 + 16 + 32; while (l > 0) { byte type = raw.ReadByte("Item-Type"); raw.SkipBytes("Reserved", 1); ushort il = raw.ReadUInt16("Item-Length"); l -= 4 + (uint)il; if (type == 0x10) { // Application Context raw.SkipBytes("Application Context", il); } else if (type == 0x20) { // Presentation Context byte id = raw.ReadByte("Presentation Context ID"); raw.SkipBytes("Reserved", 3); il -= 4; while (il > 0) { byte pt = raw.ReadByte("Presentation Context Item-Type"); raw.SkipBytes("Reserved", 1); ushort pl = raw.ReadUInt16("Presentation Context Item-Length"); string sx = raw.ReadString("Presentation Context Syntax UID", pl); if (pt == 0x30) { var pc = new DicomPresentationContext(id, DicomUID.Parse(sx)); _assoc.PresentationContexts.Add(pc); } else if (pt == 0x40) { var pc = _assoc.PresentationContexts[id]; pc.AddTransferSyntax(DicomTransferSyntax.Parse(sx)); } il -= (ushort)(4 + pl); } } else if (type == 0x50) { // User Information while (il > 0) { byte ut = raw.ReadByte("User Information Item-Type"); raw.SkipBytes("Reserved", 1); ushort ul = raw.ReadUInt16("User Information Item-Length"); il -= (ushort)(4 + ul); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplemetationClassUID = new DicomUID(raw.ReadString("Implementation Class UID", ul), "Implementation Class UID", DicomUidType.Unknown); } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x54) { raw.SkipBytes("SCU/SCP Role Selection", ul); /* * ushort rsul = raw.ReadUInt16(); * if ((rsul + 4) != ul) { * throw new DicomNetworkException("SCU/SCP role selection length (" + ul + " bytes) does not match uid length (" + rsul + " + 4 bytes)"); * } * raw.ReadChars(rsul); // Abstract Syntax * raw.ReadByte(); // SCU role * raw.ReadByte(); // SCP role */ } else { //Debug.Log.Error("Unhandled user item: 0x{0:x2} ({1} + 4 bytes)", ut, ul); raw.SkipBytes("Unhandled User Item", ul); } } } } }
/// <summary> /// Reads A-ASSOCIATE-RJ from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { raw.ReadByte("Reserved"); _rt = (DicomRejectResult)raw.ReadByte("Result"); _so = (DicomRejectSource)raw.ReadByte("Source"); _rn = (DicomRejectReason)raw.ReadByte("Reason"); }
/// <summary> /// Reads A-RELEASE-RP from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { raw.ReadUInt32("Reserved"); }
private bool ProcessNextPDU() { RawPDU raw = new RawPDU(_network); if (raw.Type == 0x04) { if (_dimse == null) { _dimse = new DcmDimseInfo(); } } try { raw.ReadPDU(); switch (raw.Type) { case 0x01: { _assoc = new DcmAssociate(); AAssociateRQ pdu = new AAssociateRQ(_assoc); pdu.Read(raw); Log.Info("{0} <- Association request:\n{1}", LogID, Associate.ToString()); OnReceiveAssociateRequest(_assoc); return true; } case 0x02: { AAssociateAC pdu = new AAssociateAC(_assoc); pdu.Read(raw); Log.Info("{0} <- Association accept:\n{1}", LogID, Associate.ToString()); OnReceiveAssociateAccept(_assoc); return true; } case 0x03: { AAssociateRJ pdu = new AAssociateRJ(); pdu.Read(raw); Log.Info("{0} <- Association reject [result: {1}; source: {2}; reason: {3}]", LogID, pdu.Result, pdu.Source, pdu.Reason); OnReceiveAssociateReject(pdu.Result, pdu.Source, pdu.Reason); return true; } case 0x04: { PDataTF pdu = new PDataTF(); pdu.Read(raw); //Log.Debug("{0} <- P-Data-TF", LogID); return ProcessPDataTF(pdu); } case 0x05: { AReleaseRQ pdu = new AReleaseRQ(); pdu.Read(raw); Log.Info("{0} <- Association release request", LogID); OnReceiveReleaseRequest(); return true; } case 0x06: { AReleaseRP pdu = new AReleaseRP(); pdu.Read(raw); Log.Info("{0} <- Association release response", LogID); OnReceiveReleaseResponse(); return true; } case 0x07: { AAbort pdu = new AAbort(); pdu.Read(raw); Log.Info("{0} <- Association abort: {1} - {2}", LogID, pdu.Source, pdu.Reason); OnReceiveAbort(pdu.Source, pdu.Reason); return true; } case 0xFF: { return false; } default: throw new DicomNetworkException("Unknown PDU type"); } } catch (SocketException) { throw; } catch (Exception e) { #if DEBUG Log.Error("{0} -> Error reading PDU [type: 0x{1:x2}]: {2}", LogID, raw.Type, e.ToString()); #else Log.Error("{0} -> Error reading PDU [type: 0x{1:x2}]: {2}", LogID, raw.Type, e.Message); #endif OnNetworkError(e); //String file = String.Format(@"{0}\Errors\{1}.pdu", // Dicom.Debug.GetStartDirectory(), DateTime.Now.Ticks); //Directory.CreateDirectory(Dicom.Debug.GetStartDirectory() + @"\Errors"); //raw.Save(file); return false; } }
/// <summary> /// Reads A-ABORT from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { raw.ReadByte("Reserved"); raw.ReadByte("Reserved"); _s = (DicomAbortSource)raw.ReadByte("Source"); _r = (DicomAbortReason)raw.ReadByte("Reason"); }
/// <summary> /// Writes A-ASSOCIATE-RQ to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x01); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (DcmPresContext pc in _assoc.GetPresentationContexts()) { // Presentation Context pdu.Write("Item-Type", (byte)0x20); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00, 3); // Abstract Syntax pdu.Write("Item-Type", (byte)0x30); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); // Transfer Syntax foreach (DicomTransferSyntax ts in pc.GetTransfers()) { pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", ts.UID.UID); pdu.WriteLength16(); } pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPduLength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", Implementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.NegotiateAsyncOps) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.AsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.AsyncOpsPerformed); } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", Implementation.Version); pdu.WriteLength16(); pdu.WriteLength16(); return pdu; }
private void EndReadPDU(IAsyncResult result) { try { byte[] buffer = (byte[])result.AsyncState; int count = _network.EndRead(result); if (count == 0) { // disconnected CloseConnection(0); return; } _readLength -= count; if (_readLength > 0) { _network.BeginRead(buffer, buffer.Length - _readLength, _readLength, EndReadPDU, buffer); return; } var raw = new RawPDU(buffer); switch (raw.Type) { case 0x01: { Association = new DicomAssociation(); var pdu = new AAssociateRQ(Association); pdu.Read(raw); LogID = Association.CallingAE; Logger.Log(LogLevel.Info, "{0} <- Association request:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationRequest(Association); break; } case 0x02: { var pdu = new AAssociateAC(Association); pdu.Read(raw); LogID = Association.CalledAE; Logger.Log(LogLevel.Info, "{0} <- Association accept:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationAccept(Association); break; } case 0x03: { var pdu = new AAssociateRJ(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association reject [result: {1}; source: {2}; reason: {3}]", LogID, pdu.Result, pdu.Source, pdu.Reason); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReject(pdu.Result, pdu.Source, pdu.Reason); break; } case 0x04: { var pdu = new PDataTF(); pdu.Read(raw); if (Options.LogDataPDUs) Logger.Info("{0} <- {1}", LogID, pdu); _processQueue.Queue(ProcessPDataTF, pdu); break; } case 0x05: { var pdu = new AReleaseRQ(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association release request", LogID); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationReleaseRequest(); break; } case 0x06: { var pdu = new AReleaseRP(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association release response", LogID); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReleaseResponse(); CloseConnection(0); break; } case 0x07: { var pdu = new AAbort(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Abort: {1} - {2}", LogID, pdu.Source, pdu.Reason); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAbort(pdu.Source, pdu.Reason); else if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAbort(pdu.Source, pdu.Reason); CloseConnection(0); break; } case 0xFF: { break; } default: throw new DicomNetworkException("Unknown PDU type"); } BeginReadPDUHeader(); } catch (IOException e) { int error = 0; if (e.InnerException is SocketException) { error = (e.InnerException as SocketException).ErrorCode; Logger.Error("Socket error while reading PDU: {0} [{1}]", (e.InnerException as SocketException).SocketErrorCode, (e.InnerException as SocketException).ErrorCode); } else if (!(e.InnerException is ObjectDisposedException)) Logger.Error("IO exception while reading PDU: {0}", e.ToString()); CloseConnection(error); } catch (Exception e) { Logger.Log(LogLevel.Error, "Exception processing PDU: {0}", e.ToString()); CloseConnection(0); } }
private async void ReadAndProcessPDUs() { try { while (this.IsConnected) { // Read PDU header _readLength = 6; var buffer = new byte[6]; var count = await this._network.ReadAsync(buffer, 0, 6).ConfigureAwait(false); do { if (count == 0) { // disconnected this.CloseConnection(null); return; } this._readLength -= count; if (this._readLength > 0) { count = await this._network.ReadAsync(buffer, 6 - this._readLength, this._readLength) .ConfigureAwait(false); } } while (this._readLength > 0); var length = BitConverter.ToInt32(buffer, 2); length = Endian.Swap(length); this._readLength = length; Array.Resize(ref buffer, length + 6); count = await this._network.ReadAsync(buffer, 6, length).ConfigureAwait(false); // Read PDU do { if (count == 0) { // disconnected this.CloseConnection(null); return; } this._readLength -= count; if (this._readLength > 0) { count = await this._network.ReadAsync(buffer, buffer.Length - this._readLength, this._readLength) .ConfigureAwait(false); } } while (this._readLength > 0); var raw = new RawPDU(buffer); switch (raw.Type) { case 0x01: { Association = new DicomAssociation(); var pdu = new AAssociateRQ(Association); pdu.Read(raw); LogID = Association.CallingAE; if (Options.UseRemoteAEForLogName) Logger = LogManager.GetLogger(LogID); Logger.Info( "{callingAE} <- Association request:\n{association}", LogID, Association.ToString()); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationRequest(Association); break; } case 0x02: { var pdu = new AAssociateAC(Association); pdu.Read(raw); LogID = Association.CalledAE; Logger.Info( "{calledAE} <- Association accept:\n{assocation}", LogID, Association.ToString()); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationAccept(Association); break; } case 0x03: { var pdu = new AAssociateRJ(); pdu.Read(raw); Logger.Info( "{logId} <- Association reject [result: {pduResult}; source: {pduSource}; reason: {pduReason}]", LogID, pdu.Result, pdu.Source, pdu.Reason); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReject( pdu.Result, pdu.Source, pdu.Reason); break; } case 0x04: { var pdu = new PDataTF(); pdu.Read(raw); if (Options.LogDataPDUs) Logger.Info("{logId} <- {@pdu}", LogID, pdu); await this.ProcessPDataTFAsync(pdu).ConfigureAwait(false); break; } case 0x05: { var pdu = new AReleaseRQ(); pdu.Read(raw); Logger.Info("{logId} <- Association release request", LogID); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationReleaseRequest(); break; } case 0x06: { var pdu = new AReleaseRP(); pdu.Read(raw); Logger.Info("{logId} <- Association release response", LogID); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReleaseResponse(); CloseConnection(null); return; } case 0x07: { var pdu = new AAbort(); pdu.Read(raw); Logger.Info( "{logId} <- Abort: {pduSource} - {pduReason}", LogID, pdu.Source, pdu.Reason); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAbort(pdu.Source, pdu.Reason); else if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAbort(pdu.Source, pdu.Reason); CloseConnection(null); return; } case 0xFF: { break; } default: throw new DicomNetworkException("Unknown PDU type"); } } } catch (ObjectDisposedException) { // silently ignore CloseConnection(null); } catch (NullReferenceException) { // connection already closed; silently ignore CloseConnection(null); } catch (IOException e) { LogIOException(this.Logger, e, true); CloseConnection(e); } catch (Exception e) { Logger.Error("Exception processing PDU: {@error}", e); CloseConnection(e); } }
/// <summary> /// Reads A-ASSOCIATE-RQ from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { var l = raw.Length - 6; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); _assoc.CalledAE = raw.ReadString("Called AE", 16); _assoc.CallingAE = raw.ReadString("Calling AE", 16); raw.SkipBytes("Reserved", 32); l -= 2 + 2 + 16 + 16 + 32; while (l > 0) { var type = raw.ReadByte("Item-Type"); raw.SkipBytes("Reserved", 1); var il = raw.ReadUInt16("Item-Length"); l -= 4 + (uint)il; if (type == 0x10) { // Application Context raw.SkipBytes("Application Context", il); } else if (type == 0x20) { // Presentation Context var id = raw.ReadByte("Presentation Context ID"); raw.SkipBytes("Reserved", 3); il -= 4; while (il > 0) { var pt = raw.ReadByte("Presentation Context Item-Type"); raw.SkipBytes("Reserved", 1); var pl = raw.ReadUInt16("Presentation Context Item-Length"); var sx = raw.ReadString("Presentation Context Syntax UID", pl); if (pt == 0x30) { var pc = new DicomPresentationContext(id, DicomUID.Parse(sx)); _assoc.PresentationContexts.Add(pc); } else if (pt == 0x40) { var pc = _assoc.PresentationContexts[id]; pc.AddTransferSyntax(DicomTransferSyntax.Parse(sx)); } il -= (ushort)(4 + pl); } } else if (type == 0x50) { // User Information while (il > 0) { var ut = raw.ReadByte("User Information Item-Type"); raw.SkipBytes("Reserved", 1); var ul = raw.ReadUInt16("User Information Item-Length"); il -= (ushort)(4 + ul); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplementationClassUID = new DicomUID( raw.ReadString("Implementation Class UID", ul), "Implementation Class UID", DicomUidType.Unknown); } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x54) { var asul = raw.ReadUInt16("Abstract Syntax Item-Length"); var syntax = raw.ReadString("Abstract Syntax UID", asul); var userRole = raw.ReadByte("SCU role"); var providerRole = raw.ReadByte("SCP role"); var pc = _assoc.PresentationContexts.FirstOrDefault( context => context.AbstractSyntax.UID.Equals(syntax)); if (pc != null) { pc.UserRole = userRole == 0x01; pc.ProviderRole = providerRole == 0x01; } } else if (ut == 0x56) { _assoc.ExtendedNegotiations.Add(DicomExtendedNegotiation.Create(raw, ul)); } else { #if !NET35 if (HandlePDUBytes != null) { HandlePDUBytes(raw.ReadBytes("Unhandled User Item", ul)); } else { raw.SkipBytes("Unhandled User Item", ul); } #else raw.SkipBytes("Unhandled User Item", ul); #endif } } } } }
/// <summary> /// Writes A-ASSOCIATE-AC to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { var pdu = new RawPDU(0x02); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", 0x10); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (var pc in _assoc.PresentationContexts) { // Presentation Context pdu.Write("Item-Type", 0x21); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", pc.ID); pdu.Write("Reserved", 0x00); pdu.Write("Result", (byte)pc.Result); pdu.Write("Reserved", 0x00); // Transfer Syntax (set to Implicit VR Little Endian if no accepted transfer syntax is defined) pdu.Write("Item-Type", 0x40); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", pc.AcceptedTransferSyntax?.UID.UID ?? DicomUID.ImplicitVRLittleEndian.UID); pdu.WriteLength16(); pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", 0x50); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", 0x51); pdu.Write("Reserved", 0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", _assoc.MaximumPDULength); // Implementation Class UID pdu.Write("Item-Type", 0x52); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", DicomImplementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.MaxAsyncOpsInvoked != 1 || _assoc.MaxAsyncOpsPerformed != 1) { pdu.Write("Item-Type", 0x53); pdu.Write("Reserved", 0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.MaxAsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.MaxAsyncOpsPerformed); } foreach (var pc in _assoc.PresentationContexts) { if (pc.UserRole.HasValue || pc.ProviderRole.HasValue) { pdu.Write("Item-Type", 0x54); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.MarkLength16("UID-Length"); pdu.Write("Abstract Syntax UID", pc.AbstractSyntax.UID); pdu.WriteLength16(); pdu.Write("SCU Role", pc.UserRole.GetValueOrDefault() ? (byte)1 : (byte)0); pdu.Write("SCP Role", pc.ProviderRole.GetValueOrDefault() ? (byte)1 : (byte)0); pdu.WriteLength16(); } } // Implementation Version pdu.Write("Item-Type", 0x55); pdu.Write("Reserved", 0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", DicomImplementation.Version); pdu.WriteLength16(); foreach (var exNeg in _assoc.ExtendedNegotiations) { exNeg.Write(pdu); } pdu.WriteLength16(); return(pdu); }
/// <summary> /// Reads A-ASSOCIATE-AC from PDU buffer /// </summary> /// <param name="raw">PDU buffer</param> public void Read(RawPDU raw) { // reset async ops in case remote end does not negotiate _assoc.MaxAsyncOpsInvoked = 1; _assoc.MaxAsyncOpsPerformed = 1; var l = raw.Length - 6; raw.ReadUInt16("Version"); raw.SkipBytes("Reserved", 2); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 16); raw.SkipBytes("Reserved", 32); l -= 68; while (l > 0) { var type = raw.ReadByte("Item-Type"); l -= 1; if (type == 0x10) { // Application Context raw.SkipBytes("Reserved", 1); var c = raw.ReadUInt16("Item-Length"); raw.SkipBytes("Value", c); l -= 3 + (uint)c; } else if (type == 0x21) { // Presentation Context raw.ReadByte("Reserved"); var pl = raw.ReadUInt16("Presentation Context Item-Length"); var id = raw.ReadByte("Presentation Context ID"); raw.ReadByte("Reserved"); var res = raw.ReadByte("Presentation Context Result/Reason"); raw.ReadByte("Reserved"); l -= (uint)pl + 3; pl -= 4; if ((DicomPresentationContextResult)res == DicomPresentationContextResult.Accept) { // Presentation Context Transfer Syntax raw.ReadByte("Presentation Context Item-Type (0x40)"); raw.ReadByte("Reserved"); var tl = raw.ReadUInt16("Presentation Context Item-Length"); var tx = raw.ReadString("Presentation Context Syntax UID", tl); pl -= (ushort)(tl + 4); _assoc.PresentationContexts[id].SetResult( (DicomPresentationContextResult)res, DicomTransferSyntax.Parse(tx)); } else { raw.SkipBytes("Rejected Presentation Context", pl); _assoc.PresentationContexts[id].SetResult((DicomPresentationContextResult)res); } } else if (type == 0x50) { // User Information raw.ReadByte("Reserved"); var il = raw.ReadUInt16("User Information Item-Length"); l -= (uint)(il + 3); while (il > 0) { var ut = raw.ReadByte("User Item-Type"); raw.ReadByte("Reserved"); var ul = raw.ReadUInt16("User Item-Length"); il -= (ushort)(ul + 4); if (ut == 0x51) { _assoc.MaximumPDULength = raw.ReadUInt32("Max PDU Length"); } else if (ut == 0x52) { _assoc.RemoteImplementationClassUID = DicomUID.Parse(raw.ReadString("Implementation Class UID", ul)); } else if (ut == 0x53) { _assoc.MaxAsyncOpsInvoked = raw.ReadUInt16("Asynchronous Operations Invoked"); _assoc.MaxAsyncOpsPerformed = raw.ReadUInt16("Asynchronous Operations Performed"); } else if (ut == 0x54) { var asul = raw.ReadUInt16("Abstract Syntax Item-Length"); var syntax = raw.ReadString("Abstract Syntax UID", asul); var userRole = raw.ReadByte("SCU role"); var providerRole = raw.ReadByte("SCP role"); var pc = _assoc.PresentationContexts.FirstOrDefault( context => context.AbstractSyntax.UID.Equals(syntax)); if (pc != null) { pc.UserRole = userRole == 0x01; pc.ProviderRole = providerRole == 0x01; } } else if (ut == 0x55) { _assoc.RemoteImplementationVersion = raw.ReadString("Implementation Version", ul); } else if (ut == 0x56) { _assoc.ExtendedNegotiations.Add(DicomExtendedNegotiation.Create(raw, ul)); } else { raw.SkipBytes("User Item Value", ul); } } } else { raw.SkipBytes("Reserved", 1); var il = raw.ReadUInt16("User Item-Length"); raw.SkipBytes("Unknown User Item", il); l -= (uint)(il + 3); } } }
/// <summary> /// Writes A-ASSOCIATE-AC to PDU buffer /// </summary> /// <returns>PDU buffer</returns> public RawPDU Write() { RawPDU pdu = new RawPDU((byte)0x02); pdu.Write("Version", (ushort)0x0001); pdu.Write("Reserved", 0x00, 2); pdu.Write("Called AE", _assoc.CalledAE, 16, ' '); pdu.Write("Calling AE", _assoc.CallingAE, 16, ' '); pdu.Write("Reserved", 0x00, 32); // Application Context pdu.Write("Item-Type", (byte)0x10); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Application Context Name", DicomUID.DICOMApplicationContextName.UID); pdu.WriteLength16(); foreach (var pc in _assoc.PresentationContexts) { // Presentation Context pdu.Write("Item-Type", (byte)0x21); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Presentation Context ID", (byte)pc.ID); pdu.Write("Reserved", (byte)0x00); pdu.Write("Result", (byte)pc.Result); pdu.Write("Reserved", (byte)0x00); // Transfer Syntax pdu.Write("Item-Type", (byte)0x40); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Transfer Syntax UID", pc.AcceptedTransferSyntax.UID.UID); pdu.WriteLength16(); pdu.WriteLength16(); } // User Data Fields pdu.Write("Item-Type", (byte)0x50); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); // Maximum PDU pdu.Write("Item-Type", (byte)0x51); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Max PDU Length", (uint)_assoc.MaximumPDULength); // Implementation Class UID pdu.Write("Item-Type", (byte)0x52); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Class UID", DicomImplementation.ClassUID.UID); pdu.WriteLength16(); // Asynchronous Operations Negotiation if (_assoc.MaxAsyncOpsInvoked != 1 || _assoc.MaxAsyncOpsPerformed != 1) { pdu.Write("Item-Type", (byte)0x53); pdu.Write("Reserved", (byte)0x00); pdu.Write("Item-Length", (ushort)0x0004); pdu.Write("Asynchronous Operations Invoked", (ushort)_assoc.MaxAsyncOpsInvoked); pdu.Write("Asynchronous Operations Performed", (ushort)_assoc.MaxAsyncOpsPerformed); } // Implementation Version pdu.Write("Item-Type", (byte)0x55); pdu.Write("Reserved", (byte)0x00); pdu.MarkLength16("Item-Length"); pdu.Write("Implementation Version", DicomImplementation.Version); pdu.WriteLength16(); pdu.WriteLength16(); return(pdu); }
private void EndReadPDU(IAsyncResult result) { try { byte[] buffer = (byte[])result.AsyncState; int count = _network.EndRead(result); if (count == 0) { // disconnected CloseConnection(null); return; } _readLength -= count; if (_readLength > 0) { _network.BeginRead(buffer, buffer.Length - _readLength, _readLength, EndReadPDU, buffer); return; } var raw = new RawPDU(buffer); switch (raw.Type) { case 0x01: { Association = new DicomAssociation(); var pdu = new AAssociateRQ(Association); pdu.Read(raw); LogID = Association.CallingAE; if (Options.UseRemoteAEForLogName) Logger = LogManager.Default.GetLogger(LogID); Logger.Info("{callingAE} <- Association request:\n{association}", LogID, Association.ToString()); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationRequest(Association); break; } case 0x02: { var pdu = new AAssociateAC(Association); pdu.Read(raw); LogID = Association.CalledAE; Logger.Info("{calledAE} <- Association accept:\n{assocation}", LogID, Association.ToString()); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationAccept(Association); break; } case 0x03: { var pdu = new AAssociateRJ(); pdu.Read(raw); Logger.Info("{logId} <- Association reject [result: {pduResult}; source: {pduSource}; reason: {pduReason}]", LogID, pdu.Result, pdu.Source, pdu.Reason); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReject(pdu.Result, pdu.Source, pdu.Reason); break; } case 0x04: { var pdu = new PDataTF(); pdu.Read(raw); if (Options.LogDataPDUs) Logger.Info("{logId} <- {@pdu}", LogID, pdu); _processQueue.Queue(ProcessPDataTF, pdu); break; } case 0x05: { var pdu = new AReleaseRQ(); pdu.Read(raw); Logger.Info("{logId} <- Association release request", LogID); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAssociationReleaseRequest(); break; } case 0x06: { var pdu = new AReleaseRP(); pdu.Read(raw); Logger.Info("{logId} <- Association release response", LogID); if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAssociationReleaseResponse(); CloseConnection(null); break; } case 0x07: { var pdu = new AAbort(); pdu.Read(raw); Logger.Info("{logId} <- Abort: {pduSource} - {pduReason}", LogID, pdu.Source, pdu.Reason); if (this is IDicomServiceProvider) (this as IDicomServiceProvider).OnReceiveAbort(pdu.Source, pdu.Reason); else if (this is IDicomServiceUser) (this as IDicomServiceUser).OnReceiveAbort(pdu.Source, pdu.Reason); CloseConnection(null); break; } case 0xFF: { break; } default: throw new DicomNetworkException("Unknown PDU type"); } BeginReadPDUHeader(); } catch (IOException e) { if (e.InnerException is SocketException) { Logger.Error("Socket error while reading PDU: {socketErrorCode} [{errorCode}]", (e.InnerException as SocketException).SocketErrorCode, (e.InnerException as SocketException).ErrorCode); } else if (!(e.InnerException is ObjectDisposedException)) Logger.Error("IO exception while reading PDU: {@error}", e); CloseConnection(e); } catch (NullReferenceException) { // connection already closed; silently ignore CloseConnection(null); } catch (Exception e) { Logger.Error("Exception processing PDU: {@error}", e); CloseConnection(e); } }
private void EndReadPDU(IAsyncResult result) { try { byte[] buffer = (byte[])result.AsyncState; int count = _network.EndRead(result); if (count == 0) { // disconnected _network.Close(); _isConnected = false; return; } _readLength -= count; if (_readLength > 0) { _network.BeginRead(buffer, buffer.Length - _readLength, _readLength, EndReadPDU, buffer); return; } var raw = new RawPDU(buffer); switch (raw.Type) { case 0x01: { Association = new DicomAssociation(); var pdu = new AAssociateRQ(Association); pdu.Read(raw); LogID = Association.CallingAE; Logger.Log(LogLevel.Info, "{0} <- Association request:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAssociationRequest(Association); } break; } case 0x02: { var pdu = new AAssociateAC(Association); pdu.Read(raw); LogID = Association.CalledAE; Logger.Log(LogLevel.Info, "{0} <- Association accept:\n{1}", LogID, Association.ToString()); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationAccept(Association); } break; } case 0x03: { var pdu = new AAssociateRJ(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association reject [result: {1}; source: {2}; reason: {3}]", LogID, pdu.Result, pdu.Source, pdu.Reason); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationReject(pdu.Result, pdu.Source, pdu.Reason); } break; } case 0x04: { var pdu = new PDataTF(); pdu.Read(raw); ProcessPDataTF(pdu); break; } case 0x05: { var pdu = new AReleaseRQ(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association release request", LogID); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAssociationReleaseRequest(); } break; } case 0x06: { var pdu = new AReleaseRP(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Association release response", LogID); if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAssociationReleaseResponse(); } _network.Close(); _isConnected = false; break; } case 0x07: { var pdu = new AAbort(); pdu.Read(raw); Logger.Log(LogLevel.Info, "{0} <- Abort: {1} - {2}", LogID, pdu.Source, pdu.Reason); if (this is IDicomServiceProvider) { (this as IDicomServiceProvider).OnReceiveAbort(pdu.Source, pdu.Reason); } else if (this is IDicomServiceUser) { (this as IDicomServiceUser).OnReceiveAbort(pdu.Source, pdu.Reason); } _network.Close(); _isConnected = false; break; } case 0xFF: { break; } default: throw new DicomNetworkException("Unknown PDU type"); } BeginReadPDUHeader(); } catch (Exception e) { Logger.Log(LogLevel.Error, "Exception processing PDU: {0}", e.ToString()); _network.Close(); _isConnected = false; } }
private void SendRawPDU(RawPDU pdu) { try { lock (_socket) { _disableTimeout = true; pdu.WritePDU(_network); _disableTimeout = false; } } catch (Exception e) { #if DEBUG Log.Error("{0} -> Error sending PDU [type: 0x{1:x2}]: {2}", LogID, pdu.Type, e.ToString()); #else Log.Error("{0} -> Error sending PDU [type: 0x{1:x2}]: {2}", LogID, pdu.Type, e.Message); #endif OnNetworkError(e); } }
/// <summary> /// Factory method for creating <see cref="DicomExtendedNegotiation"/> instances. /// </summary> /// <param name="raw">Raw PDU.</param> /// <param name="length">Length.</param> /// <returns>A new <see cref="DicomExtendedNegotiation"/> instance.</returns> public static DicomExtendedNegotiation Create(RawPDU raw, ushort length) { var uidLen = raw.ReadUInt16("SOP Class UID Length"); var uidStr = raw.ReadString("SOP Class UID", uidLen); var uid = DicomUID.Parse(uidStr); IExtendedNegotiationSubItem subItem = null; var subItemSize = 0; var remaining = length - uidLen - 2; if (subItemCreators.ContainsKey(uid)) { subItem = subItemCreators[uid](raw, remaining, out subItemSize); } remaining -= subItemSize; if (remaining > 0) { raw.SkipBytes("Unread bytes", remaining); } return new DicomExtendedNegotiation(uid, subItem); }