How to get buffer into CompletionROUTINE as apart of WSARecvFrom call? - c

I'm working on a UDP server, and am trying to use overlapped IO. I've been trying to use MSDN examples and documentation for research but haven't found use of the lpCompletionRoutine argument of the function.
I notice you pass a PWSAOVERLAPPED to WSARecvFrom, and it contains a LPVOID Pointer member. Would I create my own user-data structure that contains a reference to the buffer and pass it as a pointer inside this Pointer member of PWSAOVERLAPPED?
I thought it was a bit redundant though that the received bytes were available in two places:
WSARecvFrom's lpNumberOfBytesRecvd argument, and lpCompletionRoutine's cbTransferred parameter.
Example of my current completion routine:
void CALLBACK CompletionROUTINE(
DWORD dwError,
DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags
) {
UNREFERENCED_PARAMETER(dwError);
UNREFERENCED_PARAMETER(lpOverlapped);
UNREFERENCED_PARAMETER(dwFlags);
/* Best way to get the bytes read here? */
Printf(L"Recieved %d bytes\n", cbTransferred);
}
and my call to WSARecvFrom:
iResult = WSARecvFrom(
listenSocket,
&wsaBuffer,
1,
&dwBytesRecieved,
&dwFlags,
(PSOCKADDR)&sender,
&senderAddrSize,
&wsaOverlapped,
CompletionROUTINE
);

From the WSAOVERLAPPED structure documentation:
hEvent Type: HANDLE
If an overlapped I/O operation is issued without an I/O completion routine (the operation's lpCompletionRoutine parameter is
set to null), then this parameter should either contain a valid handle
to a WSAEVENT object or be null. If the lpCompletionRoutine parameter
of the call is non-null then applications are free to use this
parameter as necessary.
So since I am providing a lpCompletionRoutine parameter, I can use WSAEvent as a pointer to my user defined data.
Thank you to the commenter that lead me to this finding.

Related

POSIX AIO callback called with the same (wrong) sigval repeatedly

I send 100 requests using aio_write. I set the sigval (callback argument) to some address using request.aio_sigevent.sigev_value.sival_ptr = some_address;. Each request has a different address. The callback is supposed to write some data to the address.
I expect the callback to be called 100 times with the 100 different arguments I gave it. Instead, the callback is called 100 times with the same argument every time: the argument for the 100th request. I've tried with both SIGEV_THREAD and SIGEV_SIGNAL with the same result both times.
The code snippet where I send the requests:
for (int i = 0; i < num_requests; i++) {
struct aiocb request = build_request(/* snip */, &array[i]);
aio_write(&request);
}
(where build_request simply constructs a struct aiocb and writes to the aio fields, as well as the aio_sigevent fields: sigev_notify, sigev_signo or sigev_notify_function, and sigev_value.sival_ptr.)
Why is this happening?
From the aio_write manual:
The control block must not be changed while the write operation is in progress.
In your case the variable goes out of scope as soon as each loop iteration ends. So it's Undefined Behaviour both in terms of pure C and in terms of the API being called. One solution is to create a static or dynamic array of aiocb.

How mmap with NULL addr works?

It is specified that when using mmap with NULL addr, the kernel chooses the (page-aligned) address at which to create the mapping:
mmap() creates a new mapping in the virtual address space of the
calling process. The starting address for the new mapping is
specified in addr. The length argument specifies the length of the
mapping (which must be greater than 0). If addr is NULL, then the kernel chooses the (page-aligned) address
at which to create the mapping; this is the most portable method of
creating a new mapping.
Supposing I have the code below :
void (*x)(void);
void (*y)(void);
x=mmap(NULL, 0x500, PROT..., FLAGS..., FD..., 0);
y=mmap(NULL, 0x500, PROT..., FLAGS..., FD..., 0);
Does it means that y will follow just after x ?
Thanks.
No, it does not say anything about the relative positioning of the mappings so you can't make any assumptions about it. Treat each mapping as completely separate from all others.

What is exc_fd_set in curl_multi_fdset()?

