// File: /workspace/github_cpp_makefile_star2_O1/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
movl $0x0, 0x14(%rsp)
movl $0xfffffff7, %ebp       # imm = 0xFFFFFFF7
cmpl $-0x1, 0x8(%rdi)
jne 0x3dd1
movq %rdi, %rbx
cmpl $-0x1, 0xc(%rdi)
jne 0x3dd1
xorl %ebp, %ebp
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x30b0
movl %eax, 0x8(%rbx)
cmpl $-0x1, %eax
je 0x3cb1
xorl %ebp, %ebp
movl %eax, %edi
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3150
movl %eax, 0x14(%rsp)
cmpl $-0x1, %eax
je 0x3ced
movl 0x8(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x3150
cmpl $-0x1, %eax
je 0x3d22
movq $0x2, 0x10(%rbx)
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0x8(%rbx), %edi
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x3420
testl %eax, %eax
je 0x3d59
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x4414(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x440f(%rip), %rdi      # 0x80aa
leaq 0x43f5(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x5c, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x43e5(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x438e(%rip), %rdi      # 0x8058
leaq 0x43c6(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x4c, %r8d
xorl %eax, %eax
callq 0x3050
jmp 0x3dd1
callq 0x3040
movl (%rax), %ecx
leaq 0x43a9(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4352(%rip), %rdi      # 0x8058
leaq 0x438a(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x50, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x4374(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x431d(%rip), %rdi      # 0x8058
leaq 0x4355(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x52, %r8d
jmp 0x3dac
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0x8(%rbx), %edi
movl $0x1, %esi
movl $0xf, %edx
movl $0x4, %r8d
callq 0x3420
testl %eax, %eax
je 0x3ddc
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x4314(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x430f(%rip), %rdi      # 0x80aa
leaq 0x42f5(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x5f, %r8d
xorl %eax, %eax
callq 0x3050
movl 0x8(%rbx), %edi
callq 0x3450
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
movl %r14d, 0x8(%rbx)
movl 0xc(%rbx), %edi
callq 0x3450
movl %r14d, 0xc(%rbx)
movl %ebp, %eax
addq $0x50, %rsp
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x14(%rsp), %rcx
movl $0x0, (%rcx)
movl 0x8(%rbx), %edi
xorl %esi, %esi
movl $0x22, %edx
movl $0x4, %r8d
callq 0x3420
cmpl $-0x1, %eax
je 0x3f00
movzwl 0x1f8(%rbx), %eax
leaq 0x14(%rsp), %rcx
movl %eax, (%rcx)
movl 0x8(%rbx), %edi
xorl %esi, %esi
movl $0x21, %edx
movl $0x4, %r8d
callq 0x3420
cmpl $-0x1, %eax
je 0x3f3a
leaq 0x14(%rsp), %rcx
movl $0x1388, (%rcx)         # imm = 0x1388
movl 0x8(%rbx), %edi
movl $0x1, %esi
movl $0x7, %edx
movl $0x4, %r8d
callq 0x3420
cmpl $-0x1, %eax
je 0x3f74
leaq 0x4281(%rip), %rdi      # 0x80e5
callq 0x3270
leaq 0x40(%rbx), %rcx
movl %eax, 0x40(%rbx)
movl $0x0, 0x44(%rbx)
movl 0x8(%rbx), %edi
xorl %esi, %esi
movl $0x23, %edx
movl $0x8, %r8d
callq 0x3420
cmpl $-0x1, %eax
je 0x3fae
leaq 0x10(%rbx), %rsi
movl 0x8(%rbx), %edi
movl $0x10, %edx
callq 0x3080
movl %eax, %ebp
testl %eax, %eax
jns 0x3ec9
callq 0x3040
movl (%rax), %eax
cmpl $0x62, %eax
je 0x3ebd
cmpl $0xd, %eax
jne 0x3ec9
leaq 0x44e2(%rip), %rdi      # 0x83a6
callq 0x3380
testl %ebp, %ebp
je 0x3fe8
callq 0x3040
movl (%rax), %ecx
leaq 0x41c5(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x41c0(%rip), %rdi      # 0x80aa
leaq 0x41a6(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x82, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x4196(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x413f(%rip), %rdi      # 0x8058
leaq 0x4177(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x6b, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x415c(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4105(%rip), %rdi      # 0x8058
leaq 0x413d(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x70, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x4122(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x40cb(%rip), %rdi      # 0x8058
leaq 0x4103(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x75, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x40e8(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4091(%rip), %rdi      # 0x8058
leaq 0x40c9(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x7b, %r8d
jmp 0x3dac
movw $0x2, 0x20(%rbx)
leaq 0x40f0(%rip), %rdi      # 0x80e5
callq 0x3270
movl %eax, 0x24(%rbx)
movw $0x6c07, 0x22(%rbx)     # imm = 0x6C07
xorl %ebp, %ebp
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x30b0
movl %eax, 0xc(%rbx)
cmpl $-0x1, %eax
je 0x40c4
xorl %ebp, %ebp
movl %eax, %edi
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3150
movl %eax, 0x14(%rsp)
cmpl $-0x1, %eax
je 0x40f9
movl 0xc(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x3150
cmpl $-0x1, %eax
je 0x412e
movq $0x6c070002, 0x30(%rbx) # imm = 0x6C070002
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0xc(%rbx), %edi
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x3420
testl %eax, %eax
je 0x4168
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x4001(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3ffc(%rip), %rdi      # 0x80aa
leaq 0x3fe2(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x9f, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x3fd2(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f7b(%rip), %rdi      # 0x8058
leaq 0x3fb3(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x8f, %r8d
jmp 0x3ce1
callq 0x3040
movl (%rax), %ecx
leaq 0x3f9d(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f46(%rip), %rdi      # 0x8058
leaq 0x3f7e(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x93, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x3f68(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f11(%rip), %rdi      # 0x8058
leaq 0x3f49(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x95, %r8d
jmp 0x3dac
leaq 0x14(%rsp), %rcx
movl $0x1, (%rcx)
movl 0xc(%rbx), %edi
movl $0x1, %esi
movl $0xf, %edx
movl $0x4, %r8d
callq 0x3420
testl %eax, %eax
je 0x41c0
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x3f05(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f00(%rip), %rdi      # 0x80aa
leaq 0x3ee6(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xa2, %r8d
jmp 0x3dac
leaq 0x3f1e(%rip), %rdi      # 0x80e5
callq 0x3270
leaq 0x48(%rbx), %rcx
movl %eax, 0x48(%rbx)
movl $0x0, 0x4c(%rbx)
movl 0xc(%rbx), %edi
xorl %esi, %esi
movl $0x23, %edx
movl $0x8, %r8d
callq 0x3420
cmpl $-0x1, %eax
je 0x425b
leaq 0x30(%rbx), %rsi
movl 0xc(%rbx), %edi
movl $0x10, %edx
callq 0x3080
movl %eax, %ebp
testl %eax, %eax
jns 0x4228
callq 0x3040
movl (%rax), %eax
cmpl $0x62, %eax
je 0x421c
cmpl $0xd, %eax
jne 0x4228
leaq 0x4183(%rip), %rdi      # 0x83a6
callq 0x3380
testl %ebp, %ebp
je 0x4295
callq 0x3040
movl (%rax), %ecx
leaq 0x3e6a(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3e65(%rip), %rdi      # 0x80aa
leaq 0x3e4b(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xb0, %r8d
jmp 0x3dac
callq 0x3040
movl (%rax), %ecx
leaq 0x3e3b(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3de4(%rip), %rdi      # 0x8058
leaq 0x3e1c(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xa8, %r8d
jmp 0x3dac
leaq 0x18(%rsp), %rdi
callq 0x32f0
movl %eax, %ebp
testl %eax, %eax
jne 0x3db3
leaq 0x18(%rsp), %rdi
movl $0x1, %esi
callq 0x3300
testl %eax, %eax
je 0x42cd
movl %eax, %ebp
leaq 0x18(%rsp), %rdi
callq 0x33d0
jmp 0x3db3
leaq 0x70(%rbx), %rdi
leaq 0x20(%rip), %rdx        # 0x42f8
leaq 0x18(%rsp), %r14
movq %r14, %rsi
movq %rbx, %rcx
callq 0x3440
movl %eax, %ebp
movq %r14, %rdi
callq 0x33d0
jmp 0x3dd1
nop