Esempio n. 1
0
axl_bool __myqtt_web_socket_session_setup (MyQttCtx * ctx, MyQttConn * conn, MyQttConnOpts * options, axlPointer user_data)
{
	noPollConn  * nopoll_conn = user_data;

	if (nopoll_conn_socket (nopoll_conn) < 0) {
		myqtt_log (MYQTT_LEVEL_CRITICAL, 
			   "Failed to create MQTT over WebSocket connection to %s:%s because socket is invalid or connection is not connected (socket: %d)",
			   nopoll_conn_host (nopoll_conn), nopoll_conn_port (nopoll_conn), nopoll_conn_socket (nopoll_conn));
		return axl_false;
	} /* end if */

	myqtt_log (MYQTT_LEVEL_DEBUG, "Creating new MQTT over WebSocket connection to %s:%s (socket: %d)",
		   nopoll_conn_host (nopoll_conn), nopoll_conn_port (nopoll_conn), nopoll_conn_socket (nopoll_conn));

	/* set socket on the connection */
	conn->session = nopoll_conn_socket (nopoll_conn);

	/* associate the connection to its websocket transport */
	__myqtt_web_socket_common_association (conn, nopoll_conn);

	/* configure this connection to have no preread */
	conn->preread_handler   = NULL;
	conn->preread_user_data = NULL;

	return axl_true;
}
Esempio n. 2
0
int create_listener(const char * port)
{
    memset(serverResponseBuffer, 0xab, 33000);
    instanceID = strdup("server");

    noPollCtx * ctx = nopoll_ctx_new ();
    if (!ctx) {
        LogPrintf("Could not create context");
        return 1;
    }
    if (debug_nopoll) {
       nopoll_log_set_handler(ctx, noPollLogger, NULL);
    }

    noPollConn * listener = nopoll_listener_new(ctx, "0.0.0.0", port);
    if (!nopoll_conn_is_ok (listener)) {
        LogPrintf("Could not listen on port %s", port);
        return 1;
    }
    LogPrintf("noPoll listener started at: %s:%s",
            nopoll_conn_host(listener), nopoll_conn_port(listener));

    nopoll_ctx_set_on_msg(ctx, listener_on_message, NULL);

    nopoll_loop_wait(ctx, 0);

    nopoll_ctx_unref(ctx);
    return 0;
}
noPollPtr ssl_context_creator (noPollCtx * ctx, noPollConn * conn, noPollConnOpts * opts, nopoll_bool is_client, noPollPtr user_data)
{
	SSL_CTX             * ssl_ctx;
	noPollConn          * listener;

	/* very basic context creation using default settings provided
	 * by OpenSSL */
	if (is_client) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
		return SSL_CTX_new (TLSv1_client_method ());
#else
	        return SSL_CTX_new (TLS_client_method ());
#endif
	} /* end if */

	/* get the ssl context */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
	ssl_ctx = SSL_CTX_new (TLSv1_server_method ());
#else
	ssl_ctx = SSL_CTX_new (TLS_server_method ());
