OpenSSL 1.1.1d - Async use of SSL_CTX_set_cert_verify_callback? - c++

Certificate validation in general requires asynchronous operations such as: OCSP/CRL fetch.
On the other hand, the callback from SSL_CTX_set_cert_verify_callback expects a synchronous result:
1 (success) / 0 (failure). (reference).
I find it kind of odd that any validation of this type is expected to be synchronous.
Is there an alternative API for certificate chain validation that supports asynchronous operations?

In theory I think you should be able to use the OpenSSL ASYNC API to do this. Normally this is used by asynchronous capable engines, but I don't see why it wouldn't also work in applications.
Firstly you would need to put your SSL object into ASYNC mode using the function call SSL_set_mode() and specifying SSL_MODE_ASYNC. You can also do this at the SSL_CTX level using SSL_CTX_set_mode(). See:
https://www.openssl.org/docs/man1.1.1/man3/SSL_set_mode.html
Once that is done you need to ensure your application is prepared to handle the return value SSL_ERROR_WANT_ASYNC from any call to SSL_get_error(). See:
https://www.openssl.org/docs/man1.1.1/man3/SSL_get_error.html
Your application can then implement a callback in the normal way via SSL_CTX_set_cert_verify_callback. If it needs to temporarily pause operation to wait for some asynchronous operation to complete then the callback should call ASYNC_pause_job(). See:
https://www.openssl.org/docs/man1.1.1/man3/ASYNC_pause_job.html
This will have the effect of control returning to your main application and SSL_get_error() will return SSL_ERROR_WANT_ASYNC. You will need to implement some mechanism for your application to know when asynchronous processing is complete. When it is, then simply retry the SSL I/O call that was previously paused. Note: this must occur on the same thread that the original call was made from. Your callback will then resume from the point at which it previously paused.

Related

GRPC C++ Async Server How differentiate between WritesDone and broken connection

When developing an Async C++ GRPC Server, how can I differentiate between the client being done with writing and the connection being broken ?
I am Streaming data from the client to the server and once the client is done it will call WritesDone to let the server know it should finish storing the file. If I have a sync server I can differentiate between the client calling WritesDone and the connection being broken by calling context->IsCancelled() but in async mode you can not call IsCancelled until you get the tag specified in AsyncNotifyWhenDone.
In both cases (WritesDone and Call done) the Read tag gets returned with ok set to false. However, the AsyncNotifyWhenDone tag, which would allow me to differentiate arrives after the read tag.
I will know after I try to call finish (it will also return false) but I need to know before I call finish as my final processing might fail and I can't return the error anymore if I already called finish.
There's no way to distinguish until the AsyncNotifyWhenDone tag returns. It may come after the Read in which case you may need to buffer it up. In the sync API you can check IsCancelled() anytime (and you can also do that in the Callback API which should be available for general use soon).

about C++ rest sdk and synchronous calls

I have started working with 'cpp rest sdk'. The key point I understood it that all requests and response are asynchronous using the means of PPL. This is fine to boost scalability and performance of the application.
The question I have is weather is any way to request and wait for a response in a 'synchronous' fashion.
I found the following web page which seems to work fine and it claims to make call in synchronous way. Is it so?
Does a call to task::get() guarantees that the function returns when the response is ready to be read?
The major idea of asynchronous programming is to chain all parts you want to have executed sequentially. If you want the program to wait until the sequence is finished, you can end the chain with .wait()
client.request(web::http::methods::GET, U("/foo.html"))
.then(/*some lambda*/)
.then(/*some lambda*/) //and so on
.wait(); //stop here until the chain is executed
Similarly, you can also use get() which also calls wait() but further returns the result of the task.

Does SendAsyncCancel cancel SendMailAsync?

In the SmtpClient class, does SendAsyncCancel cancel the SendMailAsync method?
I see a few code examples on the www which imply it does.
However MSDN says,
Use the SendAsyncCancel method to cancel a pending SendAsync operation. If there is mail waiting to be sent, this method releases resources used to store the mail. If there is no mail waiting to be sent, this method does nothing.
... which implies that it cancels SendAsync but not SendMailAsync.
Is there a way to cancel SendMailAsync? If not, why not?
If you want to cancel an asynchronous send (therefore use the old SendAsync instead of the newer SendMailAsync), what are any other disadvantages of using SendAsync instead of SendMailAsync?
I tried to invoke SendMailAsync from a post-back handler of an ASP web page, and it threw an exception:
System.InvalidOperationException: Asynchronous operations are not allowed in this context. Page starting an asynchronous operation has to have the Async attribute set to true and an asynchronous operation can only be started on a page prior to PreRenderComplete event.
at System.Web.LegacyAspNetSynchronizationContext.OperationStarted()
at System.ComponentModel.AsyncOperation.CreateOperation(Object userSuppliedState, SynchronizationContext syncContext)
at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken)
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken)
at System.Net.Mail.SmtpClient.SendMailAsync(MailMessage message)
at MyWebSite.AdminTest.TestEmail.<sendAsynchronous>d__9.MoveNext()
From this I deduce two things:
SendMailAsync is indeed implemented using SendAsync (you can see it on the call-stack of the exception). SendAsyncCancel therefore will presumably work for SendMailAsync too.
You can't call SendMailAsync from an ASP unless you want to deal with the "Asynchronous operations are not allowed in this context" problem. That's discussed here and looks like it might be messy. Whereas I guess that calling SendAsync probably doesn't have this problem (because I'm using HttpClient.SendAsync and ContinueWith elsewhere, with a CountdownEvent.Wait at the end to wait for the operation to complete, without seeing this exception being thrown).
SendMailAsync can be used when it's invoked via HostingEnvironment.QueueBackgroundWorkItem.

