netdicom

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2020 License: Apache-2.0 Imports: 19 Imported by: 0

README

GoDoc Build Status

Golang implementation of DICOM network protocol.

See doc.go for (incomplete) documentation. See storeclient and storeserver for examples.

Inspired by https://github.com/pydicom/pynetdicom3.

Status as of 2017-10-02:

  • C-STORE, C-FIND, C-GET work, both for the client and the server. Look at sampleclient, sampleserver, or e2e_test.go for examples. In general, the server (provider)-side code is better tested than the client-side code.

  • Compatibility has been tested against pynetdicom and Osirix MD.

TODO:

  • Documentation.

  • Better SSL support.

  • Implement the rest of DIMSE protocols, in particular C-MOVE on the client side, and N-* commands.

  • Better message validation.

  • Remove the "limit" param from the Decoder, and rely on io.EOF detection instead.

Documentation

Overview

Package netdicom implements the DICOM network protocol.

This package exports two main classes: ServiceUser for implementing DICOM clients, and ServiceProvider for implementing DICOM servers.

Index

Constants

View Source
const DefaultMaxPDUSize = 4 << 20

DefaultMaxPDUSize is the the PDU size advertized by go-netdicom.

Variables

This section is empty.

Functions

func RunProviderForConn

func RunProviderForConn(conn net.Conn, params ServiceProviderParams)

RunProviderForConn starts threads for running a DICOM server on "conn". This function returns immediately; "conn" will be cleaned up in the background.

func SetProviderFaultInjector

func SetProviderFaultInjector(f FaultInjector)

SetProviderFaultInjector sets the fault injector to be used by all provider (server) side statemachines.

func SetUserFaultInjector

func SetUserFaultInjector(f FaultInjector)

SetUserFaultInjector sets the fault injector to be used by all user (client) side statemachines.

Types

type CEchoCallback

type CEchoCallback func(conn ConnectionState) dimse.Status

CEchoCallback implements C-ECHO callback. It typically just returns dimse.Success.

type CFindCallback

type CFindCallback func(
	conn ConnectionState,
	transferSyntaxUID string,
	sopClassUID string,
	filters []*dicom.Element,
	ch chan CFindResult)

CFindCallback implements a C-FIND handler. sopClassUID is the data type requested (e.g.,"1.2.840.10008.5.1.4.1.1.1.2"), and transferSyntaxUID is the data encoding requested (e.g., "1.2.840.10008.1.2.1"). These args are extracted from the request packet.

This function should stream CFindResult objects through "ch". The function may block. To report a matched DICOM dataset, the function should send one CFindResult with a nonempty Element field. To report multiple DICOM-dataset matches, the callback should send multiple CFindResult objects, one for each dataset. The callback must close the channel after it produces all the responses.

type CFindResult

type CFindResult struct {
	// Exactly one of Err or Elements is set.
	Err      error
	Elements []*dicom.Element // Elements belonging to one dataset.
}

CFindResult is an object streamed by CFind method.

type CMoveCallback

type CMoveCallback func(
	conn ConnectionState,
	transferSyntaxUID string,
	sopClassUID string,
	filters []*dicom.Element,
	ch chan CMoveResult)

CMoveCallback implements C-MOVE or C-GET handler. sopClassUID is the data type requested (e.g.,"1.2.840.10008.5.1.4.1.1.1.2"), and transferSyntaxUID is the data encoding requested (e.g., "1.2.840.10008.1.2.1"). These args are extracted from the request packet.

The callback must stream datasets or error to "ch". The callback may block. The callback must close the channel after it produces all the datasets.

type CMoveResult

type CMoveResult struct {
	Remaining int // Number of files remaining to be sent. Set -1 if unknown.
	Err       error
	Path      string         // Path name of the DICOM file being copied. Used only for reporting errors.
	DataSet   *dicom.DataSet // Contents of the file.
}

CMoveResult is an object streamed by CMove implementation.

type CStoreCallback

type CStoreCallback func(
	conn ConnectionState,
	transferSyntaxUID string,
	sopClassUID string,
	sopInstanceUID string,
	data []byte) dimse.Status