Curl's curl_multi_fdset function has the following declaration:
CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
Curl documentation does not explain the meaning of exc_fd_set. What is the meaning of exc_fd_set?
I have just updated the curl_multi_fdset() man page to better explain what the arguments are actually used for:
If the read_fd_set argument is not a null pointer, it points to an
object of type fd_set that on returns specifies the file descriptors
to be checked for being ready to read.
If the write_fd_set argument is not a null pointer, it points to an
object of type fd_set that on return specifies the file descriptors to
be checked for being ready to write.
If the exc_fd_set argument is not a null pointer, it points to an
object of type fd_set that on return specifies the file descriptors to
be checked for error conditions pending.
Very likely the same meaning as with select(2), as the function is meant to supply the FD sets for it.
Those listed in readfds will be watched to see if characters become available for reading (more precisely, to see if a read will not block; in particular, a file descriptor is also ready on end-of-file), those in writefds will be watched to see if a write will not block, and those in exceptfds will be watched for exceptions.

lpNumberOfBytesRead and lpNumberOfBytesWritten using Sockets

I am learning C and I am wondering what I need to add for those values in my WriteFile and ReadFile methods
lpNumberOfBytesRead and lpNumberOfBytesWritten
WriteFile((HANDLE)sock, "\x05\x01\x00", 3, NULL, NULL);
ReadFile((HANDLE)sock, buf, 1024, NULL, NULL);
it says in the documentation one of the two NULL values can't be NULL as my friend pointed out...
Any ideas *cheers
Assuming that you are not going to use overlapped I/O, (and from your question, I get a strong feeling that you are not), you need to pass a pointer to a DWORD variable that will receive the values:
DWORD NumberOfBytesWritten;
WriteFile((HANDLE)sock, "\x05\x01\x00", 3, &NumberOfBytesWritten, NULL);
If the function returns successfully (and you should check its return value to determine that), NumberOfBytesWritten will be set to the number of bytes that were actually written to the file.

passing structure to a function in C

I have a structure :
PROCESSENTRY32 pe32;
I want to pass this structure to a function. The function will create a file and write the data in the structure to that file. Name of the function is takeinput(). I passed the structure to function :
errflag = takeinput (&pe32);
In takeinput(PROCESSENTRY32 *pe31), I created a file D:\File.txt by using createfile(). Now I have to write the date from into file.txt. I am using :
WriteFile(
hFile, // open file handle
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
Here hFile I know. Last three I know. but I am confused about the DataBuffer paramter. What to pass there ? There are many variables in structure pe31. Can anybody help me in this?
If there is another way to write the data of the structure to the file.txt, kindly explain me. Thanks in advance.
That's the buffer which holds your data. Your call will be:
takeinput (PROCESSENTRY32* ppe32)
{
WriteFile(
hFile, // open file handle
(void*)ppe2, // pointer to buffer to write
sizeof(PROCESSENTRY32), // number of bytes to write
&dwBytesWritten, // this will contain number of bytes actually written
NULL); // no overlapped structure
// some other stuff
}
After return dwBytesWritten should be equal to sizeof(PROCESSENTRY32).
WriteFile function signature is
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out_opt LPDWORD lpNumberOfBytesWritten,
__inout_opt LPOVERLAPPED lpOverlapped
);
your DataBuffer is lpBuffer in the signature and lpBuffer is a pointer to the buffer containing the data to be written to the file or device. You should explicitly cast a pointer to your data (PROCESSENTRY32 pe31) to a pointer to void ( (void)pe31 ) and pass it to WriteFile.
Have you read the documentation for the WriteFile function? That might help you understand what each of the parameters that it takes are used for and what they mean.
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out_opt LPDWORD lpNumberOfBytesWritten,
__inout_opt LPOVERLAPPED lpOverlapped
);
You say you're confused about the DataBuffer parameter. MSDN explains that this is:
A pointer to the buffer containing the data to be written to the file or device.
This buffer must remain valid for the duration of the write operation. The caller must not use this buffer until the write operation is completed.
So, in essence, the DataBuffer (lpBuffer) parameter is where you provide the data that you want to be written out to the text file.
There's a full example of how to open and write to a file here. You should be able to follow along with the code to see how to code this for your specific case.

Resources