Running as a Server
This example shows a server performing the following:
creating a server session container
accuring a server service
listening to configured ports
accepting new session
accepting and processing requests
sending responses
Example
int
ServerReceiveAndSend(std::shared_ptr<medcrypt::guardian::Guardian> my_guardian)
{
medcrypt::guardian::Status status = 0;
/* Create server session container */
std::list<SessionGroup> sessions;
/* Acquire Service */
std::unique_ptr<medcrypt::guardian::Service> my_service;
status = guardian.FindService("MyServerService", &my_service);
if( status || !service )
{
/* Did not find server service 'MyServerService' */
return RETURNCODE_FAILED;
}
/* Start Listening */
status = my_service->Listen();
if (status) {
/* error listening to configured ports */
return RETURNCODE_FAILED;
}
/* Main Loop : accept session (new connection), accept request, process, send response, clear stale/closed sessions */
std::string rxdata;
std::string txdata;
std::unique_ptr<medcrypt::guardian::ChannelGuard> my_channel;
while (true)
{
rxdata.clear();
txdata.clear();
/* run guardian background tasks on a regular basis */
status = guardian.Run();
if( status ) {
/* error running Guardian */
return RETURNCODE_FAILED;
}
/* accept waiting session from client if available */
if( service->ClientWaiting() ) {
std::unique_ptr<medcrypt::guardian::Session> my_session;
/* actually accept the connection by Starting a new session */
service->Start(&my_session);
if( my_session ) {
sessions.push_back(SessionGroup());
sessions.back().session = std::move(my_session);
sessions.back().failed_read_count = 0;
}
}
/* process all sessions */
std::unique_ptr<medcrypt::guardian::ChannelGuard> my_channel;
auto my_session = sessions.begin();
for( ; my_session != sessions.end(); my_session++ ) {
/* find the appropriate channel under this session for the data we are processing
(defined in certified profile) */
status = my_session->session->FindChannel("MyDataChannel", &my_channel);
if( status || !my_channel ) {
/* no channel 'MyDataChannel' */
/* remove session and continue */
my_session->session->Shutdown();
my_session->session.reset();
continue;
}
/* get any waiting data, respond if available */
/* NOTE: with safe-open turned on in the profile, data whose signature fails to verify would not be returned */
size_t rxsize = PAYLOAD_SIZE_IN_BYTES;
rxdata = std::string(PAYLOAD_SIZE_IN_BYTES, '\1');
status = my_channel->AsyncDataFromChannel(&rxdata[0], &rxsize);
rxdata.resize(rxsize);
/* keep track of read failures, close the session if there are too many */
if( medcrypt::guardian::GuardianStatusEnum::AGAIN == EXTRACT_STATUS(status) ) {
my_session->failed_read_count++;
}
else if (medcrypt::guardian::GuardianStatusEnum::OK != EXTRACT_STATUS(status) &&
medcrypt::guardian::GuardianStatusEnum::VERIFYFAIL != EXTRACT_STATUS(status)) {
/* DataFromChannel error */
/* remove session and continue */
my_session->session->Shutdown();
my_session->session.reset();
continue;
}
else {
/* process the incoming data and formulate response */
my_session->failed_read_count = 0;
if (medcrypt::guardian::GuardianStatusEnum::VERIFYFAIL == EXTRACT_STATUS(status)) {
/* process untrusted data */
} else {
/* process trusted data */
}
/* send the data */
status = channel->DataForChannel(txdata.c_str(), txdata.size());
if (medcrypt::guardian::GuardianStatusEnum::OK != EXTRACT_STATUS(status)) {
/* DataForChannel error */
/* remove session and continue */
my_session->session->Shutdown();
my_session->session.reset();
continue;
}
}
}
/* remove any dead sessions from list */
my_session = sessions.begin();
while( my_session != sessions.end() ) {
auto rm = my_session;
my_session++;
if( !rm->session ||
rm->failed_read_count > SERVER_CLOSE_DELAY ) {
sessions.erase(rm);
}
}
}
my_service->Shutdown();
my_guardian->Shutdown();
return 0;
}
Last updated
Was this helpful?