/*
 * Copyright (c) 2014 Masatake YAMATO <yamato@redhat.com>
 * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@altlinux.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "tests.h"
#include <assert.h>
#include <unistd.h>

#include "msghdr.h"

int
main(void)
{
	tprintf("%s", "");

	int fds[2];
	if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds))
		perror_msg_and_skip("socketpair");
	assert(0 == fds[0]);
	assert(1 == fds[1]);

	static const char w0_c[] = "012";
	const char *w0_d = hexdump_strdup(w0_c);
	void *w0 = tail_memdup(w0_c, LENGTH_OF(w0_c));

	static const char w1_c[] = "34567";
	const char *w1_d = hexdump_strdup(w1_c);
	void *w1 = tail_memdup(w1_c, LENGTH_OF(w1_c));

	static const char w2_c[] = "89abcde";
	const char *w2_d = hexdump_strdup(w2_c);
	void *w2 = tail_memdup(w2_c, LENGTH_OF(w2_c));

	const struct iovec w0_iov_[] = {
		{
			.iov_base = w0,
			.iov_len = LENGTH_OF(w0_c)
		}, {
			.iov_base = w1,
			.iov_len = LENGTH_OF(w1_c)
		}
	};
	struct iovec *w0_iov = tail_memdup(w0_iov_, sizeof(w0_iov_));

	const struct iovec w1_iov_[] = {
		{
			.iov_base = w2,
			.iov_len = LENGTH_OF(w2_c)
		}
	};
	struct iovec *w1_iov = tail_memdup(w1_iov_, sizeof(w1_iov_));

	const struct mmsghdr w_mmh_[] = {
		{
			.msg_hdr = {
				.msg_iov = w0_iov,
				.msg_iovlen = ARRAY_SIZE(w0_iov_),
			}
		}, {
			.msg_hdr = {
				.msg_iov = w1_iov,
				.msg_iovlen = ARRAY_SIZE(w1_iov_),
			}
		}
	};
	void *w_mmh = tail_memdup(w_mmh_, sizeof(w_mmh_));
	const unsigned int n_w_mmh = ARRAY_SIZE(w_mmh_);

	int r = send_mmsg(1, w_mmh, n_w_mmh, MSG_DONTROUTE | MSG_NOSIGNAL);
	if (r < 0)
		perror_msg_and_skip("sendmmsg");
	assert(r == (int) n_w_mmh);
	assert(close(1) == 0);
	tprintf("sendmmsg(1, [{msg_hdr={msg_name=NULL, msg_namelen=0"
		", msg_iov=[{iov_base=\"%s\", iov_len=%u}"
		", {iov_base=\"%s\", iov_len=%u}], msg_iovlen=%u"
		", msg_controllen=0, msg_flags=0}, msg_len=%u}"
		", {msg_hdr={msg_name=NULL, msg_namelen=0"
		", msg_iov=[{iov_base=\"%s\", iov_len=%u}], msg_iovlen=%u"
		", msg_controllen=0, msg_flags=0}, msg_len=%u}], %u"
		", MSG_DONTROUTE|MSG_NOSIGNAL) = %d\n"
		" = %u buffers in vector 0\n"
		" * %u bytes in buffer 0\n"
		" | 00000 %-49s  %-16s |\n"
		" * %u bytes in buffer 1\n"
		" | 00000 %-49s  %-16s |\n"
		" = %u buffers in vector 1\n"
		" * %u bytes in buffer 0\n"
		" | 00000 %-49s  %-16s |\n",
		w0_c, LENGTH_OF(w0_c),
		w1_c, LENGTH_OF(w1_c),
		(unsigned int) ARRAY_SIZE(w0_iov_),
		LENGTH_OF(w0_c) + LENGTH_OF(w1_c),
		w2_c, LENGTH_OF(w2_c), (unsigned int) ARRAY_SIZE(w1_iov_),
		LENGTH_OF(w2_c),
		n_w_mmh, r,
		(unsigned int) ARRAY_SIZE(w0_iov_),
		LENGTH_OF(w0_c), w0_d, w0_c,
		LENGTH_OF(w1_c), w1_d, w1_c,
		(unsigned int) ARRAY_SIZE(w1_iov_),
		LENGTH_OF(w2_c), w2_d, w2_c);

	const unsigned int w_len =
		LENGTH_OF(w0_c) + LENGTH_OF(w1_c) + LENGTH_OF(w2_c);
	const unsigned int r_len = (w_len + 1) / 2;
	void *r0 = tail_alloc(r_len);
	void *r1 = tail_alloc(r_len);
	void *r2 = tail_alloc(r_len);
	const struct iovec r0_iov_[] = {
		{
			.iov_base = r0,
			.iov_len = r_len
		}
	};
	struct iovec *r0_iov = tail_memdup(r0_iov_, sizeof(r0_iov_));
	const struct iovec r1_iov_[] = {
		{
			.iov_base = r1,
			.iov_len = r_len
		},
		{
			.iov_base = r2,
			.iov_len = r_len
		}
	};
	struct iovec *r1_iov = tail_memdup(r1_iov_, sizeof(r1_iov_));

	const struct mmsghdr r_mmh_[] = {
		{
			.msg_hdr = {
				.msg_iov = r0_iov,
				.msg_iovlen = ARRAY_SIZE(r0_iov_),
			}
		}, {
			.msg_hdr = {
				.msg_iov = r1_iov,
				.msg_iovlen = ARRAY_SIZE(r1_iov_),
			}
		}
	};
	void *r_mmh = tail_memdup(r_mmh_, sizeof(r_mmh_));
	const unsigned int n_r_mmh = ARRAY_SIZE(r_mmh_);

	static const char r0_c[] = "01234567";
	const char *r0_d = hexdump_strdup(r0_c);
	static const char r1_c[] = "89abcde";
	const char *r1_d = hexdump_strdup(r1_c);

	assert(recv_mmsg(0, r_mmh, n_r_mmh, MSG_DONTWAIT, NULL) == (int) n_r_mmh);
	assert(close(0) == 0);
	tprintf("recvmmsg(0, [{msg_hdr={msg_name=NULL, msg_namelen=0"
		", msg_iov=[{iov_base=\"%s\", iov_len=%u}], msg_iovlen=%u"
		", msg_controllen=0, msg_flags=0}, msg_len=%u}"
		", {msg_hdr={msg_name=NULL, msg_namelen=0"
		", msg_iov=[{iov_base=\"%s\", iov_len=%u}"
		", {iov_base=\"\", iov_len=%u}], msg_iovlen=%u"
		", msg_controllen=0, msg_flags=0}, msg_len=%u}], %u"
		", MSG_DONTWAIT, NULL) = %d\n"
		" = %u buffers in vector 0\n"
		" * %u bytes in buffer 0\n"
		" | 00000 %-49s  %-16s |\n"
		" = %u buffers in vector 1\n"
		" * %u bytes in buffer 0\n"
		" | 00000 %-49s  %-16s |\n",
		r0_c, r_len, (unsigned int) ARRAY_SIZE(r0_iov_),
		LENGTH_OF(r0_c), r1_c, r_len, r_len,
		(unsigned int) ARRAY_SIZE(r1_iov_), LENGTH_OF(r1_c),
		n_r_mmh, r,
		(unsigned int) ARRAY_SIZE(r0_iov_), LENGTH_OF(r0_c),
		r0_d, r0_c,
		(unsigned int) ARRAY_SIZE(r1_iov_), LENGTH_OF(r1_c),
		r1_d, r1_c);

	tprintf("+++ exited with 0 +++\n");
	return 0;
}
