Index: src/vortex_connection.c
===================================================================
--- src/vortex_connection.c (revision 3338)
+++ src/vortex_connection.c (working copy)
@@ -28,9 +28,9 @@
*
* Postal address:
* Advanced Software Production Line, S.L.
- * C/ Antonio Suarez Nº 10,
+ * C/ Antonio Suarez N∫ 10,
* Edificio Alius A, Despacho 102
- * Alcalá de Henares 28802 (Madrid)
+ * Alcal· de Henares 28802 (Madrid)
* Spain
*
* Email address:
@@ -108,6 +108,11 @@
char * port;
/**
+ * @brief Local port number used by an outgoing connection (optional)
+ */
+ uint16_t localPort;
+
+ /**
* @brief Allows to hold and report current connection status.
*/
bool is_connected;
@@ -1151,6 +1156,47 @@
}
/**
+ * @internal wrapper around "bind" system call, which also sets SO_REUSEADDR option.
+ *
+ * @param sock The socket to bind.
+ * @param addr The raw 32-bit address to bind to (network byte-order)
+ * @param port The port number (host byte-order)
+ *
+ * @return 0 on success, -1 on failure
+ */
+int vortex_bind (int sock,
+ in_addr_t addr,
+ uint16_t port,
+ bool reusePort )
+{
+ struct sockaddr_in saddr;
+ int result;
+#if defined(AXL_OS_WIN32)
+ BOOL unit = true;
+#else
+ int unit = 1;
+#endif
+ result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&unit, sizeof (unit));
+
+ if( result==0 && reusePort ) {
+ // If supported (BSD and OS X), also set REUSEPORT, to allow simultaneous listening and
+ // outgoing connection on the same port. (This is used in NAT hole-punching.)
+#ifdef SO_REUSEPORT
+ result = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*)&unit, sizeof (unit));
+#endif
+ }
+
+ if( result < 0 )
+ return result;
+
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = addr;
+ saddr.sin_port = htons(port);
+ return bind(sock,(struct sockaddr*)&saddr,sizeof(saddr));
+}
+
+/**
* @internal Function to perform a wait operation on the provided
* socket, assuming the wait operation will be performed on a
* nonblocking socket. The function configure the socket to be
@@ -1302,6 +1348,16 @@
goto __vortex_connection_new_finalize;
}
+ /* bind to a local port number, if the client requested it */
+ if (connection->localPort > 0) {
+ if( vortex_bind(connection->session,INADDR_ANY,connection->localPort,true) < 0 ) {
+ connection->message = axl_strdup_printf("unable to bind socket to local port: %s (%i)",
+ strerror(errno),errno);
+ vortex_log (LOG_DOMAIN, VORTEX_LEVEL_CRITICAL, "%s",connection->message);
+ goto __vortex_connection_new_finalize;
+ }
+ }
+
/* prepare socket configuration to operate using TCP/IP
* socket */
memset(&saddr, 0, sizeof(saddr));
@@ -1470,9 +1526,24 @@
/* seems that current Vortex Library have TLS
* profile built-in support and auto TLS is
* activated */
- connection = vortex_tls_start_negociation_sync (connection,
+ //jpa: Patch: Don't lose the VortexConnection if negotiation fails!
+ VortexStatus status;
+ char *message = NULL;
+ vortex_connection_ref(connection, "__vortex_connection_new");
+ VortexConnection *newConnection = vortex_tls_start_negociation_sync (connection,
ctx->connection_auto_tls_server_name,
- NULL, NULL);
+ &status,&message);
+ if (!newConnection) {
+ __vortex_connection_set_not_connected (connection, message);
+ if (connection->message)
+ axl_free (connection->message);
+ connection->message = axl_strdup (message);
+ goto __vortex_connection_new_invoke_caller;
+ }
+ vortex_connection_unref(connection, "__vortex_connection_new");
+ connection = newConnection;
+ //jpa: END
+
if (!vortex_connection_is_ok (connection, false)) {
goto __vortex_connection_new_invoke_caller;
}
@@ -1612,17 +1683,45 @@
VortexConnectionNew on_connected,
axlPointer user_data)
{
+ return vortex_connection_new2(host,(uint16_t)strtod(port,NULL),0,on_connected,user_data);
+}
+/**
+ * @brief Allows to create a new BEEP session (connection) to the given host:port,
+ * with the port specified as an integer, and optionally specifying a local port number.
+ *
+ * See vortex_connection_new for more information.
+ *
+ * @param host The remote peer to connect to.
+ * @param port The peer's port to connect to.
+ * @param localPort The local port number to use, or zero if you don't care (the usual case).
+ * @param on_connected Optional handler to process connection new status.
+ * @param user_data Optional handler to process connection new status
+ *
+ * @return A newly created \ref VortexConnection if called in a
+ * blocking manner, or NULL if you provide the on_connected handler.
+ */
+VortexConnection * vortex_connection_new2 (const char * host,
+ uint16_t port,
+ uint16_t localPort,
+ VortexConnectionNew on_connected,
+ axlPointer user_data)
+{
+
VortexConnectionNewData * data;
v_return_val_if_fail (host, NULL);
v_return_val_if_fail (port, NULL);
+
+ char portStr[10];
+ sprintf(portStr,"%hu",port);
data = axl_new (VortexConnectionNewData, 1);
data->connection = axl_new (VortexConnection, 1);
data->connection->id = __vortex_connection_get_next_id ();
data->connection->host = axl_strdup (host);
- data->connection->port = axl_strdup (port);
+ data->connection->port = axl_strdup (portStr);
+ data->connection->localPort = localPort;
data->connection->channels = vortex_hash_new_full (axl_hash_int, axl_hash_equal_int,
NULL,
(axlDestroyFunc) vortex_channel_unref);
Index: src/vortex_connection.h
===================================================================
--- src/vortex_connection.h (revision 3338)
+++ src/vortex_connection.h (working copy)
@@ -70,6 +70,12 @@
VortexConnectionNew on_connected,
axlPointer user_data);
+VortexConnection * vortex_connection_new2 (const char * host,
+ uint16_t port,
+ uint16_t localPort,
+ VortexConnectionNew on_connected,
+ axlPointer user_data);
+
bool vortex_connection_reconnect (VortexConnection * connection,
VortexConnectionNew on_connected,
axlPointer user_data);
@@ -312,6 +318,11 @@
bool __vortex_connection_parse_greetings (VortexConnection * connection,
VortexFrame * frame);
+int vortex_bind (int sock,
+ in_addr_t addr,
+ uint16_t port,
+ bool reusePort);
+
#endif
/* @} */
Index: src/vortex_listener.c
===================================================================
--- src/vortex_listener.c (revision 3338)
+++ src/vortex_listener.c (working copy)
@@ -370,14 +370,11 @@
VortexCtx * ctx = vortex_ctx_get ();
struct hostent * he;
struct in_addr * haddr;
- struct sockaddr_in saddr;
struct sockaddr_in sin;
VORTEX_SOCKET fd;
#if defined(AXL_OS_WIN32)
- BOOL unit = true;
int sin_size = sizeof (sin);
#else
- int unit = 1;
socklen_t sin_size = sizeof (sin);
#endif
char * host = data->host;
@@ -407,18 +404,7 @@
goto error;
}
-#if defined(AXL_OS_WIN32)
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&unit, sizeof(BOOL));
-#else
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &unit, sizeof (unit));
-#endif
-
- memset(&saddr, 0, sizeof(struct sockaddr_in));
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(int_port);
- memcpy(&saddr.sin_addr, haddr, sizeof(struct in_addr));
-
- if (bind(fd, (struct sockaddr *)&saddr, sizeof (struct sockaddr_in)) == VORTEX_SOCKET_ERROR) {
+ if (vortex_bind(fd,haddr->s_addr,int_port,false) == VORTEX_SOCKET_ERROR ) {
vortex_close_socket (fd);
message = "unable to bind address";
goto error;