TCP Server on M52233DEMO

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

TCP Server on M52233DEMO

5,021 Views
Kremer
Contributor I
 Hi all
 
 I´m trying to include a TCP Server in the ColdFire_Lite.mcp (Interniche sample program) but i´m facing some problems.
 Searching through some older threads in the forum, i could develope the attached code (tcp_server.c), wich i just add as a source file for the ColdFire_Lite.mcp.
 I modified the function int create_apptasks(void) on file tk_misc.c to create a new task wich is intended to be the new tcp server feature.
 I´m not using the msring structure as the http server does. I think it is unecessary since i want to make only one connection per session, not allowing multiple connections to be made in the same port.
 
 I can compile the project, burn it to flash and start debug, but then some problems happens:
 
1) The listening function works, putting the specific port to listen for incoming connections, and the TCP_check() function is called regularly BEFORE any connection is made. But when i connect succefully to the board, the TCP_check() function is not called anymore. It seems that the task is not being executed anymore right after a connectiona is made. It prints on uart the messagem "OPEN", wich indicates that the Callback routine is being called, but the TCP_check() routine, wich was being regularly called, is not called anymore right after this. Since i try to read the incoming data inside the TCP_check function, the result is that i can just connect to the target, but not process any incoming data.
 
2) When i close the connection and reconnect to the target it works fine for some times, but after a number of tries, i start to have memory problems, and the message "calloc1 failed: size 124, failures : n" where n is the number of erros (increased by the number of times i try to reconnect) is shown and the connection can´t be made.
 
 Please mates, any help is usefull to me, since i´m new to this coldfire chip.
 
 Thanks and best regards
 
Labels (1)
0 Kudos
Reply
9 Replies

1,680 Views
Kremer
Contributor I
Sorry, the code is below:
 
#include "ipport.h"        /* from Interniche directory */
#include "osport.h"
#include "msock.h"
//*****************************************************************************
// Declare Task Object
//*****************************************************************************TK_OBJECT(to_keludpclient);
TK_OBJECT(to_tcpserver);
TK_ENTRY(tk_tcpserver);
struct inet_taskinfo tcp_listener_task={ &to_tcpserver,
                                   "TCP passivo",
                                   tk_tcpserver,
                                   NET_PRIORITY,
                                   APP_STACK_SIZE
                                 };
void TCP_check(void);
int TCP_Callback(int code, M_SOCK so, void * data);
int TCP_init(void);
M_SOCK tcp_server_socket;
int tcp_semaphore=0;
#define RECV_BUFFER_SIZE  0x400
#define TCP_PORT_NUMBER  1024
int TCP_Closed=1;
struct sockaddr_in tcp_sin;

