TPIFileTest.c

/*
    File:       TPIFileTest.c
 
    Contains:   A trivial test program for the TPIFile module.
 
    Written by: Quinn "The Eskimo!"
 
    Copyright:  © 1997 by Apple Computer, Inc., all rights reserved.
 
    Change History (most recent first):
 
    You may incorporate this sample code into your applications without
    restriction, though the sample code has been provided "AS IS" and the
    responsibility for its operation is 100% yours.  However, what you are
    not permitted to do is to redistribute the source as "DSC Sample Code"
    after having made changes. If you're going to re-distribute the source,
    we require that you make it clear in the source that the code was
    descended from Apple Sample Code, but that you've made changes.
*/
 
/////////////////////////////////////////////////////////////////////
// Pick up all the OT client info, specifically the OTRegisterPort.
 
#include <OpenTransport.h>
#include <Events.h>
 
/////////////////////////////////////////////////////////////////////
// OK, so it's yet another console based sample from Quinn!
 
#include <stdio.h>
#include <limits.h>
 
/////////////////////////////////////////////////////////////////////
// Pick up the name of the TPIFile port.
 
#include "TPIFile.h"
 
/////////////////////////////////////////////////////////////////////
 
// Define a global buffer to hold the data we're reading out of the file.
// 
// Note the number of bytes that we read out of the endpoint in a single
// hit is not the same chunk size as used by the TPIFile module to read
// the file (which is 2KB).  This is a deliberate test of the way OT
// endpoint libraries do deblocking.
 
enum {
    kBufferSize = 1000
};
 
static char gBuffer[kBufferSize];
 
/////////////////////////////////////////////////////////////////////
 
static OSStatus TestTPIFile(ConstFSSpecPtr fss, UInt32 byteCount, Boolean disconnect)
    // Test the TPIFile module by opening an endpoint to the
    // file specified by fss and printing the contents to
    // the console window.
{
    OSStatus err;
    EndpointRef ep;
    TCall sndCall;
    FileSpecAddress connectAddr;
    OTFlags junkFlags;
    long i;
    
    // Open the endpoint to our module.
    
    ep = OTOpenEndpoint(OTCreateConfiguration(kTPIFilePortName), 0, nil, &err);
    
    // Switch to sync/blocking mode to simplify our code and then
    // do a null bind in preparation for the connect.
    if (err == noErr) {
        (void) OTSetBlocking(ep);
        (void) OTSetSynchronous(ep);
        err = OTBind(ep, nil, nil);
    }
    
    // Connect to a file specified by an AF_FILESPEC address format.
    if (err == noErr) {
        connectAddr.fAddressType = AF_FILESPEC;
        connectAddr.fss = *fss;
        sndCall.addr.buf = (UInt8 *) &connectAddr;
        sndCall.addr.len = sizeof(connectAddr);
        sndCall.opt.buf = nil;
        sndCall.opt.len = 0;
        sndCall.udata.buf = nil;
        sndCall.udata.len = 0;
        sndCall.sequence = 0;
        err = OTConnect(ep, &sndCall, nil);
    }
    
    // A standard OTRcv and print loop.
    if (err == noErr) {
        do {
            err = OTRcv(ep, gBuffer, kBufferSize, &junkFlags);
            if (err > noErr) {
                for (i = 0; i < err; i++) {
                    if (byteCount == 0) {
                        err = noErr;
                        goto premature_close;
                    }
                    byteCount -= 1;
                    if (gBuffer[i] == 13) {
                        putchar(10);
                    } else {
                        putchar(gBuffer[i]);
                    }
                }
                fflush(stdout);
                err = noErr;
            }
        } while (err == noErr);
    }
 
premature_close:
    if (err == noErr && disconnect) {
        err = OTSndDisconnect(ep, nil);
    }
 
    // When we can't read any more data, consult and print the reason.  
    if (err == kOTLookErr) {
        printf("Got kOTLookErr.\n");
        err = OTLook(ep);
        switch (err) {
            case T_DISCONNECT:
                printf("T_DISCONNECT\n");
                break;
            default:
                printf("Unknown look %d\n", err);
        }
        err = kOTLookErr;
    }
    
    if (ep != kOTInvalidEndpointRef) {
        (void) OTCloseProvider(ep);
    }
    return (err);
}
 
/////////////////////////////////////////////////////////////////////
 
static OSStatus TestBogusConnect(void)
    // Test how well the TPI module handles being asked to connect
    // to a bogus FSSpec.
{
    OSStatus err;
    FSSpec bogusFileSpec;
    
    (void) FSMakeFSSpec(0, 0, "\pBogus Victim", &bogusFileSpec);
    
    err = TestTPIFile(&bogusFileSpec, 1024, false);
    
    return (err);
}
 
