/*++ Copyright (c) 1994-1997 Microsoft Corporation Module Name: simplex.c Abstract: Simple single-threaded DLC test/example program. Need 2 instances of this app - 1 to send and 1 to receive (i.e. the typical DLC situation hence simplex, or half-duplex in old money). By default, both sides use SAP 4 Receiver is started: simplex Transmitter is started e.g. simplex /t02608c4c970e in this example the node address is in canonical form (ethernet format) as displayed by "net config wksta", e.g., not the non-canonical (token-ring format) that the DLC API expects. If this test app is being run over token ring then you would supply the non-canonical address, as used by token ring, e.g. simplex /t10005a7b08b4 Command line options are: /a# - use adapter # /b# - change the buffer pool size from the default 20K to # /o - options: /or# - set receive READ option /ot# - set transmit READ option /r# - send to remote SAP # (transmitter only) /s# - open local SAP # /t# - send to station address # (transmitter only) /z# - transmit packets of size #, else send random sized packets (transmitter only) Contents: main usage get_funky_number is_radical_digit char_to_number handle_ctrl_c terminate xtou open_adapter adapter_status close_adapter create_buffer open_sap open_station connect_station flow_control get_buffer free_buffer post_receive post_read tx_i_frame slush do_transmit do_receive check_keyboard dispatch_read_events handle_status_change handle_receive_data handle_transmit_complete handle_command_complete twiddle_bits swap_bits my_malloc my_calloc my_free nice_num Author: Richard L Firth (rfirth) 6-Mar-1994 Environment: Win32 app (console) Revision History: John Lee (johnlee) 22-Feb-1996 --*/ #include #include #include #include #include #include #undef tolower #include #include #include "dlcdebug.h" #ifndef _CRTAPI1 #define _CRTAPI1 #endif #define SIMPLEX_VERSION "1.11" #define RECEIVE_MODE 0 #define TRANSMIT_MODE 1 #define DLCBUFSIZE 20000 #define SAP_NUMBER 4 #define RECEIVE_COMPLETE_FLAG 0x50204030 #define RECEIVE_DATA_FLAG 0x50204040 #define TRANSMIT_COMPLETE_FLAG 0x50404030 #define TX_STATE_OPENING 1 #define TX_STATE_OPENED 2 #define TX_STATE_TRANSMITTING 3 #define TX_STATE_BUSY 4 #define RX_STATE_LISTENING 1 #define RX_STATE_RECEIVING 2 #define RX_STATE_BLOCKED 3 #define MAX_OUTSTANDING_TRANSMIT_THRESHOLD 100 #define MIN_OUTSTANDING_TRANSMIT_THRESHOLD 10 #define IS_ARG(c) (((c) == '-') || ((c) == '/')) #define ZAP(thing) memset(&thing, 0, sizeof(thing)) #define MALLOC my_malloc #define CALLOC my_calloc #define FREE my_free typedef struct { DWORD sequence; DWORD size; DWORD signature; DWORD checksum; char data[]; } TEST_PACKET, *PTEST_PACKET; void _CRTAPI1 main(int, char**); void usage(void); DWORD get_funky_number(char**); BOOL is_radical_digit(char, DWORD); DWORD char_to_number(char); void _CRTAPI1 handle_ctrl_c(int); void terminate(int); unsigned char xtou(char); void open_adapter(void); unsigned short adapter_status(void); void close_adapter(void); void create_buffer(int); void open_sap(int); void open_station(void); void connect_station(unsigned short); void flow_control(int); PLLC_BUFFER get_buffer(void); int free_buffer(PLLC_BUFFER); void post_receive(void); PLLC_CCB post_read(void); void tx_i_frame(void); DWORD slush(char*, int); void do_transmit(void); void do_receive(void); void check_keyboard(void); void dispatch_read_events(PLLC_CCB); void handle_status_change(PLLC_CCB); void handle_receive_data(PLLC_CCB); void handle_transmit_complete(PLLC_CCB); void handle_command_complete(PLLC_CCB); void twiddle_bits(LPBYTE, DWORD); unsigned char swap_bits(unsigned char); void* my_malloc(int); void* my_calloc(int, int); void my_free(void*); char* nice_num(unsigned long); BYTE Adapter = 0; DWORD BufferPoolSize = DLCBUFSIZE; BYTE RemoteNode[6]; WORD LocalSap = SAP_NUMBER; WORD RemoteSap = SAP_NUMBER; DWORD Mode = RECEIVE_MODE; BOOL SwapAddressBits = 0; HANDLE TheMainEvent; DWORD MaxFrameSize; DWORD TransmitDataLength = 0; LPBYTE BufferPool; HANDLE BufferHandle; USHORT StationId; DWORD RxState = 0; DWORD TxState = 0; DWORD LocalBusy = 0; DWORD RemoteBusy = 0; DWORD Verbose = 0; DWORD JustBufferInfo = 0; LONG AllocatedBytesOutstanding = 0; DWORD TotalBytesAllocated = 0; DWORD TotalBytesFreed = 0; LONG OutstandingTransmits = 0; DWORD DisplayBufferFreeInfo = 1; DWORD DisplayFrameReceivedInfo = 1; DWORD DisplayTransmitInfo = 0; DWORD DisplayCcb = 1; DWORD TotalTransmits = 0; DWORD TotalTransmitCompletions = 0; DWORD TransmitCompleteEvents = 0; DWORD CommandCompleteEvents = 0; DWORD StatusChangeEvents = 0; DWORD ReceiveDataEvents = 0; DWORD DataFramesReceived = 0; DWORD DlcBuffersReceived = 0; DWORD DlcBuffersFreed = 0; DWORD TotalBytesTransmitted = 0; DWORD TotalTxBytesCompleted = 0; DWORD TotalPacketBytesReceived = 0; DWORD TotalDlcBytesReceived = 0; DWORD TotalReadsChecked = 0; DWORD TotalReadEvents = 0; DWORD MaxChainedReceives = 0; DWORD MaxChainedTransmits = 0; DWORD MinBuffersAvailable = 0; DWORD MaxBuffersAvailable = 0; DWORD LinkLostEvents = 0; DWORD DiscEvents = 0; DWORD FrmrReceivedEvents = 0; DWORD FrmrSentEvents = 0; DWORD SabmeResetEvents = 0; DWORD SabmeOpenEvents = 0; DWORD RemoteBusyEnteredEvents = 0; DWORD RemoteBusyLeftEvents = 0; DWORD TiExpiredEvents = 0; DWORD DlcCounterOverflowEvents = 0; DWORD AccessPriorityLoweredEvents = 0; DWORD InvalidStatusChangeEvents = 0; DWORD LocalBusyEvents = 0; BYTE OptionChainReceiveData = 1; BYTE OptionChainTransmits = 0; // The application ID is used on Windows 95, but not on Windows NT. BYTE bApplId = 0; void _CRTAPI1 main(int argc, char** argv) { printf("\nDLC simplex test. Version " SIMPLEX_VERSION " " __DATE__ " " __TIME__ "\n\n"); for (--argc, ++argv; argc; --argc, ++argv) { if (IS_ARG(**argv)) { switch (tolower(*++*argv)) { case 'a': Adapter = atoi(++*argv); break; case 'b': ++*argv; BufferPoolSize = get_funky_number(argv); break; case 'h': case '?': usage(); case 'o': ++*argv; while (**argv) { switch (tolower(**argv)) { case 'r': ++*argv; OptionChainReceiveData = (BYTE)get_funky_number(argv); break; case 't': ++*argv; OptionChainTransmits = (BYTE)get_funky_number(argv); break; default: printf("error: unrecognized option '%c'\n", **argv); usage(); } } case 'r': ++*argv; RemoteSap = (WORD)get_funky_number(argv); break; case 's': ++*argv; LocalSap = (WORD)get_funky_number(argv); break; case 't': { int i; LPSTR p = ++*argv; Mode = TRANSMIT_MODE; if (strlen(p) != 12) { printf("incorrect remote node format (12 hex digits required)\n"); usage(); } for (i = 0; i < 6; ++i) { RemoteNode[i] = (xtou(*p++) << 4) + xtou(*p++); } break; } case 'v': Verbose = 1; break; case 'z': ++*argv; TransmitDataLength = get_funky_number(argv); break; } } } if ((TheMainEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { printf("CreateEvent returns %d\n", GetLastError()); exit(1); } printf("Running in %s mode.\n\n", (Mode == TRANSMIT_MODE) ? "Transmit" : "Receive" ); if (Mode == TRANSMIT_MODE) { printf("remote node = %02x-%02x-%02x-%02x-%02x-%02x\n", RemoteNode[0] & 0xff, RemoteNode[1] & 0xff, RemoteNode[2] & 0xff, RemoteNode[3] & 0xff, RemoteNode[4] & 0xff, RemoteNode[5] & 0xff ); DisplayTransmitInfo = 1; } open_adapter(); MaxFrameSize = min((1500 - (14 + 4)), MaxFrameSize); if (TransmitDataLength && (TransmitDataLength > MaxFrameSize)) { TransmitDataLength = MaxFrameSize; } printf("opened adapter %d. maximum frame size = %d\n", Adapter, MaxFrameSize); switch (adapter_status()) { case 0: printf("type of adapter %d is token ring: not flipping hamburgers (nor address bits)\n", Adapter); SwapAddressBits = 0; break; case 1: printf("type of adapter %d is ethernet: will flip address bits\n", Adapter); SwapAddressBits = 1; break; case 2: printf("type of adapter %d is PC/Network card: don't know how to handle\n", Adapter); terminate(1); case 3: printf("adapter %d is >> UNKNOWN <<. Will assume FDDI and flip bits.\n" "If not correct, please fix\n", Adapter); printf("hit a key to continue... "); getch(); putchar('\n'); break; } create_buffer(BufferPoolSize); MinBuffersAvailable = free_buffer(get_buffer()); printf("created %d byte buffer pool @%x. Handle = %x. Initial buffers = %d\n", BufferPoolSize, BufferPool, BufferHandle, MinBuffersAvailable); open_sap(LocalSap); if (Verbose) { printf("opened SAP %d: StationId = %04x\n", LocalSap, StationId); } signal(SIGINT, handle_ctrl_c); if (Mode == TRANSMIT_MODE) { if (SwapAddressBits) { twiddle_bits(RemoteNode, 6); } do_transmit(); } else { do_receive(); } terminate(0); } void usage() { printf("usage: simplex [/a#] [/b#] [/h] [/o