\r
typedef NTSTATUS (* SendCBHandler )(SdpSocket *);\r
typedef NTSTATUS (* RecvCBHandler )(SdpSocket *);\r
+typedef NTSTATUS (* CheckSocketStateFunction )(SdpSocket *);\r
\r
\r
const int SEND_CB_CALLED = 0x00000001;\r
const int RECV_CB_CALLED = 0x00000002;\r
-const int SHUTDOWN_SIGNALLED = 0x00000004;\r
-const int SHUTDOWN_HANDELED = 0x00000008;\r
-const int ERROR_SIGNALLED = 0x00000010;\r
+const int ERROR_SIGNALLED = 0x00000004;\r
\r
const int DPC_FLAGS = SEND_CB_CALLED | RECV_CB_CALLED;\r
inline void ResetFlags(int &Flags)\r
{\r
if (flags & SEND_CB_CALLED) return true;\r
if (flags & RECV_CB_CALLED) return true;\r
- if ((flags & SHUTDOWN_SIGNALLED) && !(flags & SHUTDOWN_HANDELED) ) return true;\r
\r
return false;\r
}\r
m_NumberOfClientWaiting = 0;\r
}\r
\r
- VOID Init(SendCBHandler SendCB, RecvCBHandler RecvCB, SdpSocket *pSdpSocket)\r
+ VOID Init(\r
+ SendCBHandler SendCB, \r
+ RecvCBHandler RecvCB,\r
+ CheckSocketStateFunction CheckSocketState,\r
+ SdpSocket *pSdpSocket )\r
{\r
m_SendCBHandler = SendCB;\r
- m_pSdpSocket = pSdpSocket;\r
+ m_CheckSocketState = CheckSocketState;\r
m_RecvCBHandler = RecvCB;\r
+ m_pSdpSocket = pSdpSocket;\r
+ \r
}\r
\r
/*\r
return value of false means that the lock can not be taken (eitheir\r
shutdown or STATUS_ALERTED, or some error has happend)\r
*/\r
- bool Lock() {\r
+ bool Lock(bool Force = false) {\r
KIRQL OldIrql;\r
int OldFlags = 0;\r
NTSTATUS rc = STATUS_SUCCESS;\r
if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
SDP_PRINT(SDP_WARN, SDP_LOCK, ("MyKeWaitForSingleObject was alerted = 0x%x\n", rc ));\r
rc = STATUS_UNEXPECTED_IO_ERROR;\r
- SignalShutdown();\r
Locked = false;\r
goto Cleanup;\r
} \r
if (WaitedOnLock) {\r
m_NumberOfClientWaiting--;\r
}\r
- ASSERT(m_NumberOfClientWaiting >= 0);\r
+ ASSERT(m_NumberOfClientWaiting >= 0); \r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
rc = HandleFlags(OldFlags);\r
- if (!NT_SUCCESS(rc)) {\r
+ if ((Force == false) && \r
+ (!NT_SUCCESS(rc) ||\r
+ (m_flags & ERROR_SIGNALLED) ||\r
+ (!NT_SUCCESS(rc = m_CheckSocketState(m_pSdpSocket)))\r
+ )) {\r
// We have to signal the error to the calling side\r
SDP_PRINT(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
Locked = false;\r
- ASSERT(m_flags & ERROR_SIGNALLED);\r
KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
m_InUse = false;\r
// Release whoever is waiting\r
goto Cleanup;\r
}\r
// Exit the loop\r
+\r
Locked = true;\r
goto Cleanup; \r
} while (true);\r
Please note that the lock is freed no metter what the error code is.\r
An error means that there was some error in the sockets.\r
*/\r
+\r
+ //?????????? should this be ntstatus or bool ???????\r
NTSTATUS Unlock()\r
{\r
KIRQL OldIrql;\r
if (!SomethingToHandle(OldFlags)) {\r
// We can safely quit the lock\r
m_InUse = false;\r
+ // Before we leave this function we check for errors / shutdown here\r
+ if (m_flags & ERROR_SIGNALLED) {\r
+ rc = STATUS_UNEXPECTED_IO_ERROR;\r
+ } else {\r
+ rc = m_CheckSocketState(m_pSdpSocket);\r
+ }\r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
break;\r
}\r
*/\r
NTSTATUS HandleFlags(int flags) {\r
NTSTATUS rc = STATUS_SUCCESS;\r
- AssertLocked();\r
+ AssertLocked(); \r
+ // Try to do this faster if nothing to do\r
+ if (flags == 0) {\r
+ return STATUS_SUCCESS;\r
+ }\r
if (flags & SEND_CB_CALLED) {\r
// We need to handle the send CB\r
rc = m_SendCBHandler(m_pSdpSocket);\r
return rc;\r
}\r
\r
- VOID SignalShutdown() {\r
- //??????? Verify use and correctnes\r
- m_flags |= SHUTDOWN_SIGNALLED;\r
- }\r
-\r
- bool IsShutdownSignaled()\r
- {\r
- return m_flags & SHUTDOWN_SIGNALLED ? true : false;\r
- }\r
- \r
- VOID SignalError(NTSTATUS rc) {ASSERT (FALSE);} //????????????\r
+ VOID SignalError(NTSTATUS rc) {ASSERT (FALSE);\r
+ m_flags |= ERROR_SIGNALLED;\r
+ } \r
\r
VOID AssertLocked() {ASSERT(m_InUse);}\r
\r
KSPIN_LOCK m_SpinLock; // The real guard of the lock\r
SendCBHandler m_SendCBHandler;\r
RecvCBHandler m_RecvCBHandler;\r
+ CheckSocketStateFunction m_CheckSocketState;\r
\r
\r
bool m_InUse; // Tells if this lock has any user\r
NTSTATUS sdp_cm_hello_check(struct sdp_msg_hello *msg_hello);\r
static NTSTATUS __send_cb2(SdpSocket * pSdpSocket);\r
static NTSTATUS __recv_cb2(SdpSocket * pSdpSocket);\r
+static NTSTATUS __accept_requests(SdpSocket * pSdpSocket);\r
\r
static void AL_API\r
cm_rej_callback(IN ib_cm_rej_rec_t *p_cm_rej_rec )\r
\r
m_CreationFlags = pSocketInParam->dwFlags;\r
\r
- m_Lock.Init(__send_cb2, __recv_cb2, this);\r
+ m_Lock.Init(__send_cb2, __recv_cb2, __accept_requests ,this);\r
pSocketOutParam->Errno = 0;// No error\r
pSocketOutParam->pSocket = this; // give the user a handle to the socket\r
KeInitializeEvent(&m_ShutdownCompleteEvent, NotificationEvent , FALSE );\r
return rc;\r
}\r
\r
+\r
+NTSTATUS SdpSocket::AcceptRequests() \r
+{\r
+ // Check if our state allows us to handle send/recv/accept ...\r
+ if (m_ShutdownCalled) return STATUS_SHUTDOWN_IN_PROGRESS;\r
+ if (m_CloseSocketCalled) return STATUS_SHUTDOWN_IN_PROGRESS;\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
NTSTATUS SdpSocket::WSPSend(\r
WspSendIn *pWspSendIn,\r
WspSendOut *pWspSendOut\r
\r
}\r
\r
-\r
-\r
rc = m_Lock.Unlock();\r
+ if (rc == STATUS_SHUTDOWN_IN_PROGRESS) {\r
+ // shutdown in progress is fine since we have started the shutdown ...\r
+ rc = STATUS_SUCCESS;\r
+ }\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
goto Cleanup;\r
return pSdpSocket->recv_cb();\r
}\r
\r
+static NTSTATUS __accept_requests(SdpSocket * pSdpSocket)\r
+{\r
+ return pSdpSocket->AcceptRequests();\r
+}\r
+\r
NTSTATUS SdpSocket::send_cb()\r
{\r
SDP_PRINT(SDP_DEBUG, SDP_SOCKET, ("called this =0x%p\n", this));\r
}\r
// now take the lock and test again\r
\r
- m_Lock.Lock(); //????????????????????force this locking ????\r
+ m_Lock.Lock(true); //????? verify must succeed\r
if (m_ShutdownCalled) {\r
// Already handled\r
m_Lock.Unlock(); // Error is ignored since this is already\r