Connecting with TCPclient code, and PING issues

I think i understand what this does… I’m going to have to brush up on classes i think! Time to put the super slow interwebs here to use and get a tutorial loaded

Where can i hide this bit of code in mine?

Any chance of one for receive too??

Hi @Hootie81

You can put this in your main sketch or another file with the circle-plus on the web IDE. You don’t need anything for receive, I think.

You can change the last line to:

myUDP iUdp;  //remove the other declaration of iUdp too!

to make porting your code easier.

I’m compiling local because the internet out here is so bad

So if i create a myUDP.h file and wack it in there and include “myUDP.h” it should do the job yeah? and in the DNS library i will change UDP iUdp; to myUDP iUdp;

so if im understanding correctly my app will call the iUdp instance of myUDP class, if the function is in myUDP it will run it (ie iUdp.write(something), if its not in there it will pass through to UDP thats in the spark_wiring_udp.h (ie iUdp.parsePacket(); )

1 Like

OK so i finally made it compile! but i keep getting an return code of 65535 any idea’s??

the return codes should be 1 or -1, -2 ,-3, -4, -5 hmmm

Hi @Hootie81

Which method is returning the funny return code? iUdp.beginPacket() or iUdp.write()?

i don’t know! this is cut and pasted bits from my code… i think its all the bits, but i don think its the problem. the libraries are here https://github.com/Hootie81/DNSClient and i cant tell which part fails…

#include "DNSClient.h"

    DNSClient dns;
    IPAddress remote_addr;
    IPAddress dnsServerIP;
    char hostname[] = "google.com";

in setup loop

dnsServerIP = (8,8,8,8);
int ret = 0;
dns.begin(dnsServerIP);
ret = dns.getHostByName(hostname, remote_addr);
    
if (ret == 1) {
   Serial.print("Remote Address: ");
   Serial.print(remote_addr);
   Serial.print(" : ");
   Serial.print(port);
      
} 
  Serial.println(ret);
    
}

I think you are running into the problem that int is 16-bits on Arduino and 32-bits on Spark. The value you are getting would be -1 on Arduino which means timeout, which makes some sense.

Reading through the code quickly, I could not spot it but…

This function:

uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)

returns a uint16_t (16-bit) and sticks in an int (32-bit) return type in gethostbyname() and looks somewhat suspect.

I added the serial prints to debug, i see receiving65335 so i dont even see the timed out… something fishy going on!

EDIT: i changed the uint16_t return type to uint32_t and it looped properly. but i get a timeout… how can i check the buffer to send? with that new class?

Ooops: Spot the bug (my added line of Debugging messed me up!)

uint32_t startTime = millis();
    Serial.print("receiving..");
    // Wait for a response packet
    while(iUdp.parsePacket() <= 0)
    {
        if((millis() - startTime) > aTimeout)
            Serial.println("timed out");
            return TIMED_OUT;
        delay(50);
    }
    Serial.print("header 0");

Braces, always braces.

2 Likes

Its a big ask i know but could someone test the header of the datagram and see whats coming out of the build request function… i dont know what happens when you stuff the millis() which is a uint32_t into a uint16_t but the first part of the datagram is a 16 bit id number

then theres the htons… which are 32bit on the spark and probably only a 16 on the arduino… sooo i dont know what its doing! The macros are in socket.h im tempted to copy them and change them to uint16_t and give them a different macro name but i dont have any way to test the results out here! and I’m just guessing my way through so its all trial and error!

So ive added a few lines so i could work out whats being sent and i saw something strange… they were all different sizes… then i remembered when you print binary it leaves off the 0’s at the front :smile:

so changed to hex and something else that messed me up… because hex does the same thing! so i printed a dot between each character to differentiate between them.

the first 2 bytes should be the unique ID number, generated kind of at random from millis() but it appeared to be the first 4 bytes… i must have changed it to uint32 yesterday when trying to fix the looping issue i had earlier…  so i squashed that down to a uint16_t again and got something reasonable…

1C.FF.1.0.0.1.0.0.0.0.0.0.6.67.6F.6F.67.6C.65.3.63.6F.6D.0.0.1.0.1.

1CFF
0100
0001
0000
0000
0000
0667
6F6F
676C
6503
636F
6D00
0001
0001

so this packet is built by the code and should have a defined structure like below all looks correct except im not sure how it should be with ‘htons’ i thought that the bytes would be reversed? maybe it is the right way?

                               1  1  1  1  1  1
 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

This is the header structure and it fits in perfect with that, except maybe the htons question above

The rest looks perfect too, just the footer with the same htons question…

