}
/* handle packets */
-bool admin_handle_client(PgSocket *admin, MBuf *pkt, int pkt_type, int pkt_len)
+bool admin_handle_client(PgSocket *admin, PktHdr *pkt)
{
const char *q;
bool res;
/* dont tolerate partial packets */
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN) {
+ if (incomplete_pkt(pkt)) {
disconnect_client(admin, true, "incomplete pkt");
return false;
}
- switch (pkt_type) {
+ switch (pkt->type) {
case 'Q':
- q = mbuf_get_string(pkt);
+ q = mbuf_get_string(&pkt->data);
if (!q) {
disconnect_client(admin, true, "incomplete query");
return false;
log_debug("got admin query: %s", q);
res = admin_parse_query(admin, q);
if (res)
- sbuf_prepare_skip(&admin->sbuf, pkt_len);
+ sbuf_prepare_skip(&admin->sbuf, pkt->len);
return res;
case 'X':
disconnect_client(admin, false, "close req");
break;
default:
- admin_error(admin, "unsupported pkt type: %d", pkt_type);
+ admin_error(admin, "unsupported pkt type: %d", pkt_desc(pkt));
disconnect_client(admin, true, "bad pkt");
break;
}
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-bool admin_handle_client(PgSocket *client, MBuf *pkt, int pkt_type, int pkt_len);
+bool admin_handle_client(PgSocket *client, PktHdr *pkt);
bool admin_pre_login(PgSocket *client);
void admin_setup(void);
bool admin_error(PgSocket *console, const char *fmt, ...);
typedef struct PgStats PgStats;
typedef struct PgAddr PgAddr;
typedef enum SocketState SocketState;
+typedef struct PktHdr PktHdr;
#include "util.h"
#include "list.h"
/* new style V3 packet header len - type:1b, len:4b */
#define NEW_HEADER_LEN 5
+#define BACKENDKEY_LEN 8
+
struct PgAddr {
struct in_addr ip_addr;
unsigned short port;
usec_t query_start; /* query start moment */
char salt[4];
- uint8 cancel_key[8];
+ uint8 cancel_key[BACKENDKEY_LEN];
PgUser * auth_user;
PgAddr addr;
return true;
}
-static bool decide_startup_pool(PgSocket *client, MBuf *pkt)
+static bool decide_startup_pool(PgSocket *client, PktHdr *pkt)
{
const char *username = NULL, *dbname = NULL;
const char *key, *val;
while (1) {
- key = mbuf_get_string(pkt);
+ key = mbuf_get_string(&pkt->data);
if (!key || *key == 0)
break;
- val = mbuf_get_string(pkt);
+ val = mbuf_get_string(&pkt->data);
if (!val)
break;
}
/* decide on packets of client in login phase */
-static bool handle_client_startup(PgSocket *client, MBuf *pkt)
+static bool handle_client_startup(PgSocket *client, PktHdr *pkt)
{
- unsigned pkt_type;
- unsigned pkt_len;
const char *passwd;
SBuf *sbuf = &client->sbuf;
/* don't tolerate partial packets */
- if (!get_header(pkt, &pkt_type, &pkt_len)) {
- disconnect_client(client, true, "client sent bad pkt header");
+ if (incomplete_pkt(pkt)) {
+ disconnect_client(client, true, "client sent partial pkt in startup phase");
return false;
}
if (client->wait_for_welcome) {
if (finish_client_login(client)) {
/* the packet was already parsed */
- sbuf_prepare_skip(sbuf, pkt_len);
+ sbuf_prepare_skip(sbuf, pkt->len);
return true;
} else
return false;
}
- slog_noise(client, "pkt='%c' len=%d",
- pkt_type < 256 ? pkt_type : '?', pkt_len);
-
- switch (pkt_type) {
+ switch (pkt->type) {
case PKT_SSLREQ:
slog_noise(client, "C: req SSL");
slog_noise(client, "P: nak");
}
break;
case PKT_STARTUP:
- if (mbuf_avail(pkt) < pkt_len - 8) {
- disconnect_client(client, true, "client sent partial pkt in startup");
- return false;
- }
if (client->pool) {
disconnect_client(client, true, "client re-sent startup pkt");
return false;
}
break;
case 'p': /* PasswordMessage */
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN) {
- disconnect_client(client, true, "client sent partial pkt in startup");
- return false;
- }
-
/* haven't requested it */
if (cf_auth_type <= AUTH_TRUST) {
disconnect_client(client, true, "unrequested passwd pkt");
return false;
}
- passwd = mbuf_get_string(pkt);
+ passwd = mbuf_get_string(&pkt->data);
if (passwd && check_client_passwd(client, passwd)) {
if (!finish_client_login(client))
return false;
}
break;
case PKT_CANCEL:
- if (mbuf_avail(pkt) == 8) {
- const uint8 *key = mbuf_get_bytes(pkt, 8);
- memcpy(client->cancel_key, key, 8);
+ if (mbuf_avail(&pkt->data) == BACKENDKEY_LEN) {
+ const uint8 *key = mbuf_get_bytes(&pkt->data, BACKENDKEY_LEN);
+ memcpy(client->cancel_key, key, BACKENDKEY_LEN);
accept_cancel_request(client);
} else
disconnect_client(client, false, "bad cancel request");
disconnect_client(client, false, "bad packet");
return false;
}
- sbuf_prepare_skip(sbuf, pkt_len);
+ sbuf_prepare_skip(sbuf, pkt->len);
client->request_time = get_cached_time();
return true;
}
/* decide on packets of logged-in client */
-static bool handle_client_work(PgSocket *client, MBuf *pkt)
+static bool handle_client_work(PgSocket *client, PktHdr *pkt)
{
- unsigned pkt_type;
- unsigned pkt_len;
SBuf *sbuf = &client->sbuf;
- if (!get_header(pkt, &pkt_type, &pkt_len)) {
- disconnect_client(client, true, "bad packet header");
- return false;
- }
- slog_noise(client, "pkt='%c' len=%d", pkt_type, pkt_len);
-
- switch (pkt_type) {
+ switch (pkt->type) {
/* request immidiate response from server */
case 'H': /* Flush */
}
if (client->pool->admin)
- return admin_handle_client(client, pkt, pkt_type, pkt_len);
+ return admin_handle_client(client, pkt);
/* aquire server */
if (!find_server(client))
return false;
- client->pool->stats.client_bytes += pkt_len;
+ client->pool->stats.client_bytes += pkt->len;
/* tag the server as dirty */
client->link->ready = 0;
/* forward the packet */
- sbuf_prepare_send(sbuf, &client->link->sbuf, pkt_len);
+ sbuf_prepare_send(sbuf, &client->link->sbuf, pkt->len);
break;
/* client wants to go away */
default:
- slog_error(client, "unknown pkt from client: %d/0x%x", pkt_type, pkt_type);
+ slog_error(client, "unknown pkt from client: %d/0x%x", pkt->type, pkt->type);
disconnect_client(client, true, "unknown pkt");
return false;
case 'X': /* Terminate */
}
/* callback from SBuf */
-bool client_proto(SBuf *sbuf, SBufEvent evtype, MBuf *pkt, void *arg)
+bool client_proto(SBuf *sbuf, SBufEvent evtype, MBuf *data, void *arg)
{
bool res = false;
PgSocket *client = arg;
+ PktHdr pkt;
+
Assert(!is_server_socket(client));
Assert(client->sbuf.sock);
disconnect_server(client->link, false, "Server connection closed");
break;
case SBUF_EV_READ:
- if (mbuf_avail(pkt) < NEW_HEADER_LEN) {
+ if (mbuf_avail(data) < NEW_HEADER_LEN && client->state != CL_LOGIN) {
slog_noise(client, "C: got partial header, trying to wait a bit");
return false;
}
+ if (!get_header(data, &pkt)) {
+ disconnect_client(client, true, "bad packet header");
+ return false;
+ }
+ slog_noise(client, "pkt='%c' len=%d", pkt_desc(&pkt), pkt.len);
+
client->request_time = get_cached_time();
switch (client->state) {
case CL_LOGIN:
- res = handle_client_startup(client, pkt);
+ res = handle_client_startup(client, &pkt);
break;
case CL_ACTIVE:
if (client->wait_for_welcome)
- res = handle_client_startup(client, pkt);
+ res = handle_client_startup(client, &pkt);
else
- res = handle_client_work(client, pkt);
+ res = handle_client_work(client, &pkt);
break;
case CL_WAITING:
fatal("why waiting client in client_proto()");
*/
/*
- * Safe and easy access to fixed memory buffer
+ * Safe and easy access to fixed memory buffer.
+ */
+
+/*
+ * FIXME: the code should be converted so that
+ * the fatal()-s can be replaced by Asserts().
*/
typedef struct MBuf MBuf;
return res;
}
-static inline unsigned mbuf_avail(MBuf *buf)
+static inline unsigned mbuf_avail(const MBuf *buf)
{
return buf->end - buf->pos;
}
-static inline unsigned mbuf_size(MBuf *buf)
+static inline unsigned mbuf_size(const MBuf *buf)
{
return buf->end - buf->data;
}
return res;
}
+static inline void mbuf_copy(const MBuf *src, MBuf *dst)
+{
+ *dst = *src;
+}
+
+static inline void mbuf_slice(MBuf *src, unsigned len, MBuf *dst)
+{
+ if (len > mbuf_avail(src))
+ fatal("buffer overflow");
+ mbuf_init(dst, src->pos, len);
+ src->pos += len;
+}
+
*/
/* parses pkt header from buffer, returns false if failed */
-bool get_header(MBuf *pkt, unsigned *pkt_type_p, unsigned *pkt_len_p)
+bool get_header(MBuf *data, PktHdr *pkt)
{
unsigned type;
unsigned len;
unsigned code;
+ unsigned got;
+ unsigned avail;
+ MBuf hdr;
- if (mbuf_avail(pkt) < NEW_HEADER_LEN) {
+ mbuf_copy(data, &hdr);
+
+ if (mbuf_avail(&hdr) < NEW_HEADER_LEN) {
log_noise("get_header: less then 5 bytes available");
return false;
}
- type = mbuf_get_char(pkt);
+ type = mbuf_get_char(&hdr);
if (type != 0) {
/* wire length does not include type byte */
- len = mbuf_get_uint32(pkt) + 1;
+ len = mbuf_get_uint32(&hdr) + 1;
+ got = NEW_HEADER_LEN;
} else {
- if (mbuf_get_char(pkt) != 0) {
+ if (mbuf_get_char(&hdr) != 0) {
log_noise("get_header: unknown special pkt");
return false;
}
/* dont tolerate partial pkt */
- if (mbuf_avail(pkt) < OLD_HEADER_LEN - 2) {
+ if (mbuf_avail(&hdr) < OLD_HEADER_LEN - 2) {
log_noise("get_header: less than 8 bytes for special pkt");
return false;
}
- len = mbuf_get_uint16(pkt);
- code = mbuf_get_uint32(pkt);
+ len = mbuf_get_uint16(&hdr);
+ code = mbuf_get_uint32(&hdr);
if (code == PKT_CANCEL)
type = PKT_CANCEL;
else if (code == PKT_SSLREQ)
log_noise("get_header: unknown special pkt: len=%u code=%u", len, code);
return false;
}
+ got = OLD_HEADER_LEN;
}
/* don't believe nonsense */
- if (len < NEW_HEADER_LEN || len >= 0x80000000)
+ if (len < got || len >= 0x80000000)
return false;
- *pkt_type_p = type;
- *pkt_len_p = len;
+ /* report pkt info */
+ pkt->type = type;
+ pkt->len = len;
+
+ /* fill apkt with only data for this pkt */
+ if (len > mbuf_avail(data))
+ avail = mbuf_avail(data);
+ else
+ avail = len;
+ mbuf_slice(data, avail, &pkt->data);
+
+ /* tag header as read */
+ mbuf_get_bytes(&pkt->data, got);
+
return true;
}
/*
* Parse server error message and log it.
*/
-void log_server_error(const char *note, MBuf *pkt)
+void log_server_error(const char *note, PktHdr *pkt)
{
const char *level = NULL, *msg = NULL, *val;
int type;
- while (mbuf_avail(pkt)) {
- type = mbuf_get_char(pkt);
+ while (mbuf_avail(&pkt->data)) {
+ type = mbuf_get_char(&pkt->data);
if (type == 0)
break;
- val = mbuf_get_string(pkt);
+ val = mbuf_get_string(&pkt->data);
if (!val)
break;
if (type == 'S')
*/
/* add another server parameter packet to cache */
-bool add_welcome_parameter(PgSocket *server,
- unsigned pkt_type, unsigned pkt_len, MBuf *pkt)
+bool add_welcome_parameter(PgSocket *server, PktHdr *pkt)
{
PgPool *pool = server->pool;
PktBuf msg;
return true;
/* incomplete startup msg from server? */
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN)
+ if (incomplete_pkt(pkt))
return false;
pktbuf_static(&msg, pool->welcome_msg + pool->welcome_msg_len,
if (pool->welcome_msg_len == 0)
pktbuf_write_AuthenticationOk(&msg);
- key = mbuf_get_string(pkt);
- val = mbuf_get_string(pkt);
+ key = mbuf_get_string(&pkt->data);
+ val = mbuf_get_string(&pkt->data);
if (!key || !val) {
- slog_error(server, "broken ParameterStatus packet");
+ disconnect_server(server, true, "broken ParameterStatus packet");
return false;
}
}
/* answer server authentication request */
-bool answer_authreq(PgSocket *server,
- unsigned pkt_type, unsigned pkt_len,
- MBuf *pkt)
+bool answer_authreq(PgSocket *server, PktHdr *pkt)
{
unsigned cmd;
const uint8 *salt;
bool res = false;
- unsigned pkt_remain;
/* authreq body must contain 32bit cmd */
- if (pkt_len < NEW_HEADER_LEN + 4)
- return false;
- /* is packet fully received? */
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN)
+ if (mbuf_avail(&pkt->data) < 4)
return false;
- cmd = mbuf_get_uint32(pkt);
- pkt_remain = pkt_len - NEW_HEADER_LEN - 4;
+ cmd = mbuf_get_uint32(&pkt->data);
switch (cmd) {
case 0:
slog_debug(server, "S: auth ok");
res = login_clear_psw(server);
break;
case 4:
- if (pkt_remain < 2)
- return false;
slog_debug(server, "S: req crypt psw");
- salt = mbuf_get_bytes(pkt, 2);
+ if (mbuf_avail(&pkt->data) < 2)
+ return false;
+ salt = mbuf_get_bytes(&pkt->data, 2);
res = login_crypt_psw(server, salt);
break;
case 5:
- if (pkt_remain < 4)
- return false;
slog_debug(server, "S: req md5-crypted psw");
- salt = mbuf_get_bytes(pkt, 4);
+ if (mbuf_avail(&pkt->data) < 4)
+ return false;
+ salt = mbuf_get_bytes(&pkt->data, 4);
res = login_md5_psw(server, salt);
break;
case 2: /* kerberos */
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-bool get_header(MBuf *pkt, unsigned *pkt_type_p, unsigned *pkt_len_p);
+/*
+ * parsed packet header, plus whatever data is
+ * available in SBuf for this packet.
+ *
+ * if (pkt->len == mbuf_avail(&pkt->data))
+ * packet is fully in buffer
+ *
+ * get_header() points pkt->data.pos after header.
+ * to packet body.
+ */
+struct PktHdr {
+ unsigned type;
+ unsigned len;
+ MBuf data;
+};
+
+bool get_header(MBuf *data, PktHdr *pkt);
bool send_pooler_error(PgSocket *client, bool send_ready, const char *msg);
-void log_server_error(const char *note, MBuf *pkt);
+void log_server_error(const char *note, PktHdr *pkt);
-bool add_welcome_parameter(PgSocket *server, unsigned pkt_type, unsigned pkt_len, MBuf *pkt);
+bool add_welcome_parameter(PgSocket *server, PktHdr *pkt);
void finish_welcome_msg(PgSocket *server);
bool welcome_client(PgSocket *client);
-bool answer_authreq(PgSocket *server, unsigned pkt_type, unsigned pkt_len, MBuf *pkt);
+bool answer_authreq(PgSocket *server, PktHdr *pkt);
bool send_startup_packet(PgSocket *server);
int scan_text_result(MBuf *pkt, const char *tupdesc, ...);
+/* is packet completely in our buffer */
+static inline bool incomplete_pkt(const PktHdr *pkt)
+{
+ return mbuf_avail(&pkt->data) != pkt->len;
+}
+
+/* one char desc */
+static inline char pkt_desc(const PktHdr *pkt)
+{
+ return pkt->type > 256 ? '!' : pkt->type;
+}
+
#include "bouncer.h"
-static bool load_parameter(PgSocket *server, MBuf *pkt, unsigned pkt_len)
+static bool load_parameter(PgSocket *server, PktHdr *pkt)
{
const char *key, *val;
PgSocket *client = server->link;
/*
* incomplete startup msg from server?
- * (hdr is already parsed here)
*/
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN)
+ if (incomplete_pkt(pkt))
return false;
- key = mbuf_get_string(pkt);
- val = mbuf_get_string(pkt);
+ key = mbuf_get_string(&pkt->data);
+ val = mbuf_get_string(&pkt->data);
if (!key || !val) {
disconnect_server(server, true, "broken ParameterStatus packet");
return false;
}
/* process packets on server auth phase */
-static bool handle_server_startup(PgSocket *server, MBuf *pkt)
+static bool handle_server_startup(PgSocket *server, PktHdr *pkt)
{
- unsigned pkt_type;
- unsigned pkt_len;
SBuf *sbuf = &server->sbuf;
bool res = false;
- if (!get_header(pkt, &pkt_type, &pkt_len)) {
- disconnect_server(server, true, "bad pkt in login phase");
- return false;
- }
-
- if (mbuf_avail(pkt) < pkt_len - NEW_HEADER_LEN) {
+ if (incomplete_pkt(pkt)) {
disconnect_server(server, true, "partial pkt in login phase");
return false;
}
- slog_noise(server, "S: pkt '%c', len=%d", pkt_type, pkt_len);
- switch (pkt_type) {
+ switch (pkt->type) {
default:
- slog_error(server, "unknown pkt from server: '%c'", pkt_type);
+ slog_error(server, "unknown pkt from server: '%c'", pkt_desc(pkt));
disconnect_server(server, true, "unknown pkt from server");
break;
/* packets that need closer look */
case 'R': /* AuthenticationXXX */
slog_debug(server, "calling login_answer");
- res = answer_authreq(server, pkt_type, pkt_len, pkt);
+ res = answer_authreq(server, pkt);
if (!res)
disconnect_server(server, false, "failed to answer authreq");
break;
case 'S': /* ParameterStatus */
- res = add_welcome_parameter(server, pkt_type, pkt_len, pkt);
+ res = add_welcome_parameter(server, pkt);
break;
case 'Z': /* ReadyForQuery */
/* ignorable packets */
case 'K': /* BackendKeyData */
- if (mbuf_avail(pkt) >= 8)
- memcpy(server->cancel_key, mbuf_get_bytes(pkt, 8), 8);
+ if (mbuf_avail(&pkt->data) >= BACKENDKEY_LEN)
+ memcpy(server->cancel_key,
+ mbuf_get_bytes(&pkt->data, BACKENDKEY_LEN),
+ BACKENDKEY_LEN);
res = true;
break;
case 'N': /* NoticeResponse */
- slog_noise(server, "skipping pkt: %c", pkt_type);
+ slog_noise(server, "skipping pkt: %c", pkt_desc(pkt));
res = true;
break;
}
if (res)
- sbuf_prepare_skip(sbuf, pkt_len);
+ sbuf_prepare_skip(sbuf, pkt->len);
return res;
}
/* process packets on logged in connection */
-static bool handle_server_work(PgSocket *server, MBuf *pkt)
+static bool handle_server_work(PgSocket *server, PktHdr *pkt)
{
- unsigned pkt_type;
- unsigned pkt_len;
bool ready = 0;
char state;
SBuf *sbuf = &server->sbuf;
Assert(!server->pool->admin);
- if (!get_header(pkt, &pkt_type, &pkt_len)) {
- disconnect_server(server, true, "bad pkt header");
- return false;
- }
- slog_noise(server, "pkt='%c' len=%d", pkt_type, pkt_len);
-
- switch (pkt_type) {
+ switch (pkt->type) {
default:
- slog_error(server, "unknown pkt: '%c'", pkt_type);
+ slog_error(server, "unknown pkt: '%c'", pkt_desc(pkt));
disconnect_server(server, true, "unknown pkt");
return false;
case 'Z': /* ReadyForQuery */
/* if partial pkt, wait */
- if (mbuf_avail(pkt) == 0)
+ if (mbuf_avail(&pkt->data) == 0)
return false;
- state = mbuf_get_char(pkt);
+ state = mbuf_get_char(&pkt->data);
/* set ready only if no tx */
if (state == 'I')
break;
case 'S': /* ParameterStatus */
- if (!load_parameter(server, pkt, pkt_len))
+ if (!load_parameter(server, pkt))
return false;
break;
break;
}
server->ready = ready;
- server->pool->stats.server_bytes += pkt_len;
+ server->pool->stats.server_bytes += pkt->len;
if (server->setting_vars) {
Assert(client);
- sbuf_prepare_skip(sbuf, pkt_len);
+ sbuf_prepare_skip(sbuf, pkt->len);
if (ready) {
server->setting_vars = 0;
sbuf_continue(&client->sbuf);
}
} else if (client) {
- sbuf_prepare_send(sbuf, &client->sbuf, pkt_len);
+ sbuf_prepare_send(sbuf, &client->sbuf, pkt->len);
if (ready) {
usec_t total;
Assert(client->query_start != 0);
if (server->state != SV_TESTED)
slog_warning(server,
"got packet '%c' from server when not linked",
- pkt_type);
- sbuf_prepare_skip(sbuf, pkt_len);
+ pkt_desc(pkt));
+ sbuf_prepare_skip(sbuf, pkt->len);
}
return true;
}
/* callback from SBuf */
-bool server_proto(SBuf *sbuf, SBufEvent evtype, MBuf *pkt, void *arg)
+bool server_proto(SBuf *sbuf, SBufEvent evtype, MBuf *data, void *arg)
{
bool res = false;
PgSocket *server = arg;
+ PktHdr pkt;
Assert(is_server_socket(server));
Assert(server->state != SV_FREE);
disconnect_client(server->link, false, "unexpected eof");
break;
case SBUF_EV_READ:
- if (mbuf_avail(pkt) < NEW_HEADER_LEN) {
+ if (mbuf_avail(data) < NEW_HEADER_LEN) {
slog_noise(server, "S: got partial header, trying to wait a bit");
return false;
}
+ /* parse pkt header */
+ if (!get_header(data, &pkt)) {
+ disconnect_server(server, true, "bad pkt header");
+ return false;
+ }
+ slog_noise(server, "S: pkt '%c', len=%d", pkt_desc(&pkt), pkt.len);
+
server->request_time = get_cached_time();
switch (server->state) {
case SV_LOGIN:
- res = handle_server_startup(server, pkt);
+ res = handle_server_startup(server, &pkt);
break;
case SV_TESTED:
case SV_USED:
case SV_ACTIVE:
case SV_IDLE:
- res = handle_server_work(server, pkt);
+ res = handle_server_work(server, &pkt);
break;
default:
fatal("server_proto: server in bad state: %d", server->state);
struct msghdr *msg, MBuf *data)
{
struct cmsghdr *cmsg;
- unsigned pkt_type, pkt_len;
- uint8 *pktptr;
- MBuf pkt;
+ PktHdr pkt;
cmsg = msg->msg_controllen ? CMSG_FIRSTHDR(msg) : NULL;
while (mbuf_avail(data) > 0) {
- if (!get_header(data, &pkt_type, &pkt_len))
+ if (!get_header(data, &pkt))
fatal("cannot parse packet");
- /* crash on overflow is ok here */
- pktptr = (uint8*)mbuf_get_bytes(data, pkt_len - NEW_HEADER_LEN);
- mbuf_init(&pkt, pktptr, pkt_len - NEW_HEADER_LEN);
+ /*
+ * There should not be partial reads from UNIX socket.
+ */
+ if (incomplete_pkt(&pkt))
+ fatal("unexpected partial packet");
- switch (pkt_type) {
+ switch (pkt.type) {
case 'T': /* RowDescription */
log_debug("takeover_parse_data: 'T'");
break;
case 'D': /* DataRow */
log_debug("takeover_parse_data: 'D'");
if (cmsg) {
- takeover_load_fd(&pkt, cmsg);
+ takeover_load_fd(&pkt.data, cmsg);
cmsg = CMSG_NXTHDR(msg, cmsg);
} else
fatal("got row without fd info");
break;
case 'C': /* CommandComplete */
log_debug("takeover_parse_data: 'C'");
- next_command(bouncer, &pkt);
+ next_command(bouncer, &pkt.data);
break;
case 'E': /* ErrorMessage */
log_server_error("old bouncer sent", &pkt);
fatal("something failed");
default:
- fatal("takeover_parse_data: unexpected pkt: '%c'", pkt_type);
+ fatal("takeover_parse_data: unexpected pkt: '%c'", pkt_desc(&pkt));
}
}
}