// File: /workspace/github_c_makefile_star2_O0/wtarreau[P]httpterm/httpterm.c
// Function: event_cli_write
int event_cli_write(int fd) {
    struct task *t = fdtab[fd].owner;
    struct session *s = t->context;
    struct buffer *b = s->rep;
    char *data_ptr;
    int ret;
    unsigned long long max;
    int max_loops = 4;

 loop_again:
    if (b->l == 0) { /* let's realign the buffer to optimize I/O */
	b->r = b->w = b->h = b->lr  = b->data;
	max = 0;
    }
    else if (b->r > b->w) {
	max = b->r - b->w;
    }
    else // cannot happen with a file's contents
	max = b->data + BUFSIZE - b->w;
    
    if (fdtab[fd].state != FD_STERROR) {
	data_ptr = b->w;
	if (max == 0) {
	    if (s->to_write > 0) {
		/* we'll send the buffer data, and make sure to align data according to
		 * what was already sent. This will guarantee that all requests will get
		 * the exact same contents. This cannot happen with a file's contents.
		 */
		unsigned int offset;
		char *buffer;
		size_t buffer_len;

		max = s->to_write;
		if (s->req_chunked) {
		    if (s->to_write > 5) {
			/* regular chunk, last 5 bytes are reserved for 0CRLFCRLF */
			buffer = common_chunk_resp;
			buffer_len = sizeof(common_chunk_resp);
			offset = (s->req_size - s->to_write) % CHUNK_LEN;
			max = s->to_write - 5;
		    } else {
			/* final chunk */
			buffer = "0\r\n\r\n";
			buffer_len = 5;
			offset = 5 - s->to_write;
		    }
		}
		else if (s->req_random) {
		    buffer = random_resp;
		    buffer_len = random_resp_len;
		    offset = (s->req_size - s->to_write) % random_resp_len;
		}
		else {
		    buffer = common_response;
		    buffer_len = sizeof(common_response);
		    offset = (s->req_size - s->to_write) % 50;
		}

		data_ptr = buffer + offset;
		if (max > (unsigned long long)(buffer_len - offset))
		    max = (unsigned long long)buffer_len - offset;

	    } else {
		if (s->res_cw != RES_DATA)
		    s->res_cw = RES_NULL;
		task_wakeup(&rq, t);
		tv_eternity(&s->cwexpire);
		my_fd_clr(fd, StaticWriteEvent);
		return 0;
	    }
	}

	if (s->req_pieces) {
	    if (max > s->req_pieces) {
		max = s->req_pieces;
		max = (((unsigned long long)max * ((rand() >> 8) & 0xFFFF)) >> 16) + 1;
	    }
	}

#ifndef MSG_NOSIGNAL
	{
	    int skerr;
	    socklen_t lskerr = sizeof(skerr);

	    getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
	    if (skerr)
		ret = -1;
	    else
		ret = send(fd, data_ptr, max, MSG_DONTWAIT);
	}
#else
	ret = max;
#ifdef ENABLE_SPLICE
	if (!b->l && max >= MIN_SPLICE && !(global.flags & GFLAGS_NO_SPLICE) && !s->req_nosplice) {
	    /* dummy data only */
	    if (!s->req_chunked) {

		if ((unsigned long long)slave_pipe_usage < s->to_write) {
		    ret = tee(master_pipe[0], slave_pipe[1], pipesize, SPLICE_F_NONBLOCK);
		    if (ret > 0)
			slave_pipe_usage += ret;
		    ret = max;
		}

		if (slave_pipe_usage) {
		    /* we need to release data from the pipe before calling tee() */
		    ret = splice(slave_pipe[0], NULL, fd, NULL, max, SPLICE_F_NONBLOCK|(((s->ka & 1) && (max >= s->to_write)) ? 0 : SPLICE_F_MORE));
		    if (ret > 0) {
			slave_pipe_usage -= ret;
			max = 0;
		    }
		    else if (ret < 0 && errno == EAGAIN) {
			/* Output buffer is full, ensure we don't try again with send() */
			max = 0;
		    }
		}
	    }

	    /* dummy chunked data */
	    else {
		int align;
		int shift;
		struct pipe *p = NULL;
		int i;
		char buf[3];
		struct pipe *not_found = NULL;
		char all_align[CHUNK_LEN];

		align = (s->req_size - s->to_write) % CHUNK_LEN;

	        /* search aligned pipe */
		memset(all_align, 0, sizeof(char) * CHUNK_LEN);
		for (i=0; i<CHUNK_LEN; i++) {
		    if (chunk_slave_pipe[i].start_alignment == align) {
			p = &chunk_slave_pipe[i];
			break;
		    }
		    all_align[chunk_slave_pipe[i].start_alignment]++;
		    if (all_align[chunk_slave_pipe[i].start_alignment] > 1)
			not_found = &chunk_slave_pipe[i];
		}

		/* if not aligned pipe found then adjust other pipe.
		 * "not_found" cannot be NULL.
		 */
		if (!p) {
		    p = not_found;
		    shift = align - p->start_alignment;
		    if (shift < 0)
			shift += CHUNK_LEN;
		    if (p->usage == 0) {
			p->stop_alignment = align;
		    }
		    else if (p->usage < shift) { /* reset */
			(void)!read(p->pipe[0], buf, p->usage);
			p->usage = 0;
			p->stop_alignment = align;
		    }
		    else {
			(void)!read(p->pipe[0], buf, shift);
			p->usage -= shift;
		    }
		    p->start_alignment = align;
		}

		/* fill data if needed */
		if ((unsigned long long)p->usage < s->to_write) {
		    ret = tee(chunked_pipe[p->stop_alignment][0], p->pipe[1], pipesize,
		              SPLICE_F_NONBLOCK);
		    if (ret > 0) {
			p->usage += ret;
			p->stop_alignment = ( p->stop_alignment + ret ) % CHUNK_LEN;
		    }
		}

		if (p->usage) {
		    /* always splice_f_more with chunked as we'll send() the 5 final bytes */
		    ret = splice(p->pipe[0], NULL, fd, NULL, max, SPLICE_F_NONBLOCK|((s->ka & 1 && !s->req_chunked) ? 0 : SPLICE_F_MORE));
		    if (ret > 0) {
			p->usage -= ret;
			max = 0;
			p->start_alignment = ( p->start_alignment + ret ) % CHUNK_LEN;
		    }
		    else if (ret < 0 && errno == EAGAIN) {
			/* Output buffer is full, ensure we don't try again with send() */
			max = 0;
		    }
		}
	    }
	}
#endif
	if (max && ret)
	    ret = send(fd, data_ptr, max, MSG_DONTWAIT | MSG_NOSIGNAL | ((s->req_pieces || ((s->ka & 1) && max >= s->to_write + b->l)) ? 0 : MSG_MORE));
#endif

	if (ret > 0) {
	    if (b->l > 0) {
		/* we were working on "standard" data */
		b->l -= ret;
		b->w += ret;
	    
		if (b->w == b->data + BUFSIZE) {
		    b->w = b->data; /* wrap around the buffer */
		}
	    } else {
		/* we were working on dummy data */
		s->to_write -= ret;
	    }
	    
	    s->res_cw = RES_DATA;
	    if (s->req_pieces) {
		/* do not loop */
		int rnd = (rand() >> 16) & 15;
		if (s->to_write && rnd) {
		    s->cli_state = CL_STPAUSE;
		    my_fd_clr(s->cli_fd, StaticWriteEvent);
		    /* pause between 1 and 256 ms */
		    tv_delayfrom(&s->cnexpire, &now, rnd);
		}
	    }
	    else if (--max_loops > 0)
		goto loop_again;
	}
	else if (ret == 0) {
	    /* nothing written, just make as if we were never called */
//	    s->res_cw = RES_NULL;
	    return 0;
	}
	else if (errno == EAGAIN) { /* ignore EAGAIN */
	    if (s->res_cw == RES_DATA)
		goto return_data;
	    return -1;
	}
	else {
	    s->res_cw = RES_ERROR;
	    fdtab[fd].state = FD_STERROR;
	}
    }
    else {
	s->res_cw = RES_ERROR;
	fdtab[fd].state = FD_STERROR;
    }
 return_data:
    if (s->proxy->clitimeout) {
	tv_delayfrom(&s->cwexpire, &now, s->proxy->clitimeout);
	/* FIXME: to prevent the client from expiring read timeouts during writes,
	 * we refresh it. A solution would be to merge read+write timeouts into a
	 * unique one, although that needs some study particularly on full-duplex
	 * TCP connections. */
	s->crexpire = s->cwexpire;
    }
    else
	tv_eternity(&s->cwexpire);

    task_wakeup(&rq, t);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movl %edi, -0x8(%rbp)
movq 0xd23b(%rip), %rax      # 0x113b0
movslq -0x8(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq 0x10(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x20(%rbp)
movl $0x4, -0x3c(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x41e2
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq $0x0, -0x38(%rbp)
jmp 0x422c
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x20(%rbp), %rcx
cmpq 0x10(%rcx), %rax
jbe 0x420d
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x20(%rbp), %rcx
movq 0x10(%rcx), %rcx
subq %rcx, %rax
movq %rax, -0x38(%rbp)
jmp 0x422a
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
addq $0x1000, %rax           # imm = 0x1000
movq -0x20(%rbp), %rcx
movq 0x10(%rcx), %rcx
subq %rcx, %rax
movq %rax, -0x38(%rbp)
jmp 0x422c
movq 0xd17d(%rip), %rax      # 0x113b0
movslq -0x8(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
cmpl $0x4, 0x18(%rax)
je 0x465f
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x4401
movq -0x18(%rbp), %rax
cmpq $0x0, 0x68(%rax)
jbe 0x43b2
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x15c(%rax)
je 0x4301
movq -0x18(%rbp), %rax
cmpq $0x5, 0x68(%rax)
jbe 0x42d9
leaq 0xd187(%rip), %rax      # 0x11420
movq %rax, -0x48(%rbp)
movq $0x10000, -0x50(%rbp)   # imm = 0x10000
movq -0x18(%rbp), %rax
movq 0x128(%rax), %rax
movq -0x18(%rbp), %rcx
subq 0x68(%rcx), %rax
movl $0x3, %ecx
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, -0x40(%rbp)
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rax
subq $0x5, %rax
movq %rax, -0x38(%rbp)
jmp 0x42fc
leaq 0xa05d(%rip), %rax      # 0xe33d
movq %rax, -0x48(%rbp)
movq $0x5, -0x50(%rbp)
movq -0x18(%rbp), %rcx
movl $0x5, %eax
subq 0x68(%rcx), %rax
movl %eax, -0x40(%rbp)
jmp 0x4381
movq -0x18(%rbp), %rax
cmpl $0x0, 0x164(%rax)
je 0x434a
movq 0x1d10b(%rip), %rax     # 0x21420
movq %rax, -0x48(%rbp)
movslq 0xd020(%rip), %rax      # 0x11340
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rax
movq 0x128(%rax), %rax
movq -0x18(%rbp), %rcx
subq 0x68(%rcx), %rax
movslq 0xd002(%rip), %rcx      # 0x11340
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, -0x40(%rbp)
jmp 0x437f
leaq 0x1d0df(%rip), %rax     # 0x21430
movq %rax, -0x48(%rbp)
movq $0x10000, -0x50(%rbp)   # imm = 0x10000
movq -0x18(%rbp), %rax
movq 0x128(%rax), %rax
movq -0x18(%rbp), %rcx
subq 0x68(%rcx), %rax
movl $0x32, %ecx
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, -0x40(%rbp)
jmp 0x4381
movq -0x48(%rbp), %rax
movl -0x40(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x38(%rbp), %rax
movq -0x50(%rbp), %rcx
movl -0x40(%rbp), %edx
subq %rdx, %rcx
cmpq %rcx, %rax
jbe 0x43b0
movq -0x50(%rbp), %rax
movl -0x40(%rbp), %ecx
subq %rcx, %rax
movq %rax, -0x38(%rbp)
jmp 0x43ff
movq -0x18(%rbp), %rax
movsbl 0x39(%rax), %eax
cmpl $0x1, %eax
je 0x43c7
movq -0x18(%rbp), %rax
movb $0x2, 0x39(%rax)
movq -0x10(%rbp), %rsi
leaq 0xcfe6(%rip), %rdi      # 0x113b8
callq 0x4110
movq -0x18(%rbp), %rdi
addq $0x18, %rdi
callq 0x40e0
movl -0x8(%rbp), %edi
movq 0x2d042(%rip), %rsi     # 0x31430
callq 0x3fd0
movl $0x0, -0x4(%rbp)
jmp 0x46ed
jmp 0x4401
movq -0x18(%rbp), %rax
cmpl $0x0, 0x168(%rax)
je 0x4462
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq 0x168(%rcx), %rcx
cmpq %rcx, %rax
jbe 0x4460
movq -0x18(%rbp), %rax
movslq 0x168(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x60(%rbp)
callq 0x2450
movl %eax, %ecx
movq -0x60(%rbp), %rax
sarl $0x8, %ecx
andl $0xffff, %ecx           # imm = 0xFFFF
movslq %ecx, %rcx
imulq %rcx, %rax
shrq $0x10, %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x4462
movq -0x38(%rbp), %rax
movl %eax, -0x2c(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x4509
cmpl $0x0, -0x2c(%rbp)
je 0x4509
movl -0x8(%rbp), %eax
movl %eax, -0x7c(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rcx
movb $0x1, %al
cmpl $0x0, 0x168(%rcx)
movb %al, -0x61(%rbp)
jne 0x44de
movq -0x18(%rbp), %rax
movl 0x54(%rax), %ecx
andl $0x1, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x7d(%rbp)
je 0x44d8
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x68(%rcx), %rcx
movq -0x20(%rbp), %rdx
movl (%rdx), %edx
addq %rdx, %rcx
cmpq %rcx, %rax
setae %al
movb %al, -0x7d(%rbp)
movb -0x7d(%rbp), %al
movb %al, -0x61(%rbp)
movq -0x70(%rbp), %rdx
movq -0x78(%rbp), %rsi
movl -0x7c(%rbp), %edi
movb -0x61(%rbp), %r8b
movl $0x8000, %ecx           # imm = 0x8000
xorl %eax, %eax
testb $0x1, %r8b
cmovnel %eax, %ecx
orl $0x4040, %ecx           # imm = 0x4040
callq 0x2150
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jle 0x4601
movq -0x20(%rbp), %rax
cmpl $0x0, (%rax)
jbe 0x456c
movl -0x2c(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
subl %edx, %ecx
movl %ecx, (%rax)
movl -0x2c(%rbp), %edx
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rcx
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x20(%rbp), %rcx
movq 0x30(%rcx), %rcx
addq $0x1000, %rcx           # imm = 0x1000
cmpq %rcx, %rax
jne 0x456a
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
jmp 0x457f
movslq -0x2c(%rbp), %rdx
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rcx
subq %rdx, %rcx
movq %rcx, 0x68(%rax)
movq -0x18(%rbp), %rax
movb $0x1, 0x39(%rax)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x168(%rax)
je 0x45ea
callq 0x2450
sarl $0x10, %eax
andl $0xf, %eax
movl %eax, -0x54(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x68(%rax)
je 0x45e8
cmpl $0x0, -0x54(%rbp)
je 0x45e8
movq -0x18(%rbp), %rax
movl $0x4, 0x4c(%rax)
movq -0x18(%rbp), %rax
movl 0x48(%rax), %edi
movq 0x2ce64(%rip), %rsi     # 0x31430
callq 0x3fd0
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movl -0x54(%rbp), %edx
leaq 0xce2d(%rip), %rsi      # 0x11410
callq 0x4030
jmp 0x45ff
movl -0x3c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, %eax
jle 0x45fd
jmp 0x41a7
jmp 0x45ff
jmp 0x465d
cmpl $0x0, -0x2c(%rbp)
jne 0x4613
movl $0x0, -0x4(%rbp)
jmp 0x46ed
callq 0x2070
cmpl $0xb, (%rax)
jne 0x4638
movq -0x18(%rbp), %rax
movsbl 0x39(%rax), %eax
cmpl $0x1, %eax
jne 0x462c
jmp 0x4682
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x46ed
movq -0x18(%rbp), %rax
movb $0x3, 0x39(%rax)
movq 0xcd69(%rip), %rax      # 0x113b0
movslq -0x8(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movl $0x4, 0x18(%rax)
jmp 0x465b
jmp 0x465d
jmp 0x4680
movq -0x18(%rbp), %rax
movb $0x3, 0x39(%rax)
movq 0xcd42(%rip), %rax      # 0x113b0
movslq -0x8(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movl $0x4, 0x18(%rax)
jmp 0x4682
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rax
cmpl $0x0, 0x30(%rax)
je 0x46c9
movq -0x18(%rbp), %rdi
addq $0x18, %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rax
movl 0x30(%rax), %edx
leaq 0xcd66(%rip), %rsi      # 0x11410
callq 0x4030
movq -0x18(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x18(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x20(%rcx), %rcx
movq %rcx, 0x10(%rax)
jmp 0x46d6
movq -0x18(%rbp), %rdi
addq $0x18, %rdi
callq 0x40e0
movq -0x10(%rbp), %rsi
leaq 0xccd7(%rip), %rdi      # 0x113b8
callq 0x4110
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax)