// File: brunokeymolen[P]ssdp/src/ssdptools.cpp
// Function: ParseUSN(unsigned char*, unsigned int, ssdpuuid*)
int ParseUSN(u8* uuidraw, u32 len, ssdpuuid *uuid){
    int ret = 0;
    int colon1 = 0;
    int colon2 = 0;
    int tel;
    int skip=0;

//    int lenleft;

    //Sanity
    if(uuid == NULL || len == 0){
        return -1;
    }
    if(memcmp(uuidraw, "uuid", 4) != 0){
        return -2;
    }

    memset(uuid, 0, sizeof(ssdpuuid));

//    lenleft = len;

    //uuid
    colon1 = getchar(uuidraw, len, ':', 1);
    colon2 = getchar(uuidraw, len, ':', 2);
    if(colon1<0 || colon1+1>=(int)len){ ret = -1;goto EXIT;}
    if(colon2<0){
        uuid->uuid=uuidraw;//+colon1+1;
        uuid->uuidlen=len;//-colon1-1;
        //uuid->uuidlen=len-colon1-1;
        goto EXIT;
    }else{
        uuid->uuid=uuidraw;//+colon1+1;
        uuid->uuidlen=colon2;
//        uuid->uuidlen=colon2-colon1-1;
    }

    //Sanity, there must be a double colon
    //Find the first '::' sequence and compute the number of semicolons to it
    //store it in the skip variable, which is used for offsetting subsequent searches
    //this is needed for some devices that have a semicolon in the name
    colon1 = getchar(uuidraw, len, ':', 2);
    colon2 = -1;
    while (colon1 < (int)len && colon2 == -1) {
        colon2 = getchar(uuidraw, len, ':', 2+skip+1);
        if (colon2-colon1 == 1) {
            uuid->uuidlen=colon1;
            colon1 = colon2;
        } else {
            colon1 = colon2;
            colon2 = -1;
            skip++;
        }
    }
    if(colon2 == -1){
        ret = -2;
        goto EXIT;
    }


    //upnp, isroot 
    colon1 = getchar(uuidraw, len, ':', 3+skip);
    if((len-colon1)>=15 && memcmp(uuidraw+colon1+1, "upnp:rootdevice", 15)==0 ){
        uuid->isrootdevice = 1;
        uuid->isdevice = 1;
        uuid->type = uuidraw+colon1+1;
        uuid->typelen = 15;
        goto EXIT;
    }

    //Sanity, there must be 4 colons after
    for(tel=4+skip;tel<=7+skip;tel++){
        colon1 = getchar(uuidraw, len, ':', tel);
        if(colon1 < 0){
            ret = -3;
            goto EXIT;
        }
    }


    //urn
    colon1 = getchar(uuidraw, len, ':', 3+skip);
    colon2 = getchar(uuidraw, len, ':', 4+skip);
    if((colon2-colon1)>=3 && memcmp(uuidraw+colon1+1, "urn", 3)!=0 ){
        ret = -4;
        goto EXIT;
    }
    uuid->fullurn = uuidraw+colon1+1;
    uuid->fullurnlen = len-colon1-1;

    colon1 = getchar(uuidraw, len, ':', 4+skip);
    colon2 = getchar(uuidraw, len, ':', 5+skip);
    uuid->urn=uuidraw+colon1+1;
    uuid->urnlen=colon2-colon1-1;



    //Device or service
    colon1 = getchar(uuidraw, len, ':', 5+skip);
    colon2 = getchar(uuidraw, len, ':', 6+skip);
    if( (colon2-colon1)>=6 && memcmp(uuidraw+colon1+1, "device", 6)==0){
        //device
        uuid->isdevice = 1;
    }else if((colon2-colon1)>=7 && memcmp(uuidraw+colon1+1, "service", 7)==0){
        //service
        uuid->isservice = 1;
    }else{
        ret = -5;
        goto EXIT;
    }


    //servicetype / devicetype
    colon1 = getchar(uuidraw, len, ':', 6+skip);
    colon2 = getchar(uuidraw, len, ':', 7+skip);
    uuid->type = uuidraw+colon1+1;
    uuid->typelen=colon2-colon1-1;

    //Workaround for MusicPal bug
    if(uuid->typelen==16 && memcmp(uuid->type, "RenderingControl", 16) == 0){
        uuid->isdevice = 0;
        uuid->isrootdevice = 0;
        uuid->isservice = 1;
    }

    //version
    uuid->version = uuidraw+colon2+1;
    uuid->versionlen=len-colon2-1;

EXIT:

    return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x34(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0xe38c
cmpl $0x0, -0x14(%rbp)
jne 0xe398
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xe83b
movq -0x10(%rbp), %rax
movl (%rax), %eax
subl $0x64697575, %eax       # imm = 0x64697575
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0xe3ba
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0xe83b
movq -0x20(%rbp), %rdi
xorl %esi, %esi
movl $0x50, %edx
callq 0x3160
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl $0x3a, %edx
movl $0x1, %ecx
callq 0x3c30
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl $0x3a, %edx
movl $0x2, %ecx
callq 0x3c30
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x28(%rbp)
jl 0xe40d
movl -0x28(%rbp), %eax
addl $0x1, %eax
cmpl -0x14(%rbp), %eax
jl 0xe419
movl $0xffffffff, -0x24(%rbp) # imm = 0xFFFFFFFF
jmp 0xe835
cmpl $0x0, -0x2c(%rbp)
jge 0xe439
movq -0x10(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movl -0x14(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x8(%rax)
jmp 0xe835
movq -0x10(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movl -0x2c(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl $0x3a, %edx
movl $0x2, %ecx
callq 0x3c30
movl %eax, -0x28(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movl -0x28(%rbp), %ecx
xorl %eax, %eax
cmpl -0x14(%rbp), %ecx
movb %al, -0x35(%rbp)
jge 0xe485
cmpl $-0x1, -0x2c(%rbp)
sete %al
movb %al, -0x35(%rbp)
movb -0x35(%rbp), %al
testb $0x1, %al
jne 0xe48e
jmp 0xe4e0
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x2, %ecx
addl $0x1, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
subl -0x28(%rbp), %eax
cmpl $0x1, %eax
jne 0xe4c8
movl -0x28(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x8(%rax)
movl -0x2c(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0xe4de
movl -0x2c(%rbp), %eax
movl %eax, -0x28(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0xe46e
cmpl $-0x1, -0x2c(%rbp)
jne 0xe4f2
movl $0xfffffffe, -0x24(%rbp) # imm = 0xFFFFFFFE
jmp 0xe835
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x3, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
movl -0x14(%rbp), %eax
subl -0x28(%rbp), %eax
cmpl $0xf, %eax
jb 0xe573
movq -0x10(%rbp), %rdi
movslq -0x28(%rbp), %rax
addq %rax, %rdi
addq $0x1, %rdi
leaq 0x2118(%rip), %rsi      # 0x10645
movl $0xf, %edx
callq 0x3120
cmpl $0x0, %eax
jne 0xe573
movq -0x20(%rbp), %rax
movb $0x1, 0x2d(%rax)
movq -0x20(%rbp), %rax
movb $0x1, 0x2c(%rax)
movq -0x10(%rbp), %rcx
movslq -0x28(%rbp), %rax
addq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x20(%rbp), %rax
movl $0xf, 0x38(%rax)
jmp 0xe835
movl -0x34(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl -0x34(%rbp), %ecx
addl $0x7, %ecx
cmpl %ecx, %eax
jg 0xe5bf
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x30(%rbp), %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jge 0xe5b2
movl $0xfffffffd, -0x24(%rbp) # imm = 0xFFFFFFFD
jmp 0xe835
jmp 0xe5b4
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0xe57c
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x3, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x4, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
subl -0x28(%rbp), %eax
cmpl $0x3, %eax
jl 0xe62f
movq -0x10(%rbp), %rdi
movslq -0x28(%rbp), %rax
addq %rax, %rdi
addq $0x1, %rdi
leaq 0x2041(%rip), %rsi      # 0x10655
movl $0x3, %edx
callq 0x3120
cmpl $0x0, %eax
je 0xe62f
movl $0xfffffffc, -0x24(%rbp) # imm = 0xFFFFFFFC
jmp 0xe835
movq -0x10(%rbp), %rcx
movslq -0x28(%rbp), %rax
addq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movl -0x14(%rbp), %ecx
subl -0x28(%rbp), %ecx
subl $0x1, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x18(%rax)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x4, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x5, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rcx
movslq -0x28(%rbp), %rax
addq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x20(%rax)
movl -0x2c(%rbp), %ecx
subl -0x28(%rbp), %ecx
subl $0x1, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x28(%rax)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x5, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x6, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
subl -0x28(%rbp), %eax
cmpl $0x6, %eax
jl 0xe71f
movq -0x10(%rbp), %rdi
movslq -0x28(%rbp), %rax
addq %rax, %rdi
addq $0x1, %rdi
leaq 0x1f48(%rip), %rsi      # 0x1064e
movl $0x6, %edx
callq 0x3120
cmpl $0x0, %eax
jne 0xe71f
movq -0x20(%rbp), %rax
movb $0x1, 0x2c(%rax)
jmp 0xe767
movl -0x2c(%rbp), %eax
subl -0x28(%rbp), %eax
cmpl $0x7, %eax
jl 0xe759
movq -0x10(%rbp), %rdi
movslq -0x28(%rbp), %rax
addq %rax, %rdi
addq $0x1, %rdi
leaq 0x1f19(%rip), %rsi      # 0x10659
movl $0x7, %edx
callq 0x3120
cmpl $0x0, %eax
jne 0xe759
movq -0x20(%rbp), %rax
movb $0x1, 0x2e(%rax)
jmp 0xe765
movl $0xfffffffb, -0x24(%rbp) # imm = 0xFFFFFFFB
jmp 0xe835
jmp 0xe767
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x6, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
movl -0x34(%rbp), %ecx
addl $0x7, %ecx
movl $0x3a, %edx
callq 0x3c30
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rcx
movslq -0x28(%rbp), %rax
addq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x30(%rax)
movl -0x2c(%rbp), %ecx
subl -0x28(%rbp), %ecx
subl $0x1, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x38(%rax)
movq -0x20(%rbp), %rax
cmpl $0x10, 0x38(%rax)
jne 0xe80e
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movups (%rax), %xmm0
movaps 0x1e52(%rip), %xmm1     # 0x10630
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
subl $0xffff, %eax           # imm = 0xFFFF
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0xe80e
movq -0x20(%rbp), %rax
movb $0x0, 0x2c(%rax)
movq -0x20(%rbp), %rax
movb $0x0, 0x2d(%rax)
movq -0x20(%rbp), %rax
movb $0x1, 0x2e(%rax)
movq -0x10(%rbp), %rcx
movslq -0x2c(%rbp), %rax
addq %rax, %rcx
addq $0x1, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movl -0x14(%rbp), %ecx
subl -0x2c(%rbp), %ecx
subl $0x1, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x48(%rax)
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)