mqtt

LWIP MQTT

调试lwip以太网MQTT连接服务器,发现如果服务器不需要用户名和密码权限则可以正常连接MQTT服务器,并能够发布和订阅消息,但连接需要用户名和密码的服务器,则提示认证失败。

分析发现函数mqtt_client_connect没有处理client结构体中的用户名和密码字段

原函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
err_t
mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg,
const struct mqtt_connect_client_info_t *client_info)
{
err_t err;
size_t len;
u16_t client_id_length;
/* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */
u16_t remaining_length = 2 + 4 + 1 + 1 + 2;
u8_t flags = 0, will_topic_len = 0, will_msg_len = 0;
u16_t client_user_len = 0, client_pass_len = 0;

LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL);
LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL);
LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL);
LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL);

if (client->conn_state != TCP_DISCONNECTED) {
LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Already connected\n"));
return ERR_ISCONN;
}

/* Wipe clean */
memset(client, 0, sizeof(mqtt_client_t));
client->connect_arg = arg;
client->connect_cb = cb;
client->keep_alive = client_info->keep_alive;
mqtt_init_requests(client->req_list, LWIP_ARRAYSIZE(client->req_list));

/* Build connect message */
if (client_info->will_topic != NULL && client_info->will_msg != NULL) {
flags |= MQTT_CONNECT_FLAG_WILL;
flags |= (client_info->will_qos & 3) << 3;
if (client_info->will_retain) {
flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
}
len = strlen(client_info->will_topic);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL);
will_topic_len = (u8_t)len;
len = strlen(client_info->will_msg);
LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);
will_msg_len = (u8_t)len;
len = remaining_length + 2 + will_topic_len + 2 + will_msg_len;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
remaining_length = (u16_t)len;
}
if (client_info->client_user != NULL) {
flags |= MQTT_CONNECT_FLAG_USERNAME;
len = strlen(client_info->client_user);
LWIP_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFFFF, return ERR_VAL);
LWIP_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return ERR_VAL);
client_user_len = (u16_t)len;
len = remaining_length + 2 + client_user_len;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
remaining_length = (u16_t)len;
}
if (client_info->client_pass != NULL) {
flags |= MQTT_CONNECT_FLAG_PASSWORD;
len = strlen(client_info->client_pass);
LWIP_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFFFF, return ERR_VAL);
LWIP_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return ERR_VAL);
client_pass_len = (u16_t)len;
len = remaining_length + 2 + client_pass_len;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
remaining_length = (u16_t)len;
}

/* Don't complicate things, always connect using clean session */
flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;

len = strlen(client_info->client_id);
LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL);
client_id_length = (u16_t)len;
len = remaining_length + 2 + client_id_length;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
remaining_length = (u16_t)len;

if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
return ERR_MEM;
}

#if LWIP_ALTCP && LWIP_ALTCP_TLS
if (client_info->tls_config) {
client->conn = altcp_tls_new(client_info->tls_config, IP_GET_TYPE(ip_addr));
} else
#endif
{
client->conn = altcp_tcp_new_ip_type(IP_GET_TYPE(ip_addr));
}
if (client->conn == NULL) {
return ERR_MEM;
}

/* Set arg pointer for callbacks */
altcp_arg(client->conn, client);
/* Any local address, pick random local port number */
err = altcp_bind(client->conn, IP_ADDR_ANY, 0);
if (err != ERR_OK) {
LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Error binding to local ip/port, %d\n", err));
goto tcp_fail;
}
LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port));

/* Connect to server */
err = altcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb);
if (err != ERR_OK) {
LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err));
goto tcp_fail;
}
/* Set error callback */
altcp_err(client->conn, mqtt_tcp_err_cb);
client->conn_state = TCP_CONNECTING;

/* Append fixed header */
mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length);
/* Append Protocol string */
mqtt_output_append_string(&client->output, "MQTT", 4);
/* Append Protocol level */
mqtt_output_append_u8(&client->output, 4);
/* Append connect flags */
mqtt_output_append_u8(&client->output, flags);
/* Append keep-alive */
mqtt_output_append_u16(&client->output, client_info->keep_alive);
/* Append client id */
mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
/* Append will message if used */
if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {
mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);
mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);
}
/* Append user name if given */
if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) {
mqtt_output_append_string(&client->output, client_info->client_user, client_user_len);
}
/* Append password if given */
if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) {
mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len);
}
return ERR_OK;

