// File: /workspace/github_cpp_makefile_star2_O2/brunokeymolen[P]ssdp/src/ssdp.cpp
// Function: SSDP::Start()
int SSDP::Start(){
    int ret = 0;
    u32 optval = 0;

    if(mMulticastSocket != INVALID_SOCKET || mUnicastSocket != INVALID_SOCKET){
        ret = -9;
        goto EXIT;
    }

    //
    //Setup the Multicast Socket
    //
    mMulticastSocket = socket(PF_INET, SOCK_DGRAM, 0);
    STATNVAL(mMulticastSocket, INVALID_SOCKET, EXIT);

    //Set nonblocking
    optval = fcntl( mMulticastSocket, F_GETFL, 0 );
    STATNVAL(optval, -1,  CLEAN_AND_EXIT);
    ret = fcntl(mMulticastSocket, F_SETFL, optval | O_NONBLOCK);
    STATNVAL(ret, -1,  CLEAN_AND_EXIT);

    //Source address
    mSrcaddr.sin_family = PF_INET;
    mSrcaddr.sin_port = 0;//Let the IP stack decide
    mSrcaddr.sin_addr.s_addr = INADDR_ANY;//Default multicast nic

    //Reuse port
    optval = 1;
    ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
    STATVAL(ret, 0, CLEAN_AND_EXIT);
    optval = 1;
    ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
    STATVAL(ret, 0, CLEAN_AND_EXIT);

    #ifdef SO_NOSIGPIPE
    //Never generate SIGPIPE on broken write
    optval = 1;
    ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&optval, sizeof(int));
    STATVAL(ret, 0, CLEAN_AND_EXIT);
    #endif

    //Disable loopback
    optval = 0;
    ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&optval, sizeof(int));
    STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);

    //TTL
    optval = mTTL;
    ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&optval, sizeof(int));
    STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);

    //buffer size
    optval = 5000;
    ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, sizeof(int));
    STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);

    //Add membership
    mMreq.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
    mMreq.imr_interface.s_addr = INADDR_ANY;
    ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreq, sizeof(struct ip_mreq));
    STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);


    //Bind to all interface(s)
    ret = ::bind(mMulticastSocket, (struct sockaddr*)&mSrcaddr, sizeof(struct sockaddr));
    if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
        printf("address in use\n");
    STATVAL(ret, 0, CLEAN_AND_EXIT);


    //Destination address
    mDstaddr.sin_family = PF_INET;
    mDstaddr.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
    mDstaddr.sin_port = htons(SSDP_MCAST_PORT);


    //
    // Setup the Unicast Socket (We listen for Advertisements)
    //
    mUnicastSocket = socket(PF_INET, SOCK_DGRAM, 0);
    STATNVAL(mUnicastSocket, INVALID_SOCKET, EXIT);

    //Set nonblocking
    optval = fcntl( mUnicastSocket, F_GETFL, 0 );
    STATNVAL(optval, -1,  CLEAN_AND_EXIT);
    ret = fcntl(mUnicastSocket, F_SETFL, optval | O_NONBLOCK);
    STATNVAL(ret, -1,  CLEAN_AND_EXIT);

    //Source address
    mUnicastSrcaddr.sin_family = PF_INET;
    mUnicastSrcaddr.sin_port = htons(SSDP_MCAST_PORT);
    mUnicastSrcaddr.sin_addr.s_addr = INADDR_ANY;//Default nic 

    //Reuse port
    optval = 1;
    ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
    STATVAL(ret, 0, CLEAN_AND_EXIT);
    optval = 1;
    ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
    STATVAL(ret, 0, CLEAN_AND_EXIT);

    //Join Multicast group
    mMreqU.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
    mMreqU.imr_interface.s_addr = INADDR_ANY;
    ret = setsockopt(mUnicastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreqU, sizeof(struct ip_mreq));
    STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);



    //Bind to all interface(s)
    ret = ::bind(mUnicastSocket, (struct sockaddr*)&mUnicastSrcaddr, sizeof(struct sockaddr));
    if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
        printf("address in use\n");
    STATVAL(ret, 0, CLEAN_AND_EXIT);



    //Start the read thread
    pthread_attr_t  attr;
    ret = pthread_attr_init(&attr);
    if(ret != 0){
        goto CLEAN_AND_EXIT;
    }
    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if(ret != 0){
        pthread_attr_destroy(&attr);
        goto CLEAN_AND_EXIT;
    }

    ret = pthread_create(&mReadThread, &attr, SSDP::sReadLoop, (void*)this);

    pthread_attr_destroy(&attr);


    goto EXIT;


