Add API to register callback to set socket options
The registered callback function will be called before connect() is called on the socket, allowing tweaking of much more than just keepalive settings. This deprecates xmpp_conn_set_keepalive(). Includes helper/example callback function to set default keepalive parameters that some library users may find useful.
This commit is contained in:
@@ -15,10 +15,6 @@
|
||||
|
||||
#include <strophe.h>
|
||||
|
||||
/* hardcoded TCP keepalive timeout and interval */
|
||||
#define KA_TIMEOUT 60
|
||||
#define KA_INTERVAL 1
|
||||
|
||||
/* define a handler for connection events */
|
||||
static void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
@@ -63,7 +59,7 @@ int main(int argc, char **argv)
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
xmpp_log_t *log;
|
||||
char *jid = NULL, *password = NULL, *cert = NULL, *key = NULL, *host = NULL;
|
||||
char *jid = NULL, *password = NULL, *host = NULL;
|
||||
long flags = 0;
|
||||
int i;
|
||||
unsigned long port = 0;
|
||||
@@ -118,9 +114,6 @@ int main(int argc, char **argv)
|
||||
xmpp_conn_set_flags(conn, flags);
|
||||
|
||||
/* setup authentication information */
|
||||
if (cert && key) {
|
||||
xmpp_conn_set_client_cert(conn, cert, key);
|
||||
}
|
||||
if (jid)
|
||||
xmpp_conn_set_jid(conn, jid);
|
||||
if (password)
|
||||
|
||||
@@ -142,21 +142,66 @@ void conn_handler(xmpp_conn_t *conn,
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(int exit_code)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: bot [options] <jid> <pass>\n\n"
|
||||
"Options:\n"
|
||||
" --jid <jid> The JID to use to authenticate.\n"
|
||||
" --pass <pass> The password of the JID.\n"
|
||||
" --tcp-keepalive Configure TCP keepalive.\n"
|
||||
" --disable-tls Disable TLS.\n"
|
||||
" --mandatory-tls Deny plaintext connection.\n"
|
||||
" --trust-tls Trust TLS certificate.\n"
|
||||
" --legacy-ssl Use old style SSL.\n"
|
||||
" --legacy-auth Allow legacy authentication.\n"
|
||||
"Note: --disable-tls conflicts with --mandatory-tls or "
|
||||
"--legacy-ssl\n");
|
||||
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
xmpp_log_t *log;
|
||||
char *jid, *pass;
|
||||
char *jid = NULL, *password = NULL, *host = NULL;
|
||||
long flags = 0;
|
||||
int i, tcp_keepalive = 0;
|
||||
unsigned long port = 0;
|
||||
|
||||
/* take a jid and password on the command line */
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: bot <jid> <pass>\n\n");
|
||||
return 1;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--help") == 0)
|
||||
usage(0);
|
||||
else if (strcmp(argv[i], "--disable-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_DISABLE_TLS;
|
||||
else if (strcmp(argv[i], "--mandatory-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_MANDATORY_TLS;
|
||||
else if (strcmp(argv[i], "--trust-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_TRUST_TLS;
|
||||
else if (strcmp(argv[i], "--legacy-ssl") == 0)
|
||||
flags |= XMPP_CONN_FLAG_LEGACY_SSL;
|
||||
else if (strcmp(argv[i], "--legacy-auth") == 0)
|
||||
flags |= XMPP_CONN_FLAG_LEGACY_AUTH;
|
||||
else if ((strcmp(argv[i], "--jid") == 0) && (++i < argc))
|
||||
jid = argv[i];
|
||||
else if ((strcmp(argv[i], "--pass") == 0) && (++i < argc))
|
||||
password = argv[i];
|
||||
else if (strcmp(argv[i], "--tcp-keepalive") == 0)
|
||||
tcp_keepalive = 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ((!jid) || (argc - i) > 2) {
|
||||
usage(1);
|
||||
}
|
||||
|
||||
jid = argv[1];
|
||||
pass = argv[2];
|
||||
if (i < argc)
|
||||
host = argv[i];
|
||||
if (i + 1 < argc)
|
||||
port = strtoul(argv[i + 1], NULL, 0);
|
||||
|
||||
/* init library */
|
||||
xmpp_initialize();
|
||||
@@ -169,23 +214,26 @@ int main(int argc, char **argv)
|
||||
/* create a connection */
|
||||
conn = xmpp_conn_new(ctx);
|
||||
|
||||
/*
|
||||
* also you can disable TLS support or force legacy SSL
|
||||
* connection without STARTTLS
|
||||
*
|
||||
* see xmpp_conn_set_flags() or examples/basic.c
|
||||
*/
|
||||
/* configure connection properties (optional) */
|
||||
xmpp_conn_set_flags(conn, flags);
|
||||
|
||||
/* setup authentication information */
|
||||
xmpp_conn_set_jid(conn, jid);
|
||||
xmpp_conn_set_pass(conn, pass);
|
||||
if (jid)
|
||||
xmpp_conn_set_jid(conn, jid);
|
||||
if (password)
|
||||
xmpp_conn_set_pass(conn, password);
|
||||
|
||||
/* enable TCP keepalive, using canned callback function */
|
||||
if (tcp_keepalive)
|
||||
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive);
|
||||
|
||||
/* initiate connection */
|
||||
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
|
||||
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {
|
||||
|
||||
/* enter the event loop -
|
||||
our connect handler will trigger an exit */
|
||||
xmpp_run(ctx);
|
||||
/* enter the event loop -
|
||||
our connect handler will trigger an exit */
|
||||
xmpp_run(ctx);
|
||||
}
|
||||
|
||||
/* release our connection and context */
|
||||
xmpp_conn_release(conn);
|
||||
|
||||
@@ -13,11 +13,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <mstcpip.h> /* tcp_keepalive */
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#include <strophe.h>
|
||||
|
||||
/* hardcoded TCP keepalive timeout and interval */
|
||||
#define KA_TIMEOUT 60
|
||||
#define KA_INTERVAL 1
|
||||
#define KA_INTERVAL 30
|
||||
#define KA_COUNT 3
|
||||
#define USER_TIMEOUT 150
|
||||
|
||||
static void print_tlscert(const xmpp_tlscert_t *cert)
|
||||
{
|
||||
@@ -80,6 +93,86 @@ static int certfail_handler(const xmpp_tlscert_t *cert,
|
||||
return read_char[0] == 'y' || read_char[0] == 'Y';
|
||||
}
|
||||
|
||||
static int sockopt_cb(xmpp_conn_t *conn, void *socket)
|
||||
{
|
||||
int timeout = KA_TIMEOUT;
|
||||
int interval = KA_INTERVAL;
|
||||
int count = KA_COUNT;
|
||||
unsigned int user_timeout = USER_TIMEOUT;
|
||||
int ret;
|
||||
int optval = (timeout && interval) ? 1 : 0;
|
||||
|
||||
(void)conn;
|
||||
|
||||
#ifdef _WIN32
|
||||
(void)count;
|
||||
(void)user_timeout;
|
||||
|
||||
SOCKET sock = *((SOCKET *)socket);
|
||||
struct tcp_keepalive ka;
|
||||
DWORD dw = 0;
|
||||
|
||||
ka.onoff = optval;
|
||||
ka.keepalivetime = timeout * 1000;
|
||||
ka.keepaliveinterval = interval * 1000;
|
||||
ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &dw,
|
||||
NULL, NULL);
|
||||
#else
|
||||
int sock = *((int *)socket);
|
||||
|
||||
fprintf(stderr, "DEBUG: setting socket options\n");
|
||||
|
||||
ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (optval) {
|
||||
#ifdef TCP_KEEPIDLE
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &timeout,
|
||||
sizeof(timeout));
|
||||
#elif defined(TCP_KEEPALIVE)
|
||||
/* QNX receives `struct timeval' as argument, but it seems OSX does int
|
||||
*/
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, &timeout,
|
||||
sizeof(timeout));
|
||||
#endif /* TCP_KEEPIDLE */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#ifdef TCP_KEEPINTVL
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &interval,
|
||||
sizeof(interval));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif /* TCP_KEEPINTVL */
|
||||
}
|
||||
|
||||
if (count) {
|
||||
#ifdef TCP_KEEPCNT
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif /* TCP_KEEPCNT */
|
||||
}
|
||||
|
||||
if (user_timeout) {
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_USER_TIMEOUT, &user_timeout,
|
||||
sizeof(user_timeout));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#elif defined(TCP_RXT_CONNDROPTIME)
|
||||
int rxt = user_timeout / 1000;
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_RXT_CONNDROPTIME, &rxt,
|
||||
sizeof(rxt));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif /* TCP_USER_TIMEOUT */
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usage(int exit_code)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@@ -184,7 +277,7 @@ int main(int argc, char **argv)
|
||||
xmpp_conn_set_flags(conn, flags);
|
||||
/* configure TCP keepalive (optional) */
|
||||
if (tcp_keepalive)
|
||||
xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL);
|
||||
xmpp_conn_set_sockopt_callback(conn, sockopt_cb);
|
||||
|
||||
/* setup authentication information */
|
||||
if (cert && key) {
|
||||
|
||||
Reference in New Issue
Block a user