// File: 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
subq $0x730, %rsp            # imm = 0x730
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x2c0(%rbp), %rdi
leaq 0x1be9(%rip), %rsi      # 0x4160
movl $0x200, %edx            # imm = 0x200
callq 0x2190
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2090
movl %eax, -0x14(%rbp)
leaq -0x28(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x2120
movw $0x2, -0x28(%rbp)
xorl %edi, %edi
callq 0x2170
movl %eax, -0x24(%rbp)
movl $0x1f40, %edi           # imm = 0x1F40
callq 0x2050
movw %ax, -0x26(%rbp)
movl -0x14(%rbp), %edi
leaq -0x28(%rbp), %rsi
movl $0x10, %edx
callq 0x2060
movl -0x14(%rbp), %edi
movl $0x1, %esi
callq 0x2230
leaq 0x1a5c(%rip), %rdi      # 0x4044
movb $0x0, %al
callq 0x2040
movl $0x10, -0x4c4(%rbp)
movl -0x14(%rbp), %edi
leaq -0x38(%rbp), %rsi
leaq -0x4c4(%rbp), %rdx
callq 0x20c0
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x68c(%rbp)
leaq -0x2c0(%rbp), %rax
movq %rax, -0x688(%rbp)
leaq -0x2c0(%rbp), %rdi
callq 0x2100
movl -0x68c(%rbp), %edi
movq -0x688(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
cmpl $0x0, -0xc0(%rbp)
jge 0x266e
leaq 0x19f3(%rip), %rdi      # 0x4052
callq 0x21a0
movl $0x1, %edi
callq 0x2240
movl -0x18(%rbp), %edi
leaq -0x4c0(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
xorl %ecx, %ecx
callq 0x20d0
movl %eax, -0xbc(%rbp)
movsbl -0x4c0(%rbp), %eax
cmpl $0x4f, %eax
jne 0x2dc5
movsbl -0x4bf(%rbp), %eax
cmpl $0x4b, %eax
jne 0x2dc5
movslq -0xbc(%rbp), %rax
movb $0x0, -0x4c0(%rbp,%rax)
movl -0xbc(%rbp), %esi
leaq -0x4c0(%rbp), %rdx
leaq 0x1991(%rip), %rdi      # 0x405e
movb $0x0, %al
callq 0x2040
callq 0x2440
callq 0x2490
movq %rax, -0x4d0(%rbp)
movq -0x4d0(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x66, %eax
jne 0x2a77
leaq 0x197c(%rip), %rdi      # 0x407b
movb $0x0, %al
callq 0x2040
callq 0x24e0
movsd %xmm0, -0x4d8(%rbp)
callq 0x24e0
movsd %xmm0, -0x4e0(%rbp)
movq -0x4d0(%rbp), %rdi
leaq 0x1907(%rip), %rsi      # 0x4035
callq 0x2260
cmpl $0x0, %eax
jne 0x2755
movsd -0x4d8(%rbp), %xmm0
addsd -0x4e0(%rbp), %xmm0
movsd %xmm0, -0x4e8(%rbp)
jmp 0x27ef
movq -0x4d0(%rbp), %rdi
leaq 0x18cd(%rip), %rsi      # 0x4030
callq 0x2260
cmpl $0x0, %eax
jne 0x2787
movsd -0x4d8(%rbp), %xmm0
subsd -0x4e0(%rbp), %xmm0
movsd %xmm0, -0x4e8(%rbp)
jmp 0x27ed
movq -0x4d0(%rbp), %rdi
leaq 0x18aa(%rip), %rsi      # 0x403f
callq 0x2260
cmpl $0x0, %eax
jne 0x27b9
movsd -0x4d8(%rbp), %xmm0
mulsd -0x4e0(%rbp), %xmm0
movsd %xmm0, -0x4e8(%rbp)
jmp 0x27eb
movq -0x4d0(%rbp), %rdi
leaq 0x1873(%rip), %rsi      # 0x403a
callq 0x2260
cmpl $0x0, %eax
jne 0x27e9
movsd -0x4d8(%rbp), %xmm0
divsd -0x4e0(%rbp), %xmm0
movsd %xmm0, -0x4e8(%rbp)
jmp 0x27eb
jmp 0x27ed
jmp 0x27ef
movq -0x4d0(%rbp), %rsi
movsd -0x4d8(%rbp), %xmm0
movsd -0x4e0(%rbp), %xmm1
movsd -0x4e8(%rbp), %xmm2
leaq 0x186d(%rip), %rdi      # 0x4082
movb $0x3, %al
callq 0x2040
leaq -0x560(%rbp), %rdi
movq -0x4d0(%rbp), %rdx
movsd -0x4d8(%rbp), %xmm0
movsd -0x4e0(%rbp), %xmm1
leaq 0x1859(%rip), %rsi      # 0x409a
movb $0x2, %al
callq 0x2080
movl -0x18(%rbp), %eax
movl %eax, -0x69c(%rbp)
leaq -0x560(%rbp), %rax
movq %rax, -0x698(%rbp)
leaq -0x560(%rbp), %rdi
callq 0x2100
movl -0x69c(%rbp), %edi
movq -0x698(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
cmpl $0x0, -0xc0(%rbp)
jge 0x28a7
leaq 0x1811(%rip), %rdi      # 0x40a9
callq 0x21a0
movl $0x1, %edi
callq 0x2240
movl -0x18(%rbp), %edi
leaq -0x4c0(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
xorl %ecx, %ecx
callq 0x20d0
movl %eax, -0xbc(%rbp)
cmpl $0x0, -0xbc(%rbp)
jge 0x28e2
leaq 0x17e4(%rip), %rdi      # 0x40b7
callq 0x21a0
movl $0x1, %edi
callq 0x2240
movslq -0xbc(%rbp), %rax
movb $0x0, -0x4c0(%rbp,%rax)
movl -0xbc(%rbp), %esi
leaq 0x1760(%rip), %rdi      # 0x405e
xorl %eax, %eax
leaq -0x4c0(%rbp), %rdx
movq %rdx, -0x6b0(%rbp)
callq 0x2040
leaq -0x5a1(%rbp), %rdi
movq %rdi, -0x6a8(%rbp)
callq 0x22c0
movq -0x6b0(%rbp), %rsi
movq -0x6a8(%rbp), %rdx
leaq -0x5a0(%rbp), %rdi
callq 0x2ea0
jmp 0x2942
xorl %eax, %eax
movl %eax, %esi
leaq -0x5a0(%rbp), %rdi
callq 0x2e60
movsd %xmm0, -0x6b8(%rbp)
jmp 0x295c
movsd -0x6b8(%rbp), %xmm0
subsd -0x4e8(%rbp), %xmm0
movaps 0x16ad(%rip), %xmm1     # 0x4020
pand %xmm1, %xmm0
movsd %xmm0, -0x6c0(%rbp)
leaq -0x5a0(%rbp), %rdi
callq 0x2140
leaq -0x5a1(%rbp), %rdi
callq 0x2200
movsd -0x6c0(%rbp), %xmm1
movsd 0x1669(%rip), %xmm0     # 0x4010
ucomisd %xmm1, %xmm0
jbe 0x2a0e
leaq -0x580(%rbp), %rdi
leaq 0x170c(%rip), %rsi      # 0x40c7
leaq 0x1708(%rip), %rdx      # 0x40ca
movb $0x0, %al
callq 0x2080
jmp 0x2a32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x5b0(%rbp)
movl %eax, -0x5b4(%rbp)
jmp 0x29fd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x5b0(%rbp)
movl %eax, -0x5b4(%rbp)
leaq -0x5a0(%rbp), %rdi
callq 0x2140
leaq -0x5a1(%rbp), %rdi
callq 0x2200
jmp 0x2e48
leaq -0x580(%rbp), %rdi
movsd -0x4e8(%rbp), %xmm0
leaq 0x16a9(%rip), %rsi      # 0x40cd
leaq 0x16aa(%rip), %rdx      # 0x40d5
movb $0x1, %al
callq 0x2080
movl -0x18(%rbp), %eax
movl %eax, -0x6cc(%rbp)
leaq -0x580(%rbp), %rax
movq %rax, -0x6c8(%rbp)
leaq -0x580(%rbp), %rdi
callq 0x2100
movl -0x6cc(%rbp), %edi
movq -0x6c8(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
jmp 0x2dc3
leaq 0x166f(%rip), %rdi      # 0x40ed
movb $0x0, %al
callq 0x2040
callq 0x24c0
movl %eax, -0x4ec(%rbp)
callq 0x24c0
movl %eax, -0x4f0(%rbp)
movq -0x4d0(%rbp), %rdi
leaq 0x158d(%rip), %rsi      # 0x4036
callq 0x2260
cmpl $0x0, %eax
jne 0x2aca
movl -0x4ec(%rbp), %eax
addl -0x4f0(%rbp), %eax
movl %eax, -0x4f4(%rbp)
jmp 0x2b54
movq -0x4d0(%rbp), %rdi
leaq 0x1559(%rip), %rsi      # 0x4031
callq 0x2260
cmpl $0x0, %eax
jne 0x2af6
movl -0x4ec(%rbp), %eax
subl -0x4f0(%rbp), %eax
movl %eax, -0x4f4(%rbp)
jmp 0x2b52
movq -0x4d0(%rbp), %rdi
leaq 0x153c(%rip), %rsi      # 0x4040
callq 0x2260
cmpl $0x0, %eax
jne 0x2b23
movl -0x4ec(%rbp), %eax
imull -0x4f0(%rbp), %eax
movl %eax, -0x4f4(%rbp)
jmp 0x2b50
movq -0x4d0(%rbp), %rdi
leaq 0x150a(%rip), %rsi      # 0x403b
callq 0x2260
cmpl $0x0, %eax
jne 0x2b4e
movl -0x4ec(%rbp), %eax
cltd
idivl -0x4f0(%rbp)
movl %eax, -0x4f4(%rbp)
jmp 0x2b50
jmp 0x2b52
jmp 0x2b54
movq -0x4d0(%rbp), %rsi
movl -0x4ec(%rbp), %edx
movl -0x4f0(%rbp), %ecx
movl -0x4f4(%rbp), %r8d
leaq 0x157d(%rip), %rdi      # 0x40f2
movb $0x0, %al
callq 0x2040
leaq -0x620(%rbp), %rdi
movq -0x4d0(%rbp), %rdx
movl -0x4ec(%rbp), %ecx
movl -0x4f0(%rbp), %r8d
leaq 0x1564(%rip), %rsi      # 0x4102
movb $0x0, %al
callq 0x2080
movl -0x18(%rbp), %eax
movl %eax, -0x6dc(%rbp)
leaq -0x620(%rbp), %rax
movq %rax, -0x6d8(%rbp)
leaq -0x620(%rbp), %rdi
callq 0x2100
movl -0x6dc(%rbp), %edi
movq -0x6d8(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
cmpl $0x0, -0xc0(%rbp)
jge 0x2c04
leaq 0x14b4(%rip), %rdi      # 0x40a9
callq 0x21a0
movl $0x1, %edi
callq 0x2240
movl -0x18(%rbp), %edi
leaq -0x4c0(%rbp), %rsi
movq %rsi, -0x6f0(%rbp)
movl $0x200, %edx            # imm = 0x200
xorl %ecx, %ecx
movl %ecx, -0x6f4(%rbp)
callq 0x20d0
movq -0x6f0(%rbp), %rdx
movq %rax, %rcx
movl -0x6f4(%rbp), %eax
movl %ecx, -0xbc(%rbp)
movslq -0xbc(%rbp), %rcx
movb $0x0, -0x4c0(%rbp,%rcx)
movl -0xbc(%rbp), %esi
leaq 0x1405(%rip), %rdi      # 0x405e
callq 0x2040
leaq -0x661(%rbp), %rdi
movq %rdi, -0x6e8(%rbp)
callq 0x22c0
movq -0x6f0(%rbp), %rsi
movq -0x6e8(%rbp), %rdx
leaq -0x660(%rbp), %rdi
callq 0x2ea0
jmp 0x2c8d
xorl %eax, %eax
movl %eax, %esi
leaq -0x660(%rbp), %rdi
callq 0x2e60
movsd %xmm0, -0x700(%rbp)
jmp 0x2ca7
movsd -0x700(%rbp), %xmm0
cvtsi2sdl -0x4f4(%rbp), %xmm1
subsd %xmm1, %xmm0
callq 0x2f50
movsd %xmm0, -0x708(%rbp)
jmp 0x2cca
leaq -0x660(%rbp), %rdi
callq 0x2140
leaq -0x661(%rbp), %rdi
callq 0x2200
movsd -0x708(%rbp), %xmm1
movsd 0x131e(%rip), %xmm0     # 0x4010
ucomisd %xmm1, %xmm0
jbe 0x2d59
leaq -0x640(%rbp), %rdi
leaq 0x13c1(%rip), %rsi      # 0x40c7
leaq 0x13bd(%rip), %rdx      # 0x40ca
movb $0x0, %al
callq 0x2080
jmp 0x2d7b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x5b0(%rbp)
movl %eax, -0x5b4(%rbp)
jmp 0x2d48
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x5b0(%rbp)
movl %eax, -0x5b4(%rbp)
leaq -0x660(%rbp), %rdi
callq 0x2140
leaq -0x661(%rbp), %rdi
callq 0x2200
jmp 0x2e48
leaq -0x640(%rbp), %rdi
movl -0x4f4(%rbp), %ecx
leaq 0x139e(%rip), %rsi      # 0x410b
leaq 0x1361(%rip), %rdx      # 0x40d5
movb $0x0, %al
callq 0x2080
movl -0x18(%rbp), %eax
movl %eax, -0x714(%rbp)
leaq -0x640(%rbp), %rax
movq %rax, -0x710(%rbp)
leaq -0x640(%rbp), %rdi
callq 0x2100
movl -0x714(%rbp), %edi
movq -0x710(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
movl -0x18(%rbp), %edi
callq 0x22e0
jmp 0x2e43
movq 0x1594(%rip), %rax      # 0x4360
movq %rax, -0x680(%rbp)
movq 0x158e(%rip), %rax      # 0x4368
movq %rax, -0x678(%rbp)
movl 0x1589(%rip), %eax      # 0x4370
movl %eax, -0x670(%rbp)
leaq 0x131c(%rip), %rdi      # 0x4110
movb $0x0, %al
callq 0x2040
movl -0x18(%rbp), %eax
movl %eax, -0x724(%rbp)
leaq -0x680(%rbp), %rax
movq %rax, -0x720(%rbp)
leaq -0x680(%rbp), %rdi
callq 0x2100
movl -0x724(%rbp), %edi
movq -0x720(%rbp), %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0xc0(%rbp)
movl -0x18(%rbp), %edi
callq 0x22e0
jmp 0x25e1
movq -0x5b0(%rbp), %rdi
callq 0x22b0
nopw %cs:(%rax,%rax)
nop