// File: /workspace/github_cpp_makefile_star2_O3/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 0x3da9
movq %rdi, %rbx
cmpl $-0x1, 0xc(%rdi)
jne 0x3da9
xorl %ebp, %ebp
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x30b0
movl %eax, 0x8(%rbx)
cmpl $-0x1, %eax
je 0x3c89
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 0x3cc5
movl 0x8(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x3150
cmpl $-0x1, %eax
je 0x3cfa
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 0x3d31
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x443c(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4437(%rip), %rdi      # 0x80aa
leaq 0x441d(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x5c, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x440d(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x43b6(%rip), %rdi      # 0x8058
leaq 0x43ee(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x4c, %r8d
xorl %eax, %eax
callq 0x3050
jmp 0x3da9
callq 0x3040
movl (%rax), %ecx
leaq 0x43d1(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x437a(%rip), %rdi      # 0x8058
leaq 0x43b2(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x50, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x439c(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4345(%rip), %rdi      # 0x8058
leaq 0x437d(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x52, %r8d
jmp 0x3d84
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 0x3db4
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x433c(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4337(%rip), %rdi      # 0x80aa
leaq 0x431d(%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 0x3e9b
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 0x3ed5
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 0x3f0f
leaq 0x42a9(%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 0x3f49
leaq 0x10(%rbx), %rsi
movl 0x8(%rbx), %edi
movl $0x10, %edx
callq 0x3080
movl %eax, %ebp
testl %eax, %eax
js 0x3f83
je 0x3fce
callq 0x3040
movq %rax, %r14
jmp 0x3fa3
callq 0x3040
movl (%rax), %ecx
leaq 0x41fb(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x41a4(%rip), %rdi      # 0x8058
leaq 0x41dc(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x6b, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x41c1(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x416a(%rip), %rdi      # 0x8058
leaq 0x41a2(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x70, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x4187(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4130(%rip), %rdi      # 0x8058
leaq 0x4168(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x75, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x414d(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x40f6(%rip), %rdi      # 0x8058
leaq 0x412e(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x7b, %r8d
jmp 0x3d84
callq 0x3040
movq %rax, %r14
movl (%rax), %eax
cmpl $0x62, %eax
je 0x3f97
cmpl $0xd, %eax
jne 0x3fa3
leaq 0x4408(%rip), %rdi      # 0x83a6
callq 0x3380
movl (%r14), %ecx
leaq 0x40f7(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x40f2(%rip), %rdi      # 0x80aa
leaq 0x40d8(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x82, %r8d
jmp 0x3d84
movw $0x2, 0x20(%rbx)
leaq 0x410a(%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 0x40aa
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 0x40df
movl 0xc(%rbx), %edi
orl $0x800, %eax            # imm = 0x800
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x3150
cmpl $-0x1, %eax
je 0x4114
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 0x414e
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x401b(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x4016(%rip), %rdi      # 0x80aa
leaq 0x3ffc(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0x9f, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x3fec(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f95(%rip), %rdi      # 0x8058
leaq 0x3fcd(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x8f, %r8d
jmp 0x3cb9
callq 0x3040
movl (%rax), %ecx
leaq 0x3fb7(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f60(%rip), %rdi      # 0x8058
leaq 0x3f98(%rip), %r9       # 0x8097
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x93, %r8d
jmp 0x3d84
callq 0x3040
movl (%rax), %ecx
leaq 0x3f82(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f2b(%rip), %rdi      # 0x8058
leaq 0x3f63(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x95, %r8d
jmp 0x3d84
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 0x41a6
movl %eax, %ebp
callq 0x3040
movl (%rax), %ecx
leaq 0x3f1f(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3f1a(%rip), %rdi      # 0x80aa
leaq 0x3f00(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xa2, %r8d
jmp 0x3d84
leaq 0x3f38(%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 0x4201
leaq 0x30(%rbx), %rsi
movl 0xc(%rbx), %edi
movl $0x10, %edx
callq 0x3080
movl %eax, %ebp
testl %eax, %eax
js 0x423b
je 0x4286
callq 0x3040
movq %rax, %r14
jmp 0x425b
callq 0x3040
movl (%rax), %ecx
leaq 0x3e95(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3e3e(%rip), %rdi      # 0x8058
leaq 0x3e76(%rip), %r9       # 0x8097
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xa8, %r8d
jmp 0x3d84
callq 0x3040
movq %rax, %r14
movl (%rax), %eax
cmpl $0x62, %eax
je 0x424f
cmpl $0xd, %eax
jne 0x425b
leaq 0x4150(%rip), %rdi      # 0x83a6
callq 0x3380
movl (%r14), %ecx
leaq 0x3e3f(%rip), %rax      # 0x80a4
movq %rax, (%rsp)
leaq 0x3e3a(%rip), %rdi      # 0x80aa
leaq 0x3e20(%rip), %r9       # 0x8097
movl %ebp, %esi
xorl %edx, %edx
movl $0xb0, %r8d
jmp 0x3d84
leaq 0x18(%rsp), %rdi
callq 0x32f0
movl %eax, %ebp
testl %eax, %eax
jne 0x3d8b
leaq 0x18(%rsp), %rdi
movl $0x1, %esi
callq 0x3300
testl %eax, %eax
je 0x42be
movl %eax, %ebp
leaq 0x18(%rsp), %rdi
callq 0x33d0
jmp 0x3d8b
leaq 0x70(%rbx), %rdi
leaq 0x1f(%rip), %rdx        # 0x42e8
leaq 0x18(%rsp), %r14
movq %r14, %rsi
movq %rbx, %rcx
callq 0x3440
movl %eax, %ebp
movq %r14, %rdi
callq 0x33d0
jmp 0x3da9