AcceptEx accepts a new connection out of nowhere

Hey,

in the program am using the overlapped version of AcceptEx() to accept new connections. After a new connection has been accepted, the programm initiates another overlapped call to AcceptEx() for accepting more connections. This works fine and i can connect multiple clients to the server successfully.

But if i just connect one client and let the server-application call WSARecv (overlapped) on this socket, AcceptEx() magically accepts a new "ghost"-connection (There is the first client running doing nothing). When i call WSARecv on that, of course - it gives an error.

The program incorporates an I/O-Completion Port for all the overlapped calls.

I donĀ“t know where the fake connection comes from. But that it seems to be a bug in my code that i am unable to find.

Things i can definetly exclude from being the errors reason: 1.The overlapped-structures i use and the parameter for casting works correct. 2. The IOCP-wrapper class.


The responsible code (as i think it is in there):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//schematic
main()
{
	Server.Init(...);
	Server.Start();			//Run-loop
}

CServer::Init(/*...*/)
{
	[...]


	//Create the listen socket...
	Ret = InitAcceptorSocket(strLocalAddress, strListenPort, nBacklog);
	if(Ret != Inc::INC_OK)
		return Ret;

	//...Associate it with the IOCP
	if(!m_pIOCP->AssociateHandle((HANDLE) m_pListenSocket->operator size_t(), 2))
		return Inc::INC_FATAL;

	[...]
}

CServer::InitAcceptorSocket(const std::wstring& strLocalAddress, const std::wstring& strListenPort, int nBacklog)
{
	//Create the socket
	m_pListenSocket.reset(new Inc::CSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP));

	//Bind to specific port
	if(!m_pListenSocket->Bind(Inc::WStringToString(strLocalAddress), Inc::WStringToString(strListenPort)))		//Works as bind just calls getadrrinfo within itself

	//Put the socket into listen mode
	if(!m_pListenSocket->Listen(nBacklog))		//simple listen-wrapper: just calls the function and returns status indication
}

//Starts the server's work-cycle
CServer::Start(/**/)
{
	//Call accept
	DoCallAccept(m_pListenSocket.get());

	//Resume the threads
	//std::for_each(m_vecThreadHandles.begin(), m_vecThreadHandles.end(), [] (HANDLE hThread) {::ResumeThread(hThread);} );

	//TEST: Enter the Loop, too
	ServerMainWorkerThreadProc(this);

	return Inc::INC_OK;
}


//Worker thread proc
uintptr_t WINAPI ServerMainWorkerThreadProc(void* pvArgs)
{
	CServer* pServer = (CServer*)pvArgs;
	bool bLooping = true;

	try
	{
		while(bLooping)
		{
			bLooping = pServer->DoWork();
		};
	}
	catch(Inc::CException& e)
	{
		DebugBreak();
	}

	return 0;
}


