El dispositivo de prueba MSP430F5529 + CC3100 IOT solo responde a algunos sitios web de prueba

8

Recientemente he estado trabajando en un proyecto de IoT utilizando un microcontrolador MSP430F5529 y un procesador de red CC3100, ambos de Texas Instrument. Para la evaluación, estoy usando la plataforma de lanzamiento MSP430F5529 y el paquete de refuerzo CC3100 . Estoy intentando que el dispositivo se conecte a la nube. Implementé con éxito la aplicación de ejemplo CC3100 get weather que se conecta a www.openweathermap.org . Este es un ejemplo de las aplicaciones de muestra del SDK CC3100 . El programa recibe y responde con éxito del sitio web www.openweathermap.org . La aplicación utiliza el método GET para realizar una solicitud desde el sitio web.

También he probado con éxito el código en www.mocky.io . El dispositivo recibe un código de estado 200 OK respuesta. Pero cuando pruebo en el sitio de prueba requestb.in no obtengo ni un código de respuesta de error de tiempo de espera 408 ni un código de respuesta de redireccionamiento de URL de 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"*

A continuación se muestra el principal que incluye algunas de las condiciones de configuración. Parte del código de manejo de errores se ha eliminado por brevedad.

 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;
}

A continuación se muestra el código getCredentials () que llama a obtener datos.

<!-- 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;
}

A continuación se muestra una función getdata () donde obtengo el error.

