mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2410 lines
49 KiB
2410 lines
49 KiB
/*++
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
|
|
A PARTICULAR PURPOSE.
|
|
|
|
Copyright (c) 1994 Microsoft Corporation. All Rights Reserved.
|
|
|
|
Module Name:
|
|
|
|
pit.c
|
|
|
|
Abstract:
|
|
|
|
Command line interpreter for the Portable Interoperability Tester.
|
|
|
|
Revision History:
|
|
|
|
Version When What
|
|
-------- -------- ----------------------------------------------
|
|
0.1 04-13-94 Created.
|
|
1.0 01-31-95 All '94 bakeoff changes plus some cleanup.
|
|
|
|
Notes:
|
|
|
|
This interpreter reads from the standard input and writes to the
|
|
standard output. Platform-specific code is #ifdef'd.
|
|
|
|
The command interpreter is fairly modular. The top level interpreter
|
|
gets the next command and dispatches it for execution. The interface
|
|
to all command procedures is the same. Each takes a command buffer, which
|
|
fully describes the command, and a boolean which indicates whether the
|
|
command is new or a replay. The command buffer, whuich is empty for new
|
|
commands, is filled in as the command gathers its input. If the command
|
|
completes successfully and it is a replayable command, the command buffer
|
|
is saved in the history list. Command procedures replay commands directly
|
|
from the command buffer when requested. Each command procedure calls out
|
|
to utility functions to gather its input and to system-specific transport
|
|
functions to perform network operations. Higher-level test procedures
|
|
(ie a datagram ping-pong test) are built using the basic commands and
|
|
also conform to the command procedure interface.
|
|
|
|
To add a new command or test, define a new command code, clone an
|
|
existing command procedure, and insert a new case into the dispatch
|
|
routine.
|
|
|
|
--*/
|
|
|
|
#include <pit.h>
|
|
|
|
#define PIT_VERSION "1.0"
|
|
|
|
/*
|
|
* Platform-specific defines
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
|
|
#define EOL '\n'
|
|
|
|
#endif /* WIN32 */
|
|
|
|
#ifdef UNX
|
|
|
|
#define EOL '\n'
|
|
|
|
#endif /* UNX */
|
|
|
|
|
|
/*
|
|
* Command codes. Codes whose command string is a single letter are
|
|
* represented by that letter. Double-letter codes are assigned a
|
|
* numeric value with a non-zero high-order byte.
|
|
*/
|
|
#define CMD_HELP ((unsigned short) '?')
|
|
#define CMD_QUIT ((unsigned short) 'q')
|
|
#define CMD_SET_ENDPOINT ((unsigned short) 'e')
|
|
#define CMD_CLOSE ((unsigned short) 'c')
|
|
#define CMD_CONNECT ((unsigned short) 'i')
|
|
#define CMD_LISTEN ((unsigned short) 'l')
|
|
#define CMD_ACCEPT ((unsigned short) 'a')
|
|
#define CMD_VERBOSE_MODE ((unsigned short) 'v')
|
|
#define CMD_RUN_TEST ((unsigned short) 't')
|
|
#define CMD_OPEN_STREAM 0x0100
|
|
#define CMD_OPEN_DATAGRAM 0x0200
|
|
#define CMD_OPEN_RAW 0x0250
|
|
#define CMD_SEND 0x0300
|
|
#define CMD_SEND_URGENT 0x0400
|
|
#define CMD_SEND_DATAGRAM 0x0500
|
|
#define CMD_RECEIVE 0x0600
|
|
#define CMD_RECEIVE_URGENT 0x0700
|
|
#define CMD_RECEIVE_DATAGRAM 0x0800
|
|
#define CMD_DISCONNECT_SEND 0x0900
|
|
#define CMD_DISCONNECT_RECEIVE 0x0a00
|
|
#define CMD_DISCONNECT_BOTH 0x0c00
|
|
#define CMD_REPEAT_LAST 0x0d00
|
|
#define CMD_REPEAT_ONE 0x0e00
|
|
#define CMD_REPEAT_RANGE 0x0f00
|
|
#define CMD_JOIN_MCAST 0x1000
|
|
#define CMD_LEAVE_MCAST 0x1100
|
|
#define CMD_SET_MCAST_IF 0x1200
|
|
#define CMD_ENABLE_MCAST_LOOP 0x1300
|
|
#define CMD_DISABLE_MCAST_LOOP 0x1400
|
|
#define CMD_NOP 0xfffe
|
|
#define CMD_INVALID 0xffff
|
|
|
|
/*
|
|
* Other defines
|
|
*/
|
|
#define MAX_ENDPOINTS 20
|
|
#define MAX_HISTORY 20
|
|
#define INVALID_ID 0
|
|
#define MAX_DATA_SIZE 8192
|
|
#define STREAM_ENDPOINT 0
|
|
#define DATAGRAM_ENDPOINT 1
|
|
#define RAW_ENDPOINT 2
|
|
|
|
/*
|
|
* Type definitions
|
|
*/
|
|
#ifndef WIN32
|
|
typedef unsigned long BOOL;
|
|
#endif /* ndif WIN32 */
|
|
typedef unsigned short ENDPOINT_ID;
|
|
typedef unsigned short COMMAND_CODE;
|
|
typedef unsigned long DATA_SIZE;
|
|
|
|
/*
|
|
* Structure to describe all information necessary to execute a command.
|
|
* This structure will be filled in as each command is processed. When
|
|
*/
|
|
typedef struct _command {
|
|
COMMAND_CODE Code;
|
|
ENDPOINT_ID Id;
|
|
IPADDR Address;
|
|
IPADDR Address2;
|
|
PORT Port;
|
|
unsigned short TestNumber;
|
|
DATA_SIZE DataSize;
|
|
unsigned long Repetitions;
|
|
DATA_SIZE ReceivedBytes;
|
|
} COMMAND, *PCOMMAND;
|
|
|
|
/*
|
|
* Global variables
|
|
*/
|
|
COMMAND CommandHistory[MAX_HISTORY]; /* circular history buffer */
|
|
ENDPOINT EndpointList[MAX_ENDPOINTS+1];
|
|
char SendBuffer[MAX_DATA_SIZE];
|
|
unsigned long SendBufferSize = MAX_DATA_SIZE;
|
|
char ReceiveBuffer[MAX_DATA_SIZE];
|
|
unsigned long ReceiveBufferSize = MAX_DATA_SIZE;
|
|
ENDPOINT_ID CurrentId = INVALID_ID;
|
|
unsigned short CommandNumber = 0;
|
|
BOOL VerboseMode = 1;
|
|
|
|
|
|
#define verboseprintf(args) if (VerboseMode) printf args;
|
|
|
|
#ifdef WIN32
|
|
|
|
BOOL
|
|
CmdDispatchCommand(
|
|
PCOMMAND Command,
|
|
BOOL NewCommand
|
|
);
|
|
|
|
#endif /* WIN32 */
|
|
|
|
#ifdef UNX
|
|
|
|
extern BOOL CmdDispatchCommand();
|
|
|
|
#endif /* UNX */
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Input gathering utilities
|
|
*
|
|
* Most return 0 on error, 1 otherwise.
|
|
*
|
|
***************************************************************************/
|
|
|
|
void
|
|
CmdFlushInput(
|
|
void
|
|
)
|
|
{
|
|
while(getchar() != EOL); /* flush to CR */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetUnsignedShort(Prompt, Value)
|
|
char *Prompt;
|
|
unsigned short *Value;
|
|
{
|
|
BOOL returnCode = 1;
|
|
|
|
printf(Prompt);
|
|
|
|
if (fscanf(stdin, "%hu", Value) != 1) {
|
|
printf("\nInvalid value\n");
|
|
returnCode = 0;
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
return(returnCode);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetUnsignedLong(Prompt, Value)
|
|
char *Prompt;
|
|
unsigned long *Value;
|
|
{
|
|
BOOL returnCode = 1;
|
|
|
|
printf(Prompt);
|
|
|
|
if (fscanf(stdin, "%lu", Value) != 1) {
|
|
printf("\nInvalid value\n");
|
|
returnCode = 0;
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
return(returnCode);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetAddress(Prompt, Address)
|
|
char *Prompt;
|
|
IPADDR *Address;
|
|
{
|
|
PIT_STATUS status;
|
|
char AddressString[256];
|
|
char *cp;
|
|
|
|
|
|
printf(Prompt);
|
|
|
|
if (!fgets(AddressString, 256, stdin)) {
|
|
printf("\nInvalid address (fgets)\n");
|
|
return(0);
|
|
}
|
|
|
|
for (cp=AddressString; *cp != '\n'; cp++);
|
|
|
|
if (*cp == '\n') {
|
|
*cp = '\0';
|
|
}
|
|
|
|
status = PitConvertAddressStringToAddress(AddressString, Address);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
printf("\nInvalid address (inet_addr)\n");
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetAddressAndPort(AddressPrompt, Address, PortPrompt, Port)
|
|
char *AddressPrompt;
|
|
IPADDR *Address;
|
|
char *PortPrompt;
|
|
PORT *Port;
|
|
{
|
|
if (!CmdGetAddress(AddressPrompt, Address)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedShort(PortPrompt, Port)) {
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetEndpointId(EndpointId)
|
|
ENDPOINT_ID *EndpointId;
|
|
{
|
|
ENDPOINT_ID id;
|
|
|
|
if (CurrentId != INVALID_ID) {
|
|
*EndpointId = CurrentId;
|
|
return(1);
|
|
}
|
|
|
|
printf("Endpoint ID> ");
|
|
|
|
if (fscanf(stdin, "%hu", &id) != 1) {
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
if ((id == INVALID_ID) || (id > MAX_ENDPOINTS)) {
|
|
printf("Invalid id\n");
|
|
return(0);
|
|
}
|
|
|
|
if (EndpointList[id] == INVALID_ENDPOINT) {
|
|
printf("Endpoint is not open\n");
|
|
return(0);
|
|
}
|
|
|
|
*EndpointId = id;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdGetDataSize(DataSize)
|
|
DATA_SIZE *DataSize;
|
|
{
|
|
DATA_SIZE size;
|
|
|
|
printf("Data size> ");
|
|
|
|
if (fscanf(stdin, "%lu", &size) != 1) {
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
if (size > MAX_DATA_SIZE) {
|
|
printf("Maximum data size is %lu\n", MAX_DATA_SIZE);
|
|
return(0);
|
|
}
|
|
|
|
*DataSize = size;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Command processing routines
|
|
*
|
|
* Most return 1 if the command was successfully processed, 0 otherwise.
|
|
*
|
|
***************************************************************************/
|
|
|
|
/*
|
|
* Read a command from stdin and decode it.
|
|
*/
|
|
COMMAND_CODE
|
|
CmdGetCommandCode(
|
|
void
|
|
)
|
|
{
|
|
char c;
|
|
COMMAND_CODE code = CMD_INVALID;
|
|
BOOL doflush = 1;
|
|
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case EOL:
|
|
code = CMD_NOP;
|
|
doflush = 0;
|
|
break;
|
|
|
|
case 'o':
|
|
c = getchar();
|
|
|
|
if (c == 's') {
|
|
code = CMD_OPEN_STREAM;
|
|
}
|
|
else {
|
|
if (c == 'd') {
|
|
code = CMD_OPEN_DATAGRAM;
|
|
}
|
|
else {
|
|
if (c == 'r') {
|
|
code = CMD_OPEN_RAW;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 's':
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case 's':
|
|
code = CMD_SEND;
|
|
break;
|
|
|
|
case 'd':
|
|
code = CMD_SEND_DATAGRAM;
|
|
break;
|
|
|
|
case 'u':
|
|
code = CMD_SEND_URGENT;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'r':
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case 's':
|
|
code = CMD_RECEIVE;
|
|
break;
|
|
|
|
case 'd':
|
|
code = CMD_RECEIVE_DATAGRAM;
|
|
break;
|
|
|
|
case 'u':
|
|
code = CMD_RECEIVE_URGENT;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'd':
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case 's':
|
|
code = CMD_DISCONNECT_SEND;
|
|
break;
|
|
|
|
case 'r':
|
|
code = CMD_DISCONNECT_RECEIVE;
|
|
break;
|
|
|
|
case 'b':
|
|
code = CMD_DISCONNECT_BOTH;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'p':
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case 'l':
|
|
code = CMD_REPEAT_LAST;
|
|
break;
|
|
|
|
case 'n':
|
|
code = CMD_REPEAT_ONE;
|
|
break;
|
|
|
|
case 'r':
|
|
code = CMD_REPEAT_RANGE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'm':
|
|
c = getchar();
|
|
|
|
switch(c) {
|
|
case 'j':
|
|
code = CMD_JOIN_MCAST;
|
|
break;
|
|
|
|
case 'l':
|
|
code = CMD_LEAVE_MCAST;
|
|
break;
|
|
|
|
case 'i':
|
|
code = CMD_SET_MCAST_IF;
|
|
break;
|
|
|
|
case 'e':
|
|
code = CMD_ENABLE_MCAST_LOOP;
|
|
break;
|
|
|
|
case 'd':
|
|
code = CMD_DISABLE_MCAST_LOOP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (getchar() == EOL) {
|
|
code = (unsigned short) c;
|
|
doflush = 0;
|
|
}
|
|
else {
|
|
code = CMD_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (doflush) {
|
|
CmdFlushInput();
|
|
}
|
|
|
|
return(code);
|
|
}
|
|
|
|
|
|
void
|
|
CmdPrintSyntax(
|
|
void
|
|
)
|
|
{
|
|
printf("PIT commands:\n");
|
|
printf("\t? Print this command guide\n");
|
|
printf("\tq Quit\n");
|
|
printf("\tos Open a stream endpoint\n");
|
|
printf("\tod Open a datagram endpoint\n");
|
|
printf("\tor Open a raw endpoint\n");
|
|
printf("\ti Initiate a connection on a stream endpoint\n");
|
|
printf("\tl Listen for connections on a stream endpoint\n");
|
|
printf("\ta Accept a connection on a listening stream endpoint\n");
|
|
printf("\tss Send data on a stream endpoint\n");
|
|
printf("\trs Receive data on a stream endpoint\n");
|
|
printf("\tsu Send urgent data on a stream endpoint\n");
|
|
printf("\tru Receive urgent data on a stream endpoint\n");
|
|
printf("\tsd Send a datagram\n");
|
|
printf("\trd Receive a datagram\n");
|
|
printf("\tds Disconnect the send side of a stream endpoint\n");
|
|
printf("\tdr Disconnect the receive side of a stream endpoint\n");
|
|
printf("\tdb Disconnect both sides of a stream endpoint\n");
|
|
printf("\tc Close an endpoint\n");
|
|
printf("\tmj Join a multicast group\n");
|
|
printf("\tml Leave a multicast group\n");
|
|
printf("\tmi Set the default multicast interface\n");
|
|
printf("\tmd Disable multicast packet loopback (defaults to ENABLED)\n");
|
|
printf("\tme Enable multicast packet loopback (defaults to ENABLED)\n");
|
|
printf("\te Set endpoint for subsequent operations (0 unsets)\n");
|
|
printf("\tpl Repeat last command\n");
|
|
printf("\tpn Repeat command by number\n");
|
|
printf("\tpr Repeat command range by number and specify iterations\n");
|
|
printf("\tv Toggle verbose mode (defaults to ON)\n");
|
|
printf("\tt Run a predefined test variation\n");
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdSetEndpointId(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
|
|
if (NewCommand) {
|
|
printf("Endpoint ID> ");
|
|
|
|
if (fscanf(stdin, "%hu", &id) != 1) {
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
if (id > MAX_ENDPOINTS) {
|
|
printf("Invalid id\n");
|
|
return(0);
|
|
}
|
|
|
|
if (id != INVALID_ID) {
|
|
if (EndpointList[id] == INVALID_ENDPOINT) {
|
|
printf("Endpoint is not open\n");
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
verboseprintf(("Current endpoint set to %hu\n", id));
|
|
|
|
CurrentId = id;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdOpenEndpoint(Type, Command, NewCommand)
|
|
int Type;
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT handle;
|
|
PORT port;
|
|
IPADDR address;
|
|
ENDPOINT_ID i;
|
|
PIT_STATUS status;
|
|
|
|
|
|
for (i=1; i <= MAX_ENDPOINTS; i++ ) {
|
|
if (EndpointList[i] == INVALID_ENDPOINT) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i > MAX_ENDPOINTS) {
|
|
printf("The maximum number of endpoints have been opened\n");
|
|
return(0);
|
|
}
|
|
|
|
if (NewCommand) {
|
|
if (Type != RAW_ENDPOINT) {
|
|
if (!CmdGetAddressAndPort(
|
|
"Local address to bind > ",
|
|
&address,
|
|
"Local port to bind > ",
|
|
&port)
|
|
) {
|
|
return(0);
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We overload the port variable here.
|
|
//
|
|
if (!CmdGetAddressAndPort(
|
|
"Local address to bind > ",
|
|
&address,
|
|
"Protocol to bind > ",
|
|
&port)
|
|
) {
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
Command->Address = address;
|
|
Command->Port = port;
|
|
}
|
|
else {
|
|
address = Command->Address;
|
|
port = Command->Port;
|
|
}
|
|
|
|
verboseprintf(("Opening...\n"));
|
|
|
|
if (Type == STREAM_ENDPOINT) {
|
|
status = PitOpenStreamEndpoint(&(EndpointList[i]), address, port);
|
|
}
|
|
else if (Type == DATAGRAM_ENDPOINT) {
|
|
status = PitOpenDatagramEndpoint(&(EndpointList[i]), address, port);
|
|
}
|
|
else {
|
|
status = PitOpenRawEndpoint(
|
|
&(EndpointList[i]),
|
|
address,
|
|
(PROTOCOL)port
|
|
);
|
|
}
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Unable to open endpoint");
|
|
return(0);
|
|
}
|
|
|
|
printf("Opened endpoint %hu\n", i);
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdCloseEndpoint(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Closing endpoint %hu...\n", id));
|
|
|
|
status = PitCloseEndpoint(EndpointList[id]);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Close of endpoint failed");
|
|
return(0);
|
|
}
|
|
|
|
EndpointList[id] = INVALID_ENDPOINT;
|
|
|
|
if (CurrentId == id) {
|
|
CurrentId = INVALID_ID;
|
|
}
|
|
|
|
verboseprintf(("Endpoint closed\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
BOOL
|
|
CmdConnect(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR address;
|
|
PORT port;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddressAndPort(
|
|
"Remote address > ",
|
|
&address,
|
|
"Remote port > ",
|
|
&port
|
|
)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Address = address;
|
|
Command->Port = port;
|
|
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
address = Command->Address;
|
|
port = Command->Port;
|
|
}
|
|
|
|
verboseprintf(("Connecting endpoint %hu...\n", id));
|
|
|
|
status = PitConnect(EndpointList[id], address, port);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Connect failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Connected.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdListen(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
verboseprintf(("Posting listen on endpoint %hu...\n", id));
|
|
|
|
status = PitListenForConnections(EndpointList[id]);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Listen failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Listening.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdAccept(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id, newid;
|
|
PIT_STATUS status;
|
|
IPADDR address;
|
|
PORT port;
|
|
char addressString[18];
|
|
|
|
|
|
for (newid = 1; newid <= MAX_ENDPOINTS; newid++) {
|
|
if (EndpointList[newid] == INVALID_ENDPOINT) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (newid > MAX_ENDPOINTS) {
|
|
printf("Too many open endpoints to accept a new connection\n");
|
|
return(0);
|
|
}
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
verboseprintf(("Posting accept on endpoint %hu...\n", id));
|
|
|
|
status = PitAcceptConnection(
|
|
EndpointList[id],
|
|
&(EndpointList[newid]),
|
|
&address,
|
|
&port
|
|
);
|
|
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Accept failed");
|
|
return(0);
|
|
}
|
|
|
|
status = PitConvertAddressToAddressString(address, addressString, 18);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
verboseprintf((
|
|
"Connection accepted from address %lx port %hu\n",
|
|
address,
|
|
port
|
|
));
|
|
}
|
|
else {
|
|
verboseprintf((
|
|
"Connection accepted from address %s, port %hu\n",
|
|
addressString,
|
|
port
|
|
));
|
|
}
|
|
|
|
printf("Connected endpoint id %hu\n", newid);
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdSend(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesSent;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->DataSize = size;
|
|
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
verboseprintf(("Sending on endpoint %hu...\n", id));
|
|
|
|
status = PitSend(EndpointList[id], SendBuffer, size, &bytesSent);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Send failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Sent %lu bytes.\n", bytesSent));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceive(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesReceived;
|
|
DATA_SIZE i;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
verboseprintf(("Posting receive on endpoint %hu...\n", id));
|
|
|
|
status = PitReceive(
|
|
EndpointList[id],
|
|
ReceiveBuffer,
|
|
MAX_DATA_SIZE,
|
|
size,
|
|
&bytesReceived
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Receive failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Received %lu bytes.\n", bytesReceived));
|
|
|
|
Command->ReceivedBytes = bytesReceived;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdSendUrgent(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesSent;
|
|
DATA_SIZE i;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
if (VerboseMode) {
|
|
printf("Urgent data = \"");
|
|
|
|
for (i=0; i<size; i++) {
|
|
printf("%c", SendBuffer[i]);
|
|
}
|
|
printf("\"\n");
|
|
}
|
|
|
|
verboseprintf(("Sending urgent data on endpoint %hu...\n", id));
|
|
|
|
status = PitSendUrgent(EndpointList[id], SendBuffer, size, &bytesSent);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Send failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Sent %lu bytes.\n", bytesSent));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceiveUrgent(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesReceived;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
verboseprintf(("Posting receive on endpoint %hu...\n", id));
|
|
|
|
status = PitReceiveUrgent(
|
|
EndpointList[id],
|
|
ReceiveBuffer,
|
|
MAX_DATA_SIZE,
|
|
size,
|
|
&bytesReceived
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Receive failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Received %lu bytes.\n", bytesReceived));
|
|
|
|
if (VerboseMode) {
|
|
DATA_SIZE i;
|
|
|
|
printf("Urgent data = \"");
|
|
|
|
for (i=0; i<bytesReceived; i++) {
|
|
printf("%c", ReceiveBuffer[i]);
|
|
}
|
|
printf("\"\n");
|
|
}
|
|
|
|
Command->ReceivedBytes = bytesReceived;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdSendDatagram(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR address;
|
|
PORT port;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesSent;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddressAndPort(
|
|
"Remote address > ",
|
|
&address,
|
|
"Remote port > ",
|
|
&port
|
|
)
|
|
) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Address = address;
|
|
Command->Port = port;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
address = Command->Address;
|
|
port = Command->Port;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
verboseprintf(("Sending datagram on endpoint %hu...\n", id));
|
|
|
|
status = PitSendDatagram(
|
|
EndpointList[id],
|
|
address,
|
|
port,
|
|
SendBuffer,
|
|
size,
|
|
&bytesSent
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Datagram send failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Sent %lu bytes.\n", bytesSent));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceiveDatagram(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR address;
|
|
PORT port;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
DATA_SIZE size;
|
|
DATA_SIZE bytesReceived;
|
|
char addressString[18];
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (size == 0) {
|
|
size = MAX_DATA_SIZE;
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
size = Command->DataSize;
|
|
|
|
if (size == 0) {
|
|
size = MAX_DATA_SIZE;
|
|
}
|
|
}
|
|
|
|
verboseprintf(("Posting datagram receive on endpoint %hu...\n", id));
|
|
|
|
status = PitReceiveDatagram(
|
|
EndpointList[id],
|
|
&address,
|
|
&port,
|
|
ReceiveBuffer,
|
|
size,
|
|
&bytesReceived
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Datagram receive failed");
|
|
return(0);
|
|
}
|
|
|
|
Command->Address = address;
|
|
Command->Port = port;
|
|
|
|
status = PitConvertAddressToAddressString(address, addressString, 18);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
verboseprintf((
|
|
"Received %lu bytes from address %lx port %hu.\n",
|
|
bytesReceived,
|
|
address,
|
|
port
|
|
));
|
|
}
|
|
else {
|
|
verboseprintf((
|
|
"Received %lu bytes from address %s port %hu.\n",
|
|
bytesReceived,
|
|
addressString,
|
|
port
|
|
));
|
|
}
|
|
|
|
Command->ReceivedBytes = bytesReceived;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdDisconnectSend(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
verboseprintf(("Disconnecting send side of endpoint %hu...\n", id));
|
|
|
|
status = PitDisconnectSend(EndpointList[id]);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Disconnect failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Disconnect complete.\n"));
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
BOOL
|
|
CmdDisconnectReceive(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
verboseprintf(("Disconnecting receive side of endpoint %hu...\n", id));
|
|
|
|
status = PitDisconnectReceive(EndpointList[id]);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Disconnect failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Disconnect complete.\n"));
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
BOOL
|
|
CmdDisconnectBoth(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
verboseprintf(("Disconnecting both sides of endpoint %hu...\n", id));
|
|
|
|
status = PitDisconnectBoth(EndpointList[id]);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Disconnect failed");
|
|
return(0);
|
|
}
|
|
|
|
verboseprintf(("Disconnect complete.\n"));
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
BOOL
|
|
CmdRepeatLastCommand(CommandNumber)
|
|
unsigned short CommandNumber;
|
|
{
|
|
if (CommandNumber == 0) {
|
|
CommandNumber = MAX_HISTORY - 1;
|
|
}
|
|
else {
|
|
CommandNumber--;
|
|
}
|
|
|
|
CmdDispatchCommand(&(CommandHistory[CommandNumber]), 0);
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdRepeatOneCommand(
|
|
void
|
|
)
|
|
{
|
|
unsigned short commandNumber;
|
|
BOOL returnCode = 1;
|
|
|
|
printf("Command number> ");
|
|
|
|
if (fscanf(stdin, "%hu", &commandNumber) != 1) {
|
|
printf("\nInvalid command number\n");
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
if (commandNumber >= MAX_HISTORY) {
|
|
printf("\nInvalid command number\n");
|
|
return(0);
|
|
}
|
|
|
|
CmdDispatchCommand(&(CommandHistory[commandNumber]), 0);
|
|
|
|
return(returnCode);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdRepeatCommandRange(
|
|
void
|
|
)
|
|
{
|
|
unsigned short startingNumber, endingNumber;
|
|
BOOL last;
|
|
unsigned short i;
|
|
unsigned long count;
|
|
|
|
|
|
printf("Starting command number> ");
|
|
|
|
if (fscanf(stdin, "%hu", &startingNumber) != 1) {
|
|
printf("\nInvalid command number\n");
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
if (startingNumber >= MAX_HISTORY) {
|
|
printf("\nInvalid command number\n");
|
|
return(0);
|
|
}
|
|
|
|
printf("Ending command number> ");
|
|
|
|
if (fscanf(stdin, "%hu", &endingNumber) != 1) {
|
|
printf("\nInvalid command number\n");
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
if (endingNumber >= MAX_HISTORY) {
|
|
printf("\nInvalid command number\n");
|
|
return(0);
|
|
}
|
|
|
|
printf("Repetions> ");
|
|
|
|
if (fscanf(stdin, "%lu", &count) != 1) {
|
|
printf("\nInvalid repetition number\n");
|
|
CmdFlushInput();
|
|
return(0);
|
|
}
|
|
|
|
CmdFlushInput();
|
|
|
|
while (count--) {
|
|
i = startingNumber;
|
|
|
|
while(1) {
|
|
|
|
CmdDispatchCommand(&(CommandHistory[i]), 0);
|
|
|
|
if (i == endingNumber) {
|
|
break;
|
|
}
|
|
|
|
if (++i == MAX_HISTORY) {
|
|
i = 0;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdJoinMulticastGroup(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR multicastAddress, interfaceAddress;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
#ifndef MCAST
|
|
|
|
printf("Multicast is not supported by this transport.\n");
|
|
return(0);
|
|
|
|
#else /* MCAST */
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddress("Multicast address to join > ", &multicastAddress)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddress("Local interface to join on > ", &interfaceAddress)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Address = multicastAddress;
|
|
Command->Address2 = interfaceAddress;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
multicastAddress = Command->Address;
|
|
interfaceAddress = Command->Address2;
|
|
}
|
|
|
|
status = PitJoinMulticastGroup(
|
|
EndpointList[id],
|
|
multicastAddress,
|
|
interfaceAddress
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Join multicast group failed");
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
#endif /* MCAST */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdLeaveMulticastGroup(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR multicastAddress, interfaceAddress;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
#ifndef MCAST
|
|
|
|
printf("Multicast is not supported by this transport.\n");
|
|
return(0);
|
|
|
|
#else /* MCAST */
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddress("Multicast address to leave > ", &multicastAddress)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddress("Local interface to leave from > ", &interfaceAddress)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Address = multicastAddress;
|
|
Command->Address2 = interfaceAddress;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
multicastAddress = Command->Address;
|
|
interfaceAddress = Command->Address2;
|
|
}
|
|
|
|
status = PitLeaveMulticastGroup(
|
|
EndpointList[id],
|
|
multicastAddress,
|
|
interfaceAddress
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(status, "Leave multicast group failed");
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
#endif /* MCAST */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdSetMulticastInterface(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
IPADDR interfaceAddress;
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
#ifndef MCAST
|
|
|
|
printf("Multicast is not supported by this transport.\n");
|
|
return(0);
|
|
|
|
#else /* MCAST */
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddress("New default interface > ", &interfaceAddress)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Address = interfaceAddress;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
interfaceAddress = Command->Address;
|
|
}
|
|
|
|
status = PitSetMulticastInterface(
|
|
EndpointList[id],
|
|
interfaceAddress
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(
|
|
status,
|
|
"Set default multicast interface failed"
|
|
);
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
#endif /* MCAST */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdEnableMulticastLoopback(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
#ifndef MCAST
|
|
|
|
printf("Multicast is not supported by this transport.\n");
|
|
return(0);
|
|
|
|
#else /* MCAST */
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
status = PitEnableMulticastLoopback(
|
|
EndpointList[id]
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(
|
|
status,
|
|
"Enable multicast packet loopback failed"
|
|
);
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
#endif /* MCAST */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdDisableMulticastLoopback(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
PIT_STATUS status;
|
|
|
|
|
|
#ifndef MCAST
|
|
|
|
printf("Multicast is not supported by this transport.\n");
|
|
return(0);
|
|
|
|
#else /* MCAST */
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
}
|
|
|
|
status = PitDisableMulticastLoopback(
|
|
EndpointList[id]
|
|
);
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
PitPrintStringForStatus(
|
|
status,
|
|
"Diable multicast packet loopback failed"
|
|
);
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
#endif /* MCAST */
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdInitiateStreamPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
DATA_SIZE j;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdSend(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdReceive(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
for (j=0; j<size; j++ ) {
|
|
if (SendBuffer[j] != ReceiveBuffer[j]) {
|
|
printf("Miscompare of byte %lu on iteration %lu\n", j, i);
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceiveStreamPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdReceive(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = Command->ReceivedBytes;
|
|
|
|
if (!CmdSend(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = size;
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdInitiateUrgentPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
DATA_SIZE j;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdSendUrgent(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdReceiveUrgent(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
for (j=0; j<size; j++ ) {
|
|
if (SendBuffer[j] != ReceiveBuffer[j]) {
|
|
printf("Miscompare of byte %lu on iteration %lu\n", j, i);
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceiveUrgentPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdReceiveUrgent(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = Command->ReceivedBytes;
|
|
|
|
if (!CmdSendUrgent(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = size;
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdInitiateDatagramPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
DATA_SIZE j;
|
|
IPADDR address;
|
|
PORT port;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetAddressAndPort(
|
|
"Remote address > ",
|
|
&address,
|
|
"Remote port > ",
|
|
&port
|
|
)
|
|
) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
Command->Address = address;
|
|
Command->Port = port;
|
|
}
|
|
else {
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdSendDatagram(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdReceiveDatagram(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
return(0);
|
|
}
|
|
|
|
for (j=0; j<size; j++ ) {
|
|
if (SendBuffer[j] != ReceiveBuffer[j]) {
|
|
printf("Miscompare of byte %lu on iteration %lu\n", j, i);
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CmdReceiveDatagramPingPong(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
ENDPOINT_ID id;
|
|
unsigned long repetitions;
|
|
DATA_SIZE size;
|
|
unsigned long i;
|
|
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetEndpointId(&id)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetDataSize(&size)) {
|
|
return(0);
|
|
}
|
|
|
|
if (!CmdGetUnsignedLong("Repetitions > ", &repetitions)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->Id = id;
|
|
Command->Repetitions = repetitions;
|
|
Command->DataSize = size;
|
|
}
|
|
else {
|
|
id = Command->Id;
|
|
repetitions = Command->Repetitions;
|
|
size = Command->DataSize;
|
|
}
|
|
|
|
for (i=repetitions; i != 0; i--) {
|
|
if (!CmdReceiveDatagram(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = Command->ReceivedBytes;
|
|
|
|
if (!CmdSendDatagram(Command, 0)) {
|
|
printf("Aborting test\n");
|
|
Command->DataSize = size;
|
|
return(0);
|
|
}
|
|
|
|
Command->DataSize = size;
|
|
}
|
|
|
|
verboseprintf(("Test complete.\n"));
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
void
|
|
CmdPrintTestList(
|
|
void
|
|
)
|
|
{
|
|
printf("Test variations:\n");
|
|
printf("\t1 Initiate regular ping-pong on a connected stream endpoint\n");
|
|
printf("\t2 Receive regular ping-pong on a connected stream endpoint\n");
|
|
printf("\t3 Initiate urgent ping-pong on a connected stream endpoint\n");
|
|
printf("\t4 Receive urgent ping-pong on a connected stream endpoint\n");
|
|
printf("\t5 Initiate ping-pong on a datagram endpoint\n");
|
|
printf("\t6 Receive ping-pong on a datagram endpoint\n");
|
|
printf("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Higher-level test command dispatch routine
|
|
*/
|
|
BOOL
|
|
CmdRunTest(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
unsigned short testNumber = 255;
|
|
BOOL saveCommand = 1;
|
|
ENDPOINT_ID id;
|
|
|
|
|
|
askagain:
|
|
|
|
if (NewCommand) {
|
|
if (!CmdGetUnsignedShort("Test to run (0 for a list, 255 to break) > ", &testNumber)) {
|
|
return(0);
|
|
}
|
|
|
|
Command->TestNumber = testNumber;
|
|
}
|
|
else {
|
|
testNumber = Command->TestNumber;
|
|
}
|
|
|
|
switch(testNumber) {
|
|
case 0:
|
|
CmdPrintTestList();
|
|
goto askagain;
|
|
break;
|
|
|
|
case 1:
|
|
CmdInitiateStreamPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 2:
|
|
CmdReceiveStreamPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 3:
|
|
CmdInitiateUrgentPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 4:
|
|
CmdReceiveUrgentPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 5:
|
|
CmdInitiateDatagramPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 6:
|
|
CmdReceiveDatagramPingPong(Command, NewCommand);
|
|
break;
|
|
|
|
case 255:
|
|
saveCommand = 0;
|
|
break;
|
|
|
|
default:
|
|
printf("Invalid test number.\n\n");
|
|
goto askagain;
|
|
break;
|
|
}
|
|
|
|
return(saveCommand);
|
|
}
|
|
|
|
|
|
/*
|
|
* Main command dispatch routine.
|
|
* Returns 1 if the command was successful and should be saved in the history
|
|
* list, 0 otherwise.
|
|
*/
|
|
BOOL
|
|
CmdDispatchCommand(Command, NewCommand)
|
|
PCOMMAND Command;
|
|
BOOL NewCommand;
|
|
{
|
|
BOOL saveCommand = 0;
|
|
|
|
|
|
switch(Command->Code) {
|
|
|
|
case CMD_OPEN_STREAM:
|
|
saveCommand = CmdOpenEndpoint(STREAM_ENDPOINT, Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_OPEN_DATAGRAM:
|
|
saveCommand = CmdOpenEndpoint(DATAGRAM_ENDPOINT, Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_OPEN_RAW:
|
|
saveCommand = CmdOpenEndpoint(RAW_ENDPOINT, Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_CONNECT:
|
|
saveCommand = CmdConnect(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_LISTEN:
|
|
saveCommand = CmdListen(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_ACCEPT:
|
|
saveCommand = CmdAccept(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_SEND:
|
|
saveCommand = CmdSend(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_RECEIVE:
|
|
saveCommand = CmdReceive(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_SEND_DATAGRAM:
|
|
saveCommand = CmdSendDatagram(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_RECEIVE_DATAGRAM:
|
|
saveCommand = CmdReceiveDatagram(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_SEND_URGENT:
|
|
saveCommand = CmdSendUrgent(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_RECEIVE_URGENT:
|
|
saveCommand = CmdReceiveUrgent(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_DISCONNECT_SEND:
|
|
saveCommand = CmdDisconnectSend(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_DISCONNECT_RECEIVE:
|
|
saveCommand = CmdDisconnectReceive(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_DISCONNECT_BOTH:
|
|
saveCommand = CmdDisconnectBoth(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_CLOSE:
|
|
saveCommand = CmdCloseEndpoint(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_SET_ENDPOINT:
|
|
saveCommand = CmdSetEndpointId(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_JOIN_MCAST:
|
|
saveCommand = CmdJoinMulticastGroup(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_LEAVE_MCAST:
|
|
saveCommand = CmdLeaveMulticastGroup(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_SET_MCAST_IF:
|
|
saveCommand = CmdSetMulticastInterface(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_ENABLE_MCAST_LOOP:
|
|
saveCommand = CmdEnableMulticastLoopback(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_DISABLE_MCAST_LOOP:
|
|
saveCommand = CmdDisableMulticastLoopback(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_RUN_TEST:
|
|
saveCommand = CmdRunTest(Command, NewCommand);
|
|
break;
|
|
|
|
case CMD_INVALID:
|
|
default:
|
|
saveCommand = 0;
|
|
printf("Unrecognized command. Type ? for help\n");
|
|
break;
|
|
}
|
|
|
|
return(saveCommand);
|
|
}
|
|
|
|
|
|
/*
|
|
* Main program routine.
|
|
*/
|
|
int
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
BOOL again = 1;
|
|
PIT_STATUS status;
|
|
int i;
|
|
BOOL saveCommand;
|
|
PCOMMAND cmd;
|
|
|
|
|
|
printf("\nPortable Interoperability Tester version %s\n\n", PIT_VERSION);
|
|
printf("Type \'?\' for help\n\n");
|
|
|
|
/*
|
|
* Initialize endpoint list
|
|
*/
|
|
for (i=1; i <= MAX_ENDPOINTS; i++) {
|
|
EndpointList[i] = INVALID_ENDPOINT;
|
|
}
|
|
|
|
/*
|
|
* Initialize command history list
|
|
*/
|
|
for (i=0; i < MAX_HISTORY; i++) {
|
|
CommandHistory[i].Code = CMD_INVALID;
|
|
}
|
|
|
|
/*
|
|
* Initialize send buffer
|
|
*/
|
|
for (i=0; i < MAX_DATA_SIZE; i++) {
|
|
SendBuffer[i] = 'a' + (i % 26);
|
|
}
|
|
|
|
status = PitInitializeTransportInterface();
|
|
|
|
if (status != PIT_SUCCESS) {
|
|
printf("PitInitializeTransportInterface: ");
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Main command processing loop. Administrative and meta-commands
|
|
* are handled here.
|
|
*/
|
|
while (again) {
|
|
COMMAND_CODE code;
|
|
|
|
saveCommand = 0;
|
|
|
|
printf("PIT %2d > ", CommandNumber);
|
|
|
|
code = CmdGetCommandCode();
|
|
|
|
switch(code) {
|
|
|
|
case CMD_NOP:
|
|
break;
|
|
|
|
case CMD_QUIT:
|
|
again = 0;
|
|
break;
|
|
|
|
case CMD_HELP:
|
|
CmdPrintSyntax();
|
|
break;
|
|
|
|
case CMD_REPEAT_LAST:
|
|
CmdRepeatLastCommand(CommandNumber);
|
|
break;
|
|
|
|
case CMD_REPEAT_ONE:
|
|
CmdRepeatOneCommand();
|
|
break;
|
|
|
|
case CMD_REPEAT_RANGE:
|
|
CmdRepeatCommandRange();
|
|
break;
|
|
|
|
case CMD_VERBOSE_MODE:
|
|
if (VerboseMode) {
|
|
VerboseMode = 0;
|
|
printf("Verbose mode is now OFF\n");
|
|
}
|
|
else {
|
|
VerboseMode = 1;
|
|
printf("Verbose mode is now ON\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
cmd = &(CommandHistory[CommandNumber]);
|
|
cmd->Code = code;
|
|
saveCommand = CmdDispatchCommand(cmd, 1);
|
|
}
|
|
|
|
if (saveCommand) {
|
|
CommandNumber = (CommandNumber + 1) % MAX_HISTORY;
|
|
}
|
|
}
|
|
|
|
PitCleanupTransportInterface();
|
|
|
|
printf("\nGoodbye\n");
|
|
printf("\n");
|
|
|
|
return(0);
|
|
}
|
|
|