All async function could return error.
async_recv complete with error always started closing process. But it could intentional cancel (operation_aborted). In this case, no longer start closing process. Just report error.
async_send needs to care about packet_id.
Basically, packet_id ownership is moved to the library if async_send() is called. So if error happens, it should be released by async_send() if releasing is needed.
PUBLISH
If packet is stored, packet_id shouldn't be released
If packet is not stored but send error happened, the packet_id should be released because the counter part never return acknowlege packet.
PUBREL
packet_id should be owned by async_mqtt until PUBCOMP is received. So it shouldn't be released.
SUBSCRIBE, UNSUBSCRIBE
If send error happened, the packet_id should be released because the counter part never return acknowlege packet.
All async function could return error. async_recv complete with error always started closing process. But it could intentional cancel (operation_aborted). In this case, no longer start closing process. Just report error.
async_send needs to care about packet_id. Basically, packet_id ownership is moved to the library if async_send() is called. So if error happens, it should be released by async_send() if releasing is needed.