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:
@@ -3,6 +3,8 @@
|
||||
- Add code coverage support
|
||||
- New API:
|
||||
- xmpp_stanza_get_child_by_path()
|
||||
- xmpp_conn_set_sockopt_callback()
|
||||
- xmpp_sockopt_cb_keepalive()
|
||||
|
||||
0.11.0
|
||||
- SASL EXTERNAL support (XEP-0178)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -174,6 +174,7 @@ struct _xmpp_conn_t {
|
||||
sock_t sock;
|
||||
int ka_timeout; /* TCP keepalive timeout */
|
||||
int ka_interval; /* TCP keepalive interval */
|
||||
int ka_count; /* TCP keepalive count */
|
||||
|
||||
tls_t *tls;
|
||||
int tls_support;
|
||||
@@ -233,6 +234,7 @@ struct _xmpp_conn_t {
|
||||
xmpp_handlist_t *timed_handlers;
|
||||
hash_t *id_handlers;
|
||||
xmpp_handlist_t *handlers;
|
||||
xmpp_sockopt_callback sockopt_cb;
|
||||
};
|
||||
|
||||
void conn_disconnect(xmpp_conn_t *conn);
|
||||
|
||||
77
src/conn.c
77
src/conn.c
@@ -46,11 +46,37 @@
|
||||
#ifndef CONNECT_TIMEOUT
|
||||
/** @def CONNECT_TIMEOUT
|
||||
* The time to wait (in milliseconds) for a connection attempt to succeed
|
||||
* or error. The default is 5 seconds.
|
||||
* or error. The default is 5 seconds.
|
||||
*/
|
||||
#define CONNECT_TIMEOUT 5000 /* 5 seconds */
|
||||
#endif
|
||||
|
||||
#ifndef KEEPALIVE_TIMEOUT
|
||||
/** @def KEEPALIVE_TIMEOUT
|
||||
* The time (in seconds) the connection needs to remain idle before TCP starts
|
||||
* sending keepalive probes, if the socket option SO_KEEPALIVE has been set on
|
||||
* this socket.
|
||||
* c.f. `TCP_KEEPIDLE` in `man 7 tcp` for linux, FreeBSD and some others or
|
||||
* `TCP_KEEPALIVE` on MacOS.
|
||||
*/
|
||||
#define KEEPALIVE_TIMEOUT 60
|
||||
#endif
|
||||
#ifndef KEEPALIVE_INTERVAL
|
||||
/** @def KEEPALIVE_INTERVAL
|
||||
* The time (in seconds) between individual keepalive probes.
|
||||
* c.f. `TCP_KEEPINTVL` in `man 7 tcp`
|
||||
*/
|
||||
#define KEEPALIVE_INTERVAL 30
|
||||
#endif
|
||||
#ifndef KEEPALIVE_COUNT
|
||||
/** @def KEEPALIVE_COUNT
|
||||
* The maximum number of keepalive probes TCP should send before dropping the
|
||||
* connection.
|
||||
* c.f. `TCP_KEEPCNT` in `man 7 tcp`
|
||||
*/
|
||||
#define KEEPALIVE_COUNT 3
|
||||
#endif
|
||||
|
||||
static int _disconnect_cleanup(xmpp_conn_t *conn, void *userdata);
|
||||
static char *_conn_build_stream_tag(xmpp_conn_t *conn,
|
||||
char **attributes,
|
||||
@@ -112,8 +138,9 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
|
||||
conn->type = XMPP_UNKNOWN;
|
||||
conn->state = XMPP_STATE_DISCONNECTED;
|
||||
conn->sock = -1;
|
||||
conn->ka_timeout = 0;
|
||||
conn->ka_interval = 0;
|
||||
conn->ka_timeout = KEEPALIVE_TIMEOUT;
|
||||
conn->ka_interval = KEEPALIVE_INTERVAL;
|
||||
conn->ka_count = KEEPALIVE_COUNT;
|
||||
conn->tls = NULL;
|
||||
conn->timeout_stamp = 0;
|
||||
conn->error = 0;
|
||||
@@ -171,6 +198,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
|
||||
/* we own (and will free) the hash values */
|
||||
conn->id_handlers = hash_new(conn->ctx, 32, NULL);
|
||||
conn->handlers = NULL;
|
||||
conn->sockopt_cb = NULL;
|
||||
|
||||
/* give the caller a reference to connection */
|
||||
conn->ref = 1;
|
||||
@@ -216,33 +244,30 @@ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn)
|
||||
return conn;
|
||||
}
|
||||
|
||||
/** Set TCP keepalive parameters
|
||||
* Turn on TCP keepalive and set timeout and interval. Zero timeout
|
||||
* disables TCP keepalives. The parameters are applied immediately for
|
||||
* a non disconnected object. Also, they are applied when the connection
|
||||
* object connects successfully.
|
||||
/** Register sockopt callback
|
||||
* Set function to be called when a new socket is created to allow setting
|
||||
* socket options before connection is started.
|
||||
*
|
||||
* @param conn a Strophe connection object
|
||||
* @param timeout TCP keepalive timeout in seconds
|
||||
* @param interval TCP keepalive interval in seconds
|
||||
* If the connection is already connected, this callback will be called
|
||||
* immediately.
|
||||
*
|
||||
* To set options that can only be applied to disconnected sockets, the
|
||||
* callback must be registered before connecting.
|
||||
*
|
||||
* @param conn The Strophe connection object this callback is being registered
|
||||
* for
|
||||
* @param callback a xmpp_sockopt_callback callback function that will receive
|
||||
* notifications of connection status
|
||||
*
|
||||
* @ingroup Connections
|
||||
*/
|
||||
void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval)
|
||||
|
||||
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
||||
xmpp_sockopt_callback callback)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
conn->ka_timeout = timeout;
|
||||
conn->ka_interval = interval;
|
||||
|
||||
conn->sockopt_cb = callback;
|
||||
if (conn->state != XMPP_STATE_DISCONNECTED)
|
||||
ret = sock_set_keepalive(conn->sock, timeout, interval);
|
||||
|
||||
if (ret < 0) {
|
||||
strophe_error(conn->ctx, "xmpp",
|
||||
"Setting TCP keepalive (%d,%d) error: %d", timeout,
|
||||
interval, sock_error());
|
||||
}
|
||||
callback(conn, &conn->sock);
|
||||
}
|
||||
|
||||
/** Release a Strophe connection object.
|
||||
@@ -1487,13 +1512,11 @@ static int _conn_connect(xmpp_conn_t *conn,
|
||||
if (!conn->domain)
|
||||
return XMPP_EMEM;
|
||||
|
||||
conn->sock = sock_connect(host, port);
|
||||
conn->sock = sock_connect(conn, host, port);
|
||||
strophe_debug(conn->ctx, "xmpp", "sock_connect() to %s:%u returned %d",
|
||||
host, port, conn->sock);
|
||||
if (conn->sock == -1)
|
||||
return XMPP_EINT;
|
||||
if (conn->ka_timeout || conn->ka_interval)
|
||||
sock_set_keepalive(conn->sock, conn->ka_timeout, conn->ka_interval);
|
||||
|
||||
/* setup handler */
|
||||
conn->conn_handler = callback;
|
||||
|
||||
@@ -231,3 +231,26 @@ int xmpp_vsnprintf(char *str, size_t count, const char *fmt, va_list arg)
|
||||
{
|
||||
return strophe_vsnprintf(str, count, fmt, arg);
|
||||
}
|
||||
|
||||
/** Set TCP keepalive parameters
|
||||
* Turn on TCP keepalive and set timeout and interval. Zero timeout
|
||||
* disables TCP keepalives. The parameters are applied immediately for
|
||||
* a non disconnected object. Also, they are applied when the connection
|
||||
* object connects successfully.
|
||||
*
|
||||
* @param conn a Strophe connection object
|
||||
* @param timeout TCP keepalive timeout in seconds
|
||||
* @param interval TCP keepalive interval in seconds
|
||||
*
|
||||
* @note this function is deprecated
|
||||
* @see xmpp_conn_set_sockopt_callback()
|
||||
*
|
||||
* @ingroup Deprecated
|
||||
*/
|
||||
void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval)
|
||||
{
|
||||
conn->ka_timeout = timeout;
|
||||
conn->ka_interval = interval;
|
||||
conn->ka_count = 0;
|
||||
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive);
|
||||
}
|
||||
|
||||
68
src/sock.c
68
src/sock.c
@@ -33,8 +33,7 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "sock.h"
|
||||
#include "snprintf.h"
|
||||
#include "common.h"
|
||||
|
||||
void sock_initialize(void)
|
||||
{
|
||||
@@ -69,7 +68,7 @@ static int _in_progress(int error)
|
||||
#endif
|
||||
}
|
||||
|
||||
sock_t sock_connect(const char *host, unsigned short port)
|
||||
sock_t sock_connect(xmpp_conn_t *conn, const char *host, unsigned short port)
|
||||
{
|
||||
sock_t sock;
|
||||
char service[6];
|
||||
@@ -95,6 +94,14 @@ sock_t sock_connect(const char *host, unsigned short port)
|
||||
if (sock < 0)
|
||||
continue;
|
||||
|
||||
if (conn->sockopt_cb != NULL)
|
||||
err = (conn->sockopt_cb)(conn, &sock);
|
||||
|
||||
if (err != 0) {
|
||||
sock_close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
err = sock_set_nonblocking(sock);
|
||||
if (err == 0) {
|
||||
err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen);
|
||||
@@ -109,12 +116,17 @@ sock_t sock_connect(const char *host, unsigned short port)
|
||||
return sock;
|
||||
}
|
||||
|
||||
int sock_set_keepalive(sock_t sock, int timeout, int interval)
|
||||
int sock_set_keepalive(sock_t sock,
|
||||
int timeout,
|
||||
int interval,
|
||||
int count,
|
||||
unsigned int user_timeout)
|
||||
{
|
||||
int ret;
|
||||
int optval = (timeout && interval) ? 1 : 0;
|
||||
|
||||
/* This function doesn't change maximum number of keepalive probes */
|
||||
UNUSED(count);
|
||||
UNUSED(user_timeout);
|
||||
|
||||
#ifdef _WIN32
|
||||
struct tcp_keepalive ka;
|
||||
@@ -149,11 +161,57 @@ int sock_set_keepalive(sock_t sock, int timeout, int interval)
|
||||
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;
|
||||
}
|
||||
|
||||
/** Example sockopt callback function
|
||||
* An example function that can be used to set reasonable default keepalive
|
||||
* options on sockets when registered for a connection with
|
||||
* xmpp_conn_set_sockopt_callback()
|
||||
*
|
||||
* @param conn a Strophe connection object
|
||||
* @param socket pointer to a socket descriptor
|
||||
*
|
||||
* @see xmpp_sockopt_callback for details on the `socket` parameter
|
||||
* @ingroup Connections
|
||||
*/
|
||||
int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *socket)
|
||||
{
|
||||
sock_t sock = *((sock_t *)socket);
|
||||
|
||||
return sock_set_keepalive(
|
||||
sock, conn->ka_timeout, conn->ka_interval, conn->ka_count,
|
||||
conn->ka_count
|
||||
? (conn->ka_timeout + conn->ka_interval * conn->ka_count) * 1000
|
||||
: 0);
|
||||
}
|
||||
|
||||
int sock_close(sock_t sock)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
11
src/sock.h
11
src/sock.h
@@ -22,6 +22,9 @@
|
||||
typedef int sock_t;
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <mstcpip.h> /* tcp_keepalive */
|
||||
typedef SOCKET sock_t;
|
||||
#endif
|
||||
|
||||
@@ -30,7 +33,7 @@ void sock_shutdown(void);
|
||||
|
||||
int sock_error(void);
|
||||
|
||||
sock_t sock_connect(const char *host, unsigned short port);
|
||||
sock_t sock_connect(xmpp_conn_t *conn, const char *host, unsigned short port);
|
||||
int sock_close(sock_t sock);
|
||||
|
||||
int sock_set_blocking(sock_t sock);
|
||||
@@ -40,6 +43,10 @@ int sock_write(sock_t sock, const void *buff, size_t len);
|
||||
int sock_is_recoverable(int error);
|
||||
/* checks for an error after connect, return 0 if connect successful */
|
||||
int sock_connect_error(sock_t sock);
|
||||
int sock_set_keepalive(sock_t sock, int timeout, int interval);
|
||||
int sock_set_keepalive(sock_t sock,
|
||||
int timeout,
|
||||
int interval,
|
||||
int count,
|
||||
unsigned int user_timeout);
|
||||
|
||||
#endif /* __LIBSTROPHE_SOCK_H__ */
|
||||
|
||||
47
strophe.h
47
strophe.h
@@ -269,6 +269,41 @@ typedef void (*xmpp_conn_handler)(xmpp_conn_t *conn,
|
||||
typedef int (*xmpp_certfail_handler)(const xmpp_tlscert_t *cert,
|
||||
const char *const errormsg);
|
||||
|
||||
/** The function which will be called when Strophe creates a new socket.
|
||||
*
|
||||
* The `sock` argument is a pointer that is dependent on the architecture
|
||||
* Strophe is compiled for.
|
||||
*
|
||||
* For POSIX compatible systems usage shall be:
|
||||
* ```
|
||||
* int soc = *((int*)sock);
|
||||
* ```
|
||||
*
|
||||
* On Windows usage shall be:
|
||||
* ```
|
||||
* SOCKET soc = *((SOCKET*)sock);
|
||||
* ```
|
||||
*
|
||||
* This function will be called for each socket that is created.
|
||||
*
|
||||
* `examples/bot.c` uses a libstrophe supplied callback function that sets
|
||||
* basic keepalive parameters (`xmpp_sockopt_cb_keepalive()`).
|
||||
*
|
||||
* `examples/complex.c` implements a custom function that could be useful
|
||||
* for an application.
|
||||
*
|
||||
* @param conn The Strophe connection object this callback originates from.
|
||||
* @param sock A pointer to the underlying file descriptor.
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*
|
||||
* @ingroup Connections
|
||||
*/
|
||||
typedef int (*xmpp_sockopt_callback)(xmpp_conn_t *conn, void *sock);
|
||||
|
||||
/* an example callback that sets basic keepalive parameters */
|
||||
int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *sock);
|
||||
|
||||
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
|
||||
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx);
|
||||
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn);
|
||||
@@ -294,7 +329,8 @@ void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass);
|
||||
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn);
|
||||
void xmpp_conn_disable_tls(xmpp_conn_t *conn);
|
||||
int xmpp_conn_is_secured(xmpp_conn_t *conn);
|
||||
void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval);
|
||||
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
||||
xmpp_sockopt_callback callback);
|
||||
int xmpp_conn_is_connecting(xmpp_conn_t *conn);
|
||||
int xmpp_conn_is_connected(xmpp_conn_t *conn);
|
||||
int xmpp_conn_is_disconnected(xmpp_conn_t *conn);
|
||||
@@ -592,9 +628,13 @@ void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
|
||||
* deprecation */
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
|
||||
#if defined(__GNUC__)
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
|
||||
#define XMPP_DEPRECATED \
|
||||
__attribute__((deprecated("Function is internal from next release on")))
|
||||
#elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 300)
|
||||
#define XMPP_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
#define XMPP_DEPRECATED \
|
||||
__declspec(deprecated("Function is internal from next release on"))
|
||||
@@ -630,6 +670,9 @@ xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
XMPP_DEPRECATED void xmpp_debug_verbose(
|
||||
int level, const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
|
||||
XMPP_DEPRECATED void
|
||||
xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user