aboutsummaryrefslogblamecommitdiffstats
path: root/libcoopgamma_flush.c
blob: a1f23d16c15a7b041fd446561f758cfe2fd7fee9 (plain) (tree)
















































                                                                                                 
/* 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;
}