検死が示した:ギャップは責任がある





私たちはサウスカロライナ州チャールストンの小さなスタートアップです。 テキストメッセージで注文を受け付け、レストランで直接印刷します。



ほぼ1年前にチャールストンでeatabit.comを立ち上げました。 この間、当社のAPIは顧客からの9300件以上の食品注文を印刷しました。これらはレストラン、スタジアム、ゴルフコースです。 モバイル通信での作業は簡単ではありません-特に試合中のスタジアムなど、ネットワーク負荷が増加しているエリアでは、システムが信号品質の低下や中断などの状況を監視します。







水曜日から木曜日までの夜は、通常、火曜日から水曜日までの夜の最小負荷での2番目の夜です。 したがって、モニターが真夜中頃に警告の波を出し始めたとき、私たちはそれが事故であると思いました。 残念ながら、それは彼女ではありませんでした...







まあ、ギャップがあります。 時々、新しい従業員がレストランに来て、プリンターのプラグをコンセントから抜いて「夜に電源を切る」ことがありますが、今回はすべてのプリンターで問題が発生しました。 当社のSIMカードプロバイダーであるT-Mobileは、時々ベースステーションを再起動し、全地域のプリンターは60〜90秒間オフになりますが、チャールストンのすべてのプリンターはオフになりません。



OK、プリンタ自体のログに関する問題を解決し始めます...







プリンターはArduino Megaチップセット(ATMega 1280)に基づいているため、Arduino IDEを起動してシステムの状態を調査します。



SYSTEM::State: Polling. SYSTEM::Polling: SYSTEM::State: Idle. WEB::Starting Poll! WEB::Poll Request: GET /v1/printer/***************/orders.txt HTTP/1.1 HOST: api.eatabit.io Authorization: Basic *********************************************** User-Agent: Eatabit_Device/0.5.1 Content-Length: 67 Content-Type: application/x-www-form-urlencoded Accept: */* Connection: close pickup_minutes=15&delivery_minutes=30&paper_status=1&cell_signal=15 WEB::Request Length: 351 WEB::Request Page Status: 0 AT+CSQ +CSQ: 20,0 OK GSM::CSQ:20 AT#SKTD=0,80,"api.eatabit.io",0,0 CONNECT GSM::SEND: Socket Enabled GSM::RCXV: Header Sent HTTP/1.1 505 HTTP Version Not Supported Connection: close Server: Cowboy Date: Wec, 21 Oct 2014 19:22:32 GMT Content-Length: 0 … ? HTTP/1.1 505 HTTP Version Not Supported
      
      





9か月間、このArduinoファームウェアを問題なく使用していましたが、今はどうですか? 突然? 真夜中に? 街中? おかしい...それは何ですか?



 Server: Cowboy     Heroku,   - Unicorn.      «»,     ? ,  cURL         : curl "http://api.eatabit.io/v1/printer/***************/orders.text?pickup_minutes=30&delivery_minutes=90&state=ok" \ > -X GET \ > -u ***************:****************** \ > -v \ > --user-agent "Eatabit_Device/0.5.1" * Hostname was NOT found in DNS cache * Trying 54.225.219.28... * Connected to api.eatabit.io (54.225.219.28) port 80 (#0) * Server auth using Basic with user '***************' > GET /v1/printer/***************/orders.text?pickup_minutes=30&delivery_minutes=90&state=ok HTTP/1.1 > Authorization: Basic ***********************************************< > User-Agent: Eatabit_Device/0.5.1 > Host: api.eatabit.io > Accept: */* > < HTTP/1.1 200 OK * Server Cowboy is not blacklisted < Server: Cowboy < Connection: keep-alive < Date: Mon, 21 Oct 2014 01:25:11 GMT < Status: 200 OK < Content-Type: text/plain < Content-Length: 7 < Etag: "26f14889eed7cc4b3b78cc667c7ee9eb" < Cache-Control: max-age=0, private, must-revalidate < X-Request-Id: dce1a529-fff1-4222-b997-21d7c074487f < X-Runtime: 1.135825 < Via: 1.1 vegur < * Connection #0 to host api.eatabit.io left intact {0:0}{}%
      
      





