1 /*
2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
3 *
4 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * event types for protocol handler
21 */
22 typedef enum {
23 SBUF_EV_READ, /* got new packet */
24 SBUF_EV_RECV_FAILED, /* error */
25 SBUF_EV_SEND_FAILED, /* error */
26 SBUF_EV_CONNECT_FAILED, /* error */
27 SBUF_EV_CONNECT_OK, /* got connection */
28 SBUF_EV_FLUSH, /* data is sent, buffer empty */
29 SBUF_EV_PKT_CALLBACK, /* next part of pkt data */
30 SBUF_EV_TLS_READY /* TLS was established */
31 } SBufEvent;
32
33 /*
34 * If less than this amount of data is pending, then
35 * prefer to merge it with next recv().
36 *
37 * It needs to be larger than data handler wants
38 * to see completely. Generally just header,
39 * but currently also ServerParam pkt.
40 */
41 #define SBUF_SMALL_PKT 64
42
43 struct tls;
44
45 /* fwd def */
46 typedef struct SBuf SBuf;
47 typedef struct SBufIO SBufIO;
48
49 /* callback should return true if it used one of sbuf_prepare_* on sbuf,
50 false if it used sbuf_pause(), sbuf_close() or simply wants to wait for
51 next event loop (eg. too few data available). */
52 typedef bool (*sbuf_cb_t)(SBuf *sbuf,
53 SBufEvent evtype,
54 struct MBuf *mbuf);
55
56 struct SBufIO {
57 ssize_t (*sbufio_recv)(SBuf *sbuf, void *buf, size_t len);
58 ssize_t (*sbufio_send)(SBuf *sbuf, const void *data, size_t len);
59 int (*sbufio_close)(SBuf *sbuf);
60 };
61
62 /*
63 * Stream Buffer.
64 *
65 * Stream is divided to packets. On each packet start
66 * protocol handler is called that decides what to do.
67 */
68 struct SBuf {
69 struct event ev; /* libevent handle */
70
71 uint8_t wait_type; /* track wait state */
72 uint8_t pkt_action; /* method for handling current pkt */
73 uint8_t tls_state; /* progress of tls */
74
75 int sock; /* fd for this socket */
76
77 unsigned pkt_remain; /* total packet length remaining */
78
79 sbuf_cb_t proto_cb; /* protocol callback */
80
81 SBuf *dst; /* target SBuf for current packet */
82
83 IOBuf *io; /* data buffer, lazily allocated */
84
85 const SBufIO *ops; /* normal vs. TLS */
86 struct tls *tls; /* TLS context */
87 const char *tls_host; /* target hostname */
88 };
89
90 #define sbuf_socket(sbuf) ((sbuf)->sock)
91
92 void sbuf_init(SBuf *sbuf, sbuf_cb_t proto_fn);
93 bool sbuf_accept(SBuf *sbuf, int read_sock, bool is_unix) _MUSTCHECK;
94 bool sbuf_connect(SBuf *sbuf, const struct sockaddr *sa, socklen_t sa_len, time_t timeout_sec) _MUSTCHECK;
95
96 /*
97 * client_accept_sslmode is the currently applied sslmode that is used to
98 * accept client connections. This is usually the same as
99 * cf_client_tls_sslmode, except when changing the TLS configuration failed for
100 * some reason (e.g. cert file not found). In this exceptional case,
101 * cf_client_tls_sslmode will be the new sslmode, which is not actually
102 * applied. And client_accept_sslmode is the still applied previous version. So
103 * usually you should use this variable over cf_client_tls_sslmode.
104 */
105 extern int client_accept_sslmode;
106 /*
107 * Same as client_accept_sslmode, but for server connections.
108 */
109 extern int server_connect_sslmode;
110
111 bool sbuf_tls_setup(void);
112 bool sbuf_tls_accept(SBuf *sbuf) _MUSTCHECK;
113 bool sbuf_tls_connect(SBuf *sbuf, const char *hostname) _MUSTCHECK;
114
115 bool sbuf_pause(SBuf *sbuf) _MUSTCHECK;
116 void sbuf_continue(SBuf *sbuf);
117 bool sbuf_close(SBuf *sbuf) _MUSTCHECK;
118
119 /* proto_fn can use those functions to order behaviour */
120 void sbuf_prepare_send(SBuf *sbuf, SBuf *dst, unsigned amount);
121 void sbuf_prepare_skip(SBuf *sbuf, unsigned amount);
122 void sbuf_prepare_fetch(SBuf *sbuf, unsigned amount);
123
124 bool sbuf_answer(SBuf *sbuf, const void *buf, size_t len) _MUSTCHECK;
125
126 bool sbuf_continue_with_callback(SBuf *sbuf, event_callback_fn cb) _MUSTCHECK;
127 bool sbuf_use_callback_once(SBuf *sbuf, short ev, event_callback_fn user_cb) _MUSTCHECK;
128
129 /*
130 * Returns true if SBuf is has no data buffered
131 * and is not in a middle of a packet.
132 */
sbuf_is_empty(SBuf * sbuf)133 static inline bool sbuf_is_empty(SBuf *sbuf)
134 {
135 return iobuf_empty(sbuf->io) && sbuf->pkt_remain == 0;
136 }
137
sbuf_is_closed(SBuf * sbuf)138 static inline bool sbuf_is_closed(SBuf *sbuf)
139 {
140 return sbuf->sock == 0;
141 }
142
143 /*
144 * Lowlevel operations.
145 */
146
sbuf_op_recv(SBuf * sbuf,void * buf,size_t len)147 static inline ssize_t sbuf_op_recv(SBuf *sbuf, void *buf, size_t len)
148 {
149 return sbuf->ops->sbufio_recv(sbuf, buf, len);
150 }
151
sbuf_op_send(SBuf * sbuf,const void * buf,size_t len)152 static inline ssize_t sbuf_op_send(SBuf *sbuf, const void *buf, size_t len)
153 {
154 return sbuf->ops->sbufio_send(sbuf, buf, len);
155 }
156
sbuf_op_close(SBuf * sbuf)157 static inline int sbuf_op_close(SBuf *sbuf)
158 {
159 return sbuf->ops->sbufio_close(sbuf);
160 }
161
162 void sbuf_cleanup(void);
163