Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client re-enqueue a packet that causes PAYLOAD_LIMIT_EXCEEDED disconnect event. #535

Open
chapost1 opened this issue Oct 16, 2024 · 4 comments
Labels
bug This issue is a bug. p2 This is a standard priority issue

Comments

@chapost1
Copy link

Describe the bug

Client keeps retrying publish message (re-enqueue) post disconnect, which it's cause is PAYLOAD_LIMIT_EXCEEDED.
which cause infinite connect/disconnect events.

Expected Behavior

Result with a puback that indicates a failure and not re-enqueue the message as it's payload won't shrink.

Current Behavior

  1. Client attempts to publish a message with payload larger than AWS max payload size.
  2. Client disconnects.
  3. Client re-connects.
  4. Client re-enqueue packet, and try to send it.
  5. Client disconnects.
  6. Client re-connects.
  7. Client re-enqueue packet, and try to send it.
  8. ...

No PUBACK response for the publish method.

Reproduction Steps

Just create a client instance that connects post disconnect events, and attempt to publish a message with payload larger than allowed size.

Possible Solution

Not sure if feasible, because if no puback is returned, then maybe it's on the iot-core service side also, but I think the solution should behave with resulting with failure puback or at least not re-enqueue as it will not be resolved by itself.

Additional Information/Context

No response

SDK version used

1.20.0

Environment details (OS name and version, etc.)

ubuntu:22.04

@chapost1 chapost1 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 16, 2024
@jmklix
Copy link
Member

jmklix commented Oct 16, 2024

Can you try using the MQTT5 client? It will handle the PAYLOAD_LIMIT_EXCEEDED, because part of the updated protocol included the server communicating that the payload limit is.
The MQTT5 client is still broken, as mentioned in this comment.

@jmklix jmklix added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 2 days. p3 This is a minor priority issue and removed needs-triage This issue or PR still needs to be triaged. labels Oct 16, 2024
@chapost1
Copy link
Author

Can you try using the MQTT5 client? It will handle the PAYLOAD_LIMIT_EXCEEDED, because part of the updated protocol included the server communicating that the payload limit is.

Already using MQTT5 client

I've tested multiple cases now and:

  • payload with the size of bytes >= 149482 results with the client to actually catch it and throw an error

  • payload with the size of bytes <= 131072 (128KB) results with no error and no disconnect event, and reaches to the broker safely

  • payload with the size of bytes >= 131073 (128KB + 1) and <= 149481 results in infinite connect and disconnect events due to the fact that the client keeps re-enqueue the message.

terminal logs

node index.js 
Connack: Connection Success event {
  connack: {
    type: 2,
    sessionPresent: false,
    reasonCode: 0,
    receiveMaximum: 100,
    maximumQos: 1,
    retainAvailable: true,
    maximumPacketSize: 149504,
    topicAliasMaximum: 8,
    userProperties: [],
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    serverKeepAlive: 120
  },
  settings: {
    maximumQos: 1,
    sessionExpiryInterval: 1200,
    receiveMaximumFromServer: 100,
    maximumPacketSizeToServer: 149504,
    topicAliasMaximumToServer: 8,
    topicAliasMaximumToClient: 0,
    serverKeepAlive: 120,
    retainAvailable: true,
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    rejoinedSession: false,
    clientId: 'test-issue-535_c4d0021a-96d0-4f43-a321-5d328f15fcb8'
  }
}
Connection established
Disconnection event {
  error: 'Error: libaws-c-mqtt: AWS_ERROR_MQTT5_DISCONNECT_RECEIVED, Mqtt5 client connection interrupted by server DISCONNECT.',
  disconnect: {
    type: 14,
    reasonCode: 151,
    reasonString: 'DISCONNECT:Packet payload is larger than the account limit:f0fbc633-ae95-43bd-9ec6-c18fca17d591',
    userProperties: []
  }
}
Connack: Connection Success event {
  connack: {
    type: 2,
    sessionPresent: false,
    reasonCode: 0,
    receiveMaximum: 100,
    maximumQos: 1,
    retainAvailable: true,
    maximumPacketSize: 149504,
    topicAliasMaximum: 8,
    userProperties: [],
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    serverKeepAlive: 120
  },
  settings: {
    maximumQos: 1,
    sessionExpiryInterval: 1200,
    receiveMaximumFromServer: 100,
    maximumPacketSizeToServer: 149504,
    topicAliasMaximumToServer: 8,
    topicAliasMaximumToClient: 0,
    serverKeepAlive: 120,
    retainAvailable: true,
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    rejoinedSession: false,
    clientId: 'test-issue-535_c4d0021a-96d0-4f43-a321-5d328f15fcb8'
  }
}
Disconnection event {
  error: 'Error: libaws-c-mqtt: AWS_ERROR_MQTT5_DISCONNECT_RECEIVED, Mqtt5 client connection interrupted by server DISCONNECT.',
  disconnect: {
    type: 14,
    reasonCode: 151,
    reasonString: 'DISCONNECT:Packet payload is larger than the account limit:c245072b-0f7f-4af9-aa14-2943c023b4b3',
    userProperties: []
  }
}
Connack: Connection Success event {
  connack: {
    type: 2,
    sessionPresent: false,
    reasonCode: 0,
    receiveMaximum: 100,
    maximumQos: 1,
    retainAvailable: true,
    maximumPacketSize: 149504,
    topicAliasMaximum: 8,
    userProperties: [],
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    serverKeepAlive: 120
  },
  settings: {
    maximumQos: 1,
    sessionExpiryInterval: 1200,
    receiveMaximumFromServer: 100,
    maximumPacketSizeToServer: 149504,
    topicAliasMaximumToServer: 8,
    topicAliasMaximumToClient: 0,
    serverKeepAlive: 120,
    retainAvailable: true,
    wildcardSubscriptionsAvailable: true,
    subscriptionIdentifiersAvailable: false,
    sharedSubscriptionsAvailable: true,
    rejoinedSession: false,
    clientId: 'test-issue-535_c4d0021a-96d0-4f43-a321-5d328f15fcb8'
  }
}
Disconnection event {
  error: 'Error: libaws-c-mqtt: AWS_ERROR_MQTT5_DISCONNECT_RECEIVED, Mqtt5 client connection interrupted by server DISCONNECT.',
  disconnect: {
    type: 14,
    reasonCode: 151,
    reasonString: 'DISCONNECT:Packet payload is larger than the account limit:0d43adad-2e29-4700-935d-7558fc3c6f15',
    userProperties: []
  }
}
^C

