MSP430F5529 + CC3100 IOT test device risponde solo ad alcuni siti Web di test


8

Recentemente ho lavorato su un progetto IoT usando un microcontrollore MSP430F5529 e un processore di rete CC3100 entrambi da Texas Instrument. Per la valutazione sto usando la piattaforma di lancio MSP430F5529 e il boosterpack CC3100 . Sto cercando di connettere il dispositivo al cloud. Ho implementato con successo l' applicazione di esempio meteo CC3100 che si collega a www.openweathermap.org . Questo esempio è tratto dalle applicazioni di esempio dell'SDK CC3100 . Il programma riceve e risponde correttamente dal sito Web www.openweathermap.org . L'applicazione utilizza il metodo GET per effettuare una richiesta dal sito Web.

Ho anche testato con successo il codice contro www.mocky.io . Il dispositivo riceve un codice di stato 200 risposta OK. Ma quando eseguo un test con il sito requestb.in non ottengo un codice di risposta errore 408 Timeout o un codice di risposta reindirizzamento URL 302.

#define WEATHER_SERVER  "api.openweathermap.org"
#define TEST_SERVER  "requestb.in"
//#define TEST_SERVER  "www.mocky.io"

#define PREFIX_BUFFER   "GET /data/2.5/weather?q="
#define POST_BUFFER     "&APPID=xxxxxxxxxxxxxxxxxx&mode=xml&units=imperial HTTP/1.1\r\nHost:api.openweathermap.org\r\nAccept: */"
#define POST_BUFFER2    "*\r\n\r\n"

#define PREFIX_BUFFER_TEST    "GET /1m75pgt1"
#define POST_BUFFER_TEST_1    " HTTP/1.1\r\nHost:requestb.in\r\nAccept: */"
#define POST_BUFFER_TEST_2    "\r\n\r\n"*

//#define PREFIX_BUFFER_TEST      "GET /v2/5967a65d1100007d16b6c2b4"
//#define POST_BUFFER_TEST_1    " HTTP/1.1\r\nHost:www.mocky.io\r\nAccept: */"
//#define POST_BUFFER_TEST_2    "\r\n\r\n"*

Di seguito è riportato il principale che include alcune delle condizioni di installazione. Parte del codice di gestione degli errori è stato rimosso per brevità.

 int main(int argc, char** argv)
{
    _i32 retVal = -1;

    retVal = initializeAppVariables();
    ASSERT_ON_ERROR(retVal);



    /* Stop WDT and initialize the system-clock of the MCU */
    stopWDT();
    initClk();


    /*
     * Following function configures the device to default state by cleaning
     * the persistent settings stored in NVMEM (viz. connection profiles &
     * policies, power policy etc)
     *
     * Applications may choose to skip this step if the developer is sure
     * that the device is in its default state at start of application
     *
     * Note that all profiles and persistent settings that were done on the
     * device will be lost
     */
    retVal = configureSimpleLinkToDefaultState();


    /*
     * Assumption is that the device is configured in station mode already
     * and it is in its default state
     */
    retVal = sl_Start(0, 0, 0);

    /* Connecting to WLAN AP */
    retVal = establishConnectionWithAP();

    retVal = getCredentials();

    retVal = disconnectFromAP();

    return 0;
}

Di seguito è riportato il codice getCredentials () che chiama i dati ottengono.

<!-- language: lang-c -->
static _i32 getCredentials()
{
    _i32 retVal = -1;

    pal_Strcpy((char *)g_DeviceData.HostName, TEST_SERVER);

    retVal = getHostIP_Device();

    g_DeviceData.SockID = createConnection();
    ASSERT_ON_ERROR(g_DeviceData.SockID);

    retVal = getData();
    ASSERT_ON_ERROR(retVal);

    retVal = sl_Close(g_DeviceData.SockID);
    ASSERT_ON_ERROR(retVal);

    return 0;
}

Di seguito è una funzione getdata () in cui sto ricevendo l'errore.

/*!
    \brief This function Obtains the required data from the server

    \param[in]      none

    \return         0 on success, -ve otherwise

    \note

    \warning
*/
static _i32 getData()
{
    _u8 *p_startPtr = NULL;
    _u8 *p_endPtr = NULL;
    _u8* p_bufLocation = NULL;
    _i32 retVal = -1;

    pal_Memset(g_DeviceData.Recvbuff, 0, sizeof(g_DeviceData.Recvbuff));

    /* Puts together the HTTP GET string. */
    p_bufLocation = g_DeviceData.SendBuff;

    pal_Strcpy(p_bufLocation, PREFIX_BUFFER_TEST);
    p_bufLocation += pal_Strlen(PREFIX_BUFFER_TEST);

    pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_1);
    p_bufLocation += pal_Strlen(POST_BUFFER_TEST_1);

    pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_2);

    /* Send the HTTP GET string to the open TCP/IP socket. */
    retVal = sl_Send(g_DeviceData.SockID, g_DeviceData.SendBuff, pal_Strlen(g_DeviceData.SendBuff), 0);
    if(retVal != pal_Strlen(g_DeviceData.SendBuff))
        ASSERT_ON_ERROR(HTTP_SEND_ERROR);

    /* Receive response */
    retVal = sl_Recv(g_DeviceData.SockID, &g_DeviceData.Recvbuff[0], MAX_SEND_RCV_SIZE, 0);
    if(retVal <= 0)
        ASSERT_ON_ERROR(HTTP_RECV_ERROR);

    g_DeviceData.Recvbuff[pal_Strlen(g_DeviceData.Recvbuff)] = '\0';
    return SUCCESS;
}

