// File: Distrotech[P]stund/stun.cxx
// Function: stunNatType(StunAddress4&, bool, bool*, bool*, int, StunAddress4*)
NatType
stunNatType( StunAddress4& dest, 
             bool verbose,
             bool* preservePort, // if set, is return for if NAT preservers ports or not
             bool* hairpin,  // if set, is the return for if NAT will hairpin packets
             int port, // port to use for the test, 0 to choose random port
             StunAddress4* sAddr // NIC to use 
   )
{ 
   assert( dest.addr != 0 );
   assert( dest.port != 0 );
	
   if ( hairpin ) 
   {
      *hairpin = false;
   }
	
   if ( port == 0 )
   {
      port = stunRandomPort();
   }
   UInt32 interfaceIp=0;
   if (sAddr)
   {
      interfaceIp = sAddr->addr;
   }
   Socket myFd1 = openPort(port,interfaceIp,verbose);
   Socket myFd2 = openPort(port+1,interfaceIp,verbose);

   if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )
   {
        cerr << "Some problem opening port/interface to send on" << endl;
       return StunTypeFailure; 
   }

   assert( myFd1 != INVALID_SOCKET );
   assert( myFd2 != INVALID_SOCKET );
    
   bool respTestI=false;
   bool isNat=true;
   StunAddress4 testIchangedAddr;
   StunAddress4 testImappedAddr;
   bool respTestI2=false; 
   bool mappedIpSame = true;
   StunAddress4 testI2mappedAddr;
   StunAddress4 testI2dest=dest;
   bool respTestII=false;
   bool respTestIII=false;

   bool respTestHairpin=false;
   bool respTestPreservePort=false;
	
   memset(&testImappedAddr,0,sizeof(testImappedAddr));
	
   StunAtrString username;
   StunAtrString password;
	
   username.sizeValue = 0;
   password.sizeValue = 0;
	
#ifdef USE_TLS 
   stunGetUserNameAndPassword( dest, username, password );
