// File: Distrotech[P]stund/server.cxx
// Function: main
int
main(int argc, char* argv[])
{
   assert( sizeof(UInt8 ) == 1 );
   assert( sizeof(UInt16) == 2 );
   assert( sizeof(UInt32) == 4 );

   initNetwork();

   clog << "STUN server version "  <<  STUN_VERSION << endl;
      
   StunAddress4 myAddr;
   StunAddress4 altAddr;
   bool verbose=false;
   bool background=false;
   
   myAddr.addr = 0;
   altAddr.addr = 0;
   myAddr.port = STUN_PORT;
   altAddr.port = STUN_PORT+1;
   int myPort = 0;
   int altPort = 0;
   int myMediaPort = 0;
   
   UInt32 interfaces[10];
   int numInterfaces = stunFindLocalInterfaces(interfaces,10);

   if (numInterfaces == 2)
   {
      myAddr.addr = interfaces[0];
      myAddr.port = STUN_PORT;
      altAddr.addr = interfaces[1];
      altAddr.port = STUN_PORT+1;
   }

   for ( int arg = 1; arg<argc; arg++ )
   {
      if ( !strcmp( argv[arg] , "-v" ) )
      {
         verbose = true;
      }
      else if ( !strcmp( argv[arg] , "-b" ) )
      {
         background = true;
      }
      else if ( !strcmp( argv[arg] , "-h" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         stunParseServerName(argv[arg], myAddr);
      }
      else if ( !strcmp( argv[arg] , "-a" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         stunParseServerName(argv[arg], altAddr);
      }
      else if ( !strcmp( argv[arg] , "-p" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         myPort = UInt16(strtol( argv[arg], NULL, 10));
      }
      else if ( !strcmp( argv[arg] , "-o" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         altPort = UInt16(strtol( argv[arg], NULL, 10));
      }
      else if ( !strcmp( argv[arg] , "-m" ) )
      {
         arg++;
         if ( argc <= arg ) 
         {
            usage();
            exit(-1);
         }
         myMediaPort = UInt16(strtol( argv[arg], NULL, 10));
      }
      else
      {
         usage();
         exit(-1);
      }
   }

   if ( myPort != 0 )
   {
      myAddr.port = myPort;
   }
   if ( altPort != 0 )
   {
      altAddr.port = altPort;
   }
   
   if (  (myAddr.addr == 0) || (altAddr.addr == 0) )
   {
      clog << "If your machine does not have exactly two ethernet interfaces, "
           << "you must specify the server and alt server" << endl;
      //usage();
      //exit(-1);
   }

   if ( myAddr.port == altAddr.port )
   {
      altAddr.port = myAddr.port+1;
   }

   if ( verbose )
   {
      clog << "Running with on interface "
           << myAddr << " with alternate " 
           << altAddr << endl;
   }
    
   if (
      ( myAddr.addr  == 0 ) ||
      ( myAddr.port  == 0 ) ||
      //( altAddr.addr == 0 ) ||
      ( altAddr.port == 0 ) 
      )
   {
      cerr << "Bad command line" << endl;
      exit(1);
   }
   
   if ( altAddr.addr == 0 )
   {
      cerr << "Warning - no alternate ip address STUN will not work" << endl;
      //exit(1);
   }
   
#if defined(WIN32)
   int pid=0;

   if ( background )
   {
      cerr << "The -b background option does not work in windows" << endl;
      exit(-1);
   }
#else
   pid_t pid=0;

   if ( background )
   {
      pid = fork();

      if (pid < 0)
      {
         cerr << "fork: unable to fork" << endl;
         exit(-1);
      }
   }
#endif

   if (pid == 0) //child or not using background
   {
      StunServerInfo info;
      bool ok = stunInitServer(info, myAddr, altAddr, myMediaPort, verbose);
      
      int c=0;
      while (ok)
      {
         ok = stunServerProcess(info, verbose);
         c++;
         if ( verbose && (c%1000 == 0) ) 
         {
            clog << "*";
         }
      }
      // Notreached
   }
   
   return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2f80, %rsp           # imm = 0x2F80
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
callq 0x8f10
movq 0xb8f3(%rip), %rdi      # 0xdfb8
leaq 0x7b75(%rip), %rsi      # 0xa241
callq 0x21f0
movq %rax, %rdi
leaq 0x7b7b(%rip), %rsi      # 0xa256
callq 0x21f0
movq %rax, %rdi
movq 0xb8de(%rip), %rsi      # 0xdfc8
callq 0x2200
movb $0x0, -0x21(%rbp)
movb $0x0, -0x22(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x1c(%rbp)
movw $0xd96, -0x18(%rbp)     # imm = 0xD96
movw $0xd97, -0x20(%rbp)     # imm = 0xD97
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
leaq -0x60(%rbp), %rdi
movl $0xa, %esi
callq 0x6d70
movl %eax, -0x64(%rbp)
cmpl $0x2, -0x64(%rbp)
jne 0x2755
movl -0x60(%rbp), %eax
movl %eax, -0x14(%rbp)
movw $0xd96, -0x18(%rbp)     # imm = 0xD96
movl -0x5c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movw $0xd97, -0x20(%rbp)     # imm = 0xD97
movl $0x1, -0x68(%rbp)
movl -0x68(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x29ad
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7ae0(%rip), %rsi      # 0xa25b
callq 0x2260
cmpl $0x0, %eax
jne 0x278e
movb $0x1, -0x21(%rbp)
jmp 0x299d
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7abd(%rip), %rsi      # 0xa25e
callq 0x2260
cmpl $0x0, %eax
jne 0x27b4
movb $0x1, -0x22(%rbp)
jmp 0x299b
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7a9a(%rip), %rsi      # 0xa261
callq 0x2260
cmpl $0x0, %eax
jne 0x280b
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x68(%rbp), %eax
jg 0x27f1
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq -0x18(%rbp), %rsi
callq 0x4f10
jmp 0x2999
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7a46(%rip), %rsi      # 0xa264
callq 0x2260
cmpl $0x0, %eax
jne 0x2862
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x68(%rbp), %eax
jg 0x2848
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq -0x20(%rbp), %rsi
callq 0x4f10
jmp 0x2997
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x79f2(%rip), %rsi      # 0xa267
callq 0x2260
cmpl $0x0, %eax
jne 0x28c4
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x68(%rbp), %eax
jg 0x289f
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x2270
movzwl %ax, %eax
movl %eax, -0x28(%rbp)
jmp 0x2995
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7993(%rip), %rsi      # 0xa26a
callq 0x2260
cmpl $0x0, %eax
jne 0x2923
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x68(%rbp), %eax
jg 0x2901
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x2270
movzwl %ax, %eax
movl %eax, -0x2c(%rbp)
jmp 0x2993
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x7937(%rip), %rsi      # 0xa26d
callq 0x2260
cmpl $0x0, %eax
jne 0x2982
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x8(%rbp), %eax
cmpl -0x68(%rbp), %eax
jg 0x2960
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
movq -0x10(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x2270
movzwl %ax, %eax
movl %eax, -0x30(%rbp)
jmp 0x2991
callq 0x2500
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
jmp 0x2993
jmp 0x2995
jmp 0x2997
jmp 0x2999
jmp 0x299b
jmp 0x299d
jmp 0x299f
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x275c
cmpl $0x0, -0x28(%rbp)
je 0x29ba
movl -0x28(%rbp), %eax
movw %ax, -0x18(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x29c7
movl -0x2c(%rbp), %eax
movw %ax, -0x20(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x29d3
cmpl $0x0, -0x1c(%rbp)
jne 0x2a04
movq 0xb5de(%rip), %rdi      # 0xdfb8
leaq 0x788f(%rip), %rsi      # 0xa270
callq 0x21f0
movq %rax, %rdi
leaq 0x78c0(%rip), %rsi      # 0xa2b0
callq 0x21f0
movq %rax, %rdi
movq 0xb5c9(%rip), %rsi      # 0xdfc8
callq 0x2200
movzwl -0x18(%rbp), %eax
movzwl -0x20(%rbp), %ecx
cmpl %ecx, %eax
jne 0x2a1b
movzwl -0x18(%rbp), %eax
addl $0x1, %eax
movw %ax, -0x20(%rbp)
testb $0x1, -0x21(%rbp)
je 0x2a6a
movq 0xb590(%rip), %rdi      # 0xdfb8
leaq 0x78ac(%rip), %rsi      # 0xa2db
callq 0x21f0
movq %rax, %rdi
leaq -0x18(%rbp), %rsi
callq 0x3890
movq %rax, %rdi
leaq 0x78ac(%rip), %rsi      # 0xa2f6
callq 0x21f0
movq %rax, %rdi
leaq -0x20(%rbp), %rsi
callq 0x3890
movq %rax, %rdi
movq 0xb563(%rip), %rsi      # 0xdfc8
callq 0x2200
cmpl $0x0, -0x14(%rbp)
je 0x2a82
movzwl -0x18(%rbp), %eax
cmpl $0x0, %eax
je 0x2a82
movzwl -0x20(%rbp), %eax
cmpl $0x0, %eax
jne 0x2aae
movq 0xb567(%rip), %rdi      # 0xdff0
leaq 0x7877(%rip), %rsi      # 0xa307
callq 0x21f0
movq %rax, %rdi
movq 0xb529(%rip), %rsi      # 0xdfc8
callq 0x2200
movl $0x1, %edi
callq 0x2230
cmpl $0x0, -0x1c(%rbp)
jne 0x2ad6
movq 0xb535(%rip), %rdi      # 0xdff0
leaq 0x7856(%rip), %rsi      # 0xa318
callq 0x21f0
movq %rax, %rdi
movq 0xb4f7(%rip), %rsi      # 0xdfc8
callq 0x2200
movl $0x0, -0x6c(%rbp)
testb $0x1, -0x22(%rbp)
je 0x2b1f
callq 0x20b0
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x6c(%rbp)
jge 0x2b1d
movq 0xb4f8(%rip), %rdi      # 0xdff0
leaq 0x784e(%rip), %rsi      # 0xa34d
callq 0x21f0
movq %rax, %rdi
movq 0xb4ba(%rip), %rsi      # 0xdfc8
callq 0x2200
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
jmp 0x2b1f
cmpl $0x0, -0x6c(%rbp)
jne 0x2bbf
movl -0x30(%rbp), %ecx
movb -0x21(%rbp), %al
leaq -0x2f78(%rbp), %rdi
leaq -0x18(%rbp), %rsi
leaq -0x20(%rbp), %rdx
andb $0x1, %al
movzbl %al, %r8d
callq 0x59a0
andb $0x1, %al
movb %al, -0x2f79(%rbp)
movl $0x0, -0x2f80(%rbp)
testb $0x1, -0x2f79(%rbp)
je 0x2bbd
movb -0x21(%rbp), %al
leaq -0x2f78(%rbp), %rdi
andb $0x1, %al
movzbl %al, %esi
callq 0x5dc0
andb $0x1, %al
movb %al, -0x2f79(%rbp)
movl -0x2f80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2f80(%rbp)
testb $0x1, -0x21(%rbp)
je 0x2bbb
movl -0x2f80(%rbp), %eax
movl $0x3e8, %ecx            # imm = 0x3E8
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x2bbb
movq 0xb409(%rip), %rdi      # 0xdfb8
leaq 0x77ac(%rip), %rsi      # 0xa362
callq 0x21f0
jmp 0x2b5b
jmp 0x2bbf
xorl %eax, %eax
addq $0x2f80, %rsp           # imm = 0x2F80
popq %rbp
retq
nopw (%rax,%rax)