bjoern avatar bjoern committed acc28fc

bug fix: truncate rx packets too long for buffer so we don't overflow; return negative value if we truncated

Comments (0)

Files changed (3)

libraries/Ethernet/UdpRaw.cpp

 	// send packet
 	return sendto(_sock,(const uint8_t *)str,len,ip,port);
 }
-/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. */
+/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. 
+ * returned value includes 8 byte UDP header!*/
 int UdpRawClass::available() {
 	return getSn_RX_RSR(_sock);
 }
 
 
-/* Read a received packet into buffer buf (whis is of maximum length len); */
+/* Read a received packet into buffer buf (which is of maximum length len); */
 /* store calling ip and port as well. Call available() to make sure data is ready first. */
 /* NOTE: I don't believe len is ever checked in implementation of recvfrom(),*/
-/*       so it's easy to overflow buf. */
-uint16_t UdpRawClass::readPacket(uint8_t * buf, uint16_t len, uint8_t *ip, uint16_t *port) {
-	return recvfrom(_sock,buf,len,ip,port);
+/*       so it's easy to overflow buffer. so we check and truncate. */
+/* returns number of bytes read, or negative number of bytes we would have needed if we truncated */
+int UdpRawClass::readPacket(uint8_t * buf, uint16_t bufLen, uint8_t *ip, uint16_t *port) {
+	int packetLen = available()-8; //skip UDP header;
+	if(packetLen < 0 ) return 0; // no real data here	
+	if(packetLen > (int)bufLen) {
+		//packet is too large - truncate
+		//HACK - hand-parse the UDP packet using TCP recv method
+		uint8_t tmpBuf[8];
+		int i;
+		//read 8 header bytes and get IP and port from it
+		recv(_sock,tmpBuf,8);
+		ip[0] = tmpBuf[0];
+		ip[1] = tmpBuf[1];
+		ip[2] = tmpBuf[2];
+		ip[3] = tmpBuf[3];
+		*port = tmpBuf[4];
+		*port = (*port << 8) + tmpBuf[5];
+		
+		//now copy first (bufLen) bytes into buf		
+		for(i=0;i<(int)bufLen;i++) {
+			recv(_sock,tmpBuf,1);
+			buf[i]=tmpBuf[0];
+		}
+		
+		//and just read the rest byte by byte and throw it away
+		while(available()) {
+			recv(_sock,tmpBuf,1);
+		}
+		
+		return (-1*packetLen);
+		
+		//ALTERNATIVE: requires stdlib - takes a bunch of space
+		/*//create new buffer and read everything into it
+		uint8_t * tmpBuf = (uint8_t *)malloc(packetLen);
+		recvfrom(_sock,tmpBuf,packetLen,ip,port);
+		if(!tmpBuf) return 0; //couldn't allocate
+		// copy first bufLen bytes
+		for(unsigned int i=0; i<bufLen; i++) {
+			buf[i]=tmpBuf[i];
+		}
+		//free temp buffer
+		free(tmpBuf);
+		*/
+		
+		
+	} 
+	return recvfrom(_sock,buf,bufLen,ip,port);
 }
 
 /* Read a received packet, throw away peer's ip and port.  See note above. */
-uint16_t UdpRawClass::readPacket(uint8_t * buf, uint16_t len) {
+int UdpRawClass::readPacket(uint8_t * buf, uint16_t len) {
 	uint8_t ip[4];
 	uint16_t port[1];
 	return recvfrom(_sock,buf,len,ip,port);

libraries/Ethernet/UdpRaw.h

 	// C-style buffer-oriented functions
 	uint16_t sendPacket(uint8_t *, uint16_t, uint8_t *, uint16_t); //send a packet to specified peer 
 	uint16_t sendPacket(const char[], uint8_t *, uint16_t);  //send a string as a packet to specified peer
-	uint16_t readPacket(uint8_t *, uint16_t);		// read a received packet 
-	uint16_t readPacket(uint8_t *, uint16_t, uint8_t *, uint16_t *);		// read a received packet, also return sender's ip and port 	
+	int readPacket(uint8_t *, uint16_t);		// read a received packet 
+	int readPacket(uint8_t *, uint16_t, uint8_t *, uint16_t *);		// read a received packet, also return sender's ip and port 	
 };
 
 extern UdpRawClass UdpRaw;

libraries/Ethernet/examples/UdpReceiveRaw/UdpReceiveRaw.pde

   // if there's data available, read a packet
   if(UdpRaw.available()) {
     packetSize = UdpRaw.readPacket(packetBuffer,MAX_SIZE,remoteIp,(uint16_t *)&remotePort);
-    if(packetSize <= MAX_SIZE) {
       
       Serial.print("Received packet of size ");
-      Serial.println(packetSize);
-      
+      Serial.println(abs(packetSize));
+
       Serial.print("From IP ");
       for(i=0; i<3; i++) {
         Serial.print(remoteIp[i],DEC);
       Serial.print(" Port ");
       Serial.println(remotePort); 
       
+      if(packetSize < 0) {
+        // if return value <0 the packet was truncated to fit into our buffer
+        Serial.print("ERROR: Packet was truncated from ");
+        Serial.print(packetSize*-1);
+        Serial.print(" to ");
+        Serial.print(MAX_SIZE);
+        Serial.println(" bytes.");
+      }
+      
       Serial.println("Contents:");
-      for(i=0; i<packetSize; i++) {
+      for(i=0; i<min(MAX_SIZE,abs(packetSize)); i++) {
         Serial.print(packetBuffer[i],BYTE);
       }
       Serial.println("");
       
-    } else {
-      // PANIC - packet too long!
-      // we've already clobbered mem past our buffer boundary
-    }
   }
   //wait a bit
   delay(10);  
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.