#endif

	/* get a reference to the listener */
	listener = nopoll_conn_get_listener (conn);

	if (nopoll_cmp ("1239", nopoll_conn_port (listener))) {
		printf ("ACCEPTED ssl connection on port: %s (for conn %p)\n", nopoll_conn_port (listener), conn);

		/* ok, especiall case where we require a certain
		 * certificate from renote side */
		if (SSL_CTX_load_verify_locations (ssl_ctx, "client-side-cert-auth-cacert.crt", NULL) != 1) {
			printf ("ERROR: unable to add ca certificate...\n");
		}


		/* make server to ask for a certificate to the client
		 * .... and verify it */
		SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
	} /* end if */
	
	printf ("RETURNING: ssl context reference %p\n", ssl_ctx);
	return ssl_ctx;
}
Esempio n. 4
0
/** 
 * @brief Allows to create a new MQTT connection to a MQTT
 * broker/server running MQTT over WebSocket.
 *
 * @param ctx The context where the operation will take place.
 *
 * @param client_identifier The client identifier that uniquely
 * identifies this MQTT client from others.  It can be NULL to let
 * MQTT 3.1.1 servers to assign a default client identifier BUT
 * clean_session must be set to axl_true. This is done automatically
 * by the library (setting clean_session to axl_true when NULL is
 * provided).
 *
 * @param clean_session Flag to clean client session or to reuse the
 * existing one. If set to axl_false, you must provide a valid
 * client_identifier (otherwise the function will fail).
 *
 * @param keep_alive Keep alive configuration in seconds after which
 * the server/broker will close the connection if it doesn't detect
 * any activity. Setting 0 will disable keep alive mechanism.
 *
 * @param conn A reference to an established noPollConn connection
 * that is connecting to the MQTT over WebSocket server we want to
 * connect to. 
 *
 * @param opts Optional connection options. See \ref myqtt_conn_opts_new
 *
 * @param on_connected Async notification handler that will be called
 * once the connection fails or it is completed. In the case this
 * handler is configured the caller will not be blocked. In the case
 * this parameter is NULL, the caller will be blocked until the
 * connection completes or fails.
 *
 * @param user_data User defined pointer that will be passed to the on_connected handler (in case it is defined).
 *
 * @return A reference to the newli created connection or NULL if
 * on_connected handler is provided. In both cases, the reference
 * returned (or received at the on_connected handler) must be checked
 * with \ref myqtt_conn_is_ok. 
 *
 * <b>About pending messages / queued messages </b>
 *
 * After successful connection with clean_session set to axl_false and
 * defined client identifier, the library will resend any queued or in
 * flight QoS1/QoS2 messages (as well as QoS0 if they were
 * stored). This is done in background without intefering the caller.
 *
 * If you need to get the number of queued messages that are going to
 * be sent use \ref myqtt_storage_queued_messages_offline. In the case
 * you need the number remaining during the process use \ref
 * myqtt_storage_queued_messages.
 *
 * See \ref myqtt_conn_new for more information.
 *
 * <b>About reconnecting</b>
 *
 * If you enable automatic reconnect support after connection close
 * (\ref myqtt_conn_opts_set_reconnect), remember to also configure
 * the recover handler by using \ref myqtt_conn_opts_set_init_session_setup_ptr. That function should
 * implement a complete reconnect and return a noPollConn reference
 * used by the internal session setup. If you don't configure this,
 * the function will disable reconnect support even if you enable it.
 *
 */
MyQttConn        * myqtt_web_socket_conn_new            (MyQttCtx        * ctx,
							 const char      * client_identifier,
							 axl_bool          clean_session,
							 int               keep_alive,
							 noPollConn      * conn,
							 MyQttConnOpts   * opts,
							 MyQttConnNew      on_connected, 
							 axlPointer        user_data)
{

	/* check if the conn reference is not defined. In that case,
	   try to craete it with the init session setup ptr */
	if (conn == NULL && opts && opts->init_session_setup_ptr)
		conn = opts->init_session_setup_ptr (ctx, NULL, opts->init_user_data, opts->init_user_data2, opts->init_user_data3);

	/* report what we are doing */
	myqtt_log (MYQTT_LEVEL_DEBUG, "Creating new MQTT over WebSocket connection to %s:%s (is ready:%d, socket: %d)",
		   nopoll_conn_host (conn), nopoll_conn_port (conn), nopoll_conn_is_ready (conn), nopoll_conn_socket (conn));

	/* check and disable reconnect if it is not configured the
	   recover handler */
	if (opts && opts->reconnect) {
		if (opts->init_session_setup_ptr == NULL) {
			myqtt_log (MYQTT_LEVEL_CRITICAL, "Disable reconnect flag because user didn't provide a recover handler (myqtt_conn_opts_set_recover_session_setup_ptr)");
			opts->reconnect = axl_false; /* disable it */
		} /* end if */
	} /* end opts */

	/* associate context */
	__myqtt_web_socket_associate_ctx (ctx, nopoll_conn_ctx (conn));

	/* call to create the connection */
	return myqtt_conn_new_full_common (ctx, client_identifier, clean_session, keep_alive, 
					   /* destination host and port but only as a matter of reporting 
					      because we are handling everything through the setup handler */
					   nopoll_conn_host (conn), nopoll_conn_port (conn), 
					   /* this is the handler that will establish the connection on top
					      of the provided noPoll connection */
					   __myqtt_web_socket_session_setup, conn, 
					   /* additional user handlers */
					   on_connected, -1, opts, user_data);
}
Esempio n. 5
0
/** 
 * @brief Allows to start a MQTT server on the provided local host
 * address and port running MQTT over WebSocket protocol.
 *
 * <b>Important note:</b> you must call to \ref myqtt_storage_set_path
 * to define the path first before creating any listener. This is
 * because creating a listener activates all server side code which
 * among other things includes the storage loading (client
 * subscriptions, offline publishing, etc). In the case direction,
 * once the storage path is loaded it cannot be changed after
 * restarting the particular context used in this operation (\ref
 * MyQttCtx).
 *
 * @param ctx The context where the operation takes place.
 *
 * @param listener The webSocket listener connection created on top of which MQTT over WebSocket is expected.
 *
 * @param opts Optional connection options to modify default behaviour.
 *
 * @param on_ready Optional on ready notification handler that gets
 * called when the listener is created or a failure was
 * found. Providing this handler makes this function to not block the
 * caller.
 *
 * @param user_data Optional user defined pointer that is passed into
 * the on_ready function (in the case the former is defined too).
 *
 * See \ref myqtt_listener_new for more information.
 *
 * @return A newly created connection listener reference (\ref
 * MyQttConn). Use \ref myqtt_conn_is_ok to check listener was created
 * without errors.
 */
