µTasker Forum
µTasker Forum => µTasker general => Topic started by: TomM on January 30, 2018, 11:23:40 PM
-
On my last project at Mark's suggestion, I used Telnet to implement a Server (though there was only one client). In the end that has worked out quit well. My current project however now just needs client functionality. So I've been looking at the Telnet code and wonder if I duplicate the start function and change the fnTCP_Listen() call to an fnTCP_Connect() call, if that would give me what I think I want?
Thanks in advance for your thoughts.
Tom
-
Tom
Try with USE_TELNET_CLIENT, which implements a client (instead of, or together with a server).
Regards
Mark
-
Mark,
My Version of uTasker must be too old. I did a search for the string TELNET_CLIENT and got zero results. My copy of application.h defines SOFTWARE_VERSION as "V1.4.011". I recall that you provided a pointer to the latest code a while ago, but I don't think my team members ever downloaded it. I can look back and see where you pointed me before and/or you could suggest how else I can add the CLIENT functionality.
Regards
Tom
-
Tom
If you don't find it in an M522xx project use the open source Kinetis code - the Telnet parts should be compatible.
Regards
Mark
-
Hi Mark,
I have been looking at Wireshark captures between the Telnet Client and the Telnet Server. I have attached two capture files which demonstrate issues with the ACK and Sequence numbers being generated by the Telnet Client (at 192.168.0.10). In the first file I only had TELNET_session->usTelnetMode set to TELNET_RAW_MODE. Backtracking through the code I found the check " if ((TELNET_session->usTelnetMode & (TELNET_CLIENT_MODE | TELNET_CLIENT_NO_NEGOTIATION)) == (TELNET_CLIENT_MODE)) { // acting as a client with negotiation not edisabled". I appeared to me that the negotiation this was allowing had the ACK being miscalculated. So I changed to TELNET_session->usTelnetMode = (TELNET_RAW_MODE | TELNET_CLIENT_MODE | TELNET_CLIENT_NO_NEGOTIATION). This resulted in the second Wireshark file which has different ACK/SEQUENCE values which are still in error until a RETRANSMIT occurs.
I'd appreciate your assistance since this appears to be a Telnet Client Code issue.
Regards,
Tom
-
Tom
I tried simulating with your recordings but you have the same MAC address at both client and server and this is causing strange effects - I don't know whether it may also have an impact on your tests too(?)
If you could set up with different MACs I may be able to detect something - in the (first) wireshark recording I see a sequence number jump between the client's connection ACK and it sending 8 bytes of data but I also see an IP identification jump as well (from 1 to 3). This means that there was presumably a short TCP frame with 3 content bytes sent (I suspect a negotiation) but this was not seen on the Ethernet - although it must have passed through IPv4 layer).
Therefore, although I see strange behavior and the MAC address conflict (I wonder whether this somehow causes a problem?), I don't see a definite TELNET (or TCP) problem yet since it would be basically correct if a transmission were lost - although I would the expect repeats of the lost frame, whereby instead the server resets the connection (timeout? after 5s?).
Note also that you have TCP windows of just 54 bytes in each direction - is this expected?
Regards
Mark
-
Mark
As usual, you seem to have found the thing I was missing, i.e. the duplicate MAC addresses. I really do know better but... after correcting that, returning to the default window size and fixing a couple of host packet processing issues, both applications are merrily communicating as expected :)
Thanks for the assistance.
Tom
-
Tom
That is good news!
Regards
Mark
-
Mark,
This post is merely a question relating to TCP buffering, i.e. the Telnet Server and Client are operating nicely.
Somewhere along the line I got the idea that I could queue multiple data packets to a Telnet Socket and not start the send until I placed what I wanted in there, maybe 120 bytes . After rereading the document you wrote captioned "how to use buffered TCP to transmit TCP frames" I realized I appear to have gotten the wrong idea. So do I any options except to have my application buffer the messages before sending?
Regards,
Tom
-
Tom
These are the buffer TCP options:
extern QUEUE_TRANSFER fnSendBufTCP(USOCKET TCP_socket, unsigned char *ptrBuf, unsigned short usDataLen, COMMAND_TYPE Command);
#define TCP_BUF_SEND 0x01
#define TCP_BUF_NEXT 0x02
#define TCP_BUF_REP 0x04
#define TCP_BUF_CHECK 0x08
#define TCP_BUF_SEND_REPORT_COPY 0x10
#define TCP_CONTENT_NEGOTIATION 0x20
#define TCP_REPEAT_WINDOW 0x40
#define TCP_BUF_KICK_NEXT 0x80
#define TCP_BUF_QUEUE 0x0100
whereby TCP_BUF_QUEUE is available only when _EXTENDED_BUFFERED_TCP is enabled.
The final flag allows preparing output data "before" the connection is established.
I don't see that there is presently an option that allows writing to the output buffer when a connection exists but not sending it yet. However it looks to be simple to add such support as follows:
In tcpip.h
#define TCP_BUF_PREPARE 0x0200 // allow preparing data in the output buffer of an open connection but not start its transmission yet
In tcp.c
#if defined _EXTENDED_BUFFERED_TCP
if ((ptr_TCP->ucTCP_state != TCP_STATE_ESTABLISHED) || ((Command & TCP_BUF_PREPARE) != 0)) { // if the connection has not yet been established or the caller wishes to prepare the buffer before sending
tcp_tx->usWaitingSize += usDataLen; // extra waiting data size
return 0; // data added to buffer but no transmission started since the connection is not (yet) open
}
#endif
This would allow TCP_BUF_PREPARE to be used to add the new data to the output buffer but not starts its transmission yet.
The flag can be left away when adding the data that is to finally start the transmission.
This would however not work if there is already transmit data in transmission since its ACK will cause as much data as possible to be sent, including any additionally queued data.
If a connection is idle (no transmit data not yet acknowledged by the peer) it should however avoid the application needing to queue the data at the higher level.
I have added the small code change - tell me if it proves to be suitable for your requirement.
Good luck.
Regards
Mark
-
Hi Mark,
First off, I did not try to add the code you provided yet. I got side tracked on debugging more basic issues in the application's behavior like handling the multiple Listeners correctly and you didn't provide a reference to where it should be placed. Unfortunately I am now consistently getting an "undef_int()". This appears to be caused by a uMemcpy() in tcp.c which is being passed a ptrTo value of 0.
So 1st question is: I'm still using the old copy of tcp.c (uTasker-1.4.006?) with the newer copy of telnet.c (uTasker-1.4.013). I think I chose not to update due to the effort involved and reviewing the differences I thought it should be OK. What are your thoughts?
The second is could you have a look at the snap shots from the debugger I've attached and see if you can suggest a way to catch this that I haven't explored. I know the fault always happens on the same message type, but not every occurrence of the message. The message address which is passed looks OK. I'd appreciate you assistance since I'm not seeing issues with the data being passed.
Thanks,
Tom
-
Hi Tom
I can see that
tcp_tx->ucDataEnd and tcp_tx->ucDataStart are both zero and any attempt to copy data to these pointers will cause a hard fault.
Since I have never tried using different versions of tcp.c and telnet.c I don't know whether there may be come incompatibility or a configuration that needs to be matched, however I would take a close look at where these two variables are initialised.
For example
tcp_tx->ucDataEnd = tcp_tx->ucDataStart = tcp_tx->ucTCP_tx;
In this case it would mean that tcp_tx->ucTCP_tx was not allocated or maybe its malloc() attempt failed. Check also the define INDIVIDUAL_BUFFERED_TCP_BUFFER_SIZE since I always work with this enabled - it looks to be involved with allocating this memory too.
Regards
Mark
P.S. The code change I made is in fnSendBufTCP(). The non-bold parts are original code.