#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <strings.h>

int main(int argc, char **argv) {
	if (argc < 2) {
		printf("Usage: %s [SERVICE]\n", argv[0]);
		exit(1);
	}

	int sockudp, socktcp;

	sockudp = socket(AF_INET, SOCK_DGRAM, 0);
	socktcp = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in addrudp;
	addrudp.sin_family = AF_INET;
	addrudp.sin_port = ((struct servent *)getservbyname(argv[1], "udp"))->s_port;
	addrudp.sin_addr.s_addr = 0;

	struct sockaddr_in addrtcp;
	addrtcp.sin_family = AF_INET;
	addrtcp.sin_port = getservbyname(argv[1], "tcp")->s_port;
	addrtcp.sin_addr.s_addr = 0;

	bind(sockudp, (struct sockaddr *)&addrudp, sizeof(addrudp));
	bind(socktcp, (struct sockaddr *)&addrtcp, sizeof(addrtcp));

	listen(socktcp, 5); // Or some good value

	fd_set set;
	int bufsize = 100;
	void *buf = malloc(sizeof(void)*bufsize);

	while(1) {
		FD_ZERO(&set);
		FD_SET(sockudp, &set);
		FD_SET(socktcp, &set);
		bzero(buf, sizeof(void)*bufsize);

		select(FD_SETSIZE, &set, NULL, NULL, NULL);

		if (FD_ISSET(sockudp, &set)) {
			struct sockaddr_in from;
			unsigned int sizefrom = sizeof(from);
			bzero(&from, sizeof(from));
			recvfrom(sockudp, buf, bufsize, 0, (struct sockaddr *)&from, &sizefrom);
			sendto(sockudp, buf, bufsize, 0, (struct sockaddr *)&from, sizeof(from));
		}
		else if (FD_ISSET(socktcp, &set)) {
			printf("new connection\n");
			struct sockaddr_in from;
			bzero(&from, sizeof(from));
			unsigned int sizefrom = sizeof(from);
			int s = accept(socktcp, (struct sockaddr *)&from, &sizefrom);

			if (fork() == 0) {
				close(sockudp);
				close(socktcp);
				int buffsize = 100;
				void *buff = malloc(buffsize);
				int amount = read(s, buff, buffsize, 0);
				send(s, buff, amount, 0);
				free(buff);
				exit(0);
			}
			close(s);
		}
	}
}


