// Equivalent to Arduino Stream find() function, but with search string in // flash/PROGMEM rather than RAM-resident. Returns true if string found // (any further pending input remains in stream), false if timeout occurs. // Can optionally pass NULL (or no argument) to read/purge the OK+CR/LF // returned by most AT commands. The ipd flag indicates this call follows // a CIPSEND request and might be broken into multiple sections with +IPD // delimiters, which must be parsed and handled (as the search string may // cross these delimiters and/or contain \r or \n itself). boolean Adafruit_ESP8266::find(Fstr *str, boolean ipd) { uint8_t stringLength, matchedLength = 0; int c; boolean found = false; uint32_t t, save; uint16_t bytesToGo = 0; if(ipd) { // IPD stream stalls really long occasionally, what gives? save = receiveTimeout; setTimeouts(ipdTimeout); } if(str == NULL) str = F("OK\r\n"); stringLength = strlen_P((Pchr *)str); if(debug && writing) { debug->print(F("<--- '")); writing = false; } for(t = millis();;) { if(ipd && !bytesToGo) { // Expecting next IPD marker? if(find(F("+IPD,"))) { // Find marker in stream for(;;) { if((c = stream->read()) > 0) { // Read subsequent chars... if(debug) debug->write(c); if(c == ':') break; // ...until delimiter. bytesToGo = (bytesToGo * 10) + (c - '0'); // Keep count t = millis(); // Timeout resets w/each byte received } else if(c < 0) { // No data on stream, check for timeout if((millis() - t) > receiveTimeout) goto bail; } else goto bail; // EOD on stream } } else break; // OK (EOD) or ERROR } if((c = stream->read()) > 0) { // Character received? if(debug) debug->write(c); // Copy to debug stream bytesToGo--; if(c == pgm_read_byte((Pchr *)str + matchedLength)) { // Match next byte? if(++matchedLength == stringLength) { // Matched whole string? found = true; // Winner! break; } } else { // Character mismatch; reset match pointer+counter matchedLength = 0; } t = millis(); // Timeout resets w/each byte received } else if(c < 0) { // No data on stream, check for timeout if((millis() - t) > receiveTimeout) break; // You lose, good day sir } else break; // End-of-data on stream } bail: // Sorry, dreaded goto. Because nested loops. if(debug) debug->println('\''); if(ipd) setTimeouts(save); return found; }
void TcpSocket::connect(const IAddress &addr) { const InetAddress *iaddr = dynamic_cast<const InetAddress *>(&addr); if (iaddr == NULL) throw cvgException("[TcpSocket] The address passed to connect() is not of type InetAddress"); disconnect(); setConnectionState(CONNECTING); try { descriptor = socket(AF_INET, SOCK_STREAM, 0); if (descriptor == -1) throw cvgException("[TcpSocket] Unable to create socket descriptor"); // Set linger time: time before the socket is reset on a connection termination linger lingerData; lingerData.l_onoff = 1; lingerData.l_linger = CVG_LITERAL_INT(TCPSOCKET_DEFAULT_LINGER_SECONDS); setsockopt(descriptor, SOL_SOCKET, SO_LINGER, &lingerData, sizeof(linger)); // Set socket timeouts setTimeouts(readTimeout, writeTimeout); // Disable Nagle's algorithm int flag = 1; if (setsockopt(descriptor, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)) == -1) throw cvgException("[TcpSocket] Cannot disable Nagle algorithm"); /* int sockBuffSize = 3 * 8000; //1e6 * 0.4 / 8; if (setsockopt(descriptor, SOL_SOCKET, SO_SNDBUF, &sockBuffSize, sizeof(int)) == -1) throw cvgException("[TcpSocket] Cannot set TCP send window size"); if (setsockopt(descriptor, SOL_SOCKET, SO_RCVBUF, &sockBuffSize, sizeof(int)) == -1) throw cvgException("[TcpSocket] Cannot set TCP reception window size"); */ // Connect to server if (::connect(descriptor, (sockaddr *)iaddr->toAddr(), sizeof(sockaddr_in)) != 0) throw cvgException("[TcpSocket] Cannot connect to server"); setConnectionState(CONNECTED); } catch (cvgException &e) { disconnect(); setConnectionState(FAULT); throw e; } }
// Constructor Adafruit_ESP8266::Adafruit_ESP8266(Stream *s, Stream *d, int8_t r) : stream(s), debug(d), reset_pin(r), host(NULL), writing(false) { setTimeouts(); };
// // MFUNCTION: CPlayer::waitPdu // // PURPOSE: Wait for an incoming pdu for the // specified timeout. // If the incoming pdu has a sequence number different // from what is expected, the pdu is ignored. // // RETURN: // If a pdu arrives in time, return 0, otherwise // return Pdu_Wait_Timeout. // int CPlayer::waitPdu(Cpdu** ppPdu, DWORD timeOut, u_int16_t sequenceNumber) { int rc = 0; if (disconnected_) return CPlayer::Pdu_Wait_Timeout; long start = 0, elapsed = 0; time(&start); // note: timeOut is in milliseconds while // elapsed is in seconds while (timeOut > (1000 * elapsed)) { if (pduEvent_.lock(timeOut - (1000 * elapsed))) { // When we get here we have an incoming PDU pduEvent_.resetEvent(); // Get all pdus from queue, consider the one // with correct sequence number while (Cpdu* pdu = getFromQueue()) { // if sequence numbers don't match, ignore // the pdu and wait for next one to arrive if (checkSequenceNumber(pdu, sequenceNumber)) { // XXX Tournament: pdu received, reset timeouts setTimeouts(0); *ppPdu = pdu; return 0; // OK! } else { // pdu had wrong sequence number - it is // and old pdu and is ignored delete pdu; // The loop will check for more pdus and // will resume waiting if necessary } } long now = 0; time(&now); elapsed += (now - start); } else { // Wait timed out, will exit loop elapsed = (1000 * timeOut); } } // this is ok, player did not respond within timeout printf("CPlayer::waitPdu: timed out (%s)\n", getUsername()); rc = CPlayer::Pdu_Wait_Timeout; // XXX Tournament if (CTournament::Inst()->isTournament()) { CpduPing p; if (p.sendPing(this) == -1) { char buf[200]; sprintf(buf, "Player %s sendPing==-1\n", getUsername()); Sys_LogError(buf); setSendError(true); } setTimeouts(getTimeouts() + 1); if (getTimeouts() >= MAX_TIMEOUTS) { // Player is not responding - set network error flag char buf[200]; sprintf(buf, "Player %s (%d) times out\n", getUsername(), getConnfd()); Sys_LogError(buf); setSendError(true); } } return rc; }