Squashed 'third_party/rawrtc/rew/' content from commit 24c91fd83

Change-Id: Ica2fcc790472ecd5b195d20da982c4e84139cbdd
git-subtree-dir: third_party/rawrtc/rew
git-subtree-split: 24c91fd839b40b11f727c902fa46d20874da33fb
diff --git a/src/pcp/reply.c b/src/pcp/reply.c
new file mode 100644
index 0000000..264dcbb
--- /dev/null
+++ b/src/pcp/reply.c
@@ -0,0 +1,93 @@
+/**
+ * @file pcp/reply.c  PCP reply
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_list.h>
+#include <re_sa.h>
+#include <re_udp.h>
+#include <re_pcp.h>
+#include "pcp.h"
+
+
+static int pcp_header_encode_response(struct mbuf *mb, enum pcp_opcode opcode,
+				      enum pcp_result result,
+				      uint32_t lifetime, uint32_t epoch_time)
+{
+	int err = 0;
+
+	if (!mb)
+		return EINVAL;
+
+	err |= mbuf_write_u8(mb, PCP_VERSION);
+	err |= mbuf_write_u8(mb, 1<<7 | opcode);
+	err |= mbuf_write_u8(mb, 0x00);
+	err |= mbuf_write_u8(mb, result);
+	err |= mbuf_write_u32(mb, htonl(lifetime));
+	err |= mbuf_write_u32(mb, htonl(epoch_time));
+	err |= mbuf_fill(mb, 0x00, 12);
+
+	return err;
+}
+
+
+/**
+ * Send a PCP response message
+ *
+ * @param us         UDP Socket
+ * @param dst        Destination network address
+ * @param req        Buffer containing original PCP request (optional)
+ * @param opcode     PCP opcode
+ * @param result     PCP result for the response
+ * @param lifetime   Lifetime in [seconds]
+ * @param epoch_time Server Epoch-time
+ * @param payload    PCP payload, e.g. struct pcp_map (optional)
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int pcp_reply(struct udp_sock *us, const struct sa *dst, struct mbuf *req,
+	      enum pcp_opcode opcode, enum pcp_result result,
+	      uint32_t lifetime, uint32_t epoch_time, const void *payload)
+{
+	struct mbuf *mb;
+	size_t start;
+	int err;
+
+	if (!us || !dst)
+		return EINVAL;
+
+	if (req) {
+		/* the complete Request must be included in the Response */
+		mb = mem_ref(req);
+	}
+	else {
+		mb = mbuf_alloc(128);
+		if (!mb)
+			return ENOMEM;
+	}
+
+	start = mb->pos;
+
+	/* encode the response packet */
+	err = pcp_header_encode_response(mb, opcode, result,
+					 lifetime, epoch_time);
+	if (err)
+		goto out;
+
+	if (payload) {
+		err = pcp_payload_encode(mb, opcode, payload);
+		if (err)
+			goto out;
+	}
+
+	mb->pos = start;
+	err = udp_send(us, dst, mb);
+
+ out:
+	mem_deref(mb);
+	return err;
+}