La sicurezza per il punto di accesso è impostata come

#define SEC_TYPE        SL_SEC_TYPE_WPA_WPA2    /* Security type of the Access point */

Infine, ci sono pochi dispositivi sensore POC fabbricati con CC3100 che devono trasferire dati nel cloud. Per semplicità stiamo usando il boosterpack, alla fine abbiamo bisogno che i dispositivi del sensore POC comunichino al cloud tramite Wifi.


Sto votando per chiudere questa domanda come off-topic perché il vero problema della domanda riguarda l'utilizzo di base dell'HTTP e, in misura minore, una particolare piattaforma integrata, non l'Internet of Things, quindi il pool di comunanza è con altre domande HTTP prima di tutto, e non proprio per le altre domande sull'IoT.
Chris Stratton,

1
Cordiali saluti, la specifica istanza requestb.in nel codice è apparentemente scaduta e ora 404 quando si accede via HTTP su TLS con SNI come funziona per quelli attualmente validi.
Chris Stratton,

@mico, ho notato che hai rimosso la tua risposta. Inoltre hai menzionato l'aggiunta di una "s" a http. Non sono sicuro di come posso ottenere il tuo suggerimento. Potete per favore darmi qualche informazione.
user8055

@ChrisStratton, Siamo spiacenti di aver votato per chiudere questa domanda. Potete per favore consigliarmi un buon sito di domande e risposte per porre questa domanda?
user8055

Ricevi quei messaggi 302 e 408 o no? In caso contrario, quali messaggi ricevi?
mico,

Risposte:


5

La differenza è perché il sito requestb.in richiede HTTP su TLS con SNI

Si tratta di protocolli HTTP / HTTPS piuttosto complessi e domande di sicurezza probabilmente meglio affrontate altrove nel sistema SE, e per lo più riguardanti i dettagli del requestb.inservizio che stai testando piuttosto che qualunque progetto IoT alla fine potresti fare. Ma finché rimane qui ...


Debug del codice di risposta requestb.in quando si tenta HTTP sulla porta 80

Tu hai detto:

Ma quando eseguo un test con il sito requestb.in non ottengo un codice di risposta errore 408 Timeout o un codice di risposta reindirizzamento URL 302.

Vediamo cosa succede:

curl -i http://requestb.in/xxxxxxxx
HTTP/1.1 301 Moved Permanently
Location: https://requestb.in/xxxxxxxx

Lo stato HTTP 301 è "Spostato in modo permanente", mentre il 302 che ti aspettavi viene talvolta utilizzato per un reindirizzamento temporaneo . Dato che probabilmente non stanno pianificando di lasciarti usare HTTP su un semplice socket TCP sulla porta 80, il reindirizzamento permanente che inviano è la risposta più corretta.

Sarebbe stato molto più utile se avessi acquisito il codice di stato che _ era stato inviato anziché elencare semplicemente due che _ non erano stati inviati

Ad ogni modo, ciò che il server sta dicendo è che dobbiamo usare HTTPS.


Quindi cosa dovresti fare per connetterti al server tramite HTTPS?

A livello base, HTTPS significa semplicemente parlare HTTP su una connessione protetta con TLS (o precedentemente, SSL), piuttosto che farlo su un semplice socket TCP.

Il tuo CC3100 supporta TLS e SSL e ci sono alcune informazioni minime sulla modifica di uno degli esempi di client HTTP dell'SDK per eseguire una connessione HTTPS creando invece un canale sicuro, disponibile su http://processors.wiki.ti.com/index.php / CC3100_HTTP_Client

Tuttavia, in questo caso requestb.inpotrebbe non essere sufficiente.

Se dovessi reindirizzare una semplice richiesta GET al s_clientcomando di openssl (o fare la stessa cosa sul CC3100)

(echo -en "GET /xxxxxxxx HTTP/1.1\nHost: requestb.in\n\n" ; sleep 10) | \
openssl s_client -connect requestb.in:443

