internal bool SendPdu(ServiceClass service, string message, DicomObject pdu) { //Logging.Log("Association.SendPdu"); try { if (State == State.Aborted) { throw AbortException; } MemoryStream memory = new MemoryStream(); pdu.Write(memory); NetworkStream output = new NetworkStream(socket, FileAccess.Write, false); byte[] bytes = memory.ToArray(); Dump(">> " + message, bytes); if (service != null) { service.LastMessage = null; } output.Write(bytes, 0, (int)memory.Length); State = (State != State.Closing) ? State.Waiting : State; } catch (Exception ex) { Logging.Log(LogLevel.Error, ex.Message); throw; } return(true); }
protected ServiceClass(ServiceClass other) { this.association = null; this.uid = other.uid; foreach (string syntax in other.syntaxes) { this.syntaxes.Add((string)syntax.Clone()); } completeEvent = new System.Threading.AutoResetEvent(false); this.id = 0xff; this.reason = PCIReason.Undefined; this.role = other.role; }
internal bool SendPdu(ServiceClass service, MessageType type, string message, DataSet dicom) { bool result = true; if (State == State.Aborted) { throw AbortException; } if (service != null) { service.LastMessage = null; } dicom.Part10Header = false; dicom.TransferSyntaxUID = MessageControl.IsCommand(type) ? Syntax.ImplicitVrLittleEndian : service.Syntaxes[0]; MemoryStream memory = new MemoryStream(); dicom.Write(memory); byte[] bytes = memory.ToArray(); PresentationDataPdu pdu = null; PresentationDataValue pdv = null; int index = 0; int remaining = (int)memory.Length; int size = this.packetSize - 128; State = (State != State.Closing) ? State.Waiting : State; while (remaining > this.packetSize && result) { pdu = new PresentationDataPdu(service.Syntaxes[0]); pdv = new PresentationDataValue(service.PresentationContextId, service.Syntaxes[0], type, bytes, index, size); pdu.Values.Add(pdv); result = Send(message, pdu); index += size; remaining -= size; } if (result) { pdu = new PresentationDataPdu(service.Syntaxes[0]); pdv = new PresentationDataValue(service.PresentationContextId, service.Syntaxes[0], type + 2, bytes, index, remaining); pdu.Values.Add(pdv); result = Send(message, pdu); } return(result); }
internal bool SendDataPdu(ServiceClass service, string message, DataSet dicom) { bool result = true; dicom.Part10Header = false; dicom.TransferSyntaxUID = service.Syntaxes[0]; MemoryStream memory = new MemoryStream(); dicom.Write(memory); byte[] bytes = memory.ToArray(); PresentationDataPdu pdu = null; PresentationDataValue pdv = null; int index = 0; int remaining = (int)memory.Length; int size = this.packetSize - 128; while (remaining > this.packetSize && result) { pdu = new PresentationDataPdu(service.Syntaxes[0]); pdv = new PresentationDataValue(service.PresentationContextId, service.Syntaxes[0], MessageType.DataSet, bytes, index, size); pdu.Values.Add(pdv); result = SendPdu(service, message, pdu); index += size; remaining -= size; } if (result) { pdu = new PresentationDataPdu(service.Syntaxes[0]); pdv = new PresentationDataValue(service.PresentationContextId, service.Syntaxes[0], MessageType.LastDataSet, bytes, index, remaining); pdu.Values.Add(pdv); result = SendPdu(service, message, pdu); } return(result); }
public void AddService(ServiceClass service) { services.Add(service); }
private void PduDataReceived(byte[] pdu) { //Logging.Log("PduDataReceived {0}", pdu); //Dump("<< P-DATA-TF", pdu); // TODO this must be able to handle multiple pdvs string syntax = Syntax.ImplicitVrLittleEndian; ServiceClass service = FindServiceClass(pdu[10]); if (service != null) { syntax = service.Syntaxes[0]; } // TODO currently assuming that a Command comes in a single pdu // TODO all DataSet fragments are combined into a single Message if (MessageControl.IsDataSet((MessageType)pdu[11])) { //Logging.Log("dataset"); if (MessageControl.IsNotLast((MessageType)pdu[11])) { //Logging.Log("not last fragment"); if (file == null) { file = new FileStream(Guid.NewGuid().ToString() + ".tmp", FileMode.Create, FileAccess.ReadWrite); //Dump("PduDataReceived1 ...", pdu); } else { //Logging.Log("Receiving {0} bytes", pdu.Length - 12); } file.Write(pdu, 12, pdu.Length - 12); return; } else { //Logging.Log("last fragment"); if (file != null) { Dump("PduDataReceived2 ...", pdu); file.Write(pdu, 12, pdu.Length - 12); file.Flush(); DataSet dicom = new DataSet(); dicom.TransferSyntaxUID = syntax; file.Seek(0, SeekOrigin.Begin); dicom.Read(file); if (service != null) { try { service.LastMessage = new Message(dicom); ((IPresentationDataSink)service).OnData(MessageType.LastDataSet, service.LastMessage); } catch (Exception ex) { Logging.Log(LogLevel.Error, "Exception in OnData for SOPClassUId={0}, {1}", service.SOPClassUId, ex.Message); } } file.Close(); File.Delete(file.Name); file = null; return; } } } // parse response MemoryStream memory = new MemoryStream(pdu, 0, pdu.Length); PresentationDataPdu response = new PresentationDataPdu(syntax); response.Read(memory); response.Dump(); foreach (PresentationDataValue pdv in response.Values) { service = FindServiceClass(pdv.context); if (service != null && service is IPresentationDataSink) { service.LastMessage = new Message(pdv.Dicom); ((IPresentationDataSink)service).OnData(pdv.control, service.LastMessage); } } }
private void AssociateRequestReceived(byte[] pdu) { Dump("<< A-ASSOCIATE-RQ", pdu); //#if DEBUG // if (number != 0) Console.WriteLine("association {0,4} opened", number); //#endif bool reject = true; // parse request MemoryStream memory = new MemoryStream(pdu, 0, pdu.Length); AssociateRequestPdu request = new AssociateRequestPdu(); request.Read(memory); //request.Dump(); CallingAeTitle = request.calling.TrimEnd(); AssociateRequestPdu accept = new AssociateRequestPdu(ProtocolDataUnit.Type.A_ASSOCIATE_AC, request.called, request.calling); // record as much as we can about the caller IPEndPoint lep = socket.LocalEndPoint as IPEndPoint; if (lep != null) { scp = new ApplicationEntity(request.calling.TrimEnd(" ".ToCharArray()), lep.Address, lep.Port); } else { scp = new ApplicationEntity(request.calling.TrimEnd(" ".ToCharArray()), 0); } IPEndPoint rep = socket.RemoteEndPoint as IPEndPoint; if (rep != null) { scu = new ApplicationEntity(request.calling.TrimEnd(" ".ToCharArray()), rep.Address, rep.Port); CallingAeIpAddress = rep.Address; } else { scu = new ApplicationEntity(request.calling.TrimEnd(" ".ToCharArray()), 0); } foreach (Item item in request.fields) { switch ((ItemType)item.Type) { case ItemType.ApplicationItem: ApplicationContextItem aci = item as ApplicationContextItem; accept.fields.Add(aci); break; case ItemType.PresentationContextItemRQ: PresentationContextItem temp = item as PresentationContextItem; PresentationContextItem response = new PresentationContextItem((byte)ItemType.PresentationContextItemAC, temp.PresentationContextId); SyntaxItem abs = ((SyntaxItem)temp.fields[0]); ServiceClass service = null; SyntaxItem transfer = null; for (int n = 1; n < temp.fields.Count; n++) { transfer = temp.fields[n] as SyntaxItem; service = FindServiceClass(abs.Syntax, transfer.Syntax); if (service != null) { break; } } if (service == null) { response.PciReason = PCIReason.AbstractSyntaxNotSupported; Logging.Log("SCU Reject PresentationContext={0} abstract={1}", temp.PresentationContextId, Reflection.GetName(typeof(SOPClass), abs.Syntax)); } else { service.PresentationContextId = temp.PresentationContextId; service.Syntaxes.Clear(); service.Syntaxes.Add(transfer.Syntax); service.PciReason = response.PciReason = PCIReason.Accepted; Logging.Log("SCU Accept PresentationContext={0} abstract={1} transfer={2}", service.PresentationContextId, Reflection.GetName(typeof(SOPClass), abs.Syntax), Reflection.GetName(typeof(Syntax), transfer.Syntax)); reject = false; } response.fields.Add(transfer); accept.fields.Add(response); break; case ItemType.UserInformationItem: UserInfoItem uii = item as UserInfoItem; int count = uii.fields.Count; // note: this is editing the sent UserInfoItem in place rather // than making a new object, make a new object for (int n = count - 1; n >= 0; n--) { Item field = uii.fields[n]; switch ((ItemType)field.Type) { case ItemType.MaximumLengthSubItem: { MaximumLengthItem length = field as MaximumLengthItem; packetSize = length.PacketSize; } break; case ItemType.ImplementationClassUidSubItem: { SyntaxItem implementation = field as SyntaxItem; implementation.Syntax = ImplementationClassUid; } break; case ItemType.ImplementationVersionNameSubItem: { SyntaxItem implementation = field as SyntaxItem; implementation.Syntax = version; } break; case ItemType.AsynchronousOperationsWindowSubItem: case ItemType.ScuScpRoleSubItem: default: uii.fields.RemoveAt(n); break; } } accept.fields.Add(uii); break; default: break; } } if (reject) { Abort(AbortSource.ServiceProvider, AbortReason.NoReasonGiven); } else { Send("A-ASSOCIATE-AC", accept); } }
private void OnOpening(byte [] pdu) { // parse response MemoryStream memory = new MemoryStream(pdu, 0, pdu.Length); switch ((ProtocolDataUnit.Type)pdu[0]) { case ProtocolDataUnit.Type.A_ASSOCIATE_AC: { Dump("<< A-ASSOCIATE-AC", pdu); AssociateRequestPdu response = new AssociateRequestPdu(); response.Read(memory); //response.Dump(); foreach (Item item in response.fields) { Logging.Log(item.Dump()); switch ((ItemType)item.Type) { case ItemType.PresentationContextItemAC: PresentationContextItem pci = item as PresentationContextItem; SyntaxItem transfer = ((SyntaxItem)pci.fields[0]); ServiceClass service = FindServiceClass(pci.PresentationContextId); if (service != null) { service.Syntaxes.Clear(); service.PciReason = pci.PciReason; if (service.PciReason == PCIReason.Accepted) { service.Syntaxes.Add(transfer.Syntax); Logging.Log("SCP Accept PresentationContext={0} class={1} syntax={2}", pci.PresentationContextId, Reflection.GetName(typeof(SOPClass), service.SOPClassUId), Reflection.GetName(typeof(Syntax), transfer.Syntax)); } else { Logging.Log("SCP Reject PresentationContext={0} class={1} syntax={2}", pci.PresentationContextId, Reflection.GetName(typeof(SOPClass), service.SOPClassUId), Reflection.GetName(typeof(Syntax), transfer.Syntax)); } } else { Logging.Log(LogLevel.Error, "SCP unknown PresentationContext={0} reason={1} class={2} syntax={3}", pci.PresentationContextId, pci.PciReason, Reflection.GetName(typeof(SOPClass), service.SOPClassUId), Reflection.GetName(typeof(Syntax), transfer.Syntax)); } break; case ItemType.UserInformationItem: UserInfoItem uii = item as UserInfoItem; int count = uii.fields.Count; for (int n = count - 1; n >= 0; n--) { Item field = uii.fields[n]; if ((ItemType)field.Type == ItemType.MaximumLengthSubItem) { MaximumLengthItem length = field as MaximumLengthItem; packetSize = length.PacketSize; } } break; } } State = State.Open; } break; case ProtocolDataUnit.Type.A_ASSOCIATE_RJ: { AssociateRejectPdu response = new AssociateRejectPdu(); response.Read(memory); State = State.Closed; Dump("<< A-ASSOCIATE-RJ", pdu); } break; default: State = State.Closed; Dump(String.Format("<< UNEXPECTED PDU(0x{0:x4})", pdu[0]), pdu); break; } if (completeEvent != null) { completeEvent.Set(); } }
/// <summary> /// Adds a Service to the Association. /// </summary> /// <param name="service"></param> public void AddService(ServiceClass service) { service.Association = this; services.Add(service); }