include/channel/cc_tcp.h (101 lines of code) (raw):
/*
* ccommon - a cache common library.
* Copyright (C) 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <cc_array.h>
#include <cc_define.h>
#include <cc_event.h>
#include <cc_option.h>
#include <cc_queue.h>
#include <cc_util.h>
#include <channel/cc_channel.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
/**
* This implements the channel interface for TCP.
*/
#define TCP_BACKLOG 128
#define TCP_POOLSIZE 0 /* unlimited */
/* name type default description */
#define TCP_OPTION(ACTION) \
ACTION( tcp_backlog, OPTION_TYPE_UINT, TCP_BACKLOG, "tcp conn backlog limit" )\
ACTION( tcp_poolsize, OPTION_TYPE_UINT, TCP_POOLSIZE, "tcp conn pool size" )
typedef struct {
TCP_OPTION(OPTION_DECLARE)
} tcp_options_st;
/* name type description */
#define TCP_METRIC(ACTION) \
ACTION( tcp_conn_create, METRIC_COUNTER, "# tcp connections created" )\
ACTION( tcp_conn_create_ex, METRIC_COUNTER, "# tcp conn create exceptions" )\
ACTION( tcp_conn_destroy, METRIC_COUNTER, "# tcp connections destroyed" )\
ACTION( tcp_conn_curr, METRIC_GAUGE, "# tcp conn allocated" )\
ACTION( tcp_conn_borrow, METRIC_COUNTER, "# tcp connections borrowed" )\
ACTION( tcp_conn_borrow_ex, METRIC_COUNTER, "# tcp conn borrow exceptions" )\
ACTION( tcp_conn_return, METRIC_COUNTER, "# tcp connections returned" )\
ACTION( tcp_conn_active, METRIC_GAUGE, "# tcp conn being borrowed" )\
ACTION( tcp_accept, METRIC_COUNTER, "# tcp connection accepts" )\
ACTION( tcp_accept_ex, METRIC_COUNTER, "# tcp accept exceptions" )\
ACTION( tcp_reject, METRIC_COUNTER, "# tcp connection rejects" )\
ACTION( tcp_reject_ex, METRIC_COUNTER, "# tcp reject exceptions" )\
ACTION( tcp_connect, METRIC_COUNTER, "# tcp connects made" )\
ACTION( tcp_connect_ex, METRIC_COUNTER, "# tcp connect exceptions " )\
ACTION( tcp_close, METRIC_COUNTER, "# tcp connection closed" )\
ACTION( tcp_recv, METRIC_COUNTER, "# recv attempted" )\
ACTION( tcp_recv_ex, METRIC_COUNTER, "# recv exceptions" )\
ACTION( tcp_recv_byte, METRIC_COUNTER, "# bytes received" )\
ACTION( tcp_send, METRIC_COUNTER, "# send attempted" )\
ACTION( tcp_send_ex, METRIC_COUNTER, "# send exceptions" )\
ACTION( tcp_send_byte, METRIC_COUNTER, "# bytes sent" )
typedef struct {
TCP_METRIC(METRIC_DECLARE)
} tcp_metrics_st;
struct tcp_conn {
STAILQ_ENTRY(tcp_conn) next; /* for conn pool */
bool free; /* in use? */
ch_level_e level; /* meta or base */
int sd; /* socket descriptor */
size_t recv_nbyte; /* received (read) bytes */
size_t send_nbyte; /* sent (written) bytes */
unsigned state:4; /* channel state */
unsigned flags:12; /* annotation fields */
err_i err; /* errno */
};
STAILQ_HEAD(tcp_conn_sqh, tcp_conn); /* corresponding header type for the STAILQ */
void tcp_setup(tcp_options_st *options, tcp_metrics_st *metrics);
void tcp_teardown(void);
void tcp_conn_reset(struct tcp_conn *c);
/* resource management */
struct tcp_conn *tcp_conn_create(void); /* channel_get_fn, with allocation */
void tcp_conn_destroy(struct tcp_conn **c); /* channel_put_fn, with deallocation */
struct tcp_conn *tcp_conn_borrow(void); /* channel_get_fn, with resource pool */
void tcp_conn_return(struct tcp_conn **c); /* channel_put_fn, with resource pool */
static inline ch_id_i tcp_read_id(struct tcp_conn *c)
{
return c->sd;
}
static inline ch_id_i tcp_write_id(struct tcp_conn *c)
{
return c->sd;
}
/* basic channel maintenance */
bool tcp_connect(struct addrinfo *ai, struct tcp_conn *c); /* channel_open_fn, client */
bool tcp_listen(struct addrinfo *ai, struct tcp_conn *c); /* channel_open_fn, server */
void tcp_close(struct tcp_conn *c); /* channel_perm_fn */
ssize_t tcp_recv(struct tcp_conn *c, void *buf, size_t nbyte); /* channel_recv_fn */
ssize_t tcp_send(struct tcp_conn *c, void *buf, size_t nbyte); /* channel_send_fn */
ssize_t tcp_recvv(struct tcp_conn *c, struct array *bufv, size_t nbyte);
ssize_t tcp_sendv(struct tcp_conn *c, struct array *bufv, size_t nbyte);
bool tcp_accept(struct tcp_conn *sc, struct tcp_conn *c); /* channel_accept_fn */
void tcp_reject(struct tcp_conn *sc); /* channel_reject_fn */
void tcp_reject_all(struct tcp_conn *sc); /* channel_reject_fn */
/* functions getting/setting connection attribute */
int tcp_set_blocking(int sd);
int tcp_set_nonblocking(int sd);
int tcp_set_reuseaddr(int sd);
int tcp_set_tcpnodelay(int sd);
int tcp_set_keepalive(int sd);
int tcp_set_linger(int sd, int timeout);
int tcp_unset_linger(int sd);
int tcp_set_sndbuf(int sd, int size);
int tcp_set_rcvbuf(int sd, int size);
int tcp_get_sndbuf(int sd);
int tcp_get_rcvbuf(int sd);
int tcp_get_soerror(int sd);
void tcp_maximize_sndbuf(int sd);
#ifdef __cplusplus
}
#endif