Releases: godicom-dev/gonetdicom
Releases · godicom-dev/gonetdicom
Release list
v0.16.0
A robustness release. Most of it is the audit of the wire decoders, the SCP
association lifecycle and the DICOMweb handlers
(#39); the two
negotiation and C-MOVE fixes that head Fixed came out of following that work up
(#42,
#41).
No exported symbol was removed. Three behaviour changes are visible to callers
and are listed under Changed, each with the way to restore the old behaviour.
Security
pdu.Readno longer sizes its buffer from the declared length, where six bytes
from an unauthenticated peer bought a 4 GiB allocation: a 16 MiB
MaxPDUReadLengthbackstop withErrPDUTooLarge,ReadLimitfor a tighter
bound, and a chunked read that grows with bytes actually received- SCP resource limits, none of which existed:
ServerConfig.HandshakeTimeout
(30s by default),IdleTimeout(refreshed per read and per write, so it
measures silence rather than duration) andMaxConcurrentAssociations(over
the cap the peer gets an A-ASSOCIATE-RJ, not a bare close).Servealso closes
in-flight connections when its context is cancelled - SCP validates the Called AE Title and the Protocol Version during negotiation
instead of accepting whatever arrives, and rejects an empty Calling AE Title —
which used to make the SCP fail while encoding its own A-ASSOCIATE-AC and drop
the connection with no explanation - WADO-RS multipart boundaries are per-response and random. The boundary was
hard-coded, so an instance containing that delimiter line ended the body early:
HTTP 200 with silently truncated data - DICOMweb path segments are validated (
ErrInvalidPath), request and response
bodies are bounded (DefaultMaxRequestBytes,DefaultMaxResponseBytes,
WithMaxRequestBytes,WithMaxResponseBytes,ErrTooLarge), and handler
errors no longer echo store internals to the client - 32-bit wire lengths are compared in
uint64instead of being converted to
int. Whereintis 32 bits wide a DIMSE Value Length of0xFFFFFFF8came
out negative, passed its bounds check and panicked the decoder from 8 bytes; a
PDV item length of0x7FFFFFFFdid the same from 20. Not reachable in a
released build, since godicom does not compile for a 32-bit target either
Fixed
- UID padding is trimmed when decoding an A-ASSOCIATE
(#42). PS3.5 9.1 pads an
odd-length UID with a NUL and most UIDs traded during negotiation are odd
(1.2.840.10008.1.1is 17 bytes), so a conforming peer sends that byte — and
it stayed in the string, losing every comparison built on it: the SCP answered
"abstract syntax not supported" for a SOP class it supports, a proposed Role
Selection was dropped, and an accepted Transfer Syntax reached godicom naming
nothing. Covers the Application Context, Abstract Syntax, Transfer Syntax,
Implementation Class UID and Role Selection SOP Class items. Encoding is
unchanged and still writes UIDs unpadded, which is what pynetdicom sends - C-MOVE sub-operation counts saturate at 65535 instead of wrapping
(#41). The four counts
are US on the wire, but the SCP also counted inuint16, so aMovePlanof
65536 stores reportedRemaining: 0in its first Pending response — an SCU
reading that as "nothing outstanding" stopped there — and the next response
computedtotal-doneas0-1and said 65535 were outstanding, so the count
moved backwards. On the failure path 65536 failures were reported as 0: total
success under a failure status. Counting is now inintand narrowed once, at
the wire, and the final status is decided on the real counts. C-MOVE itself has
no 65535 limit, so an oversized plan is served and logged rather than rejected - One reader per SCP association. Cancel detection read the connection directly
under a 2 ms deadline, so a C-CANCEL-RQ split across TCP segments was consumed
and discarded and the next read landed mid-PDU, after which the SCP could block
forever on an open connection. Removing the per-response deadline also made
600 C-FIND matches stream in ~20 ms instead of ~1.5 s - The SCP dispatches on the Command Field rather than trying each
Decode*RQin
turn: a command set carrying no (0000,0100) satisfied all of them and was
handled as a C-ECHO. A C-CANCEL-RQ arriving after its operation finished is
logged and ignored instead of aborting the association - Presentation-context-IDs are assigned without collisions and validated before
anything is sent (ErrPresentationContexts,MaxPresentationContexts). The
oldid = 2*i+1overflowed a byte past the 128th context and ignored IDs the
caller had set, proposing one ID twice CStoreno longer writes the SOP Instance UID it generates into the caller's
Dataset, which made a reused Dataset send every instance under one identity- Message IDs are atomic, and
Abortno longer clears the connection out from
under a blocked reader — aborting a blocked C-FIND panicked on a nilnet.Conn pdurefuses to encode a value its length field cannot describe (ErrTooLong)
rather than writing a truncated length
Changed
- A requested
Priorityof MEDIUM is sent as MEDIUM. MEDIUM encodes as
0x0000, and every SCU verb read that zero as "unset" and substituted LOW, so
MEDIUM was the one priority the API could not express. An unsetPrioritynow
means MEDIUM; passdimse.PriorityLowto deprioritise a request - An SCP answers only to its own AE title. Set
ServerConfig.AllowAnyCalledAETitle, or list the titles it should answer to in
AlternativeAETitles, for the previous behaviour pdu.Readrejects a PDU declaring more thanMaxPDUReadLength(16 MiB).ae.AllStorageSOPClassesis built fromgodicom/uidconstants instead of UID
strings with names in trailing comments, five of which disagreed with the UID
beside them. The exported list is byte-identical: same 170 entries, same order- Named constants for the A-ASSOCIATE-RJ result / source / reason bytes and the
protocol version bit (pdu.RejectResultPermanent,
pdu.RejectSourceServiceUser,pdu.RejectReasonCalledAENotRecognized,
pdu.ProtocolVersion1, …)
Added
ae.UIDStringsconvertsuid.UIDvalues to the[]stringthe abstract-syntax
and transfer-syntax fields hold, so callers can name a SOP class instead of
pasting its UID- Fuzz targets over the unauthenticated wire path —
pdu.FuzzRead,
pdu.FuzzDecodePDataTF,dimse.FuzzDecodeElements,
dimse.FuzzCommandDecoders— asserting encode/decode round-trip byte identity
and full byte accounting, not just the absence of panics - CI runs ubuntu/windows/macos against Go 1.26 and 1.27, tests
./pdu ./dimse ./statuson linux/386, and fuzzes each target for 60s per run
v0.15.0
Added
log/slogfoundation aligned with godicom:WithLogger/LoggerFromContext/SetDefaultLogger, quietDiscardHandlerdefault, fixed attribute keys- AE / SCP / DICOMweb resolve
Config.Logger/Client.Loggerover context - Debug: PDU send/recv (
pdu_type_name) and DIMSE command summaries (command_name,pc_id,message_id,status)
Changed
- Depend on godicom v0.26.0
- Docs: README aligned with pynetdicom-style layout
v0.14.0
v0.13.0
What's Changed
- Depend on godicom
v0.24.0 ae.NewInstanceUID— mint SOP Instance / Transaction UIDs viauid.GenerateUID- C-STORE SCU: empty
AffectedSOPInstanceUIDfalls back toData.SOPInstanceUID, otherwise auto-minted - N-CREATE SCP: success responses without an instance UID mint one (Part 7)
Install: go get github.com/godicom-dev/gonetdicom@v0.13.0
v0.12.0
What's Changed
- Inbound C-STORE:
StoreRequest.Data≈event.dataset,StoreRequest.FileMeta≈event.file_meta - Save like storescp: compose
godicom.FileDatasetwithEnforceFileFormat: true(keeps TransferSyntaxUID for compressed/multi-frame)
Install: go get github.com/godicom-dev/gonetdicom@v0.12.0
fd := &godicom.FileDataset{Dataset: req.Data, FileMeta: req.FileMeta}
fd.SaveAs(req.AffectedSOPInstanceUID+".dcm", &godicom.WriteOptions{EnforceFileFormat: true})v0.11.0
v0.10.0
What's Changed
ae.AllStorageSOPClasses: pynetdicom_STORAGE_CLASSES/ AllStoragePresentationContexts catalog- Optional
AcceptedAbstractSyntaxes: []string{"*"}escape hatch
Install: go get github.com/godicom-dev/gonetdicom@v0.10.0
AcceptedAbstractSyntaxes: ae.AllStorageSOPClasses,v0.9.0
v0.2.0
Added
- DIMSE TLS (
Config.TLS,ListenAndServeTLS),IdleTimeout, optionalslog - DICOMweb
NewClientoptions: TLS / timeout / logger / custom HTTP client - Opt-in PACS soak:
go test -tags=integration ./ae -run TestIntegrationCEchoPACS
go get github.com/godicom-dev/gonetdicom@v0.2.0v0.1.0
First tagged release of gonetdicom.
Highlights
- DIMSE (Phase 1–2): Association SCU/SCP, C-ECHO / C-STORE / C-FIND / C-MOVE / C-GET
- DICOMweb (Phase 3): WADO-RS (study/series/instance + metadata), STOW-RS, QIDO-RS (studies/series/instances)
- Depends on godicom v0.23.0
Install
go get github.com/godicom-dev/gonetdicom@v0.1.0See CHANGELOG.md for details.