void ICACHE_FLASH_ATTR MQTTCMD_Subscribe(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); if (cmdGetArgc(&req) != 2) return; MQTT_Client* client = &mqttClient; uint16_t len; // get topic len = cmdArgLen(&req); if (len > 128) return; // safety check uint8_t* topic = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, topic, len); topic[len] = 0; // get qos uint32_t qos = 0; cmdPopArg(&req, (uint8_t*)&qos, 4); DBG("MQTT: MQTTCMD_Subscribe topic=%s, qos=%u\n", topic, qos); MQTT_Subscribe(client, (char*)topic, (uint8_t)qos); os_free(topic); return; }
void ICACHE_FLASH_ATTR MQTTCMD_Setup(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); MQTT_Client* client = &mqttClient; if (cmdGetArgc(&req) != 4) return; // create callback MqttCmdCb* callback = (MqttCmdCb*)os_zalloc(sizeof(MqttCmdCb)); cmdPopArg(&req, &callback->connectedCb, 4); cmdPopArg(&req, &callback->disconnectedCb, 4); cmdPopArg(&req, &callback->publishedCb, 4); cmdPopArg(&req, &callback->dataCb, 4); client->user_data = callback; DBG("MQTT connectedCb=%x\n", callback->connectedCb); client->cmdConnectedCb = cmdMqttConnectedCb; client->cmdDisconnectedCb = cmdMqttDisconnectedCb; client->cmdPublishedCb = cmdMqttPublishedCb; client->cmdDataCb = cmdMqttDataCb; if (client->connState == MQTT_CONNECTED) { if (callback->connectedCb) cmdMqttConnectedCb(client); } else if (callback->disconnectedCb) { cmdMqttDisconnectedCb(client); } }
uint32_t ICACHE_FLASH_ATTR MQTTCMD_Connect(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); #ifdef MQTT_1_CLIENT if (mqttClient.connState == MQTT_CONNECTED && mqttClient.cmdConnectedCb) { mqttClient.cmdConnectedCb((uint32_t*)&mqttClient); } else if (mqttClient.connState == MQTT_DISCONNECTED && mqttClient.cmdDisconnectedCb) { mqttClient.cmdDisconnectedCb((uint32_t*)&mqttClient); } return 1; #else if (cmdGetArgc(&req) != 4) return 0; // get mqtt client uint32_t client_ptr; cmdPopArg(&req, (uint8_t*)&client_ptr, 4); MQTT_Client* client = (MQTT_Client*)client_ptr; DBG("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr); uint16_t len; // get host if (client->host) os_free(client->host); len = cmdArgLen(&req); if (len > 128) return 0; // safety check client->host = (char*)os_zalloc(len + 1); cmdPopArg(&req, client->host, len); client->host[len] = 0; // get port cmdPopArg(&req, (uint8_t*)&client->port, 4); // get security cmdPopArg(&req, (uint8_t*)&client->security, 4); DBG("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n", client->host, client->port, client->security); MQTT_Connect(client); return 1; #endif }
void ICACHE_FLASH_ATTR MQTTCMD_Publish(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); if (cmdGetArgc(&req) != 5) return; MQTT_Client* client = &mqttClient; uint16_t len; // get topic len = cmdArgLen(&req); if (len > 128) return; // safety check uint8_t *topic = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, topic, len); topic[len] = 0; // get data len = cmdArgLen(&req); uint8_t *data = (uint8_t*)os_zalloc(len+1); if (!data) { // safety check os_free(topic); return; } cmdPopArg(&req, data, len); data[len] = 0; uint16_t data_len; uint8_t qos, retain; // get data length cmdPopArg(&req, &data_len, sizeof(data_len)); // get qos cmdPopArg(&req, &qos, sizeof(qos)); // get retain cmdPopArg(&req, &retain, sizeof(retain)); DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%d, retain=%d\n", topic, data_len, qos, retain); MQTT_Publish(client, (char*)topic, (char*)data, data_len, qos%3, retain&1); os_free(topic); os_free(data); return; }
void ICACHE_FLASH_ATTR REST_SetHeader(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); if(cmdGetArgc(&req) != 2) return; // Get client uint32_t clientNum = cmd->value; RestClient *client = restClient + (clientNum % MAX_REST); // Get header selector uint32_t header_index; if (cmdPopArg(&req, (uint8_t*)&header_index, 4)) return; // Get header value uint16_t len = cmdArgLen(&req); if (len > 256) return; //safety check switch(header_index) { case HEADER_GENERIC: if(client->header) os_free(client->header); client->header = (char*)os_zalloc(len + 3); cmdPopArg(&req, (uint8_t*)client->header, len); client->header[len] = '\r'; client->header[len+1] = '\n'; client->header[len+2] = 0; DBG("REST: Set header: %s\r\n", client->header); break; case HEADER_CONTENT_TYPE: if(client->content_type) os_free(client->content_type); client->content_type = (char*)os_zalloc(len + 3); cmdPopArg(&req, (uint8_t*)client->content_type, len); client->content_type[len] = '\r'; client->content_type[len+1] = '\n'; client->content_type[len+2] = 0; DBG("REST: Set content_type: %s\r\n", client->content_type); break; case HEADER_USER_AGENT: if(client->user_agent) os_free(client->user_agent); client->user_agent = (char*)os_zalloc(len + 3); cmdPopArg(&req, (uint8_t*)client->user_agent, len); client->user_agent[len] = '\r'; client->user_agent[len+1] = '\n'; client->user_agent[len+2] = 0; DBG("REST: Set user_agent: %s\r\n", client->user_agent); break; } }
void ICACHE_FLASH_ATTR MQTTCMD_Lwt(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); if (cmdGetArgc(&req) != 4) return; MQTT_Client* client = &mqttClient; // free old topic & message if (client->connect_info.will_topic) os_free(client->connect_info.will_topic); if (client->connect_info.will_message) os_free(client->connect_info.will_message); uint16_t len; // get topic len = cmdArgLen(&req); if (len > 128) return; // safety check client->connect_info.will_topic = (char*)os_zalloc(len + 1); cmdPopArg(&req, client->connect_info.will_topic, len); client->connect_info.will_topic[len] = 0; // get message len = cmdArgLen(&req); if (len > 128) return; // safety check client->connect_info.will_message = (char*)os_zalloc(len + 1); cmdPopArg(&req, client->connect_info.will_message, len); client->connect_info.will_message[len] = 0; // get qos cmdPopArg(&req, (uint8_t*)&client->connect_info.will_qos, 4); // get retain cmdPopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4); DBG("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n", client->connect_info.will_topic, client->connect_info.will_message, client->connect_info.will_qos, client->connect_info.will_retain); // trigger a reconnect to set the LWT MQTT_Reconnect(client); }
uint32_t ICACHE_FLASH_ATTR MQTTCMD_Disconnect(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); #ifdef MQTT_1_CLIENT return 1; #else if (cmdGetArgc(&req) != 1) return 0; // get mqtt client uint32_t client_ptr; cmdPopArg(&req, (uint8_t*)&client_ptr, 4); MQTT_Client* client = (MQTT_Client*)client_ptr; DBG("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr); // disconnect MQTT_Disconnect(client); return 1; #endif }
void ICACHE_FLASH_ATTR MQTTCMD_Setup(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); MQTT_Client* client = &mqttClient; if (cmdGetArgc(&req) != 4) return; #if 0 // This section is commented-out because we're using the same client as esp-link is using itself, // i.e. the one set-up in the Web UI. This code was here when we used a separate client for the // attached uC, which just makes life more complicated... if (cmdGetArgc(&req) != 9) return 0; // create mqtt client uint8_t clientLen = sizeof(MQTT_Client); MQTT_Client* client = (MQTT_Client*)os_zalloc(clientLen); if (client == NULL) return 0; os_memset(client, 0, clientLen); uint16_t len; uint8_t *client_id, *user_data, *pass_data; uint32_t keepalive, clean_session; // get client id len = cmdArgLen(&req); if (len > 32) return 0; // safety check client_id = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, client_id, len); client_id[len] = 0; // get username len = cmdArgLen(&req); if (len > 32) return 0; // safety check user_data = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, user_data, len); user_data[len] = 0; // get password len = cmdArgLen(&req); if (len > 32) return 0; // safety check pass_data = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, pass_data, len); pass_data[len] = 0; // get keepalive cmdPopArg(&req, (uint8_t*)&keepalive, 4); // get clean session cmdPopArg(&req, (uint8_t*)&clean_session, 4); #ifdef MQTTCMD_DBG DBG("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session); #endif // init client // TODO: why malloc these all here, pass to MQTT_InitClient to be malloc'd again? MQTT_InitClient(client, (char*)client_id, (char*)user_data, (char*)pass_data, keepalive, clean_session); os_free(client_id); os_free(user_data); os_free(pass_data); #endif // create callback MqttCmdCb* callback = (MqttCmdCb*)os_zalloc(sizeof(MqttCmdCb)); cmdPopArg(&req, &callback->connectedCb, 4); cmdPopArg(&req, &callback->disconnectedCb, 4); cmdPopArg(&req, &callback->publishedCb, 4); cmdPopArg(&req, &callback->dataCb, 4); client->user_data = callback; DBG("MQTT connectedCb=%x\n", callback->connectedCb); client->cmdConnectedCb = cmdMqttConnectedCb; client->cmdDisconnectedCb = cmdMqttDisconnectedCb; client->cmdPublishedCb = cmdMqttPublishedCb; client->cmdDataCb = cmdMqttDataCb; if (client->connState == MQTT_CONNECTED) { if (callback->connectedCb) cmdMqttConnectedCb(client); } else if (callback->disconnectedCb) { cmdMqttDisconnectedCb(client); } }
void ICACHE_FLASH_ATTR REST_Request(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); DBG("REST: request"); if (cmd->argc != 2 && cmd->argc != 3) return; // Get client uint32_t clientNum = cmd->value; RestClient *client = restClient + (clientNum % MAX_REST); DBG(" #%ld", clientNum); // Get HTTP method uint16_t len = cmdArgLen(&req); if (len > 15) goto fail; char method[16]; cmdPopArg(&req, method, len); method[len] = 0; DBG(" method=%s", method); // Get HTTP path len = cmdArgLen(&req); if (len > 1023) goto fail; char path[1024]; cmdPopArg(&req, path, len); path[len] = 0; DBG(" path=%s", path); // Get HTTP body uint32_t realLen = 0; if (cmdGetArgc(&req) == 2) { realLen = 0; } else { realLen = cmdArgLen(&req); if (realLen > 2048) goto fail; } DBG(" bodyLen=%ld", realLen); // we need to allocate memory for the header plus the body. First we count the length of the // header (including some extra counted "%s" and then we add the body length. We allocate the // whole shebang and copy everything into it. // BTW, use http/1.0 to avoid responses with transfer-encoding: chunked char *headerFmt = "%s %s HTTP/1.0\r\n" "Host: %s\r\n" "%s" "Content-Length: %d\r\n" "Connection: close\r\n" "Content-Type: %s\r\n" "User-Agent: %s\r\n\r\n"; uint16_t headerLen = strlen(headerFmt) + strlen(method) + strlen(path) + strlen(client->host) + strlen(client->header) + strlen(client->content_type) + strlen(client->user_agent); DBG(" hdrLen=%d", headerLen); if (client->data) os_free(client->data); client->data = (char*)os_zalloc(headerLen + realLen); if (client->data == NULL) goto fail; DBG(" totLen=%ld data=%p", headerLen + realLen, client->data); client->data_len = os_sprintf((char*)client->data, headerFmt, method, path, client->host, client->header, realLen, client->content_type, client->user_agent); DBG(" hdrLen=%d", client->data_len); if (realLen > 0) { cmdPopArg(&req, client->data + client->data_len, realLen); client->data_len += realLen; } DBG("\n"); //DBG("REST request: %s", (char*)client->data); //DBG("REST: pCon state=%d\n", client->pCon->state); client->pCon->state = ESPCONN_NONE; espconn_regist_connectcb(client->pCon, tcpclient_connect_cb); espconn_regist_reconcb(client->pCon, tcpclient_recon_cb); if(UTILS_StrToIP((char *)client->host, &client->pCon->proto.tcp->remote_ip)) { DBG("REST: Connect to ip %s:%ld\n",client->host, client->port); //if(client->security){ // espconn_secure_connect(client->pCon); //} //else { espconn_connect(client->pCon); //} } else { DBG("REST: Connect to host %s:%ld\n", client->host, client->port); espconn_gethostbyname(client->pCon, (char *)client->host, &client->ip, rest_dns_found); } return; fail: DBG("\n"); }
void ICACHE_FLASH_ATTR REST_Setup(CmdPacket *cmd) { CmdRequest req; uint32_t port, security; int32_t err = -1; // error code in case of failure // start parsing the command cmdRequest(&req, cmd); if(cmdGetArgc(&req) != 3) goto fail; err--; // get the hostname uint16_t len = cmdArgLen(&req); if (len > 128) goto fail; // safety check err--; uint8_t *rest_host = (uint8_t*)os_zalloc(len + 1); if (cmdPopArg(&req, rest_host, len)) goto fail; err--; rest_host[len] = 0; // get the port if (cmdPopArg(&req, (uint8_t*)&port, 2)) { os_free(rest_host); goto fail; } err--; // get the security mode if (cmdPopArg(&req, (uint8_t*)&security, 1)) { os_free(rest_host); goto fail; } err--; // clear connection structures the first time if (restNum == 0xff) { os_memset(restClient, 0, MAX_REST * sizeof(RestClient)); restNum = 0; } // allocate a connection structure RestClient *client = restClient + restNum; uint8_t clientNum = restNum; restNum = (restNum+1)%MAX_REST; // free any data structure that may be left from a previous connection if (client->header) os_free(client->header); if (client->content_type) os_free(client->content_type); if (client->user_agent) os_free(client->user_agent); if (client->data) os_free(client->data); if (client->pCon) { if (client->pCon->proto.tcp) os_free(client->pCon->proto.tcp); os_free(client->pCon); } os_memset(client, 0, sizeof(RestClient)); DBG("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security); client->resp_cb = cmd->value; client->host = (char *)rest_host; client->port = port; client->security = security; client->header = (char*)os_zalloc(4); client->header[0] = 0; client->content_type = (char*)os_zalloc(22); os_sprintf((char *)client->content_type, "x-www-form-urlencoded"); client->user_agent = (char*)os_zalloc(9); os_sprintf((char *)client->user_agent, "esp-link"); client->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); client->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); client->pCon->type = ESPCONN_TCP; client->pCon->state = ESPCONN_NONE; client->pCon->proto.tcp->local_port = espconn_port(); client->pCon->proto.tcp->remote_port = client->port; client->pCon->reverse = client; cmdResponseStart(CMD_RESP_V, clientNum, 0); cmdResponseEnd(); return; fail: cmdResponseStart(CMD_RESP_V, err, 0); cmdResponseEnd(); return; }