/*
 * Test program that sends numbers to a server to be
 * added together and returned back to the client
 *
 * On one Be machine (called server), do this:
 *
 *    # nmtest -s
 *
 * On another, do this to add two number (55 & 22) on server
 *
 *    # nmtest -c server 55 22
 */
#include "NetMessage.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * UDP port number we'll use by default
 * Can be overriden by command line option, in case of conflict
 */
#define DEFAULT_PORT 0xface

/*
 * Names of various items in the BMessage
 */
static const char TOTAL[] = "Total";
static const char NUMBER1[] = "Number1";
static const char NUMBER2[] = "Number2";


/*
 * Translate Be error code to string
 */
static char *
errorstr(
		 long code
		 )
{
	static char str[80];

	switch (code) {
	case NET_CANT_SEND:
		return ("Can't send");
	case NET_CANT_RECV:
		return ("Can't receive");
	case B_TIMED_OUT:
		return ("Timed out");
	default:
		sprintf(str, "Unknown code: %08x", code);
		return (str);
	}
}

/*
 * The server thread.  Never returns.
 *
 */
static int
server(int port)
{
	NetServer *server;
	BMessage *msg;
	BMessage *replymsg;
	int num1;
	int num2;
	long status;

	server = new NetServer(port);
	for (;;) {
		status = server->ReceiveMessage(&msg);
		if (status < B_NO_ERROR) {
			printf("unable to receive, %s\n", errorstr(status));
			break;
		}
		switch (msg->what) {
		case 'ADD_':
			printf("Got request, transaction id %u\n", 
				   server->CurrentTransactionID());
			num1 = msg->FindLong(NUMBER1);
			num2 = msg->FindLong(NUMBER2);
			replymsg = new BMessage(msg->what);
			replymsg->AddLong(TOTAL, num1 + num2);
			status = server->SendReply(replymsg);
			if (status < B_NO_ERROR) {
				printf("unable to send reply, code %08x\n", status);
			}
			delete replymsg;
			break;
		default:
			printf("bad message ID received\n");
			break;
		}
		delete msg;
	}
	return (status);
}

/*
 * The client thread
 */
static int
client(
	   const char *server,
	   int port,
	   int num1,
	   int num2
	   )
{
	BMessage *msg;
	BMessage *reply;
	NetClient *client;
	long status;

	client = new NetClient(server, port);
	if (client->HostLookupFailed()) {
		printf("Can't find host %s\n", server);
		return (1);
	}
	msg = new BMessage('ADD_');
	msg->AddLong(NUMBER1, num1);
	msg->AddLong(NUMBER2, num2);
	status = client->SendMessage(msg, &reply);
	if (status < B_NO_ERROR) {
		printf("Unable to send message: %s\n", errorstr(status));
		return (1);
	}
	printf("%s says sum is %d\n", server, reply->FindLong(TOTAL));
	return (0);
}


/*
 * Print usage message and die
 */
static void
usage(const char *myname)
{
	fprintf(stderr, 
			"usage: %s [-p port] -s  # starts server\n", myname);
	fprintf(stderr, 
			"       %s [-p port] -c server number1 number2 # add numbers on server\n", myname);
	exit(1);
}


/*
 * Main program: no duh!
 */
int
main(int argc, char **argv)
{
	char *myname = argv[0];
	int port = DEFAULT_PORT;
	int runserver = 0;
	int runclient = 0;
	char *servername;
	int num1;
	int num2;

	for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
		if (strcmp(argv[0], "-s") == 0) {
			runserver++;
		} else if (strcmp(argv[0], "-c") == 0) {
			runclient++;
			if (argc < 4) {
				usage(myname);
			}
			servername = argv[1];
			num1 = atoi(argv[2]);
			num2 = atoi(argv[3]);
			argc -= 3, argv += 3;
		} else if (strcmp(argv[0], "-p") == 0) {
			if (argc < 1) {
				usage(myname);
			}
			port = atoi(argv[1]);
			argc--, argv++;
		} else {
			usage(myname);
		}
	}
	if (runserver) {
		exit(server(port));
	}
	if (runclient) {
		exit(client(servername, port, num1, num2));
	}
	usage(myname);
	return (1);
}
