Figure 7: Client application model

UINT CMainFrame::MakeCallThread(PVOID pParam)
{
    CMainFrame* pMainFrame = (CMainFrame*)pParam;

    // instantiate Remote Connect object - request outbound/use
    // default I/O thread
    CRemoteConnect obj(CRemoteConnect::MAKECALL,TRUE);
    if (!obj.PortInitOk())
        return 1L;

    // put user interface algorithm here - do a simple loopback
    // as an example - start loopback by opening a file and
    // writing some text to output port
    ifstream infile("testfile.txt");
    if (!infile)
        return 1L;
    ofstream outfile("modemecho.txt");
    if (!outfile)
        return 1L;
    CByteArray inMsg;
    char outMsg[MAX_IO_BYTES+1];
    infile.read(outMsg,MAX_IO_BYTES);
    obj.putMessage(outMsg,infile.gcount());
    while (!infile.eof())
    {
        if (WaitForSingleObject(pMainFrame->m_exitThreadEvent,0)
              != WAIT_TIMEOUT)
            return 0L;  // file closes automatically
        // Block on read message up to 1sec
        if (obj.SyncRead(inMsg,1000))
            while (inMsg.GetSize())
            {
                BYTE inbyte = inMsg.GetAt(0);
                outfile << inbyte;
                inMsg.RemoveAt(0);
            }
        if (!infile.eof() && obj.txREADY())
        {
            infile.read(outMsg,MAX_IO_BYTES);
            obj.putMessage(outMsg,infile.gcount());
        }
    }
    // all done writing the file so while no terminate,
    // get the rest of it
    while (WaitForSingleObject(pMainFrame->m_exitThreadEvent,0)
               == WAIT_TIMEOUT)
        // Block on read message up to 1sec
        if (obj.SyncRead(inMsg,1000))
            while (inMsg.GetSize())
            {
                BYTE inbyte = inMsg.GetAt(0);
                outfile << inbyte;
                inMsg.RemoveAt(0);
            }
    return 0L;
}