// File: /workspace/github_cpp_makefile_star2_O1/SaadBazaz[P]RIP-Protocol-Simulation/ProxyRouter.cpp
// Function: main
int main()
{
	cout << "Which Unique Port do you want to use?\n";
	cin >> port;

	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	assert(sockfd != -1);

	printf("sockfd=%d\n", sockfd);

	struct sockaddr_in saddr, caddr;
	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

	int res = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
	assert(res != -1);

	//Create listening queue
	listen(sockfd, 5);

	//Define fdset collection
	fd_set fdset;

	//Define fds array
	int fds[MAXFD];
	int i = 0;
	for (; i < MAXFD; ++i)
	{
		fds[i] = -1;
	}


	//Add a file descriptor to the fds array
	fds_add(fds, sockfd);





{
	char option;
	
	do {

		cout << "Would you like to connect to any other routers? (y/n)\n";
		cin >> option;
		if (option == 'n' or option == 'N'){
			break;
		} 

		int router_port;
		cout<<"Enter the partner router's Unique Port: ";
		cin >> router_port;

		int sockfd_router = socket(AF_INET, SOCK_STREAM, 0);
		assert(sockfd_router != -1);

		//Set Address Information
		struct sockaddr_in saddr;
		memset(&saddr, 0, sizeof(saddr));
		saddr.sin_family = AF_INET;
		saddr.sin_port = htons(router_port);
		saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

		//Link to router
		int res = connect(sockfd_router, (struct sockaddr *)&saddr, sizeof(saddr));
		assert(res != -1);

		TableRow myself(port, -1, "ROUTER");

		cout << "Sending this router's unique port to partner router..." << endl;
		string init_msg = constructNewMessage(UPDATE, port, router_port, (void *)&myself);
		send(sockfd_router, init_msg.c_str(), strlen(init_msg.c_str()), 0);

		cout << endl;


		TableRow table_row (router_port, sockfd_router, "ROUTER");
		table.push_back(table_row);

		fds_add(fds, sockfd_router);		

		printTable();

	}
	while(option != 'n' and option != 'N');


}


	while (1)
	{
		FD_ZERO(&fdset); //Clear the fdset array to 0

		int maxfd = -1;

		int i = 0;

		//For loop finds the maximum subscript for the ready event in the fds array
		for (; i < MAXFD; i++)
		{
			if (fds[i] == -1)
			{
				continue;
			}

			FD_SET(fds[i], &fdset);

			if (fds[i] > maxfd)
			{
				maxfd = fds[i];
			}
		}

		struct timeval tv = {5, 0}; //Set timeout of 5 seconds

		int n = select(maxfd + 1, &fdset, NULL, NULL, &tv); //Selectect system call, where we only focus on read events
		if (n == -1)										//fail
		{
			perror("select error");
		}
		else if (n == 0) //Timeout, meaning no file descriptor returned
		{
			printf(".\n");
			sendTableToAllRouters();
		}
		else //Ready event generation
		{
			//Because we only know the number of ready events by the return value of select, we don't know which events are ready.
			//Therefore, each file descriptor needs to be traversed for judgment
			for (i = 0; i < MAXFD; ++i)
			{
				if (fds[i] == -1) //If fds[i]==-1, the event is not ready
				{
					continue;
				}
				if (FD_ISSET(fds[i], &fdset)) //Determine if the event corresponding to the file descriptor is ready
				{

					//There are two kinds of cases for judging file descriptors
					try
					{
						if (fds[i] == sockfd) //A file descriptor is a socket, meaning accept if a new client requests a connection
						{
							//accept
							struct sockaddr_in caddr;
							int len = sizeof(caddr);

							int c = accept(sockfd, (struct sockaddr *)&caddr, (socklen_t *)&len); //Accept new client connections
							if (c < 0)
							{
								continue;
							}

							printf("accept c=%d\n", c);
							fds_add(fds, c); //Add the connection socket to the array where the file descriptor is stored
							TableRow newClient(-1, c, "UNKNOWN");
							table.push_back(newClient);
							printTable();

							sendTableToAllRouters();

						}
						else //Receive data recv when an existing client sends data
						{
							char buff[500] = {0};
							int res = recv(fds[i], buff, 499, 0);
							if (res <= 0)
							{
								close(fds[i]);
								auto index_vec = findAllRowsByFD(fds[i]);

								fds[i] = -1;
								printf("one client over\n");

								for (int i=0; i<index_vec.size(); i++)
								{
									table.erase(table.begin() + index_vec[i]);
									if (i+1!=index_vec.size())
										index_vec[i+1]--;
								}

								printTable();
								sendTableToAllRouters();
							}
							else
							{
								printf("recv(%d)=%s\n", fds[i], buff); //Output Client Sent Information
								handlePacket(fds[i], buff);
							}
						}
					}
					catch (...)
					{
						cout<<"Crashed!"<<endl;
						// send(fds[i], "BAD", 3, 0);
						sleep(5);
					}
				}
			}
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x388, %rsp            # imm = 0x388
movq 0x64ac(%rip), %r15      # 0xafd0
leaq 0x3638(%rip), %rsi      # 0x8163
movl $0x26, %edx
movq %r15, %rdi
callq 0x22b0
movq 0x64a1(%rip), %rdi      # 0xafe0
leaq 0x66fa(%rip), %rsi      # 0xb240
callq 0x2170
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2080
cmpl $-0x1, %eax
jne 0x4b80
leaq 0x3622(%rip), %rdi      # 0x818a
leaq 0x3628(%rip), %rsi      # 0x8197
leaq 0x3631(%rip), %rcx      # 0x81a7
movl $0x1ae, %edx            # imm = 0x1AE
callq 0x2180
movl %eax, %ebp
leaq 0x3629(%rip), %rdi      # 0x81b2
movl %eax, %esi
xorl %eax, %eax
callq 0x2050
pxor %xmm0, %xmm0
leaq 0x370(%rsp), %rbx
movdqa %xmm0, (%rbx)
movw $0x2, (%rbx)
movzwl 0x6692(%rip), %eax      # 0xb240
rolw $0x8, %ax
movw %ax, 0x2(%rbx)
leaq 0x3600(%rip), %rdi      # 0x81bd
callq 0x2260
movl %eax, 0x4(%rbx)
movl %ebp, %edi
movq %rbx, %rsi
movl $0x10, %edx
callq 0x2070
cmpl $-0x1, %eax
jne 0x4bf8
leaq 0x35e7(%rip), %rdi      # 0x81c7
leaq 0x35b0(%rip), %rsi      # 0x8197
leaq 0x35b9(%rip), %rcx      # 0x81a7
movl $0x1b9, %edx            # imm = 0x1B9
callq 0x2180
movl %ebp, %edi
movl $0x5, %esi
callq 0x2290
pcmpeqd %xmm0, %xmm0
movdqa %xmm0, 0xb0(%rsp)
movdqa %xmm0, 0xa0(%rsp)
movq $-0x1, 0xc0(%rsp)
xorl %eax, %eax
cmpl $-0x1, 0xa0(%rsp,%rax,4)
je 0x4c3d
incq %rax
cmpq $0xa, %rax
jne 0x4c28
jmp 0x4c44
movl %ebp, 0xa0(%rsp,%rax,4)
movq 0x6395(%rip), %r12      # 0xafe0
leaq 0x344d(%rip), %rbx      # 0x809f
leaq 0x344c(%rip), %r14      # 0x80a5
movl $0x36, %edx
movq %r15, %rdi
leaq 0x3569(%rip), %rsi      # 0x81d1
callq 0x22b0
movq %r12, %rdi
leaq 0xb(%rsp), %rsi
callq 0x22f0
movb 0xb(%rsp), %al
andb $-0x21, %al
cmpb $0x4e, %al
je 0x4fce
movl $0x28, %edx
movq %r15, %rdi
leaq 0x3571(%rip), %rsi      # 0x8208
callq 0x22b0
movq %r12, %rdi
leaq 0xc(%rsp), %rsi
callq 0x2170
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2080
cmpl $-0x1, %eax
je 0x54ad
movl %eax, %r13d
pxor %xmm0, %xmm0
movdqa %xmm0, 0x30(%rsp)
movw $0x2, 0x30(%rsp)
movzwl 0xc(%rsp), %eax
rolw $0x8, %ax
movw %ax, 0x32(%rsp)
leaq 0x34d1(%rip), %rdi      # 0x81bd
callq 0x2260
movl %eax, 0x34(%rsp)
movl %r13d, %edi
leaq 0x30(%rsp), %rsi
movl $0x10, %edx
callq 0x21f0
cmpl $-0x1, %eax
je 0x54cc
movl 0x6529(%rip), %r15d     # 0xb240
leaq 0x90(%rsp), %rax
movq %rax, 0x80(%rsp)
leaq 0x80(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x7150
movl %r15d, 0x170(%rsp)
movl $0xffffffff, 0x174(%rsp) # imm = 0xFFFFFFFF
movw $0x0, 0x178(%rsp)
movl $0x0, 0x17c(%rsp)
leaq 0x190(%rsp), %rax
movq %rax, 0x180(%rsp)
movq 0x80(%rsp), %rsi
movq 0x88(%rsp), %rdx
addq %rsi, %rdx
leaq 0x180(%rsp), %rdi
callq 0x70c0
movb $0x0, 0x1a0(%rsp)
movq $-0x1, 0x1a4(%rsp)
movq 0x80(%rsp), %rdi
leaq 0x90(%rsp), %rax
cmpq %rax, %rdi
je 0x4dcb
movq 0x90(%rsp), %rsi
incq %rsi
callq 0x2270
movl $0x36, %edx
movq 0x61f9(%rip), %rdi      # 0xafd0
leaq 0x3467(%rip), %rsi      # 0x8245
callq 0x22b0
movq 0x61e6(%rip), %rcx      # 0xafd0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2240
movsbl %al, %esi
movq 0x61c8(%rip), %rdi      # 0xafd0
callq 0x2030
movq %rax, %rdi
callq 0x2190
movl 0x6425(%rip), %edx      # 0xb240
movl 0xc(%rsp), %ecx
leaq 0x10(%rsp), %rdi
movl $0x2, %esi
leaq 0x170(%rsp), %r8
callq 0x2a0b
movq 0x10(%rsp), %r15
movq %r15, %rdi
callq 0x2110
movl %r13d, %edi
movq %r15, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
callq 0x2120
movq 0x6176(%rip), %rcx      # 0xafd0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2240
movsbl %al, %esi
movq 0x6158(%rip), %rdi      # 0xafd0
callq 0x2030
movq %rax, %rdi
callq 0x2190
movl 0xc(%rsp), %r15d
leaq 0x70(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x60(%rsp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x7150
movl %r15d, 0xf0(%rsp)
movl %r13d, 0xf4(%rsp)
movw $0x0, 0xf8(%rsp)
movl $0x0, 0xfc(%rsp)
leaq 0x110(%rsp), %r15
movq %r15, 0x100(%rsp)
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %rdx
addq %rsi, %rdx
leaq 0x100(%rsp), %rdi
callq 0x70c0
movb $0x0, 0x120(%rsp)
movq $-0x1, 0x124(%rsp)
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x4f23
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x2270
leaq 0x62fe(%rip), %rdi      # 0xb228
leaq 0xf0(%rsp), %rsi
callq 0x6c66
xorl %eax, %eax
cmpl $-0x1, 0xa0(%rsp,%rax,4)
je 0x4f4e
incq %rax
cmpq $0xa, %rax
jne 0x4f39
jmp 0x4f56
movl %r13d, 0xa0(%rsp,%rax,4)
callq 0x33d3
movq 0x100(%rsp), %rdi
cmpq %r15, %rdi
je 0x4f78
movq 0x110(%rsp), %rsi
incq %rsi
callq 0x2270
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x4f94
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2270
movq 0x180(%rsp), %rdi
leaq 0x190(%rsp), %rax
cmpq %rax, %rdi
je 0x4fb9
movq 0x190(%rsp), %rsi
incq %rsi
callq 0x2270
movb 0xb(%rsp), %al
andb $-0x21, %al
cmpb $0x4e, %al
movq 0x6008(%rip), %r15      # 0xafd0
jne 0x4c59
leaq 0x6253(%rip), %r12      # 0xb228
leaq 0x170(%rsp), %r14
pxor %xmm0, %xmm0
movdqa %xmm0, 0x160(%rsp)
movdqa %xmm0, 0x150(%rsp)
movdqa %xmm0, 0x140(%rsp)
movdqa %xmm0, 0x130(%rsp)
movdqa %xmm0, 0x120(%rsp)
movdqa %xmm0, 0x110(%rsp)
movdqa %xmm0, 0x100(%rsp)
movdqa %xmm0, 0xf0(%rsp)
xorl %eax, %eax
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movl 0xa0(%rsp,%rax,4), %edx
cmpl $-0x1, %edx
je 0x506c
leal 0x3f(%rdx), %esi
testl %edx, %edx
cmovnsl %edx, %esi
movl %esi, %r8d
andl $-0x40, %r8d
movl %edx, %ecx
subl %r8d, %ecx
movl $0x1, %r8d
shlq %cl, %r8
sarl $0x6, %esi
movslq %esi, %rcx
orq %r8, 0xf0(%rsp,%rcx,8)
cmpl %edi, %edx
cmovgl %edx, %edi
incq %rax
cmpq $0xa, %rax
jne 0x5030
movdqu 0x2fb3(%rip), %xmm0     # 0x8030
movdqa %xmm0, 0x30(%rsp)
incl %edi
leaq 0xf0(%rsp), %rsi
xorl %edx, %edx
xorl %ecx, %ecx
leaq 0x30(%rsp), %r8
callq 0x2230
testl %eax, %eax
je 0x5481
cmpl $-0x1, %eax
je 0x549c
xorl %ebx, %ebx
movl 0xa0(%rsp,%rbx,4), %r13d
cmpl $-0x1, %r13d
je 0x5380
leal 0x3f(%r13), %eax
testl %r13d, %r13d
cmovnsl %r13d, %eax
sarl $0x6, %eax
cltq
movq 0xf0(%rsp,%rax,8), %rax
btq %r13, %rax
jae 0x5380
cmpl %ebp, %r13d
jne 0x513a
movl $0x10, 0xc(%rsp)
movl %ebp, %edi
leaq 0x10(%rsp), %rsi
leaq 0xc(%rsp), %rdx
callq 0x20c0
movl %eax, %r15d
testl %eax, %eax
js 0x5380
leaq 0x3177(%rip), %rdi      # 0x8289
movl %r15d, %esi
xorl %eax, %eax
callq 0x2050
xorl %eax, %eax
cmpl $-0x1, 0xa0(%rsp,%rax,4)
je 0x5295
incq %rax
cmpq $0xa, %rax
jne 0x511e
jmp 0x529d
movl $0x1f4, %edx            # imm = 0x1F4
movq %r14, %rdi
xorl %esi, %esi
callq 0x2150
movl $0x1f3, %edx            # imm = 0x1F3
movl %r13d, %edi
movq %r14, %rsi
xorl %ecx, %ecx
callq 0x20d0
leaq (%rsp,%rbx,4), %r15
addq $0xa0, %r15
testl %eax, %eax
jle 0x51e5
leaq 0x312d(%rip), %rdi      # 0x829e
movl %r13d, %esi
movq %r14, %rdx
xorl %eax, %eax
callq 0x2050
leaq 0xe0(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq %r14, %rdi
callq 0x2110
leaq (%rsp,%rax), %rdx
addq $0x170, %rdx            # imm = 0x170
leaq 0xd0(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x7150
movq %r15, %rdi
movq %r13, %rsi
callq 0x3c07
movq 0xd0(%rsp), %rdi
leaq 0xe0(%rsp), %rax
cmpq %rax, %rdi
je 0x5380
movq 0xe0(%rsp), %rsi
jmp 0x5378
movl %r13d, %edi
callq 0x23f0
leaq 0x10(%rsp), %rdi
movl %r13d, %esi
callq 0x3769
movl $0xffffffff, (%r15)     # imm = 0xFFFFFFFF
leaq 0x30f5(%rip), %rdi      # 0x82fd
callq 0x2340
movq 0x10(%rsp), %rax
cmpq %rax, 0x18(%rsp)
je 0x526b
xorl %r15d, %r15d
movslq (%rax,%r15,4), %rsi
shlq $0x6, %rsi
addq 0x5ffd(%rip), %rsi      # 0xb228
movq %r12, %rdi
callq 0x7852
leaq 0x1(%r15), %rcx
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
cmpq %rdx, %rcx
je 0x5252
decl 0x4(%rax,%r15,4)
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
movq %rcx, %r15
cmpq %rcx, %rdx
ja 0x521c
callq 0x33d3
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3823
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x5380
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
jmp 0x537b
movl %r15d, 0xa0(%rsp,%rax,4)
leaq 0x50(%rsp), %rax
movq %rax, 0x40(%rsp)
leaq 0x40(%rsp), %rdi
leaq 0x2fe3(%rip), %rsi      # 0x8296
leaq 0x2fe3(%rip), %rdx      # 0x829d
callq 0x7150
movl $0xffffffff, 0x170(%rsp) # imm = 0xFFFFFFFF
movl %r15d, 0x174(%rsp)
movw $0x0, 0x178(%rsp)
movl $0x0, 0x17c(%rsp)
leaq 0x190(%rsp), %rax
movq %rax, 0x180(%rsp)
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq %rsi, %rdx
leaq 0x180(%rsp), %rdi
callq 0x70c0
movb $0x0, 0x1a0(%rsp)
movq $-0x1, 0x1a4(%rsp)
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x5341
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x2270
movq %r12, %rdi
movq %r14, %rsi
callq 0x6c66
callq 0x33d3
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3823
movq 0x180(%rsp), %rdi
leaq 0x190(%rsp), %rax
cmpq %rax, %rdi
je 0x5380
movq 0x190(%rsp), %rsi
incq %rsi
callq 0x2270
incq %rbx
cmpq $0xa, %rbx
jne 0x50ae
jmp 0x4fdd
jmp 0x53d7
movq %rax, %r15
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x541b
movq 0x50(%rsp), %rsi
jmp 0x53fc
movq %rax, %r15
movq 0xd0(%rsp), %rdi
leaq 0xe0(%rsp), %rax
cmpq %rax, %rdi
je 0x541b
movq 0xe0(%rsp), %rsi
jmp 0x53fc
jmp 0x53d7
jmp 0x53d7
jmp 0x5401
jmp 0x53d7
movq %rax, %r15
jmp 0x541b
movq %rax, %r15
movq 0x180(%rsp), %rdi
leaq 0x190(%rsp), %rax
cmpq %rax, %rdi
je 0x541b
movq 0x190(%rsp), %rsi
incq %rsi
jmp 0x5416
movq %rax, %r15
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x541b
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2270
movq %r15, %rdi
callq 0x2100
movl $0x8, %edx
movq 0x5ba1(%rip), %rdi      # 0xafd0
leaq 0x2e75(%rip), %rsi      # 0x82ab
callq 0x22b0
movq 0x5b8e(%rip), %rcx      # 0xafd0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2240
movsbl %al, %esi
movq 0x5b70(%rip), %rdi      # 0xafd0
callq 0x2030
movq %rax, %rdi
callq 0x2190
movl $0x5, %edi
callq 0x21c0
callq 0x2380
jmp 0x5380
leaq 0x2c77(%rip), %rdi      # 0x80ff
callq 0x2340
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3823
jmp 0x4fdd
leaq 0x2dd9(%rip), %rdi      # 0x827c
callq 0x2200
jmp 0x4fdd
leaq 0x2d7d(%rip), %rdi      # 0x8231
leaq 0x2cdc(%rip), %rsi      # 0x8197
leaq 0x2ce5(%rip), %rcx      # 0x81a7
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x2180
leaq 0x2cf4(%rip), %rdi      # 0x81c7
leaq 0x2cbd(%rip), %rsi      # 0x8197
leaq 0x2cc6(%rip), %rcx      # 0x81a7
movl $0x1ec, %edx            # imm = 0x1EC
callq 0x2180
movq %rax, %rbx
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x556d
movq 0x70(%rsp), %rsi
jmp 0x554e
jmp 0x556a
jmp 0x558b
movq %rax, %rbx
movq 0x80(%rsp), %rdi
leaq 0x90(%rsp), %rax
cmpq %rax, %rdi
je 0x55b3
movq 0x90(%rsp), %rsi
jmp 0x55ab
movq %rax, %rbx
jmp 0x55b3
movq %rax, %rbx
movq 0x100(%rsp), %rdi
cmpq %r15, %rdi
je 0x556d
movq 0x110(%rsp), %rsi
incq %rsi
callq 0x2270
jmp 0x556d
movq %rax, %rbx
callq 0x2380
jmp 0x55b3
movq %rax, %rdi
callq 0x7047
movq %rax, %rbx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x558e
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2270
jmp 0x558e
movq %rax, %rbx
movq 0x180(%rsp), %rdi
leaq 0x190(%rsp), %rax
cmpq %rax, %rdi
je 0x55b3
movq 0x190(%rsp), %rsi
incq %rsi
callq 0x2270
movq %rbx, %rdi
callq 0x23a0
nop