// File: /workspace/github_cpp_makefile_star2_O2/Distrotech[P]stund/stun.cxx
// Function: stunServerProcessMsg(char*, unsigned int, StunAddress4&, StunAddress4&, StunAddress4&, StunAddress4&, StunMessage*, StunAddress4*, StunAtrString*, bool*, bool*, bool)
bool
stunServerProcessMsg( char* buf,
                      unsigned int bufLen,
                      StunAddress4& from, 
                      StunAddress4& secondary,
                      StunAddress4& myAddr,
                      StunAddress4& altAddr, 
                      StunMessage* resp,
                      StunAddress4* destination,
                      StunAtrString* hmacPassword,
                      bool* changePort,
                      bool* changeIp,
                      bool verbose)
{
    
   // set up information for default response 
	
   memset( resp, 0 , sizeof(*resp) );
	
   *changeIp = false;
   *changePort = false;
	
   StunMessage req;
   bool ok = stunParseMessage( buf,bufLen, req, verbose);
	
   if (!ok)      // Complete garbage, drop it on the floor
   {
      if (verbose) clog << "Request did not parse" << endl;
      return false;
   }
   if (verbose) clog << "Request parsed ok" << endl;
	
   StunAddress4 mapped = req.mappedAddress.ipv4;
   StunAddress4 respondTo = req.responseAddress.ipv4;
   UInt32 flags = req.changeRequest.value;
	
   switch (req.msgHdr.msgType)
   {
      case SharedSecretRequestMsg:
         if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl;
         // !cj! - should fix so you know if this came over TLS or UDP
         stunCreateSharedSecretResponse(req, from, *resp);
         //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS");
         return true;
			
      case BindRequestMsg:
         if (!req.hasMessageIntegrity)
         {
            if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl;
				
            if (0) // !jf! mustAuthenticate
            {
               if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl;
               stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity");
               return true;
            }
         }
         else
         {
            if (!req.hasUsername)
            {
               if (verbose) clog << "No UserName. Send 432." << endl;
               stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity");
               return true;
            }
            else
            {
               if (verbose) clog << "Validating username: " << req.username.value << endl;
               // !jf! could retrieve associated password from provisioning here
               if (strcmp(req.username.value, "test") == 0)
               {
                  if (0)
                  {
                     // !jf! if the credentials are stale 
                     stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest");
                     return true;
                  }
                  else
                  {
                     if (verbose) clog << "Validating MessageIntegrity" << endl;
                     // need access to shared secret
							
                     unsigned char hmac[20];
#ifndef NOSSL
                     unsigned int hmacSize=20;

                     HMAC(EVP_sha1(), 
                          "1234", 4, 
                          reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, 
                          hmac, &hmacSize);
                     assert(hmacSize == 20);
#endif
							
                     if (memcmp(buf, hmac, 20) != 0)
                     {
                        if (verbose) clog << "MessageIntegrity is bad. Sending " << endl;
                        stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234");
                        return true;
                     }
							
                     // need to compute this later after message is filled in
                     resp->hasMessageIntegrity = true;
                     assert(req.hasUsername);
                     resp->hasUsername = true;
                     resp->username = req.username; // copy username in
                  }
               }
               else
               {
                  if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl; 
               }
            }
         }
			
         // TODO !jf! should check for unknown attributes here and send 420 listing the
         // unknown attributes. 
			
         if ( respondTo.port == 0 ) respondTo = from;
         if ( mapped.port == 0 ) mapped = from;
				
         *changeIp   = ( flags & ChangeIpFlag )?true:false;
         *changePort = ( flags & ChangePortFlag )?true:false;
			
         if (verbose)
         {
            clog << "Request is valid:" << endl;
            clog << "\t flags=" << flags << endl;
            clog << "\t changeIp=" << *changeIp << endl;
            clog << "\t changePort=" << *changePort << endl;
            clog << "\t from = " << from << endl;
            clog << "\t respond to = " << respondTo << endl;
            clog << "\t mapped = " << mapped << endl;
         }
				
         // form the outgoing message
         resp->msgHdr.msgType = BindResponseMsg;
         for ( int i=0; i<16; i++ )
         {
            resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i];
         }
		
         if ( req.xorOnly == false )
         {
            resp->hasMappedAddress = true;
            resp->mappedAddress.ipv4.port = mapped.port;
            resp->mappedAddress.ipv4.addr = mapped.addr;
         }

         if (1) // do xorMapped address or not 
         {
            resp->hasXorMappedAddress = true;
            UInt16 id16 = req.msgHdr.id.octet[0]<<8 
               | req.msgHdr.id.octet[1];
            UInt32 id32 = req.msgHdr.id.octet[0]<<24 
               | req.msgHdr.id.octet[1]<<16 
               | req.msgHdr.id.octet[2]<<8 
               | req.msgHdr.id.octet[3];
            resp->xorMappedAddress.ipv4.port = mapped.port^id16;
            resp->xorMappedAddress.ipv4.addr = mapped.addr^id32;
         }
         
         resp->hasSourceAddress = true;
         resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port;
         resp->sourceAddress.ipv4.addr = (*changeIp)   ? altAddr.addr : myAddr.addr;
			
         resp->hasChangedAddress = true;
         resp->changedAddress.ipv4.port = altAddr.port;
         resp->changedAddress.ipv4.addr = altAddr.addr;
	
         if ( secondary.port != 0 )
         {
            resp->hasSecondaryAddress = true;
            resp->secondaryAddress.ipv4.port = secondary.port;
            resp->secondaryAddress.ipv4.addr = secondary.addr;
         }
         
         if ( req.hasUsername && req.username.sizeValue > 0 ) 
         {
            // copy username in
            resp->hasUsername = true;
            assert( req.username.sizeValue % 4 == 0 );
            assert( req.username.sizeValue < STUN_MAX_STRING );
            memcpy( resp->username.value, req.username.value, req.username.sizeValue );
            resp->username.sizeValue = req.username.sizeValue;
         }
		
         if (1) // add ServerName 
         {
            resp->hasServerName = true;
            const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4
            
            assert( sizeof(serverName) < STUN_MAX_STRING );
            //cerr << "sizeof serverName is "  << sizeof(serverName) << endl;
            assert( sizeof(serverName)%4 == 0 );
            memcpy( resp->serverName.value, serverName, sizeof(serverName));
            resp->serverName.sizeValue = sizeof(serverName);
         }
         
         if ( req.hasMessageIntegrity & req.hasUsername )  
         {
            // this creates the password that will be used in the HMAC when then
            // messages is sent
            stunCreatePassword( req.username, hmacPassword );
         }
				
         if (req.hasUsername && (req.username.sizeValue > 64 ) )
         {
            UInt32 source;
            assert( sizeof(int) == sizeof(UInt32) );
					
            sscanf(req.username.value, "%x", &source);
            resp->hasReflectedFrom = true;
            resp->reflectedFrom.ipv4.port = 0;
            resp->reflectedFrom.ipv4.addr = source;
         }
				
         destination->port = respondTo.port;
         destination->addr = respondTo.addr;
			
         return true;
			
      default:
         if (verbose) clog << "Unknown or unsupported request " << endl;
         return false;
   }
	
   assert(0);
   return false;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x528, %rsp            # imm = 0x528
