// 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;
}
Esempio n. 2
0
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();
};
Esempio n. 4
0
//
// 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;
}