/* * 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; } } } }
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; }