// File: /workspace/github_c_makefile_star2_O0/stefpant[P]TCPserver/webserver/webserver.c
// Function: main
int main(int argc,char* argv[]){
	//int err;//thread error
	int s_port,c_port;
	int n_threads = 5;//by default 5 threads
	char *rootdir = NULL;
//	int flagSHUTDOWN=0;//when set 1 exit
//~~~~~~~~~~~~~~~~~~~~~~~~~~PARSE ARGUMENTS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	printf("Parent %ld: just started!\n", pthread_self());
	if(input_parse(argc,argv,&s_port,&c_port,&n_threads,&rootdir) < 0){
		free(rootdir);
		exit(9);
	}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//printf("%s\n",rootdir);
//~~~~~~~~~~~~~~~~~~~~~INIT: pool,mutexes,conditions~~~~~~~~~~~~~~~~~~~~~~~
	reqArray_init(&ra);

	pthread_mutex_init(&mtx, 0);
	pthread_mutex_init(&mtxcounter, 0);
	pthread_mutex_init(&mtxbytes, 0);
	pthread_cond_init(&cv_notempty, 0);
	pthread_cond_init(&cv_notfull, 0);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MAKING THREADS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	pthread_t *tids = NULL;

	tids = malloc(n_threads*sizeof(pthread_t));

	for(int i=0; i<n_threads; i++)//create threads to execute threadExec
		pthread_create(tids+i,NULL,threadExec, (void *)rootdir);

	//test terminating last thread to create new one
	//to test this decrease above for loop by one( i<nthreads-1 )
	//pthread_create(tids+(n_threads-1),NULL,killthread, (void *)rootdir);

	printf("Parent %ld: just created new threads!\n", pthread_self());
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	time_t start,localend;
	int hh,mm,ss;
	time(&start);//server started
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~MAKING SOCKETS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	int s_sock,c_sock,newsock,newcsock;
	struct sockaddr_in server;
	struct sockaddr * serverptr = (struct sockaddr *)&server;
	if( (s_sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0 ) //socket for service port
		{perror("socket");exit(9);}
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(s_port);
	if( setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 },sizeof(int)) < 0 )
		{perror("setsockopt");exit(9);}
	if( bind(s_sock,serverptr,sizeof(server)) < 0 ){perror("bind");exit(9);}
	if( listen(s_sock,100) < 0 ){perror("listen");exit(9);}

	if( (c_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) //socket for command port
		{perror("socket");exit(9);}
	server.sin_port = htons(c_port); //change port
	if( setsockopt(c_sock, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 },sizeof(int)) < 0 )
		{perror("setsockopt");exit(9);}
	if( bind(c_sock,serverptr,sizeof(server)) < 0 ){perror("bind");exit(9);}
	if( listen(c_sock,100) < 0 ){perror("listen");exit(9);}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	struct pollfd pfds[2];
	pfds[0].fd = s_sock;
	pfds[0].events = POLLIN;
	pfds[1].fd = c_sock;
	pfds[1].events = POLLIN;

