// File: Distrotech[P]stund/client.cxx
// Function: main
int
main(int argc, char* argv[])
{
   assert( sizeof(UInt8 ) == 1 );
   assert( sizeof(UInt16) == 2 );
   assert( sizeof(UInt32) == 4 );
    
   initNetwork();
    
   cout << "STUN client version " << STUN_VERSION << endl;
   
   int testNum = 0;
   bool verbose = false;
	
   StunAddress4 stunServerAddr;
   stunServerAddr.addr=0;

   int srcPort=0;
   StunAddress4 sAddr[MAX_NIC];
   int retval[MAX_NIC];
   int numNic=0;

   for ( int i=0; i<MAX_NIC; i++ )
   {
      sAddr[i].addr=0; 
      sAddr[i].port=0; 
      retval[i]=0;
   }
   
   for ( int arg = 1; arg<argc; arg++ )
   {
      if ( !strcmp( argv[arg] , "-v" ) )
      {
         verbose = true;
      }
      else if ( !strcmp( argv[arg] , "-i" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         if ( numNic >= MAX_NIC )
         {  
            cerr << "Can not have more than "<<  MAX_NIC <<" -i options" << endl;
            usage();
            exit(-1);
         }
         
         stunParseServerName(argv[arg], sAddr[numNic++]);
      }
      else if ( !strcmp( argv[arg] , "-p" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         srcPort = strtol( argv[arg], NULL, 10);
      }
      else    
      {
        char* ptr;
        int t =  strtol( argv[arg], &ptr, 10 );
        if ( *ptr == 0 )
        { 
           // conversion worked
           testNum = t;
           cout << "running test number " << testNum  << endl; 
        }
        else
        {
           bool ret = stunParseServerName( argv[arg], stunServerAddr);
           if ( ret != true )
           {
              cerr << argv[arg] << " is not a valid host name " << endl;
              usage();
              exit(-1);
           }
	}	
      }
   }

   if ( srcPort == 0 )
   {
      srcPort = stunRandomPort();
   }
   
   if ( numNic == 0 )
   {
      // use default 
      numNic = 1;
   }
   
   for ( int nic=0; nic<numNic; nic++ )
   {
      sAddr[nic].port=srcPort;
      if ( stunServerAddr.addr == 0 )
      {
         usage();
         exit(-1);
      }
   
      if (testNum==0)
      {
         bool presPort=false;
         bool hairpin=false;
		
         NatType stype = stunNatType( stunServerAddr, verbose, &presPort, &hairpin, 
                                      srcPort, &sAddr[nic]);
		
         if ( nic == 0 )
         {
            cout << "Primary: ";
         }
         else
         {
            cout << "Secondary: ";
         }
         
         switch (stype)
         {
            case StunTypeFailure:
               cout << "Some stun error detetecting NAT type";
	       retval[nic] = -1;
               exit(-1);
               break;
            case StunTypeUnknown:
               cout << "Some unknown type error detetecting NAT type";
	       retval[nic] = 0xEE;
               break;
            case StunTypeOpen:
               cout << "Open";
	       retval[nic] = 0x00; 
               break;
            case StunTypeIndependentFilter:
               cout << "Independent Mapping, Independent Filter";
               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
               retval[nic] = 0x02;
               break;
            case StunTypeDependentFilter:
               cout << "Independent Mapping, Address Dependent Filter";
               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
               retval[nic] = 0x04;
               break;
            case StunTypePortDependedFilter:
               cout << "Independent Mapping, Port Dependent Filter";
               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
               retval[nic] = 0x06;
               break;
            case StunTypeDependentMapping:
               cout << "Dependent Mapping";
               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
               retval[nic] = 0x08;
               break;
            case StunTypeFirewall:
               cout << "Firewall";
               retval[nic] = 0x0A;
               break;
            case StunTypeBlocked:
               cout << "Blocked or could not reach STUN server";
               retval[nic] = 0x0C;
               break;
            default:
               cout << stype;
               cout << "Unkown NAT type";
               retval[nic] = 0x0E;  // Unknown NAT type
               break;
         }
         cout << "\t"; cout.flush();
         
         if (!hairpin)
         {
             retval[nic] |= 0x10;
         }       

         if (presPort)
         {
             retval[nic] |= 0x01;
         }
      }
      else if (testNum==100)
      {
         Socket myFd = openPort(srcPort,sAddr[nic].addr,verbose);
      
         StunMessage req;
         memset(&req, 0, sizeof(StunMessage));
      
         StunAtrString username;
         StunAtrString password;
         username.sizeValue = 0;
         password.sizeValue = 0;
      
         stunBuildReqSimple( &req, username, 
                             false , false , 
                             0x0c );
      
         char buf[STUN_MAX_MESSAGE_SIZE];
         int len = STUN_MAX_MESSAGE_SIZE;
      
         len = stunEncodeMessage( req, buf, len, password,verbose );
      
         if ( verbose )
         {
            cout << "About to send msg of len " << len 
                 << " to " << stunServerAddr << endl;
         }
      
         while (1)
         {
            for ( int i=0; i<100; i++ )
            {
               sendMessage( myFd,
                            buf, len, 
                            stunServerAddr.addr, 
                            stunServerAddr.port,verbose );
            }
#ifdef WIN32 // !cj! TODO - should fix this up in windows
            clock_t now = clock();
            assert( CLOCKS_PER_SEC == 1000 );
            while ( clock() <= now+10 ) { };
#else
            usleep(10*1000);
#endif
         }
      }
      else if (testNum==-2)
      {
         const int numPort = 5;
         int fd[numPort];
         StunAddress4 mappedAddr;
         
         for( int i=0; i<numPort; i++ )
         {
            fd[i] = stunOpenSocket( stunServerAddr, &mappedAddr,
                                    (srcPort==0)?0:(srcPort+i), &sAddr[nic],
                                    verbose );
            cout << "Got port at " << mappedAddr.port << endl;
         }
          
         for( int i=0; i<numPort; i++ )
         {
            closesocket(fd[i]);
         }
      }
      else if (testNum==-1)
      {
         int fd3,fd4;
         StunAddress4 mappedAddr;
         
         bool ok = stunOpenSocketPair(stunServerAddr,
                                      &mappedAddr,
                                      &fd3,
                                      &fd4,
                                      srcPort, 
                                      &sAddr[nic],
                                      verbose);
         if ( ok )
         {
            closesocket(fd3);
            closesocket(fd4);
            cout << "Got port pair at " << mappedAddr.port << endl;
         }
         else
         {
            cerr << "Opened a stun socket pair FAILED" << endl;
         }
      }
      else
      {
         stunTest( stunServerAddr,testNum,verbose,&(sAddr[nic]) );
      }
   } // end of for loop 
   cout << endl;
   
   UInt32 ret=0;
   for ( int i=numNic-1; i>=0; i-- )
   {
      if ( retval[i] == -1 )
      {
         ret = 0xFFFFFFFF;
         break;
      }
      ret = ret << 8;
      ret = ret | ( retval[i] & 0xFF );
   }
   
   cout << "Return value is " << hex << "0x";
   cout.fill('0');
   cout.width(6);
   cout << ret << dec << endl;
   cout.fill(' ');
   
   return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xfc0, %rsp            # imm = 0xFC0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
callq 0x96a0
movq 0xb99b(%rip), %rdi      # 0xdfd0
leaq 0x7b36(%rip), %rsi      # 0xa172
callq 0x21f0
movq %rax, %rdi
leaq 0x7b3c(%rip), %rsi      # 0xa187
callq 0x21f0
movq %rax, %rdi
movq 0xb966(%rip), %rsi      # 0xdfc0
callq 0x2200
movl $0x0, -0x14(%rbp)
movb $0x0, -0x15(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
cmpl $0x3, -0x54(%rbp)
jge 0x26ba
movslq -0x54(%rbp), %rax
movl $0x0, -0x3c(%rbp,%rax,8)
movslq -0x54(%rbp), %rax
movw $0x0, -0x40(%rbp,%rax,8)
movslq -0x54(%rbp), %rax
movl $0x0, -0x4c(%rbp,%rax,4)
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x2686
movl $0x1, -0x58(%rbp)
movl -0x58(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x28f6
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7aac(%rip), %rsi      # 0xa18c
callq 0x2270
cmpl $0x0, %eax
jne 0x26f3
movb $0x1, -0x15(%rbp)
jmp 0x28e6
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7a89(%rip), %rsi      # 0xa18f
callq 0x2270
cmpl $0x0, %eax
jne 0x27b5
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x58(%rbp), %eax
jg 0x2734
callq 0x2510
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
cmpl $0x3, -0x50(%rbp)
jl 0x2787
movq 0xb8af(%rip), %rdi      # 0xdff0
leaq 0x7a4a(%rip), %rsi      # 0xa192
callq 0x21f0
movq %rax, %rdi
movl $0x3, %esi
callq 0x2300
movq %rax, %rdi
leaq 0x7a46(%rip), %rsi      # 0xa1aa
callq 0x21f0
movq %rax, %rdi
movq 0xb84d(%rip), %rsi      # 0xdfc0
callq 0x2200
callq 0x2510
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x50(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0x50(%rbp)
cltq
leaq -0x40(%rbp), %rsi
shlq $0x3, %rax
addq %rax, %rsi
callq 0x56c0
jmp 0x28e4
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x79ee(%rip), %rsi      # 0xa1b6
callq 0x2270
cmpl $0x0, %eax
jne 0x2814
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x58(%rbp), %eax
jg 0x27f2
callq 0x2510
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x2280
movl %eax, -0x24(%rbp)
jmp 0x28e2
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq -0x60(%rbp), %rsi
movl $0xa, %edx
callq 0x2280
movl %eax, -0x64(%rbp)
movq -0x60(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jne 0x2872
movl -0x64(%rbp), %eax
movl %eax, -0x14(%rbp)
movq 0xb786(%rip), %rdi      # 0xdfd0
leaq 0x7968(%rip), %rsi      # 0xa1b9
callq 0x21f0
movq %rax, %rdi
movl -0x14(%rbp), %esi
callq 0x2300
movq %rax, %rdi
movq 0xb755(%rip), %rsi      # 0xdfc0
callq 0x2200
jmp 0x28e0
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq -0x20(%rbp), %rsi
callq 0x56c0
andb $0x1, %al
movb %al, -0x65(%rbp)
movb -0x65(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
je 0x28de
movq -0x10(%rbp), %rax
movslq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movq 0xb744(%rip), %rdi      # 0xdff0
callq 0x21f0
movq %rax, %rdi
leaq 0x7913(%rip), %rsi      # 0xa1ce
callq 0x21f0
movq %rax, %rdi
movq 0xb6f6(%rip), %rsi      # 0xdfc0
callq 0x2200
callq 0x2510
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
jmp 0x28e0
jmp 0x28e2
jmp 0x28e4
jmp 0x28e6
jmp 0x28e8
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x26c1
cmpl $0x0, -0x24(%rbp)
jne 0x2904
callq 0x5050
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x50(%rbp)
jne 0x2911
movl $0x1, -0x50(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x3067
movl -0x24(%rbp), %eax
movw %ax, %cx
movslq -0x6c(%rbp), %rax
movw %cx, -0x40(%rbp,%rax,8)
cmpl $0x0, -0x1c(%rbp)
jne 0x2948
callq 0x2510
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
cmpl $0x0, -0x14(%rbp)
jne 0x2d0e
movb $0x0, -0x6d(%rbp)
movb $0x0, -0x6e(%rbp)
movb -0x15(%rbp), %al
movl -0x24(%rbp), %r8d
movslq -0x6c(%rbp), %rcx
leaq -0x40(%rbp), %r9
shlq $0x3, %rcx
addq %rcx, %r9
leaq -0x20(%rbp), %rdi
leaq -0x6d(%rbp), %rdx
leaq -0x6e(%rbp), %rcx
andb $0x1, %al
movzbl %al, %esi
callq 0x7d90
movl %eax, -0x74(%rbp)
cmpl $0x0, -0x6c(%rbp)
jne 0x29a4
movq 0xb63a(%rip), %rdi      # 0xdfd0
leaq 0x784c(%rip), %rsi      # 0xa1e9
callq 0x21f0
jmp 0x29b7
movq 0xb625(%rip), %rdi      # 0xdfd0
leaq 0x7841(%rip), %rsi      # 0xa1f3
callq 0x21f0
movl -0x74(%rbp), %eax
movq %rax, -0xfa8(%rbp)
subq $0x8, %rax
ja 0x2c92
movq -0xfa8(%rbp), %rax
leaq 0x762b(%rip), %rcx      # 0xa004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0xb5e7(%rip), %rdi      # 0xdfd0
leaq 0x780f(%rip), %rsi      # 0xa1ff
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0xffffffff, -0x4c(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2240
movq 0xb5be(%rip), %rdi      # 0xdfd0
leaq 0x780b(%rip), %rsi      # 0xa224
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0xee, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb59a(%rip), %rdi      # 0xdfd0
leaq 0x7814(%rip), %rsi      # 0xa251
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0x0, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb576(%rip), %rdi      # 0xdfd0
leaq 0x77f5(%rip), %rsi      # 0xa256
callq 0x21f0
testb $0x1, -0x6d(%rbp)
je 0x2a81
movq 0xb55d(%rip), %rdi      # 0xdfd0
leaq 0x7804(%rip), %rsi      # 0xa27e
callq 0x21f0
jmp 0x2a94
movq 0xb548(%rip), %rdi      # 0xdfd0
leaq 0x7801(%rip), %rsi      # 0xa290
callq 0x21f0
testb $0x1, -0x6e(%rbp)
je 0x2aaf
movq 0xb52f(%rip), %rdi      # 0xdfd0
leaq 0x77f6(%rip), %rsi      # 0xa29e
callq 0x21f0
jmp 0x2ac2
movq 0xb51a(%rip), %rdi      # 0xdfd0
leaq 0x77f0(%rip), %rsi      # 0xa2ad
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0x2, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb4f6(%rip), %rdi      # 0xdfd0
leaq 0x77d9(%rip), %rsi      # 0xa2ba
callq 0x21f0
testb $0x1, -0x6d(%rbp)
je 0x2b01
movq 0xb4dd(%rip), %rdi      # 0xdfd0
leaq 0x7784(%rip), %rsi      # 0xa27e
callq 0x21f0
jmp 0x2b14
movq 0xb4c8(%rip), %rdi      # 0xdfd0
leaq 0x7781(%rip), %rsi      # 0xa290
callq 0x21f0
testb $0x1, -0x6e(%rbp)
je 0x2b2f
movq 0xb4af(%rip), %rdi      # 0xdfd0
leaq 0x7776(%rip), %rsi      # 0xa29e
callq 0x21f0
jmp 0x2b42
movq 0xb49a(%rip), %rdi      # 0xdfd0
leaq 0x7770(%rip), %rsi      # 0xa2ad
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0x4, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb476(%rip), %rdi      # 0xdfd0
leaq 0x7787(%rip), %rsi      # 0xa2e8
callq 0x21f0
testb $0x1, -0x6d(%rbp)
je 0x2b81
movq 0xb45d(%rip), %rdi      # 0xdfd0
leaq 0x7704(%rip), %rsi      # 0xa27e
callq 0x21f0
jmp 0x2b94
movq 0xb448(%rip), %rdi      # 0xdfd0
leaq 0x7701(%rip), %rsi      # 0xa290
callq 0x21f0
testb $0x1, -0x6e(%rbp)
je 0x2baf
movq 0xb42f(%rip), %rdi      # 0xdfd0
leaq 0x76f6(%rip), %rsi      # 0xa29e
callq 0x21f0
jmp 0x2bc2
movq 0xb41a(%rip), %rdi      # 0xdfd0
leaq 0x76f0(%rip), %rsi      # 0xa2ad
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0x6, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb3f6(%rip), %rdi      # 0xdfd0
leaq 0x7732(%rip), %rsi      # 0xa313
callq 0x21f0
testb $0x1, -0x6d(%rbp)
je 0x2c01
movq 0xb3dd(%rip), %rdi      # 0xdfd0
leaq 0x7684(%rip), %rsi      # 0xa27e
callq 0x21f0
jmp 0x2c14
movq 0xb3c8(%rip), %rdi      # 0xdfd0
leaq 0x7681(%rip), %rsi      # 0xa290
callq 0x21f0
testb $0x1, -0x6e(%rbp)
je 0x2c2f
movq 0xb3af(%rip), %rdi      # 0xdfd0
leaq 0x7676(%rip), %rsi      # 0xa29e
callq 0x21f0
jmp 0x2c42
movq 0xb39a(%rip), %rdi      # 0xdfd0
leaq 0x7670(%rip), %rsi      # 0xa2ad
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0x8, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb379(%rip), %rdi      # 0xdfd0
leaq 0x76c7(%rip), %rsi      # 0xa325
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0xa, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movq 0xb358(%rip), %rdi      # 0xdfd0
leaq 0x76af(%rip), %rsi      # 0xa32e
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0xc, -0x4c(%rbp,%rax,4)
jmp 0x2cc0
movl -0x74(%rbp), %esi
movq 0xb334(%rip), %rdi      # 0xdfd0
callq 0x2300
movq 0xb328(%rip), %rdi      # 0xdfd0
leaq 0x76a6(%rip), %rsi      # 0xa355
callq 0x21f0
movslq -0x6c(%rbp), %rax
movl $0xe, -0x4c(%rbp,%rax,4)
movq 0xb309(%rip), %rdi      # 0xdfd0
leaq 0x7697(%rip), %rsi      # 0xa365
callq 0x21f0
movq 0xb2f6(%rip), %rdi      # 0xdfd0
callq 0x2150
testb $0x1, -0x6e(%rbp)
jne 0x2cf4
movslq -0x6c(%rbp), %rax
movl -0x4c(%rbp,%rax,4), %ecx
orl $0x10, %ecx
movl %ecx, -0x4c(%rbp,%rax,4)
testb $0x1, -0x6d(%rbp)
je 0x2d09
movslq -0x6c(%rbp), %rax
movl -0x4c(%rbp,%rax,4), %ecx
orl $0x1, %ecx
movl %ecx, -0x4c(%rbp,%rax,4)
jmp 0x3057
cmpl $0x64, -0x14(%rbp)
jne 0x2e61
movl -0x24(%rbp), %eax
movw %ax, %cx
movslq -0x6c(%rbp), %rax
movl -0x3c(%rbp,%rax,8), %esi
movb -0x15(%rbp), %al
andb $0x1, %al
movzwl %cx, %edi
movzbl %al, %edx
callq 0x8e90
movl %eax, -0x78(%rbp)
leaq -0x540(%rbp), %rdi
xorl %esi, %esi
movl $0x4c8, %edx            # imm = 0x4C8
callq 0x2130
movw $0x0, -0x542(%rbp)
movw $0x0, -0x644(%rbp)
leaq -0x540(%rbp), %rdi
leaq -0x642(%rbp), %rsi
xorl %ecx, %ecx
movl $0xc, %r8d
movl %ecx, %edx
callq 0x76c0
movl $0x800, -0xf54(%rbp)    # imm = 0x800
leaq -0xf50(%rbp), %rsi
movl -0xf54(%rbp), %edx
movb -0x15(%rbp), %al
leaq -0x540(%rbp), %rdi
leaq -0x744(%rbp), %rcx
andb $0x1, %al
movzbl %al, %r8d
callq 0x44c0
movl %eax, -0xf54(%rbp)
testb $0x1, -0x15(%rbp)
je 0x2e05
movq 0xb20f(%rip), %rdi      # 0xdfd0
leaq 0x759f(%rip), %rsi      # 0xa367
callq 0x21f0
movq %rax, %rdi
movl -0xf54(%rbp), %esi
callq 0x2300
movq %rax, %rdi
leaq 0x759c(%rip), %rsi      # 0xa381
callq 0x21f0
movq %rax, %rdi
leaq -0x20(%rbp), %rsi
callq 0x4040
movq %rax, %rdi
movq 0xb1c0(%rip), %rsi      # 0xdfc0
callq 0x2200
jmp 0x2e07
movl $0x0, -0xf58(%rbp)
cmpl $0x64, -0xf58(%rbp)
jge 0x2e55
movl -0x78(%rbp), %edi
leaq -0xf50(%rbp), %rsi
movl -0xf54(%rbp), %edx
movl -0x1c(%rbp), %ecx
movw -0x20(%rbp), %r8w
movb -0x15(%rbp), %al
andb $0x1, %al
movzwl %r8w, %r8d
movzbl %al, %r9d
callq 0x93d0
movl -0xf58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf58(%rbp)
jmp 0x2e11
movl $0x2710, %edi           # imm = 0x2710
callq 0x22a0
jmp 0x2e07
cmpl $-0x2, -0x14(%rbp)
jne 0x2f6a
movl $0x5, -0xf5c(%rbp)
movl $0x0, -0xf7c(%rbp)
cmpl $0x5, -0xf7c(%rbp)
jge 0x2f2e
cmpl $0x0, -0x24(%rbp)
jne 0x2e9c
xorl %eax, %eax
movl %eax, -0xfac(%rbp)
jmp 0x2eab
movl -0x24(%rbp), %eax
addl -0xf7c(%rbp), %eax
movl %eax, -0xfac(%rbp)
movl -0xfac(%rbp), %edx
movslq -0x6c(%rbp), %rax
leaq -0x40(%rbp), %rcx
shlq $0x3, %rax
addq %rax, %rcx
movb -0x15(%rbp), %al
leaq -0x20(%rbp), %rdi
leaq -0xf78(%rbp), %rsi
andb $0x1, %al
movzbl %al, %r8d
callq 0x87a0
movl %eax, %ecx
movslq -0xf7c(%rbp), %rax
movl %ecx, -0xf70(%rbp,%rax,4)
movq 0xb0e0(%rip), %rdi      # 0xdfd0
leaq 0x748f(%rip), %rsi      # 0xa386
callq 0x21f0
movq %rax, %rdi
movzwl -0xf78(%rbp), %esi
callq 0x22f0
movq %rax, %rdi
movq 0xb0ab(%rip), %rsi      # 0xdfc0
callq 0x2200
movl -0xf7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf7c(%rbp)
jmp 0x2e7f
movl $0x0, -0xf80(%rbp)
cmpl $0x5, -0xf80(%rbp)
jge 0x2f65
movslq -0xf80(%rbp), %rax
movl -0xf70(%rbp,%rax,4), %edi
callq 0x31c0
movl -0xf80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf80(%rbp)
jmp 0x2f38
jmp 0x3053
cmpl $-0x1, -0x14(%rbp)
jne 0x302e
movl -0x24(%rbp), %r8d
movslq -0x6c(%rbp), %rax
leaq -0x40(%rbp), %r9
shlq $0x3, %rax
addq %rax, %r9
movb -0x15(%rbp), %al
leaq -0x20(%rbp), %rdi
leaq -0xf90(%rbp), %rsi
leaq -0xf84(%rbp), %rdx
leaq -0xf88(%rbp), %rcx
andb $0x1, %al
movzbl %al, %eax
movl %eax, (%rsp)
callq 0x8990
andb $0x1, %al
movb %al, -0xf91(%rbp)
testb $0x1, -0xf91(%rbp)
je 0x300a
movl -0xf84(%rbp), %edi
callq 0x31c0
movl -0xf88(%rbp), %edi
callq 0x31c0
movq 0xaff2(%rip), %rdi      # 0xdfd0
leaq 0x73ae(%rip), %rsi      # 0xa393
callq 0x21f0
movq %rax, %rdi
movzwl -0xf90(%rbp), %esi
callq 0x22f0
movq %rax, %rdi
movq 0xafbd(%rip), %rsi      # 0xdfc0
callq 0x2200
jmp 0x302c
movq 0xafdf(%rip), %rdi      # 0xdff0
leaq 0x738d(%rip), %rsi      # 0xa3a5
callq 0x21f0
movq %rax, %rdi
movq 0xaf99(%rip), %rsi      # 0xdfc0
callq 0x2200
jmp 0x3051
movl -0x14(%rbp), %esi
movb -0x15(%rbp), %al
movslq -0x6c(%rbp), %rdx
leaq -0x40(%rbp), %rcx
shlq $0x3, %rdx
addq %rdx, %rcx
leaq -0x20(%rbp), %rdi
andb $0x1, %al
movzbl %al, %edx
callq 0x78a0
jmp 0x3053
jmp 0x3055
jmp 0x3057
jmp 0x3059
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x2918
movq 0xaf62(%rip), %rdi      # 0xdfd0
movq 0xaf4b(%rip), %rsi      # 0xdfc0
callq 0x2200
movl $0x0, -0xf98(%rbp)
movl -0x50(%rbp), %eax
subl $0x1, %eax
movl %eax, -0xf9c(%rbp)
cmpl $0x0, -0xf9c(%rbp)
jl 0x30f2
movslq -0xf9c(%rbp), %rax
cmpl $-0x1, -0x4c(%rbp,%rax,4)
jne 0x30b3
movl $0xffffffff, -0xf98(%rbp) # imm = 0xFFFFFFFF
jmp 0x30f2
movl -0xf98(%rbp), %eax
shll $0x8, %eax
movl %eax, -0xf98(%rbp)
movl -0xf98(%rbp), %eax
movslq -0xf9c(%rbp), %rcx
movl -0x4c(%rbp,%rcx,4), %ecx
andl $0xff, %ecx
orl %ecx, %eax
movl %eax, -0xf98(%rbp)
movl -0xf9c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xf9c(%rbp)
jmp 0x3090
movq 0xaed7(%rip), %rdi      # 0xdfd0
leaq 0x72c6(%rip), %rsi      # 0xa3c6
callq 0x21f0
movq %rax, %rdi
leaq 0xd1(%rip), %rsi        # 0x31e0
callq 0x20c0
movq %rax, %rdi
leaq 0x72b9(%rip), %rsi      # 0xa3d7
callq 0x21f0
movq 0xaea6(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq 0xae9c(%rip), %rdi      # 0xdfd0
addq -0x18(%rax), %rdi
movl $0x30, %esi
callq 0x2210
movq 0xae87(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq 0xae7d(%rip), %rdi      # 0xdfd0
addq -0x18(%rax), %rdi
movl $0x6, %esi
callq 0x3210
movl -0xf98(%rbp), %esi
movq 0xae62(%rip), %rdi      # 0xdfd0
callq 0x2260
movq %rax, %rdi
leaq 0xc3(%rip), %rsi        # 0x3240
callq 0x20c0
movq %rax, %rdi
movq 0xae34(%rip), %rsi      # 0xdfc0
callq 0x2200
movq 0xae38(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq 0xae2e(%rip), %rdi      # 0xdfd0
addq -0x18(%rax), %rdi
movl $0x20, %esi
callq 0x2210
movl -0xf98(%rbp), %eax
addq $0xfc0, %rsp            # imm = 0xFC0
popq %rbp
retq
nop