在scm acceptor中增加解析应用层协议的实现
This commit is contained in:
@@ -56,7 +56,7 @@ struct acceptor_scm
|
|||||||
void * logger;
|
void * logger;
|
||||||
|
|
||||||
/* CONFIG */
|
/* CONFIG */
|
||||||
char str_scm_socket_file[TFE_STRING_MAX];
|
char str_scm_socket[TFE_STRING_MAX];
|
||||||
|
|
||||||
/* PERSIST RUNTIME RESOURCE */
|
/* PERSIST RUNTIME RESOURCE */
|
||||||
int fd_scm_socket;
|
int fd_scm_socket;
|
||||||
@@ -65,11 +65,209 @@ struct acceptor_scm
|
|||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum tcp_restore_info_tlv_type
|
||||||
|
{
|
||||||
|
TCP_RESTORE_INFO_TLV_SEQ,
|
||||||
|
TCP_RESTORE_INFO_TLV_ACK,
|
||||||
|
TCP_RESTORE_INFO_TLV_MSS_CLIENT,
|
||||||
|
TCP_RESTORE_INFO_TLV_MSS_SERVER,
|
||||||
|
TCP_RESTORE_INFO_TLV_WSACLE_CLIENT,
|
||||||
|
TCP_RESTORE_INFO_TLV_WSACLE_SERVER,
|
||||||
|
TCP_RESTORE_INFO_TLV_SACK_CLIENT,
|
||||||
|
TCP_RESTORE_INFO_TLV_SACK_SERVER,
|
||||||
|
TCP_RESTORE_INFO_TLV_TS_CLIENT,
|
||||||
|
TCP_RESTORE_INFO_TLV_TS_SERVER,
|
||||||
|
TCP_RESTORE_INFO_TLV_PROTOCOL,
|
||||||
|
TCP_RESTORE_INFO_TLV_USER_DEFINED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcp_restore_info_endpoint
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
uint32_t seq;
|
||||||
|
uint32_t ack;
|
||||||
|
bool wscale_perm;
|
||||||
|
bool timestamp_perm;
|
||||||
|
bool sack_perm;
|
||||||
|
uint16_t mss;
|
||||||
|
uint8_t wscale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcp_restore_info
|
||||||
|
{
|
||||||
|
struct tcp_restore_info_endpoint client;
|
||||||
|
struct tcp_restore_info_endpoint server;
|
||||||
|
unsigned int protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcp_restore_info_tlv
|
||||||
|
{
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t length;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint8_t value_as_uint8[0];
|
||||||
|
uint16_t value_as_uint16[0];
|
||||||
|
uint32_t value_as_uint32[0];
|
||||||
|
unsigned char value_as_string[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct tcp_restore_info_header
|
||||||
|
{
|
||||||
|
uint8_t __magic__[2]; /* Must be 0x4d, 0x5a */
|
||||||
|
uint16_t nr_tlvs;
|
||||||
|
struct tcp_restore_info_tlv tlvs[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define TCP_RESTORE_TCPOPT_KIND 88
|
||||||
|
#define TCP_RESTORE_TCPOPT_LENGTH 4
|
||||||
|
|
||||||
|
/* Copy from tfe-kmod */
|
||||||
|
int tcp_restore_info_parse_from_cmsg(struct acceptor_scm * ctx,
|
||||||
|
const char * data, unsigned int datalen, struct tcp_restore_info * out)
|
||||||
|
{
|
||||||
|
struct tcp_restore_info_header * header = (struct tcp_restore_info_header *)data;
|
||||||
|
unsigned int tlv_iter;
|
||||||
|
unsigned int nr_tlvs;
|
||||||
|
|
||||||
|
if(unlikely(header->__magic__[0] != 0x4d || header->__magic__[1] != 0x5a))
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: wrong magic, drop it.\n");
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_tlvs = ntohs(header->nr_tlvs);
|
||||||
|
if (unlikely(nr_tlvs >= 256))
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: numbers of tlvs is larger than 256, drop it.\n");
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(datalen < sizeof(struct tcp_restore_info_header)))
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: length is shorter than tlv header, drop it.\n");
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
datalen -= sizeof(struct tcp_restore_info_header);
|
||||||
|
data += sizeof(struct tcp_restore_info_header);
|
||||||
|
|
||||||
|
for(tlv_iter = 0; tlv_iter < nr_tlvs; tlv_iter++)
|
||||||
|
{
|
||||||
|
struct tcp_restore_info_tlv * tlv = (struct tcp_restore_info_tlv *)data;
|
||||||
|
uint16_t tlv_type = ntohs(tlv->type);
|
||||||
|
uint16_t tlv_length = ntohs(tlv->length);
|
||||||
|
|
||||||
|
unsigned int __length = tlv_length;
|
||||||
|
if(unlikely(datalen < __length))
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: left space is smaller than tlv's length, "
|
||||||
|
"datalen is %u, tlv's length is %u, drop it.", datalen, __length);
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unlikely(tlv_length < sizeof(uint16_t) * 2))
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: invalid tlv length, "
|
||||||
|
"should larger than sizeof(type) + sizeof(length).");
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlv_length -= sizeof(uint16_t) * 2;
|
||||||
|
|
||||||
|
#define __CHECK_TLV_LENGTH(x) do { if(unlikely(x != tlv_length)) { \
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore format: invalid tlv length, should be %u, actually is %u, drop it.", \
|
||||||
|
(unsigned int)x, (unsigned int)tlv_length); goto invalid_format; }} while(0)
|
||||||
|
|
||||||
|
switch(tlv_type)
|
||||||
|
{
|
||||||
|
case TCP_RESTORE_INFO_TLV_SEQ:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint32_t));
|
||||||
|
out->client.seq = ntohl(tlv->value_as_uint32[0]);
|
||||||
|
out->server.ack = ntohl(tlv->value_as_uint32[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_ACK:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint32_t));
|
||||||
|
out->client.ack = ntohl(tlv->value_as_uint32[0]);
|
||||||
|
out->server.seq = ntohl(tlv->value_as_uint32[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_TS_CLIENT:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->client.timestamp_perm = !!(tlv->value_as_uint8[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_TS_SERVER:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->server.timestamp_perm = !!(tlv->value_as_uint8[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_WSACLE_CLIENT:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->client.wscale_perm = true;
|
||||||
|
out->client.wscale = tlv->value_as_uint8[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_WSACLE_SERVER:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->server.wscale_perm = true;
|
||||||
|
out->server.wscale = tlv->value_as_uint8[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_SACK_CLIENT:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->client.sack_perm = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_SACK_SERVER:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->server.sack_perm = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_MSS_CLIENT:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint16_t));
|
||||||
|
out->client.mss = ntohs(tlv->value_as_uint16[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_MSS_SERVER:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint16_t));
|
||||||
|
out->server.mss = ntohs(tlv->value_as_uint16[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_PROTOCOL:
|
||||||
|
__CHECK_TLV_LENGTH(sizeof(uint8_t));
|
||||||
|
out->protocol = tlv->value_as_uint8[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCP_RESTORE_INFO_TLV_USER_DEFINED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: unsupported type %x, drop it.\n", tlv_type);
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += __length;
|
||||||
|
datalen -= __length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
invalid_format:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void acceptor_scm_event(evutil_socket_t fd, short what, void * user)
|
void acceptor_scm_event(evutil_socket_t fd, short what, void * user)
|
||||||
{
|
{
|
||||||
struct acceptor_scm * __ctx = (struct acceptor_scm *) user;
|
struct acceptor_scm * __ctx = (struct acceptor_scm *) user;
|
||||||
struct cmsghdr * __cmsghdr;
|
struct cmsghdr * __cmsghdr;
|
||||||
struct tfe_proxy_accept_para __accept_para{};
|
struct tfe_proxy_accept_para __accept_para{};
|
||||||
|
struct tcp_restore_info restore_info{};
|
||||||
|
|
||||||
int * __fds = NULL;
|
int * __fds = NULL;
|
||||||
assert(__ctx != NULL && __ctx->thread == pthread_self());
|
assert(__ctx != NULL && __ctx->thread == pthread_self());
|
||||||
@@ -124,17 +322,15 @@ void acceptor_scm_event(evutil_socket_t fd, short what, void * user)
|
|||||||
goto __die;
|
goto __die;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (tcp_restore_info_parse_from_cmsg(__ctx, __buffer, (size_t)rd, &restore_info) < 0)
|
||||||
if (unlikely(__kni_parse_tlv_data(__ctx, &__accept_para, __buffer, (size_t) rd) < 0))
|
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, close KNI connection.");
|
TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, drop the connection.");
|
||||||
goto __close_kni_connection;
|
goto __drop_recieved_fds;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
__accept_para.downstream_fd = __fds[0];
|
__accept_para.downstream_fd = __fds[0];
|
||||||
__accept_para.upstream_fd = __fds[1];
|
__accept_para.upstream_fd = __fds[1];
|
||||||
__accept_para.session_type = STREAM_PROTO_SSL;
|
__accept_para.session_type = restore_info.protocol ? STREAM_PROTO_SSL : STREAM_PROTO_PLAIN;
|
||||||
|
|
||||||
TFE_PROXY_STAT_INCREASE(STAT_FD_OPEN_BY_KNI_ACCEPT, 2);
|
TFE_PROXY_STAT_INCREASE(STAT_FD_OPEN_BY_KNI_ACCEPT, 2);
|
||||||
if (tfe_proxy_fds_accept(__ctx->proxy, &__accept_para) < 0)
|
if (tfe_proxy_fds_accept(__ctx->proxy, &__accept_para) < 0)
|
||||||
@@ -188,6 +384,7 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char *
|
|||||||
{
|
{
|
||||||
struct acceptor_scm * __ctx = ALLOC(struct acceptor_scm, 1);
|
struct acceptor_scm * __ctx = ALLOC(struct acceptor_scm, 1);
|
||||||
struct sockaddr_un __sockaddr_un{};
|
struct sockaddr_un __sockaddr_un{};
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
__ctx->proxy = proxy;
|
__ctx->proxy = proxy;
|
||||||
@@ -195,11 +392,17 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char *
|
|||||||
__ctx->logger = logger;
|
__ctx->logger = logger;
|
||||||
|
|
||||||
/* Read the unix domain socket file, this file is used to recieve fds from KNI */
|
/* Read the unix domain socket file, this file is used to recieve fds from KNI */
|
||||||
MESA_load_profile_string_def(profile, "acceptor_scm", "scm_socket_file", __ctx->str_scm_socket_file,
|
MESA_load_profile_string_def(profile, "acceptor_scm", "scm_socket_file", __ctx->str_scm_socket,
|
||||||
sizeof(__ctx->str_scm_socket_file), TFE_CONFIG_SCM_SOCKET_FILE);
|
sizeof(__ctx->str_scm_socket), TFE_CONFIG_SCM_SOCKET_FILE);
|
||||||
|
|
||||||
__sockaddr_un.sun_family = AF_UNIX;
|
__sockaddr_un.sun_family = AF_UNIX;
|
||||||
strncpy(__sockaddr_un.sun_path, __ctx->str_scm_socket_file, sizeof(__sockaddr_un.sun_path));
|
strncpy(__sockaddr_un.sun_path, __ctx->str_scm_socket, sizeof(__sockaddr_un.sun_path));
|
||||||
|
|
||||||
|
if (remove(__ctx->str_scm_socket) < 0 && errno != ENOENT)
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(__ctx->logger, "Failed at remove(%s) : %s", __ctx->str_scm_socket, strerror(errno));
|
||||||
|
goto __errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create new event base, this event base will be dispatched at separated thread */
|
/* Create new event base, this event base will be dispatched at separated thread */
|
||||||
__ctx->ev_base = event_base_new();
|
__ctx->ev_base = event_base_new();
|
||||||
@@ -216,11 +419,11 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char *
|
|||||||
goto __errout;
|
goto __errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = connect(__ctx->fd_scm_socket, (struct sockaddr *)&__sockaddr_un, sizeof(__sockaddr_un));
|
ret = bind(__ctx->fd_scm_socket, (struct sockaddr *)&__sockaddr_un, sizeof(__sockaddr_un));
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at connecting to %s: %s", __sockaddr_un.sun_path, strerror(errno));
|
TFE_LOG_ERROR(__ctx->logger, "Failed at binding to %s: %s", __sockaddr_un.sun_path, strerror(errno));
|
||||||
goto __errout;
|
goto __errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
__ctx->ev_scm_socket = event_new(__ctx->ev_base, __ctx->fd_scm_socket,
|
__ctx->ev_scm_socket = event_new(__ctx->ev_base, __ctx->fd_scm_socket,
|
||||||
@@ -247,7 +450,7 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char *
|
|||||||
goto __errout;
|
goto __errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
TFE_LOG_INFO(__ctx->logger, "KNI scm socket file: %s", __ctx->str_scm_socket_file);
|
TFE_LOG_INFO(__ctx->logger, "scm socket file: %s", __ctx->str_scm_socket);
|
||||||
return __ctx;
|
return __ctx;
|
||||||
|
|
||||||
__errout:
|
__errout:
|
||||||
|
|||||||
Reference in New Issue
Block a user