// File: BelfordZ[P]SimpleFileServer/Server.cpp
// Function: process_request(void*)
void* process_request(void* ptr)
{
   initData* message = (initData*) ptr;

   /*
     Ditto what I said above about our sockets basically
     being a bunch of highschoolers...
   */

   std::cout << "Asking client to connect on " << message->port << std::endl;
   Socket newServer = Socket(message->port+1);
   Socket newClient = Socket(message->port);
   Socket sktOut = Socket();
   Socket sktIn = Socket();

   newServer.accept(sktIn);
   newClient.accept(sktOut);

   std::ifstream inFile;
   //std::cout << "Opening " << message->filename << "... ";
   inFile.open(message->filename.c_str());
   //std::cout << "Done!" << std::endl;
   int index = 0;
   std::string myTemp;
   sktIn.recv(myTemp);
   std::cout << "Client has ACK'd our port number response" << std::endl;
   std::string tmp;
   while(!inFile.fail())
   {
      getline(inFile, tmp);
      index += 1;
      
      //std::cout << "Server::Line " << index << " of the frame set:" << tmp << std::endl;

      //
      // Generate two FrameSets from the same line: one with all of the "Good" frames, one with
      // some "Bad" frames. Try to send the ones from the bad set first, and if we get a NAK on
      // one of them, retransmit from the known good FrameSet. Simple as that.
      //
      std::cout << "Sending line " << index << std::endl;
      FrameSet goodLine = FrameSet(tmp, false);
      FrameSet line = FrameSet(tmp);
      int numOfFrames = line.get_number_of_frames();

      //send sync frame
      sktOut.send(line.frames[0].get_frame_as_string());

      std::string syncResponse = "";
      sktIn.recv(syncResponse);
      Frame syncResponseFrame(syncResponse);
      
      if(syncResponseFrame.get_frame_type() == NAK) {
	 sktOut.send(goodLine.frames[0].get_frame_as_string());
	 std::string clientAck = "";
	 sktIn.recv(clientAck); // Discard client ACK for good SYNC frame, start sending data.
      }
      	 
      //for all the rest of the frames
      for (int i = 1; i<numOfFrames; i++)
      {
	 sktOut.send(line.frames[i].get_frame_as_string()); // try to send a frame that may be bad first
	 
	 std::string inFrameString;
	 sktIn.recv(inFrameString);
	 Frame *inFrame = new Frame(inFrameString);
	 
	 switch (inFrame->get_frame_type())
	 {
	    case ACK:
	    {
	       std::cout << "Got ACK, OK!" << std::endl;
	       break;
	    }				 
	    case NAK:
	    {
	       std::cout << "Got NAK, retransmitting!" << std::endl;
	       sktOut.send(goodLine.frames[i].get_frame_as_string()); // send a good frame since we got NAK
	       sktIn.recv(inFrameString); // discard ACK, we know the frame we sent was good
	       break;
	    }			 
	    default:
	       break;
	 }
      }
   }
   Frame goodbyeFrame(GOODBYE, " GOODBYE Client");
   sktOut.send(goodbyeFrame.get_frame_as_string());
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x580, %rsp            # imm = 0x580
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq 0xb99a(%rip), %rdi      # 0xffd8
leaq 0x6b27(%rip), %rsi      # 0xb16c
callq 0x32c0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x3480
movq %rax, %rdi
movq 0xb95d(%rip), %rsi      # 0xffc0
callq 0x3310
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
incl %esi
leaq -0x30(%rbp), %rdi
callq 0x98a0
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
leaq -0x50(%rbp), %rdi
callq 0x98a0
jmp 0x468c
leaq -0x80(%rbp), %rdi
callq 0x9860
jmp 0x4697
leaq -0xa0(%rbp), %rdi
callq 0x9860
jmp 0x46a5
leaq -0x30(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x9d80
jmp 0x46b7
leaq -0x50(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x9d80
jmp 0x46c6
leaq -0x2a8(%rbp), %rdi
callq 0x3380
jmp 0x46d4
movq -0x10(%rbp), %rdi
callq 0x3140
movq %rax, %rsi
leaq -0x2a8(%rbp), %rdi
movl $0x8, %edx
callq 0x31c0
jmp 0x46f3
movl $0x0, -0x2ac(%rbp)
leaq -0x2d0(%rbp), %rdi
movq %rdi, -0x508(%rbp)
callq 0x3400
movq -0x508(%rbp), %rsi
leaq -0xa0(%rbp), %rdi
callq 0x9e50
jmp 0x4725
movq 0xb8ac(%rip), %rdi      # 0xffd8
leaq 0x6a56(%rip), %rsi      # 0xb189
callq 0x32c0
movq %rax, -0x510(%rbp)
jmp 0x4741
movq -0x510(%rbp), %rdi
movq 0xb871(%rip), %rsi      # 0xffc0
callq 0x3310
jmp 0x4756
leaq -0x2f0(%rbp), %rdi
callq 0x3400
movq -0x2a8(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x2a8(%rbp,%rax), %rdi
callq 0x3030
movb %al, -0x511(%rbp)
jmp 0x4782
movb -0x511(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x4793
jmp 0x4dbb
leaq -0x2a8(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
callq 0x3090
jmp 0x47a8
movl -0x2ac(%rbp), %eax
incl %eax
movl %eax, -0x2ac(%rbp)
movq 0xb81b(%rip), %rdi      # 0xffd8
leaq 0x69ef(%rip), %rsi      # 0xb1b3
callq 0x32c0
movq %rax, -0x520(%rbp)
jmp 0x47d2
movq -0x520(%rbp), %rdi
movl -0x2ac(%rbp), %esi
callq 0x3480
movq %rax, -0x528(%rbp)
jmp 0x47ed
movq -0x528(%rbp), %rdi
movq 0xb7c5(%rip), %rsi      # 0xffc0
callq 0x3310
jmp 0x4802
leaq -0x308(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
xorl %edx, %edx
callq 0x87c0
jmp 0x4819
leaq -0x320(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
movl $0x1, %edx
callq 0x87c0
jmp 0x4833
leaq -0x320(%rbp), %rdi
callq 0x8bd0
movl %eax, -0x52c(%rbp)
jmp 0x4847
movl -0x52c(%rbp), %eax
movl %eax, -0x324(%rbp)
xorl %eax, %eax
movl %eax, %esi
leaq -0x320(%rbp), %rdi
callq 0x5260
movq %rax, %rsi
leaq -0x348(%rbp), %rdi
callq 0x8360
jmp 0x4874
leaq -0x80(%rbp), %rdi
leaq -0x348(%rbp), %rsi
callq 0x9de0
jmp 0x4886
leaq -0x348(%rbp), %rdi
callq 0x3548
leaq -0x369(%rbp), %rdi
movq %rdi, -0x538(%rbp)
callq 0x34a0
movq -0x538(%rbp), %rdx
leaq 0x6b1f(%rip), %rsi      # 0xb3d2
leaq -0x368(%rbp), %rdi
callq 0x3ad0
jmp 0x48c1
leaq -0x369(%rbp), %rdi
callq 0x3330
leaq -0xa0(%rbp), %rdi
leaq -0x368(%rbp), %rsi
callq 0x9e50
jmp 0x48e2
leaq -0x3b8(%rbp), %rdi
leaq -0x368(%rbp), %rsi
callq 0x80a0
jmp 0x48f7
leaq -0x3b8(%rbp), %rdi
callq 0x5080
movl %eax, -0x53c(%rbp)
jmp 0x490b
movl -0x53c(%rbp), %eax
cmpl $0x6, %eax
jne 0x4b06
xorl %eax, %eax
movl %eax, %esi
leaq -0x308(%rbp), %rdi
callq 0x5260
movq %rax, %rsi
leaq -0x3d8(%rbp), %rdi
callq 0x8360
jmp 0x493b
leaq -0x80(%rbp), %rdi
leaq -0x3d8(%rbp), %rsi
callq 0x9de0
jmp 0x494d
leaq -0x3d8(%rbp), %rdi
callq 0x3548
leaq -0x3f9(%rbp), %rdi
movq %rdi, -0x548(%rbp)
callq 0x34a0
movq -0x548(%rbp), %rdx
leaq 0x6a58(%rip), %rsi      # 0xb3d2
leaq -0x3f8(%rbp), %rdi
callq 0x3ad0
jmp 0x4988
leaq -0x3f9(%rbp), %rdi
callq 0x3330
leaq -0xa0(%rbp), %rdi
leaq -0x3f8(%rbp), %rsi
callq 0x9e50
jmp 0x49a9
leaq -0x3f8(%rbp), %rdi
callq 0x3548
jmp 0x4b06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4f0a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4f01
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4ef8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4eec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4ee0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4ed4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4ec8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4daa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4d9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x348(%rbp), %rdi
callq 0x3548
jmp 0x4d9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x369(%rbp), %rdi
callq 0x3330
jmp 0x4d9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4d92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4d86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x3d8(%rbp), %rdi
callq 0x3548
jmp 0x4d86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x3f9(%rbp), %rdi
callq 0x3330
jmp 0x4d86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x3f8(%rbp), %rdi
callq 0x3548
jmp 0x4d86
movl $0x1, -0x400(%rbp)
movl -0x400(%rbp), %eax
cmpl -0x324(%rbp), %eax
jge 0x4d51
movslq -0x400(%rbp), %rsi
leaq -0x320(%rbp), %rdi
callq 0x5260
movq %rax, %rsi
leaq -0x420(%rbp), %rdi
callq 0x8360
jmp 0x4b46
leaq -0x80(%rbp), %rdi
leaq -0x420(%rbp), %rsi
callq 0x9de0
jmp 0x4b58
leaq -0x420(%rbp), %rdi
callq 0x3548
leaq -0x440(%rbp), %rdi
movq %rdi, -0x550(%rbp)
callq 0x3400
movq -0x550(%rbp), %rsi
leaq -0xa0(%rbp), %rdi
callq 0x9e50
jmp 0x4b8c
movl $0x48, %edi
callq 0x32d0
movq %rax, -0x558(%rbp)
jmp 0x4b9f
movq -0x558(%rbp), %rdi
leaq -0x440(%rbp), %rsi
callq 0x80a0
jmp 0x4bb4
movq -0x558(%rbp), %rax
movq %rax, -0x448(%rbp)
movq -0x448(%rbp), %rdi
callq 0x5080
movl %eax, -0x55c(%rbp)
jmp 0x4bd6
movl -0x55c(%rbp), %eax
subl $0x5, %eax
je 0x4c47
jmp 0x4be3
movl -0x55c(%rbp), %eax
subl $0x6, %eax
je 0x4c7d
jmp 0x4d21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x420(%rbp), %rdi
callq 0x3548
jmp 0x4d86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4d43
movq -0x558(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
movl $0x48, %esi
callq 0x32e0
jmp 0x4d43
movq 0xb38a(%rip), %rdi      # 0xffd8
leaq 0x656c(%rip), %rsi      # 0xb1c1
callq 0x32c0
movq %rax, -0x568(%rbp)
jmp 0x4c63
movq -0x568(%rbp), %rdi
movq 0xb34f(%rip), %rsi      # 0xffc0
callq 0x3310
jmp 0x4c78
jmp 0x4d23
movq 0xb354(%rip), %rdi      # 0xffd8
leaq 0x6543(%rip), %rsi      # 0xb1ce
callq 0x32c0
movq %rax, -0x570(%rbp)
jmp 0x4c99
movq -0x570(%rbp), %rdi
movq 0xb319(%rip), %rsi      # 0xffc0
callq 0x3310
jmp 0x4cae
movslq -0x400(%rbp), %rsi
leaq -0x308(%rbp), %rdi
callq 0x5260
movq %rax, %rsi
leaq -0x468(%rbp), %rdi
callq 0x8360
jmp 0x4cd2
leaq -0x80(%rbp), %rdi
leaq -0x468(%rbp), %rsi
callq 0x9de0
jmp 0x4ce4
leaq -0x468(%rbp), %rdi
callq 0x3548
leaq -0xa0(%rbp), %rdi
leaq -0x440(%rbp), %rsi
callq 0x9e50
jmp 0x4d05
jmp 0x4d23
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x468(%rbp), %rdi
callq 0x3548
jmp 0x4d43
jmp 0x4d23
leaq -0x440(%rbp), %rdi
callq 0x3548
movl -0x400(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x400(%rbp)
jmp 0x4b10
leaq -0x440(%rbp), %rdi
callq 0x3548
jmp 0x4d86
leaq -0x3b8(%rbp), %rdi
callq 0x5190
leaq -0x368(%rbp), %rdi
callq 0x3548
leaq -0x320(%rbp), %rdi
callq 0x5280
leaq -0x308(%rbp), %rdi
callq 0x5280
jmp 0x4762
leaq -0x3b8(%rbp), %rdi
callq 0x5190
leaq -0x368(%rbp), %rdi
callq 0x3548
leaq -0x320(%rbp), %rdi
callq 0x5280
leaq -0x308(%rbp), %rdi
callq 0x5280
jmp 0x4ec8
movl $0x3, -0x4b4(%rbp)
leaq -0x4d9(%rbp), %rdi
movq %rdi, -0x578(%rbp)
callq 0x34a0
movq -0x578(%rbp), %rdx
leaq 0x6401(%rip), %rsi      # 0xb1e7
leaq -0x4d8(%rbp), %rdi
callq 0x3ad0
jmp 0x4df4
leaq -0x4b0(%rbp), %rdi
leaq -0x4b4(%rbp), %rsi
leaq -0x4d8(%rbp), %rdx
movl $0x1, %ecx
callq 0x7c40
jmp 0x4e15
leaq -0x4d8(%rbp), %rdi
callq 0x3548
leaq -0x4d9(%rbp), %rdi
callq 0x3330
leaq -0x500(%rbp), %rdi
leaq -0x4b0(%rbp), %rsi
callq 0x8360
jmp 0x4e42
leaq -0x80(%rbp), %rdi
leaq -0x500(%rbp), %rsi
callq 0x9de0
jmp 0x4e54
leaq -0x500(%rbp), %rdi
callq 0x3548
ud2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4e88
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x4d8(%rbp), %rdi
callq 0x3548
leaq -0x4d9(%rbp), %rdi
callq 0x3330
jmp 0x4ec8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x4ebc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x500(%rbp), %rdi
callq 0x3548
leaq -0x4b0(%rbp), %rdi
callq 0x5190
leaq -0x2f0(%rbp), %rdi
callq 0x3548
leaq -0x2d0(%rbp), %rdi
callq 0x3548
leaq -0x2a8(%rbp), %rdi
callq 0x30c0
leaq -0xa0(%rbp), %rdi
callq 0x9d00
leaq -0x80(%rbp), %rdi
callq 0x9d00
leaq -0x50(%rbp), %rdi
callq 0x9d00
leaq -0x30(%rbp), %rdi
callq 0x9d00
movq -0x58(%rbp), %rdi
callq 0x3490
nopl (%rax)