text: #include "server.hh"
  #include "client.hh"
  #include "bytebuffer.hh"
  
  #include <cstdio>
  #include <cstring>
  
  /* ----------------- TYPE DEFINITIONS ----------------- */
  
  /**
   * A Function that expects a String Array which has as its first Element the
   * Option's Name itself and after that any amount of Values or Parameters.
  */
  typedef int (*optsetter)(char **, uint8_t);
  
  struct option {
  	char *		optname;
  	optsetter	optfunc;
  	uint8_t		optargs;
  };
  
  
  /* ----------------- FUNCTIONS DECLARATIONS ----------------- */
  
  /**
   * Portopt converts the passed String Array to the Port that is used for
   * both the Client's Connection and the Servers Socket binding.
  */
  int portopt(char ** args, uint8_t len);
  
  
  /**
   * Addropt converts the passed String Array to the Address that is used by the Client to
   * connect to the Server.
  */
  int addropt(char ** args, uint8_t len);
  
  
  /**
   * Cliopt changes, based on the String Array, the amount of Clients that can connect to the
   * Server.
  */
  int clicopt(char ** args, uint8_t len);
  
  
  /**
   * Prints to the STDOUT how the Program can be used.
   * This Function can be used in two Modes. The "Error-Mode" and the
   * "Help-Mode".
  */
  void print_usage(bool print_help);
  
  
  /**
   * Parses the given Array to the Options that influence that Program on Runtime.
   * The Function takes a String Array, the Index at which the first Option will be
   * found and the length of the Array.
  */
  int parse_options(int firstopt, int argc, char ** argv);
  
  
  /* ----------------- GLOBAL VARIABLES DEFINITIONS ----------------- */
  
  char * gUsages[] = {
  	(char *) "-p [value]",	(char *) "The Port to which the Server will listen or the client will write.",
  	(char *) "-i [addr]",	(char *) "Internet IP Address to which the Client will connect. Defaults to \"127.0.0.1\"",
  	(char *) "-c [amount]",	(char *) "The Amount of Clients that want to read from this Server."
  };
  
  struct option gOptions[] {
  	{(char *) "-p", portopt, 1},
  	{(char *) "-i", addropt, 1},
  	{(char *) "-c", clicopt, 1}
  };
  
  int		gClientCount	= 1;
  int		gPort			= 16661;
  char *	gIpAddr			= (char *) "127.0.0.1";
  
  
  
  int main(int argc, char ** argv) {
  
  	/* No Argumentes passed means neither Server nor Client can be started. */
  	/* Print the usage instead to lead the user into the right direction. */
  	if(argc <= 1) {
  		print_usage(false);
  		return 0;
  	}
  
  	char * arg = argv[1];
  
  	/* The User selected the "help" Argument which prints the Usage and advanced Information like */
  	/* passable options */
  	if(strcmp(arg, "help") == 0) {
  		print_usage(true);
  		return 0;
  	
  	/* A Server will be started. The Server acts as the Host where the Keyboard must be physically connected to. */
  	/* (Or at least in a Way that SDL recognizes the Keyboard which also works with wirless keyboards ) */
  	/* I assume that having the Host and Client run on the same System may cause a Feedback-Loop. I invite you to try. */
  	} else if(strcmp(arg, "server") == 0) {
  		
  		if(parse_options(2, argc, argv) == -1)
  			return -1;
  		
  		Server server(gPort);
  		return server.Start(gClientCount);
  
  	/* A Client will be started which connects to the default IP (which is localhost (which may cause Feedback Loop)).*/
  	/* Or, if passed, to the Hosts IP. */
  	} else if(strcmp(arg, "client") == 0) {
  
  		if(parse_options(2, argc, argv) == -1)
  			return -1;
  
  		Client client;
  		return client.Connect(gIpAddr, gPort);
  	}
  
  	/* Some random Input was passed. Just print out the usage. */
  	print_usage(false);
  	return 0;
  }
  
  /* ----------------- FUNCTIONS DEFINITIONS ----------------- */
  
  
  
  int portopt(char ** args, uint8_t len) {
  	char * sPort = args[1];
  	int iPort;
  
  	if(sscanf(sPort, "%d", &iPort) != 1 || iPort <= 0 || iPort > 256*256) {
  		printf("%s is not a valid Port!\n", sPort);
  		return -1;
  	}
  	
  	gPort = iPort;
  	return 0;
  }
  
  
  
  
  
  int addropt(char ** args, uint8_t len) {
  	char * addr = args[1];
  	gIpAddr = addr; // Dangerous
  
  	return 0;
  }
  
  
  
  
  
  int clicopt(char ** args, uint8_t len) {
  	char * sCount = args[1];
  	int iCount = 0;
  
  	if(sscanf(sCount, "%d", &iCount) != 1 || iCount <= 0) {
  		printf("%s is not a valid Number!\n", sCount);
  		return -1;
  	}
  	
  	gClientCount = iCount;
  	return 0;
  }
  
  
  
  
  
  void print_usage(bool print_help) {
  	printf("USAGE\n\tkeyshare [arg] [options]\n");
  
  	if(print_help) {
  		printf("\nARGUMENTS\n\t\"server\", \"client\", \"help\"\n");
  		printf("\nOPTIONS\n");
  
  		for(unsigned int i = 0; i < sizeof(gUsages)/sizeof(char *); i += 2) {
  
  			char * optname = gUsages[i];
  			char * optdesc = gUsages[i+1];
  			
  			printf("\t %-15s %-20s \n", optname, optdesc);
  		}
  	} else {
  		printf("\nOr use the Argument \"help\".\n");
  	}
  }
  
  
  
  
  
  int parse_options(int firstopt, int argc, char ** argv) {
  	for(int i = firstopt; i < argc;) {
  		char * optname = argv[i];
  		struct option opt;
  		int optset = 0;
  
  		/* Find Option */
  		for(unsigned int i = 0; i < sizeof(gOptions)/sizeof(struct option); ++i) {
  			if(strcmp(gOptions[i].optname, optname) == 0) {
  				opt = gOptions[i];
  				optset = 1;
  				break;
  			}
  		}
  
  		/* Optset is set, when the Option was found in the "Database" */
  		if(optset) {
  			
  			/* Parse Specific Option */
  			if(i + opt.optargs < argc) {
  				if(opt.optfunc(&(argv[i]), opt.optargs + 1) == -1)
  					return -1;
  				
  				i += 1 + opt.optargs;
  
  			/* Option is missing the right amount of arguments */
  			} else {
  				printf("There are not enough Arguments!\n");
  				return -1;
  			}
  
  		/* Option is unknown */
  		} else {
  			printf("Unkown Option: %s\n", argv[i]);
  			return -1;
  		}
  	}
  
  	return 0;
  }