int websocket_data_handler(struct mg_connection *conn) {
  unsigned char buf[200], reply[200];
  int n, i, mask_len, xor, msg_len, len;
  len = 0;
  msg_len = mask_len = 0;
  for (;;) {
    if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
      return 0;
    }
    len += n;
    if (len >= 2) {
      msg_len = buf[1] & 127;
      mask_len = (buf[1] & 128) ? 4 : 0;
      if (msg_len > 125) {
        return 0;
      }
      if (len >= 2 + mask_len + msg_len) {
        break;
      }
    }
  }
  reply[0] = 0x81;
  reply[1] = msg_len;
  for (i = 0; i < msg_len; i++) {
    xor = mask_len == 0 ? 0 : buf[2 + (i % 4)];
    reply[i + 2] = buf[i + 2 + mask_len] ^ xor;
  }
  mg_write(conn, reply, 2 + msg_len);
  return memcmp(reply + 2, "exit", 4);
}


x86 assembly (clang, -O0):
<websocket_data_handler>:
push   %rbp
mov    %rsp,%rbp
sub    $0x1d0,%rsp
mov    %rdi,-0x10(%rbp)
movl   $0x0,-0x1c8(%rbp)
movl   $0x0,-0x1bc(%rbp)
movl   $0x0,-0x1c4(%rbp)
mov    -0x10(%rbp),%rdi
lea    -0xe0(%rbp),%rsi
movslq -0x1c8(%rbp),%rax
add    %rax,%rsi
movslq -0x1c8(%rbp),%rax
mov    $0xc8,%edx
sub    %rax,%rdx
mov    $0x0,%al
call   1050 <mg_read@plt>
mov    %eax,-0x1b4(%rbp)
cmp    $0x0,%eax
jg     11a3 <websocket_data_handler+0x73>
movl   $0x0,-0x4(%rbp)
jmp    132f <websocket_data_handler+0x1ff>
mov    -0x1b4(%rbp),%eax
add    -0x1c8(%rbp),%eax
mov    %eax,-0x1c8(%rbp)
cmpl   $0x2,-0x1c8(%rbp)
jl     1232 <websocket_data_handler+0x102>
movzbl -0xdf(%rbp),%eax
and    $0x7f,%eax
mov    %eax,-0x1c4(%rbp)
movzbl -0xdf(%rbp),%edx
and    $0x80,%edx
xor    %eax,%eax
mov    $0x4,%ecx
cmp    $0x0,%edx
cmovne %ecx,%eax
mov    %eax,-0x1bc(%rbp)
cmpl   $0x7d,-0x1c4(%rbp)
jle    120b <websocket_data_handler+0xdb>
movl   $0x0,-0x4(%rbp)
jmp    132f <websocket_data_handler+0x1ff>
mov    -0x1c8(%rbp),%eax
mov    -0x1bc(%rbp),%ecx
add    $0x2,%ecx
add    -0x1c4(%rbp),%ecx
cmp    %ecx,%eax
jl     122d <websocket_data_handler+0xfd>
jmp    1237 <websocket_data_handler+0x107>
jmp    1232 <websocket_data_handler+0x102>
jmp    115d <websocket_data_handler+0x2d>
movb   $0x81,-0x1b0(%rbp)
mov    -0x1c4(%rbp),%eax
mov    %al,-0x1af(%rbp)
movl   $0x0,-0x1b8(%rbp)
mov    -0x1b8(%rbp),%eax
cmp    -0x1c4(%rbp),%eax
jge    12f5 <websocket_data_handler+0x1c5>
cmpl   $0x0,-0x1bc(%rbp)
jne    1280 <websocket_data_handler+0x150>
xor    %eax,%eax
mov    %eax,-0x1cc(%rbp)
jmp    12a2 <websocket_data_handler+0x172>
mov    -0x1b8(%rbp),%eax
mov    $0x4,%ecx
cltd
idiv   %ecx
add    $0x2,%edx
movslq %edx,%rax
movzbl -0xe0(%rbp,%rax,1),%eax
ff
mov    %eax,-0x1cc(%rbp)
mov    -0x1cc(%rbp),%eax
mov    %eax,-0x1c0(%rbp)
mov    -0x1b8(%rbp),%eax
add    $0x2,%eax
add    -0x1bc(%rbp),%eax
cltq
movzbl -0xe0(%rbp,%rax,1),%eax
ff
xor    -0x1c0(%rbp),%eax
mov    %al,%cl
mov    -0x1b8(%rbp),%eax
add    $0x2,%eax
cltq
mov    %cl,-0x1b0(%rbp,%rax,1)
mov    -0x1b8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1b8(%rbp)
jmp    1254 <websocket_data_handler+0x124>
mov    -0x10(%rbp),%rdi
lea    -0x1b0(%rbp),%rsi
mov    -0x1c4(%rbp),%edx
add    $0x2,%edx
mov    $0x0,%al
call   1030 <mg_write@plt>
lea    -0x1b0(%rbp),%rdi
add    $0x2,%rdi
lea    0xcde(%rip),%rsi
mov    $0x4,%edx
call   1040 <memcmp@plt>
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x1d0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<websocket_data_handler>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x198,%rsp
mov    %rdi,%r15
xor    %ebp,%ebp
lea    0xd0(%rsp),%r14
mov    $0xc8,%edx
mov    %r14,%rsi
xor    %eax,%eax
call   1040 <mg_read@plt>
test   %eax,%eax
jle    1285 <websocket_data_handler+0x165>
xor    %ebx,%ebx
xor    %ebp,%ebp
jmp    1188 <websocket_data_handler+0x68>
nopw   0x0(%rax,%rax,1)
movslq %ebx,%rax
lea    (%rsp,%rax,1),%rsi
add    $0xd0,%rsi
mov    $0xc8,%edx
sub    %rax,%rdx
mov    %r15,%rdi
xor    %eax,%eax
call   1040 <mg_read@plt>
test   %eax,%eax
jle    1285 <websocket_data_handler+0x165>
mov    %ebx,%ecx
mov    %eax,%ebx
add    %ecx,%ebx
cmp    $0x2,%ebx
jl     1160 <websocket_data_handler+0x40>
movzbl 0xd1(%rsp),%eax
mov    %eax,%ecx
and    $0x7f,%ecx
cmp    $0x7d,%ecx
ja     11e9 <websocket_data_handler+0xc9>
shr    $0x5,%rax
and    $0xfffffffc,%eax
lea    (%rcx,%rax,1),%edx
add    $0x2,%edx
cmp    %edx,%ebx
jb     1160 <websocket_data_handler+0x40>
lea    0x2(%rcx),%edx
movb   $0x81,(%rsp)
mov    %cl,0x1(%rsp)
test   %ecx,%ecx
je     125f <websocket_data_handler+0x13f>
cmp    $0x1,%ecx
jne    11f0 <websocket_data_handler+0xd0>
xor    %esi,%esi
test   $0x1,%cl
je     125f <websocket_data_handler+0x13f>
test   %eax,%eax
je     124b <websocket_data_handler+0x12b>
mov    %esi,%ecx
and    $0x3,%ecx
mov    0x2(%rcx,%r14,1),%cl
jmp    124d <websocket_data_handler+0x12d>
xor    %ebp,%ebp
jmp    1285 <websocket_data_handler+0x165>
mov    %ecx,%r8d
and    $0xfffffffe,%r8d
lea    (%rsp,%rax,1),%rbp
add    $0xd3,%rbp
xor    %esi,%esi
jmp    122c <websocket_data_handler+0x10c>
cs nopw 0x0(%rax,%rax,1)
movzbl -0x1(%rbp,%rsi,1),%ebx
mov    %bl,0x2(%rsp,%rsi,1)
xor    %ebx,%ebx
xor    0x0(%rbp,%rsi,1),%bl
mov    %bl,0x3(%rsp,%rsi,1)
add    $0x2,%rsi
cmp    %rsi,%r8
je     11d0 <websocket_data_handler+0xb0>
test   %eax,%eax
je     1210 <websocket_data_handler+0xf0>
mov    %esi,%edi
and    $0x2,%edi
movzbl -0x1(%rbp,%rsi,1),%ebx
xor    0x2(%rdi,%r14,1),%bl
mov    %bl,0x2(%rsp,%rsi,1)
movzbl 0x3(%rdi,%r14,1),%ebx
jmp    121b <websocket_data_handler+0xfb>
xor    %ecx,%ecx
add    %rsi,%rax
add    $0x2,%rax
xor    0xd0(%rsp,%rax,1),%cl
mov    %cl,0x2(%rsp,%rsi,1)
mov    %rsp,%rsi
mov    %r15,%rdi
xor    %eax,%eax
call   1030 <mg_write@plt>
mov    0x2(%rsp),%eax
bswap  %eax
xor    %ebp,%ebp
cmp    $0x65786975,%eax
setae  %bpl
cmp    $0x65786974,%eax
sbb    $0x0,%ebp
mov    %ebp,%eax
add    $0x198,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.mg_connection = type opaque
@.str = [5 x i8] c"exit\00"
define i32 @websocket_data_handler(%struct.mg_connection* %0) {
%2 = alloca i32
%3 = alloca %struct.mg_connection*
%4 = alloca [200 x i8]
%5 = alloca [200 x i8]
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
store %struct.mg_connection* %0, %struct.mg_connection** %3
store i32 0, i32* %11
store i32 0, i32* %8
store i32 0, i32* %10
br label %12
12: ; preds = %54, %1
%13 = load %struct.mg_connection*, %struct.mg_connection** %3
%14 = getelementptr inbounds [200 x i8], [200 x i8]* %4, i64 0, i64 0
%15 = load i32, i32* %11
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds i8, i8* %14, i64 %16
%18 = load i32, i32* %11
%19 = sext i32 %18 to i64
%20 = sub i64 200, %19
%21 = call i32 (%struct.mg_connection*, i8*, i64, ...) bitcast (i32 (...)* @mg_read to i32 (%struct.mg_connection*, i8*, i64, ...)*)(%struct.mg_connection* %13, i8* %17, i64 %20)
store i32 %21, i32* %6
%22 = icmp sle i32 %21, 0
br i1 %22, label %23, label %24
23: ; preds = %12
store i32 0, i32* %2
br label %105
24: ; preds = %12
%25 = load i32, i32* %6
%26 = load i32, i32* %11
%27 = add nsw i32 %26, %25
store i32 %27, i32* %11
%28 = load i32, i32* %11
%29 = icmp sge i32 %28, 2
br i1 %29, label %30, label %54
30: ; preds = %24
%31 = getelementptr inbounds [200 x i8], [200 x i8]* %4, i64 0, i64 1
%32 = load i8, i8* %31
%33 = zext i8 %32 to i32
%34 = and i32 %33, 127
store i32 %34, i32* %10
%35 = getelementptr inbounds [200 x i8], [200 x i8]* %4, i64 0, i64 1
%36 = load i8, i8* %35
%37 = zext i8 %36 to i32
%38 = and i32 %37, 128
%39 = icmp ne i32 %38, 0
%40 = zext i1 %39 to i64
%41 = select i1 %39, i32 4, i32 0
store i32 %41, i32* %8
%42 = load i32, i32* %10
%43 = icmp sgt i32 %42, 125
br i1 %43, label %44, label %45
44: ; preds = %30
store i32 0, i32* %2
br label %105
45: ; preds = %30
%46 = load i32, i32* %11
%47 = load i32, i32* %8
%48 = add nsw i32 2, %47
%49 = load i32, i32* %10
%50 = add nsw i32 %48, %49
%51 = icmp sge i32 %46, %50
br i1 %51, label %52, label %53
52: ; preds = %45
br label %55
53: ; preds = %45
br label %54
54: ; preds = %53, %24
br label %12
55: ; preds = %52
%56 = getelementptr inbounds [200 x i8], [200 x i8]* %5, i64 0, i64 0
store i8 -127, i8* %56
%57 = load i32, i32* %10
%58 = trunc i32 %57 to i8
%59 = getelementptr inbounds [200 x i8], [200 x i8]* %5, i64 0, i64 1
store i8 %58, i8* %59
store i32 0, i32* %7
br label %60
60: ; preds = %93, %55
%61 = load i32, i32* %7
%62 = load i32, i32* %10
%63 = icmp slt i32 %61, %62
br i1 %63, label %64, label %96
64: ; preds = %60
%65 = load i32, i32* %8
%66 = icmp eq i32 %65, 0
br i1 %66, label %67, label %68
67: ; preds = %64
br label %76
68: ; preds = %64
%69 = load i32, i32* %7
%70 = srem i32 %69, 4
%71 = add nsw i32 2, %70
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [200 x i8], [200 x i8]* %4, i64 0, i64 %72
%74 = load i8, i8* %73
%75 = zext i8 %74 to i32
br label %76
76: ; preds = %68, %67
%77 = phi i32 [ 0, %67 ], [ %75, %68 ]
store i32 %77, i32* %9
%78 = load i32, i32* %7
%79 = add nsw i32 %78, 2
%80 = load i32, i32* %8
%81 = add nsw i32 %79, %80
%82 = sext i32 %81 to i64
%83 = getelementptr inbounds [200 x i8], [200 x i8]* %4, i64 0, i64 %82
%84 = load i8, i8* %83
%85 = zext i8 %84 to i32
%86 = load i32, i32* %9
%87 = xor i32 %85, %86
%88 = trunc i32 %87 to i8
%89 = load i32, i32* %7
%90 = add nsw i32 %89, 2
%91 = sext i32 %90 to i64
%92 = getelementptr inbounds [200 x i8], [200 x i8]* %5, i64 0, i64 %91
store i8 %88, i8* %92
br label %93
93: ; preds = %76
%94 = load i32, i32* %7
%95 = add nsw i32 %94, 1
store i32 %95, i32* %7
br label %60
96: ; preds = %60
%97 = load %struct.mg_connection*, %struct.mg_connection** %3
%98 = getelementptr inbounds [200 x i8], [200 x i8]* %5, i64 0, i64 0
%99 = load i32, i32* %10
%100 = add nsw i32 2, %99
%101 = call i32 (%struct.mg_connection*, i8*, i32, ...) bitcast (i32 (...)* @mg_write to i32 (%struct.mg_connection*, i8*, i32, ...)*)(%struct.mg_connection* %97, i8* %98, i32 %100)
%102 = getelementptr inbounds [200 x i8], [200 x i8]* %5, i64 0, i64 0
%103 = getelementptr inbounds i8, i8* %102, i64 2
%104 = call i32 @memcmp(i8* %103, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 4)
store i32 %104, i32* %2
br label %105
105: ; preds = %96, %44, %23
%106 = load i32, i32* %2
ret i32 %106
}

