aboutsummaryrefslogtreecommitdiffstats
path: root/libcoopgamma_flush.c
blob: a1f23d16c15a7b041fd446561f758cfe2fd7fee9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* See LICENSE file for copyright and license details. */
#include "common.h"


/**
 * Send all pending outbound data
 * 
 * If this function or another function that sends a request
 * to the server fails with EINTR, call this function to
 * complete the transfer. The `async` parameter will always
 * be in a properly configured state if a function fails
 * with EINTR.
 * 
 * @param   ctx  The state of the library, must be connected
 * @return       Zero on success, -1 on error
 */
int
libcoopgamma_flush(libcoopgamma_context_t *restrict ctx)
{
	ssize_t sent;
	size_t chunksize = ctx->outbound_head - ctx->outbound_tail;
	size_t sendsize;

	while (ctx->outbound_tail < ctx->outbound_head) {
		sendsize = ctx->outbound_head - ctx->outbound_tail;
		sendsize = sendsize < chunksize ? sendsize : chunksize;
		sent = send(ctx->fd, &ctx->outbound[ctx->outbound_tail], sendsize, MSG_NOSIGNAL);
		if (sent < 0) {
			if (errno == EPIPE)
				errno = ECONNRESET;
			if (errno != EMSGSIZE)
				return -1;
			if (!(chunksize >>= 1))
				return -1;
			continue;
		}

#ifdef DEBUG_MODE
		fprintf(stderr, "\033[31m");
		fwrite(&ctx->outbound[ctx->outbound_tail], (size_t)sent, 1U, stderr);
		fprintf(stderr, "\033[m");
		fflush(stderr);
#endif

		ctx->outbound_tail += (size_t)sent;
	}

	return 0;
}