private void OnReceiveCStoreRequest(object sender, CStoreRequestReceivedEventArgs request) { try { if (__CurrentRequest != null && __MovedInstances != null) { if (CanMoveCStoreRequest(request)) { GatewaySession.Log(__Client, DicomCommandType.CMove, LogType.Debug, MessageDirection.Output, null, "[Gateway] Sending C-Move response to client \"" + __ClientAE + "\""); lock ( _storeLock ) { OnMoveDataSet(request.RequestDataSet); GatewaySession.Log(__Client, DicomCommandType.CMove, LogType.Debug, MessageDirection.Output, null, "[Gateway] C-Move response sent successfully to client \"" + __ClientAE + "\""); } } } } catch (Exception ex) { GatewaySession.Log(__Client, DicomCommandType.CMove, LogType.Error, MessageDirection.Output, null, "[Gateway] Failed to send C-Move response to client \"" + __ClientAE + "\"\n" + ex.Message); __CurrentStatus = DicomCommandStatusType.Failure; } }
private QueryRetrieveScu GetScu(AeInfo server) { QueryRetrieveScu scu = null; bool useSecurePort = (server.Port == 0) && (server.SecurePort != 0); int port = useSecurePort ? server.SecurePort : server.Port; if (useSecurePort) { GatewaySession.InitializeDicomSecurity(false); scu = new QueryRetrieveScu(string.Empty, DicomNetSecurityMode.Tls, GatewaySession._openSslOptions); scu.UseSecureHost = true; GatewaySession.SetCiphers(scu); } if (scu == null) { scu = new QueryRetrieveScu(); } scu.AETitle = server.AETitle; scu.HostAddress = IPAddress.Parse(server.Address); scu.HostPort = port; return(scu); }
private void Find_AfterSecureLinkReady(object sender, AfterSecureLinkReadyEventArgs e) { DicomConnection connection = sender as DicomConnection; if (e.Error == DicomExceptionCode.Success) { DicomTlsCipherSuiteType cipher = connection.GetTlsCipherSuite(); GatewaySession.Log(LogType.Information, String.Format(SECURE_LINK_READY_CIPHERSUITE, cipher.GetCipherFriendlyName())); } else { GatewaySession.Log(LogType.Information, String.Format(SECURE_LINK_FAILED, e.Error)); } }
public bool IsAbstractSyntaxSupported(string abstractSyntax) { if (abstractSyntax == DicomUidType.PatientRootQueryFind || abstractSyntax == DicomUidType.PatientStudyQueryFind || abstractSyntax == DicomUidType.StudyRootQueryFind) { if (!GatewaySession.HasGetwayLicense) { string message = "[Gateway] Valid license for gateway server not found. Abstract syntax not accepted by gateway server"; GatewaySession.Log(_Client, DicomCommandType.CFind, LogType.Error, MessageDirection.Input, null, message); } return(GatewaySession.HasGetwayLicense); } return(false); }
/// <inheritdoc/> public virtual RequestContextModel GetContext(RequestHeader requestHeader, RequestType requestType) { if (requestHeader == null) { throw new ArgumentNullException(nameof(requestHeader)); } GatewaySession session = null; try { lock (_lock) { // check for create / activate session request which are handled differently. if (requestType == RequestType.CreateSession) { return(new RequestContextModel(requestHeader, requestType)); } // find session. if (_sessions.TryGetValue(requestHeader.AuthenticationToken, out session)) { // validate request header in context of this session. session.ValidateRequest(requestHeader, requestType); return(new RequestContextModel(requestHeader, requestType, session)); } // No session, validate the request as a session less request var identity = ValidateSessionLessRequest(requestHeader.AuthenticationToken, requestType); return(new RequestContextModel(requestHeader, requestType, identity)); } } catch (Exception e) { if (e is ServiceResultException sre && sre.StatusCode == StatusCodes.BadSessionNotActivated) { if (session != null) { CloseSession(session.Id); } } throw new ServiceResultException(e, StatusCodes.BadUnexpectedError); } }
private void OnMatchFound(DicomDataSet response) { try { if (null != MatchFound) { try { GatewaySession.Log(__Client, DicomCommandType.CFind, LogType.Debug, MessageDirection.Output, null, "[Gateway] Sending C-Find response to client \"" + (__Client.IsAssociated() ? __Client.Association.Calling : string.Empty) + "\""); DicomElement element = response.FindFirstElement(null, DicomTag.RetrieveAETitle, true); if (null != element) { response.DeleteElement(element); } response.InsertElementAndSetValue(DicomTag.InstanceAvailability, "NEARLINE"); MatchFound(this, new MatchFoundEventArgs(response)); GatewaySession.Log(__Client, DicomCommandType.CFind, LogType.Debug, MessageDirection.Output, null, "[Gateway] C-Find response sent successfully to client \"" + (__Client.IsAssociated() ? __Client.Association.Calling : string.Empty) + "\""); } catch (Exception exception) { GatewaySession.Log(__Client, DicomCommandType.CFind, LogType.Error, MessageDirection.Output, null, "[Gateway] Faild to send C-Find response to client \"" + (__Client.IsAssociated() ? __Client.Association.Calling : string.Empty) + "\"\n" + exception.Message); } } } finally { response.Dispose(); } }
/// <inheritdoc/> public virtual bool ActivateSession(RequestContextModel context, NodeId authenticationToken, SignatureData clientSignature, List <SoftwareCertificate> clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, out byte[] serverNonce) { // find session. GatewaySession session = null; lock (_lock) { if (!_sessions.TryGetValue(authenticationToken, out session)) { throw new ServiceResultException(StatusCodes.BadSessionClosed); } } if (session.IsClosed) { throw new ServiceResultException(StatusCodes.BadSessionClosed); } // Activate session. var nonceLength = (uint)_configuration.NonceLength; serverNonce = Utils.Nonce.CreateNonce(nonceLength); var contextChanged = session.Activate(context, clientSignature, clientSoftwareCertificates, userIdentityToken, userTokenSignature, serverNonce); if (contextChanged) { _sessionActivated?.Invoke(session, null); } // indicates that the identity context for the session has changed. return(contextChanged); }
//[PresentationContext(DicomUidType.PatientRootQueryFind, new byte[] {1,0,1},DicomUidType.ImplicitVRLittleEndian)] //[PresentationContext(DicomUidType.PatientStudyQueryFind, DicomUidType.ImplicitVRLittleEndian)] //[PresentationContext(DicomUidType.StudyRootQueryFind, DicomUidType.ImplicitVRLittleEndian)] public DicomCommandStatusType OnFind ( DicomClient client, byte presentationId, int messageId, string affectedClass, DicomCommandPriorityType priority, DicomDataSet request ) { int countOfServersConnection; try { __Client = client; if (null == __ServersManager) { GatewaySession.Log(string.Empty, string.Empty, -1, DicomCommandType.CFind, LogType.Error, MessageDirection.None, null, "[Gateway] Gateway server not available"); return(DicomCommandStatusType.ProcessingFailure); } countOfServersConnection = 0; //make sure to break the loop on success or normal failure while (countOfServersConnection < __ServersManager.Servers.Count) { AeInfo currentRemoteServer; DicomScp remoteScp; QueryRetrieveScu cFindScu; countOfServersConnection++; currentRemoteServer = __ServersManager.GetRemoteServer(); remoteScp = GetScp(currentRemoteServer); cFindScu = GetScu(__ServersManager.Gateway.Server); try { RegisterEvents(cFindScu); if (cFindScu.SecurityMode == DicomNetSecurityMode.Tls) { GatewaySession.InitializeDicomSecurity(false); GatewaySession.SetCiphers(cFindScu); GatewaySession.SetSecurityCertificates(cFindScu); } __CFindScu = cFindScu; __CurrentStatus = DicomCommandStatusType.Success; GatewaySession.Log(client, DicomCommandType.CFind, LogType.Information, MessageDirection.Output, request, "[Gateway] Sending C-Find request to remote server \"" + currentRemoteServer.AETitle + "\""); cFindScu.Find(remoteScp, request); GatewaySession.Log(client, DicomCommandType.CFind, LogType.Information, MessageDirection.None, null, "[Gateway] C-Find request sent successfully \"" + currentRemoteServer.AETitle + "\""); break; } catch (ClientConnectionException exception) { GatewaySession.Log(client, DicomCommandType.CFind, LogType.Warning, MessageDirection.None, null, "[Gateway] Connecting to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); __ServersManager.SetRemoteServerConnectionFailure(); __CurrentStatus = DicomCommandStatusType.Failure; } catch (ClientCommunicationException exception) { __CurrentStatus = exception.Status; GatewaySession.Log(client, DicomCommandType.CFind, LogType.Error, MessageDirection.None, null, "[Gateway] Communicating with server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } catch (DicomException exception) { if (__CurrentStatus == DicomCommandStatusType.Success) { __CurrentStatus = DicomCommandStatusType.Failure; } GatewaySession.Log(client, DicomCommandType.CFind, LogType.Error, MessageDirection.None, null, "[Gateway] Forwarding to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } catch (Exception exception) { if (__CurrentStatus == DicomCommandStatusType.Success) { __CurrentStatus = DicomCommandStatusType.ProcessingFailure; } GatewaySession.Log(client, DicomCommandType.CFind, LogType.Error, MessageDirection.None, null, "[Gateway] Forwarding to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } finally { UnregisterEvents(cFindScu); cFindScu.Dispose(); __CFindScu = null; } } return(__CurrentStatus); } finally { request.Dispose(); } }
/// <inheritdoc/> public IServerSession CreateSession(RequestContextModel context, EndpointDescription endpoint, X509Certificate2 serverCertificate, byte[] clientNonce, X509Certificate2 clientCertificate, double requestedTimeout, out NodeId sessionId, out NodeId authenticationToken, out byte[] serverNonce, out double revisedTimeout) { GatewaySession session = null; lock (_lock) { // check session count. if (_configuration.MaxSessionCount > 0 && _sessions.Count >= _configuration.MaxSessionCount) { throw new ServiceResultException(StatusCodes.BadTooManySessions); } // check for same Nonce in another session if (clientNonce != null) { foreach (var sessionIterator in _sessions.Values) { if (Utils.CompareNonce(sessionIterator.ClientNonce, clientNonce)) { throw new ServiceResultException(StatusCodes.BadNonceInvalid); } } } // Create session sessionId = new NodeId(Guid.NewGuid()); authenticationToken = new NodeId(Utils.Nonce.CreateNonce(kDefaultNonceLength)); var nonceLength = (uint)_configuration.NonceLength; serverNonce = Utils.Nonce.CreateNonce(nonceLength == 0 ? kDefaultNonceLength : nonceLength); var maxSessionTimeout = _configuration.MaxSessionTimeout.TotalMilliseconds; var minSessionTimeout = _configuration.MinSessionTimeout.TotalMilliseconds; if (requestedTimeout > maxSessionTimeout) { revisedTimeout = maxSessionTimeout; } else if (requestedTimeout < minSessionTimeout) { revisedTimeout = minSessionTimeout; } else { revisedTimeout = requestedTimeout; } // Add session to list session = new GatewaySession(this, context, sessionId, endpoint, clientCertificate, clientNonce, serverCertificate, serverNonce, TimeSpan.FromMilliseconds(revisedTimeout), _configuration.MaxRequestAge, _validateUser); if (!_sessions.TryAdd(authenticationToken, session)) { throw new ServiceResultException(StatusCodes.BadInternalError); } } _sessionCreated?.Invoke(session, null); return(session); }
//[PresentationContext(DicomUidType.PatientRootQueryMove, new byte[] {1,0,1},DicomUidType.ImplicitVRLittleEndian)] //[PresentationContext(DicomUidType.PatientStudyQueryMove, DicomUidType.ImplicitVRLittleEndian)] //[PresentationContext(DicomUidType.StudyRootQueryMove, DicomUidType.ImplicitVRLittleEndian)] public DicomCommandStatusType OnMove ( DicomClient client, byte presentationId, int messageId, string affectedClass, DicomCommandPriorityType priority, string moveAE, DicomDataSet request ) { try { int countOfServersConnection; __Client = client; __ClientAE = client.AETitle; if (null == __ServersManager) { GatewaySession.Log(string.Empty, string.Empty, -1, DicomCommandType.CMove, LogType.Error, MessageDirection.None, null, "[Gateway] Gateway server not available"); return(DicomCommandStatusType.ProcessingFailure); } countOfServersConnection = 0; //make sure to break the loop on success or normal failure while (countOfServersConnection < __ServersManager.Servers.Count) { AeInfo currentRemoteServer; DicomScp remoteScp; QueryRetrieveScu cMoveScu; countOfServersConnection++; currentRemoteServer = __ServersManager.GetRemoteServer( ); remoteScp = GetScp(currentRemoteServer); cMoveScu = GetScu(__ServersManager.Gateway.Server); try { RegisterEvents(cMoveScu); if (cMoveScu.SecurityMode == DicomNetSecurityMode.Tls) { // Set the TLS certificate cMoveScu.SetTlsClientCertificate( GatewaySession.DicomSecurityAgent.CertificateFileName, GatewaySession.DicomSecurityAgent.CertificateType, GatewaySession.DicomSecurityAgent.KeyFileName.Length > 0 ? GatewaySession.DicomSecurityAgent.KeyFileName : null); } __CMoveScu = cMoveScu; __CurrentStatus = DicomCommandStatusType.Success; __CurrentRequest = new MoveRequestInformation(request); __MovedInstances = new List <string> ( ); __ForwardedInstances = new List <string> ( ); ServerEventBroker.Instance.Subscribe <CStoreRequestReceivedEventArgs> (OnReceiveCStoreRequest); ServerEventBroker.Instance.Subscribe <CStoreResponseSentEventArgs> (OnSendCStoreResponse); try { GatewaySession.Log(client, DicomCommandType.CMove, LogType.Information, MessageDirection.Output, request, "[Gateway] Sending C-Move request to remote server \"" + currentRemoteServer.AETitle + "\""); cMoveScu.Move(remoteScp, __ServersManager.Gateway.Server.AETitle, request); GatewaySession.Log(client, DicomCommandType.CMove, LogType.Information, MessageDirection.Output, request, "[Gateway] C-Move request sent successfully \"" + currentRemoteServer.AETitle + "\""); } finally { ServerEventBroker.Instance.Unsubscribe <CStoreRequestReceivedEventArgs> (OnReceiveCStoreRequest); ServerEventBroker.Instance.Unsubscribe <CStoreResponseSentEventArgs> (OnSendCStoreResponse); } break; } catch (ClientConnectionException exception) { GatewaySession.Log(client, DicomCommandType.CMove, LogType.Warning, MessageDirection.None, null, "[Gateway] Connecting to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); __ServersManager.SetRemoteServerConnectionFailure( ); if (countOfServersConnection >= __ServersManager.Servers.Count) { __CurrentStatus = DicomCommandStatusType.Failure; } } catch (ClientCommunicationException exception) { //Don't update the status, just log a message here //__CurrentStatus = exception.Status ; GatewaySession.Log(client, DicomCommandType.CMove, LogType.Warning, MessageDirection.None, null, "[Gateway] Problem occured moving from server \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } catch (DicomException exception) { if (__CurrentStatus == DicomCommandStatusType.Success) { __CurrentStatus = DicomCommandStatusType.Failure; } GatewaySession.Log(client, DicomCommandType.CMove, LogType.Error, MessageDirection.None, null, "[Gateway] Sending to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } catch (Exception exception) { if (__CurrentStatus == DicomCommandStatusType.Success) { __CurrentStatus = DicomCommandStatusType.ProcessingFailure; } GatewaySession.Log(client, DicomCommandType.CMove, LogType.Error, MessageDirection.None, null, "[Gateway] Sending to server failed \"" + currentRemoteServer.AETitle + "\"\n" + exception.Message); break; } finally { UnregisterEvents(cMoveScu); cMoveScu.Dispose( ); __CMoveScu = null; } } return(__CurrentStatus); } finally { request.Dispose( ); } }
private void OnSendCStoreResponse(object sender, CStoreResponseSentEventArgs response) { try { bool process = false; lock ( _instancesListLock ) { process = (__MovedInstances.Contains(response.Instance) && !__ForwardedInstances.Contains(response.Instance)); } if (process && response.Status == DicomCommandStatusType.Success) { if (ServiceLocator.IsRegistered <ForwardOptions> ( ) && DataAccessServices.IsDataAccessServiceRegistered <IForwardDataAccessAgent> ( )) { ForwardOptions forwardOptions = ServiceLocator.Retrieve <ForwardOptions> ( ); IForwardDataAccessAgent dataAccess = DataAccessServices.GetDataAccessService <IForwardDataAccessAgent> ( ); if (null != forwardOptions && null != dataAccess) { DateTime?expires = null; DateTime forwardDate = DateTime.Now; if (dataAccess.IsForwarded(response.Instance)) { return; } if (forwardOptions.ImageHold != null && forwardOptions.ImageHold != 0) { switch (forwardOptions.HoldInterval) { case HoldInterval.Days: { expires = forwardDate.AddDays(forwardOptions.ImageHold.Value); } break; case HoldInterval.Months: { expires = forwardDate.AddMonths(forwardOptions.ImageHold.Value); } break; default: { expires = forwardDate.AddYears(forwardOptions.ImageHold.Value); } break; } } dataAccess.SetInstanceForwarded(response.Instance, forwardDate, expires); } } } } catch (Exception ex) { GatewaySession.Log(__Client, DicomCommandType.CMove, LogType.Error, MessageDirection.Output, null, "[Gateway] Failed to set instance forwarding.\n" + ex.Message); } }