( sleepè fare in modo che openssl attenda una risposta anziché riattaccare alla conclusione dell'input)

Si otterrebbe un errore strano:

Routine SSL: SSL23_GET_SERVER_HELLO: errore handshake avviso sslv3

Potresti pensare che abbia qualcosa a che fare con le versioni SSL vs. TLS, ma in realtà è perché requestb.inrichiede qualcosa chiamato Server Name Indication (Wikipedia) . Ciò significa effettivamente che è necessario indicare allo stack SSL di indicare al server quale servername deve autenticare.

Continuando con le dimostrazioni da riga di comando, aggiungeremmo semplicemente un -servernameargomento:

(echo -en "GET /xxxxxxxx HTTP/1.1\nHost: requestb.in\n\n" ; sleep 10) |\
openssl s_client -connect requestb.in:443 -servername requestb.in

Se questo viene fatto con l'hash URL di un'istanza requestb.in valida, produce un risultato ed è visibile nel pannello di registro del browser che l'ha creato.


Implementazione di Server Name Indication (SNI) su CC3xxx

Ci sono alcuni post nel forum che suggeriscono che l'implementazione TLS su CC3xxx non ha supportato SNI e che non ci sono piani concreti per aggiungere questo; tuttavia, è possibile verificare se è ancora così.

Ma è importante ricordare che c'è un albero di livelli di rete coinvolti:

WiFi
  IP packets
    TCP session
      TLS session
        HTTP protocol

Poiché CC3100 ti consente di parlare TCP (e in effetti lo stavi facendo nel tuo codice esistente), sei libero di "portare la tua" implementazione TLS che ha il supporto SNI. Ad esempio, questo post sul blog discute il porting della libreria mbed TLS (precedentemente PolarSSL) su CC3xxx e menziona SNI come funzionalità.

TL; DR

requestb.inè un obiettivo impegnativo in quanto richiede che tu parli HTTP su una sessione protetta con TLS e implementando l' indicazione del nome del server . Se parlare con questo host non fa parte del tuo progetto finale, potresti trovare meglio passare semplicemente a quegli host che sono - quelli destinati all'uso con client embedded minimi sui dispositivi IoT potrebbero essere configurati per rendere le cose un po 'più facili non usando SNI.

Sarà anche molto più efficiente se prendi l'abitudine di catturare i dettagli dei problemi che incontri: lo sviluppo incorporato è sempre difficile da eseguire il debug e meno informazioni sugli errori catturati tramite la registrazione o un debugger, più tempo speso a indovinare .


Sembra una buona risposta, ma va oltre la mia comprensione. Spero di raggiungere questo livello di conoscenza approfondita nel prossimo futuro. Ma grazie mille per la risposta.
user8055

1
Il requisito SNI lo rende davvero complicato: la mia raccomandazione sarebbe di saltare requestb.in, concentrarsi sui requisiti di qualsiasi cosa tu stia effettivamente cercando di parlare nel tuo progetto reale e, se necessario, trovare un servizio beffardo più simile a tale requisito.
Chris Stratton,

Ora quando leggo questo e dopo aver eliminato due dei miei sforzi competitivi, suggerisco lo stesso, fare qualcosa di più produttivo. E accetta lo sforzo di Chris.
mico,

1

È molto probabile che sia openweathermap.org che www.mocky.io supportino http o la porta 80. Di seguito sono riportati alcuni indizi.

openweathermap.org

Openweathermap

openweathermap-url

www.mocky.io

Mocky

Mocky-url

Sembra requestb.in supportare solo HTTPS o porta 443.

requestb.in

requestb

requestb-url

Questo potrebbe spiegare il problema. Di seguito sono riportati alcuni riferimenti che potrebbero essere d'aiuto.

Nel foglio dati CC3100 non ci sono riferimenti a CC3100 che lavora con HTTPS. Tutti i riferimenti sono solo HTTP. Questo probabilmente spiega meglio il problema. Allegare sotto un'eccezione dal foglio dati.

CC3100 - Scheda tecnica esclusa

Sembra che per scheda tecnica CC3120 supporti HTTPS. Allegare di seguito è tranne dal foglio dati. Ci sono alcuni riferimenti a HTTPS.

CC3100 - Scheda tecnica esclusa

Il percorso più probabile è sostituire CC3100 con CC3120.

Riferimenti:


1
Dopo numerose modifiche che introducono errori e poi li correggono, questo potrebbe ora avvicinarsi a essere una risposta effettiva. Ma devi ancora riscriverlo: se la tua tesi è che un sito supporta http e l'altro solo https, allora dillo in anticipo.
Chris Stratton,

2
E la tua analisi del CC3100 e le raccomandazioni sulla sostituzione rimangono del tutto errate. Dice esplicitamente che supporta TLS / SSL, mentre si tenta di sostenere che non guarda erroneamente la sua capacità di web server, quando la domanda non ha nulla a che fare con l'essere un server. La domanda in realtà non sta usando affatto una libreria HTTP, ma lo fa manualmente su un socket TCP. Per contattare un server HTTPS, è necessario eseguire operazioni simili su una connessione SSL.
Chris Stratton,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.