tcp_fail:
altcp_abort(client->conn);
client->conn = NULL;
return err;
}

修改后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
err_t
mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg,
const struct mqtt_connect_client_info_t *client_info)
{
err_t err;
size_t len;
u16_t client_id_length;
/* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */
u16_t remaining_length = 2 + 4 + 1 + 1 + 2;
u8_t flags = 0, will_topic_len = 0, will_msg_len = 0;

LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL);
LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL);
LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL);
LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL);

if (client->conn_state != TCP_DISCONNECTED) {
LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n"));
return ERR_ISCONN;
}

/* Wipe clean */
memset(client, 0, sizeof(mqtt_client_t));
client->connect_arg = arg;
client->connect_cb = cb;
client->keep_alive = client_info->keep_alive;
mqtt_init_requests(client->req_list);

/* Build connect message */
if (client_info->will_topic != NULL && client_info->will_msg != NULL) {
flags |= MQTT_CONNECT_FLAG_WILL;
flags |= (client_info->will_qos & 3) << 3;
if (client_info->will_retain) {
flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
}

len = strlen(client_info->will_topic);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL);
will_topic_len = (u8_t)len;
len = strlen(client_info->will_msg);
LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);
will_msg_len = (u8_t)len;
len = remaining_length + 2 + will_topic_len + 2 + will_msg_len;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
remaining_length = (u16_t)len;
}

/* Don't complicate things, always connect using clean session */
flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;

len = strlen(client_info->client_id);
LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL);
client_id_length = (u16_t)len;
len = remaining_length + 2 + client_id_length;
LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
//-------------------------------------------------------------------------------------------------------------------------------
if(client_info->client_user!=NULL)
{
flags |= MQTT_CONNECT_FLAG_USERNAME;
len+=2 + strlen(client_info->client_user);
}
if(client_info->client_pass!=NULL)
{
flags |= MQTT_CONNECT_FLAG_PASSWORD;
len+=2 + strlen(client_info->client_pass);
}
//-------------------------------------------------------------------------------------------------------------------------------
remaining_length = (u16_t)len;
if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
return ERR_MEM;
}

client->conn = tcp_new();
if (client->conn == NULL) {
return ERR_MEM;
}

/* Set arg pointer for callbacks */
tcp_arg(client->conn, client);
/* Any local address, pick random local port number */
err = tcp_bind(client->conn, IP_ADDR_ANY, 0);
if (err != ERR_OK) {
LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err));
goto tcp_fail;
}
LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port));

/* Connect to server */
err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb);
if (err != ERR_OK) {
LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err));
goto tcp_fail;
}
/* Set error callback */
tcp_err(client->conn, mqtt_tcp_err_cb);
client->conn_state = TCP_CONNECTING;

/* Append fixed header */
mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length);
/* Append Protocol string */
mqtt_output_append_string(&client->output, "MQTT", 4);
/* Append Protocol level */
mqtt_output_append_u8(&client->output, 4);
/* Append connect flags */
mqtt_output_append_u8(&client->output, flags);
/* Append keep-alive */
mqtt_output_append_u16(&client->output, client_info->keep_alive);
/* Append client id */
mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
/* Append will message if used */
if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {
mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);
mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);
}
//-------------------------------------------------------------------------------------------------------------------------------
if((flags & MQTT_CONNECT_FLAG_USERNAME) != 0)
{
mqtt_output_append_string(&client->output, client_info->client_user, strlen(client_info->client_user));
}
if((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0)
{
mqtt_output_append_string(&client->output, client_info->client_pass, strlen(client_info->client_pass));
}
//-------------------------------------------------------------------------------------------------------------------------------
return ERR_OK;

tcp_fail:
tcp_abort(client->conn);
client->conn = NULL;
return err;
}

2.02以后的版本已经修复这个bug

-->

请我喝杯咖啡吧~

支付宝
微信