MyQttConn       * myqtt_web_socket_listener_new         (MyQttCtx             * ctx,
							 noPollConn           * listener,
							 MyQttConnOpts        * opts,
							 MyQttListenerReady     on_ready, 
							 axlPointer             user_data)
{
	MyQttWebSocketReady * websocket_ready = NULL;
	MyQttConn           * myqtt_listener;

	if (! nopoll_conn_is_ok (listener)) {
		myqtt_log (MYQTT_LEVEL_CRITICAL, "Unable to create listener, received reference is not working");
		return NULL;
	} /* end if */

	/* create object for the function proxy but only in the user
	   on_ready function is defined */
	if (on_ready) {
		websocket_ready = axl_new (MyQttWebSocketReady, 1);
		if (websocket_ready == NULL) {
			myqtt_log (MYQTT_LEVEL_CRITICAL, "Unable to allocate memory to start the listener..");
			return NULL;
		} /* end if */
		
		websocket_ready->user_data     = user_data;
		websocket_ready->listener      = listener;
		websocket_ready->user_on_ready = on_ready;
	} /* end if */

	/* associate context */
	__myqtt_web_socket_associate_ctx (ctx, nopoll_conn_ctx (listener));

	myqtt_listener = __myqtt_listener_new_common (ctx, nopoll_conn_host (listener), 
						      __myqtt_listener_get_port (nopoll_conn_port (listener)), 
						      /* register connection and socket */
						      axl_true, nopoll_conn_socket (listener), 
						      opts, on_ready, MYQTT_IPv6, __myqtt_web_socket_accept_connection, 
						      /* configure proxy on ready */
						      __myqtt_web_socket_listener_ready, websocket_ready);

	if (myqtt_listener) {
		/* configure here reference to the noPoll listener */
		myqtt_conn_set_data_full (myqtt_listener, "__my:ws:lstnr", listener,
					  NULL, (axlDestroyFunc) __myqtt_web_socket_close_conn);

		/* configure on ready */
	} /* end if */

	return myqtt_listener;
}
int main (int argc, char ** argv)
{
	noPollConn     * listener;
	noPollConn     * listener_6;
	noPollConn     * listener2;
	noPollConn     * listener_62;
#if defined(NOPOLL_HAVE_SSLv23_ENABLED)	
	noPollConn     * listener3;
#endif
#if defined(NOPOLL_HAVE_SSLv3_ENABLED)	
	noPollConn     * listener4;
#endif	
#if defined(NOPOLL_HAVE_TLSv11_ENABLED)
	noPollConn     * listener5;
	noPollConn     * listener_65;
#endif
	noPollConn     * listener6;
#if defined(NOPOLL_HAVE_TLSv12_ENABLED)
	noPollConn     * listener7;
#endif	
	int              iterator;
	noPollConnOpts * opts;

	signal (SIGTERM,  __terminate_listener);

#if defined(__NOPOLL_PTHREAD_SUPPORT__)	
	printf ("INFO: install default threading functions to check noPoll locking code..\n");
	nopoll_thread_handlers (__nopoll_regtest_mutex_create,
				__nopoll_regtest_mutex_destroy,
				__nopoll_regtest_mutex_lock,
				__nopoll_regtest_mutex_unlock);
#endif

	/* create the context */
	ctx = nopoll_ctx_new ();

	iterator = 1;
	while (iterator < argc) {
		/* check for debug */
		printf ("Checking agument: %s\n", argv[iterator]);
		if (nopoll_cmp (argv[iterator], "--debug")) {
			printf ("Activating debug..\n");
			nopoll_log_enable (ctx, nopoll_true);
#if !defined(NOPOLL_OS_WIN32)
			nopoll_log_color_enable (ctx, nopoll_true);
#endif
		} /* end if */

		/* next position */
		iterator++;
	} 

	/* call to create a listener */
	listener = nopoll_listener_new (ctx, "0.0.0.0", "1234");
	if (! nopoll_conn_is_ok (listener)) {
		printf ("ERROR: Expected to find proper listener connection status, but found..\n");
		return -1;
	}

	printf ("noPoll listener started at: %s:%s (refs: %d)..\n", nopoll_conn_host (listener), nopoll_conn_port (listener), nopoll_conn_ref_count (listener));

	/* call to create a listener */
	listener_6 = nopoll_listener_new6 (ctx, "::1", "2234");
	if (! nopoll_conn_is_ok (listener_6)) {
		printf ("ERROR: Expected to find proper listener connection status, but found (IPv6 -- .1.1)..\n");
		return -1;
	} /* end if */

	printf ("noPoll listener started at (IPv6): %s:%s (refs: %d)..\n", nopoll_conn_host (listener_6), nopoll_conn_port (listener_6), nopoll_conn_ref_count (listener_6));

	/* now start a TLS version */
	printf ("Test: starting listener with TLS (TLSv1) at :1235\n");
	listener2 = nopoll_listener_tls_new (ctx, "0.0.0.0", "1235");
	if (! nopoll_conn_is_ok (listener2)) {
		printf ("ERROR: Expected to find proper listener TLS connection status, but found..\n");
		return -1;
	} /* end if */

	/* configure certificates to be used by this listener */
	if (! nopoll_listener_set_certificate (listener2, "test-certificate.crt", "test-private.key", NULL)) {
		printf ("ERROR: unable to configure certificates for TLS websocket..\n");
		return -1;
	}

	/* register certificates at context level */
	if (! nopoll_ctx_set_certificate (ctx, NULL, "test-certificate.crt", "test-private.key", NULL)) {
		printf ("ERROR: unable to setup certificates at context level..\n");
		return -1;
	}

	/* now start a TLS version */
	printf ("Test: starting listener with TLS IPv6 (TLSv1) at :2235\n");
	listener_62 = nopoll_listener_tls_new6 (ctx, "::1", "2235");
	if (! nopoll_conn_is_ok (listener_62)) {
		printf ("ERROR: Expected to find proper listener TLS connection status, but found..\n");
		return -1;
	} /* end if */

	/* configure certificates to be used by this listener */
	if (! nopoll_listener_set_certificate (listener_62, "test-certificate.crt", "test-private.key", NULL)) {
		printf ("ERROR: unable to configure certificates for TLS websocket..\n");
		return -1;
	}

	/* register certificates at context level */
	if (! nopoll_ctx_set_certificate (ctx, NULL, "test-certificate.crt", "test-private.key", NULL)) {
		printf ("ERROR: unable to setup certificates at context level..\n");
		return -1;
	}

#if defined(NOPOLL_HAVE_SSLv23_ENABLED)	
	/* start listener with sslv23 */
	printf ("Test: starting listener with TLS (SSLv23) at :1236 (all methods)\n");
	opts     = nopoll_conn_opts_new ();
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_SSLV23);
	listener3 = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", "1236");
	if (! nopoll_conn_is_ok (listener3)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (:1236, SSLv23), but found..\n");
		return -1;
	} /* end if */
