libcurl: how to get a file descriptor from an active connection? - libcurl

Piggybacking on the topic described here (Using libcurl multi interface for consecutive requests for same "easy" handle), my organization has wrapper classes for select and poll to handle input/output from file descriptors. In keeping aligned with our wrapper classes, I would like to get the file descriptor of each easy handle. I'm using the multi interface to work with multiple easy handles in a real time application.
I understand I can use the curl_multi_fd_set to get the FD sets. I could loop through the FD set to get the FD number. However, I won't know the associated easy handle for the FD. Additionally, if an FD is opened above the FD_SET limit, I won't get that FD.
Another option I'm considering is to use the curl_easy_getinfo and use the ACTIVESOCKET or LASTSOCKET options. My libcurl is old, so I couldn't use the ACTIVESOCKET for a test. However, a little test I performed using the curl_multi_perform, followed by a curl_easy_getinfo(LASTSOCKET) gave me a result of -1 -- meaning no file descriptor. Easy handle requests were performed on websites such as google.com. I'll try to update my libcurl to a newer version to see if I get a different result with the ACTIVESOCKET.
Is there another way to get the file descriptor from the easy handle?

I would propose you switch over and use the multi_socket API instead, with curl_multi_socket_action being the primary driver.
This API calls you to tell you about each and every socket to wait for, and then you wait for that/those and tell libcurl when something happened on that socket. It allows you to incorporate libcurl into your own IO loop/socket wrapper systems pretty easily.

Related

Is it possible to wrap existing TCP/OpenSSL session with `iostream`?

I use custom code to create SSL connection over native Berkeley sockets interface. I need to wrap the resulted socket with iostream to use existing algorithms written in C++ with these sockets data.
Is there any easy way to do it without need to implement stream and streambuf from scratch?
I learned boost::iostreams and boost::asio.
I didn't find any way to wrap existing OpenSSL session with boost::asio. Or may be anyone knows how to do that?
After boost:asio I concentrated my research on boost:iostreams.
boost::iostreams looks like good idea, however, its problem is that it uses read buffering. So, if we need to read just 1 byte from SSL session, it asks the TCP device to read 4 kilobytes and results in timeout. From the other hand, when I set buffer size to 0, boost::iostreams start to call write method for each byte, so when I try to write 10 bytes to stream, it calls SSL_write 10 times. TCP device itself can not use write buffering, because there are no way to forward flush method to device, so application level protocol may expect that data is sent to another peer while the data remains in output buffer.
So, we need unbuffered read and buffered flushable write; is that possible with boost::iostreams?
I found solution myself.
First of all, it is required to mark the device as flushable. Because there are not ready-made template for such device, you have to inherit device<dual_use, Ch> and override its category with multiple inheritance:
struct category : device<dual_use, Ch>::category, flushable_tag
Now when you will call flush on stream, it will forward the call to your device.
Next step is to disable stream own buffering (i. e. call open with 2nd and 3rd parameters equal to 0).
In such configuration boost will write to device each byte of data separatelly. However, you can implement buffering on device level, and flush the buffer on flush call.

Determining if a file exists on a network drive without a 20 second timeout

Is there an easy way to determine if a file on a remote system exists without a 20-25 second hang if it doesn't?
Functions like...
PathFileExists();
GetFileAttributes();
...don't allow you to set a timeout duration, so when the file doesn't exist you end up waiting for a long time. I think it might be possible to put one of these calls into a thread and set the thread to expire after 1 second (or whatever), but I'd prefer to use a lightweight native Windows function or boost function rather than an inelegant threading solution.
It's a bit hard to prove a negative, but I will argue that no such method exists.
The normal Windows asynchronous I/O method uses the OVERLAPPED structure, and in its documentation it references the ReadFile and WriteFile methods. From the other side, no variant of GetFileAttributes mentions OVERLAPPED or asynchronous I/O. Hence, it seems safe to assume it is always synchronous.
AFAIK no, generally there’s no easy way.
If your server is configured to responds to pings, you can use IcmpSendEcho API to ping the server before accessing it’s shared files, the API’s quite simple and it accepts the timeout.
If your server doesn’t respond to pings (by default modern versions of Windows don’t), you can write a function that tries to connect to TCP port 135 or 445, if connected closes the connection and returns success, if failed returns error. This will allow you to implement shorter timeout than the default.
In both methods, you’ll need to resolve the network drive path into the name of the server, see e.g. GetVolumePathName API.

