Exemplo n.º 1
0
/*
 * main(): This function is the entry point for the server program of Share Your Playlist application.
 * This function creates the upload and download sockets and waits for client connections.
 * We have implemented all the 3 methods used in concurrency in servers namely:
 * 1. Multi-process approach using fork() for handling upload and download functionalities
 * 2. Non-blocking I/O using select() for monitoring two ports on server
 * 3. Multi-threaded approach for data redundancy between servers
 */
int main(int argc, char **argv) {
	struct sockaddr_in sockserv;
	unsigned int alen;
	int upload_sock, download_sock, i, slave_sock, fds[2], *fd = NULL;
	struct sockaddr *addr;
	socklen_t *addrlen;

	//binds sockets for upload and download functionality
	upload_sock = passiveTCP(UPLOAD_PORT);
	download_sock = passiveTCP(DOWNLOAD_PORT);

	printf("Upload sock : %d\n", upload_sock);
	printf("Download sock : %d\n", download_sock);

	fds[0] = upload_sock;
	fds[1] = download_sock;

	while (1) {
		//calls function to identify which port client connected to
		slave_sock = network_accept_any(fds, 2, &fd);

		//Initializing thread attributes for prstats thread
		(void) pthread_attr_init(&ta);
		(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
		(void) pthread_mutex_init(&stats.st_mutex, 0);

		/*if(pthread_create(&th, &ta, (void * (*)(void *))prstats, 0) < 0)
		 fatal("prstats thread failed");*/

		//Based on socket that obtained the connection, we use multi-process approach using fork() to provide concurrency
		//Based on upload/download, the respective functions are called in the child processes.
		if (*fd == upload_sock) {
			switch (fork()) {
			case 0:
				close(*fd);
				exit(handleUpload(slave_sock));
			default:
				close(slave_sock);
				break;
			}
		}
		if (*fd == download_sock) {
			switch (fork()) {
			case 0:
				close(*fd);
				exit(handleDownload(slave_sock));
			default:
				close(slave_sock);
				break;
			}
		}
	}
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
#ifdef _WIN32
	nodaemon = 1;
	WSADATA wsadata;
	WSAStartup(0x0202, &wsadata);
#endif

	SOCKET s = INVALID_SOCKET;

	s = socket(AF_INET6, SOCK_STREAM, 0);

	if (s != INVALID_SOCKET)
	{
		HaveIPv6Stack = 1;
		close(s);
		s = INVALID_SOCKET;
	}

	s = socket(AF_INET, SOCK_STREAM, 0);

	if (s != INVALID_SOCKET)
	{
		HaveIPv4Stack = 1;
		close(s);
	}

	int o;
	const static char* const optstring = "u:g:L:p:i:P:l:r:feD46";
	
	for (opterr = 0; ( o = getopt(argc, argv, optstring) ) > 0; ) switch (o)
	{
		case '4':
			if (!HaveIPv4Stack)
			{
				fprintf(stderr, "Fatal: Your system does not support %s.\n", cIPv4);
				return !0;
			}
			v4required = 1;
			break;
		case '6':
			if (!HaveIPv6Stack)
			{
				fprintf(stderr, "Fatal: Your system does not support %s.\n", cIPv6);
				return !0;
			}
			v6required = 1;
			break;
		case 'p':
			fn_pid = optarg;
			break;
		case 'i':
			fn_ini = optarg;
			break;
		case 'l':
			fn_log = optarg;
			break;
		case 'L':
			maxsockets++;
			break;
		case 'f':
			nodaemon = 1;
			logstdout = 1;
			break;
		case 'D':
			nodaemon = 1;
			break;
		case 'e':
			logstdout = 1;
			break;
		case 'r':
			RandomizationLevel = atoi(optarg);
			if (RandomizationLevel < 0 || RandomizationLevel > 2) RandomizationLevel = 1;
			break;
		case 'g':
			if (GetGid()) return !0;
			break;
		case 'u':
			if (GetUid()) return !0;
			break;
		case 'P':
			break;
		default:
			Usage(argv[0]);
			return !0;
	}

	if (optind != argc)
	{
		Usage(argv[0]);
		return !0;
	}

	int allocsockets = maxsockets ? maxsockets : 2;
	SocketList = malloc(allocsockets * sizeof(SOCKET));

#if defined(__BSD__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
	optind = 1;
	optreset = 1; // Makes BSD getopt happy
#else
	optind = 0; // Makes GLIBC getopt happy
#endif

	for (opterr = 0; ( o = getopt(argc, argv, optstring) ) > 0; ) switch (o)
	{
		case 'L':
			AddSocketAddress(optarg);
			break;
		case 'P':
			defaultport = optarg;
			break;
		default:
			break;
	}

	if (!maxsockets)
	{
		if (HaveIPv6Stack && (v6required || !v4required)) AddSocketAddress("::");
		if (HaveIPv4Stack && (v4required || !v6required)) AddSocketAddress("0.0.0.0");
	}

	if (!numsockets)
	{
		fprintf(stderr, "Fatal: Could not listen on any socket.\n");
		return !0;
	}

#ifndef _WIN32
	if ((gid != INVALID_GID && setgid(gid)) || (uid != INVALID_GID && setuid(uid)))
	{
		fprintf(stderr, "Fatal: setgid/setuid for %s failed.\n", optarg);
		return !0;
	}

#endif

	if (RandomizationLevel == 1)
	{
		int i;
		srand((unsigned int)time(NULL));
		int serverType = rand() % _countof(HostOS);
		int16_t lang = LcidList[rand() % _countof(LcidList)];

		for (i = 0; i < _countof(RandomPid); i++)
		{
			GenerateRandomPid(AppList[i].guid, RandomPid[i], serverType, lang);
		}
	}

#ifndef _WIN32 // Windows has no fork or signal handling
	if ( !nodaemon) if (daemon(!0, logstdout))
	{
		fprintf(stderr, "Fatal: Could not daemonize to background.\n");
		return errno;
	}

	{
		struct sigaction sa =
		{
			.sa_handler = SIG_IGN,
			.sa_flags   = SA_NOCLDWAIT
		};

		if ( sigemptyset(&sa.sa_mask) || sigaction(SIGCHLD, &sa, 0) )
			return errno;
	}
#endif

	logger("KMS emulator started successfully\n");

	if (fn_pid)
	{
		FILE *_f = fopen(fn_pid, "w");

		if ( _f ) {
			fprintf(_f, "%u", getpid());
			fclose(_f);
		}
		else
		{
			logger("Warning: Cannot write pid file.\n");
		}
	}

	srand( (int)time(NULL) );

	RpcAssocGroup = rand();

	for (;;)
	{
		socklen_t len;
		struct sockaddr_storage addr;
		SOCKET s_client;

		for (;;) if ( (s_client = network_accept_any(SocketList, numsockets, NULL, NULL)) < 0 )
		{
			if ( errno != EINTR )
				return errno;
		}
		else break;

		RpcAssocGroup++;
		len = sizeof addr;

		if (getsockname(s_client, (struct sockaddr*)&addr, &len) ||
				getnameinfo((struct sockaddr*)&addr, len, NULL, 0, RpcSecondaryAddress, sizeof(RpcSecondaryAddress), NI_NUMERICSERV))
		{
			strcpy(RpcSecondaryAddress, "1688"); // In case of failure use default port (doesn't seem to break activation)
		}

		RpcSecondaryAddressLength = LE16(strlen(RpcSecondaryAddress) + 1);

#ifndef _WIN32
		int pid;
		if ( (pid = fork()) < 0 )
			return errno;

		else if ( pid )
			close(s_client);

		else
#endif
		{
			char ipstr[256], text[256];

			struct timeval to = {
				.tv_sec  = 60,
				.tv_usec = 0
			};

			setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (char*)&to, sizeof(to));
			setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (char*)&to, sizeof(to));
			len = sizeof addr;

			if (getpeername(s_client, (struct sockaddr*)&addr, &len) ||
					!ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len))
			{
				*ipstr = 0;
			}

			char *connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4;
			static char *const cAccepted = "accepted";
			static char *const cClosed = "closed";
			static char *const fIP = "%s connection %s: %s.\n";

			CloseAllListeningSockets();
			sprintf(text, fIP, connection_type, cAccepted, ipstr);
			if (*ipstr) logger(text);
			RpcServer(s_client);
#ifdef _WIN32
			shutdown(s_client, SD_BOTH);
#endif
			close(s_client);

			sprintf(text, fIP, connection_type, cClosed, ipstr);
			if (*ipstr) logger(text);
#ifndef _WIN32
			return 0;
#endif
		}
	}

	unlink(fn_pid);
	CloseAllListeningSockets();
	return 0;
}