CLEAN_AND_EXIT:
    close(mMulticastSocket);
    mMulticastSocket = INVALID_SOCKET;
    close(mUnicastSocket);
    mUnicastSocket = INVALID_SOCKET;

EXIT:
    return ret;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x50, %rsp
andl $0x0, 0x14(%rsp)
pushq $-0x9
popq %rbp
cmpl $-0x1, 0x8(%rdi)
jne 0x3bf6
movq %rdi, %rbx
cmpl $-0x1, 0xc(%rdi)
jne 0x3bf6
pushq $0x2
popq %rdi
xorl %ebp, %ebp
movl %edi, %esi
xorl %edx, %edx
callq 0x30a0
movl %eax, 0x8(%rbx)
cmpl $-0x1, %eax
je 0x3aff
xorl %ebp, %ebp
pushq $0x3
popq %rsi
movl %eax, %edi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3140
movl %eax, 0x14(%rsp)
cmpl $-0x1, %eax
je 0x3b34
movl 0x8(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
pushq $0x4
popq %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x3140
cmpl $-0x1, %eax
je 0x3b5f
movq $0x2, 0x10(%rbx)
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0x8(%rbx), %edi
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
pushq $0x4
popq %r8
callq 0x33e0
testl %eax, %eax
je 0x3b8c
movl %eax, %ebp
callq 0x3030
movl (%rax), %ecx
leaq 0x45be(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x45b9(%rip), %rdi      # 0x80aa
leaq 0x459f(%rip), %r9       # 0x8097
pushq $0x5c
jmp 0x3bd1
callq 0x3030
movl (%rax), %ecx
leaq 0x4597(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4540(%rip), %rdi      # 0x8058
leaq 0x4578(%rip), %r9       # 0x8097
pushq $-0x1
popq %rdx
pushq $0x4c
popq %r8
movl %edx, %esi
xorl %eax, %eax
callq 0x3040
jmp 0x3bf6
callq 0x3030
movl (%rax), %ecx
leaq 0x4562(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x450b(%rip), %rdi      # 0x8058
leaq 0x4543(%rip), %r9       # 0x8097
pushq $-0x1
popq %rdx
pushq $0x50
popq %r8
movl %edx, %esi
jmp 0x3bd7
callq 0x3030
movl (%rax), %ecx
leaq 0x4537(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x44e0(%rip), %rdi      # 0x8058
leaq 0x4518(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
pushq $0x52
popq %r8
movl %ebp, %esi
movl %ebp, %edx
jmp 0x3bd7
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0x8(%rbx), %edi
pushq $0x1
popq %rsi
pushq $0xf
popq %rdx
pushq $0x4
popq %r8
callq 0x33e0
testl %eax, %eax
je 0x3c01
movl %eax, %ebp
callq 0x3030
movl (%rax), %ecx
leaq 0x44e7(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x44e2(%rip), %rdi      # 0x80aa
leaq 0x44c8(%rip), %r9       # 0x8097
pushq $0x5f
popq %r8
movl %ebp, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3040
movl 0x8(%rbx), %edi
callq 0x3420
orl $-0x1, 0x8(%rbx)
movl 0xc(%rbx), %edi
callq 0x3420
orl $-0x1, 0xc(%rbx)
movl %ebp, %eax
addq $0x50, %rsp
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x14(%rsp), %rcx
andl $0x0, (%rcx)
movl 0x8(%rbx), %edi
pushq $0x22
popq %rdx
pushq $0x4
popq %r8
xorl %esi, %esi
callq 0x33e0
cmpl $-0x1, %eax
je 0x3cce
movzwl 0x1f8(%rbx), %eax
leaq 0x14(%rsp), %rcx
movl %eax, (%rcx)
movl 0x8(%rbx), %edi
pushq $0x21
popq %rdx
pushq $0x4
popq %r8
xorl %esi, %esi
callq 0x33e0
cmpl $-0x1, %eax
je 0x3cf8
leaq 0x14(%rsp), %rcx
movl $0x1388, (%rcx)         # imm = 0x1388
movl 0x8(%rbx), %edi
pushq $0x1
popq %rsi
pushq $0x7
popq %rdx
pushq $0x4
popq %r8
callq 0x33e0
cmpl $-0x1, %eax
je 0x3d22
leaq 0x446d(%rip), %rdi      # 0x80e5
callq 0x3270
leaq 0x40(%rbx), %rcx
movl %eax, 0x40(%rbx)
andl $0x0, 0x44(%rbx)
movl 0x8(%rbx), %edi
pushq $0x23
popq %rdx
pushq $0x8
popq %r8
xorl %esi, %esi
callq 0x33e0
cmpl $-0x1, %eax
je 0x3d4c
leaq 0x10(%rbx), %rsi
movl 0x8(%rbx), %edi
pushq $0x10
popq %rdx
callq 0x3070
movl %eax, %ebp
testl %eax, %eax
js 0x3d76
je 0x3dc1
callq 0x3030
movq %rax, %r14
jmp 0x3d96
callq 0x3030
movl (%rax), %ecx
leaq 0x43c8(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4371(%rip), %rdi      # 0x8058
leaq 0x43a9(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
pushq $0x6b
jmp 0x3b84
callq 0x3030
movl (%rax), %ecx
leaq 0x439e(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4347(%rip), %rdi      # 0x8058
leaq 0x437f(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
pushq $0x70
jmp 0x3b84
callq 0x3030
movl (%rax), %ecx
leaq 0x4374(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x431d(%rip), %rdi      # 0x8058
leaq 0x4355(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
pushq $0x75
jmp 0x3b84
callq 0x3030
movl (%rax), %ecx
leaq 0x434a(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x42f3(%rip), %rdi      # 0x8058
leaq 0x432b(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
pushq $0x7b
jmp 0x3b84
callq 0x3030
movq %rax, %r14
movl (%rax), %eax
cmpl $0x62, %eax
je 0x3d8a
cmpl $0xd, %eax
jne 0x3d96
leaq 0x4615(%rip), %rdi      # 0x83a6
callq 0x3370
movl (%r14), %ecx
leaq 0x4304(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x42ff(%rip), %rdi      # 0x80aa
leaq 0x42e5(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x82, %r8d
jmp 0x3bd7
movw $0x2, 0x20(%rbx)
leaq 0x4317(%rip), %rdi      # 0x80e5
callq 0x3270
movl %eax, 0x24(%rbx)
movw $0x6c07, 0x22(%rbx)     # imm = 0x6C07
pushq $0x2
popq %rdi
xorl %ebp, %ebp
movl %edi, %esi
xorl %edx, %edx
callq 0x30a0
movl %eax, 0xc(%rbx)
cmpl $-0x1, %eax
je 0x3e8e
xorl %ebp, %ebp
pushq $0x3
popq %rsi
movl %eax, %edi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3140
movl %eax, 0x14(%rsp)
cmpl $-0x1, %eax
je 0x3ebe
movl 0xc(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
pushq $0x4
popq %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x3140
cmpl $-0x1, %eax
je 0x3eee
movq $0x6c070002, 0x30(%rbx) # imm = 0x6C070002
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0xc(%rbx), %edi
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
pushq $0x4
popq %r8
callq 0x33e0
testl %eax, %eax
je 0x3f20
movl %eax, %ebp
callq 0x3030
movl (%rax), %ecx
leaq 0x4237(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4232(%rip), %rdi      # 0x80aa
leaq 0x4218(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x9f, %r8d
jmp 0x3bd7
callq 0x3030
movl (%rax), %ecx
leaq 0x4208(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x41b1(%rip), %rdi      # 0x8058
leaq 0x41e9(%rip), %r9       # 0x8097
pushq $-0x1
popq %rdx
movl %edx, %esi
movl $0x8f, %r8d
jmp 0x3b28
callq 0x3030
movl (%rax), %ecx
leaq 0x41d8(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4181(%rip), %rdi      # 0x8058
leaq 0x41b9(%rip), %r9       # 0x8097
pushq $-0x1
popq %rdx
movl %edx, %esi
movl $0x93, %r8d
jmp 0x3bd7
callq 0x3030
movl (%rax), %ecx
leaq 0x41a8(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4151(%rip), %rdi      # 0x8058
leaq 0x4189(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
movl %ebp, %esi
movl %ebp, %edx
movl $0x95, %r8d
jmp 0x3bd7
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0xc(%rbx), %edi
pushq $0x1
popq %rsi
pushq $0xf
popq %rdx
pushq $0x4
popq %r8
callq 0x33e0
testl %eax, %eax
je 0x3f72
movl %eax, %ebp
callq 0x3030
movl (%rax), %ecx
leaq 0x4153(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x414e(%rip), %rdi      # 0x80aa
leaq 0x4134(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xa2, %r8d
jmp 0x3bd7
leaq 0x416c(%rip), %rdi      # 0x80e5
callq 0x3270
leaq 0x48(%rbx), %rcx
movl %eax, 0x48(%rbx)
andl $0x0, 0x4c(%rbx)
movl 0xc(%rbx), %edi
pushq $0x23
popq %rdx
pushq $0x8
popq %r8
xorl %esi, %esi
callq 0x33e0
cmpl $-0x1, %eax
je 0x3fc4
leaq 0x30(%rbx), %rsi
movl 0xc(%rbx), %edi
pushq $0x10
popq %rdx
callq 0x3070
movl %eax, %ebp
testl %eax, %eax
js 0x3ff6
je 0x4041
callq 0x3030
movq %rax, %r14
jmp 0x4016
callq 0x3030
movl (%rax), %ecx
leaq 0x40d2(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x407b(%rip), %rdi      # 0x8058
leaq 0x40b3(%rip), %r9       # 0x8097
pushq $-0x1
popq %rbp
movl %ebp, %esi
movl %ebp, %edx
movl $0xa8, %r8d
jmp 0x3bd7
callq 0x3030
movq %rax, %r14
movl (%rax), %eax
cmpl $0x62, %eax
je 0x400a
cmpl $0xd, %eax
jne 0x4016
leaq 0x4395(%rip), %rdi      # 0x83a6
callq 0x3370
movl (%r14), %ecx
leaq 0x4084(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x407f(%rip), %rdi      # 0x80aa
leaq 0x4065(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xb0, %r8d
jmp 0x3bd7
leaq 0x18(%rsp), %rdi
callq 0x32d0
movl %eax, %ebp
testl %eax, %eax
jne 0x3bde
leaq 0x18(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x32e0
testl %eax, %eax
je 0x4077
movl %eax, %ebp
leaq 0x18(%rsp), %rdi
callq 0x33b0
jmp 0x3bde
leaq 0x70(%rbx), %rdi
leaq 0x20(%rip), %rdx        # 0x40a2
leaq 0x18(%rsp), %r14
movq %r14, %rsi
movq %rbx, %rcx
callq 0x3400
movl %eax, %ebp
movq %r14, %rdi
callq 0x33b0
jmp 0x3bf6
nop