// File: /workspace/github_cpp_makefile_star2_O2/BruceHu1005[P]np-assignment1/servermain.cpp
// Function: main
int main(int argc, char *argv[]){
  
  /* Do more magic */
  int listen_fd;//to create socket
	int conn_fd;//to accept connection
	struct sockaddr_in serv_addr;//server receive on this address
	struct sockaddr_in client_addr;//server sends to client on this address
	struct sockaddr_storage their_addr;
	int recv_num;
	int send_num;
	char send_buf[BUFF_LEN] = "TEXT TCP 1.0, Enter OK to start!";
	char recv_buf[BUFF_LEN];
	socklen_t clientAddressLength;

  listen_fd=socket(AF_INET,SOCK_STREAM,0); 	 //create socket
	memset(&serv_addr,0,sizeof(serv_addr)); //initialize the socket addresses
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_addr.sin_port=htons(PORT);

  bind(listen_fd,(struct sockaddr *)&serv_addr, sizeof(serv_addr));
	listen(listen_fd,1);

  while(1) {
		printf("server wait:\n");
		clientAddressLength=sizeof(client_addr);
		conn_fd=accept(listen_fd,(struct sockaddr*)&client_addr, &clientAddressLength);
   
    //rceive from client
		send_num = send(conn_fd, send_buf, strlen(send_buf), 0);
		if (send_num < 0)
		{
			perror("send error:");
			exit(1);
		}
		recv_num = recv(conn_fd, recv_buf, sizeof(recv_buf), 0);
		if (recv_buf[0] == 'O'&&recv_buf[1] == 'K') {
			recv_buf[recv_num] = '\0';
			printf("server receive %d bytes: %s\n", recv_num, recv_buf);
			initCalcLib();
			char *ptr;
			ptr = randomType(); // Get a random arithemtic operator. 

			double f1, f2, fresult;
			int i1, i2, iresult;

			/* Act differently depending on what operator you got, judge type by first char in string. If 'f' then a float */

			if (ptr[0] == 'f') {
				printf("Float\t");
				f1 = randomFloat();
				f2 = randomFloat();

				/* At this point, ptr holds operator, f1 and f2 the operands. Now we work to determine the reference result. */

				if (strcmp(ptr, "fadd") == 0) {
					fresult = f1 + f2;
				}
				else if (strcmp(ptr, "fsub") == 0) {
					fresult = f1 - f2;
				}
				else if (strcmp(ptr, "fmul") == 0) {
					fresult = f1 * f2;
				}
				else if (strcmp(ptr, "fdiv") == 0) {
					fresult = f1 / f2;
				}
				printf("%s %8.8g %8.8g = %8.8g\n", ptr, f1, f2, fresult);
				char str[100];
				sprintf(str, "%s %8.8g %8.8g", ptr, f1, f2);
				send_num = send(conn_fd, str, strlen(str), 0);
				if (send_num < 0)
				{
					perror("sendto error:");
					exit(1);
				}
				recv_num = recv(conn_fd, recv_buf, sizeof(recv_buf), 0);
				if (recv_num < 0)
				{
					perror("recvfrom error:");
					exit(1);
				}
				recv_buf[recv_num] = '\0';
				printf("server receive %d bytes: %s\n", recv_num, recv_buf);
				
				char grade[20];
				if (fabs(stod(recv_buf)-fresult)<0.0001) {

					sprintf(grade, "%s", "OK");

				}
				else
				{
					sprintf(grade, "%s%8.8g", "ERROR, Right answer is ", fresult);
				}
				send_num = send(conn_fd, grade, strlen(grade), 0);
			}
			else {
				printf("Int\t");
				i1 = randomInt();
				i2 = randomInt();

				if (strcmp(ptr, "add") == 0) {
					iresult = i1 + i2;
				}
				else if (strcmp(ptr, "sub") == 0) {
					iresult = i1 - i2;
				}
				else if (strcmp(ptr, "mul") == 0) {
					iresult = i1 * i2;
				}
				else if (strcmp(ptr, "div") == 0) {
					iresult = i1 / i2;
				}

				printf("%s %d %d = %d \n", ptr, i1, i2, iresult);
				char str[100];
				sprintf(str, "%s %d %d", ptr, i1, i2);
				send_num = send(conn_fd, str, strlen(str), 0);
				if (send_num < 0)
				{
					perror("sendto error:");
					exit(1);
				}
				
				recv_num = recv(conn_fd, recv_buf, sizeof(recv_buf), 0);
				recv_buf[recv_num] = '\0';
				printf("server receive %d bytes: %s\n", recv_num, recv_buf);
				
				char grade[20];
				if (abs((stod(recv_buf)) - iresult) < 0.0001) {

					sprintf(grade, "%s", "OK");

				}
				else
				{
					sprintf(grade, "%s%d", "ERROR, Right answer is ", iresult);
				}
				send_num = send(conn_fd, grade, strlen(grade), 0);
				close(conn_fd);
			}

		}
		else {
			char buf[20]="disconnected";
			printf("Client refused connection\n");
			send_num = send(conn_fd, buf, strlen(buf), 0);
			close(conn_fd);
		}

	}
	close(listen_fd);
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4f8, %rsp            # imm = 0x4F8
leaq 0xd98(%rip), %rsi       # 0x2160
leaq -0x520(%rbp), %rbx
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
callq 0x1100
pushq $0x2
popq %rdi
pushq $0x1
popq %r15
movl %r15d, %esi
xorl %edx, %edx
callq 0x1070
movl %eax, %r14d
leaq -0xb8(%rbp), %rsi
andq $0x0, 0x8(%rsi)
movq $0x401f0002, (%rsi)     # imm = 0x401F0002
pushq $0x10
popq %rdx
movl %eax, %edi
callq 0x1050
movl %r14d, %edi
movl %r15d, %esi
callq 0x1150
leaq 0xd0f(%rip), %r15       # 0x212e
leaq -0x120(%rbp), %r12
movl %r14d, -0x4c(%rbp)
movq %r15, %rdi
callq 0x11a0
movl $0x10, -0x5c(%rbp)
movl %r14d, %edi
leaq -0xa8(%rbp), %rsi
leaq -0x5c(%rbp), %rdx
callq 0x1090
movl %eax, %r13d
movq %rbx, %rdi
callq 0x10b0
movl %r13d, %edi
movq %rbx, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
testl %eax, %eax
js 0x1916
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
leaq -0x320(%rbp), %rsi
xorl %ecx, %ecx
callq 0x10a0
cmpb $0x4f, -0x320(%rbp)
jne 0x1497
cmpb $0x4b, -0x31f(%rbp)
je 0x14df
movapd 0xec1(%rip), %xmm0      # 0x2360
movapd %xmm0, -0x120(%rbp)
andl $0x0, -0x110(%rbp)
leaq 0xc86(%rip), %rdi       # 0x213b
callq 0x11a0
movq %r12, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
movl %r13d, %edi
callq 0x11d0
jmp 0x142a
movslq %eax, %rsi
movb $0x0, -0x320(%rbp,%rsi)
leaq 0xb5f(%rip), %rdi       # 0x2050
leaq -0x320(%rbp), %rdx
xorl %eax, %eax
callq 0x1040
callq 0x131c
callq 0x134d
movq %rax, %r15
cmpb $0x66, (%rax)
je 0x170c
leaq 0xbc0(%rip), %rdi       # 0x20dc
xorl %eax, %eax
callq 0x1040
callq 0x136c
movl %eax, -0x40(%rbp)
callq 0x136c
movl %eax, %r14d
movq %r15, %rdi
leaq 0xaf9(%rip), %rsi       # 0x2036
callq 0x1170
testl %eax, %eax
movq %r15, %rbx
je 0x1598
movq %rbx, %rdi
leaq 0xade(%rip), %rsi       # 0x2031
callq 0x1170
testl %eax, %eax
je 0x15a6
movq %rbx, %rdi
leaq 0xada(%rip), %rsi       # 0x2040
callq 0x1170
testl %eax, %eax
je 0x15b4
movq %rbx, %r15
movq %rbx, %rdi
leaq 0xabf(%rip), %rsi       # 0x203b
callq 0x1170
testl %eax, %eax
movl -0x50(%rbp), %r8d
movl -0x40(%rbp), %edx
jne 0x15c1
movsbl %dl, %eax
idivb %r14b
movsbl %al, %r8d
jmp 0x15c1
movq %rbx, %r15
movl %r14d, %r8d
movl -0x40(%rbp), %edx
addl %edx, %r8d
jmp 0x15c1
movq %rbx, %r15
movl -0x40(%rbp), %edx
movl %edx, %r8d
subl %r14d, %r8d
jmp 0x15c1
movq %rbx, %r15
movl %r14d, %r8d
movl -0x40(%rbp), %edx
imull %edx, %r8d
leaq 0xb19(%rip), %rdi       # 0x20e1
movq %r15, %rbx
movq %r15, %rsi
movl %edx, %r15d
movl %r14d, %ecx
movl %r8d, -0x50(%rbp)
xorl %eax, %eax
callq 0x1040
movq %r12, %rdi
leaq 0xb08(%rip), %rsi       # 0x20f1
movq %rbx, %rdx
movl %r15d, %ecx
movl %r14d, %r8d
xorl %eax, %eax
callq 0x1060
movq %r12, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
testl %eax, %eax
js 0x192a
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
leaq -0x320(%rbp), %rbx
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x10a0
movslq %eax, %rsi
movb $0x0, -0x320(%rbp,%rsi)
leaq 0xa0c(%rip), %rdi       # 0x2050
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1040
leaq -0x98(%rbp), %r15
movq %r15, %rdi
movq %rbx, %rsi
leaq -0x29(%rbp), %rdx
callq 0x197a
movq %r15, %rdi
xorl %esi, %esi
callq 0x195c
movl -0x50(%rbp), %ebx
cvtsi2sd %ebx, %xmm1
subsd %xmm1, %xmm0
andpd 0x99f(%rip), %xmm0      # 0x2020
movapd %xmm0, -0x40(%rbp)
movq %r15, %rdi
callq 0x10c0
movsd 0x97a(%rip), %xmm0      # 0x2010
ucomisd -0x40(%rbp), %xmm0
jbe 0x16b4
movb $0x0, -0x6e(%rbp)
movw $0x4b4f, -0x70(%rbp)    # imm = 0x4B4F
leaq 0xa80(%rip), %r15       # 0x212e
leaq -0x70(%rbp), %rbx
jmp 0x16dc
leaq -0x70(%rbp), %r15
movq %r15, %rdi
leaq 0xa38(%rip), %rsi       # 0x20fa
leaq 0x9fb(%rip), %rdx       # 0x20c4
movl %ebx, %ecx
xorl %eax, %eax
callq 0x1060
movq %r15, %rbx
leaq 0xa52(%rip), %r15       # 0x212e
movl -0x4c(%rbp), %r14d
movq %rbx, %rdi
callq 0x10b0
movl %r13d, %edi
movq %rbx, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
movl %r13d, %edi
callq 0x11d0
leaq -0x520(%rbp), %rbx
jmp 0x142a
leaq 0x95a(%rip), %rdi       # 0x206d
xorl %eax, %eax
callq 0x1040
callq 0x137f
movsd %xmm0, -0x40(%rbp)
callq 0x137f
movsd %xmm0, -0x48(%rbp)
movq %r15, %rdi
leaq 0x8fd(%rip), %rsi       # 0x2035
callq 0x1170
testl %eax, %eax
movq %r15, -0x78(%rbp)
je 0x1797
movq %r15, %rdi
leaq 0x8e1(%rip), %rsi       # 0x2030
callq 0x1170
testl %eax, %eax
je 0x17ab
movq %r15, %rdi
leaq 0x8dd(%rip), %rsi       # 0x203f
callq 0x1170
testl %eax, %eax
je 0x17bf
movq %r15, %rdi
leaq 0x8c5(%rip), %rsi       # 0x203a
callq 0x1170
testl %eax, %eax
movsd -0x58(%rbp), %xmm2
movsd -0x40(%rbp), %xmm0
movsd -0x48(%rbp), %xmm1
jne 0x17d1
movapd %xmm0, %xmm2
divsd %xmm1, %xmm2
jmp 0x17d1
movsd -0x40(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x48(%rbp), %xmm1
addsd %xmm1, %xmm2
jmp 0x17d1
movsd -0x40(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x48(%rbp), %xmm1
subsd %xmm1, %xmm2
jmp 0x17d1
movsd -0x40(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x48(%rbp), %xmm1
mulsd %xmm1, %xmm2
leaq 0x89c(%rip), %rdi       # 0x2074
movq -0x78(%rbp), %r15
movq %r15, %rsi
movsd %xmm2, -0x58(%rbp)
movb $0x3, %al
callq 0x1040
movq %r12, %rdi
leaq 0x897(%rip), %rsi       # 0x208c
movq %r15, %rdx
movsd -0x40(%rbp), %xmm0
movsd -0x48(%rbp), %xmm1
movb $0x2, %al
callq 0x1060
movq %r12, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
testl %eax, %eax
js 0x192a
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
leaq -0x320(%rbp), %r15
movq %r15, %rsi
xorl %ecx, %ecx
callq 0x10a0
testl %eax, %eax
js 0x1933
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
movb $0x0, -0x320(%rbp,%rcx)
leaq 0x7ef(%rip), %rdi       # 0x2050
movl %eax, %esi
movq %r15, %rdx
xorl %eax, %eax
callq 0x1040
movq %r15, %rsi
leaq -0x98(%rbp), %r15
movq %r15, %rdi
leaq -0x29(%rbp), %rdx
callq 0x197a
movq %r15, %rdi
xorl %esi, %esi
callq 0x195c
subsd -0x58(%rbp), %xmm0
andpd 0x786(%rip), %xmm0      # 0x2020
movapd %xmm0, -0x40(%rbp)
movq %r15, %rdi
callq 0x10c0
movsd 0x761(%rip), %xmm0      # 0x2010
ucomisd -0x40(%rbp), %xmm0
jbe 0x18cd
movb $0x0, -0x6e(%rbp)
movw $0x4b4f, -0x70(%rbp)    # imm = 0x4B4F
leaq 0x867(%rip), %r15       # 0x212e
leaq -0x70(%rbp), %rax
jmp 0x18f8
leaq -0x70(%rbp), %r15
movq %r15, %rdi
leaq 0x7e1(%rip), %rsi       # 0x20bc
leaq 0x7e2(%rip), %rdx       # 0x20c4
movsd -0x58(%rbp), %xmm0
movb $0x1, %al
callq 0x1060
movq %r15, %rax
leaq 0x836(%rip), %r15       # 0x212e
movq %rax, %rdi
callq 0x10b0
movl %r13d, %edi
leaq -0x70(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10d0
jmp 0x142a
leaq 0x727(%rip), %rdi       # 0x2044
callq 0x1110
pushq $0x1
popq %rdi
callq 0x1160
leaq 0x76a(%rip), %rdi       # 0x209b
jmp 0x191d
leaq 0x76f(%rip), %rdi       # 0x20a9
jmp 0x191d
jmp 0x1940
jmp 0x1951
movq %rax, %rbx
leaq -0x98(%rbp), %rdi
callq 0x10c0
jmp 0x1954
movq %rax, %rbx
movq %rbx, %rdi
callq 0x11b0