Program crashes when trying to retrieve contents of pointer - c++

I'm making a socket program in C++ using winsock2 and I'm trying to use WSAAccept to conditionally accept connections. I copied the example ConditionalFunction from MSDN for the lpfnCondition argument in WSAAccept as seen below.
SOCKET WSAAccept(
_In_ SOCKET s,
_Out_ struct sockaddr *addr,
_Inout_ LPINT addrlen,
_In_ LPCONDITIONPROC lpfnCondition, //<---------
_In_ DWORD_PTR dwCallbackData
);
However when trying to access the contents of lpCallerId in the ConditionalFunction like so WSABUF buffer = *lpCallerData my program crashes. I know this is the source of the problem because when I comment that line out my program doesn't crash. I don't think all of my code would be necessary. Any help would be lovely.
EDIT:
CALLBACK ConditionalAccept(LPWSABUF lpCallerId,LPWSABUF lpCallerData,LPQOS lpSQOS,
LPQOS lpGQOS,LPWSABUF lpCalleeId,LPWSABUF lpCalleeData,
GROUP *g,DWORD_PTR dwCallbackData)
{
WSABUF buffer = *lpCallerData;
if (lpSQOS != NULL) {
RtlZeroMemory(lpSQOS, sizeof(QOS));
return CF_ACCEPT;
} else
return CF_REJECT;
}
...
WSAAccept(slisten, (SOCKADDR*)&acceptSock, &Size, &ConditionalAccept, NULL);

As Luke stated, you are not checking lpCallerData for NULL before dereferencing it. That is why your code is crashing.
int CALLBACK ConditionalAccept(LPWSABUF lpCallerId,LPWSABUF lpCallerData,LPQOS lpSQOS,
LPQOS lpGQOS,LPWSABUF lpCalleeId,LPWSABUF lpCalleeData,
GROUP *g,DWORD_PTR dwCallbackData)
{
WSABUF buffer = {0};
if (lpCallerData != NULL) { // <-- add this check!
buffer = *lpCallerData;
}
if (lpSQOS != NULL) {
RtlZeroMemory(lpSQOS, sizeof(QOS));
return CF_ACCEPT;
} else
return CF_REJECT;
}
However, lpCallerData is meaningless in TCP/IP and will always be NULL. TCP/IP does not support exchanging caller/callee data during connection establishment. This is clearly stated in the WSAConnect() documentation:
The lpCallerData parameter contains a pointer to any user data that is to be sent along with the connection request (called connect data). This is additional data, not in the normal network data stream, that is sent with network requests to establish a connection. This option is used by legacy protocols such as DECNet, OSI TP4, and others.
Note Connect data is not supported by the TCP/IP protocol in Windows. Connect data is supported only on ATM (RAWWAN) over a raw socket.

Related

Passing data to another thread in a C++ winsock app