movq %r9, 0x30(%rsp)
movq %r8, 0x28(%rsp)
movq %rcx, 0x38(%rsp)
movq %rdx, 0x10(%rsp)
movl %esi, %r14d
movq %rdi, %rbp
movb 0x588(%rsp), %bl
movq 0x580(%rsp), %r13
movq 0x578(%rsp), %r15
movq 0x560(%rsp), %rdi
xorl %r12d, %r12d
movl $0x4c8, %edx            # imm = 0x4C8
xorl %esi, %esi
callq 0x2110
movb %r12b, (%r13)
movq %r15, %rax
movl %ebx, %r15d
movb %r12b, (%rax)
movzbl %bl, %ecx
leaq 0x60(%rsp), %rdx
movq %rbp, %r13
movq %rbp, %rdi
movl %r14d, %esi
callq 0x2d54
testb %al, %al
je 0x455c
testb %r15b, %r15b
je 0x44c8
movq 0x6b04(%rip), %rdi      # 0xafb8
leaq 0x35a5(%rip), %rsi      # 0x7a60
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
movq 0x7c(%rsp), %r12
movq 0x8c(%rsp), %r14
movq %r12, 0x20(%rsp)
movq %r14, 0x18(%rsp)
movzwl 0x60(%rsp), %eax
cmpl $0x1, %eax
movq 0x560(%rsp), %rbx
je 0x4578
cmpl $0x2, %eax
jne 0x4644
testb %r15b, %r15b
je 0x451e
movq 0x6aae(%rip), %rdi      # 0xafb8
leaq 0x3561(%rip), %rsi      # 0x7a72
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
movw $0x102, (%rbx)          # imm = 0x102
movups 0x64(%rsp), %xmm0
movups %xmm0, 0x4(%rbx)
movb $0x1, %bpl
movb %bpl, 0x5c(%rbx)
leaq 0x5e(%rbx), %rsi
movq 0x10(%rsp), %rdi
callq 0x40dd
movb %bpl, 0x160(%rbx)
addq $0x162, %rbx            # imm = 0x162
movq %rbx, %rsi
callq 0x427f
jmp 0x4666
testb %r15b, %r15b
je 0x4664
movq 0x6a4c(%rip), %rdi      # 0xafb8
leaq 0x34d7(%rip), %rsi      # 0x7a4a
jmp 0x4657
movl 0x98(%rsp), %ecx
cmpb $0x0, 0x2c4(%rsp)
je 0x467a
cmpb $0x0, 0xbc(%rsp)
je 0x49e9
movq %rcx, 0x8(%rsp)
testb %r15b, %r15b
je 0x45d0
movq 0x6a0c(%rip), %rdi      # 0xafb8
leaq 0x3566(%rip), %rsi      # 0x7b19
callq 0x21d0
leaq 0xbe(%rsp), %rsi
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
leaq 0xbe(%rsp), %rbp
leaq 0x3550(%rip), %rsi      # 0x7b2f
pushq $0x5
popq %rdx
movq %rbp, %rdi
callq 0x21e0
testl %eax, %eax
je 0x4a23
testb %r15b, %r15b
movq 0x8(%rsp), %rcx
movq 0x578(%rsp), %r13
je 0x46a8
movq 0x69a9(%rip), %rdi      # 0xafb8
leaq 0x3650(%rip), %rsi      # 0x7c66
callq 0x21d0
movq %rax, %rdi
movq %rbp, %rsi
callq 0x21d0
leaq 0x364c(%rip), %rsi      # 0x7c79
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
movq 0x8(%rsp), %rcx
jmp 0x46a8
testb %r15b, %r15b
je 0x4664
movq 0x6968(%rip), %rdi      # 0xafb8
leaq 0x36d3(%rip), %rsi      # 0x7d2a
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x528, %rsp            # imm = 0x528
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb %r15b, %r15b
movq 0x578(%rsp), %r13
je 0x46a8
movq 0x692a(%rip), %rdi      # 0xafb8
movq %rcx, %rbp
leaq 0x3412(%rip), %rsi      # 0x7aaa
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
movq %rbp, %rcx
movl %r14d, %eax
testw %r14w, %r14w
jne 0x46c1
movq 0x10(%rsp), %rax
movq (%rax), %r14
movq %r14, 0x18(%rsp)
movl %r14d, %eax
movw %ax, 0x6(%rsp)
movl %r12d, %ebp
testw %r12w, %r12w
jne 0x46df
movq 0x10(%rsp), %rax
movq (%rax), %r12
movq %r12, 0x20(%rsp)
movl %r12d, %ebp
shrq $0x20, %r14
movq %r14, 0x8(%rsp)
shrq $0x20, %r12
movl %ecx, %eax
shrb $0x2, %al
andb $0x1, %al
movq 0x580(%rsp), %r14
movb %al, (%r14)
movl %ecx, %eax
shrb %al
andb $0x1, %al
movb %al, (%r13)
testb %r15b, %r15b
je 0x4820
movq 0x68a0(%rip), %rdi      # 0xafb8
movq %rcx, %r15
leaq 0x3561(%rip), %rsi      # 0x7c83
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
leaq 0x355f(%rip), %rsi      # 0x7c95
movq 0x687b(%rip), %rdi      # 0xafb8
callq 0x21d0
movq %rax, %rdi
movq %r15, %rsi
callq 0x2130
movq %rax, %rdi
callq 0x20c0
leaq 0x3542(%rip), %rsi      # 0x7c9e
movq 0x6855(%rip), %rdi      # 0xafb8
movq %rdi, %r15
callq 0x21d0
movzbl (%r14), %esi
movq %rax, %rdi
callq 0x2280
movq %rax, %rdi
callq 0x20c0
leaq 0x3524(%rip), %rsi      # 0x7caa
movq %r15, %rdi
callq 0x21d0
movzbl (%r13), %esi
movq %rax, %rdi
callq 0x2280
movq %rax, %rdi
callq 0x20c0
leaq 0x350e(%rip), %rsi      # 0x7cb8
movq %r15, %rdi
callq 0x21d0
movq %rax, %r14
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x3732
movq %r14, %rdi
callq 0x20c0
leaq 0x34f1(%rip), %rsi      # 0x7cc2
movq %r15, %rdi
callq 0x21d0
movq %rax, %r14
leaq 0x18(%rsp), %rsi
movq %rax, %rdi
callq 0x3732
movq %r14, %rdi
callq 0x20c0
leaq 0x34da(%rip), %rsi      # 0x7cd2
movq %r15, %rdi
callq 0x21d0
movq %rax, %r14
leaq 0x20(%rsp), %rsi
movq %rax, %rdi
callq 0x3732
movq %r14, %rdi
movq 0x580(%rsp), %r14
callq 0x20c0
movq %r13, %rdi
movq 0x570(%rsp), %r13
movq 0x568(%rsp), %r15
movw $0x101, (%rbx)          # imm = 0x101
xorl %eax, %eax
cmpq $0x10, %rax
je 0x484d
movb 0x64(%rsp,%rax), %cl
movb %cl, 0x4(%rbx,%rax)
incq %rax
jmp 0x483a
cmpb $0x0, 0x414(%rsp)
jne 0x4863
movb $0x1, 0x14(%rbx)
movw %bp, 0x1c(%rbx)
movl %r12d, 0x20(%rbx)
movb $0x1, %al
movb %al, 0x3a4(%rbx)
movzbl 0x64(%rsp), %ecx
movl %ecx, %edx
shll $0x8, %edx
movzbl 0x65(%rsp), %esi
orl %esi, %edx
shll $0x18, %ecx
shll $0x10, %esi
orl %ecx, %esi
movzbl 0x66(%rsp), %ecx
shll $0x8, %ecx
orl %esi, %ecx
movzbl 0x67(%rsp), %esi
orl %ecx, %esi
xorl %edx, %ebp
movw %bp, 0x3ac(%rbx)
xorl %r12d, %esi
movl %esi, 0x3b0(%rbx)
movb %al, 0x3c(%rbx)
cmpb $0x0, (%rdi)
movq 0x28(%rsp), %rsi
movq %rsi, %rcx
movq 0x30(%rsp), %rdx
cmovneq %rdx, %rcx
movzwl (%rcx), %ecx
movw %cx, 0x44(%rbx)
cmpb $0x0, (%r14)
cmovneq %rdx, %rsi
movl 0x4(%rsi), %ecx
movl %ecx, 0x48(%rbx)
movb %al, 0x4c(%rbx)
movzwl (%rdx), %eax
movw %ax, 0x54(%rbx)
movl 0x4(%rdx), %eax
movl %eax, 0x58(%rbx)
movq 0x38(%rsp), %rcx
movzwl (%rcx), %eax
testw %ax, %ax
je 0x4907
movb $0x1, 0x4b8(%rbx)
movw %ax, 0x4c0(%rbx)
movl 0x4(%rcx), %eax
movl %eax, 0x4c4(%rbx)
leaq 0xbe(%rsp), %r14
movb -0x2(%r14), %r12b
movzwl 0x100(%r14), %ebp
testw %bp, %bp
setne %al
andb %r12b, %al
cmpb $0x1, %al
jne 0x4957
movb $0x1, 0x5c(%rbx)
testb $0x3, %bpl
jne 0x4aba
cmpw $0x100, %bp             # imm = 0x100
jae 0x4ad9
movzwl %bp, %edx
leaq 0x5e(%rbx), %rdi
movq %r14, %rsi
callq 0x2170
movw %bp, 0x15e(%rbx)
movb $0x1, 0x3b5(%rbx)
movaps 0x39fb(%rip), %xmm0     # 0x8360
movups %xmm0, 0x3b6(%rbx)
movw $0x10, 0x4b6(%rbx)
testb %r12b, 0x2c4(%rsp)
je 0x4997
movq %r13, %rsi
callq 0x427f
movb 0xbc(%rsp), %r12b
movzwl 0x1be(%rsp), %ebp
testb $0x1, %r12b
je 0x49d5
cmpw $0x41, %bp
jb 0x49d5
leaq 0x337d(%rip), %rsi      # 0x7d27
leaq 0x40(%rsp), %r12
movq %r14, %rdi
movq %r12, %rdx
xorl %eax, %eax
callq 0x21c0
movb $0x1, 0x394(%rbx)
andw $0x0, 0x39c(%rbx)
movl (%r12), %eax
movl %eax, 0x3a0(%rbx)
movzwl 0x6(%rsp), %eax
movw %ax, (%r15)
movq 0x8(%rsp), %rax
movl %eax, 0x4(%r15)
jmp 0x4a1b
testb %r15b, %r15b
je 0x4a09
movq 0x65c3(%rip), %rdi      # 0xafb8
leaq 0x30dc(%rip), %rsi      # 0x7ad8
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
leaq 0x30df(%rip), %rdx      # 0x7aef
pushq $0x20
popq %rsi
movq %rbx, %rdi
callq 0x4b17
movb $0x1, %bpl
jmp 0x4666
testb %r15b, %r15b
je 0x4a43
movq 0x6589(%rip), %rdi      # 0xafb8
leaq 0x30fe(%rip), %rsi      # 0x7b34
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
leaq 0x40(%rsp), %rsi
pushq $0x14
popq %rdx
movq %r13, %rdi
callq 0x21e0
testl %eax, %eax
je 0x4a82
testb %r15b, %r15b
je 0x4a77
movq 0x6555(%rip), %rdi      # 0xafb8
leaq 0x30e6(%rip), %rsi      # 0x7b50
callq 0x21d0
movq %rax, %rdi
callq 0x20c0
leaq 0x30f4(%rip), %rdx      # 0x7b72
pushq $0x3
jmp 0x4a12
movb $0x1, 0x264(%rbx)
cmpb $0x0, 0xbc(%rsp)
je 0x4af8
movb $0x1, 0x5c(%rbx)
leaq 0x5e(%rbx), %rdi
movl $0x102, %edx            # imm = 0x102
movq %rbp, %rsi
callq 0x2170
movq 0x8(%rsp), %rcx
movq 0x578(%rsp), %r13
jmp 0x46a8
leaq 0x321d(%rip), %rdi      # 0x7cde
leaq 0x2c85(%rip), %rsi      # 0x774d
leaq 0x30e1(%rip), %rcx      # 0x7bb0
movl $0x4ad, %edx            # imm = 0x4AD
callq 0x2120
leaq 0x321e(%rip), %rdi      # 0x7cfe
leaq 0x2c66(%rip), %rsi      # 0x774d
leaq 0x30c2(%rip), %rcx      # 0x7bb0
movl $0x4ae, %edx            # imm = 0x4AE
callq 0x2120
leaq 0x30a1(%rip), %rdi      # 0x7ba0
leaq 0x2c47(%rip), %rsi      # 0x774d
leaq 0x30a3(%rip), %rcx      # 0x7bb0
movl $0x45f, %edx            # imm = 0x45F
callq 0x2120