// File: /workspace/github_cpp_makefile_star2_O3/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 $0x508, %rsp            # imm = 0x508
leaq 0xd6f(%rip), %rsi       # 0x2160
leaq -0x530(%rbp), %r14
movl $0x200, %edx            # imm = 0x200
movq %r14, %rdi
callq 0x1100
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x1070
movl %eax, %ebx
leaq -0xc0(%rbp), %rsi
movq $0x0, 0x8(%rsi)
movq $0x401f0002, (%rsi)     # imm = 0x401F0002
movl %eax, %edi
movl $0x10, %edx
callq 0x1050
movl %ebx, -0x84(%rbp)
movl %ebx, %edi
movl $0x1, %esi
callq 0x1160
leaq 0xcdb(%rip), %rbx       # 0x212e
leaq -0xb0(%rbp), %r15
movq %rbx, %rdi
callq 0x11b0
movl $0x10, -0x88(%rbp)
movl -0x84(%rbp), %edi
movq %r15, %rsi
leaq -0x88(%rbp), %rdx
callq 0x1090
movl %eax, %r13d
movq %r14, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r14, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10c0
testl %eax, %eax
js 0x1a69
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
leaq -0x330(%rbp), %rsi
xorl %ecx, %ecx
callq 0x10a0
cmpb $0x4f, -0x330(%rbp)
jne 0x14cc
cmpb $0x4b, -0x32f(%rbp)
je 0x151e
movapd 0xe8c(%rip), %xmm0      # 0x2360
movapd %xmm0, -0x130(%rbp)
movl $0x0, -0x120(%rbp)
leaq 0xc4e(%rip), %rdi       # 0x213b
callq 0x11b0
leaq -0x130(%rbp), %r12
movq %r12, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10c0
movl %r13d, %edi
callq 0x11e0
jmp 0x145a
movslq %eax, %rsi
movb $0x0, -0x330(%rbp,%rsi)
leaq 0xb20(%rip), %rdi       # 0x2050
leaq -0x330(%rbp), %rbx
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1040
leaq 0x2c20(%rip), %rdi      # 0x4168
callq 0x1130
movl %eax, %edi
callq 0x1140
callq 0x1080
leal 0x7(%rax), %ecx
testl %eax, %eax
cmovnsl %eax, %ecx
andl $-0x8, %ecx
subl %ecx, %eax
cltq
leaq 0x2ba1(%rip), %rcx      # 0x4110
movq (%rcx,%rax,8), %r15
cmpb $0x66, (%r15)
je 0x17d4
leaq 0xb58(%rip), %rdi       # 0x20dc
xorl %eax, %eax
callq 0x1040
callq 0x1080
movslq %eax, %r12
imulq $0x51eb851f, %r12, %rax # imm = 0x51EB851F
movq %rax, %rcx
shrq $0x3f, %rcx
sarq $0x25, %rax
addl %ecx, %eax
imull $0x64, %eax, %eax
subl %eax, %r12d
callq 0x1080
movslq %eax, %rbx
imulq $0x51eb851f, %rbx, %rax # imm = 0x51EB851F
movq %rax, %rcx
shrq $0x3f, %rcx
sarq $0x25, %rax
addl %ecx, %eax
imull $0x64, %eax, %eax
subl %eax, %ebx
movq %r15, %rdi
leaq 0xa5e(%rip), %rsi       # 0x2036
callq 0x1180
testl %eax, %eax
movl -0x2c(%rbp), %eax
je 0x1630
movl %eax, -0x2c(%rbp)
movq %r15, %rdi
leaq 0xa40(%rip), %rsi       # 0x2031
callq 0x1180
testl %eax, %eax
je 0x1636
movq %r15, %rdi
leaq 0xa3c(%rip), %rsi       # 0x2040
callq 0x1180
testl %eax, %eax
je 0x163e
movq %r15, %rdi
leaq 0xa24(%rip), %rsi       # 0x203b
callq 0x1180
testl %eax, %eax
movl -0x2c(%rbp), %r8d
jne 0x1645
movsbl %r12b, %eax
idivb %bl
movsbl %al, %r8d
jmp 0x1645
leal (%rbx,%r12), %r8d
jmp 0x1645
movl %r12d, %r8d
subl %ebx, %r8d
jmp 0x1645
movl %ebx, %r8d
imull %r12d, %r8d
leaq 0xa95(%rip), %rdi       # 0x20e1
movq %r15, %rsi
movl %r12d, %edx
movl %ebx, %ecx
movl %r8d, -0x2c(%rbp)
xorl %eax, %eax
callq 0x1040
movq %r15, %rdx
leaq -0x130(%rbp), %r15
movq %r15, %rdi
leaq 0xa7e(%rip), %rsi       # 0x20f1
movl %r12d, %ecx
movl %ebx, %r8d
xorl %eax, %eax
callq 0x1060
movq %r15, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r15, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10c0
testl %eax, %eax
js 0x1a7f
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
leaq -0x330(%rbp), %rbx
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x10a0
movslq %eax, %rsi
movb $0x0, -0x330(%rbp,%rsi)
leaq 0x985(%rip), %rdi       # 0x2050
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1040
leaq -0x68(%rbp), %rax
movq %rax, -0x78(%rbp)
movq %rbx, %rdi
callq 0x10b0
leaq (%rax,%rbp), %rdx
addq $-0x330, %rdx           # imm = 0xFCD0
leaq -0x78(%rbp), %rdi
movq %rbx, %rsi
callq 0x1af8
movq -0x78(%rbp), %rbx
callq 0x1030
movq %rax, %r15
movl (%rax), %r12d
movl $0x0, (%rax)
movq %rbx, %rdi
leaq -0x80(%rbp), %rsi
callq 0x10f0
cmpq %rbx, -0x80(%rbp)
je 0x1a88
movapd %xmm0, %xmm1
movl (%r15), %eax
testl %eax, %eax
je 0x173c
cmpl $0x22, %eax
jne 0x173f
jmp 0x1a94
movl %r12d, (%r15)
movq -0x78(%rbp), %rdi
leaq -0x68(%rbp), %rax
cmpq %rax, %rdi
je 0x1762
movq -0x68(%rbp), %rsi
incq %rsi
movapd %xmm1, -0x50(%rbp)
callq 0x1150
movapd -0x50(%rbp), %xmm1
movl -0x2c(%rbp), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
subsd %xmm0, %xmm1
andpd 0x8a8(%rip), %xmm1      # 0x2020
movsd 0x890(%rip), %xmm0      # 0x2010
ucomisd %xmm1, %xmm0
leaq 0x9a3(%rip), %rbx       # 0x212e
leaq -0xb0(%rbp), %r15
jbe 0x17b0
movb $0x0, -0x9e(%rbp)
movw $0x4b4f, -0xa0(%rbp)    # imm = 0x4B4F
leaq -0xa0(%rbp), %r12
jmp 0x14f9
leaq -0xa0(%rbp), %r12
movq %r12, %rdi
leaq 0x939(%rip), %rsi       # 0x20fa
leaq 0x8fc(%rip), %rdx       # 0x20c4
xorl %eax, %eax
callq 0x1060
jmp 0x14f9
leaq 0x892(%rip), %rdi       # 0x206d
xorl %eax, %eax
callq 0x1040
callq 0x1080
cvtsi2sd %eax, %xmm1
movsd 0x815(%rip), %xmm0      # 0x2008
divsd %xmm0, %xmm1
movsd %xmm1, -0x50(%rbp)
callq 0x1080
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0x7f8(%rip), %xmm0      # 0x2008
movsd %xmm0, -0x38(%rbp)
movq %r15, %rdi
leaq 0x816(%rip), %rsi       # 0x2035
callq 0x1180
testl %eax, %eax
je 0x187a
movq %r15, %rdi
leaq 0x7fe(%rip), %rsi       # 0x2030
callq 0x1180
testl %eax, %eax
je 0x188e
movq %r15, %rdi
leaq 0x7fa(%rip), %rsi       # 0x203f
callq 0x1180
testl %eax, %eax
je 0x18a2
movq %r15, %rdi
leaq 0x7e2(%rip), %rsi       # 0x203a
callq 0x1180
testl %eax, %eax
movsd -0x58(%rbp), %xmm2
movsd -0x50(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
jne 0x18b4
movapd %xmm0, %xmm2
divsd %xmm1, %xmm2
jmp 0x18b4
movsd -0x50(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x38(%rbp), %xmm1
addsd %xmm1, %xmm2
jmp 0x18b4
movsd -0x50(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x38(%rbp), %xmm1
subsd %xmm1, %xmm2
jmp 0x18b4
movsd -0x50(%rbp), %xmm0
movapd %xmm0, %xmm2
movsd -0x38(%rbp), %xmm1
mulsd %xmm1, %xmm2
leaq 0x7b9(%rip), %rdi       # 0x2074
movq %r15, %rsi
movsd %xmm2, -0x58(%rbp)
movb $0x3, %al
callq 0x1040
movq %r15, %rdx
leaq -0x130(%rbp), %r15
movq %r15, %rdi
leaq 0x7ae(%rip), %rsi       # 0x208c
movsd -0x50(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
movb $0x2, %al
callq 0x1060
movq %r15, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r15, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10c0
testl %eax, %eax
js 0x1a7f
movl $0x200, %edx            # imm = 0x200
movl %r13d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x10a0
testl %eax, %eax
js 0x1aa0
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
movb $0x0, -0x330(%rbp,%rcx)
leaq 0x710(%rip), %rdi       # 0x2050
movl %eax, %esi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x1040
leaq -0x68(%rbp), %rax
movq %rax, -0x78(%rbp)
movq %rbx, %rdi
callq 0x10b0
leaq (%rax,%rbp), %rdx
addq $-0x330, %rdx           # imm = 0xFCD0
leaq -0x78(%rbp), %rdi
movq %rbx, %rsi
callq 0x1af8
movq -0x78(%rbp), %rbx
callq 0x1030
movq %rax, %r15
movl (%rax), %r12d
movl $0x0, (%rax)
movq %rbx, %rdi
leaq -0x80(%rbp), %rsi
callq 0x10f0
cmpq %rbx, -0x80(%rbp)
je 0x1aa9
movapd %xmm0, %xmm2
movl (%r15), %eax
testl %eax, %eax
je 0x19b8
cmpl $0x22, %eax
movsd -0x58(%rbp), %xmm1
jne 0x19c0
jmp 0x1ab5
movl %r12d, (%r15)
movsd -0x58(%rbp), %xmm1
movq -0x78(%rbp), %rdi
leaq -0x68(%rbp), %rax
cmpq %rax, %rdi
je 0x19e8
movq -0x68(%rbp), %rsi
incq %rsi
movapd %xmm2, -0x50(%rbp)
callq 0x1150
movapd -0x50(%rbp), %xmm2
movsd -0x58(%rbp), %xmm1
subsd %xmm1, %xmm2
andpd 0x62c(%rip), %xmm2      # 0x2020
movsd 0x614(%rip), %xmm0      # 0x2010
ucomisd %xmm2, %xmm0
leaq 0x727(%rip), %rbx       # 0x212e
leaq -0xb0(%rbp), %r15
jbe 0x1a29
movb $0x0, -0x9e(%rbp)
movw $0x4b4f, -0xa0(%rbp)    # imm = 0x4B4F
leaq -0xa0(%rbp), %r12
jmp 0x1a4c
leaq -0xa0(%rbp), %r12
movq %r12, %rdi
leaq 0x682(%rip), %rsi       # 0x20bc
leaq 0x683(%rip), %rdx       # 0x20c4
movapd %xmm1, %xmm0
movb $0x1, %al
callq 0x1060
movq %r12, %rdi
callq 0x10b0
movl %r13d, %edi
movq %r12, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x10c0
jmp 0x145a
leaq 0x5d4(%rip), %rdi       # 0x2044
callq 0x1110
movl $0x1, %edi
callq 0x1170
leaq 0x615(%rip), %rdi       # 0x209b
jmp 0x1a70
leaq 0x670(%rip), %rdi       # 0x20ff
callq 0x10d0
leaq 0x664(%rip), %rdi       # 0x20ff
callq 0x1190
leaq 0x602(%rip), %rdi       # 0x20a9
jmp 0x1a70
leaq 0x64f(%rip), %rdi       # 0x20ff
callq 0x10d0
leaq 0x643(%rip), %rdi       # 0x20ff
callq 0x1190
jmp 0x1ac5
jmp 0x1aca
movq %rax, %rbx
jmp 0x1aef
movq %rax, %rbx
cmpl $0x0, (%r15)
jne 0x1ad6
movl %r12d, (%r15)
movq -0x78(%rbp), %rdi
leaq -0x68(%rbp), %rax
cmpq %rax, %rdi
je 0x1aef
movq -0x68(%rbp), %rsi
incq %rsi
callq 0x1150
movq %rbx, %rdi
callq 0x11c0
nop