//~~~~~~~~~~~~~~~~~~~~~~~~~LOOP:ACCEPTING CONNECTIONS~~~~~~~~~~~~~~~~~~~~~~~
	while( 1 ){
//~~~~~~~~~~~~~~~~~~~~~~~~~CHECK IF THREADS ARE ALIVE~~~~~~~~~~~~~~~~~~~~~~~
		for(int i=0; i<n_threads; i++){
			if(pthread_kill(*(tids+i),0) != 0){//thread i died
				printf("Thread with id '%ld' died.\n",*(tids+i));
				pthread_create(tids+i,NULL,threadExec, (void *)rootdir);
				printf("Just created a new one with id '%ld'!\n",*(tids+i));
			}
		}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		poll(pfds,2,-1);//wait a connection
		if(pfds[0].revents & POLLIN){//client connected on service port
			if( (newsock = accept4(s_sock,NULL,NULL,SOCK_NONBLOCK)) < 0)//non blocking fd
				{perror("accept");exit(9);}
			place(&ra, newsock);
			pthread_cond_signal(&cv_notempty);
			//printf("Parent: send fd!\n");
		}
		if(pfds[1].revents & POLLIN){//client on command port
			if( (newcsock = accept(c_sock,NULL,NULL)) < 0)
				{perror("accept");exit(9);}
//			while(1){//1
				char *buf = malloc(9*sizeof(char));//should not be resized
				read_command(newcsock,&buf,9);
				if( !strcmp(buf,"STATS") ){
					time(&localend);
					localend -= start;
					hh = localend/3600;//creating time format
					localend -= hh*3600;
					mm = localend/60;
					ss = localend - mm*60;
					char* statrep=NULL;
					if(asprintf(&statrep,"Server up for %02d:%02d:%02d, served %d pages, %d bytes\n",hh,mm,ss,totalrc,totalBytes) != -1){
						int len=strlen(statrep);
						write(newcsock,statrep,len+1);
						free(statrep);
					}
					//printf("Server up for %02d:%02d:%02d, served %d pages, %d bytes\n",hh,mm,ss,totalrc,totalBytes);
				}
				else if( !strcmp(buf,"SHUTDOWN") ){
					close(newcsock);
					free(buf);
//					flagSHUTDOWN=1;//2
					break;
				}
//				else if( !strcmp(buf,"STOP") ){//3
//					close(newcsock);//4
//					free(buf);//5
//					break;//6
//				}//7
				else
					write(newcsock,"Unknown command!\n",18);
				free(buf);
				close(newcsock);//--8
//			}//9
		}
//		if(flagSHUTDOWN) break;//10
	}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//should clear pool first
	//here if i got SHUTDOWN command to send exit msg(sending -1 in pool)
	for(int i=0; i<n_threads; i++){
		place(&ra,-1);
		pthread_cond_signal(&cv_notempty);
		printf("Parent: send stop!\n");
	}

	for(int i=0; i<n_threads; i++)
		 pthread_join(*(tids+i),NULL);//join threads

	//printf("Finaly counter is %d\n",totalrc);

	//free structs
	pthread_mutex_destroy(&mtx);
	pthread_mutex_destroy(&mtxcounter);
	pthread_mutex_destroy(&mtxbytes);
	pthread_cond_destroy(&cv_notempty);
	pthread_cond_destroy(&cv_notfull);
	reqArray_destroy(&ra);
	close(s_sock);
	close(c_sock);
	free(rootdir);
	free(tids);
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x5, -0x1c(%rbp)
movq $0x0, -0x28(%rbp)
callq 0x2270
movq %rax, %rsi
leaq 0xa68(%rip), %rdi       # 0x433f
movb $0x0, %al
callq 0x2100
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq -0x14(%rbp), %rdx
leaq -0x18(%rbp), %rcx
leaq -0x1c(%rbp), %r8
leaq -0x28(%rbp), %r9
callq 0x3190
cmpl $0x0, %eax
jge 0x3912
movq -0x28(%rbp), %rdi
callq 0x2030
movl $0x9, %edi
callq 0x22f0
leaq 0x293f(%rip), %rdi      # 0x6258
callq 0x3500
leaq 0x28ab(%rip), %rdi      # 0x61d0
xorl %eax, %eax
movl %eax, %esi
callq 0x2320
leaq 0x292b(%rip), %rdi      # 0x6260
xorl %eax, %eax
movl %eax, %esi
callq 0x2320
leaq 0x2943(%rip), %rdi      # 0x6288
xorl %eax, %eax
movl %eax, %esi
callq 0x2320
leaq 0x28d3(%rip), %rdi      # 0x6228
xorl %eax, %eax
movl %eax, %esi
callq 0x21c0
leaq 0x2893(%rip), %rdi      # 0x61f8
xorl %eax, %eax
movl %eax, %esi
callq 0x21c0
movq $0x0, -0x30(%rbp)
movslq -0x1c(%rbp), %rdi
shlq $0x3, %rdi
callq 0x21e0
movq %rax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x39c4
movq -0x30(%rbp), %rdi
movslq -0x34(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x28(%rbp), %rcx
xorl %eax, %eax
movl %eax, %esi
leaq -0x2d4(%rip), %rdx      # 0x36e0
callq 0x2250
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x398e
callq 0x2270
movq %rax, %rsi
leaq 0x987(%rip), %rdi       # 0x435a
movb $0x0, %al
callq 0x2100
leaq -0x40(%rbp), %rdi
callq 0x21b0
leaq -0x74(%rbp), %rax
movq %rax, -0x80(%rbp)
movl $0x2, %edi
movl $0x801, %esi            # imm = 0x801
xorl %edx, %edx
callq 0x2350
movl %eax, -0x58(%rbp)
cmpl $0x0, %eax
jge 0x3a1a
leaq 0x976(%rip), %rdi       # 0x4381
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movw $0x2, -0x74(%rbp)
xorl %edi, %edi
callq 0x2120
movl %eax, -0x70(%rbp)
movl -0x14(%rbp), %eax
movzwl %ax, %edi
callq 0x20f0
movw %ax, -0x72(%rbp)
movl -0x58(%rbp), %edi
movl $0x1, -0x84(%rbp)
movl $0x1, %esi
movl $0x2, %edx
leaq -0x84(%rbp), %rcx
movl $0x4, %r8d
callq 0x2090
cmpl $0x0, %eax
jge 0x3a7d
leaq 0x91a(%rip), %rdi       # 0x4388
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x58(%rbp), %edi
movq -0x80(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
movl $0x10, %edx
callq 0x2240
cmpl $0x0, %eax
jge 0x3ab7
leaq 0x8eb(%rip), %rdi       # 0x4393
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x58(%rbp), %edi
movl $0x64, %esi
callq 0x21f0
cmpl $0x0, %eax
jge 0x3adf
leaq 0x8c8(%rip), %rdi       # 0x4398
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2350
movl %eax, -0x5c(%rbp)
cmpl $0x0, %eax
jge 0x3b0e
leaq 0x882(%rip), %rdi       # 0x4381
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x18(%rbp), %eax
movzwl %ax, %edi
callq 0x20f0
movw %ax, -0x72(%rbp)
movl -0x5c(%rbp), %edi
movl $0x1, -0x94(%rbp)
movl $0x1, %esi
movl $0x2, %edx
leaq -0x94(%rbp), %rcx
movl $0x4, %r8d
callq 0x2090
cmpl $0x0, %eax
jge 0x3b61
leaq 0x836(%rip), %rdi       # 0x4388
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x5c(%rbp), %edi
movq -0x80(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rsi
movl $0x10, %edx
callq 0x2240
cmpl $0x0, %eax
jge 0x3b9b
leaq 0x807(%rip), %rdi       # 0x4393
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x5c(%rbp), %edi
movl $0x64, %esi
callq 0x21f0
cmpl $0x0, %eax
jge 0x3bc3
leaq 0x7e4(%rip), %rdi       # 0x4398
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x58(%rbp), %eax
movl %eax, -0xb0(%rbp)
movw $0x1, -0xac(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0xa8(%rbp)
movw $0x1, -0xa4(%rbp)
movl $0x0, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x3c91
movq -0x30(%rbp), %rax
movslq -0xb4(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %esi, %esi
callq 0x2180
cmpl $0x0, %eax
je 0x3c7b
movq -0x30(%rbp), %rax
movslq -0xb4(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x76e(%rip), %rdi       # 0x439f
movb $0x0, %al
callq 0x2100
movq -0x30(%rbp), %rdi
movslq -0xb4(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x28(%rbp), %rcx
xorl %eax, %eax
movl %eax, %esi
leaq -0x579(%rip), %rdx      # 0x36e0
callq 0x2250
movq -0x30(%rbp), %rax
movslq -0xb4(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x747(%rip), %rdi       # 0x43bb
movb $0x0, %al
callq 0x2100
jmp 0x3c7d
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb4(%rbp)
jmp 0x3bf1
leaq -0xb0(%rbp), %rdi
movl $0x2, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x2230
movswl -0xaa(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x3d12
movl -0x58(%rbp), %edi
movq $0x0, -0xc0(%rbp)
movq -0xc0(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
movl $0x800, %ecx            # imm = 0x800
callq 0x20e0
movl %eax, -0x60(%rbp)
cmpl $0x0, %eax
jge 0x3cf7
leaq 0x6fa(%rip), %rdi       # 0x43e2
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl -0x60(%rbp), %esi
leaq 0x2557(%rip), %rdi      # 0x6258
callq 0x35a0
leaq 0x251b(%rip), %rdi      # 0x6228
callq 0x2160
movswl -0xa2(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x3ed4
movl -0x5c(%rbp), %edi
movq $0x0, -0xc8(%rbp)
movq -0xc8(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x22c0
movl %eax, -0x64(%rbp)
cmpl $0x0, %eax
jge 0x3d61
leaq 0x690(%rip), %rdi       # 0x43e2
callq 0x22b0
movl $0x9, %edi
callq 0x22f0
movl $0x9, %edi
callq 0x21e0
movq %rax, -0xd0(%rbp)
movl -0x64(%rbp), %edi
leaq -0xd0(%rbp), %rsi
movl $0x9, %edx
callq 0x27f0
movq -0xd0(%rbp), %rdi
leaq 0x655(%rip), %rsi       # 0x43e9
callq 0x2190
cmpl $0x0, %eax
jne 0x3e7c
leaq -0x48(%rbp), %rdi
callq 0x21b0
movq -0x40(%rbp), %rcx
movq -0x48(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl $0xe10, %ecx            # imm = 0xE10
cqto
idivq %rcx
movl %eax, -0x4c(%rbp)
imull $0xe10, -0x4c(%rbp), %eax # imm = 0xE10
movslq %eax, %rcx
movq -0x48(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl $0x3c, %ecx
cqto
idivq %rcx
movl %eax, -0x50(%rbp)
movq -0x48(%rbp), %rax
imull $0x3c, -0x50(%rbp), %ecx
movslq %ecx, %rcx
subq %rcx, %rax
movl %eax, -0x54(%rbp)
movq $0x0, -0xd8(%rbp)
movl -0x4c(%rbp), %edx
movl -0x50(%rbp), %ecx
movl -0x54(%rbp), %r8d
movl 0x23aa(%rip), %r9d      # 0x61c8
movl 0x23a8(%rip), %eax      # 0x61cc
leaq -0xd8(%rbp), %rdi
leaq 0x5bd(%rip), %rsi       # 0x43ef
movl %eax, (%rsp)
movb $0x0, %al
callq 0x2220
cmpl $-0x1, %eax
je 0x3e7a
movq -0xd8(%rbp), %rdi
callq 0x20d0
movl %eax, -0xdc(%rbp)
movl -0x64(%rbp), %edi
movq -0xd8(%rbp), %rsi
movl -0xdc(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rdx
callq 0x20a0
movq -0xd8(%rbp), %rdi
callq 0x2030
jmp 0x3ec0
movq -0xd0(%rbp), %rdi
leaq 0x59e(%rip), %rsi       # 0x4428
callq 0x2190
cmpl $0x0, %eax
jne 0x3eaa
movl -0x64(%rbp), %edi
callq 0x2140
movq -0xd0(%rbp), %rdi
callq 0x2030
jmp 0x3ed9
movl -0x64(%rbp), %edi
leaq 0x57d(%rip), %rsi       # 0x4431
movl $0x12, %edx
callq 0x20a0
jmp 0x3ec0
movq -0xd0(%rbp), %rdi
callq 0x2030
movl -0x64(%rbp), %edi
callq 0x2140
jmp 0x3be7
movl $0x0, -0xe0(%rbp)
movl -0xe0(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x3f2a
leaq 0x2363(%rip), %rdi      # 0x6258
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x35a0
leaq 0x2322(%rip), %rdi      # 0x6228
callq 0x2160
leaq 0x531(%rip), %rdi       # 0x4443
movb $0x0, %al
callq 0x2100
movl -0xe0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe0(%rbp)
jmp 0x3ee3
movl $0x0, -0xe4(%rbp)
movl -0xe4(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x3f68
movq -0x30(%rbp), %rax
movslq -0xe4(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2300
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
jmp 0x3f34
leaq 0x2261(%rip), %rdi      # 0x61d0
callq 0x2110
leaq 0x22e5(%rip), %rdi      # 0x6260
callq 0x2110
leaq 0x2301(%rip), %rdi      # 0x6288
callq 0x2110
leaq 0x2295(%rip), %rdi      # 0x6228
callq 0x2280
leaq 0x2259(%rip), %rdi      # 0x61f8
callq 0x2280
leaq 0x22ad(%rip), %rdi      # 0x6258
callq 0x3570
movl -0x58(%rbp), %edi
callq 0x2140
movl -0x5c(%rbp), %edi
callq 0x2140
movq -0x28(%rbp), %rdi
callq 0x2030
movq -0x30(%rbp), %rdi
callq 0x2030
xorl %eax, %eax
addq $0xf0, %rsp
popq %rbp
retq