#include "protocol_api.h"
#include "protocol_private.h"
-struct ctdb_req_call_wire {
- struct ctdb_req_header hdr;
- uint32_t flags;
- uint32_t db_id;
- uint32_t callid;
- uint32_t hopcount;
- uint32_t keylen;
- uint32_t calldatalen;
- uint8_t data[1]; /* key[] followed by calldata[] */
-};
-
struct ctdb_reply_call_wire {
struct ctdb_req_header hdr;
uint32_t status;
size_t ctdb_req_call_len(struct ctdb_req_header *h, struct ctdb_req_call *c)
{
- return offsetof(struct ctdb_req_call_wire, data) +
- ctdb_tdb_data_len(&c->key) +
- ctdb_tdb_data_len(&c->calldata);
+ return ctdb_req_header_len(h) +
+ ctdb_uint32_len(&c->flags) +
+ ctdb_uint32_len(&c->db_id) +
+ ctdb_uint32_len(&c->callid) +
+ ctdb_uint32_len(&c->hopcount) +
+ ctdb_tdb_datan_len(&c->key) +
+ ctdb_tdb_datan_len(&c->calldata);
}
int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c,
uint8_t *buf, size_t *buflen)
{
- struct ctdb_req_call_wire *wire =
- (struct ctdb_req_call_wire *)buf;
+ size_t offset = 0;
size_t length, np;
+ uint32_t u32;
if (c->key.dsize == 0) {
return EINVAL;
}
h->length = *buflen;
- ctdb_req_header_push(h, (uint8_t *)&wire->hdr, &np);
+ ctdb_req_header_push(h, buf+offset, &np);
+ offset += np;
- wire->flags = c->flags;
- wire->db_id = c->db_id;
- wire->callid = c->callid;
- wire->hopcount = c->hopcount;
- wire->keylen = ctdb_tdb_data_len(&c->key);
- wire->calldatalen = ctdb_tdb_data_len(&c->calldata);
- ctdb_tdb_data_push(&c->key, wire->data, &np);
- ctdb_tdb_data_push(&c->calldata, wire->data + wire->keylen, &np);
+ ctdb_uint32_push(&c->flags, buf+offset, &np);
+ offset += np;
+
+ ctdb_uint32_push(&c->db_id, buf+offset, &np);
+ offset += np;
+
+ ctdb_uint32_push(&c->callid, buf+offset, &np);
+ offset += np;
+
+ ctdb_uint32_push(&c->hopcount, buf+offset, &np);
+ offset += np;
+
+ u32 = ctdb_tdb_data_len(&c->key);
+ ctdb_uint32_push(&u32, buf+offset, &np);
+ offset += np;
+
+ u32 = ctdb_tdb_data_len(&c->calldata);
+ ctdb_uint32_push(&u32, buf+offset, &np);
+ offset += np;
+
+ ctdb_tdb_data_push(&c->key, buf+offset, &np);
+ offset += np;
+
+ ctdb_tdb_data_push(&c->calldata, buf+offset, &np);
+ offset += np;
return 0;
}
TALLOC_CTX *mem_ctx,
struct ctdb_req_call *c)
{
- struct ctdb_req_call_wire *wire =
- (struct ctdb_req_call_wire *)buf;
- size_t length, np;
+ struct ctdb_req_header header;
+ size_t offset = 0, np;
+ uint32_t u32;
int ret;
- length = offsetof(struct ctdb_req_call_wire, data);
- if (buflen < length) {
- return EMSGSIZE;
+ ret = ctdb_req_header_pull(buf+offset, buflen-offset, &header, &np);
+ if (ret != 0) {
+ return ret;
}
- if (wire->keylen > buflen || wire->calldatalen > buflen) {
- return EMSGSIZE;
+ offset += np;
+
+ if (h != NULL) {
+ *h = header;
}
- if (length + wire->keylen < length) {
- return EMSGSIZE;
+
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->flags, &np);
+ if (ret != 0) {
+ return ret;
}
- if (length + wire->keylen + wire->calldatalen < length) {
- return EMSGSIZE;
+ offset += np;
+
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->db_id, &np);
+ if (ret != 0) {
+ return ret;
}
- if (buflen < length + wire->keylen + wire->calldatalen) {
- return EMSGSIZE;
+ offset += np;
+
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->callid, &np);
+ if (ret != 0) {
+ return ret;
}
+ offset += np;
- if (h != NULL) {
- ret = ctdb_req_header_pull((uint8_t *)&wire->hdr, buflen, h,
- &np);
- if (ret != 0) {
- return ret;
- }
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &c->hopcount, &np);
+ if (ret != 0) {
+ return ret;
}
+ offset += np;
- c->flags = wire->flags;
- c->db_id = wire->db_id;
- c->callid = wire->callid;
- c->hopcount = wire->hopcount;
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
+ if (ret != 0) {
+ return ret;
+ }
+ offset += np;
+ c->key.dsize = u32;
- ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+ ret = ctdb_uint32_pull(buf+offset, buflen-offset, &u32, &np);
+ if (ret != 0) {
+ return ret;
+ }
+ offset += np;
+ c->calldata.dsize = u32;
+
+ if (buflen-offset < c->key.dsize) {
+ return EMSGSIZE;
+ }
+
+ ret = ctdb_tdb_data_pull(buf+offset, c->key.dsize, mem_ctx, &c->key,
&np);
if (ret != 0) {
return ret;
}
+ offset += np;
+
+ if (buflen-offset < c->calldata.dsize) {
+ return EMSGSIZE;
+ }
- ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->calldatalen,
+ ret = ctdb_tdb_data_pull(buf+offset, c->calldata.dsize,
mem_ctx, &c->calldata, &np);
if (ret != 0) {
return ret;
}
+ offset += np;
return 0;
}
#include "protocol/protocol_basic.c"
#include "protocol/protocol_types.c"
#include "protocol/protocol_header.c"
+#include "protocol/protocol_call.c"
#include "tests/src/protocol_common.h"
#include "tests/src/protocol_common_ctdb.h"
return 0;
}
+struct ctdb_req_call_wire {
+ struct ctdb_req_header hdr;
+ uint32_t flags;
+ uint32_t db_id;
+ uint32_t callid;
+ uint32_t hopcount;
+ uint32_t keylen;
+ uint32_t calldatalen;
+ uint8_t data[1]; /* key[] followed by calldata[] */
+};
+
+static size_t ctdb_req_call_len_old(struct ctdb_req_header *h,
+ struct ctdb_req_call *c)
+{
+ return offsetof(struct ctdb_req_call_wire, data) +
+ ctdb_tdb_data_len(&c->key) +
+ ctdb_tdb_data_len(&c->calldata);
+}
+
+static int ctdb_req_call_push_old(struct ctdb_req_header *h,
+ struct ctdb_req_call *c,
+ uint8_t *buf, size_t *buflen)
+{
+ struct ctdb_req_call_wire *wire =
+ (struct ctdb_req_call_wire *)buf;
+ size_t length, np;
+
+ if (c->key.dsize == 0) {
+ return EINVAL;
+ }
+
+ length = ctdb_req_call_len_old(h, c);
+ if (*buflen < length) {
+ *buflen = length;
+ return EMSGSIZE;
+ }
+
+ h->length = *buflen;
+ ctdb_req_header_push_old(h, (uint8_t *)&wire->hdr);
+
+ wire->flags = c->flags;
+ wire->db_id = c->db_id;
+ wire->callid = c->callid;
+ wire->hopcount = c->hopcount;
+ wire->keylen = ctdb_tdb_data_len(&c->key);
+ wire->calldatalen = ctdb_tdb_data_len(&c->calldata);
+ ctdb_tdb_data_push(&c->key, wire->data, &np);
+ ctdb_tdb_data_push(&c->calldata, wire->data + wire->keylen, &np);
+
+ return 0;
+}
+
+static int ctdb_req_call_pull_old(uint8_t *buf, size_t buflen,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_call *c)
+{
+ struct ctdb_req_call_wire *wire =
+ (struct ctdb_req_call_wire *)buf;
+ size_t length, np;
+ int ret;
+
+ length = offsetof(struct ctdb_req_call_wire, data);
+ if (buflen < length) {
+ return EMSGSIZE;
+ }
+ if (wire->keylen > buflen || wire->calldatalen > buflen) {
+ return EMSGSIZE;
+ }
+ if (length + wire->keylen < length) {
+ return EMSGSIZE;
+ }
+ if (length + wire->keylen + wire->calldatalen < length) {
+ return EMSGSIZE;
+ }
+ if (buflen < length + wire->keylen + wire->calldatalen) {
+ return EMSGSIZE;
+ }
+
+ if (h != NULL) {
+ ret = ctdb_req_header_pull_old((uint8_t *)&wire->hdr, buflen,
+ h);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ c->flags = wire->flags;
+ c->db_id = wire->db_id;
+ c->callid = wire->callid;
+ c->hopcount = wire->hopcount;
+
+ ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+ &np);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->calldatalen,
+ mem_ctx, &c->calldata, &np);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
COMPAT_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header);
+COMPAT_CTDB4_TEST(struct ctdb_req_call, ctdb_req_call, CTDB_REQ_CALL);
+
int main(int argc, char *argv[])
{
if (argc == 2) {
COMPAT_TEST_FUNC(ctdb_req_header)();
+ COMPAT_TEST_FUNC(ctdb_req_call)();
+
return 0;
}
PROTOCOL_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header);
-static void test_ctdb_req_call(void)
-{
- TALLOC_CTX *mem_ctx;
- uint8_t *pkt;
- size_t datalen, pkt_len, len;
- int ret;
- struct ctdb_req_header h, h2;
- struct ctdb_req_call c, c2;
-
- printf("ctdb_req_call\n");
- fflush(stdout);
-
- mem_ctx = talloc_new(NULL);
- assert(mem_ctx != NULL);
-
- ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_CALL,
- DESTNODE, SRCNODE, REQID);
-
- fill_ctdb_req_call(mem_ctx, &c);
- datalen = ctdb_req_call_len(&h, &c);
- ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
- assert(ret == 0);
- assert(pkt != NULL);
- assert(pkt_len >= datalen);
- len = 0;
- ret = ctdb_req_call_push(&h, &c, pkt, &len);
- assert(ret == EMSGSIZE);
- assert(len == datalen);
- ret = ctdb_req_call_push(&h, &c, pkt, &pkt_len);
- assert(ret == 0);
- ret = ctdb_req_call_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
- assert(ret == 0);
- verify_ctdb_req_header(&h, &h2);
- assert(h2.length == pkt_len);
- verify_ctdb_req_call(&c, &c2);
-
- talloc_free(mem_ctx);
-}
+PROTOCOL_CTDB4_TEST(struct ctdb_req_call, ctdb_req_call, CTDB_REQ_CALL);
static void test_ctdb_reply_call(void)
{
TEST_FUNC(ctdb_req_header)();
- test_ctdb_req_call();
+ TEST_FUNC(ctdb_req_call)();
test_ctdb_reply_call();
test_ctdb_reply_error();
test_ctdb_req_dmaster();