So I have this winsock application (a server, able to accept multiple clients), where in the main thread I setup the socket and create another thread where I listen for clients (listen_for_clients function).
I also constantly receive data from a device in the main thread, which I afterwards concatenate to char arrays (buffers) of Client objects (BroadcastSample function). Currently I create a thread for each connected client (ProcessClient function), where I initialize a Client object and push it to a global vector of clients after which I send data to this client through the socket whenever the buffer in the corresponding Client object exceeds 4000 characters.
Is there a way I can send data from the main thread to the separate client threads so I don't have to use structs/classes (also to send a green light if I want to send the already accumulated data) and also if I'm going to keep a global container of objects, what is a good way to remove a disconnected client object from it without crashing the program because another thread is using the same container?
struct Client{
int buffer_len;
char current_buffer[5000];
SOCKET s;
};
std::vector<Client*> clientBuffers;
DWORD WINAPI listen_for_clients(LPVOID Param)
{
SOCKET client;
sockaddr_in from;
int fromlen = sizeof(from);
char buf[100];
while(true)
{
client = accept(ListenSocket,(struct sockaddr*)&from,&fromlen);
if(client != INVALID_SOCKET)
{
printf("Client connected\n");
unsigned dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ProcessClient, (void*)client, 0, &dwThreadId);
}
}
closesocket(ListenSocket);
WSACleanup();
ExitThread(0);
}
unsigned __stdcall ProcessClient(void *data)
{
SOCKET ClientSocket = (SOCKET)data;
Client * a = new Client();
a->current_buffer[0] = '\0';
a->buffer_len = 0;
a->s = ClientSocket;
clientBuffers.push_back(a);
char szBuffer[255];
while(true)
{
if(a->buffer_len > 4000)
{
send(ClientSocket,a->current_buffer,sizeof(a->current_buffer),0);
memset(a->current_buffer,0,5000);
a->buffer_len = 0;
a->current_buffer[0] = '\0';
}
}
exit(1);
}
//function below is called only in main thread, about every 100ms
void BroadcastSample(Sample s)
{
for(std::vector<Client*>::iterator it = clientBuffers.begin(); it != clientBuffers.end(); it++)
{
strcat((*it)->current_buffer,s.to_string);
(*it)->buffer_len += strlen(s.to_string);
}
}
This link has some Microsoft documentation on MS-style mutexes (muticies?).
This other link has some general info on mutexes.
Mutexes are the general mechanism for protecting data which is accessed by multiple threads. There are data structures with built-in thread safety, but in my experience, they usually have caveats that you'll eventually miss. That's just my two cents.
Also, for the record, you shouldn't use strcat, but rather strncat. Also, if one of your client servicing threads accesses one of those buffers after strncat overwrites the old '\0' but before it appends the new one, you'll have a buffer overread (read past end of allocated buffer).
Mutexes will also solve your current busy-waiting problem. I'm not currently near a windows compiler, or I'd try to help more.

ProtocolBuffer can't define data although it is received

I'm trying to use Google's ProtocolBuffer to send/receive data in a server/client architecture. I am able to connect the two with winsock and I am able to send and receive data from ProtocolBuffer with it but there seems to be a problem with deserializing the data on the server (I haven't done the opposite so I can't tell if that works yet)
Here's the code I use to create a sample packet of data to send to the server:
MessageID *message = new MessageID();
message->set_type(MessageID::Type::MessageID_Type_PLAYERDATA);
PlayerData::Vector2 *position = new PlayerData::Vector2();
position->set_x(10.0f);
position->set_y(25.0f);
PlayerData *data = new PlayerData();
data->set_health((UINT32)50);
data->set_allocated_position(position);
auto inventory = data->add_items();
inventory->set_itemid((INT32)1);
inventory->set_count((INT32)5);
message->set_allocated_playerdata(data);
m_pNetworkObject->Send(message);
This is the code that actually sends the data over a TCP connection:
// Serialize to string.
std::string sendData;
data->SerializeToString(&sendData);
// Convert data to const char*
const char* dataToSend = sendData.c_str();
int iResult;
iResult = send( ConnectSocket, dataToSend, data->ByteSize(), 0 );
if (iResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
exit(1);
}
So, this was code that is run on the client. Now, when I receive this on the server I get the following errors from ProtocolBuffer:
Can't parse message of type "MessageID" because it is missing required fields: type
Can't parse message of type "PlayerData" because it is missing required fields: Position, Health
The code on the server that decompiles the winsock data is like this:
// decompile to a proto file and check ID
MessageID* receivedData = new MessageID();
receivedData->ParseFromArray(&recv, strlen(recv));
// check and redeserialize
switch (receivedData->type())
{
case MessageID::Type::MessageID_Type_PLAYERDATA:
{
PlayerData* playerData = new PlayerData();
playerData->ParseFromArray(&recv, strlen(recv));
UsePlayerData(sock, playerData);
break;
}
case MessageID::Type::MessageID_Type_WORLDDATA:
{
WorldData* worldData = new WorldData();
worldData->ParseFromArray(&recv, strlen(recv));
UseWorldData(sock, worldData);
break;
}
}
The weird thing is that, although the error says that the data doesn't contain the Type value it does set it to 1 and the switch statement works. After that when I try to take a look at the Position and Health data everything is 0.
I have no idea what I'm doing wrong. I read most of the ProtocolBuffer tutorials and help but it seems to no avail.
EDIT:
I tried serializing and then deserializing the data in the same application (without the networking involved) and with the following code it worked to do just that:
std::string sendData;
message->SerializeToString(&sendData);
MessageID* receivedData = new MessageID();
receivedData->ParseFromString(sendData);
If I check the data in receivedData it is exactly the same (so, the right values) as in the original object "message"
Your problem is that you are using strlen() to find the length of the message. strlen() just looks for the first zero-valued byte and assumes that's the end. This is the convention for text strings, but does not apply to binary messages like Protocol Buffers. In this case, strlen() is returning a size that is too short and so some fields are missing from the message, but the opposite can happen too -- strlen() can run off the end of the buffer and return a size that is too long, or even crash your program.
So, you need to make sure the actual exact size of the message is communicated from the sender to the receiver.