So this is a bit of the code (CLASS_IN is defined 0x0001) and makes the last line of code. but the rest of them are similar…

twoByteBuffer = htons(CLASS_IN);
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));

Sooo cut and paste from socket.h… uint32 would make 4 bytes?? makes sense for htonl ie a long but same for a short?

#define htons(A)     ((((UINT32)(A) & 0xff00) >> 8) | \
                          (((UINT32)(A) & 0x00ff) << 8))

#define htonl(A)    ((((UINT32)(A) & 0xff000000) >> 24) | \
                     (((UINT32)(A) & 0x00ff0000) >> 8) | \
                     (((UINT32)(A) & 0x0000ff00) << 8) | \
                     (((UINT32)(A) & 0x000000ff) << 24))

So these macros (i think thats what they are??) are they right? and why isnt it 0100 instead of the 0001 that its defined as?

It works! i had 1 little thing messed up… IPAddress was pumping out 8.0.0.0 instead of 8.8.8.8 so once i found that it worked!

So whats the proper way to assign an IPAddress?

to get it working i put this, but i want to assign it at the top of the code to make it easier to see and change…

dns.begin(IPAddress(8,8,8,8));

I’m using TCPClient to POST data to a REST interface. The data is logged every 30 seconds. The REST interface resides on a Heroku app(Amazon)
The device has been running contentiously for weeks. The logs show, that on a random basis, API calls sometimes fail for as long as 6 minutes. This happens once or twice a day and on some days not at all.
Reading this post, I tried connecting usinga static IP instead of ‘connect(‘www.myapp.com’)’ to check if dns is causing stability issues (I know it’s not a solution) The results so far are perfect, which means Heroku don’t move their VM’s too often.

Question: Would it make sense to use a dns caching system where a successful connection caches the IP for consecutive calls and a failiure would do a new dns lookup? Is there a library for this? I know web browsers do cache dns lookups to some extent

@gadi you could try my dns lookup library https://community.spark.io/t/dns-lookup-alternate-gethostbyname/5427
Wouldn’t be hard to cache the IP it returns if it returns 0.0.0.0 then it failed and you could use the old IP

@bko - any reason we shouldn’t add buffering as part of the core firmware? (we will be adding it to TCP also to increase write performance there too, but here it’s not only about performance but about semantics/packet boundaries.)

I’m thinking of adding another method writePacket(uint8_t* data) that performs a beginPacket()/writeUnbuffered()/endPacket() as one step, avoiding the need to buffer the user’s data. The name makes it clear the function sends one complete packet.

What do you think?

Hi @mdma

My only point on buffering is that if the user has a string or array to send, then there is already a tx buffer and you don’t really need another one. Since it is a blocking call until the data is copied into the TI CC3000, it is not like the user can free the array out from under the client. It is more of a programmer problem, I think: you need to think about efficiency when you are coding.

So I think a buffer is fine if we have the RAM for it and it would help the small packet problem.

[EDIT] I would be interested in how you are going to decide to flush the buffer? You probably should think about that too!

I like the new method idea! It will be non-Arduino compatible but maybe a pull request could be sent their way as well.

Good question! I was thinking flush when the internal buffer is full or when the user calls endPacket(). To give the user manual control, then a writeFlush() function could be added. Although given that packets are sent as discrete entities, I wonder if we should ever flush apart from at the end of the packet, and instead return failure if the user writes more data than can fit in the (dynamically allocated) buffer.

[A side rantdiscussion - isn't it strange that in Arduino-land, flush() means purge a read buffer? I don't get the semantics of that and how you can know how much data or which data you are flushing. A write-flush is more usual and predictable, e.g. with buffering, caching etc.. :question: ]

So TCP does not have endPacket() but UDP does–which one are you changing? Both?

I agree that flush is a name with too many meaning already.

I plan to do both UDP and TCP. With UDP it’s more critical since the packet boundaries are part of the protocol the peer sees.

I’m unsure which way to go with TCP - add buffering to TCPClient, or leave it as is, and introduce a BufferedTCPClient so that TCPClient maintains the compatible but “broken” feature set of the Arduino.

I had these lines of code for testing before but would not build now.

IPAddress resolvedIP(BYTE_N(ip_addr, 3), BYTE_N(ip_addr, 2), BYTE_N(ip_addr, 1), BYTE_N(ip_addr, 0));

IPAddress dnshost(ip_config.aucDNSServer[3], ip_config.aucDNSServer[2], ip_config.aucDNSServer[1], ip_config.aucDNSServer[0]);

Any suggestions what had been changed under ?