What IO operations causes completion packets to be sent to the completion port when using sockets?

In IOCP, when starting an IO operation such as WSARecv(), a completion packet will be sent to the completion port when the IO operation completes.
What I want to know is what IO operations causes completion packets to be sent to the completion port when using sockets, for example, I know that WSASend(), WSARecv(), AcceptEx(), and PostQueuedCompletionStatus() causes completion packets to be sent. Is there other IO operations that does that?
A completion will be queued to the IOCP associated with a socket only if an API call that can generate completions is called in a way that requests a completion to be queued. So you will know which API calls can generate completions by the fact that you've read the documentation and you're passing an OVERLAPPED structure to them.
Thus you don't really need to know the answer to your question as you will never get a completion that you do not expect to get as you have to have called an appropriate API with appropriate parameters for a completion to be generated.
You can then differentiate between the API that caused the completion to be generated by adding some form of identifying "per operation data" to the OVERLAPPED either by making an 'extended overlapped stucture' or by using the event handle as opaque data. Either way you get a chance to send some context from the API call site to the IOCP completion handling site. This context is of your own design and can tell you what initiated the completion.
Then you get to use the return value from the GetQueuedCompletionStatus() call to determine if the completion is a success or failure and you can then access the error code for failures using WSAGetLastError() (though see this answer for more detail on an additional hoop that you could jump through to get more accurate error codes).
This then lets you determine which of the events listed in EJP's answer you have.
The actual set of functions that can generate a completion for socket operations can change with changes in the OS. The easiest way to determine what these are for the operating system that you're targeting is to either read the MSDN docs or do a search of the SDK headers for lpOverlapped... As you'll see from the current VS2013 headers there are quite a few that relate to sockets; AcceptEx(), ConnectEx(), DisconnectEx(), TransmitFile(), the HTTP.sys API, the RIO API, etc.
You're missing the point. What causes completion packets to be sent is events, not API calls. There are basically only a few TCP events:
inbound connection
outbound connection complete
data
write finished
timeout
end of stream, and
error.
Copied from the site
Supported I/O Functions
The following functions can be used to start I/O operations that complete by using I/O completion ports. You must pass the function an instance of the OVERLAPPED structure and a file handle previously associated with an I/O completion port (by a call to CreateIoCompletionPort) to enable the I/O
completion port mechanism:
ConnectNamedPipe
DeviceIoControl
LockFileEx
ReadDirectoryChangesW
ReadFile
TransactNamedPipe
WaitCommEvent
WriteFile
WSASendMsg
WSASendTo
WSASend
WSARecvFrom
WSARecvMsg
WSARecv

C++ Cross Platform Timeout reads

I am implementing a test server for bots competing in an AI competition, the bots communicate with the server via standard input/output. The bots only have so long for their turns. In a previous AI competition I wrote the server in Java and handled this by using BlockingQueue and threads on the blocking reads/write to the process streams.
For this competition looking to use C++. I found Boost.Process and Boost.Asio but as far as I can tell, Asio library doesn't have a way to timeout on how long to wait for a read. It has been designed around using callback functions to tell you when the read has completed. Whereas I want to block but with a maximum timeout. I could do this with platform specific API like select but looking for more cross platform solution. Any suggestions?
EDIT: To clarify I want a class BotConnection that deals with communicating with the bot process that has two methods eg: string readLine(long timeoutInMilliseconds) and void writeLine(string line, long timeoutInMilliseconds) . So the calling code is written like it is using a blocking call but can timeout (throwing an exception or change the method signatures above so a successful flag is returned on if the operation completed or timedout)
You can create timer objects that track the timeout. A typical approach is to create a regular timer with an async handler. Each time it fires you iterate over your connection objects looking for those which have not transmitted any data. In your connection read handlers you flag the object as having received data. In rough pseudo-code:
timer_handler:
for cnx in connections:
if cnx.recv_count > 0:
cnx.recv_count = 0
cnx.idle_count = 0
continue
cnx.idle_count += 1
if cnx.idle_count > idle_limit:
cnx.close()
cnx_read_handler:
cnx.recv_count += 1
Note: I've not used asio, but I did check and timer's do appear to be provided.
There is no portable way to read and write to standard input and output with a timeout.
Boost.Asio provides posix::stream_descriptor to synchronously and asynchronously read and write to POSIX file descriptors, such as standard input and output, as demonstrated in the posix chat client example. While Boost.Asio does not provide support for cancelling synchronous operations, most asynchronous operations can be cancelled in a portable way. Asynchronous operations combined with Boost.Asio Timers allow for timeouts: an asynchronous operation is initiated on an entity, a timer is set and if the timer expires then cancel() is invoked on the entity. See the Boost.Asio timeout examples for more details.
Windows standard handles do not support asynchronous I/O via completion ports. Hence, Boost.Asio's windows::stream_handle's documentation notes that named pipes are supported, but anonymous pipes and console streams are not. There are a few unanswered questions, such as this one, about asynchronous I/O support for standard input and output handles. With the lack of asynchronous support, additional threads and buffering may be required to abstract the platform specific behavior from the application.