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?