Ethernet lib client.flush() Bug?

Hello there,

I currently try to write a little IRC Bot with the Arduino and the Ethernet Shield. I ran into a problem and I think that it is maybe a bug in the Ethernet lib. I am not a really good C/C++ coder and also absolutly new to hardware and micros.

The code isn´t very well designed (not optimized) at the moment, because it´s just a prototype I wrote in about 3h.

Sketch:

#include <MsTimer2.h>
#include <Ethernet.h>
#include <Client.h>

// Network
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 111 };
byte ircserver[] = { 207, 182, 240, 74 };

// IRC
char hostname[] = "irc.freenode.net";
char nickname[] = "stahlArduinoBot";
char ident[] = "arduinoBot";
char channel[] = "#stahlstift";

// Don´t touch anything!
Client client(ircserver, 6667);
const int bufferSize = 1024;
char buffer[bufferSize]; // Buffer für die Timerfunktion
int pingDelay = 100; // Wird für einen sicheren Anmeldeprozess benötigt!



// NTC
int tempPin = 0;
float voltbit = 0.0048828125f;


boolean authIRC() {
  int buffSize = 512;
  char authBuffer[buffSize]; // lokaler Buffer, da dieser nur einmal benötigt wird
  int i = 0;
  boolean initData = false;
  boolean authInfoSended = false;
  long authTimeout = 60000; // 60 Sekunden
  long startTime = millis();
  
  while(!initData) { // Ich muss sicher sein, das Daten eingetroffen sind    
    if(client.available()) {
      initData = true; // Hier weiß ich nun das Daten vorhanden sind und kann die WhileSchleife später beenden
      
      while (client.available()) {        
        char c = client.read();
        if (c == 13) {
          authBuffer[i] = 0;
          i = 0;           
          if (authInfoSended) {          
            // TODO: Registrierter Benutzername
            if (strstr(authBuffer, "Welcome to the freenode IRC Network") != NULL) {
              return true;
            }
            
            // Timeout damit wir uns nicht in einer Endlosschleife befinden, falls mit der Anmeldung was schief ging
            if ((millis() - startTime) > authTimeout) {
              Serial.println("Timeout!");
              return false;
            }
          } else {
            // Anmelden
            client.print("NICK ");
            client.println(nickname);
            
            client.print("USER ");
            client.print(ident);
            client.print(" ");
            client.print(hostname);
            client.println(" bla :arduino");
            
            authInfoSended = true;
            startTime = millis(); // Ab hier beginnt die Timeoutzählung
          }
        } else {
          authBuffer[i] = c;
          i++;
        }
        delay(pingDelay);
      }
    }
  }
  return false;
}

void checkMsg() {
  int i = 0;
  
  // DEBUG 1 Check
  if(client.available()) {
    Serial.println("not empty!");
  } else {
    Serial.println("empty!"); // it will print empty
  }
  
  // DEBUG 2 Check
  if(client.available()) {
    Serial.println("not empty!"); // it will print not empty!
  } else {
    Serial.println("empty!"); 
  }
  
  // DEBUG 3 Check
  if(client.available()) {
    Serial.println("not empty!"); // it will print not empty!
  } else {
    Serial.println("empty!"); 
  }
  
  // DEBUG 4 Check
  if(client.available()) {
    Serial.println("not empty!"); // it will print not empty!
  } else {
    Serial.println("empty!"); 
  }
  
  while(client.available()) {
    char c = client.read();
    if (c == 13) {
      buffer[i] = 0;
      i = 0;
      
      // Auf Server PING antworten
      if (strstr(buffer, "PING ") != NULL) {
        if (buffer[0] == 'P' && buffer[1] == 'I' && buffer[2] == 'N' && buffer[3] == 'G') {
          client.println("PONG"); 
        }
      }

      // Nachricht aus dem aktuellen Channel?
      if (strstr(buffer, channel) != NULL) {
        // Auf !roomtemp im aktuellen Channel reagieren
        if (strstr(buffer, "!roomtemp")) {
          // NTC
          float tmp = analogRead(tempPin) * voltbit;
          int r1 = (5 * 1000 / (5-tmp)) - 1000;
  
          client.print("PRIVMSG ");
          client.print(channel);
          client.print(" :In stahlstift´s room is currently ");
          client.print(r1);
          client.println(" (NTC ohm - translation table will be there in a feature version). Thanks for your interest! (simpleIRC v0.1 by stahlstift on Arduino Duemilanove)"); 
        }
      }
      
      Serial.print("checkMsg(): ");
      Serial.println(buffer);
    } else {
      buffer[i] = c;
      i++;
    }
  }
}

void joinRoom() {
  client.print("JOIN ");
  client.println(channel);
}

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  delay(2000); // EthernetShield etwas Zeit lassen
  if (client.connect()) {
    if(!authIRC()) {
      Serial.println("Authentifizierung fehlgeschlagen!");
    } else {
      Serial.println("Authentifizierung erfolgreich");
          
      joinRoom();
           
      client.flush(); // Message of the Day, Raumliste etc, den ganzen Mist löschen, den wollen wir nicht einlesen :)
           
      delay(1000); // Noch ne Sekunde warten bevor es los geht :)
     
      // Der Timer ruft jede Sekunde "checkMsg" auf welche Kommandos entgegen nimmt
      MsTimer2::set(1000, checkMsg);
      MsTimer2::start();
    }
  } else {
    Serial.println("Verbindung fehlgeschlagen!");
  }
}

void loop() { 
  if (!client.connected()) {
    Serial.println("Verbindung verloren");
    client.flush();
    client.stop();
    
    while(true); // Damit Verbindung verloren nicht gespammed wird!
  }
}

The problem is in "void checkMsg() {".
Because freenode spams me with motd and channel list I want to do client.flush() and so I do. But client.available() is in the first statment empty, in the second not and in the while-loop also not.

Maybe it´s a failure from me, so...

I am using the Arduino 2009 and Arduino 0017.

Greetings!

By the way,
I startet a project on googlecode for the IRC Client.
http://code.google.com/p/arduinoirc/

There is nothing there at the moment, after fixing the bug I got described above, I try to start a lib for easy using.

The code above is GPL3! So be nice!

I completely redesigned the Code.

Now it doesn´t depend any more on client.flush() and it is a bit more "event driven" and now also able to join multiple Channels and listen in them.

  • ~700bytes smaller :slight_smile:

Code will follow the next days on the google project site.

stahlstift -

I have used flush() and it works as advertised. It isn't guaranteed to work in your case because the data may not be in the buffer yet for the function to flush.

You may need to design a more suitable function like "ignoreIRCStuffIDontWantToDealWith" to accomplish what you are aiming for.