bool CServer::DoWork()
{

	DWORD dwBytes = 0;
	ULONG_PTR ulKey = 0;
	OVERLAPPED* pOverlapped = nullptr;

	//Dequeue a completion packet
	if(!m_pIOCP->GetCompletionStatus(&dwBytes, &ulKey, &pOverlapped, INFINITE))
	{
		//error stuff
	}

	//Check for termination request:
	if(!dwBytes && !ulKey && !pOverlapped)
		return false;

	//Convert the Overlapped and check which work has to be done
	switch(((MYOVERLAPPED*)pOverlapped)->WorkType)
	{
	case WT_ACCEPT:					//A new connection has been accepted
		HandleAcceptedConnection((WORK_ACCEPT*)pOverlapped);
		break;
	case WT_SEND:					//Send data
		//HandleSendRequest((WORK_SEND*)pOverlapped);
		break;
	case WT_RECV:					//Data has been received
		//HandleReceivedData((WORK_RECV*)pOverlapped);
		break;
	[...]
		
	return true;
}

	//New connection has been accepted
bool CServer::HandleAcceptedConnection(WORK_ACCEPT* pWork)
{
	//Create a new client socket object
	std::unique_ptr<Inc::CSocket> pSocket(new Inc::CSocket(pWork->SocketNewConnection));		//obtains the nescessary information (like AF_INET , etc by calls to getsockopt - works fine)

	//Associate with the IOCP
	if(!m_pIOCP->AssociateHandle((HANDLE)((SOCKET)(*(pSocket.get()))), 2))
	{
		//Report the error
	}

	//Queue a recv-packet
	if(!DoCallRecv(pSocket.get()))
	{
		//Report the error
	}

	//Release the client-socket-object
	pSocket.release();

	//Call accept another time
	DoCallAccept(pWork->pListenSocket);

	//Cleanuo
	delete pWork;

	return true;
}


//Call Recv on the socket
bool CServer::DoCallRecv(Inc::CSocket* pSocket)
{
	//Create the work object for receiving data
	std::unique_ptr<WORK_RECV> pWorkRecv(new WORK_RECV);
	memset((OVERLAPPED*)pWorkRecv.get(), 0, sizeof(OVERLAPPED));
	pWorkRecv->pSocket = pSocket;


	//Call Recv
	std::string strRecvBuffer;		//temporary receive buffer for immediate completion
	short sRet = pSocket->Recv(strRecvBuffer, pWorkRecv->pTestWSABuf, 2048, (OVERLAPPED*)pWorkRecv.get());
	[...]
	if(sRet == Inc::REMOTETRANSACTION_PENDING)
	{
		//release the work item so it is still on the heap when the overlapped operation completes
		pWorkRecv.release();
	}

	return true;
}

//Queue a call to accept
bool CServer::DoCallAccept(Inc::CSocket* pListenSocket)
{
	//Create the overlapped-structure
	std::unique_ptr<WORK_ACCEPT> pWork(new WORK_ACCEPT);
	memset((OVERLAPPED*)pWork.get(), 0, sizeof(OVERLAPPED));
	pWork->pListenSocket = pListenSocket;
	pWork->pSocket = m_pListenSocket.get();

	//Call accept
	pWork->SocketNewConnection = m_pListenSocket->Accept(nullptr, nullptr, (OVERLAPPED*)pWork.get());

	//Release the work object
	pWork.release();

	return true;
}


//The accept function for My custom socket-wrapper-class
SOCKET Inc::CSocket::Accept(sockaddr_storage* pAddr, int* pAddrLen, OVERLAPPED* pOverlapped)
{
	[...]
	else		//Overlapped
	{
		//create the client socket
		SOCKET ClientSock = socket(m_SocketAF, SOCK_STREAM, 0);
		if(ClientSock == INVALID_SOCKET)
			throw(Inc::CException(WSAGetLastError(), "Socket creation failed."));
		//address structure & size
		sockaddr_storage *ClientAddress = {0}; DWORD dwClientAddressSize = sizeof(sockaddr_storage);
		//output buffer
		//char acOutputBuffer[(2 * sizeof(sockaddr_storage)) + 32] = "";
		//received bytes
		DWORD dwBytes = 0;

		if(m_lpfnAcceptEx(m_Socket, ClientSock, (PVOID)m_acOutputBuffer, 0, (dwClientAddressSize + 16), (dwClientAddressSize + 16), &dwBytes, pOverlapped) == FALSE)
		{
			int nError = WSAGetLastError();
			if(nError != WSA_IO_PENDING)
				throw(Inc::CException(nError, "AcceptEx failed."));

			return ClientSock;
		}

		//if immidiately & successfully connected, get the client address
		[...]

		return ClientSock;
	}
}


//The receive function
short Inc::CSocket::RecvHelper(std::string& strIncomingDataBuffer, WSABUF*& pWSABuf, unsigned int nBytesToRecv, OVERLAPPED* pOverlapped)
{
	int iRet = 0;					//ret code
	DWORD dwReceived = 0, dwFlags = 0;

	//Clear the Buffer
	strIncomingDataBuffer.clear();

	//create the receiving buffer
	std::unique_ptr<char[]> pcBuf(new char[nBytesToRecv]);
	//create the WSABUF
	std::unique_ptr<WSABUF> pWSABufBuf (new WSABUF);
	pWSABufBuf->len = nBytesToRecv;
	pWSABufBuf->buf = pcBuf.get();


	iRet = WSARecv(m_Socket, pWSABufBuf.get(), 1, pOverlapped ? NULL : (&dwReceived), &dwFlags, pOverlapped, NULL);
	if(iRet == 0)
	{
		//closed (gracefully) by the client (indicated by zero bytes returned)
		if(dwReceived == 0 && (!pOverlapped))
			return REMOTECONNECTION_CLOSED;		//return

		//successfull received
		strIncomingDataBuffer.assign(pWSABufBuf->buf, dwReceived);

		return SUCCESS;
	}
	if(iRet == SOCKET_ERROR)
	{
		int nError = WSAGetLastError();

		//Overlapped transaction initiated successfully
		//waiting for completion
		if(nError == WSA_IO_PENDING)
		{
			//release the buffers
			pcBuf.release();
			pWSABuf = pWSABufBuf.release();		//hand it over to the user

			return REMOTETRANSACTION_PENDING;	//return "transaction pending"-status
		}

		//forced closure(program forced to exit)
		if(nError == WSAECONNRESET)
		{
		[...]
}
Topic archived. No new replies allowed.