#endif

#if defined(NOPOLL_HAVE_SSLv3_ENABLED)	
	printf ("Test: starting listener with TLS (SSLv3) at :1237\n");
	opts     = nopoll_conn_opts_new ();
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_SSLV3);
	listener4 = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", "1237");
	if (! nopoll_conn_is_ok (listener4)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (:1237, SSLv3), but found..\n");
		return -1;
	} /* end if */
#endif	

#if defined(NOPOLL_HAVE_TLSv11_ENABLED)
	printf ("Test: starting listener with TLS (TLSv1.1) at :1238\n");
	opts     = nopoll_conn_opts_new ();
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_TLSV1_1);
	listener5 = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", "1238");
	if (! nopoll_conn_is_ok (listener5)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (:1238, TLSv1.1), but found..\n");
		return -1;
	} /* end if */

	printf ("Test: starting listener with TLS (TLSv1.1) (IPv6) at :2238\n");
	opts     = nopoll_conn_opts_new ();
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_TLSV1_1);
	listener_65 = nopoll_listener_tls_new_opts6 (ctx, opts, "::1", "2238");
	if (! nopoll_conn_is_ok (listener_65)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (::1:2238, TLSv1.1, IPv6), but found..\n");
		return -1;
	} /* end if */
	
#endif

#if defined(NOPOLL_HAVE_TLSv12_ENABLED)
	printf ("Test: starting listener with TLS (TLSv1.2) at :1240\n");
	opts     = nopoll_conn_opts_new ();
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_TLSV1_2);
	listener7 = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", "1240");
	if (! nopoll_conn_is_ok (listener7)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (:1240, TLSv1.2), but found..\n");
		return -1;
	} /* end if */
