From bdd90aeb65d82ecae8fe58b441d25a1e1b129bf3 Mon Sep 17 00:00:00 2001
From: Thomas Munro
Date: Sat, 29 Jan 2022 02:15:10 +1300
Subject: [PATCH 1/3] Add low level socket events for libpq.
Provide a way to get a callback when a socket is created or closed.
XXX TODO handle callback failure
XXX TODO investigate overheads/other implications of having a callback
installed
---
src/interfaces/libpq/fe-connect.c | 24 ++++++++++++++++++++++++
src/interfaces/libpq/libpq-events.c | 11 +++++++++++
src/interfaces/libpq/libpq-events.h | 10 +++++++++-
3 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index a6a1db3356..ddc3f38cf1 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -452,7 +452,19 @@ pqDropConnection(PGconn *conn, bool flushInput)
/* Close the socket itself */
if (conn->sock != PGINVALID_SOCKET)
+ {
+ /* Report that the socket is closing. */
+ for (int i = 0; i < conn->nEvents; i++)
+ {
+ PGEventSocket evt;
+
+ evt.conn = conn;
+ evt.socket = conn->sock;
+ (void) conn->events[i].proc(PGEVT_SOCKETCLOSE, &evt,
+ conn->events[i].passThrough);
+ }
closesocket(conn->sock);
+ }
conn->sock = PGINVALID_SOCKET;
/* Optionally discard any unread data */
@@ -2576,6 +2588,18 @@ keep_going: /* We will come back to here until there is
goto error_return;
}
+ /* Report that a new socket has been created. */
+ for (int i = 0; i < conn->nEvents; i++)
+ {
+ PGEventSocket evt;
+
+ evt.conn = conn;
+ evt.socket = conn->sock;
+ (void) conn->events[i].proc(PGEVT_SOCKET, &evt,
+ conn->events[i].passThrough);
+ /* XXX check call result and fail */
+ }
+
/*
* Once we've identified a target address, all errors
* except the preceding socket()-failure case should be
diff --git a/src/interfaces/libpq/libpq-events.c b/src/interfaces/libpq/libpq-events.c
index 7754c37748..2c549ec457 100644
--- a/src/interfaces/libpq/libpq-events.c
+++ b/src/interfaces/libpq/libpq-events.c
@@ -87,6 +87,17 @@ PQregisterEventProc(PGconn *conn, PGEventProc proc,
return false;
}
+ /* If we already have a socket, report a socket event immediately. */
+ if (conn->sock != PGINVALID_SOCKET)
+ {
+ PGEventSocket evt;
+
+ evt.conn = conn;
+ evt.socket = conn->sock;
+ (void) proc(PGEVT_SOCKET, &evt, passThrough);
+ /* XXX check return and fail (callback out of memory) */
+ }
+
return true;
}
diff --git a/src/interfaces/libpq/libpq-events.h b/src/interfaces/libpq/libpq-events.h
index d93b7c4d4e..da64dc866b 100644
--- a/src/interfaces/libpq/libpq-events.h
+++ b/src/interfaces/libpq/libpq-events.h
@@ -31,7 +31,9 @@ typedef enum
PGEVT_CONNDESTROY,
PGEVT_RESULTCREATE,
PGEVT_RESULTCOPY,
- PGEVT_RESULTDESTROY
+ PGEVT_RESULTDESTROY,
+ PGEVT_SOCKET,
+ PGEVT_SOCKETCLOSE
} PGEventId;
typedef struct
@@ -66,6 +68,12 @@ typedef struct
PGresult *result;
} PGEventResultDestroy;
+typedef struct
+{
+ PGconn *conn;
+ pgsocket socket;
+} PGEventSocket;
+
typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough);
/* Registers an event proc with the given PGconn. */
--
2.33.1