forked from grailbio/go-netdicom
-
Notifications
You must be signed in to change notification settings - Fork 3
/
cstore.go
90 lines (86 loc) · 3.06 KB
/
cstore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package netdicom
import (
"fmt"
"github.com/grailbio/go-dicom"
"github.com/grailbio/go-dicom/dicomio"
"github.com/grailbio/go-dicom/dicomlog"
"github.com/grailbio/go-dicom/dicomtag"
"github.com/grailbio/go-dicom/dicomuid"
"github.com/grailbio/go-netdicom/dimse"
)
// Helper function used by C-{STORE,GET,MOVE} to send a dataset using C-STORE
// over an already-established association.
func runCStoreOnAssociation(upcallCh chan upcallEvent, downcallCh chan stateEvent,
cm *contextManager, messageID dimse.MessageID,
ds *dicom.DataSet, opts *dicom.WriteOptSet) error {
var getElement = func(tag dicomtag.Tag) (string, error) {
elem, err := ds.FindElementByTag(tag)
if err != nil {
return "", fmt.Errorf("dicom.cstore: data lacks %s: %v", tag.String(), err)
}
s, err := elem.GetString()
if err != nil {
return "", err
}
return s, nil
}
sopInstanceUID, err := getElement(dicomtag.MediaStorageSOPInstanceUID)
if err != nil {
return fmt.Errorf("dicom.cstore: data lacks SOPInstanceUID: %v", err)
}
sopClassUID, err := getElement(dicomtag.MediaStorageSOPClassUID)
if err != nil {
return fmt.Errorf("dicom.cstore: data lacks MediaStorageSOPClassUID: %v", err)
}
dicomlog.Vprintf(1, "dicom.cstore(%s): DICOM abstractsyntax: %s, sopinstance: %s", cm.label, dicomuid.UIDString(sopClassUID), sopInstanceUID)
context, err := cm.lookupByAbstractSyntaxUID(sopClassUID)
if err != nil {
dicomlog.Vprintf(0, "dicom.cstore(%s): sop class %v not found in context %v", cm.label, sopClassUID, err)
return err
}
dicomlog.Vprintf(1, "dicom.cstore(%s): using transfersyntax %s to send sop class %s, instance %s",
cm.label,
dicomuid.UIDString(context.transferSyntaxUID),
dicomuid.UIDString(sopClassUID),
sopInstanceUID)
bodyEncoder := dicomio.NewBytesEncoderWithTransferSyntax(context.transferSyntaxUID)
for _, elem := range ds.Elements {
if elem.Tag.Group == dicomtag.MetadataGroup {
continue
}
dicom.WriteElement(bodyEncoder, elem, opts)
}
if err := bodyEncoder.Error(); err != nil {
dicomlog.Vprintf(0, "dicom.cstore(%s): body encoder failed: %v", cm.label, err)
return err
}
downcallCh <- stateEvent{
event: evt09,
dimsePayload: &stateEventDIMSEPayload{
abstractSyntaxName: sopClassUID,
command: &dimse.CStoreRq{
AffectedSOPClassUID: sopClassUID,
MessageID: messageID,
CommandDataSetType: dimse.CommandDataSetTypeNonNull,
AffectedSOPInstanceUID: sopInstanceUID,
},
data: bodyEncoder.Bytes(),
},
}
for {
dicomlog.Vprintf(0, "dicom.cstore(%s): Start reading resp w/ messageID:%v", cm.label, messageID)
event, ok := <-upcallCh
if !ok {
return fmt.Errorf("dicom.cstore(%s): Connection closed while waiting for C-STORE response", cm.label)
}
dicomlog.Vprintf(1, "dicom.cstore(%s): resp event: %v", cm.label, event.command)
doassert(event.eventType == upcallEventData)
doassert(event.command != nil)
resp, ok := event.command.(*dimse.CStoreRsp)
doassert(ok) // TODO(saito)
if resp.Status.Status != 0 {
return fmt.Errorf("dicom.cstore(%s): failed: %v", cm.label, resp.String())
}
return nil
}
}