Ramin Toussi
Ramin Toussi

Reputation: 132

Paho MQTT C++ client server address issues when connecting to the broker

I am developing a C++ MQTT client to connect to the AWS IoT Core and I am using Paho MQTT CPP for that. My code is simply based on the ssl_publish which uses the async_client class and SSL for communicating with the broker. I have discovered that the only way to make the connection work and be able to publish a message to a topic on AWS IoT Core is to both

  1. Pass in the address of the broker to the async_client constructor as ssl://: format where the port is 8883 and the ip can be fetched using ping or nslookup on the AWS IoT Core endpoint.
  2. Add the AWS IoT Core endpoint endpoint to a vector and set it on the connection_options using the set_servers() method.

Anything else will fail with different TCP errors such as -1 and -11.

The question is when the async_client constructor is receiving the server address why do we need to sort of set it again on the connection options. Is it a bug on Paho CPP or is it the expected behavior by design. what am i missing in that case then?

The code that works looks like the below:


/**
 * #includes
*/
const std::string DFLT_SERVER_ADDRESS   { "ssl://xx.xxx.xxx.xxx:8883" };
const std::string DFLT_CLIENT_ID        { "mytopic" }; 

/**
 * Other properties like mqtt topic, cert paths and qos are here
*/

// This is the aws iot core end point
static const std::vector<std::string> URIsVec = {
    "xxxxx.iot.eu-west-1.amazonaws.com",
};

const mqtt::const_string_collection_ptr URIs = std::make_shared<const mqtt::string_collection>(URIsVec);

/////////////////////////////////////////////////////////////////////////////

/**
 * A callback class for use with the main MQTT client.
 */
class callback : public virtual mqtt::callback
{
    /**
     * implementation
    */
};

/////////////////////////////////////////////////////////////////////////////

using namespace std;

int main(int argc, char* argv[])
{
    string  address  = (argc > 1) ? string(argv[1]) : DFLT_SERVER_ADDRESS,
            clientID = (argc > 2) ? string(argv[2]) : DFLT_CLIENT_ID;


    // Call to the async_client ctor
    mqtt::async_client client(address, clientID);

    callback cb;
    client.set_callback(cb);

    // Build the connect options, including SSL and a LWT message.

    mqtt::ssl_options sslopts;
    // details of setting the sslopts

    mqtt::connect_options connopts;
    // Removing this line will fail the connection even though the async_client already knows about the server address via its constructor
    connopts.set_servers(URIs);
    // details of setting the connopts

    try {
        // Connect using SSL/TLS

        cout << "\nConnecting ... " << endl;
        mqtt::token_ptr conntok = client.connect(connopts);
        cout << "Waiting for the connection..." << endl;
        conntok->wait();
        cout << "  ...OK" << endl;

        // Send a message

        cout << "\nSending message..." << endl;
        auto msg = mqtt::make_message(LWT_TOPIC, "Hello World!", QOS, true);
        client.publish(msg)->wait_for(TIMEOUT);
        cout << "  ...OK" << endl;

        // Disconnect

        cout << "\nDisconnecting..." << endl;
        client.disconnect()->wait();
        cout << "  ...OK" << endl;
    }
    catch (const mqtt::exception& exc) {
        cerr << exc.what() << endl;
        return 1;
    }

    return 0;
}

My Environment:

Complementary Info:

I tested connection using the mosquitto_pub on the same topic and by using same certificates and it works with the AWS IoT Core domain name and the port, no need to set the ip address.

Upvotes: 2

Views: 662

Answers (0)

Related Questions