/*------------------------------------------------------------------------- * * ic_proxy_server.h * * * Copyright (c) 2020-Present Pivotal Software, Inc. * * *------------------------------------------------------------------------- */ #ifndef IC_PROXY_SERVER_H #define IC_PROXY_SERVER_H #include "postgres.h" #include #include "ic_proxy.h" #include "ic_proxy_iobuf.h" #include "ic_proxy_packet.h" #include "ic_proxy_router.h" typedef struct ICProxyPeer ICProxyPeer; typedef struct ICProxyClient ICProxyClient; typedef struct ICProxyDelay ICProxyDelay; /* * A peer is a connection to an other proxy. * * TODO: allocate the name buffer on demand. */ struct ICProxyPeer { uv_tcp_t tcp; /* the libuv handle */ int16 content; /* content, aka segid, only for logging */ uint16 dbid; /* dbid is peerid */ uint32 state; /* or'ed bits of below ones */ #define IC_PROXY_PEER_STATE_CONNECTING 0x00000001 #define IC_PROXY_PEER_STATE_CONNECTED 0x00000002 #define IC_PROXY_PEER_STATE_ACCEPTED 0x00000004 #define IC_PROXY_PEER_STATE_LEGACY 0x00000008 #define IC_PROXY_PEER_STATE_SENDING_HELLO 0x00000010 #define IC_PROXY_PEER_STATE_SENT_HELLO 0x00000020 #define IC_PROXY_PEER_STATE_RECEIVING_HELLO_ACK 0x00000040 #define IC_PROXY_PEER_STATE_RECEIVED_HELLO_ACK 0x00000080 #define IC_PROXY_PEER_STATE_RECEIVING_HELLO 0x00000100 #define IC_PROXY_PEER_STATE_RECEIVED_HELLO 0x00000200 #define IC_PROXY_PEER_STATE_SENDING_HELLO_ACK 0x00000400 #define IC_PROXY_PEER_STATE_SENT_HELLO_ACK 0x00000800 #define IC_PROXY_PEER_STATE_SHUTTING 0x00001000 #define IC_PROXY_PEER_STATE_SHUTTED 0x00002000 #define IC_PROXY_PEER_STATE_CLOSING 0x00004000 #define IC_PROXY_PEER_STATE_CLOSED 0x00008000 #define IC_PROXY_PEER_STATE_READY_FOR_MESSAGE \ (IC_PROXY_PEER_STATE_CONNECTED | \ IC_PROXY_PEER_STATE_ACCEPTED) #define IC_PROXY_PEER_STATE_READY_FOR_DATA \ (IC_PROXY_PEER_STATE_SENT_HELLO_ACK | \ IC_PROXY_PEER_STATE_RECEIVED_HELLO_ACK) List *reqs; /* outgoing queue for data that can't be sent * immediately */ ICProxyIBuf ibuf; /* ibuf detects the packet boundaries */ char name[128]; /* name of the client, only for logging */ }; /* * A delay is a c2p packet that cannot be sent immediately. * * The libuv callbacks are all called directly from the libuv mainloop, no * embedding, no nesting, this is important to ensure that all the callbacks * are __atomic__, they do not need to worry about that something is modified * concurrently. * * However most callbacks created by us are nested, for example for a pair of * loopback clients, they communicate via callbacks directly, if one of them * sends a control message to the other, it could cause reentrance of some of * the callback functions, which will cause unexpected behavior. To prevent * that, we delay the sending of such kind of packets. * * A control message usually needs a callback, it is recorded for the delayed * packet, so once the packet is sent out the callback can still be triggered. * * Note that a delay can be transferred from a legacy peer to a new one, so we * must record the peer id instead of the peer pointer. */ struct ICProxyDelay { int16 content; /* the content of the peer, only for logging */ uint16 dbid; /* the dbid and peerid of the peer */ ICProxyPkt *pkt; /* the packet, owned by us */ ic_proxy_sent_cb callback; /* the sent callback */ void *opaque; /* the sent callback data */ }; extern int ic_proxy_server_main(void); extern void ic_proxy_server_quit(uv_loop_t *loop, bool relaunch); extern ICProxyClient *ic_proxy_client_new(uv_loop_t *loop, bool placeholder); extern const char *ic_proxy_client_get_name(ICProxyClient *client); extern uv_stream_t *ic_proxy_client_get_stream(ICProxyClient *client); extern int ic_proxy_client_read_hello(ICProxyClient *client); extern void ic_proxy_client_on_p2c_data(ICProxyClient *client, ICProxyPkt *pkt, ic_proxy_sent_cb callback, void *opaque); extern ICProxyClient *ic_proxy_client_blessed_lookup(uv_loop_t *loop, const ICProxyKey *key); extern void ic_proxy_client_table_init(void); extern void ic_proxy_client_table_uninit(void); extern void ic_proxy_client_table_shutdown_by_dbid(uint16 dbid); extern void ic_proxy_peer_table_init(void); extern void ic_proxy_peer_table_uninit(void); extern ICProxyPeer *ic_proxy_peer_new(uv_loop_t *loop, int16 content, uint16 dbid); extern void ic_proxy_peer_free(ICProxyPeer *peer); extern void ic_proxy_peer_read_hello(ICProxyPeer *peer); extern void ic_proxy_peer_connect(ICProxyPeer *peer, struct sockaddr_in *dest); extern void ic_proxy_peer_route_data(ICProxyPeer *peer, ICProxyPkt *pkt, ic_proxy_sent_cb callback, void *opaque); extern ICProxyPeer *ic_proxy_peer_lookup(int16 content, uint16 dbid); extern ICProxyPeer *ic_proxy_peer_blessed_lookup(uv_loop_t *loop, int16 content, uint16 dbid); extern ICProxyDelay *ic_proxy_peer_build_delay(ICProxyPeer *peer, ICProxyPkt *pkt, ic_proxy_sent_cb callback, void *opaque); #endif /* IC_PROXY_SERVER_H */