DUL Service Provider (dulprovider)¶
This module implements the DUL service provider, allowing a DUL service user to send and receive DUL messages (PDUs). The User and Provider talk to each other using a TCP socket. The DULServer runs in a thread, polling TCP socket for incoming messages and sending messages from user queue. Underlying logic of the service is implemented via state machine that is described in DICOM standard.
In most of the cases you would not need to access
DULServiceProvider directly, but rather would
use higher level objects like sub-classes of
Association or various services.
- pynetdicom2.dulprovider.CLOSE_TIMEOUT: float = 10¶
Maximum time (in seconds) to wait for the remote peer to close its side of the connection during
DULServiceProvider._close(). Without a bound a half-open or misbehaving peer would keep the association in STA_13 indefinitely. The wait is performed in small non-blocking steps so the event loop keeps running while waiting.
- pynetdicom2.dulprovider.MAX_ASSOCIATION_PDU_LENGTH = 65536¶
Upper bound (in bytes) for the body of received association PDUs. Association PDUs are exchanged before the Maximum Length negotiation takes effect, so a fixed limit is applied: 64 KiB comfortably accommodates the largest sane association PDU (e.g. one carrying 128 presentation contexts) while still protecting the provider from a peer that declares an absurd length (up to 4 GiB) in order to exhaust memory.
- pynetdicom2.dulprovider.ASSOCIATION_PDU_TYPES = frozenset({1, 2, 3})¶
PDU type bytes of the association PDUs: A-ASSOCIATE-RQ, A-ASSOCIATE-AC and A-ASSOCIATE-RJ.
- pynetdicom2.dulprovider.POLL_INTERVAL = 0.05¶
Interval (in seconds) at which the DUL event loop polls the socket for incoming data. The same interval is used to pace the loop while no socket exists so an idle provider does not spin at 100% CPU.
- pynetdicom2.dulprovider.DEFAULT_MAX_PDU_LENGTH = 65536¶
Default maximum PDU length (in bytes) used when no value is negotiated or provided by the caller.
- pynetdicom2.dulprovider.SOCKET_TIMEOUT = 30¶
Timeout (in seconds) applied to all operations on the DUL socket. Without a bound a stalled peer (e.g. one that has stopped reading) would block sends indefinitely, hanging the DUL thread and deadlocking
kill().
- pynetdicom2.dulprovider.KILL_TIMEOUT = 5¶
Maximum time (in seconds)
DULServiceProvider.kill()waits for the DUL thread to terminate.
- class pynetdicom2.dulprovider.DULServiceProvider(store_in_file: set[UID], get_file_cb: Callable[[PContextDef, Dataset], tuple[BinaryIO, int]], dul_socket: socket | None = None, max_pdu_length: int = 65536, artim_timeout: int = 10)¶
Implements DUL service.
This class is responsible for low-level operations with incoming and outgoing PDUs.
Service can be initialized by providing open socket that service would use for sending and receiving PDUs. In case the socket is not provided service opens a client socket by itself when sending
AAssociateRqPDUinstance.Underlying implementation relies on state machine that is defined in Service State Machine (fsm)
- Variables:
primitive – current PDU
dimse_gen – generator, used break current outgoing DIMSE message into P-DATA-TF PDUs
event – current event
max_pdu_length – maximum PDU length for incoming P-DATA-TF PDUs
to_service_user – outgoing data queue
from_service_user – incoming data queue
dul_socket – socket, that service uses
is_killed – DUL service termination flag
- property accepted_contexts: dict[int, PContextDef]¶
Accepted presentation contexts in the current association
- create_socket() None¶
Creates a client socket and establishes a connection.
The connection attempt is bounded by
SOCKET_TIMEOUTand no socket is leaked if the connection cannot be established.
- send(primitive: Iterator[PDataTfPDU] | AAssociatePDUBase | AAssociateRqPDU | AAssociateAcPDU | AAssociateRjPDU | PDataTfPDU | AReleasePDUBase | AReleaseRqPDU | AReleaseRpPDU | AAbortPDU) None¶
Puts PDU into outgoing queue.
Note
PDU is not immediately written into the socket, but rather put into queue that is processed by the service event loop.
- Parameters:
primitive – outgoing PDU. Possible PDU types are described in PDU Types (pdu)
- receive(timeout: float) tuple[DIMSEMessage, int] | AAssociatePDUBase | AAssociateRqPDU | AAssociateAcPDU | AAssociateRjPDU | PDataTfPDU | AReleasePDUBase | AReleaseRqPDU | AReleaseRpPDU | AAbortPDU¶
Tries to get PDU from incoming queue.
If timeout is exceeded method raises
DCMTimeoutErrorexception.- Parameters:
timeout – the amount of seconds method waits for PDU to appear in incoming queue
- Returns:
PDU instance or a tuple containing DIMSE Message and Presentation Context ID. Possible PDU types are described in PDU Types (pdu). Possible DIMSE messages are described in DIMSE Messages (dimsemessages).
- Raises:
exceptions.DCMTimeoutError – If specified timeout is exceeded
- stop() bool¶
Tries to stop service for idle association.
If association is not in idle state, method will return
Falseand association will not be stopped.- Returns:
Trueif service termination flag was successfully set (current association state was ‘idle’),Falseotherwise
- kill() None¶
Sets termination flag for event loop and waits for thread to exit.
Waits at most
KILL_TIMEOUTseconds: if a socket operation is blocked on a stalled peer the thread may take a little longer to wind down, in which case it is left to finish on its own rather than blocking the caller indefinitely.
- run() None¶
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.