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)
|