why shutdown on udp socket blocks?

I'm writing a UDP server application for windows desktop/server.
My code uses the WSA API suggested by windows the following way (This is my simplified receivePacket method):
struct Packet
{
unsigned int size;
char buffer[MAX_SIZE(1024)];
}
bool receivePacket(Packet packet)
{
WSABUFFER wsa_buffer[2];
wsa_buffer[0].buf = &packet.size;
wsa_buffer[0].len = sizeof(packet.size);
wsa_buffer[1].buf = packet.buffer;
wsa_buffer[1].len = MAX_SIZE;
bool retval = false;
int flags = 0;
int recv_bytes = 0;
inet_addr client_addr;
int client_addr_len = sizeof(client_addr);
if(WSARecvFrom(_socket, wsa_buffer, sizeof(wsa_buffer)/sizeof(wsa_buffer[0]), &bytes_recv, &flags, (sockaddr *)&client_addr, &client_addr_len, NULL, NULL) == 0)
{
//Packet received successfully
}
else
{
//Report
}
}
Now, when I'm trying to close my application gracefully, not network-wise, but rather application-wise (going through all the d'tors and stuff), i'm trying to unblock this call.
To do this, I call the shutdown(_socket, SD_BOTH) method. Unfortunately, the call to shutdown itself BLOCKS!
After reading every possible page in the MSDN, I didn't find any reference to why this happens, other ways of attacking the problem or any way out.
Another thing I checked was using the SO_RCVTIMEO. Surprisingly, this sockopt didn't work as expected as well.
Is there any problem with my code/approach?
Did you run shutdown on duplicated handle? Shutdown on the same handle will wait any active operation on this handle to complete.

C++ Get Handle of Open Sockets of a Program

How is it possible to get the Socket ID (Handle) of the created sockets of a program?
I know I can get all the open sockets in all programs by GetTcpTable() but it has two problems:
It shows all programs sockets
It doesn't return ID (Handle) of sockets
As Remy said, its not trivial. You have to call OpenProcess with PROCESS_DUP_HANDLE for each process in the system. You might also need PROCESS_QUERY_INFORMATION and PROCESS_VM_READ, but I've never needed it (I've seen other code that uses it).
For each process, you access the donor process's handle table with NtQuerySystemInformation (with an information class of SystemHandleInformation). Finally, you call DuplicateHandle to make the process's handle your handle, too.
You will have to filter the handle types when enumerating the donor process's handle table. For each handle you have duplicated, call NtQueryObject with ObjectTypeInformation. If the type is a socket, you keep it open and put it in your list. Otherwise, close it and go on.
To perform the compare, the code looks similar to below. The type is returned as a UNICODE_STRING:
// info was returned from NtQueryObject, ObjectTypeInformation
POBJECT_TYPE_INFORMATION pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)(LPVOID)info;
wstring type( pObjectTypeInfo->Name.Buffer, pObjectTypeInfo->Name.Length );
if( 0 != wcscmp( L"Socket", type.c_str() ) ) { /* Not a Socket */ }
If there is no Socket type (I don't recall), you should try to get the name associated with the handle (its still a UNICODE_STRING), and look for \\Device\\Tcp. This time, you would use the same handle, but call NtQueryObject with ObjectNameInformation:
// info was returned from NtQueryObject, ObjectNameInformation
POBJECT_NAME_INFORMATION pObjectNameInfo = (POBJECT_NAME_INFORMATION)(LPVOID)info;
wstring name( pObjectNameInfo->Name.Buffer, pObjectNameInfo->Name.Length );
if( name.substr(0, 11) == "\\Device\\Tcp" ) ) { /* It's a TCP Socket */ }
Myself an another fellow did similar a few years ago. Instead of Sockets, we used Mutexes and Events to crash privileged Antivirus components from their userland UI program (which was sharing handles with the privileged component for IPC). See Old Dogs and New Tricks: Do You Know Where Your Handles Are?.
Ok, thanks to everyone that tried to solve my problem
After a lot of works I get how to handle it myself, this is how i tried to get the specified socket :
At the first I looked in to program's disassembly and find out the calls to WS2_32 Send function.
As the picture show there is a call to Socket send function at 0x467781 and the Socket handle saved to the stack in the EDX register
Now what i need to do is to Hook my code in to that function.
void GetSocket(int Flag,int DataSize, char* Data, SOCKET Socket)
{
sSocket = Socket;
sFlag = Flag;
sDataSize = DataSize;
sData = Data;
SendPacket(sSocket,Data,DataSize); //Send packets manually
}
__declspec(naked) void MyFunc()
{
__asm
{
PUSH EDX // Socket
PUSH ECX // Buffer
PUSH EAX // Buffer Size
PUSH 0 // Flag
CALL GetSocket
MOV EAX, sDataSize
MOV ECX, sData
MOV EDX, sWowSocket
JMP [JumpAddress] // JumpAddress = 0x467787 (After that CALL)
}
}
And now i all have to do is to change that CALL (in 0x467781) to a JMP to our function(MyFunc) and it can be done with the following function :
*(DWORD*) (0x467781 + 0x01) = (DWORD)MyFunc- (0x467781 + 0x05);
Now I'm done,I can easily see each packet that it sends to server and change them if necessary and also send my custom packets whit its Socket :)

