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