CStoreCallback is called C-STORE request. sopInstanceUID is the UID of the data. sopClassUID is the data type requested (e.g.,"1.2.840.10008.5.1.4.1.1.1.2"), and transferSyntaxUID is the encoding of the data (e.g., "1.2.840.10008.1.2.1"). These args are extracted from the request packet.

"data" is the payload, i.e., a sequence of serialized dicom.DataElement objects in transferSyntaxUID. "data" does not contain metadata elements (elements whose Tag.Group=2 -- e.g., TransferSyntaxUID and MediaStorageSOPClassUID), since they are stripped by the requster (two key metadata are passed as sop{Class,Instance)UID).

The function should store encode the sop{Class,InstanceUID} as the DICOM header, followed by data. It should return either dimse.Success0 on success, or one of CStoreStatus* error codes on errors.

type ConnectionState

type ConnectionState struct {
	// TLS connection state. It is nonempty only when the connection is set up
	// over TLS.
	TLS tls.ConnectionState
}

ConnectionState informs session state to callbacks.

type FaultInjector

type FaultInjector interface {
	fmt.Stringer
	// contains filtered or unexported methods
}

FaultInjector is a unittest helper. It's used by the statemachine to inject faults.

func NewFuzzFaultInjector

func NewFuzzFaultInjector(fuzz []byte) FaultInjector

NewFuzzFaultInjector creates a new fuzzing fault injector

type QRLevel

type QRLevel int

QRLevel is used to specify the element hierarchy assumed during C-FIND, C-GET, and C-MOVE. P3.4, C.3.

http://dicom.nema.org/Dicom/2013/output/chtml/part04/sect_C.3.html

const (
	// QRLevelPatient chooses Patient-Root QR model.  P3.4, C.3.1
	QRLevelPatient QRLevel = iota

	// QRLevelStudy chooses Study-Root QR model.  P3.4, C.3.2
	QRLevelStudy

	// QRLevelSeries chooses Study-Root QR model, but using "SERIES" QueryRetrieveLevel.  P3.4, C.3.2
	QRLevelSeries
)

func (QRLevel) String

func (i QRLevel) String() string

type ServiceProvider

type ServiceProvider struct {
	// contains filtered or unexported fields
}

ServiceProvider encapsulates the state for DICOM server (provider).

func NewServiceProvider

func NewServiceProvider(params ServiceProviderParams, port string) (*ServiceProvider, error)

NewServiceProvider creates a new DICOM server object. "listenAddr" is the TCP address to listen to. E.g., ":1234" will listen to port 1234 at all the IP address that this machine can bind to. Run() will actually start running the service.

func (*ServiceProvider) ListenAddr

func (sp *ServiceProvider) ListenAddr() net.Addr

ListenAddr returns the TCP address that the server is listening on. It is the address passed to the NewServiceProvider(), except that if value was of form <name>:0, the ":0" part is replaced by the actual port numwber.

func (*ServiceProvider) Run

func (sp *ServiceProvider) Run()

Run listens to incoming connections, accepts them, and runs the DICOM protocol. This function never returns.

type ServiceProviderParams

type ServiceProviderParams struct {
	// The application-entity title of the server. Must be nonempty
	AETitle string

	// Names of remote AEs and their host:ports. Used only by C-MOVE. This
	// map should be nonempty iff the server supports CMove.
	RemoteAEs map[string]string

	// Called on C_ECHO request. If nil, a C-ECHO call will produce an error response.
	//
	// TODO(saito) Support a default C-ECHO callback?
	CEcho CEchoCallback

	// Called on C_FIND request.
	// If CFindCallback=nil, a C-FIND call will produce an error response.
	CFind CFindCallback

	// CMove is called on C_MOVE request.
	CMove CMoveCallback

	// CGet is called on C_GET request. The only difference between cmove
	// and cget is that cget uses the same connection to send images back to
	// the requester. Generally you shuold set the same function to CMove
	// and CGet.
	CGet CMoveCallback

	// If CStoreCallback=nil, a C-STORE call will produce an error response.
	CStore CStoreCallback

	// TLSConfig, if non-nil, enables TLS on the connection. See
	// https://gist.github.com/michaljemala/d6f4e01c4834bf47a9c4 for an
	// example for creating a TLS config from x509 cert files.
	TLSConfig *tls.Config
}