Can epoll receive udp packet?

I am a newbie of network programming and I've hear about epoll. I read a couple of tutorials and now I got some basic idea of what epoll does and how I can implement this.
The question is that can I use epoll even if client will using udp connection? All the tutorials I read used tcp connection.
Also is there a good tutorials or a sample code that explains multi-thread based server implementation using epoll? Those tutorials I got from online only showed how to create a simple echo server on single thread.
Thanks in advance.
There is no problem to use epoll with UDP, the epoll just notifies if there is any data to read in the file descriptor. There are some implications in the read/write... operations related to the UDP socket behaviour (from the man page of epoll):
For stream-oriented files (e.g., pipe, FIFO, stream socket), the condition
that the read/write I/O space is exhausted can also be detected by
checking the amount of data read from / written to the target file
descriptor. For example, if you call read(2) by asking to read a certain
amount of data and read(2) returns a lower number of bytes, you can be
sure of having exhausted the read I/O space for the file descriptor. The
same is true when writing using write(2). (Avoid this latter technique if
you cannot guarantee that the monitored file descriptor always refers to a
stream-oriented file.)
On the other hand is not very usual to use the epoll directly. The best way of using epoll is using an event loop library, libev, or libevent, for example. This is a better aproach, beacause epoll is not available in every system and using this kind of libraries your programs are more portable.
Here you can found an example of libev use with UDP, and Here other example with libevent.

WinApi get number of available bytes from a USB port?

Is there a way to check the number of bytes available from a USB device (printer in our case)?
We're using CreateFile and ReadFile and WriteFile for IO communications with our USB device, which works. But We can't figure out how much data is available without actually doing a read. We can't use GetFileSize, as even the documentation says you can't use it for a :
"nonseeking device such as a pipe or a communications device"...
So that doesn't work. Any suggestions? Are we doing our USB I/O incorrectly? Is there a better way to Read/Write to USB?
You first need to open up the port in asynchronous mode. To do that, pass the flag FILE_FLAG_OVERLAPPED to CreateFile. Then, when you call ReadFile, pass in a pointer to an OVERLAPPED structure. This does an asynchronous read and immediately returns ERROR_IO_PENDING without blocking (or, if the OS already has the data buffered, you might get lucky and get a successful read -- be prepared to handle that case).
Once the asynchronous I/O has started, you can then periodically check if it has completed with GetOverlappedResult.
This allows you to answer the question "are X bytes of data available?" for a particular value of X (the one passed to ReadFile). 95% of the time, that's good enough, since you're looking for data in a particular format. The other 5% of the time, you'll need to add another layer of abstraction top, where you keep doing asynchronous reads and store the data in a buffer.
Note that asynchronous I/O is very tricky to get right, and there's a lot of edge cases to consider. Carefully read all of the documentation for these functions to make sure your code is correct.
Can you use C#? If so you can access the USB port using System.IO.SerialPort class, and then set up a DataReceived event handler for incoming data. There is a BytesToRead property that tells you how much data is waiting to be read.
All of this must be available in native code, if I can find it I'll edit this.
EDIT: the best I can find for native is ReadPrinter - I don't see how to check if data is there, this will block if it's not.

Sending the contents of a file to a client

I am writing a C++ server side application called quote of the day. I am using the winsock2 library. I want to send the contents of a file back to the client, including newlines by using the send function. The way i tried it doesn't work. How would i go about doing this?
Reading the file and writing to the socket are 2 distinct operations. Winsock does not have an API for sending a file directly.
As for reading the file, simply make sure you open it in read binary mode if using fopen, or simply use the CreateFile, and ReadFile Win32 API and it will be binary mode by default.
Usually you will read the file in chunks (for example 10KB at a time) and then send each of those chunks over the socket by using send or WSASend. Once you are done, you can close the socket.
On the receiving side, read whatever's available on the socket until the socket is closed. As you read data into a buffer, write the amount read to a file.
Hmm... I think Win32 should have something similar to "sendfile" in Linux.
If it doesn't you still can use memory-mapping (but, don't forgot to handle files with size larger than available virtual address space). You probably will need to use blocking sockets to avoid returning to application until all data is consumed. And I think there was something with "overlapped" operation to implement async IO.
I recommend dropping winsock and instead using something more modern such as Boost.Asio:
http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/tutorial.html
There is also an example on transmitting a file:
http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/examples.html