// File: /workspace/github_cpp_makefile_star2_O3/m1c0l[P]TCP/client.cpp
// Function: main
int main(int argc, char **argv)
{
    if (argc != 3) {
		cerr << "usage: " << argv[0] << " SERVER-HOST-OR-IP PORT-NUMBER" << '\n';
        exit(1);
    }

    string ip = argv[1];
    string port = argv[2];

	// Get IP address if we're given a hostname
	addrinfo hints;
	addrinfo* res;

	// prepare hints
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET; // IPv4
	hints.ai_socktype = SOCK_STREAM; // TCP

	// get address
	int status = 0;
	if ((status = getaddrinfo(ip.c_str(), port.c_str(), &hints, &res)) != 0) {
		// cerr << "getaddrinfo: " << gai_strerror(status) << '\n';
		exit(2);
	}

	addrinfo* p = res;
	// convert address to IPv4 address
	sockaddr_in* ipv4;
	char ipstr[INET_ADDRSTRLEN] = {'\0'};
	if (p != 0) {
		ipv4 = (sockaddr_in*)p->ai_addr;

		// convert the IP to a string
		inet_ntop(p->ai_family, &(ipv4->sin_addr), ipstr, sizeof(ipstr));
	}
	else {
		// cerr << "IP address not found for " << ip << endl;
		exit(3);
	}
	ip = ipstr;
	// cerr << "IP: " << ip << "\n";

	srand (time(NULL)); //Used to generate random ISN
 
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket");
		exit(1);
    }

	// Set receive timeout of 0.5 s
	timeval recvTimeval;
	recvTimeval.tv_sec = 0;
	recvTimeval.tv_usec = TIMEOUT * 1000;
	setSocketTimeout(sockfd, recvTimeval);
 
    sockaddr_in si_server;
    memset((char *) &si_server, 0, sizeof(si_server));
    si_server.sin_family = AF_INET;
    si_server.sin_port = htons(stoi(port));
	socklen_t serverLen = sizeof(si_server);

    if (inet_aton(ip.c_str(), &si_server.sin_addr) == 0) {
        perror("inet_aton");
	    exit(1);
    }


	uint16_t seqToSend = rand() % MAX_SEQ_NUM;
   	uint16_t ackToSend = 0;
	uint16_t recvWindowToSend = INIT_RECV_WINDOW;
	TcpMessage packetToSend, packetReceived;
	uint16_t synAckSeq;


	/* handshake */
	bool hasResentSyn = false;
	while (true) {
		/* send SYN */
		packetToSend = TcpMessage(seqToSend, ackToSend, recvWindowToSend, "S");
		printSend("SYN", seqToSend, hasResentSyn);
		hasResentSyn = true; // set this to true so "retransmit" will print the 2nd time
		// keep this // cerr output for now, remove it later
		// cerr << "sending SYN:" << endl;
		packetToSend.dump();
		packetToSend.sendto(sockfd, &si_server, serverLen);

		/* receive SYN-ACK */
		int r = packetReceived.recvfrom(sockfd, &si_server, serverLen);
		if (r == RECV_TIMEOUT) {
			continue; // resend SYN
		}
		else {
			printRecv(packetReceived.seqNum);
			// cerr << "receiving SYN-ACK:" << endl;
			packetReceived.dump();
			if (!packetReceived.getFlag('a') || !packetReceived.getFlag('s')) {
				// error: server responded, but without syn-ack
				// cerr << "Server responded, but without syn-ack!\n";
				//exit(1);
			}
			if (packetReceived.ackNum != incSeqNum(seqToSend, 1)) {
				// cerr << "SYN-ACK has wrong ack number; drop packet" << endl;
				continue;
			}
			synAckSeq = packetReceived.seqNum;
			break;
		}
	}

	// seq/ack for client's ACK for handshake
	seqToSend = incSeqNum(seqToSend, 1);// increase sequence number by 1
	uint16_t handshakeSeq = seqToSend;
	ackToSend = incSeqNum(packetReceived.seqNum, 1);
	uint16_t handshakeAck = ackToSend;

	//return 0;

	/* receive data */

	ofstream outFile(OUTPUT_FILE);
	bool handshakeComplete = false;
	TcpMessage dataAck;

	// store the out-of-order packets in case we get in order packets
	unordered_map<uint16_t, TcpMessage> outOfOrderPkts; // seqNum -> TcpMessage
	// first data packet's sequence number we should receive
	uint16_t nextInOrderSeq = ackToSend;
	uint16_t lastAckSent = BAD_SEQ_NUM;
	bool handshakeAckResend = false;

	while (true) {
		/* send handshake ACK */
		if (!handshakeComplete) {
			packetToSend = TcpMessage(handshakeSeq, handshakeAck, recvWindowToSend, "A");
			printSend("ACK", handshakeAck, handshakeAckResend);
			lastAckSent = handshakeAck;
			// cerr << "sending ACK:" << endl;
			packetToSend.dump();
			packetToSend.sendto(sockfd, &si_server, serverLen);
			handshakeAckResend = true;
		}

		/* receive data packet */
		int r = packetReceived.recvfrom(sockfd, &si_server, serverLen);
		// if timeout, try to recvfrom again
		if (r == RECV_TIMEOUT) {
			continue;
		}
		// if duplicate SYN-ACK, resend handshake ACK
		if (packetReceived.seqNum == synAckSeq) {
			continue;
		}
		handshakeComplete = true; // done with handshake if this is a data pkt

		// else, r == RECV_SUCCESS
		// cerr << "receiving data:" << endl;
		packetReceived.dump();

		// FIN received
		if (packetReceived.getFlag('F')) {
			// cerr << "OoO map size at FIN: " << outOfOrderPkts.size() << '\n';
			printRecv(packetReceived.seqNum);
			break;
		}
		printRecv(packetReceived.seqNum);

		streamsize dataSize = packetReceived.data.size();
		uint16_t seqReceived = packetReceived.seqNum;
		bool shouldDropPkt = false;
		// check if packet's within window boundary; if not, drop packet
		uint16_t windowMaxSeq = incSeqNum(nextInOrderSeq, recvWindowToSend);
		if (windowMaxSeq > nextInOrderSeq) {
			// no wrap around
			shouldDropPkt = seqReceived < nextInOrderSeq || seqReceived > windowMaxSeq;
		}
		else {
			// wrap around
			shouldDropPkt = seqReceived > windowMaxSeq && seqReceived < nextInOrderSeq;
		}
		if (shouldDropPkt) {
			// cerr << "Received pkt not w/in window!\n";
		}
		if (!shouldDropPkt) {
			if (seqReceived == nextInOrderSeq) { 
				// cerr << "Received in order packet!\n";
				// save data to file
				const char *data = packetReceived.data.c_str();
				outFile.write(data, dataSize);

				// see if we received an OoO pkt earlier w/ this seq #
				if (outOfOrderPkts.count(seqReceived)) {
					// delete it from map
					outOfOrderPkts.erase(seqReceived);
				}
				// update the next expected sequence number, increase by data size we got
				nextInOrderSeq = incSeqNum(nextInOrderSeq, dataSize);
				// loop through saved OoO packets to see if they're next in order
				while (outOfOrderPkts.count(nextInOrderSeq)) {
					// cerr << "Writing OoO pkt w/ seq # " << nextInOrderSeq << " from map\n";
					TcpMessage poppedMsg = outOfOrderPkts[nextInOrderSeq];
					const char *poppedData = poppedMsg.data.c_str();
					streamsize poppedDataSize = poppedMsg.data.size();
					outFile.write(poppedData, poppedDataSize);
					outOfOrderPkts.erase(nextInOrderSeq);
					nextInOrderSeq = incSeqNum(nextInOrderSeq, poppedDataSize);
				}
			}
			else {
				// out of order, store it for later
				// cerr << "Received out of order packet! Writing to map\n";
				outOfOrderPkts[seqReceived] = packetReceived;
			}
		}
		ackToSend = nextInOrderSeq; 
		dataAck = TcpMessage(seqToSend, ackToSend, recvWindowToSend, "A");
		printSend("ACK", ackToSend, ackToSend == lastAckSent);
		// cerr << "sending ACK:" << endl;
		dataAck.dump();
		dataAck.sendto(sockfd, &si_server, serverLen);
		lastAckSent = ackToSend;
	}

 

	/* Send FIN-ACK for the FIN received earlier */
	bool hasSentFinAck = false;
	bool hasSentFin = false;
	bool hasReceivedAck = false; /* receive packets until a FIN-ACK is received from server */
	// seq # stays same b/c no payload
	ackToSend = incSeqNum(packetReceived.seqNum, 1);
	packetToSend = TcpMessage(seqToSend, ackToSend, recvWindowToSend, "FA");
	packetToSend.sendto(sockfd, &si_server, serverLen);
	printSend("FIN", ackToSend, hasSentFinAck);
	// cerr << "Sending FIN-ACK to server\n";
	packetToSend.dump();

	while (!hasReceivedAck) {

		/* Send FIN; seq # stays same b/c no payload */
		packetToSend = TcpMessage(seqToSend, ackToSend, recvWindowToSend, "F");
		packetToSend.sendto(sockfd, &si_server, serverLen);
		printSend("FIN", ackToSend, hasSentFin);
		hasSentFin = true; // so "retransmission" prints the second time
		// cerr << "Sending FIN to server\n";
		packetToSend.dump();

		int r = packetReceived.recvfrom(sockfd, &si_server, serverLen);
		if (r == RECV_TIMEOUT) {
			continue;
		}
		printRecv(packetReceived.seqNum);
		switch(packetReceived.flags) {
			// server resends FIN
			case FIN_FLAG:
				/* Send FIN-ACK */
				printSend("FIN", ackToSend, true);
				// cerr << "Received FIN\n";
				ackToSend = incSeqNum(packetReceived.seqNum, 1);
				packetToSend = TcpMessage(seqToSend, ackToSend, recvWindowToSend, "FA");
				packetToSend.sendto(sockfd, &si_server, serverLen);
				// cerr << "Sending FIN-ACK to server\n";
				packetToSend.dump();
				break;

			// get FIN-ACK; can exit now
			case ACK_FLAG:
				// cerr << "Received ACK of FIN! Closing connection.\n";
				hasReceivedAck = true;
				break;

			default:
				// cerr << "Received packet wasn't FIN-ACK or FIN!\n";
				//exit(1);
				break;

		}
	}



	close(sockfd);
	outFile.close();
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x518, %rsp            # imm = 0x518
movq %rsi, %rbx
cmpl $0x3, %edi
jne 0x3aee
movq 0x8(%rbx), %rsi
leaq 0x170(%rsp), %rdi
leaq 0x2e0(%rsp), %rdx
callq 0x3eaa
movq 0x10(%rbx), %rsi
leaq 0x2b0(%rsp), %rdi
leaq 0x2e0(%rsp), %rdx
callq 0x3eaa
xorps %xmm0, %xmm0
leaq 0x4e0(%rsp), %rdx
movaps %xmm0, (%rdx)
movaps %xmm0, 0x10(%rdx)
movaps %xmm0, 0x20(%rdx)
movabsq $0x100000002, %rax      # imm = 0x100000002
movq %rax, 0x4(%rdx)
movq 0x170(%rsp), %rdi
movq 0x2b0(%rsp), %rsi
leaq 0x168(%rsp), %rcx
callq 0x2250
testl %eax, %eax
jne 0x3b32
movq 0x168(%rsp), %rax
xorps %xmm0, %xmm0
movaps %xmm0, 0x2d0(%rsp)
testq %rax, %rax
je 0x3b3c
movq 0x18(%rax), %rsi
movl 0x4(%rax), %edi
addq $0x4, %rsi
leaq 0x2d0(%rsp), %rbx
movq %rbx, %rdx
movl $0x10, %ecx
callq 0x21f0
leaq 0x170(%rsp), %r14
movq 0x8(%r14), %r15
movq %rbx, %rdi
callq 0x20d0
movq %r14, %rdi
xorl %esi, %esi
movq %r15, %rdx
movq %rbx, %rcx
movq %rax, %r8
callq 0x22e0
xorl %edi, %edi
callq 0x21a0
movl %eax, %edi
callq 0x21b0
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x2060
cmpl $-0x1, %eax
je 0x3b46
movl %eax, %ebx
movl $0x7a120, %edx          # imm = 0x7A120
movl %eax, %edi
xorl %esi, %esi
callq 0x2ac7
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
movw $0x2, 0x40(%rsp)
movq 0x2b0(%rsp), %r15
callq 0x2030
movq %rax, %r14
movl (%rax), %ebp
movl $0x0, (%rax)
leaq 0x2e0(%rsp), %r12
movq %r15, %rdi
movq %r12, %rsi
movl $0xa, %edx
callq 0x2280
cmpq %r15, (%r12)
je 0x3b4b
movslq %eax, %rcx
cmpq %rax, %rcx
jne 0x3b57
movl (%r14), %ecx
cmpl $0x22, %ecx
je 0x3b57
testl %ecx, %ecx
jne 0x2e6e
movl %ebp, (%r14)
rolw $0x8, %ax
leaq 0x44(%rsp), %rsi
movw %ax, -0x2(%rsi)
movq 0x170(%rsp), %rdi
callq 0x2130
testl %eax, %eax
je 0x3b63
callq 0x2070
movl %eax, %ebp
leaq 0x78(%rsp), %rdi
callq 0x26f8
leaq 0x50(%rsp), %rdi
callq 0x26f8
movslq %ebp, %rax
imulq $-0x77777777, %rax, %rcx # imm = 0x88888889
shrq $0x20, %rcx
addl %eax, %ecx
movl %ecx, %edx
shrl $0x1f, %edx
shrl $0xe, %ecx
addl %edx, %ecx
imull $0x7800, %ecx, %ecx     # imm = 0x7800
subl %ecx, %eax
xorl %r14d, %r14d
movzwl %ax, %ebp
leaq 0x50(%rsp), %r13
leaq 0x2a0(%rsp), %r15
movq %r15, 0x290(%rsp)
leaq 0x290(%rsp), %r12
movq %r12, %rdi
leaq 0x21c0(%rip), %rsi      # 0x50ba
leaq 0x21ba(%rip), %rdx      # 0x50bb
callq 0x2952
leaq 0x2e0(%rsp), %rdi
movl %ebp, %esi
xorl %edx, %edx
movl $0x3c00, %ecx           # imm = 0x3C00
movq %r12, %r8
callq 0x251c
movq 0x2e0(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x2e8(%rsp), %rsi
callq 0x2240
movq 0x2e8(%rsp), %rdi
leaq 0x2f8(%rsp), %rax
cmpq %rax, %rdi
je 0x2f66
movq 0x2f8(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x290(%rsp), %rdi
cmpq %r15, %rdi
je 0x2f83
movq 0x2a0(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x280(%rsp), %r15
movq %r15, 0x270(%rsp)
leaq 0x270(%rsp), %r12
movq %r12, %rdi
leaq 0x20c5(%rip), %rsi      # 0x506a
leaq 0x20c1(%rip), %rdx      # 0x506d
callq 0x2952
movzbl %r14b, %edx
andl $0x1, %edx
movq %r12, %rdi
movl %ebp, %esi
callq 0x2bf4
movq 0x270(%rsp), %rdi
cmpq %r15, %rdi
je 0x2fdf
movq 0x280(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x78(%rsp), %r14
movq %r14, %rdi
callq 0x28ba
leaq 0x40(%rsp), %r15
movq %r14, %rdi
movl %ebx, %esi
movq %r15, %rdx
movl $0x10, %ecx
callq 0x2806
movq %r13, %rdi
movl %ebx, %esi
movq %r15, %rdx
movl $0x10, %ecx
callq 0x2854
movb $0x1, %r14b
cmpl $0x2, %eax
je 0x2ed8
movzwl 0x50(%rsp), %edi
callq 0x2bac
movq %r13, %rdi
callq 0x28ba
movq %r13, %rdi
movl $0x61, %esi
callq 0x2724
testb %al, %al
je 0x3051
movq %r13, %rdi
movl $0x73, %esi
callq 0x2724
movzwl 0x52(%rsp), %r15d
movl %ebp, %edi
movl $0x1, %esi
callq 0x29e8
cmpw %ax, %r15w
jne 0x2ed8
movzwl 0x50(%rsp), %eax
movw %ax, 0x3e(%rsp)
movl %ebp, %edi
movl $0x1, %esi
callq 0x29e8
movw %ax, 0xc(%rsp)
movzwl 0x50(%rsp), %edi
movl $0x1, %esi
callq 0x29e8
movl %eax, %r14d
leaq 0x201b(%rip), %rsi      # 0x50bc
leaq 0x2e0(%rsp), %rdi
movl $0x10, %edx
callq 0x2200
leaq 0x1c8(%rsp), %rdi
callq 0x26f8
leaq 0x1c0(%rsp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
leaq 0x8(%rsp), %rax
movw %r14w, (%rax)
movw $0xd903, %r15w          # imm = 0xD903
xorl %r13d, %r13d
xorl %r12d, %r12d
movl %ebx, 0xa4(%rsp)
testb $0x1, %r13b
jne 0x323d
leaq 0x158(%rsp), %rax
movq %rax, 0x148(%rsp)
leaq 0x148(%rsp), %r15
movq %r15, %rdi
leaq 0x1f9e(%rip), %rsi      # 0x50cb
leaq 0x1f98(%rip), %rdx      # 0x50cc
callq 0x2952
movzwl 0xc(%rsp), %esi
movzwl %r14w, %ebp
leaq 0x10(%rsp), %rdi
movl %ebp, %edx
movl $0x3c00, %ecx           # imm = 0x3C00
movq %r15, %r8
callq 0x251c
movq 0x10(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x2240
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x318e
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x148(%rsp), %rdi
leaq 0x158(%rsp), %rax
cmpq %rax, %rdi
je 0x31b3
movq 0x158(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x138(%rsp), %rax
movq %rax, 0x128(%rsp)
leaq 0x128(%rsp), %r15
movq %r15, %rdi
leaq 0x1ea9(%rip), %rsi      # 0x507e
leaq 0x1ea5(%rip), %rdx      # 0x5081
callq 0x2952
movzbl %r12b, %edx
andl $0x1, %edx
movq %r15, %rdi
movl %ebp, %esi
callq 0x2bf4
movq 0x128(%rsp), %rdi
leaq 0x138(%rsp), %rax
cmpq %rax, %rdi
je 0x3217
movq 0x138(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x78(%rsp), %rdi
callq 0x28ba
movb $0x1, %r12b
leaq 0x78(%rsp), %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2806
movl %r14d, %r15d
leaq 0x50(%rsp), %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2854
cmpl $0x2, %eax
je 0x3101
movzwl 0x3e(%rsp), %eax
cmpw %ax, 0x50(%rsp)
je 0x3101
leaq 0x50(%rsp), %rdi
callq 0x28ba
leaq 0x50(%rsp), %rdi
movl $0x46, %esi
callq 0x2724
movzwl 0x50(%rsp), %ecx
testb %al, %al
jne 0x3611
movzwl %cx, %edi
callq 0x2bac
movq 0x60(%rsp), %r13
movzwl 0x50(%rsp), %eax
movw %ax, 0xa(%rsp)
movzwl 0x8(%rsp), %edi
movl $0x3c00, %esi           # imm = 0x3C00
callq 0x29e8
movzwl 0x8(%rsp), %r9d
movzwl 0xa(%rsp), %ecx
cmpw %r9w, %ax
jbe 0x32df
cmpw %r9w, %cx
setb %dl
cmpw %ax, %cx
seta %al
orb %dl, %al
je 0x32f4
jmp 0x34c3
cmpw %ax, %cx
seta %al
cmpw %r9w, %cx
setb %dl
testb %dl, %al
jne 0x34c3
cmpw %r9w, %cx
jne 0x3492
movq 0x58(%rsp), %rsi
leaq 0x2e0(%rsp), %rdi
movq %r13, %rdx
callq 0x2260
movzwl 0xa(%rsp), %ecx
movq 0x190(%rsp), %rdi
movq 0x198(%rsp), %r8
movq %rcx, %rax
xorl %edx, %edx
divq %r8
movq %rdx, %rsi
movl %esi, %eax
movq (%rdi,%rax,8), %rax
testq %rax, %rax
je 0x3379
movq (%rax), %r9
cmpw 0x8(%r9), %cx
je 0x3367
movq (%r9), %r9
testq %r9, %r9
je 0x3379
movzwl 0x8(%r9), %edi
movq %rdi, %rax
xorl %edx, %edx
divq %r8
cmpq %rsi, %rdx
jne 0x3379
cmpw %di, %cx
jne 0x3348
leaq 0x190(%rsp), %rdi
leaq 0xa(%rsp), %rsi
callq 0x3f90
movzwl 0x8(%rsp), %edi
movzwl %r13w, %esi
callq 0x29e8
movl %eax, %r9d
movw %ax, 0x8(%rsp)
movzwl %r9w, %eax
movq 0x190(%rsp), %rsi
movq 0x198(%rsp), %rdi
xorl %edx, %edx
divq %rdi
movq %rdx, %rcx
movl %ecx, %eax
movq (%rsi,%rax,8), %rax
testq %rax, %rax
je 0x34c3
movq (%rax), %r8
cmpw 0x8(%r8), %r9w
je 0x33ec
movq (%r8), %r8
testq %r8, %r8
je 0x34c3
movzwl 0x8(%r8), %esi
movq %rsi, %rax
xorl %edx, %edx
divq %rdi
cmpq %rcx, %rdx
jne 0x34c3
cmpw %si, %r9w
jne 0x33c4
leaq 0x190(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x4086
movq (%rax), %rcx
movq %rcx, 0x10(%rsp)
leaq 0x28(%rsp), %rcx
movq %rcx, 0x18(%rsp)
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rdx
addq %rsi, %rdx
leaq 0x18(%rsp), %rdi
callq 0x28bc
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %r13
leaq 0x2e0(%rsp), %rdi
movq %r13, %rdx
callq 0x2260
leaq 0x190(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x3f90
movzwl 0x8(%rsp), %edi
movzwl %r13w, %esi
callq 0x29e8
movl %eax, %r9d
movw %ax, 0x8(%rsp)
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x338f
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movzwl 0x8(%rsp), %r9d
jmp 0x338f
leaq 0x190(%rsp), %rdi
leaq 0xa(%rsp), %rsi
callq 0x4086
movq 0x50(%rsp), %rcx
movq %rcx, (%rax)
addq $0x8, %rax
movq %rax, %rdi
leaq 0x58(%rsp), %rsi
callq 0x20e0
movzwl 0x8(%rsp), %r9d
movl %r9d, %ebx
leaq 0x118(%rsp), %rax
movq %rax, 0x108(%rsp)
leaq 0x108(%rsp), %rbp
movq %rbp, %rdi
leaq 0x1be3(%rip), %rsi      # 0x50cb
leaq 0x1bdd(%rip), %rdx      # 0x50cc
callq 0x2952
movzwl 0xc(%rsp), %esi
movzwl %bx, %r13d
leaq 0x10(%rsp), %rdi
movl %r13d, %edx
movl $0x3c00, %ecx           # imm = 0x3C00
movq %rbp, %r8
callq 0x251c
movq 0x10(%rsp), %rax
movq %rax, 0x1c8(%rsp)
leaq 0x1d0(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x2240
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x354d
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x108(%rsp), %rdi
leaq 0x118(%rsp), %rax
cmpq %rax, %rdi
je 0x3572
movq 0x118(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0xf8(%rsp), %rax
movq %rax, 0xe8(%rsp)
leaq 0xe8(%rsp), %rbp
movq %rbp, %rdi
leaq 0x1aea(%rip), %rsi      # 0x507e
leaq 0x1ae6(%rip), %rdx      # 0x5081
callq 0x2952
xorl %edx, %edx
cmpw %r15w, %r13w
sete %dl
movq %rbp, %rdi
movl %r13d, %esi
callq 0x2bf4
movq 0xe8(%rsp), %rdi
leaq 0xf8(%rsp), %rax
cmpq %rax, %rdi
movl %ebx, %r15d
je 0x35dc
movq 0xf8(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x1c8(%rsp), %rdi
callq 0x28ba
movl 0xa4(%rsp), %ebx
leaq 0x1c8(%rsp), %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2806
movb $0x1, %r13b
jmp 0x3101
movzwl %cx, %edi
callq 0x2bac
movzwl 0x50(%rsp), %edi
movl $0x1, %esi
callq 0x29e8
movl %eax, %r13d
leaq 0x260(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x1a8c(%rip), %rsi      # 0x50ca
leaq 0x1a87(%rip), %rdx      # 0x50cc
leaq 0x250(%rsp), %rdi
callq 0x2952
movzwl 0xc(%rsp), %esi
movzwl %r13w, %ebp
leaq 0x10(%rsp), %rdi
leaq 0x250(%rsp), %r8
movl %esi, 0xc(%rsp)
movl %ebp, %edx
movl $0x3c00, %ecx           # imm = 0x3C00
callq 0x251c
leaq 0x18(%rsp), %r14
movq -0x8(%r14), %rax
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
movq %r14, %rsi
callq 0x2240
movq (%r14), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x36b0
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x250(%rsp), %rdi
cmpq %r15, %rdi
je 0x36cd
movq 0x260(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x78(%rsp), %rdi
leaq 0x40(%rsp), %rdx
movl %ebx, %esi
movl $0x10, %ecx
callq 0x2806
leaq 0x240(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0x19d7(%rip), %rsi      # 0x50cd
leaq 0x19d3(%rip), %rdx      # 0x50d0
leaq 0x230(%rsp), %rdi
callq 0x2952
leaq 0x230(%rsp), %rdi
movl %ebp, %esi
xorl %edx, %edx
callq 0x2bf4
movq 0x230(%rsp), %rdi
cmpq %r14, %rdi
je 0x3738
movq 0x240(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x78(%rsp), %rdi
callq 0x28ba
xorl %r15d, %r15d
leaq 0x78(%rsp), %r12
leaq 0xa8(%rsp), %r14
movzwl %r13w, %ebp
leaq 0xd8(%rsp), %rax
movq %rax, 0xc8(%rsp)
leaq 0xc8(%rsp), %r13
movq %r13, %rdi
leaq 0x1959(%rip), %rsi      # 0x50d1
leaq 0x1953(%rip), %rdx      # 0x50d2
callq 0x2952
leaq 0x10(%rsp), %rdi
movl 0xc(%rsp), %esi
movl %ebp, %edx
movl $0x3c00, %ecx           # imm = 0x3C00
movq %r13, %r8
callq 0x251c
movq 0x10(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x2240
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x37d4
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0xc8(%rsp), %rdi
leaq 0xd8(%rsp), %rax
cmpq %rax, %rdi
je 0x37f9
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x21e0
movq %r12, %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2806
leaq 0xb8(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq %r14, %rdi
leaq 0x18a6(%rip), %rsi      # 0x50cd
leaq 0x18a2(%rip), %rdx      # 0x50d0
callq 0x2952
movzbl %r15b, %edx
andl $0x1, %edx
movq %r14, %rdi
movl %ebp, %esi
callq 0x2bf4
movq 0xa8(%rsp), %rdi
leaq 0xb8(%rsp), %rax
cmpq %rax, %rdi
je 0x3869
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x21e0
movq %r12, %rdi
callq 0x28ba
leaq 0x50(%rsp), %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2854
movb $0x1, %r15b
cmpl $0x2, %eax
je 0x3756
movzwl 0x50(%rsp), %edi
callq 0x2bac
movzwl 0x56(%rsp), %eax
cmpl $0x4, %eax
je 0x39e2
cmpl $0x1, %eax
jne 0x3756
leaq 0x220(%rsp), %r15
movq %r15, 0x210(%rsp)
leaq 0x210(%rsp), %r13
movq %r13, %rdi
leaq 0x17f7(%rip), %rsi      # 0x50cd
leaq 0x17f3(%rip), %rdx      # 0x50d0
callq 0x2952
movq %r13, %rdi
movl %ebp, %esi
movl $0x1, %edx
callq 0x2bf4
movq 0x210(%rsp), %rdi
cmpq %r15, %rdi
je 0x390e
movq 0x220(%rsp), %rsi
incq %rsi
callq 0x21e0
movzwl 0x50(%rsp), %edi
movl $0x1, %esi
callq 0x29e8
movl %eax, %ebp
leaq 0x200(%rsp), %r15
movq %r15, 0x1f0(%rsp)
leaq 0x1f0(%rsp), %r13
movq %r13, %rdi
leaq 0x1789(%rip), %rsi      # 0x50ca
leaq 0x1784(%rip), %rdx      # 0x50cc
callq 0x2952
movzwl %bp, %edx
leaq 0x10(%rsp), %rdi
movl 0xc(%rsp), %esi
movl $0x3c00, %ecx           # imm = 0x3C00
movq %r13, %r8
callq 0x251c
movq 0x10(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x2240
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x399e
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x1f0(%rsp), %rdi
cmpq %r15, %rdi
movl %ebp, %r13d
je 0x39be
movq 0x200(%rsp), %rsi
incq %rsi
callq 0x21e0
movq %r12, %rdi
movl %ebx, %esi
leaq 0x40(%rsp), %rdx
movl $0x10, %ecx
callq 0x2806
movb $0x1, %r15b
movq %r12, %rdi
callq 0x28ba
jmp 0x3752
movl %ebx, %edi
callq 0x2340
leaq 0x2e0(%rsp), %rdi
callq 0x2290
leaq 0x190(%rsp), %rdi
callq 0x3ef2
leaq 0x1e0(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3a24
movq 0x1e0(%rsp), %rsi
incq %rsi
callq 0x21e0
movq 0x359d(%rip), %rax      # 0x6fc8
movq (%rax), %rcx
movq 0x18(%rax), %rax
leaq 0x2e8(%rsp), %rdi
movq %rcx, -0x8(%rdi)
movq -0x18(%rcx), %rcx
movq %rax, 0x2e0(%rsp,%rcx)
callq 0x2180
leaq 0x3d8(%rsp), %rdi
callq 0x20a0
leaq 0x68(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3a77
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x90(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3a98
movq 0x90(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x2c0(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3ab9
movq 0x2c0(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x180(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3ada
movq 0x180(%rsp), %rsi
incq %rsi
callq 0x21e0
xorl %eax, %eax
addq $0x518, %rsp            # imm = 0x518
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x34fb(%rip), %rdi      # 0x6ff0
leaq 0x1586(%rip), %rsi      # 0x5082
callq 0x21c0
movq (%rbx), %rsi
movq %rax, %rdi
callq 0x21c0
leaq 0x1577(%rip), %rsi      # 0x508a
movq %rax, %rdi
callq 0x21c0
movq %rax, %rdi
movl $0xa, %esi
callq 0x2220
movl $0x1, %edi
callq 0x2230
movl $0x2, %edi
callq 0x2230
movl $0x3, %edi
callq 0x2230
callq 0x23b4
leaq 0x1581(%rip), %rdi      # 0x50d3
callq 0x2100
leaq 0x1575(%rip), %rdi      # 0x50d3
callq 0x22a0
callq 0x239f
movq %rax, %rbx
movq 0x1f0(%rsp), %rdi
cmpq %r15, %rdi
je 0x3de9
movq 0x200(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
movq %rax, %rbx
movq 0x210(%rsp), %rdi
cmpq %r15, %rdi
je 0x3de9
movq 0x220(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
movq %rax, %rbx
movq 0x230(%rsp), %rdi
cmpq %r14, %rdi
je 0x3de9
movq 0x240(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
movq %rax, %rbx
movq 0x250(%rsp), %rdi
cmpq %r15, %rdi
je 0x3de9
movq 0x260(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
jmp 0x3de6
movq %rax, %rbx
jmp 0x3e17
jmp 0x3d8c
jmp 0x3d8c
jmp 0x3d8c
movq %rax, %rbx
jmp 0x3e3f
jmp 0x3c2a
jmp 0x3c2a
jmp 0x3c2a
movq %rax, %rbx
jmp 0x3e60
movq %rax, %rbx
jmp 0x3e81
movq %rax, %rbx
cmpl $0x0, (%r14)
jne 0x3e60
movl %ebp, (%r14)
jmp 0x3e60
jmp 0x3de6
jmp 0x3de6
jmp 0x3de6
jmp 0x3de6
movq %rax, %rbx
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0x28(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
movq %rax, %rbx
movq 0x108(%rsp), %rdi
leaq 0x118(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0x118(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
movq %rax, %rbx
movq 0xe8(%rsp), %rdi
leaq 0xf8(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0xf8(%rsp), %rsi
jmp 0x3dda
jmp 0x3d8c
movq %rax, %rbx
movq 0x290(%rsp), %rdi
cmpq %r15, %rdi
je 0x3e24
movq 0x2a0(%rsp), %rsi
jmp 0x3d23
jmp 0x3d8c
movq %rax, %rbx
movq 0x270(%rsp), %rdi
cmpq %r15, %rdi
je 0x3e24
movq 0x280(%rsp), %rsi
incq %rsi
callq 0x21e0
jmp 0x3e24
jmp 0x3de6
jmp 0x3de6
movq %rax, %rbx
movq 0xa8(%rsp), %rdi
leaq 0xb8(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0xb8(%rsp), %rsi
jmp 0x3dda
movq %rax, %rbx
movq 0xc8(%rsp), %rdi
leaq 0xd8(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0xd8(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
jmp 0x3de6
jmp 0x3de6
jmp 0x3d8c
jmp 0x3de6
movq %rax, %rbx
jmp 0x3e24
movq %rax, %rbx
movq 0x128(%rsp), %rdi
leaq 0x138(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0x138(%rsp), %rsi
jmp 0x3dda
jmp 0x3de6
jmp 0x3de6
movq %rax, %rbx
movq 0x148(%rsp), %rdi
leaq 0x158(%rsp), %rax
cmpq %rax, %rdi
je 0x3de9
movq 0x158(%rsp), %rsi
incq %rsi
callq 0x21e0
jmp 0x3de9
jmp 0x3de6
movq %rax, %rbx
leaq 0x190(%rsp), %rdi
callq 0x3ef2
leaq 0x1e0(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3e17
movq 0x1e0(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x2e0(%rsp), %rdi
callq 0x22c0
leaq 0x68(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3e3f
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x90(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3e60
movq 0x90(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x2c0(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3e81
movq 0x2c0(%rsp), %rsi
incq %rsi
callq 0x21e0
leaq 0x180(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x3ea2
movq 0x180(%rsp), %rsi
incq %rsi
callq 0x21e0
movq %rbx, %rdi
callq 0x2310