LLVM IR (-O2):
%struct.mg_connection = type opaque
@.str = [5 x i8] c"exit\00"
define i32 @websocket_data_handler(%struct.mg_connection* %0) {
%2 = alloca [200 x i8]
%3 = alloca [200 x i8]
%4 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 0
%5 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 0
%6 = call i32 (%struct.mg_connection*, i8*, i64, ...) bitcast (i32 (...)* @mg_read to i32 (%struct.mg_connection*, i8*, i64, ...)*)(%struct.mg_connection* %0, i8* %4, i64 200)
%7 = icmp slt i32 %6, 1
br i1 %7, label %100, label %8
8: ; preds = %1
%9 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 1
br label %10
10: ; preds = %8, %26
%11 = phi i32 [ %6, %8 ], [ %30, %26 ]
%12 = phi i32 [ 0, %8 ], [ %13, %26 ]
%13 = add nsw i32 %11, %12
%14 = icmp sgt i32 %13, 1
br i1 %14, label %15, label %26
15: ; preds = %10
%16 = load i8, i8* %9
%17 = zext i8 %16 to i32
%18 = and i32 %17, 127
%19 = lshr i32 %17, 5
%20 = and i32 %19, 4
%21 = icmp ugt i32 %18, 125
br i1 %21, label %100, label %22
22: ; preds = %15
%23 = add nuw nsw i32 %18, 2
%24 = add nuw nsw i32 %23, %20
%25 = icmp ult i32 %13, %24
br i1 %25, label %26, label %32
26: ; preds = %22, %10
%27 = sext i32 %13 to i64
%28 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %27
%29 = sub nsw i64 200, %27
%30 = call i32 (%struct.mg_connection*, i8*, i64, ...) bitcast (i32 (...)* @mg_read to i32 (%struct.mg_connection*, i8*, i64, ...)*)(%struct.mg_connection* %0, i8* %28, i64 %29)
%31 = icmp slt i32 %30, 1
br i1 %31, label %100, label %10
32: ; preds = %22
store i8 -127, i8* %5
%33 = trunc i32 %18 to i8
%34 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 1
store i8 %33, i8* %34
%35 = icmp eq i32 %18, 0
br i1 %35, label %96, label %36
36: ; preds = %32
%37 = icmp eq i32 %20, 0
%38 = zext i32 %20 to i64
%39 = zext i32 %18 to i64
%40 = and i64 %39, 1
%41 = icmp eq i32 %18, 1
br i1 %41, label %79, label %42
42: ; preds = %36
%43 = and i64 %39, 126
br label %44
44: ; preds = %68, %42
%45 = phi i64 [ 0, %42 ], [ %76, %68 ]
%46 = phi i64 [ 0, %42 ], [ %77, %68 ]
br i1 %37, label %62, label %47
47: ; preds = %44
%48 = and i64 %45, 2
%49 = add nuw nsw i64 %48, 2
%50 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %49
%51 = load i8, i8* %50
%52 = add nuw nsw i64 %45, 2
%53 = add nuw nsw i64 %52, %38
%54 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %53
%55 = load i8, i8* %54
%56 = xor i8 %55, %51
%57 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 %52
store i8 %56, i8* %57
%58 = and i64 %45, 2
%59 = add nuw nsw i64 %58, 3
%60 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %59
%61 = load i8, i8* %60
br label %68
62: ; preds = %44
%63 = add nuw nsw i64 %45, 2
%64 = add nuw nsw i64 %63, %38
%65 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %64
%66 = load i8, i8* %65
%67 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 %63
store i8 %66, i8* %67
br label %68
68: ; preds = %62, %47
%69 = phi i8 [ %61, %47 ], [ 0, %62 ]
%70 = add nuw nsw i64 %45, 3
%71 = add nuw nsw i64 %70, %38
%72 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %71
%73 = load i8, i8* %72
%74 = xor i8 %73, %69
%75 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 %70
store i8 %74, i8* %75
%76 = add nuw nsw i64 %45, 2
%77 = add i64 %46, 2
%78 = icmp eq i64 %77, %43
br i1 %78, label %79, label %44
79: ; preds = %68, %36
%80 = phi i64 [ 0, %36 ], [ %76, %68 ]
%81 = icmp eq i64 %40, 0
br i1 %81, label %96, label %82
82: ; preds = %79
br i1 %37, label %88, label %83
83: ; preds = %82
%84 = and i64 %80, 3
%85 = add nuw nsw i64 %84, 2
%86 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %85
%87 = load i8, i8* %86
br label %88
88: ; preds = %83, %82
%89 = phi i8 [ %87, %83 ], [ 0, %82 ]
%90 = add nuw nsw i64 %80, 2
%91 = add nuw nsw i64 %90, %38
%92 = getelementptr inbounds [200 x i8], [200 x i8]* %2, i64 0, i64 %91
%93 = load i8, i8* %92
%94 = xor i8 %93, %89
%95 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 %90
store i8 %94, i8* %95
br label %96
96: ; preds = %88, %79, %32
%97 = call i32 (%struct.mg_connection*, i8*, i32, ...) bitcast (i32 (...)* @mg_write to i32 (%struct.mg_connection*, i8*, i32, ...)*)(%struct.mg_connection* %0, i8* %5, i32 %23)
%98 = getelementptr inbounds [200 x i8], [200 x i8]* %3, i64 0, i64 2
%99 = call i32 @memcmp(i8* dereferenceable(4) %98, i8* dereferenceable(4) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 4)
br label %100
100: ; preds = %26, %15, %1, %96
%101 = phi i32 [ %99, %96 ], [ 0, %1 ], [ 0, %15 ], [ 0, %26 ]
ret i32 %101
}