TK_ENTRY(tk_tcpserver)
{
  int err;
  // Wait for the network to be ready
  while (!iniche_net_ready)
  {
     TK_SLEEP(1);
  }
  err = TCP_init();
  if (err != SUCCESS)
   {
     dtrap(); // TCP_init() failed!!!
   }
  // Endless loop - this is the task running.
  #ifdef NPDEBUG
   printf("Initiating loop for TCP_check()...\n");
  #endif
  for (;:smileywink:
  {
     // Check for incomming traffic.
     TCP_check();
     // Yield to CPU for other tasks to run.
     tk_yield();
     // Check for system shutdown
     if (net_system_exit)
     {
        break;
     }
  }
  TK_RETURN_OK();
}
void TCP_check(void)
{
  // Create a 32-bit alignment buffer
   char buffer[RECV_BUFFER_SIZE];
 int length=0;
 int j;
 int k;
 
  
  if(MCF_GPIO_PORTTC<0x07)
   MCF_GPIO_PORTTC++;
  else
   MCF_GPIO_PORTTC = 0x00;
  if (tcp_server_socket == INVALID_SOCKET)
  {
     return;
  }
  if(TCP_Closed==0)
   while ((length = m_recv(tcp_server_socket, &buffer[0], RECV_BUFFER_SIZE ))>0)
   {
     tcp_semaphore = 1;
     // Read tcp_msring data and process
     
     if (length > 0)
     {
      #ifdef NPDEBUG
       printf("TCP Received...\n");
      #endif
        m_send(tcp_server_socket, &buffer[0], length);
     }
     tcp_semaphore = 0;
   }
 }
 
int TCP_Callback(int code, M_SOCK so, void * data)
{
  int e = 0;

  switch (code)
  {
     // socket open complete
     case M_OPENOK:
        if (TCP_Closed)
        {
           printf("OPEN\n");
           TCP_Closed = 0;
        }
        break;
     // socket has closed     
     case M_CLOSED:
        m_close(so);
        TCP_Closed = 1;
        printf("CLOSED\n");
        TCP_init();
        break;                          // let stale conn timer catch these
     // passing received data
     // blocked transmit now ready
     case M_RXDATA:                      // received data packet, let recv() handle it
     case M_TXDATA:                      // ready to send more, loop will do it
        e = -1;                         // return nonzero code to indicate we don't want it
        break;
     default:
        printf("dtrap %d\n", code);
        dtrap();                  // not a legal case
        return 0;
  }
  TK_WAKE(&to_tcpserver);                      // wake server task
  USE_VOID(data);
  return e;
}
int TCP_init()
{
  int e;
  tcp_semaphore = 0;
  // Init a socket structure with our Port Number
  tcp_sin.sin_addr.s_addr = (INADDR_ANY);
  tcp_sin.sin_port        = (TCP_PORT_NUMBER);
  tcp_server_socket = m_listen(&tcp_sin, TCP_Callback, &e);
  printf("Listening...\n");
  if (tcp_server_socket == INVALID_SOCKET)
  {
     printf("error %d starting listen on TCP server\n", e);
  }
  return SUCCESS ;
}
0 Kudos
Reply

1,680 Views
ColdFireHot
Contributor I
Kremer,
  The socket returned from the m_listen() function is not a real socket.  It must not be used for communication.  When the callback is called the M_SOCK "so" that is returned is the real socket to be used for communicating with the client, thus the use of msring.
 
  The socket returned from the m_listen() will only be used for m_close() when communication is completed.
 
  The comment about creating a 32-bit alignment buffer was to indicate that you should not change the unsigned long to a char.  Explicitly casting to char * was deliberate.  The 32-bit processor will run more efficiently if the data is aligned.
 
Mark
 
Attached is the latest variation of the code.
 
0 Kudos
Reply

1,680 Views
Kremer
Contributor I
Hi Mark
 
 Thank you for your reply. I guess i need a better documentation about using those msring structs, mini BSD sockets and the RTOS. I got some information on www.freertos.com, and from interniche html pages that come with the ColdFire_Lite project, but i think they are very poor on examples of utilization.
 Can you please point me to some better documentation?
 
 Thank you and best regards
 
0 Kudos
Reply

1,680 Views
ColdFireHot
Contributor I
Kremer,
  I agree with you on the InterNiche documentation for mini sockets.  I have no more information than is available in the html pages, however I did some experimenting and I think I know how it works, well, better now.
 
The msring struct is not required but it is a way of allowing asynchronous events to be pushed onto the ring and removed as time permits.  This means heavy traffic could keep the processor busy enough to not allow your local task time to process the initial request.
  Example; If two clients try to connect at the same time the listener will accept the first request and "Callback" to your routine to handle the socket.  The second client will then be handled by the listener and "Callback" again with a different socket handle.
This example may be rare but then most bugs in code are too.  I recomment using the msring method as outlined in the example code in the ColdFire_Lite program as it seems to work.
 
In my code example I have taken steps to close the listening socket as soon as I have a request.  This allowed me to only have one connection at a time to the listening port.
 
With only one possible client connection, I could use a global M_SOCK for the client connection and not have to use the msring structure.  For safety sake I left the msring method in place.
 
Regards,
Mark
 
0 Kudos
Reply

1,680 Views
Kremer
Contributor I
 Mark
 
 Thank you for your explanation about the msring. I found this structure pretty nice to handle multiple connections. As you mentioned before, when using this msring struct the server is abled to do multiple listening on the same port, by pushing the new request onto the msring structure for further handling.
 I modified your example and change the macro MAX_NUMBER_OF_SESSIONS (wich is 4 and is being used by the http server) to MAX_NUMBER_OF_TCP_SESSIONS, wich i set to only one. As a result, the system only accpets one tcp session at a time. It works very fine.
 But i´m still having a weird problem. When i run the code, everything works fine. I can connect to my tcp server and receive the info i want. I can open the page through a browser too. But when i open a second instance of my browser (Internet Explorer) and try to connect to the http_server again (eg 2 http sessions in the same pc) the chip issue an error message "calloc1 failed". The same message is shown when i try to disconnect and reconnect multiple times in a fast way. As a result the program stucks and nothing is executed anymore.
 Have you seen such behavior there? When i remove the tcp_server from tasks this behavior isn´t reproduced. Any tips, thoughts or rules are welcome to avoid this problem.
 
 Thank you and best regards
 Kremer
0 Kudos
Reply

1,680 Views
ColdFireHot
Contributor I
Kremer,
  I duplicated the error you described.  I still have not found a way to prevent a second client from connecting to the same port without closing the listening socket.  The session count to which you refer is for the high level http server code to run more effectively with a single application client (the browser), it does not prevent another attempt to connect from another application client (a second browser).  This can be seen with Ethereal.  The same is true of the TCP connections with Hyperterm.  What I am looking for in Ethereal is the [RST/ACK] indicating that the port is busy and cannot accept any more connections.  It is different from when I close the port which yields a "port not available" message.  I have not found any information on how to modify the TCB to only allow one connection at a time.
 
  The http server appears to only expect a single application client to connect.  I really don't know much about how the browser works.
 
   What I did was to run two Hypertem windows both connecting to the same port.  With the demo board off both Hyperterm connections will timeout and be in the disconnected state.  Then I power up the demo board.  Then I start typing in one window and before the send messages are completed I start typing in the other Hyperterm window.  This causes some really weird stuff to happen.  If you keep switching between the two Hyperterm windows and type something before the send messages are done the demo board will eventually crash.
 
Regards,
Mark
 
0 Kudos
Reply

1,680 Views
Kremer
Contributor I
 Hi Mark
 
 As you could reproduce the problem there, can you try to guess what´s going wrong with this?
 I did a lot of debug sessions and noticed that, for every connection request that the module receives, it must allocate an TCP control block to it. It happens before the callback routine call. Specifically on tk_netmain task, wich keeps looking for new received nework packets.
 So, when memory problems happens, the application should ignore the connection request and reinitializa any variable wich had it´s value set by this request. I can see it is doing it, but one rouitne is messing up with the aplication.
 I noticed the problem occurs when it access this part of the tcp_rcv function in tcpin.c :
 
     tp_new = m_newtcpcb(so);
     if(tp_new == NULL)
     {
        m_delsocket(so);
        GOTO_DROP;
     }
 The system crash occurs when tp_new is equal to null, causing the routine m_delsocket(so); to be called.
 This delsocket possibly is trying to delete something that isn´t there yet, causing the system to crash in a way that i didn´t realized yet. But comenting this call to m_delsocket(), the system doesn´t crash anymore and both servers continue to run.
 
0 Kudos
Reply

1,680 Views
wyliek
Contributor I
Hi there

Sorry, I havent been able to participate in this discussion for a few weeks now as for some reason the site was not working from my browser. Kremer, have you made any progress with the TCP server? Do you know why commenting out that line of code works. My TCP server is working now and does not cause errors anymore. I can post the code if you like?

Mark, any progress on accepting only one socket connection?

Have either of you been working with UDP at all? I am having problems with dropped UDP packets.

Anyways let me know how things are coming along

Cheers
0 Kudos
Reply

1,680 Views
WOLF
Contributor I
Can anyone post the tcp_server.h file for the source listed here, I would like to try this code. i'm trying to create a VERY simple HTTP server and this looks like a great starting point.
 
Thanks,
0 Kudos
Reply