/////////////////////////////////////////////////////////////////////
 
static OSStatus TestConnectAsync(ConstFSSpecPtr fss, Boolean disconnect)
    // Test an asynchronous connect operation followed immediately
    // by a disconnect.
{
    OSStatus err;
    EndpointRef ep;
    TCall sndCall;
    FileSpecAddress connectAddr;
        
    ep = OTOpenEndpoint(OTCreateConfiguration(kTPIFilePortName), 0, nil, &err);
    
    // Switch to sync/blocking mode to simplify our code and then
    // do a null bind in preparation for the connect.
    if (err == noErr) {
        (void) OTSetBlocking(ep);
        (void) OTSetSynchronous(ep);
        err = OTBind(ep, nil, nil);
    }
    
    // Connect to a file specified by an AF_FILESPEC address format.
    if (err == noErr) {
        (void) OTSetAsynchronous(ep);
        connectAddr.fAddressType = AF_FILESPEC;
        connectAddr.fss = *fss;
        sndCall.addr.buf = (UInt8 *) &connectAddr;
        sndCall.addr.len = sizeof(connectAddr);
        sndCall.opt.buf = nil;
        sndCall.opt.len = 0;
        sndCall.udata.buf = nil;
        sndCall.udata.len = 0;
        sndCall.sequence = 0;
        err = OTConnect(ep, &sndCall, nil);
        if (err == kOTNoDataErr) {
            err = noErr;
            printf("Connecting\n");
        }
    }
    if ( (err == noErr) && disconnect) {
        err = OTSndDisconnect(ep, nil);
        if (err == noErr) {
            printf("Waiting for disconnect");
            while ( OTGetEndpointState(ep) != T_IDLE ) {
                if ( TickCount() % 10 == 0 ) {
                    printf(".");
                }
            }
            printf("\n");
        }
    }
 
    if (ep != kOTInvalidEndpointRef) {
        (void) OTCloseProvider(ep);
    }
    
    return (err);
}
 
/////////////////////////////////////////////////////////////////////
 
static OSStatus TestConnectAsyncWithExtraEndpoint(ConstFSSpecPtr fss, Boolean disconnect)
{
    OSStatus err;
    EndpointRef ep;
    char junkStr[256];
    
    ep = OTOpenEndpoint(OTCreateConfiguration(kTPIFilePortName), 0, nil, &err);
    if (err == noErr) {
        err = TestConnectAsync(fss, disconnect);
    }
    if (err == noErr) {
        printf("Press return to continue.\n");
        gets(junkStr);
    }
    
    return (err);
}
 
 
/////////////////////////////////////////////////////////////////////
 
void main(void)
{
    OSStatus err;
    FSSpec fileToTest;
    char commandStr[256];
    
    printf("Hello Cruel World!\n");
    fflush(stdout);
    
    err = InitOpenTransport();
    
    if (err == noErr) {
    
        // Hardwire this code to read a file called "Victim" in the
        // same folder as the application.
        
        err = FSMakeFSSpec(0, 0, "\pVictim", &fileToTest);
 
        if (err == noErr) {
            printf("a) Read and print all.\n");
            printf("b) Read and print with premature close.\n");
            printf("c) Read and print with premature disconnect.\n");
            printf("d) Connect to a bogus file.\n");
            printf("e) Connect async then fast close.\n");
            printf("f) Connect async then fast disconnect.\n");
            printf("g) Connect async then fast close with extra endpoint.\n");
            printf("Enter the test you want to perform:\n");
            gets(commandStr);
            
            switch (commandStr[0]) {
                case 'a':
                    err = TestTPIFile(&fileToTest, ULONG_MAX, false);
                    break;
                case 'b':
                    err = TestTPIFile(&fileToTest, 1024, false);
                    break;
                case 'c':
                    err = TestTPIFile(&fileToTest, 1024, true);
                    break;
                case 'd':
                    err = TestBogusConnect();
                    break;
                case 'e':
                    err = TestConnectAsync(&fileToTest, false);
                    break;
                case 'f':
                    err = TestConnectAsync(&fileToTest, true);
                    break;
                case 'g':
                    err = TestConnectAsyncWithExtraEndpoint(&fileToTest, false);
                    break;
                default:
                    printf("Huh?\n");
                    err = -1;
                    break;
            }
        }
        
        CloseOpenTransport();
    }
    
    if (err == noErr) {
        printf("Success.\n");
    } else {
        printf("Failed with error %d.\n", err);
    }
    printf("Done.  Press command-Q to Quit.\n");
}