Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
knopkem committed Sep 27, 2020
1 parent 3f9cf5a commit 7ccff4c
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
build
prebuilds
data
.vscode
*.dcm

Expand Down
33 changes: 24 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@
Nodejs native addon for DICOM DIMSE services using the DCMTK DICOM c++ toolkit.

# supported DIMSE services
* C-Echo-scu
* C-Find-scu
* C-Move-scu
* C-Get-scu
* C-Store-scu
* C-Store-scp
* C-Echo as SCU and SCP
* C-Find as SCU and SCP
* C-Move as SCU and SCP
* C-Get as SCU and SCP
* C-Store as SCU and SCP

# Roadmap:
* multithreaded association handling (scp)
* extended characterSet support
* JPEG 2000 support (c-store scu)

## How to install
This package uses prebuild to fetch precompiled binaries, so provided your platform is supported, all you need to do is:

```npm i -s dicom-native-addon```

Otherwise install will try to compile the sources for your platform, you will need:
Expand All @@ -29,9 +30,11 @@ Otherwise install will try to compile the sources for your platform, you will ne
## Examples

run the examples:
```npm run example:[echo|find|get|move|store]```
```npm run example:[echoscu|findscu|getscu|movescu|storescu|storescp]```

# PACS-server

# Store-SCP
## Supports: ECHO, FIND, MOVE, GET and STORE-SCP using sqlite db backend
```
const dimse = require('dicom-dimse-native');
Expand All @@ -42,7 +45,19 @@ dimse.startScp(JSON.stringify(
"ip" : "127.0.0.1",
"port": "9999"
},
"storagePath": "./data" // Directory where incoming DICOM files will be stored
"peers": [
{
"aet": "CONQUESTSRV1",
"ip" : "127.0.0.1",
"port": "5678"
},
{
"aet": "DCM4CHEE",
"ip" : "127.0.0.1",
"port": "11112"
}
],
"storagePath": "./data" // Directory where incoming DICOM files will be stored
}
), (result) => {
try {
Expand Down
5 changes: 5 additions & 0 deletions dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class DCMTK_DCMQRDB_EXPORT DcmQueryRetrieveStoreContext
*/
void setFileName(const char *fn) { fileName = fn; }

void setStorageDir(const char* fn) { _storageDir = fn; }
const char* storageDir() { return _storageDir; }

/** callback handler called by the DIMSE_storeProvider callback function.
* @param progress progress state (in)
* @param req original store request (in)
Expand Down Expand Up @@ -122,6 +125,8 @@ class DCMTK_DCMQRDB_EXPORT DcmQueryRetrieveStoreContext
/// file name under which the incoming image should be stored
const char *fileName;

const char* _storageDir;

/// DICOM file format into which the image is received
DcmFileFormat *dcmff;

Expand Down
30 changes: 28 additions & 2 deletions dcmqrdb/libsrc/dcmqrsrv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,33 @@ static void storeCallback(
T_DIMSE_C_StoreRSP *rsp, /* final store response */
DcmDataset **stDetail)
{
DcmQueryRetrieveStoreContext *context = OFstatic_cast(DcmQueryRetrieveStoreContext *, callbackData);
context->callbackHandler(progress, req, imageFileName, imageDataSet, rsp, stDetail);
if (progress->state == DIMSE_StoreEnd) {
DcmQueryRetrieveStoreContext* context = OFstatic_cast(DcmQueryRetrieveStoreContext*, callbackData);


OFString studyInstanceUID;
OFString sopInstanceUID;
(*imageDataSet)->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
(*imageDataSet)->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);

OFString baseStr;
OFStandard::combineDirAndFilename(baseStr, context->storageDir(), studyInstanceUID, OFTrue);
if (!OFStandard::dirExists(baseStr))
{
if (OFStandard::createDirectory(baseStr, context->storageDir()).bad())
{
std::cerr << "failed to create directory " << baseStr.c_str() << std::endl;
return;
}
}

OFString filename;
OFStandard::combineDirAndFilename(filename, baseStr, sopInstanceUID, OFTrue);
char newFilename[1024];
OFStandard::strlcpy(newFilename, filename.c_str(), 1025);
context->setFileName(filename.c_str());
context->callbackHandler(progress, req, newFilename, imageDataSet, rsp, stDetail);
}
}


Expand Down Expand Up @@ -392,6 +417,7 @@ OFCondition DcmQueryRetrieveSCP::storeSCP(T_ASC_Association * assoc, T_DIMSE_C_S
#endif

context.setFileName(imageFileName);
context.setStorageDir(config_->getStorageArea("any"));

// store SourceApplicationEntityTitle in metaheader
if (assoc && assoc->params)
Expand Down
5 changes: 3 additions & 2 deletions examples/storescp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ addon.startScp(JSON.stringify(
"ip" : "127.0.0.1",
"port": "9999"
},
"peers": [
"peers": [ // peers needed for C-MOVE destination
{
"aet": "CONQUESTSRV1",
"ip" : "RYZEN7",
"port": "5678"
}
],
"storagePath": "./data",
"verbose": true
"permissive": true, // any AET can perform FIND,GET and STORE
"verbose": true // verbose logging
}
), (result) => {
if (result && result.length > 0) {
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
"main": "index.js",
"scripts": {
"install": "npx prebuild-install -r napi || npx cmake-js compile",
"example:echo": "node ./examples/echo.js",
"example:find": "node ./examples/find.js",
"example:get": "node ./examples/get.js",
"example:move": "node ./examples/move.js",
"example:store": "node ./examples/store.js",
"example:echoscu": "node ./examples/echoscu.js",
"example:findscu": "node ./examples/findscu.js",
"example:getscu": "node ./examples/getscu.js",
"example:movescu": "node ./examples/movescu.js",
"example:storescu": "node ./examples/storescu.js",
"example:storescp": "node ./examples/storescp.js",
"test": "mocha"
},
"keywords": [
Expand All @@ -30,7 +31,7 @@
"PACS"
],
"author": "Michael Knopke",
"license": "ISC",
"license": "MIT",
"dependencies": {
"bindings": "^1.5.0",
"node-addon-api": "^3.0.2",
Expand Down
9 changes: 0 additions & 9 deletions src/Addon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "StoreAsyncWorker.h"
#include "ServerAsyncWorker.h"

#include "sqlite3.h"
#include <iostream>

using namespace Napi;
Expand Down Expand Up @@ -58,14 +57,6 @@ Value DoStore(const CallbackInfo& info) {
}

Value StartScp(const CallbackInfo& info) {

std::cout << "Sqlite version: " << sqlite3_libversion() << std::endl;

sqlite3* mydb;
std::cout << sqlite3_open("test.db", &mydb) << std::endl;
std::cout << "Database file:" << mydb << std::endl;
std::cout << sqlite3_close(mydb);

std::string input = info[0].As<String>().Utf8Value();
Function cb = info[1].As<Function>();

Expand Down
1 change: 1 addition & 0 deletions src/ServerAsyncWorker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ void ServerAsyncWorker::Execute(const ExecutionProgress &progress)
cfg.addPeer(peer.aet.c_str(), peer.ip.c_str(), std::stoi(peer.port));
}
cfg.setStorageArea(in.storagePath.c_str());
cfg.setPermissiveMode(in.permissive);

DcmQueryRetrieveOptions options;
options.net_ = network;
Expand Down
5 changes: 5 additions & 0 deletions src/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace ns {
};

struct sInput {
sInput() : verbose(false), permissive(false) {}
sIdent source;
sIdent target;
std::string storagePath;
Expand All @@ -78,6 +79,7 @@ namespace ns {
std::vector<sTag> tags;
std::vector<sIdent> peers;
bool verbose;
bool permissive;
inline bool valid() {
return source.valid() && target.valid();
}
Expand Down Expand Up @@ -154,6 +156,9 @@ namespace ns {
in.peers.push_back(peer);
}
} catch(...) {}
try {
in.permissive = j.at("permissive");
} catch(...) {}
try {
in.verbose = j.at("verbose");
} catch(...) {}
Expand Down
2 changes: 1 addition & 1 deletion src/dcmsqldb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ std::list< sQRes > DcmSQLiteDatabase::query(const std::list<DcmSmallDcmElm> & fi
DCMNET_WARN(bindName + bindValue);
}
}
DCMNET_WARN(prepare);

for (sqlite3pp::query::iterator i = query.begin(); i != query.end(); ++i) {

std::list<DcmSmallDcmElm> responseList;
Expand Down
12 changes: 10 additions & 2 deletions src/dcmsqlhdl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,23 @@ int DcmQueryRetriveConfigExt::peerForAETitle(const char* AETitle, const char** H

int DcmQueryRetriveConfigExt::peerInAETitle(const char* calledAETitle, const char* callingAETitle, const char* HostName) const
{
if (_permissive) return 1;

std::list<sPeer>::const_iterator it;
for (it = _peers.begin(); it != _peers.end(); it++)
{
// Access the object through iterator
if (strcmp(it->aet.c_str(), callingAETitle) == 0 &&
strcmp(it->hostname.c_str(), HostName) == 0) {
if (strcmp(it->aet.c_str(), callingAETitle) == 0 /* &&
strcmp(it->hostname.c_str(), HostName) == 0 */) {
return 1;
}
}
DCMNET_WARN("No matching AET found for AET:" << calledAETitle);
return 0;
}

//------------------------------------------------------------------------------------------------------

int DcmQueryRetriveConfigExt::checkForSameVendor(const char* AETitle1, const char* AETitle2) const {
return 1;
}
Expand Down Expand Up @@ -851,6 +855,7 @@ OFCondition DcmQueryRetrieveSQLiteDatabaseHandle::cancelMoveRequest( DcmQueryRet
OFCondition DcmQueryRetrieveSQLiteDatabaseHandle::makeNewStoreFileName(const char* SOPClassUID, const char* SOPInstanceUID,
char* newImageFileName, size_t newImageFileNameLen)
{
/*
OFString filename;
char prefix[12];
Expand All @@ -865,6 +870,9 @@ OFCondition DcmQueryRetrieveSQLiteDatabaseHandle::makeNewStoreFileName(const cha
return QR_EC_IndexDatabaseError;
OFStandard::strlcpy(newImageFileName, filename.c_str(), newImageFileNameLen);
*/
// Note: filename ist overridden in storeCallback
return OFCondition(EC_Normal);
}

Expand Down
3 changes: 3 additions & 0 deletions src/dcmsqlhdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ class DcmQueryRetriveConfigExt : public DcmQueryRetrieveConfig
{

public:
DcmQueryRetriveConfigExt() : _permissive(false) {}
void addPeer(const char* AETitle, const char* HostName, int PortNumber);
void setStorageArea(const OFFilename& filename) { _storageArea = filename; }
void setPermissiveMode(bool enabled) { _permissive = enabled; }

// override
int peerForAETitle(const char* AETitle, const char** HostName, int* PortNumber) const;
Expand All @@ -35,6 +37,7 @@ class DcmQueryRetriveConfigExt : public DcmQueryRetrieveConfig
};
std::list<sPeer> _peers;
OFFilename _storageArea;
bool _permissive;
};

class DcmQueryRetrieveSQLiteDatabaseHandleFactory : public DcmQueryRetrieveDatabaseHandleFactory
Expand Down

0 comments on commit 7ccff4c

Please sign in to comment.