#endif
	
   int count=0;
   while ( count < 7 )
   {
      struct timeval tv;
      fd_set fdSet; 
#ifdef WIN32
      unsigned int fdSetSize;
#else
      int fdSetSize;
#endif
      FD_ZERO(&fdSet); fdSetSize=0;
      FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;
      FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;
      tv.tv_sec=0;
      tv.tv_usec=150*1000; // 150 ms 
      if ( count == 0 ) tv.tv_usec=0;
		
      int  err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
      int e = getErrno();
      if ( err == SOCKET_ERROR )
      {
         // error occured
         cerr << "Error " << e << " " << strerror(e) << " in select" << endl;
        return StunTypeFailure; 
     }
      else if ( err == 0 )
      {
         // timeout occured 
         count++;
			
         if ( !respTestI ) 
         {
            stunSendTest( myFd1, dest, username, password, 1 ,verbose );
         }         
			
         if ( (!respTestI2) && respTestI ) 
         {
            // check the address to send to if valid 
            if (  ( testI2dest.addr != 0 ) &&
                  ( testI2dest.port != 0 ) )
            {
               stunSendTest( myFd1, testI2dest, username, password, 10  ,verbose);
            }
         }
			
         if ( !respTestII )
         {
            stunSendTest( myFd2, dest, username, password, 2 ,verbose );
         }
			
         if ( !respTestIII )
         {
            stunSendTest( myFd2, dest, username, password, 3 ,verbose );
         }
			
         if ( respTestI && (!respTestHairpin) )
         {
            if (  ( testImappedAddr.addr != 0 ) &&
                  ( testImappedAddr.port != 0 ) )
            {
               stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose );
            }
         }
      }
      else
      {
         //if (verbose) clog << "-----------------------------------------" << endl;
         assert( err>0 );
         // data is avialbe on some fd 
			
         for ( int i=0; i<2; i++)
         {
            Socket myFd;
            if ( i==0 ) 
            {
               myFd=myFd1;
            }
            else
            {
               myFd=myFd2;
            }
				
            if ( myFd!=INVALID_SOCKET ) 
            {					
               if ( FD_ISSET(myFd,&fdSet) )
               {
                  char msg[STUN_MAX_MESSAGE_SIZE];
                  int msgLen = sizeof(msg);
                  						
                  StunAddress4 from;
						
                  getMessage( myFd,
                              msg,
                              &msgLen,
                              &from.addr,
                              &from.port,verbose );
						
                  StunMessage resp;
                  memset(&resp, 0, sizeof(StunMessage));
						
                  stunParseMessage( msg,msgLen, resp,verbose );
						
                  if ( verbose )
                  {
                     clog << "Received message of type " << resp.msgHdr.msgType 
                          << "  id=" << (int)(resp.msgHdr.id.octet[0]) << endl;
                  }
						
                  switch( resp.msgHdr.id.octet[0] )
                  {
                     case 1:
                     {
                        if ( !respTestI )
                        {
									
                           testIchangedAddr.addr = resp.changedAddress.ipv4.addr;
                           testIchangedAddr.port = resp.changedAddress.ipv4.port;
                           testImappedAddr.addr = resp.mappedAddress.ipv4.addr;
                           testImappedAddr.port = resp.mappedAddress.ipv4.port;
			
                           respTestPreservePort = ( testImappedAddr.port == port ); 
                           if ( preservePort )
                           {
                              *preservePort = respTestPreservePort;
                           }								
									
                           testI2dest.addr = resp.changedAddress.ipv4.addr;
									
                           if (sAddr)
                           {
                              sAddr->port = testImappedAddr.port;
                              sAddr->addr = testImappedAddr.addr;
                           }
									
                           count = 0;
                        }		
                        respTestI=true;
                     }
                     break;
                     case 2:
                     {  
                        respTestII=true;
                     }
                     break;
                     case 3:
                     {
                        respTestIII=true;
                     }
                     break;
                     case 10:
                     {
                        if ( !respTestI2 )
                        {
                           testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;
                           testI2mappedAddr.port = resp.mappedAddress.ipv4.port;
								
                           mappedIpSame = false;
                           if ( (testI2mappedAddr.addr  == testImappedAddr.addr ) &&
                                (testI2mappedAddr.port == testImappedAddr.port ))
                           { 
                              mappedIpSame = true;
                           }
								
							
                        }
                        respTestI2=true;
                     }
                     break;
                     case 11:
                     {
							
                        if ( hairpin ) 
                        {
                           *hairpin = true;
                        }
                        respTestHairpin = true;
                     }
                     break;
                  }
               }
            }
         }
      }
   }
	
   // see if we can bind to this address 
   //cerr << "try binding to " << testImappedAddr << endl;
   Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false );
   if ( s != INVALID_SOCKET )
   {
      closesocket(s);
      isNat = false;
      //cerr << "binding worked" << endl;
   }
   else
   {
      isNat = true;
      //cerr << "binding failed" << endl;
   }
	
   if (verbose)
   {
      clog << "test I = " << respTestI << endl;
      clog << "test II = " << respTestII << endl;
      clog << "test III = " << respTestIII << endl;
      clog << "test I(2) = " << respTestI2 << endl;
      clog << "is nat  = " << isNat <<endl;
      clog << "mapped IP same = " << mappedIpSame << endl;
      clog << "hairpin = " << respTestHairpin << endl;
      clog << "preserver port = " << respTestPreservePort << endl;
   }
	
#if 0
   // implement logic flow chart from draft RFC
   if ( respTestI )
   {
      if ( isNat )
      {
         if (respTestII)
         {
            return StunTypeConeNat;
         }
         else
         {
            if ( mappedIpSame )
            {
               if ( respTestIII )
               {
                  return StunTypeRestrictedNat;
               }
               else
               {
                  return StunTypePortRestrictedNat;
               }
            }
            else
            {
               return StunTypeSymNat;
            }
         }
      }
      else
      {
         if (respTestII)
         {
            return StunTypeOpen;
         }
         else
         {
            return StunTypeSymFirewall;
         }
      }
   }
   else
   {
      return StunTypeBlocked;
   }
#else
   if ( respTestI ) // not blocked 
   {
      if ( isNat )
      {
         if ( mappedIpSame )
         {
            if (respTestII)
            {
               return StunTypeIndependentFilter;
            }
            else
            {
               if ( respTestIII )
               {
                  return StunTypeDependentFilter;
               }
               else
               {
                  return StunTypePortDependedFilter;
               }
            }
         }
         else // mappedIp is not same 
         {
            return StunTypeDependentMapping;
         }
      }
      else  // isNat is false
      {
         if (respTestII)
         {
            return StunTypeOpen;
         }
         else
         {
            return StunTypeFirewall;
         }
      }
   }
   else
   {
      return StunTypeBlocked;
   }