すべてがうまくいくようです... WTF?! リクエストの残りが作成されるArduinoファームウェアを確認します。



 if(isCommsBufferAvailable()) { //make the chunk uint8_t dataLength = snprintf(( char * )tempString, sizeof(tempString), "pickup_minutes=%hhu&delivery_minutes=%hhu&paper_status=%hhu&cell_signal=%hhu", settings.getPickupMinutes(), settings.getDeliveryMinutes(), printer.hasPaper(), gsmModem.getSignal() ); uint8_t contentLength[4]; dataLength = strlen( ( char * ) tempString); itoa(dataLength,( char * ) contentLength, 10); IF_DEBUG(DEBUG_INFO) PORT_DEBUG.println("WEB::Starting Poll!"); reserveCommsBuffer(); //build the header for the POLL request strcpy( ( char * ) commsOrderBuffer, "GET /v1/printer/"); strcat( ( char * ) commsOrderBuffer, ( char * ) settings.getIMEI()); strcat( ( char * ) commsOrderBuffer, "/orders.txt HTTP/1.1\r\n"); strcat( ( char * ) commsOrderBuffer, "HOST: "); strcat( ( char * ) commsOrderBuffer, SERVER_NAME); strcat( ( char * ) commsOrderBuffer, "\r\n"); strcat( ( char * ) commsOrderBuffer, "Authorization: Basic "); strcat( ( char * ) commsOrderBuffer, ( char * ) settings.getAccess()); strcat( ( char * ) commsOrderBuffer, "\r\n"); strcat( ( char * ) commsOrderBuffer, "User-Agent: Eatabit_Device/"); strcat( ( char * ) commsOrderBuffer, SOFTWARE_VER); strcat( ( char * ) commsOrderBuffer, "\r\n"); strcat( ( char * ) commsOrderBuffer, "Content-Length: "); strcat( ( char * ) commsOrderBuffer, ( char * ) contentLength); strcat( ( char * ) commsOrderBuffer, "\r\n"); strcat( ( char * ) commsOrderBuffer, "Content-Type: application/x-www-form-urlencoded\r\n"); strcat( ( char * ) commsOrderBuffer, "Accept: */*\r\n"); strcat( ( char * ) commsOrderBuffer, "Connection: close\r\n"); strcat( ( char * ) commsOrderBuffer, "\r\n"); strcat( ( char * ) commsOrderBuffer, ( char * ) tempString); IF_DEBUG(DEBUG_BUFFERS) { temp1 = strlen((char*) commsOrderBuffer); PORT_DEBUG.println("WEB::Poll Request: "); PORT_DEBUG.println((char*)commsOrderBuffer); PORT_DEBUG.print("WEB::Request Length: "); PORT_DEBUG.println(temp1); } temp1 = gsmModem.requestPage( (uint8_t *) SERVER_NAME, PORT_NUMBER, commsOrderBuffer, commsOrderBuffer, ORDER_QUE_MAX_ORDER_SIZE); IF_DEBUG(DEBUG_BUFFERS) { PORT_DEBUG.print("WEB::Request Page Status: "); PORT_DEBUG.println(temp1); } //go wait for the response _state = WEB_WAIT_POLL; } else { IF_DEBUG(DEBUG_BUFFERS) PORT_DEBUG.println("WEB::Buffer In use!"); } break;
      
      





待って それは本当に... URLとHTTPバージョンの文字列の違いがあります-余分なスペース:



 strcat( ( char * ) commsOrderBuffer, "/orders.txt HTTP/1.1\r\n");
      
      





カウボーイは、URLの末尾に余分なスペースを追加して、分析中のパラメーター間で複数のスペース文字を処理できないという理論をテストしてみましょう。



 curl "http://api.eatabit.io/v1/printer/***************/orders.text?pickup_minutes=30&delivery_minutes=90&state=ok " \ -X GET \ -u ***************:****************** \ -v \ --user-agent "Eatabit_Device/0.5.1" * Hostname was NOT found in DNS cache * Trying 54.225.123.174... * Connected to api.eatabit.io (54.225.123.174) port 80 (#0) * Server auth using Basic with user '***************' > GET /v1/printer/***************/orders.text?pickup_minutes=30&delivery_minutes=90&state=ok HTTP/1.1 > Authorization: Basic ***********************************************<< > User-Agent: Eatabit_Device/0.5.1 > Host: api.eatabit.io > Accept: */* > < HTTP/1.1 505 HTTP Version Not Supported < Connection: close * Server Cowboy is not blacklisted < Server: Cowboy < Date: Mon, 27 Oct 2014 02:03:25 GMT < Content-Length: 0 < * Closing connection 0
      
      





あります!







そのため、コード内に(余分なスペースの形で)バグが検出されました。 しかし、なぜすべてが突然始まったのでしょうか? 結局のところ、このバグは動作中のファームウェアで少なくとも9か月間存在していました...







何が変わった?



 Server: Cowboy
      
      





カウボーイ。 誰がこのサーバーを立ち上げたのでしょうか? Heroku? AWS? Googleでの表面検索では、この質問に対する明確な答えは得られませんでした。 あちこちにリクエストを送信しましたが、まだ回答を待っています。 連絡を取り合いましょう。



All Articles