Find Client IP address --Adafruit CC3000 Library

Using these modifications; it is returning the client ip address every time.

"This function is not built-in so you'll have to modify the library slightly. This is one way to do it, I think:"

Tisteandii 

Navigate to the class Adafruit_CC3000_ClientRef in the file Adafruit_CC3000_Server.h. In the class definition, just before the private methods and attributes are defined, you will add a new public attribute as follows:

uint8_t ip_addr[4];  // assuming a typical IPv4 address
It will hold the IP address of each ClientRef instance as the connection is accepted.
Go to Adafruit_CC3000_Server::acceptNewConnections() near the end of Adafruit_CC3000_Server.cpp. A few lines will be added to get the IP address from the CC3000 and store it temporarily in the appropriate struct:
static sockaddr tSocketClientAddr;  // file scope
static socklen_t addr_len;

// Accept new connections and update the connected clients.
bool Adafruit_CC3000_Server::acceptNewConnections() {
  bool newClientCreated = false;
  // For any unconnected client, see if new connections are pending and accept
  // them as a new client.
  for (int i = 0; i < MAX_SERVER_CLIENTS; ++i) {
    if (!_clients[i].connected()) {
      // Note: Because the non-blocking option was set for the listening
      // socket this call will not block and instead return SOC_IN_PROGRESS (-2) 
      // if there are no pending client connections. Also, the address of the 
      // connected client is not needed, so those parameters are set to NULL.
      cc3k_int_poll();
      addr_len = sizeof(tSocketClientAddr);
      int soc = accept(_listenSocket, &tSocketClientAddr, &addr_len);
      if (soc > -1) {
        _clients[i] = Adafruit_CC3000_Client(soc);
        newClientCreated = true;
      }
      // else either there were no sockets to accept or an error occured.
    }
  }
  return newClientCreated;
}


You'll also edit the getClientRef() method in Adafruit_CC3000_Server.cpp:

Adafruit_CC3000_ClientRef Adafruit_CC3000_Server::getClientRef(int8_t clientIndex) {
  if (clientIndex != -1) {   
  // for client ip address to work correctly.
    Adafruit_CC3000_ClientRef newClient =  Adafruit_CC3000_ClientRef(&_clients[clientIndex]);
    // at least 2 (family) + 2 (port) + 4 (ip_addr) bytes expected
    // also check if address is standard ipv4
    if ((addr_len >= 8) && (tSocketClientAddr.sa_family == AF_INET)){
       // copy address into array; in network byte order  
       memcpy(newClient.ip_addr, &(tSocketClientAddr.sa_data[2]), 4);
    }
    return newClient;
  }

  // Couldn't find a client ready to read, so return a client that is not 
  // connected to signal no clients are available for reading (convention
  // used by the Ethernet library).
  return Adafruit_CC3000_ClientRef(NULL);
}

_____________________________________________________________________________
Followed Tisteandii’s modications; except for one small change:

Use this edit of the getClientRef() method in Adafruit_CC3000_Server.cpp:

Adafruit_CC3000_ClientRef Adafruit_CC3000_Server::getClientRef(int8_t clientIndex) {
  if (clientIndex = 2) {   /////// Here is the change, “clientIndex = 2”  ///////////////////// 
  //////   for Cient IP address to be returned every time.   ///////////////////////////////
    Adafruit_CC3000_ClientRef newClient =  Adafruit_CC3000_ClientRef(&_clients[clientIndex]);
    // at least 2 (family) + 2 (port) + 4 (ip_addr) bytes expected
    // also check if address is standard ipv4
    if ((addr_len >= 8) && (tSocketClientAddr.sa_family == AF_INET)){
       // copy address into array; in network byte order  
       memcpy(newClient.ip_addr, &(tSocketClientAddr.sa_data[2]), 4);
    }
    return newClient;
  }

  // Couldn't find a client ready to read, so return a client that is not 
  // connected to signal no clients are available for reading (convention
  // used by the Ethernet library).
  return Adafruit_CC3000_ClientRef(NULL);
}


Now the address is stored in an array for each client and can be accessed from your sketch. For example, you can access the address in your sketch like this:

In the loop() of the the HttpServer example:
 Adafruit_CC3000_ClientRef client = httpServer.available();
 if (client) {
   char ip2String[16] = "";   //client.ip_addr = clientIP[16]
    snprintf(ip2String, 16, "%d.%d.%d.%d", client.ip_addr[3], client.ip_addr[2], client.ip_addr[1],       client.ip_addr[0]);
    
    Serial.print("Client IP:  ");  
    Serial.println(ip2String);   }
   
   // other code
 }

Why does “clientIndex != -1” not return the Client IP address every time
and “clientIndex = 2” returns client IP address every time?

Does this change have a negative impact on the library?

Adafruit CC3000 Library --Github

Attached files: two modified library files with (clientIndex = 2) and a HTTPServer-Test sketch based on the library example from the linked library.

CC3000.zip (9.38 KB)