001/**
002 * Copyright (C) 2014  Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/
003 *
004 * This file is part of Dicoogle/dicoogle.
005 *
006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * Dicoogle/dicoogle is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with Dicoogle.  If not, see <http://www.gnu.org/licenses/>.
018 */
019/**
020 *
021 *  Generic DICOM Worklist Server SCP
022 */
023package pt.ua.dicoogle.server.queryretrieve;
024
025//import configurations.ConfigurationsValues;
026
027//import gui.MainWindow;
028//import gui.MainWindow.LOG_MODES;
029import java.io.IOException;
030import java.util.concurrent.Executor;
031
032
033import org.dcm4che2.data.DicomObject;
034import org.dcm4che2.net.Association;
035import org.dcm4che2.net.ConfigurationException;
036import org.dcm4che2.data.UID;
037import org.dcm4che2.net.CommandUtils;
038import org.dcm4che2.net.Device;
039import org.dcm4che2.net.NetworkApplicationEntity;
040import org.dcm4che2.net.NetworkConnection;
041import org.dcm4che2.net.NewThreadExecutor;
042import org.dcm4che2.net.TransferCapability;
043import org.dcm4che2.net.UserIdentity;
044import org.dcm4che2.net.service.VerificationService;
045import pt.ua.dicoogle.core.ServerSettings;
046
047/**
048 *
049 * @author Joaoffr  <joaoffr@ua.pt>
050 * @author DavidP   <davidp@ua.pt>
051 *
052 * @version $Revision: 002 $ $Date: 2008-11-22 14:25:00  $
053 * @since Nov 21, 2008
054 *
055 */
056public class DicomEchoReply extends VerificationService {
057
058    
059    /** Settings */         
060    ServerSettings s = ServerSettings.getInstance();
061    
062    private static final String[] TRANSF_CAP = {
063        UID.ImplicitVRLittleEndian,
064        UID.ExplicitVRBigEndian,
065        UID.ExplicitVRLittleEndian
066    };
067
068    /* Implemented SOP Class */
069    private static final String SOP_CLASS = UID.VerificationSOPClass;
070
071    private static final int PORT_OFFSET = 100;
072
073    private static final String SERVICE_LABEL = "";
074
075
076    /**** Class Atributes ****/
077
078    private static final String MODULE_NAME = "DICOMWLS_EchoReply";                     /* DEFAULT Implemented module name */
079    private final NetworkApplicationEntity remoteAE = new NetworkApplicationEntity();   /* Remote Application Entity (client) */
080    private final NetworkConnection remoteConn = new NetworkConnection();               /* Remote connection associated with remoteAE */
081    private final Device device = new Device(MODULE_NAME);                              /* Module device */
082    private final NetworkApplicationEntity localAE = new NetworkApplicationEntity();    /* Local Application Entity (this server) 'ea' */
083    private final NetworkConnection localConn = new NetworkConnection();                /* Local connection associated with localAE 'conn' */
084    private boolean started = false;                                                    /* True if server is allready started */
085    private int port = 0;
086
087
088
089    /* Module executor */
090    private static final Executor executor = (Executor) new NewThreadExecutor(MODULE_NAME);        /* Server thread */
091
092
093
094    public DicomEchoReply() {
095
096        super();
097
098        this.port = s.getWlsPort() + DicomEchoReply.PORT_OFFSET; ;
099        /* clients */
100        this.remoteAE.setInstalled(true);
101        this.remoteAE.setAssociationInitiator(true);
102        this.remoteAE.setNetworkConnection(this.remoteConn);
103        
104
105
106        /* server */
107        this.started = false;
108        this.localAE.setInstalled(true);
109        this.localAE.setAssociationAcceptor(true);
110        this.localAE.setAssociationInitiator(false);
111        this.localAE.setNetworkConnection(this.localConn );
112        this.localAE.setAETitle(s.getAE() + DicomEchoReply.SERVICE_LABEL);
113        this.localAE.register(new VerificationService());
114        this.localAE.register(this);
115
116        TransferCapability[] tc = { new TransferCapability( DicomEchoReply.SOP_CLASS,
117                                                            DicomEchoReply.TRANSF_CAP,
118                                                            TransferCapability.SCP) };
119        this.localAE.setTransferCapability(tc);
120
121/*        this.localAE.setDimseRspTimeout(confs.getWlsConfigs().getDIMSE_RSP_TIMEOUT());
122        this.localAE.setIdleTimeout(confs.getWlsConfigs().getIDLE_TIMEOUT());*/
123
124        /*this.localAE.setMaxPDULengthReceive(confs.getWlsConfigs().getMAX_PDU_LENGTH_RECEIVE());
125        this.localAE.setMaxPDULengthSend(confs.getWlsConfigs().getMAX_PDU_LENGTH_SEND());*/
126        /**
127        this.localAE.setSupportedCharacterSet("CharacterSetSup");*/
128
129        this.localConn.setPort(this.port);
130        //this.localConn.setMaxScpAssociations(confs.getWlsConfigs().getMAX_CLIENT_ASSOCS());
131        /*this.localConn.setHostname(DicomWLS.LOCAL_HOST_NAME);*/
132       // this.localConn.setAcceptTimeout(confs.getWlsConfigs().getACCEPT_TIMEOUT());
133        //this.localConn.setConnectTimeout(confs.getWlsConfigs().getCONNECTION_TIMEOUT());
134
135
136        //this.device.setDescription(confs.getWlsConfigs().getDEVICE_DESCRIPTION());
137        this.device.setNetworkApplicationEntity(this.localAE);
138        this.device.setNetworkConnection(this.localConn);
139        /*this.device.setDeviceName(DicomWLS.MODULE_NAME);*/
140
141    }
142
143
144    /**
145     * Set local Host Name
146     * @param hostname
147     */
148    public final void setLocalHost(String hostname) {
149        this.localConn.setHostname(hostname);
150    }
151
152    /**
153     * Get Local Host Name
154     * @return
155     */
156    public final String getLocalHost() {
157        return this.localConn.getHostname();
158    }
159
160    /**
161     * Set Remote Host Name
162     * @param hostname
163     */
164    public final void setRemoteHost(String hostname) {
165        this.remoteConn.setHostname(hostname);
166    }
167
168    /**
169     * Get Remote Host Name
170     * @return
171     */
172    public final String getRemoteHost() {
173        return this.remoteConn.getHostname();
174    }
175
176    /**
177     * Set Local Port
178     * @param port
179     */
180    public final void setLocalPort(int port) {
181         int tmp = (port >= 1 && port <= 0xffff) ? port : 105;
182         this.localConn.setPort(tmp);
183    }
184
185    /**
186     * Get Local Port
187     * @return
188     */
189    public final int getLocalPort() {
190        return this.localConn.getPort();
191    }
192
193    /**
194     * Set Remote Application Entity Title
195     * @param called
196     */
197    public final void setRemoteAET(String called) {
198        this.remoteAE.setAETitle(called);
199    }
200
201    /**
202     * Get Remote Application Entity Title
203     * @return
204     */
205    public final String getRemoteAET() {
206        return this.remoteAE.getAETitle();
207    }
208
209    /**
210     * Set Local Application Entity Title
211     * @param calling
212     */
213    public final void setLocalAET(String calling) {
214        this.localAE.setAETitle(calling);
215    }
216
217    /**
218     * Get Local Application Entity Title
219     * @return
220     */
221    public final String getLocalAET() {
222        return this.localAE.getAETitle();
223    }
224
225    /**
226     * Set Local User Identity
227     * @param userIdentity
228     */
229    public final void setUserIdentity(UserIdentity userIdentity) {
230        this.localAE.setUserIdentity(userIdentity);
231    }
232
233    /**
234     * Get Local User Identity
235     * @return
236     */
237    public final UserIdentity getUserIdentity() {
238        return this.localAE.getUserIdentity();
239    }
240
241    public boolean isStarted() {
242        return started;
243    }
244
245    public void setStarted(boolean started) {
246        this.started = started;
247    }
248
249    /**
250     *
251     * @param connectTimeout
252     */
253    public final void setConnectTimeout(int connectTimeout) {
254        this.localConn.setConnectTimeout(connectTimeout);
255    }
256
257    /**
258     *
259     * @param maxPDULength
260     */
261    public final void setMaxPDULengthReceive(int maxPDULength) {
262        this.localAE.setMaxPDULengthReceive(maxPDULength);
263    }
264
265    /**
266     *
267     * @param maxPDULength
268     */
269    public final void setMaxPDULengthSend(int maxPDULength) {
270        this.localAE.setMaxPDULengthSend(maxPDULength);
271    }
272
273    /**
274     *
275     * @param packPDV
276     */
277    public final void setPackPDV(boolean packPDV) {
278        this.localAE.setPackPDV(packPDV);
279    }
280
281    /**
282     *
283     * @param period
284     */
285    public final void setAssociationReaperPeriod(int period) {
286        this.device.setAssociationReaperPeriod(period);
287    }
288
289    /**
290     *
291     * @param timeout
292     */
293    public final void setDimseRspTimeout(int timeout) {
294        this.localAE.setDimseRspTimeout(timeout);
295    }
296
297    /**
298     *
299     * @param tcpNoDelay
300     */
301    public final void setTcpNoDelay(boolean tcpNoDelay) {
302        this.localConn.setTcpNoDelay(tcpNoDelay);
303    }
304
305    /**
306     *
307     * @param timeout
308     */
309    public final void setAcceptTimeout(int timeout) {
310        this.localConn.setAcceptTimeout(timeout);
311    }
312
313    /**
314     *
315     * @param timeout
316     */
317    public final void setReleaseTimeout(int timeout) {
318        this.localConn.setReleaseTimeout(timeout);
319    }
320
321    /**
322     *
323     * @param timeout
324     */
325    public final void setSocketCloseDelay(int timeout) {
326        this.localConn.setSocketCloseDelay(timeout);
327    }
328
329    /**
330     *
331     * @param bufferSize
332     */
333    public final void setReceiveBufferSize(int bufferSize) {
334        this.localConn.setReceiveBufferSize(bufferSize);
335    }
336
337    /**
338     *
339     * @param bufferSize
340     */
341    public final void setSendBufferSize(int bufferSize) {
342        this.localConn.setSendBufferSize(bufferSize);
343    }
344
345    /**
346     *
347     * @param ts
348     */
349    public void setTransferSyntax(String[] ts) {
350        TransferCapability[] tc = { new TransferCapability(
351                UID.ModalityWorklistInformationModelFIND, ts,
352                TransferCapability.SCU) };
353        this.localAE.setTransferCapability(tc);
354    }
355
356    /**
357     *
358     * @param timeout
359     */
360    public final void setIdleTimeout(int timeout) {
361        this.localAE.setIdleTimeout(timeout);
362    }
363
364
365
366    /**
367     * Start server socket accept client(s) connection
368     *
369     * @return
370     * @throws java.io.IOException
371     * @throws org.dcm4che2.net.ConfigurationException
372     * @throws java.lang.InterruptedException
373     */
374    public boolean startListening() {
375        if (this.device != null) {
376            try {
377                CommandUtils.setIncludeUIDinRSP(true);
378                this.device.startListening(DicomEchoReply.executor);
379            } catch (Exception ex) {
380                 ///MainWindow.getMw().add2ServerLogln(ex.getMessage(), LOG_MODES.ERROR);
381                 return false;
382            }
383            this.started = true;
384            return true;
385        }
386
387        return false;
388    }
389
390    /**
391     * Stop all active client socket connections
392     *
393     * @return
394     * @throws java.io.IOException
395     * @throws org.dcm4che2.net.ConfigurationException
396     * @throws java.lang.InterruptedException
397     */
398    public boolean stopListening() {
399        if (this.device != null) {
400            this.device.stopListening();
401            this.started = false;
402            return true;
403        }
404
405        return false;
406    }
407
408    @Override
409    public String toString() {
410        return( "[START INFO PRINT]" + "\n" +
411                    "\tModuleName = " + DicomEchoReply.MODULE_NAME + "\n" +
412                    "\tLocalAETitle = " + this.localAE.getAETitle() + "\n" +
413                    "\tPort = " + this.localConn.getPort() + "\n" +
414                    "\tTransfereCapabilities = " + strVectConcat(this.localAE.getTransferCapability()[0].getTransferSyntax(), "; ") + "\n" +
415                    "\tModality = " + DicomEchoReply.SOP_CLASS + "\n" +
416                    "\tStarted = " + this.started + "\n" +
417                "[END INFO PRINT]" + "\n"
418              );
419    }
420
421    @Override
422    public void cecho(Association as, int pcid, DicomObject cmd) throws IOException {
423        ///MainWindow.getMw().add2ServerLogln("CEcho request from " + as.getRemoteAET() + " received!", LOG_MODES.INFO);
424
425        super.cecho(as, pcid, cmd);
426
427        //System.out.println(cmd);
428
429        ///MainWindow.getMw().add2ServerLogln("CEcho response send to " + as.getRemoteAET() + "!", LOG_MODES.INFO);
430
431    }
432    
433
434    private static String strVectConcat(String[] stVectIN, String sep) {
435
436        if (stVectIN == null) return new String("[any]");
437
438        String temp = new String("");
439        for (int i = 0; i < stVectIN.length - 1; i++)
440            temp = temp + stVectIN[i] + sep;
441
442        temp = temp + stVectIN[stVectIN.length - 1];
443
444        return temp;
445    }
446
447}
448