201 строка
5.6 KiB
C
201 строка
5.6 KiB
C
|
/*
|
||
|
* librdkafka - Apache Kafka C library
|
||
|
*
|
||
|
* Copyright (c) 2012,2013 Magnus Edenhill
|
||
|
* 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.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Kafka protocol definitions.
|
||
|
*/
|
||
|
|
||
|
#define RD_KAFKA_PORT 9092
|
||
|
#define RD_KAFKA_PORT_STR "9092"
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Request header
|
||
|
*/
|
||
|
struct rd_kafkap_reqhdr {
|
||
|
int32_t Size;
|
||
|
int16_t ApiKey;
|
||
|
#define RD_KAFKAP_Produce 0
|
||
|
#define RD_KAFKAP_Fetch 1
|
||
|
#define RD_KAFKAP_Offset 2
|
||
|
#define RD_KAFKAP_Metadata 3
|
||
|
#define RD_KAFKAP_LeaderAndIsr 4
|
||
|
#define RD_KAFKAP_StopReplica 5
|
||
|
#define RD_KAFKAP_OffsetCommit 6
|
||
|
#define RD_KAFKAP_OffsetFetch 7
|
||
|
int16_t ApiVersion;
|
||
|
int32_t CorrId;
|
||
|
/* ClientId follows */
|
||
|
} RD_PACKED;
|
||
|
|
||
|
/**
|
||
|
* Response header
|
||
|
*/
|
||
|
struct rd_kafkap_reshdr {
|
||
|
int32_t Size;
|
||
|
int32_t CorrId;
|
||
|
} RD_PACKED;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* Kafka protocol string representation: { uint16, data.. }
|
||
|
*
|
||
|
*/
|
||
|
typedef struct rd_kafkap_str_s {
|
||
|
int16_t len; /* big endian */
|
||
|
char str[0]; /* allocated dynamically */
|
||
|
} RD_PACKED rd_kafkap_str_t;
|
||
|
|
||
|
#define RD_KAFKAP_KEY_LEN_NULL -1
|
||
|
/* Returns the actual size of a kafka protocol string representation. */
|
||
|
#define RD_KAFKAP_STR_SIZE(kstr) (int16_t)(sizeof((kstr)->len) + \
|
||
|
(ntohs((kstr)->len) == \
|
||
|
RD_KAFKAP_KEY_LEN_NULL ? \
|
||
|
0 : ntohs((kstr)->len)))
|
||
|
|
||
|
/* Macro suitable for "%.*s" printing. */
|
||
|
#define RD_KAFKAP_STR_PR(kstr) \
|
||
|
(ntohs((kstr)->len) == RD_KAFKAP_KEY_LEN_NULL ? \
|
||
|
0 : (int)ntohs((kstr)->len)), (kstr)->str
|
||
|
|
||
|
static inline int rd_kafkap_str_cmp (const rd_kafkap_str_t *a,
|
||
|
const rd_kafkap_str_t *b) RD_UNUSED;
|
||
|
static inline int rd_kafkap_str_cmp (const rd_kafkap_str_t *a,
|
||
|
const rd_kafkap_str_t *b) {
|
||
|
if (a->len != b->len)
|
||
|
return -1;
|
||
|
return memcmp(a->str, b->str, ntohs(a->len));
|
||
|
}
|
||
|
|
||
|
static inline int rd_kafkap_str_cmp_str (const rd_kafkap_str_t *a,
|
||
|
const char *str) RD_UNUSED;
|
||
|
static inline int rd_kafkap_str_cmp_str (const rd_kafkap_str_t *a,
|
||
|
const char *str) {
|
||
|
int len = strlen(str);
|
||
|
if (ntohs(a->len) != len)
|
||
|
return -1;
|
||
|
return memcmp(a->str, str, ntohs(a->len));
|
||
|
}
|
||
|
|
||
|
|
||
|
static inline rd_kafkap_str_t *rd_kafkap_str_new (const char *str) RD_UNUSED;
|
||
|
static inline rd_kafkap_str_t *rd_kafkap_str_new (const char *str) {
|
||
|
rd_kafkap_str_t *kstr;
|
||
|
int len = 0;
|
||
|
|
||
|
if (str)
|
||
|
len = strlen(str);
|
||
|
else
|
||
|
len = 0;
|
||
|
|
||
|
/* We allocate one more byte so we can null-terminate the string.
|
||
|
* This null-termination is not included in the length so it
|
||
|
* is not sent over the wire. */
|
||
|
kstr = malloc(sizeof(*kstr) + len + 1);
|
||
|
|
||
|
if (str) {
|
||
|
kstr->len = ntohs(len);
|
||
|
memcpy(kstr->str, str, len+1);
|
||
|
} else
|
||
|
kstr->len = ntohs(RD_KAFKAP_KEY_LEN_NULL);
|
||
|
|
||
|
return kstr;
|
||
|
}
|
||
|
|
||
|
#define rd_kafkap_str_destroy(kstr) free(kstr)
|
||
|
|
||
|
#define rd_kafkap_strdupa(kstr) strndupa((kstr)->str,\
|
||
|
RD_KAFKAP_STR_SIZE((kstr)))
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* Kafka protocol bytes representation: { uint32, data.. }
|
||
|
*
|
||
|
*/
|
||
|
typedef struct rd_kafkap_bytes_s {
|
||
|
int32_t len; /* big endian */
|
||
|
char data[0]; /* allocated dynamically */
|
||
|
} RD_PACKED rd_kafkap_bytes_t;
|
||
|
|
||
|
#define RD_KAFKAP_KEY_LEN_NULL -1
|
||
|
/* Returns the actual size of a kafka protocol bytes representation. */
|
||
|
#define RD_KAFKAP_BYTES_SIZE(kbytes) (int32_t)(sizeof((kbytes)->len) + \
|
||
|
(ntohl((kbytes)->len) == \
|
||
|
RD_KAFKAP_KEY_LEN_NULL ? \
|
||
|
0 : ntohl((kbytes)->len)))
|
||
|
|
||
|
static inline int rd_kafkap_bytes_cmp (const rd_kafkap_bytes_t *a,
|
||
|
const rd_kafkap_bytes_t *b) RD_UNUSED;
|
||
|
static inline int rd_kafkap_bytes_cmp (const rd_kafkap_bytes_t *a,
|
||
|
const rd_kafkap_bytes_t *b) {
|
||
|
if (a->len != b->len)
|
||
|
return -1;
|
||
|
return memcmp(a->data, b->data, ntohl(a->len));
|
||
|
}
|
||
|
|
||
|
static inline int rd_kafkap_bytes_cmp_bytes (const rd_kafkap_bytes_t *a,
|
||
|
const void *data, size_t datalen)
|
||
|
RD_UNUSED;
|
||
|
static inline int rd_kafkap_bytes_cmp_bytes (const rd_kafkap_bytes_t *a,
|
||
|
const void *data, size_t datalen) {
|
||
|
if (a->len != datalen)
|
||
|
return -1;
|
||
|
return memcmp(a->data, data, ntohl(a->len));
|
||
|
}
|
||
|
|
||
|
|
||
|
static inline rd_kafkap_bytes_t *rd_kafkap_bytes_new (const void *data,
|
||
|
size_t datalen) RD_UNUSED;
|
||
|
static inline rd_kafkap_bytes_t *rd_kafkap_bytes_new (const void *data,
|
||
|
size_t datalen) {
|
||
|
rd_kafkap_bytes_t *kbytes;
|
||
|
|
||
|
kbytes = malloc(sizeof(*kbytes) + datalen);
|
||
|
|
||
|
if (data) {
|
||
|
kbytes->len = ntohl(datalen);
|
||
|
memcpy(kbytes->data, data, datalen);
|
||
|
} else
|
||
|
kbytes->len = ntohl(RD_KAFKAP_KEY_LEN_NULL);
|
||
|
|
||
|
return kbytes;
|
||
|
}
|
||
|
|
||
|
#define rd_kafkap_bytes_destroy(kbytes) free(kbytes)
|
||
|
|