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.
fuente
Respuestas:
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.in
servicio 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:
Veamos qué pasa:
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.in
esto bien puede no ser suficiente.Si
s_client
tuviera que canalizar una solicitud GET muy simple en el comando de openssl (o hacer lo mismo en el CC3100)(el
sleep
es hacer que openssl espere una respuesta en lugar de colgar al final de la entrada)Tendría un error extraño:
Es posible que esto tenga algo que ver con las versiones SSL vs. TLS, pero en realidad es porque
requestb.in
requiere 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
-servername
argumento: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:
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.in
es 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 .
fuente
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
www.mocky.io
Parece que requestb.in solo admite HTTPS o el puerto 443.
requestb.in
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.
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.
El camino más probable es reemplazar el CC3100 con CC3120.
Referencias
fuente