File: pktbuf.h

package info (click to toggle)
pgbouncer 1.3.3-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 932 kB
  • ctags: 1,085
  • sloc: ansic: 8,710; sh: 490; makefile: 213; python: 99
file content (139 lines) | stat: -rw-r--r-- 4,155 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * PgBouncer - Lightweight connection pooler for PostgreSQL.
 * 
 * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
 * 
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Safe & easy creation of PostgreSQL packets.
 */

typedef struct PktBuf PktBuf;
struct PktBuf {
	uint8_t *buf;
	int buf_len;
	int write_pos;
	int pktlen_pos;

	int send_pos;
	struct event *ev;

	unsigned failed:1;
	unsigned sending:1;
	unsigned fixed_buf:1;
};

/*
 * pktbuf creation
 */
PktBuf *pktbuf_dynamic(int start_len)	_MUSTCHECK;
void pktbuf_static(PktBuf *buf, uint8_t *data, int len);

/*
 * sending
 */
bool pktbuf_send_immidiate(PktBuf *buf, PgSocket *sk)	_MUSTCHECK;
bool pktbuf_send_queued(PktBuf *buf, PgSocket *sk)  _MUSTCHECK;

/*
 * low-level ops
 */
void pktbuf_start_packet(PktBuf *buf, int type);
void pktbuf_put_char(PktBuf *buf, char val);
void pktbuf_put_uint16(PktBuf *buf, uint16_t val);
void pktbuf_put_uint32(PktBuf *buf, uint32_t val);
void pktbuf_put_uint64(PktBuf *buf, uint64_t val);
void pktbuf_put_string(PktBuf *buf, const char *str);
void pktbuf_put_bytes(PktBuf *buf, const void *data, int len);
void pktbuf_finish_packet(PktBuf *buf);
#define pktbuf_written(buf) ((buf)->write_pos)


/*
 * Packet writing
 */
void pktbuf_write_generic(PktBuf *buf, int type, const char *fmt, ...);
void pktbuf_write_RowDescription(PktBuf *buf, const char *tupdesc, ...);
void pktbuf_write_DataRow(PktBuf *buf, const char *tupdesc, ...);

/*
 * Shortcuts for actual packets.
 */
#define pktbuf_write_ParameterStatus(buf, key, val) \
	pktbuf_write_generic(buf, 'S', "ss", key, val)

#define pktbuf_write_AuthenticationOk(buf) \
	pktbuf_write_generic(buf, 'R', "i", 0)

#define pktbuf_write_ReadyForQuery(buf) \
	pktbuf_write_generic(buf, 'Z', "c", 'I')

#define pktbuf_write_CommandComplete(buf, desc) \
	pktbuf_write_generic(buf, 'C', "s", desc)

#define pktbuf_write_BackendKeyData(buf, key) \
	pktbuf_write_generic(buf, 'K', "b", key, 8)

#define pktbuf_write_CancelRequest(buf, key) \
	pktbuf_write_generic(buf, PKT_CANCEL, "b", key, 8)

#define pktbuf_write_StartupMessage(buf, user, parms, parms_len) \
	pktbuf_write_generic(buf, PKT_STARTUP, "bsss", parms, parms_len, "user", user, "")

#define pktbuf_write_PasswordMessage(buf, psw) \
	pktbuf_write_generic(buf, 'p', "s", psw)

#define pktbuf_write_Notice(buf, msg) \
	pktbuf_write_generic(buf, 'N', "sscss", "SNOTICE", "C00000", 'M', msg, "");

/*
 * Shortcut for creating DataRow in memory.
 */

#define BUILD_DataRow(reslen, dst, dstlen, args...) do { \
	PktBuf _buf; \
	pktbuf_static(&_buf, dst, dstlen); \
	pktbuf_write_DataRow(&_buf, ## args); \
	reslen = _buf.failed ? -1 : _buf.write_pos; \
} while (0)

/*
 * Shortcuts for immidiate send of one packet.
 */

#define SEND_wrap(buflen, pktfn, res, sk, args...) do { \
	uint8_t _data[buflen]; PktBuf _buf; \
	pktbuf_static(&_buf, _data, sizeof(_data)); \
	pktfn(&_buf, ## args); \
	res = pktbuf_send_immidiate(&_buf, sk); \
} while (0)

#define SEND_RowDescription(res, sk, args...) \
	SEND_wrap(512, pktbuf_write_RowDescription, res, sk, ## args)

#define SEND_generic(res, sk, args...) \
	SEND_wrap(512, pktbuf_write_generic, res, sk, ## args)

#define SEND_ReadyForQuery(res, sk) \
	SEND_wrap(8, pktbuf_write_ReadyForQuery, res, sk)

#define SEND_CancelRequest(res, sk, key) \
	SEND_wrap(16, pktbuf_write_CancelRequest, res, sk, key)

#define SEND_PasswordMessage(res, sk, psw) \
	SEND_wrap(512, pktbuf_write_PasswordMessage, res, sk, psw)