#endif

	opts     = nopoll_conn_opts_new ();

	/* configure server certificates (server.pem) signed by the
	 * provided ca (root.pem) also configured in the last
	 * parameter */
	if (! nopoll_conn_opts_set_ssl_certs (opts, 
					      "server.pem",
					      "server.pem",
					      NULL,
					      "root.pem")) {
		printf ("ERROR: unable to setup certificates...\n");
		return -1;
	}
	/* configure peer verification */
	nopoll_conn_opts_ssl_peer_verify (opts, nopoll_true);
	    
	listener6 = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", "1239");
	if (! nopoll_conn_is_ok (listener6)) {
		printf ("ERROR: Expected to find proper listener TLS connection status (:1236, SSLv23), but found..\n");
		return -1;
	} /* end if */


	/* configure ssl context creator */
	/* nopoll_ctx_set_ssl_context_creator (ctx, ssl_context_creator, NULL); */

	/* set on message received */
	nopoll_ctx_set_on_msg (ctx, listener_on_message, NULL);

	/* set on open */
	nopoll_ctx_set_on_open (ctx, on_connection_opened, NULL);
	
	/* process events */
	nopoll_loop_wait (ctx, 0);

	/* unref connection */
	nopoll_conn_close (listener);
	nopoll_conn_close (listener_6);  /* ipv6 */
	
	nopoll_conn_close (listener2);
	nopoll_conn_close (listener_62); /* ipv6 */
	
#if defined(NOPOLL_HAVE_SSLv23_ENABLED)	
	nopoll_conn_close (listener3);
#endif
#if defined(NOPOLL_HAVE_SSLv3_ENABLED)	
	nopoll_conn_close (listener4);
#endif	
#if defined(NOPOLL_HAVE_TLSv12_ENABLED)
	nopoll_conn_close (listener5);
	nopoll_conn_close (listener_65);
#endif
	nopoll_conn_close (listener6);
#if defined(NOPOLL_HAVE_TLSv12_ENABLED)
	nopoll_conn_close (listener7);
#endif	

	/* finish */
	printf ("Listener: finishing references: %d\n", nopoll_ctx_ref_count (ctx));
	if (previous_msg) {
		printf ("..reference counting for previous msg: %d\n", nopoll_msg_ref_count (previous_msg));
		nopoll_msg_unref (previous_msg);
	} /* end if */

	nopoll_ctx_unref (ctx);

	/* call to release all pending memory allocated as a
	 * consequence of using nopoll (especially TLS) */
	nopoll_cleanup_library ();

	return 0;
}