Session() {capn_init_malloc(&capn);}
static int init_fp(struct capn *c, FILE *f, struct capn_stream *z, int packed) { /* * Initialize 'c' from the contents of 'f', assuming the message has been * serialized with the standard framing format. From https://capnproto.org/encoding.html: * * When transmitting over a stream, the following should be sent. All integers are unsigned and little-endian. * (4 bytes) The number of segments, minus one (since there is always at least one segment). * (N * 4 bytes) The size of each segment, in words. * (0 or 4 bytes) Padding up to the next word boundary. * The content of each segment, in order. */ struct capn_segment *s = NULL; uint32_t i, segnum, total = 0; uint32_t hdr[1024]; uint8_t zbuf[ZBUF_SZ]; char *data = NULL; capn_init_malloc(c); /* Read the first four bytes to know how many headers we have */ if (read_fp(&segnum, 4, f, z, zbuf, packed)) goto err; segnum = capn_flip32(segnum); if (segnum > 1023) goto err; segnum++; /* The wire encoding was zero-based */ /* Read the header list */ if (read_fp(hdr, 8 * (segnum/2) + 4, f, z, zbuf, packed)) goto err; for (i = 0; i < segnum; i++) { uint32_t n = capn_flip32(hdr[i]); if (n > INT_MAX/8 || n > UINT32_MAX/8 || UINT32_MAX - total < n*8) goto err; hdr[i] = n*8; total += hdr[i]; } /* Allocate space for the data and the capn_segment structs */ s = (struct capn_segment*) calloc(1, total + (sizeof(*s) * segnum)); if (!s) goto err; /* Now read the data and setup the capn_segment structs */ data = (char*) (s+segnum); if (read_fp(data, total, f, z, zbuf, packed)) goto err; for (i = 0; i < segnum; i++) { s[i].len = s[i].cap = hdr[i]; s[i].data = data; data += s[i].len; capn_append_segment(c, &s[i]); } /* Set the entire region to be freed on the last segment */ s[segnum-1].user = s; return 0; err: memset(c, 0, sizeof(*c)); free(s); return -1; }