static void on_json_end() { HTTPLOG_PRINTLN(">j"); if ( IrCtrl.state != IR_WRITING ) { HTTPLOG_PRINTLN("!E5"); IR_dump(); return; } IR_xmit(); on_ir_xmit(); }
void irkit_http_loop() { #ifdef USE_INTERNET // long poll if (TIMER_FIRED(polling_timer)) { TIMER_STOP(polling_timer); if (TIMER_RUNNING(suspend_polling_timer)) { // suspend GET /m for a while if we have received a POST /messages request from client // client is in wifi, we can ignore our server for a while TIMER_START(polling_timer, SUSPEND_GET_MESSAGES_INTERVAL); } else { int8_t result = irkit_httpclient_get_messages(); if ( result < 0 ) { HTTPLOG_PRINTLN("!E3"); // maybe time cures GS? (no it doesn't, let's hardware reset, software reset doesn't work here) // don't software reset AVR, because that cuts off serial logging (for debug purpose only) wifi_hardware_reset(); } else { polling_cid = result; } } } if (TIMER_FIRED(suspend_polling_timer)) { TIMER_STOP(suspend_polling_timer); } #endif }
static int8_t on_request(int8_t cid, int8_t routeid, GSwifi::GSREQUESTSTATE state) { if ( (state == GSwifi::GSREQUESTSTATE_RECEIVED) && (! gs.validRequest()) && (! has_valid_pass) ) { HTTPLOG_PRINTLN("!E32"); gs.writeHead(cid, 400); gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); return -1; } switch (routeid) { case 0: // POST /messages return on_post_messages_request(cid, state); case 1: // POST /keys // when client requests for a new key, // we request server for one, and respond to client with the result from server return on_post_keys_request(cid, state); case 2: // GET /messages return on_get_messages_request(cid, state); case 3: // POST /wifi return on_post_wifi_request(cid, state); default: break; } return -1; }
static int8_t on_post_messages_request(int8_t cid, GSwifi::GSREQUESTSTATE state) { while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); parse_json( letter ); } if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { // should be xmitting or idle (xmit finished) if (IrCtrl.state == IR_WRITING) { HTTPLOG_PRINTLN("!E7"); // invalid json gs.writeHead(cid, 400); gs.writeEnd(); } else { gs.writeHead(cid, 200); gs.writeEnd(); } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); #ifdef USE_INTERNET TIMER_START( suspend_polling_timer, SUSPEND_GET_MESSAGES_INTERVAL ); #endif } return 0; }
static int8_t on_get_messages_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< G /m ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } switch (status_code) { case 200: while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); parse_json( letter ); } if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { // should not be WRITING here, should be XMITTING or IDLE (xmit finished) if (IrCtrl.state == IR_WRITING) { // prevent from locking in WRITING state forever IR_state( IR_IDLE ); } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); if ((polling_cid == cid) || (polling_cid == CID_UNDEFINED)) { polling_cid = CID_UNDEFINED; ring_put( &commands, COMMAND_START_POLLING ); } // if polling_cid != cid // there's already an ongoing polling request, so request again when that one finishes } break; case HTTP_STATUSCODE_CLIENT_TIMEOUT: polling_cid = CID_UNDEFINED; ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); irkit_httpclient_start_polling( 5 ); break; case HTTP_STATUSCODE_DISCONNECT: polling_cid = CID_UNDEFINED; irkit_httpclient_start_polling( 5 ); break; // heroku responds with 503 if longer than 30sec, // or when deploy occurs case 503: default: if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); irkit_httpclient_start_polling( 5 ); } break; } return 0; }
static int8_t on_post_keys_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /k ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } gs.writeHead( post_keys_cid, status_code ); switch (status_code) { case 200: while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); gs.write( letter ); } gs.writeEnd(); break; default: gs.writeEnd(); break; } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); ring_put( &commands, COMMAND_CLOSE ); if (ring_isfull( &commands )) { HTTPLOG_PRINTLN("!E8"); return -1; } ring_put( &commands, post_keys_cid ); return 0; }
static int8_t on_post_door_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /d ")); HTTPLOG_PRINTLN(status_code); gs.bufferClear(); if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } switch (status_code) { case 200: keys.setKeyValid(true); // save only independent area, since sharedbuffer might be populated by IR or so. keys.save2(); IR_state( IR_IDLE ); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); #ifdef USE_INTERNET ring_put( &commands, COMMAND_START_POLLING ); #endif on_irkit_ready(); break; #ifdef USE_INTERNET case 401: case HTTP_STATUSCODE_CLIENT_TIMEOUT: // keys have expired, we have to start listening for POST /wifi again keys.clear(); keys.save(); software_reset(); break; case 400: // must be program bug, happens when there's no hostname parameter case 408: case 503: // heroku responds with 503 if longer than 30sec default: // retry again on next loop ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); ring_put( &commands, COMMAND_POST_DOOR ); break; #endif } return 0; }
static int8_t on_post_messages_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /m ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); return 0; }
static void on_json_start() { HTTPLOG_PRINTLN("j<"); IR_state( IR_WRITING ); }
static void on_json_start() { HTTPLOG_PRINTLN("j<"); IR_state( IR_WRITING ); has_valid_pass = false; }