ServiceProviderParams defines parameters for ServiceProvider.

type ServiceUser

type ServiceUser struct {
	// contains filtered or unexported fields
}

ServiceUser encapsulates implements the client side of DICOM network protocol.

user, err := netdicom.NewServiceUser(netdicom.ServiceUserParams{SOPClasses: sopclass.QRFindClasses})
// Connect to server 1.2.3.4, port 8888
user.Connect("1.2.3.4:8888")
// Send test.dcm to the server
ds, err := dicom.ReadDataSetFromFile("test.dcm", dicom.ReadOptions{})
err := user.CStore(ds)
// Disconnect
user.Release()

The ServiceUser class is thread compatible. That is, you cannot call C* methods - say CStore and CFind requests - concurrently from two goroutines. You must wait for CStore to finish before issuing CFind.

func NewServiceUser

func NewServiceUser(params ServiceUserParams) (*ServiceUser, error)

NewServiceUser creates a new ServiceUser. The caller must call either Connect() or SetConn() before calling any other method, such as Cstore.

func (*ServiceUser) CEcho

func (su *ServiceUser) CEcho() error

CEcho send a C-ECHO request to the remote AE and waits for a response. Returns nil iff the remote AE responds ok.

func (*ServiceUser) CFind

func (su *ServiceUser) CFind(qrLevel QRLevel, filter []*dicom.Element) chan CFindResult

CFind issues a C-FIND request. Returns a channel that streams sequence of either an error or a dataset found. The caller MUST read all responses from the channel before issuing any other DIMSE command (C-FIND, C-STORE, etc).

The param sopClassUID is one of the UIDs defined in sopclass.QRFindClasses. filter is the list of elements to match and retrieve.

REQUIRES: Connect() or SetConn has been called.

func (*ServiceUser) CGet

func (su *ServiceUser) CGet(qrLevel QRLevel, filter []*dicom.Element,
	cb func(transferSyntaxUID, sopClassUID, sopInstanceUID string, data []byte) dimse.Status) error

CGet runs a C-GET command. It calls "cb" sequentially for every dataset received. "cb" should return dimse.Success iff the data was successfully and stably written. This function blocks until it receives all datasets from the server.

The "data" arg to "cb" is the serialized dataset, encoded according to transferSyntaxUID.

TODO(saito) We should parse the data into DataSet before passing to "cb".

func (*ServiceUser) CStore

func (su *ServiceUser) CStore(ds *dicom.DataSet) error

CStore issues a C-STORE request to transfer "ds" in remove peer. It blocks until the operation finishes.

REQUIRES: Connect() or SetConn has been called.

func (*ServiceUser) Connect

func (su *ServiceUser) Connect(serverAddr string)

Connect connects to the server at the given "host:port". Either Connect or SetConn must be before calling CStore, etc.

func (*ServiceUser) Release

func (su *ServiceUser) Release()

Release shuts down the connection. It must be called exactly once. After Release(), no other operation can be performed on the ServiceUser object.

func (*ServiceUser) SetConn

func (su *ServiceUser) SetConn(conn net.Conn)

SetConn instructs ServiceUser to use the given network connection to talk to the server. Either Connect or SetConn must be before calling CStore, etc.

type ServiceUserParams

type ServiceUserParams struct {
	// Application-entity title of the peer. If empty, set to "unknown-called-ae"
	CalledAETitle string
	// Application-entity title of the client. If empty, set to
	// "unknown-calling-ae"
	CallingAETitle string

	// List of SOPUIDs wanted by the client. The value is typically one of
	// the constants listed in sopclass package.
	SOPClasses []string

	// List of Transfer syntaxes supported by the user.  If you know the
	// transer syntax of the file you are going to copy, set that here.
	// Otherwise, you'll need to re-encode the data w/ the given transfer
	// syntax yourself.
	//
	// TODO(saito) Support reencoding internally on C_STORE, etc. The DICOM
	// spec is particularly moronic here, since we could just have specified
	// the transfer syntax per data sent.
	TransferSyntaxes []string
}

ServiceUserParams defines parameters for a ServiceUser.

Directories

Path Synopsis
A sample program for issuing C-STORE or C-FIND to a remote server.
A sample program for issuing C-STORE or C-FIND to a remote server.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL