LDicomNet::SendCCancelRequest (original) (raw)

Summary

Sends a C-CANCEL-REQ message to a peer member of a connection. This function is available in the PACS Imaging Toolkit.

Syntax

#include "ltdic.h"

L_INT LDicomNet::SendCCancelRequest(nPresentationID, nMessageID)

Parameters

L_UCHAR nPresentationID

Presentation ID. The presentation ID provides information about both the class type of the data and the transfer syntax to use when transferring the data.

L_UINT16 nMessageID

Message ID. Each message sent by a member of a connection should have a unique ID. Since a member of a connection may send several messages, this ID allows that member to identify when a specific request has been completed.

Returns

Value Meaning
0 SUCCESS
>0 An error occurred. Refer to Return Codes.

Comments

Calling this function generates a call to LDicomNet::OnReceiveCCancelRequest on the SCP.

Required DLLs and Libraries

Platforms

Win32, x64

See Also

Functions

Topics

Example

This is a basic, but complete example that shows a DICOM client sending a C-Cancel-REQ to a server to cancel the last request (a C-Echo-REQ), and the server processing the request.

namespace LDicomNet_SendCCancelRequest_Namespace { // Logs a message // This implementation logs to the console, and the debug window L_VOID LogMessage(TCHAR *szMsg) { wprintf(TEXT("\n")); wprintf(szMsg); OutputDebugStringW(TEXT("\n")); OutputDebugStringW(szMsg); } L_VOID LogMessage(TCHAR *s, L_INT n) { TCHAR szLog[200] = {0}; wsprintf(szLog, TEXT("%s [%d]"), s, n); LogMessage(szLog); } // ******************************************************************************************* // Client Class // // Class that is used to connect to the server // ******************************************************************************************* class CMyClient : public LDicomNet { public: CMyClient(L_INT32 nMode): LDicomNet(NULL, nMode) { m_waitEvent = CreateEvent( NULL, TRUE, TRUE, TEXT("ClientEvent")); ResetEvent(m_waitEvent); } ~CMyClient(void) { CloseHandle(m_waitEvent); } // Client L_VOID OnConnect (L_INT nError); L_VOID OnReceiveAssociateAccept (LDicomAssociate *pPDU); L_VOID OnReceiveReleaseResponse (); L_VOID OnReceiveCEchoResponse (L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass, L_UINT16 nStatus); L_BOOL Wait(DWORD timeout = 5000); private: HANDLE m_waitEvent; }; // Continues dispatching messages until hEvent is signalled, our timeout // Returns TRUE if hEvent is signalled // Returns FALSE if timeout L_BOOL MessageLoop ( HANDLE hEvent, // handles that need to be waited on DWORD timeout // timeout in milliseconds ) { DWORD dwStart = GetTickCount(); MSG msg = {0}; volatile L_BOOL bRunForever = TRUE; while (bRunForever) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) { ResetEvent(hEvent); return TRUE; } DWORD dwCurrent = GetTickCount(); if ((dwCurrent - dwStart) > timeout) { return FALSE; } } return TRUE; } L_VOID CMyClient::OnConnect(L_INT nError) { L_TCHAR szMsg[200] = {0}; wsprintf(szMsg, TEXT("CMyClient::OnConnect: nError[%d]"), nError); LogMessage(szMsg); } L_VOID CMyClient::OnReceiveAssociateAccept (LDicomAssociate *pPDU) { UNREFERENCED_PARAMETER(pPDU); SetEvent(m_waitEvent); LogMessage(TEXT("CMyClient::OnReceiveAssociateAccept")); } L_VOID CMyClient::OnReceiveCEchoResponse(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass, L_UINT16 nStatus) { SetEvent(m_waitEvent); L_TCHAR szMsg[200] = {0}; if (pszClass == NULL) { pszClass = TEXT(""); } wsprintf(szMsg, TEXT("CMyClient::OnReceiveCEchoResponse: \n\tnPresentationID[%d], \n\tnMessageID[%d], \n\tpszClass[%s], \n\tnStatus[%d]"), nPresentationID, nMessageID, pszClass, nStatus); LogMessage(szMsg); } L_VOID CMyClient::OnReceiveReleaseResponse() { SetEvent(m_waitEvent); LogMessage(TEXT("CMyClient::OnReceiveReleaseResponse")); } L_BOOL CMyClient::Wait(DWORD timeout) { L_BOOL bRet = MessageLoop(m_waitEvent, timeout); return bRet; } // ******************************************************************************************* // Server Connection Class // // When a client connects, CMyServer creates a new instance of the CMyServerConnection class // and accepts the connection. // ******************************************************************************************* class CMyServerConnection : public LDicomNet { public: CMyServerConnection(L_INT32 nMode): LDicomNet(NULL, nMode) { } ~CMyServerConnection(void) { } // Server L_VOID OnReceiveAssociateRequest(LDicomAssociate *pPDU); L_VOID OnReceiveAssociateReject(L_UCHAR nResult, L_UCHAR nSource, L_UCHAR nReason); L_VOID OnReceiveCEchoRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass); L_VOID OnReceiveCCancelRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID); L_VOID OnReceiveReleaseRequest(); }; #define SIZEINWORD(p) sizeof(p)/sizeof(L_TCHAR) L_VOID CMyServerConnection::OnReceiveAssociateRequest(LDicomAssociate *pPDU) { LogMessage(TEXT("\tCMyServerConnection::OnReceiveAssociateRequest")); //check the version, if not 1, reject it if (pPDU->GetVersion() != 1) { LogMessage(TEXT("\tCMyServerConnection::SendAssociateReject")); SendAssociateReject( PDU_REJECT_RESULT_PERMANENT, PDU_REJECT_SOURCE_USER, PDU_REJECT_REASON_UNKNOWN ); } else { LDicomAssociate DicomAssociate(FALSE); L_TCHAR clientAE[20] = {0}; pPDU->GetCalling(clientAE, 20); if (lstrcmp(clientAE, TEXT("LEAD_CLIENT")) != 0) { LogMessage(TEXT("\tCMyServerConnection::SendAssociateReject")); SendAssociateReject( PDU_REJECT_RESULT_PERMANENT, PDU_REJECT_SOURCE_USER, PDU_REJECT_REASON_UNKNOWN ); return; } //Copy presentation objects from received //Reply that we only support the first Transfer Syntax from the received hPDU L_TCHAR szTransfer[PDU_MAX_UID_SIZE+1] = {0}; L_TCHAR szAbstract[PDU_MAX_UID_SIZE+1] = {0}; L_INT iPresentationCount = pPDU->GetPresentationCount(); for (L_UCHAR i = 0; i<iPresentationCount; i++) { L_UCHAR nId = pPDU->GetPresentation(i); pPDU->GetTransfer(nId, 0, szTransfer, PDU_MAX_UID_SIZE+1); L_UCHAR nResult = PDU_ACCEPT_RESULT_SUCCESS; pPDU->GetAbstract(nId, szAbstract, PDU_MAX_UID_SIZE+1); DicomAssociate.AddPresentation( nId, nResult, szAbstract); DicomAssociate.AddTransfer( nId, szTransfer); } LogMessage(TEXT("\tCMyServerConnection::SendAssociateAccept")); SendAssociateAccept(&DicomAssociate); } } L_VOID CMyServerConnection::OnReceiveAssociateReject(L_UCHAR nResult, L_UCHAR nSource, L_UCHAR nReason) { L_TCHAR szMsg[200] = {0}; wsprintf(szMsg, TEXT("\tOnReceiveAssociateReject\nResult[%d]\nSource[%d]\nReason[%d]"), nResult, nSource, nReason); LogMessage(szMsg); } L_VOID CMyServerConnection::OnReceiveCEchoRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass) { LogMessage(TEXT("\tCMyServerConnection::OnReceiveCEchoRequest")); LogMessage(TEXT("\tCMyServerConnection::SendCEchoResponse")); SendCEchoResponse(nPresentationID, nMessageID, pszClass, COMMAND_STATUS_SUCCESS); } L_VOID CMyServerConnection::OnReceiveCCancelRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID) { LogMessage(TEXT("\tCMyServerConnection::OnReceiveCCancelRequest")); LogMessage(TEXT("\t\t nPresentationID"), nPresentationID); LogMessage(TEXT("\t\t nMessageID"), nMessageID); LogMessage(TEXT("\t\tCancel the last request (in this case a C-Echo-REQ)")); } L_VOID CMyServerConnection::OnReceiveReleaseRequest() { LogMessage(TEXT("\tCMyServerConnection::OnReceiveReleaseRequest")); LogMessage(TEXT("\tCMyServerConnection::SendReleaseResponse")); SendReleaseResponse(); } // ******************************************************************************************* // Server Class // // Listens for connections // When a client connects, this class creates a CMyServerConnection and accepts the connection // ******************************************************************************************* class CMyServer : public LDicomNet { public: CMyServer(L_INT32 nMode): LDicomNet(NULL, nMode) { m_pServerConnection = NULL; } ~CMyServer(void) { if (m_pServerConnection != NULL) { delete m_pServerConnection; } } L_VOID OnAccept (L_INT nError); L_VOID OnClose (L_INT nError, LDicomNet *pServerConnection); CMyServerConnection *m_pServerConnection; }; L_VOID CMyServer::OnAccept(L_INT nError) { LogMessage(TEXT("\tCMyServer::OnAccept")); if (nError != DICOM_SUCCESS) { return; } if (m_pServerConnection != NULL) { delete m_pServerConnection; m_pServerConnection = NULL; } m_pServerConnection = new CMyServerConnection(DICOM_SECURE_NONE); if (m_pServerConnection == NULL) { return; } nError = LDicomNet::Accept(m_pServerConnection); if (nError != DICOM_SUCCESS) { delete m_pServerConnection; return; } } L_VOID CMyServer::OnClose(L_INT nError, LDicomNet *pServerConnection) { UNREFERENCED_PARAMETER(nError); LogMessage(TEXT("\tCMyServer::OnClose")); if (m_pServerConnection == pServerConnection) { m_pServerConnection = NULL; } delete (CMyServerConnection *)pServerConnection; } // ******************************************************************************************* // Sample starts here // ******************************************************************************************* #define WaitForProcessing() \ { \ if (!client.Wait()) \ { \ LogMessage(TEXT("Timeout: client.Connect")); \ nRet = DICOM_ERROR_NET_TIME_OUT; \ goto Cleanup; \ } \ } L_INT LDicomNet_SendCCancelRequestExample() { LogMessage(TEXT("\n\n *** SendCCancelRequestExample ***")); L_TCHAR *pszServerAddress = TEXT("127.0.0.1"); L_UINT uServerPort = 105; L_INT nRet = DICOM_SUCCESS; LDicomNet::StartUp(); CMyClient client(DICOM_SECURE_NONE); CMyServer server(DICOM_SECURE_NONE); LogMessage(TEXT("\tCMyServer::Listen")); nRet = server.Listen(pszServerAddress, uServerPort, 5); LogMessage(TEXT("CMyClient::Connect")); client.Connect(NULL, 0, pszServerAddress, uServerPort); if (!client.Wait(2000)) { if (!client.IsConnected()) { LogMessage(TEXT("Timeout: client.Connect")); nRet = DICOM_ERROR_NET_TIME_OUT; goto Cleanup; } } if (nRet == DICOM_SUCCESS) { //create the Associate Class as Request LDicomAssociate dicomAssociateRequest(TRUE); dicomAssociateRequest.Default(); // Send A-Associate-RQ message dicomAssociateRequest.SetCalled(TEXT("LEAD_SERVER")); dicomAssociateRequest.SetCalling(TEXT("LEAD_CLIENT")); LogMessage(TEXT("CMyClient::SendAssociateRequest")); nRet = client.SendAssociateRequest(&dicomAssociateRequest); if (!client.Wait(5000)) { LogMessage(TEXT("Timeout: client.Connect")); nRet = DICOM_ERROR_NET_TIME_OUT; goto Cleanup; } } L_UCHAR nPresentationID = client.GetAssociate()->FindAbstract(UID_VERIFICATION_CLASS); L_UINT16 uUniqueID = 99; LogMessage(TEXT("CMyClient::SendCEchoRequest")); client.SendCEchoRequest( nPresentationID, uUniqueID, UID_VERIFICATION_CLASS); WaitForProcessing(); LogMessage(TEXT("CMyClient::SendCCancelRequest")); client.SendCCancelRequest( nPresentationID, uUniqueID); client.Wait(1000); LogMessage(TEXT("CMyClient::SendReleaseRequest")); client.SendReleaseRequest(); WaitForProcessing(); Cleanup: LogMessage(TEXT("CMyClient::Close")); client.Close(); client.Wait(1000); LogMessage(TEXT("\tCMyServer::Close")); server.Close(); LDicomNet::ShutDown(); return nRet; } }