// File: hzeller[P]FlaschenTaschen-PixelPusher-bridge/ft-server.cc
// Function: udp_server_run_blocking(CompositeFlaschenTaschen*, ft::Mutex*)
void udp_server_run_blocking(CompositeFlaschenTaschen *display,
                             ft::Mutex *mutex) {
    static const int kBufferSize = 65535;  // maximum UDP has to offer.
    char *packet_buffer = new char[kBufferSize];
    bzero(packet_buffer, kBufferSize);

    struct sigaction sa = {{0}};  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
    sa.sa_handler = InterruptHandler;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);

    for (;;) {
        // TODO: also store src-address in case we want to do rate-limiting
        // per source-address.
        ssize_t received_bytes = recvfrom(server_socket,
                                          packet_buffer, kBufferSize,
                                          0, NULL, 0);
        if (interrupt_received)
            break;

        if (received_bytes < 0 && errno == EINTR) // Other signals. Don't care.
            continue;

        if (received_bytes < 0) {
            perror("Trouble receiving.");
            break;
        }

        ImageMetaInfo img_info = {0};
        img_info.width = display->width();  // defaults.
        img_info.height = display->height();

        const char *pixel_pos = ReadImageData(packet_buffer, received_bytes,
                                              &img_info);
        mutex->Lock();
        display->SetLayer(img_info.layer);
        for (int y = 0; y < img_info.height; ++y) {
            for (int x = 0; x < img_info.width; ++x) {
                Color c;
                c.r = *pixel_pos++;
                c.g = *pixel_pos++;
                c.b = *pixel_pos++;
                display->SetPixel(x + img_info.offset_x,
                                  y + img_info.offset_y,
                                  c);
            }
        }
        display->Send();
        display->SetLayer(0);  // Back to sane default.
        mutex->Unlock();
    }
    delete [] packet_buffer;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x2040
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
xorl %esi, %esi
movl $0xffff, %edx           # imm = 0xFFFF
callq 0x2110
leaq -0xb0(%rbp), %rdi
xorl %esi, %esi
movl $0x98, %edx
callq 0x2110
leaq 0x235(%rip), %rax       # 0x2ef0
movq %rax, -0xb0(%rbp)
movl $0xf, %edi
leaq -0xb0(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x2230
movl $0x2, %edi
leaq -0xb0(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x2230
movl 0x9546(%rip), %edi      # 0xc238
movq -0x18(%rbp), %rsi
movl $0xffff, %edx           # imm = 0xFFFF
xorl %ecx, %ecx
xorl %eax, %eax
movl %eax, %r9d
movq %r9, %r8
callq 0x2180
movq %rax, -0xb8(%rbp)
movb 0x954a(%rip), %al       # 0xc261
testb $0x1, %al
je 0x2d20
jmp 0x2ebf
cmpq $0x0, -0xb8(%rbp)
jge 0x2d36
callq 0x2050
cmpl $0x4, (%rax)
jne 0x2d36
jmp 0x2cec
cmpq $0x0, -0xb8(%rbp)
jge 0x2d51
leaq 0x551d(%rip), %rdi      # 0x8264
callq 0x21b0
jmp 0x2ebf
leaq -0xd0(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x2110
movq -0x8(%rbp), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movl %eax, -0xd0(%rbp)
movq -0x8(%rbp), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movl %eax, -0xcc(%rbp)
movq -0x18(%rbp), %rdi
movq -0xb8(%rbp), %rsi
leaq -0xd0(%rbp), %rdx
callq 0x53c0
movq %rax, -0xd8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2f00
movq -0x8(%rbp), %rdi
movl -0xbc(%rbp), %esi
callq 0x3560
movl $0x0, -0xdc(%rbp)
movl -0xdc(%rbp), %eax
cmpl -0xcc(%rbp), %eax
jge 0x2e9c
movl $0x0, -0xe0(%rbp)
movl -0xe0(%rbp), %eax
cmpl -0xd0(%rbp), %eax
jge 0x2e86
movq -0xd8(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0xd8(%rbp)
movb (%rax), %al
movb %al, -0xe3(%rbp)
movq -0xd8(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0xd8(%rbp)
movb (%rax), %al
movb %al, -0xe2(%rbp)
movq -0xd8(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0xd8(%rbp)
movb (%rax), %al
movb %al, -0xe1(%rbp)
movq -0x8(%rbp), %rdi
movl -0xe0(%rbp), %esi
addl -0xc4(%rbp), %esi
movl -0xdc(%rbp), %edx
addl -0xc0(%rbp), %edx
movq (%rdi), %rax
leaq -0xe3(%rbp), %rcx
callq *0x20(%rax)
movl -0xe0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe0(%rbp)
jmp 0x2de0
jmp 0x2e88
movl -0xdc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xdc(%rbp)
jmp 0x2dc4
movq -0x8(%rbp), %rdi
movq (%rdi), %rax
callq *0x28(%rax)
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x3560
movq -0x10(%rbp), %rdi
callq 0x2f20
jmp 0x2cec
movq -0x18(%rbp), %rax
movq %rax, -0xf0(%rbp)
cmpq $0x0, %rax
je 0x2edc
movq -0xf0(%rbp), %rdi
callq 0x2250
addq $0xf0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)