How to pass user-defined data to a worker thread using IOCP?

Hey... I created a small test server using I/O completion ports and winsock.
I can successfully connect and associate a socket handle with the completion port.
But I don´t know how to pass user-defined data-structures into the wroker thread...
What I´ve tried so far was passing a user-structure as (ULONG_PTR)&structure as the Completion Key in the association-call of CreateIoCompletionPort()
But that did not work.
Now I tried defining my own OVERLAPPED-structure and using CONTAINING_RECORD() as described here http://msdn.microsoft.com/en-us/magazine/cc302334.aspx and http://msdn.microsoft.com/en-us/magazine/bb985148.aspx.
But that does not work, too. (I get freaky values for the contents of pHelper)
So my Question is: How can I pass data to the worker thread using WSARecv(), GetQueuedCompletionStatus() and the Completion packet or the OVERLAPPED-strucutre?
EDIT: How can I successfully transmit "per-connection-data"?... It seems like I got the art of doing it (like explained in the two links above) wrong.
Here goes my code: (Yes, its ugly and its only TEST-code)
struct helper
{
SOCKET m_sock;
unsigned int m_key;
OVERLAPPED over;
};
///////
SOCKET newSock = INVALID_SOCKET;
WSABUF wsabuffer;
char cbuf[250];
wsabuffer.buf = cbuf;
wsabuffer.len = 250;
DWORD flags, bytesrecvd;
while(true)
{
newSock = accept(AcceptorSock, NULL, NULL);
if(newSock == INVALID_SOCKET)
ErrorAbort("could not accept a connection");
//associate socket with the CP
if(CreateIoCompletionPort((HANDLE)newSock, hCompletionPort, 3,0) != hCompletionPort)
ErrorAbort("Wrong port associated with the connection");
else
cout << "New Connection made and associated\n";
helper* pHelper = new helper;
pHelper->m_key = 3;
pHelper->m_sock = newSock;
memset(&(pHelper->over), 0, sizeof(OVERLAPPED));
flags = 0;
bytesrecvd = 0;
if(WSARecv(newSock, &wsabuffer, 1, NULL, &flags, (OVERLAPPED*)pHelper, NULL) != 0)
{
if(WSAGetLastError() != WSA_IO_PENDING)
ErrorAbort("WSARecv didnt work");
}
}
//Cleanup
CloseHandle(hCompletionPort);
cin.get();
return 0;
}
DWORD WINAPI ThreadProc(HANDLE h)
{
DWORD dwNumberOfBytes = 0;
OVERLAPPED* pOver = nullptr;
helper* pHelper = nullptr;
WSABUF RecvBuf;
char cBuffer[250];
RecvBuf.buf = cBuffer;
RecvBuf.len = 250;
DWORD dwRecvBytes = 0;
DWORD dwFlags = 0;
ULONG_PTR Key = 0;
GetQueuedCompletionStatus(h, &dwNumberOfBytes, &Key, &pOver, INFINITE);
//Extract helper
pHelper = (helper*)CONTAINING_RECORD(pOver, helper, over);
cout << "Received Overlapped item" << endl;
if(WSARecv(pHelper->m_sock, &RecvBuf, 1, &dwRecvBytes, &dwFlags, pOver, NULL) != 0)
cout << "Could not receive data\n";
else
cout << "Data Received: " << RecvBuf.buf << endl;
ExitThread(0);
}
If you pass your struct like this it should work just fine:
helper* pHelper = new helper;
CreateIoCompletionPort((HANDLE)newSock, hCompletionPort, (ULONG_PTR)pHelper,0);
...
helper* pHelper=NULL;
GetQueuedCompletionStatus(h, &dwNumberOfBytes, (PULONG_PTR)&pHelper, &pOver, INFINITE);
Edit to add per IO data:
One of the frequently abused features of the asynchronous apis is they don't copy the OVERLAPPED struct, they simply use the provided one - hence the overlapped struct returned from GetQueuedCompletionStatus points to the originally provided struct. So:
struct helper {
OVERLAPPED m_over;
SOCKET m_socket;
UINT m_key;
};
if(WSARecv(newSock, &wsabuffer, 1, NULL, &flags, &pHelper->m_over, NULL) != 0)
Notice that, again, in your original sample, you were getting your casting wrong. (OVERLAPPED*)pHelper was passing a pointer to the START of the helper struct, but the OVERLAPPED part was declared last. I changed it to pass the address of the actual overlapped part, which means that the code compiles without a cast, which lets us know we are doing the correct thing. I also moved the overlapped struct to be the first member of the struct.
To catch the data on the other side:
OVERLAPPED* pOver;
ULONG_PTR key;
if(GetQueuedCompletionStatus(h,&dw,&key,&pOver,INFINITE))
{
// c cast
helper* pConnData = (helper*)pOver;
On this side it is particularly important that the overlapped struct is the first member of the helper struct, as that makes it easy to cast back from the OVERLAPPED* the api gives us, and the helper* we actually want.
You can send special-purpose data of your own to the completion port via PostQueuedCompletionStatus.
The I/O completion packet will satisfy
an outstanding call to the
GetQueuedCompletionStatus function.
This function returns with the three
values passed as the second, third,
and fourth parameters of the call to
PostQueuedCompletionStatus. The system
does not use or validate these values.
In particular, the lpOverlapped
parameter need not point to an
OVERLAPPED structure.
I use the standard socket routines (socket, closesocket, bind, accept, connect ...) for creating/destroying and ReadFile/WriteFile for I/O as they allow use of the OVERLAPPED structure.
After your socket has accepted or connected you should associate it with the session context that it services. Then you associate your socket to an IOCP and (in the third parameter) provide it with a reference to the session context. The IOCP does not know what this reference is and doesn't care either for that matter. The reference is for YOUR use so that when you get an IOC through GetQueuedCompletionStatus the variable pointed to by parameter 3 will be filled in with the reference so that you immediately find the context associated with the socket event and can begin servicing the event. I usually use an indexed structure containing (among other things) the socket declaration, the overlapped structure as well as other session-specific data. The reference I pass to CreateIoCompletionPort in parameter 3 will be the index to the structure member containing the socket.
You need to check if GetQueuedCompletionStatus returned a completion or a timeout. With a timeout you can run through your indexed structure and see (for example) if one of them has timed out or something else and take appropriate house-keeping actions.
The overlapped structure also needs to be checked to see that the I/O completed correctly.
The function servicing the IOCP should be a separate, multi-threaded entity. Use the same number of threads that you have cores in your system, or at least no more than that as it wastes system resources (you don't have more resources for servicing the event than the number of cores in your system, right?).
IOCPs really are the best of all worlds (too good to be true) and anyone who says "one thread per socket" or "wait on multiple-socket list in one function" don't know what they are talking about. The former stresses your scheduler and the latter is polling and polling is ALWAYS extremely wasteful.