Writing a Callback
As you write the callback functions, keep the required function signatures in mind. You can add additional parameters as callee data as described in Chapter 8, “The Functor Package,” in the Threads Module User’s Guide.
NOTE: Rogue Wave does not provide technical support for writing callbacks. The functions in the HTTPS package that set the callback are provided for convenience only.
To use your callback, you will:
1. Create an appropriate functor that wraps your function and passes in any necessary data. For example, you could pass in a handle to your windowing system to pop up a message box from the callback.
2. Call either RWHttpsSecurityManager::setNameCheckCallback() or RWHttpsSecurityManager::setNameMismatchCallback() and pass your functor as the argument.
NOTE: A certificate name check callback must return true if the name in the server’s certificate is the same as the name of the host, and false if the names are different.
This example uses utility functions provided in "args.h".
Example 12 – Supplying a Callback
// File: examples/https/manual/CallbackExample.cpp
#include <rw/itc/RWTIOUResult.h>
#include <rw/internet/RWURL.h>
#include <rw/network/RWWinSockInfo.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/http/RWHttpAgent.h>
#include <rw/http/RWHttpReply.h>
#include <rw/https/RWHttpsSecurityManager.h>
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include "args.h"
// This data is used to seed the RNG
const unsigned char seed[] = "123456789012345678901234567890"
"123456789012345678901234567890"
"123456789012345678901234567890"
"123456789012345678901234567890"
"123456789012345678901234567890";
bool
myCertificateNameCheckCallback(RWCString /* host */,
RWX509Certificate /* cert */)
{
cout << "My Certificate Name Check Function called!" << endl;
// This function should return true if the names match and False
// if they don't.
// We return false every time to ensure the Name Mismatch Callback
// gets called. (Example purposes only. Don't do this!)
return false;
}
void
myCertificateNameMismatchCallback(RWCString /* host */,
RWX509Certificate /* cert */)
{
cout << "My Certificate Name Mismatch Function called!" << endl;
}
int main(int argc, char** argv)
{
RWWinSockInfo info;
RWSecureSocketPackageInit secsockInit;
// Seed the RNG. Seeding from a const string is not
// secure and not recommended for a real-world
// application, however for the purposes of this
// example is sufficient.
RWSecureSocketPackageInit::seedRNGFromMemory(seed, sizeof(seed));
RWTValSlist<RWCString> args = processArgs(argc, argv);
if (args.entries() < 1) {
cout << "Usage: " << argv[0] << " <url>" << endl;
return 1;
}
RWURL url(args[0]);
RWSecureSocketContext context;
// In a secure application, some level of authentication is
// usually performed to verify either the server or client
// matches the host we connected to. For simplicity in this
// example, we will ignore this step.
//
// context.prepareToAuthenticate("<certificate file>");
RWHttpsSecurityManager::setAgentContext(context);
RWHttpsSecurityManager::setNameCheckCallback
(myCertificateNameCheckCallback); //1
RWHttpsSecurityManager::setNameMismatchCallback
(myCertificateNameMismatchCallback); //2
RWHttpAgent agent;
RWTIOUResult<RWHttpReply> replyIOU;
try {
replyIOU = agent.executeGet(url);
RWHttpReply reply = replyIOU.redeem();
cout << reply.asString() << endl;
if (reply.is2XX()) {
cout << reply.getBody() << endl;
}
}
catch (const RWxmsg& msg) {
cerr << "An unexpected exception occurred: "
<< msg.why() << endl;
return 1;
}
#if defined(RW_THR_MUST_CALL_SHUTDOWN)
// On some platforms and buildtypes, all of the threads
// in the system must have finished executing before
// the main thread exits. This call ensures that all
// threads have completed their execution before
// continuing.
RWThreadManager::instance().shutdown();
#endif
return 0;
}