public void Register(ApplicationEntity entity) { if (hosts.ContainsKey(entity.Title)) { hosts[entity.Title] = entity; } else { hosts.Add(entity.Title, entity); } }
/// <summary> /// Establish an association between two Dicom devices. /// </summary> /// <param name="scp">The called device.</param> /// <param name="scu">The calling device.</param> /// <returns></returns> public bool Open(ApplicationEntity scp, ApplicationEntity scu) { this.scp = scp; this.scu = scu; // connect if (!Connect(scp.Address, scp.Port)) { return(false); } machineThread = new Thread(new ThreadStart(StateMachine)); machineThread.Name = "Association.StateMachine"; machineThread.Start(); if (!threadEvent.WaitOne(timeout, false)) { Logging.Log("Background thread not started."); State = State.Closed; return(false); } // get request AssociateRequestPdu pdu = GetAssociationRequestPdu(); // write pdu MemoryStream memory = new MemoryStream(); pdu.Write(memory); //pdu.Dump(); Dump(">> " + "A-ASSOCIATE-RQ", memory.ToArray()); State = State.Opening; NetworkStream output = new NetworkStream(socket, FileAccess.Write, false); output.Write(memory.ToArray(), 0, (int)memory.Length); if (!completeEvent.WaitOne(timeout, false)) { Logging.Log("A-ASSOCIATE-RQ FAILED"); State = State.Closed; return(false); } return(State == State.Open); }
private bool SendImage(ApplicationEntity host, string path) { bool result = true; try { DataSet dicom = new DataSet(); dicom.Read(path); string uid = (string)dicom[t.SOPClassUID].Value; StorageServiceSCU storage = new StorageServiceSCU(uid); storage.Syntaxes.Add(Syntax.ImplicitVrLittleEndian); Association association = new Association(); association.AddService(storage); if (association.Open(host)) { if (storage.Active) { try { storage.Store(dicom); } catch (Exception ex) { result = false; Debug.WriteLine(ex.Message); } } } else { result = false; //Debug.WriteLine("\ncan't Open."); } association.Close(); } catch (Exception) { result = false; } return(result); }
private void ParseApplicationEntity(string line, Dictionary <string, ApplicationEntity> hosts) { string[] parts = line.Split(",".ToCharArray()); if (parts.Length >= 3) { string title = parts[0].ToUpper().Trim(); if (!hosts.ContainsKey(title)) { hosts[title] = new ApplicationEntity(title, IPAddress.Parse(parts[1].Trim()), Int32.Parse(parts[2].Trim())); } else { Logging.Log(LogLevel.Warning, String.Format("ignoring duplicate hosts entry, line={0}.", line)); } } else { Logging.Log(LogLevel.Error, String.Format("hosts entry has too few fields, line={0}.", line)); } }
public void OnData(MessageType control, Message message) { Logging.Log("\nCMoveServiceSCP({0}).OnData", Reflection.GetName(typeof(SOPClass), this.SOPClassUId)); DataSet dicom = message.Dicom; if (MessageControl.IsCommand(control)) { MessageId = (ushort)dicom[t.MessageId].Value; // TODO accomodate trailing spaces destination = ((string)dicom[t.MoveDestination].Value).TrimEnd(); } else { PresentationDataValue pdv; PresentationDataPdu command; DataSet fragment = new DataSet(); if (!this.Association.Hosts.ContainsKey(destination)) { pdv = new PresentationDataValue(PresentationContextId, Syntaxes[0], MessageType.LastCommand); fragment.Part10Header = false; fragment.TransferSyntaxUID = syntaxes[0]; fragment.Add(t.GroupLength(0), (uint)0); fragment.Add(t.AffectedSOPClassUID, this.SOPClassUId); fragment.Add(t.CommandField, (ushort)CommandType.C_MOVE_RSP); fragment.Add(t.MessageIdBeingRespondedTo, MessageId); fragment.Add(t.CommandDataSetType, (ushort)DataSetType.DataSetNotPresent); fragment.Add(t.Status, (ushort)0xA801); pdv.Dicom = fragment; command = new PresentationDataPdu(syntaxes[0]); command.Values.Add(pdv); SendPdu("C-MOVE-RSP", command); return; } ApplicationEntity host = this.Association.Hosts[destination]; List <string> imagelist = Query(dicom); int failed = 0; for (int n = 0; n < imagelist.Count; n++) { if (!SendImage(host, imagelist[n])) { failed++; } pdv = new PresentationDataValue(PresentationContextId, Syntaxes[0], MessageType.LastCommand); fragment = new DataSet(); fragment.Part10Header = false; fragment.TransferSyntaxUID = syntaxes[0]; fragment.Add(t.GroupLength(0), (uint)0); fragment.Add(t.AffectedSOPClassUID, this.SOPClassUId); fragment.Add(t.CommandField, (ushort)CommandType.C_MOVE_RSP); fragment.Add(t.MessageIdBeingRespondedTo, MessageId); fragment.Add(t.CommandDataSetType, (ushort)DataSetType.DataSetPresent); fragment.Add(t.Status, (ushort)0xff00); fragment.Set(t.NumberofRemainingSuboperations, imagelist.Count - n - 1); fragment.Set(t.NumberofCompletedSuboperations, n + 1 - failed); fragment.Set(t.NumberofFailedSuboperations, failed); fragment.Set(t.NumberofWarningSuboperations, 0); pdv.Dicom = fragment; command = new PresentationDataPdu(syntaxes[0]); command.Values.Add(pdv); SendPdu("C-MOVE-RSP", command); } int status = (failed > 0) ? 0xB000 : 0x0000; pdv = new PresentationDataValue(PresentationContextId, Syntaxes[0], MessageType.LastCommand); fragment = new DataSet(); fragment.Part10Header = false; fragment.TransferSyntaxUID = syntaxes[0]; fragment.Add(t.GroupLength(0), (uint)0); fragment.Add(t.AffectedSOPClassUID, this.SOPClassUId); fragment.Add(t.CommandField, (ushort)CommandType.C_FIND_RSP); fragment.Add(t.MessageIdBeingRespondedTo, MessageId); fragment.Add(t.CommandDataSetType, (ushort)DataSetType.DataSetNotPresent); fragment.Add(t.Status, (ushort)status); fragment.Set(t.NumberofCompletedSuboperations, imagelist.Count); fragment.Set(t.NumberofFailedSuboperations, 0); fragment.Set(t.NumberofWarningSuboperations, 0); pdv.Dicom = fragment; command = new PresentationDataPdu(syntaxes[0]); command.Values.Add(pdv); SendPdu("C-MOVE-RSP", command); } }
public Server(ApplicationEntity host) : this(host.Title, host.Port) { }
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); } }
/// <summary> /// Establish an association with an SCP using the current machine name as the calling AE title. /// </summary> /// <param name="provider">The AE title of the SCP.</param> /// <param name="address">The TCP/IP address of the SCP.</param> /// <param name="port">The TCP/IP port of the SCP.</param> /// <returns></returns> public bool Open(ApplicationEntity host) { return(Open(host, new ApplicationEntity(Dns.GetHostName(), IPAddress.Loopback, 0))); }