code snippet that re-produces the issue.

const iotsdk = require('aws-iot-device-sdk-v2')
const iot = iotsdk.iot
const mqtt5 = iotsdk.mqtt5
const fs = require('node:fs')
const events = require('node:events')
const crypto = require('node:crypto')
const { scheduler } = require('node:timers/promises')

const getClient = () => {
    const port = 8883
    const clientId = `test-issue-535_${crypto.randomUUID()}`

    const cert = fs.readFileSync('./cert.crt')
    const privateKey = fs.readFileSync('./key.pem')
    const endpoint = fs.readFileSync('./endpoint.txt', 'utf-8').trim()

    const config = iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromMemory(
        endpoint,
        cert,
        privateKey
    )
        .withPort(port)
        .withConnectProperties({
            clientId,
            keepAliveIntervalSeconds: 120,
            sessionExpiryIntervalSeconds: 1200,
        })
        .withSessionBehavior(mqtt5.ClientSessionBehavior.Clean)
        .build()

    const client = new mqtt5.Mqtt5Client(config);

    return client
}

const connect = async (client) => {
    // makes sure process won't die during first connection attempt
    const timer = setInterval(() => { }, 60 * 1000)
    // Allow node to die if the promise above resolved
    clearKeepAliveInterval = () => clearInterval(timer)
    // set up event handlers      
    client.on('error', (error) => {
        console.error("Error event: " + error.toString());
    });

    client.on('connectionSuccess', (eventData) => {
        console.log("Connack: Connection Success event", {
            connack: eventData.connack,
            settings: eventData.settings
        });
    });

    client.on('disconnection', (eventData) => {
        console.log("Disconnection event", {
            error: eventData.error.toString(),
            disconnect: eventData.disconnect || null,
        });
    });

    const connectionSuccess = events.once(client, "connectionSuccess");

    client.start()
    // connect
    await connectionSuccess

    console.log("Connection established")

    return client
}

const run = async () => {
    const client = getClient()
    await connect(client)

    // publish a large payload
    const payload = Buffer.alloc(128*1024 + 1, 'a')

    await client.publish({
        topicName: 'test-issue-535',
        payload: payload,
        qos: mqtt5.QoS.AtLeastOnce,
        retain: false
    })

    await scheduler.wait(1000)
}

run().catch((error) => {
    console.error("An error occurred:", error)
    process.exit(1)
})

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 2 days. label Oct 17, 2024
@bretambrose
Copy link
Contributor

This is an IoT Core bug that I reported a year ago. Will follow up and see why it has not been addressed yet.

@jmklix jmklix added p2 This is a standard priority issue and removed p3 This is a minor priority issue labels Oct 17, 2024
@jmklix
Copy link
Member

jmklix commented Oct 17, 2024

P162538649

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. p2 This is a standard priority issue
Projects
None yet
Development

No branches or pull requests

3 participants