#endif
	
   return StunTypeUnknown;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1030, %rsp           # imm = 0x1030
movb %sil, %al
movq %rdi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movl %r8d, -0x2c(%rbp)
movq %r9, -0x38(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x4(%rax)
je 0x7dc3
jmp 0x7de2
leaq 0x3111(%rip), %rdi      # 0xaedb
leaq 0x2984(%rip), %rsi      # 0xa755
movl $0x75b, %edx            # imm = 0x75B
leaq 0x321f(%rip), %rcx      # 0xaffc
callq 0x2140
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
cmpl $0x0, %eax
je 0x7df0
jmp 0x7e0f
leaq 0x3122(%rip), %rdi      # 0xaf19
leaq 0x2957(%rip), %rsi      # 0xa755
movl $0x75c, %edx            # imm = 0x75C
leaq 0x31f2(%rip), %rcx      # 0xaffc
callq 0x2140
cmpq $0x0, -0x28(%rbp)
je 0x7e1d
movq -0x28(%rbp), %rax
movb $0x0, (%rax)
cmpl $0x0, -0x2c(%rbp)
jne 0x7e2b
callq 0x5050
movl %eax, -0x2c(%rbp)
movl $0x0, -0x3c(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x7e43
movq -0x38(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x2c(%rbp), %eax
movw %ax, %cx
movl -0x3c(%rbp), %esi
movb -0x11(%rbp), %al
andb $0x1, %al
movzwl %cx, %edi
movzbl %al, %edx
callq 0x8e90
movl %eax, -0x40(%rbp)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movw %ax, %cx
movl -0x3c(%rbp), %esi
movb -0x11(%rbp), %al
andb $0x1, %al
movzwl %cx, %edi
movzbl %al, %edx
callq 0x8e90
movl %eax, -0x44(%rbp)
cmpl $-0x1, -0x40(%rbp)
je 0x7e8a
cmpl $-0x1, -0x44(%rbp)
jne 0x7eb8
movq 0x615f(%rip), %rdi      # 0xdff0
leaq 0x31b3(%rip), %rsi      # 0xb04b
callq 0x21f0
movq %rax, %rdi
movq 0x6119(%rip), %rsi      # 0xdfc0
callq 0x2200
movl $0x1, -0x4(%rbp)
jmp 0x878f
cmpl $-0x1, -0x40(%rbp)
je 0x7ec0
jmp 0x7edf
leaq 0x31b3(%rip), %rdi      # 0xb07a
leaq 0x2887(%rip), %rsi      # 0xa755
movl $0x775, %edx            # imm = 0x775
leaq 0x3122(%rip), %rcx      # 0xaffc
callq 0x2140
cmpl $-0x1, -0x44(%rbp)
je 0x7ee7
jmp 0x7f06
leaq 0x31a4(%rip), %rdi      # 0xb092
leaq 0x2860(%rip), %rsi      # 0xa755
movl $0x776, %edx            # imm = 0x776
leaq 0x30fb(%rip), %rcx      # 0xaffc
callq 0x2140
movb $0x0, -0x45(%rbp)
movb $0x1, -0x46(%rbp)
movb $0x0, -0x59(%rbp)
movb $0x1, -0x5a(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x6c(%rbp)
movb $0x0, -0x6d(%rbp)
movb $0x0, -0x6e(%rbp)
movb $0x0, -0x6f(%rbp)
movb $0x0, -0x70(%rbp)
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0x2130
movw $0x0, -0x72(%rbp)
movw $0x0, -0x174(%rbp)
movl $0x0, -0x278(%rbp)
cmpl $0x7, -0x278(%rbp)
jge 0x8564
jmp 0x7f69
leaq -0x308(%rbp), %rax
movq %rax, -0x318(%rbp)
movl $0x0, -0x310(%rbp)
movl -0x310(%rbp), %eax
cmpq $0x10, %rax
jae 0x7fb3
movq -0x318(%rbp), %rax
movl -0x310(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x310(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x310(%rbp)
jmp 0x7f81
jmp 0x7fb5
movl $0x0, -0x30c(%rbp)
movl -0x40(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movl -0x40(%rbp), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x308(%rbp,%rax,8), %rcx
movq %rcx, -0x308(%rbp,%rax,8)
movl -0x40(%rbp), %eax
addl $0x1, %eax
cmpl -0x30c(%rbp), %eax
jle 0x8012
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x100c(%rbp)
jmp 0x801e
movl -0x30c(%rbp), %eax
movl %eax, -0x100c(%rbp)
movl -0x100c(%rbp), %eax
movl %eax, -0x30c(%rbp)
movl -0x44(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movl -0x44(%rbp), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x308(%rbp,%rax,8), %rcx
movq %rcx, -0x308(%rbp,%rax,8)
movl -0x44(%rbp), %eax
addl $0x1, %eax
cmpl -0x30c(%rbp), %eax
jle 0x807d
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1010(%rbp)
jmp 0x8089
movl -0x30c(%rbp), %eax
movl %eax, -0x1010(%rbp)
movl -0x1010(%rbp), %eax
movl %eax, -0x30c(%rbp)
movq $0x0, -0x288(%rbp)
movq $0x249f0, -0x280(%rbp) # imm = 0x249F0
cmpl $0x0, -0x278(%rbp)
jne 0x80bf
movq $0x0, -0x280(%rbp)
movl -0x30c(%rbp), %edi
leaq -0x308(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x288(%rbp), %r8
movq %rcx, %rdx
callq 0x21d0
movl %eax, -0x31c(%rbp)
callq 0x8e80
movl %eax, -0x320(%rbp)
cmpl $-0x1, -0x31c(%rbp)
jne 0x8174
movq 0x5ef0(%rip), %rdi      # 0xdff0
leaq 0x2fa3(%rip), %rsi      # 0xb0aa
callq 0x21f0
movq %rax, %rdi
movl -0x320(%rbp), %esi
callq 0x2300
movq %rax, %rdi
leaq 0x2369(%rip), %rsi      # 0xa48d
callq 0x21f0
movq %rax, -0x1018(%rbp)
movl -0x320(%rbp), %edi
callq 0x20b0
movq -0x1018(%rbp), %rdi
movq %rax, %rsi
callq 0x21f0
movq %rax, %rdi
leaq 0x2f5d(%rip), %rsi      # 0xb0b1
callq 0x21f0
movq %rax, %rdi
movq 0x5e5d(%rip), %rsi      # 0xdfc0
callq 0x2200
movl $0x1, -0x4(%rbp)
jmp 0x878f
cmpl $0x0, -0x31c(%rbp)
jne 0x82ae
movl -0x278(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x278(%rbp)
testb $0x1, -0x45(%rbp)
jne 0x81bf
movl -0x40(%rbp), %edi
movq -0x10(%rbp), %rsi
movb -0x11(%rbp), %al
leaq -0x172(%rbp), %rdx
leaq -0x274(%rbp), %rcx
movl $0x1, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0x7b70
testb $0x1, -0x59(%rbp)
jne 0x8205
testb $0x1, -0x45(%rbp)
je 0x8205
cmpl $0x0, -0x68(%rbp)
je 0x8203
movzwl -0x6c(%rbp), %eax
cmpl $0x0, %eax
je 0x8203
movl -0x40(%rbp), %edi
movb -0x11(%rbp), %al
leaq -0x6c(%rbp), %rsi
leaq -0x172(%rbp), %rdx
leaq -0x274(%rbp), %rcx
movl $0xa, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0x7b70
jmp 0x8205
testb $0x1, -0x6d(%rbp)
jne 0x8234
movl -0x44(%rbp), %edi
movq -0x10(%rbp), %rsi
movb -0x11(%rbp), %al
leaq -0x172(%rbp), %rdx
leaq -0x274(%rbp), %rcx
movl $0x2, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0x7b70
testb $0x1, -0x6e(%rbp)
jne 0x8263
movl -0x44(%rbp), %edi
movq -0x10(%rbp), %rsi
movb -0x11(%rbp), %al
leaq -0x172(%rbp), %rdx
leaq -0x274(%rbp), %rcx
movl $0x3, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0x7b70
testb $0x1, -0x45(%rbp)
je 0x82a9
testb $0x1, -0x6f(%rbp)
jne 0x82a9
cmpl $0x0, -0x54(%rbp)
je 0x82a7
movzwl -0x58(%rbp), %eax
cmpl $0x0, %eax
je 0x82a7
movl -0x40(%rbp), %edi
movb -0x11(%rbp), %al
leaq -0x58(%rbp), %rsi
leaq -0x172(%rbp), %rdx
leaq -0x274(%rbp), %rcx
movl $0xb, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0x7b70
jmp 0x82a9
jmp 0x855d
cmpl $0x0, -0x31c(%rbp)
jle 0x82b9
jmp 0x82d8
leaq 0x2dfc(%rip), %rdi      # 0xb0bc
leaq 0x248e(%rip), %rsi      # 0xa755
movl $0x7d5, %edx            # imm = 0x7D5
leaq 0x2d29(%rip), %rcx      # 0xaffc
callq 0x2140
movl $0x0, -0x324(%rbp)
cmpl $0x2, -0x324(%rbp)
jge 0x855b
cmpl $0x0, -0x324(%rbp)
jne 0x8303
movl -0x40(%rbp), %eax
movl %eax, -0x328(%rbp)
jmp 0x830c
movl -0x44(%rbp), %eax
movl %eax, -0x328(%rbp)
cmpl $-0x1, -0x328(%rbp)
je 0x8545
movl -0x328(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x308(%rbp,%rax,8), %rax
movq %rax, -0x1020(%rbp)
movl -0x328(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x1020(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x8543
movl $0x800, -0xb34(%rbp)    # imm = 0x800
movl -0x328(%rbp), %edi
leaq -0xb30(%rbp), %rsi
leaq -0xb3c(%rbp), %rcx
addq $0x4, %rcx
leaq -0xb3c(%rbp), %r8
movb -0x11(%rbp), %al
leaq -0xb34(%rbp), %rdx
andb $0x1, %al
movzbl %al, %r9d
callq 0x91a0
leaq -0x1004(%rbp), %rdi
xorl %esi, %esi
movl $0x4c8, %edx            # imm = 0x4C8
callq 0x2130
leaq -0xb30(%rbp), %rdi
movl -0xb34(%rbp), %esi
movb -0x11(%rbp), %al
leaq -0x1004(%rbp), %rdx
andb $0x1, %al
movzbl %al, %ecx
callq 0x3380
testb $0x1, -0x11(%rbp)
je 0x842e
movq 0x5bca(%rip), %rdi      # 0xdfb0
leaq 0x2cd5(%rip), %rsi      # 0xb0c2
callq 0x21f0
movq %rax, %rdi
movzwl -0x1004(%rbp), %esi
callq 0x22f0
movq %rax, %rdi
leaq 0x2cd1(%rip), %rsi      # 0xb0dc
callq 0x21f0
movq %rax, %rdi
movzbl -0x1000(%rbp), %esi
callq 0x2300
movq %rax, %rdi
movq 0x5b97(%rip), %rsi      # 0xdfc0
callq 0x2200
movzbl -0x1000(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x1028(%rbp)
subl $0xa, %eax
ja 0x8541
movq -0x1028(%rbp), %rax
leaq 0x1fb1(%rip), %rcx      # 0xa408
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
testb $0x1, -0x45(%rbp)
jne 0x84df
movl -0xfac(%rbp), %eax
movl %eax, -0x4c(%rbp)
movw -0xfb0(%rbp), %ax
movw %ax, -0x50(%rbp)
movl -0xfe4(%rbp), %eax
movl %eax, -0x54(%rbp)
movw -0xfe8(%rbp), %ax
movw %ax, -0x58(%rbp)
movzwl -0x58(%rbp), %eax
cmpl -0x2c(%rbp), %eax
sete %al
andb $0x1, %al
movb %al, -0x70(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x84b0
movb -0x70(%rbp), %cl
movq -0x20(%rbp), %rax
andb $0x1, %cl
movb %cl, (%rax)
movl -0xfac(%rbp), %eax
movl %eax, -0x68(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x84d5
movw -0x58(%rbp), %cx
movq -0x38(%rbp), %rax
movw %cx, (%rax)
movl -0x54(%rbp), %ecx
movq -0x38(%rbp), %rax
movl %ecx, 0x4(%rax)
movl $0x0, -0x278(%rbp)
movb $0x1, -0x45(%rbp)
jmp 0x8541
movb $0x1, -0x6d(%rbp)
jmp 0x8541
movb $0x1, -0x6e(%rbp)
jmp 0x8541
testb $0x1, -0x59(%rbp)
jne 0x8529
movl -0xfe4(%rbp), %eax
movl %eax, -0x60(%rbp)
movw -0xfe8(%rbp), %ax
movw %ax, -0x64(%rbp)
movb $0x0, -0x5a(%rbp)
movl -0x60(%rbp), %eax
cmpl -0x54(%rbp), %eax
jne 0x8527
movzwl -0x64(%rbp), %eax
movzwl -0x58(%rbp), %ecx
cmpl %ecx, %eax
jne 0x8527
movb $0x1, -0x5a(%rbp)
jmp 0x8529
movb $0x1, -0x59(%rbp)
jmp 0x8541
cmpq $0x0, -0x28(%rbp)
je 0x853d
movq -0x28(%rbp), %rax
movb $0x1, (%rax)
movb $0x1, -0x6f(%rbp)
jmp 0x8543
jmp 0x8545
jmp 0x8547
movl -0x324(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x324(%rbp)
jmp 0x82e2
jmp 0x855d
jmp 0x855f
jmp 0x7f5a
movl -0x54(%rbp), %esi
xorl %edx, %edx
movl %edx, %edi
callq 0x8e90
movl %eax, -0x1008(%rbp)
cmpl $-0x1, -0x1008(%rbp)
je 0x8590
movl -0x1008(%rbp), %edi
callq 0x31c0
movb $0x0, -0x46(%rbp)
jmp 0x8594
movb $0x1, -0x46(%rbp)
testb $0x1, -0x11(%rbp)
je 0x872e
movq 0x5a0b(%rip), %rdi      # 0xdfb0
leaq 0x2b36(%rip), %rsi      # 0xb0e2
callq 0x21f0
movq %rax, %rdi
movb -0x45(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x59f5(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x59d9(%rip), %rdi      # 0xdfb0
leaq 0x2b0e(%rip), %rsi      # 0xb0ec
callq 0x21f0
movq %rax, %rdi
movb -0x6d(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x59c3(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x59a7(%rip), %rdi      # 0xdfb0
leaq 0x2ae7(%rip), %rsi      # 0xb0f7
callq 0x21f0
movq %rax, %rdi
movb -0x6e(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x5991(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x5975(%rip), %rdi      # 0xdfb0
leaq 0x2ac1(%rip), %rsi      # 0xb103
callq 0x21f0
movq %rax, %rdi
movb -0x59(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x595f(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x5943(%rip), %rdi      # 0xdfb0
leaq 0x2a9c(%rip), %rsi      # 0xb110
callq 0x21f0
movq %rax, %rdi
movb -0x46(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x592d(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x5911(%rip), %rdi      # 0xdfb0
leaq 0x2a75(%rip), %rsi      # 0xb11b
callq 0x21f0
movq %rax, %rdi
movb -0x5a(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x58fb(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x58df(%rip), %rdi      # 0xdfb0
leaq 0x2a55(%rip), %rsi      # 0xb12d
callq 0x21f0
movq %rax, %rdi
movb -0x6f(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x58c9(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0x58ad(%rip), %rdi      # 0xdfb0
leaq 0x2a2e(%rip), %rsi      # 0xb138
callq 0x21f0
movq %rax, %rdi
movb -0x70(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x2320
movq %rax, %rdi
movq 0x5897(%rip), %rsi      # 0xdfc0
callq 0x2200
testb $0x1, -0x45(%rbp)
je 0x8788
testb $0x1, -0x46(%rbp)
je 0x8770
testb $0x1, -0x5a(%rbp)
je 0x8767
testb $0x1, -0x6d(%rbp)
je 0x874f
movl $0x4, -0x4(%rbp)
jmp 0x878f
testb $0x1, -0x6e(%rbp)
je 0x875e
movl $0x5, -0x4(%rbp)
jmp 0x878f
movl $0x6, -0x4(%rbp)
jmp 0x878f
movl $0x7, -0x4(%rbp)
jmp 0x878f
testb $0x1, -0x6d(%rbp)
je 0x877f
movl $0x2, -0x4(%rbp)
jmp 0x878f
movl $0x8, -0x4(%rbp)
jmp 0x878f
movl $0x3, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x1030, %rsp           # imm = 0x1030
popq %rbp
retq
nopl (%rax,%rax)