/*!
    \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 seguridad para el punto de acceso se configura como

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

Finalmente, hay pocos dispositivos sensores POC fabricados con CC3100 que necesiten transferir datos a la nube. Por simplicidad, estamos usando el boosterpack, eventualmente necesitamos que los dispositivos sensores POC se comuniquen con la nube a través de Wifi.

usuario8055
fuente
Estoy votando para cerrar esta pregunta como fuera de tema porque el tema real de la pregunta es sobre el uso básico de HTTP y, en menor medida, una plataforma integrada particular, no Internet of Things, por lo tanto, el conjunto de puntos en común es para otras preguntas HTTP primero, y no realmente a otras preguntas de IoT en absoluto.
Chris Stratton
1
Para su información, la instancia específica de requestb.in en su código aparentemente ha excedido el tiempo de espera y ahora es 404 cuando se accede a través de HTTP a través de TLS con SNI, ya que funciona para los válidos actualmente.
Chris Stratton
@mico, noté que has eliminado tu respuesta. También mencionaste agregar una "s" a http. No estoy seguro de cómo puedo lograr su sugerencia. ¿Puedes por favor darme algunas ideas?
user8055
@ChrisStratton, lamento escuchar que está votando para cerrar estas preguntas. ¿Me puede recomendar un buen sitio de preguntas y respuestas para hacer esta pregunta?
user8055
¿Recibes esos mensajes 302 y 408 o no? Si no, ¿qué mensajes recibes?
mico

Respuestas:

5

La diferencia es porque el sitio requestb.in requiere HTTP sobre TLS con SNI

Esta es una pregunta de seguridad y protocolos HTTP / HTTPS bastante compleja que probablemente se aborde mejor en otras partes del sistema SE, y principalmente sobre los detalles del requestb.inservicio que está probando en lugar de cualquier proyecto de IoT que eventualmente esté haciendo. Pero mientras permanezca aquí ...


Depuración del código de respuesta requestb.in al intentar HTTP en el puerto 80

Tu dijiste:

Pero cuando pruebo en el sitio de prueba requestb.in no obtengo ni un código de respuesta de error de tiempo de espera 408 ni un código de respuesta de redireccionamiento de URL de 302.

Veamos qué pasa:

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

El estado HTTP 301 es "movido permanentemente", mientras que el 302 que esperaba a veces se usa para una redirección temporal . Dado que probablemente no planean permitirle usar HTTP en un socket TCP simple en el puerto 80, la redirección permanente que envían es la respuesta más correcta.

Hubiera sido mucho más útil si hubiera capturado el código de estado que se envió en lugar de simplemente enumerar dos que no se enviaron

En cualquier caso, lo que dice el servidor es que debemos usar HTTPS.


Entonces, ¿qué necesitarías hacer para conectarte al servidor a través de HTTPS?

En un nivel básico, HTTPS simplemente significa hablar HTTP a través de una conexión segura con TLS (o previamente, SSL), en lugar de hacerlo a través de un socket TCP simple.

Su CC3100 admite TLS y SSL , y hay información mínima sobre cómo modificar uno de los ejemplos de cliente HTTP del SDK para realizar una conexión HTTPS haciendo un canal seguro, disponible en http://processors.wiki.ti.com/index.php / CC3100_HTTP_Client

Sin embargo, en el caso de requestb.inesto bien puede no ser suficiente.

Si s_clienttuviera que canalizar una solicitud GET muy simple en el comando de openssl (o hacer lo mismo en el CC3100)

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

(el sleepes hacer que openssl espere una respuesta en lugar de colgar al final de la entrada)

Tendría un error extraño:

Rutinas SSL: SSL23_GET_SERVER_HELLO: error de apretón de manos de alerta sslv3

Es posible que esto tenga algo que ver con las versiones SSL vs. TLS, pero en realidad es porque requestb.inrequiere algo llamado Indicación de nombre del servidor (Wikipedia) . Esto significa que debe decirle a la pila SSL que le diga al servidor en qué nombre de servidor debe autenticarse.

Continuando con las demostraciones de la línea de comandos, simplemente agregaríamos un -servernameargumento:

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

Si esto se hace con el hash de URL de una instancia requestb.in válida, produce un resultado y es visible en el panel de registro del navegador que lo creó.


Implementación de la Indicación del nombre del servidor (SNI) en el CC3xxx

Hay algunas publicaciones en el foro que sugieren que la implementación de TLS en CC3xxx no ha admitido SNI y que no hay planes concretos para agregar esto; sin embargo, puede verificar si ese sigue siendo el caso.

Pero es importante recordar que hay un árbol de capas de red involucradas:

WiFi
  IP packets
    TCP session
      TLS session
        HTTP protocol

Dado que el CC3100 le permite hablar TCP (y de hecho lo estaba haciendo en su código existente), es libre de "traer su propia" implementación de TLS que tiene soporte SNI. Por ejemplo, esta publicación de blog discute cómo portar la biblioteca mbed TLS (anteriormente PolarSSL) al CC3xxx y menciona SNI como capacidad.

TL; DR

requestb.ines un objetivo desafiante ya que requiere que hable HTTP en una sesión protegida con TLS e implementando la Indicación de nombre del servidor . Si hablar con este host no es parte de su proyecto final, puede que le resulte mejor simplemente pasar a los hosts que sí lo están; aquellos destinados a ser utilizados con clientes integrados mínimos en dispositivos IoT podrían configurarse para facilitar las cosas un poco. sin usar SNI.

También será mucho más eficiente si tiene el hábito de capturar los detalles de los problemas que encuentra: el desarrollo integrado siempre es un desafío para la depuración, y mientras menos información sobre las fallas que capture a través de un registro o un depurador, más tiempo pase adivinando .

Chris Stratton
fuente
Parece una buena respuesta, pero está más allá de mi comprensión. Espero alcanzar este nivel de conocimiento profundo en el futuro cercano. Pero muchas gracias por la respuesta.
user8055
1
El requisito de SNI realmente lo hace complicado: mi recomendación sería omitir requestb.in, concentrarse en los requisitos de lo que sea que realmente esté tratando de hablar en su proyecto real y, si es necesario, encontrar un servicio de simulación que sea más similar a ese requisito
Chris Stratton
Ahora, al leer esto y después de eliminar dos de mis esfuerzos competitivos, sugiero lo mismo, hacer algo más productivo. Y acepta el esfuerzo de Chris.
mico
1

Es muy probable que tanto openweathermap.org como www.mocky.io sean compatibles con http o el puerto 80. A continuación hay algunas pistas.

openweathermap.org

Openweathermap

openweathermap-url

www.mocky.io

de mal gusto

mocky-url

Parece que requestb.in solo admite HTTPS o el puerto 443.

requestb.in

requestb

requestb-url

Esto podría explicar el problema. A continuación hay algunas referencias que pueden ayudar.

En la hoja de datos CC3100 no hay referencias a CC3100 que trabaje con HTTPS. Todas las referencias son solo a HTTP. Esto probablemente explica mejor el problema. Adjunte a continuación una excepción de la hoja de datos.

CC3100 - Excepciones de la hoja de datos

Parece que según la hoja de datos CC3120 es compatible con HTTPS. Adjunte a continuación es excepto de la hoja de datos. Hay pocas referencias a HTTPS.

CC3100 - Excepciones de la hoja de datos

El camino más probable es reemplazar el CC3100 con CC3120.

Referencias

Mahendra Gunawardena
fuente
1
Después de numerosas ediciones introducir errores y luego corregirlos, esto podría ahora estar acercándose a ser una respuesta real. Pero realmente todavía necesita reescribirlo: si su tesis es que un sitio admite http y el otro solo https, simplemente dígalo por adelantado.
Chris Stratton
2
Y su análisis del CC3100 y la recomendación de reemplazo sigue siendo completamente erróneo. Dice explícitamente que es compatible con TLS / SSL, mientras intenta argumentar que no lo hace mirando erróneamente su capacidad de servidor web, cuando la pregunta no tiene nada que ver con ser un servidor. La pregunta en realidad no es usar una biblioteca HTTP en absoluto, sino hacerlo manualmente sobre un socket TCP. Para contactar a un servidor HTTPS, necesitaría realizar operaciones similares sobre una conexión SSL.
Chris Stratton