xtcp

Technical questions regarding the XTC tools and programming with XMOS.
mikhail
Junior Member
Posts: 7
Joined: Fri Jul 30, 2010 12:16 pm

xtcp

Post by mikhail »

Hello,

I'm fighting wiht the xmos_tcpip stack. Does anyone know how to use it with UDP? I need to send a few UDP messages, don't need to connections and all this TCP stuff.


tyler
Member
Posts: 15
Joined: Tue Jul 13, 2010 12:42 pm

Post by tyler »

The xtcp is a bit difficult to use.

I'd recommend spending some time learning how it works (unless you already have). ie the xtcp_server and xtcp_client etc.


I currently am using xtcp to multicast a stream of data. The way I have it working now:

I connect to the multicast address:

Code: Select all

xtcp_connect(tcp_svr, PORT_LISTEN, ip_addr, XTCP_PROTOCOL_UDP);
Now, I want to send this stream as fast as possible. So when I get the SENT event back from the tcp server, I use that to start another send.

Try experimenting with polling. I have that turned on with a relatively high poll interval. That makes it work.

Also, you should really look at the uIP Reference Manual. It provides a lot of insight, as xtcp is based upon this IP stack.
[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo *Click*
mikhail
Junior Member
Posts: 7
Joined: Fri Jul 30, 2010 12:16 pm

Post by mikhail »

Thanx a lot! Now I got it. Still a few problems, but now smth is working. I also need to stream some media data, namely RTP audio.

For those who are still fighting, here is the code:

Code: Select all

void xhttpd(chanend tcp_svr) 
{
  xtcp_connection_t conn;
  xtcp_appstate_t state;
  xtcp_ipaddr_t host = {192,168,0,102};
  unsigned char data[XTCP_CLIENT_BUF_SIZE] = {'h', 'e', 'l', 'l', 'o'};
  int len;
  int rem_port = 2222;
  timer tmr;
  unsigned t;
  unsigned ledOn = 1;

  xtcp_connect(tcp_svr, rem_port, host, XTCP_PROTOCOL_UDP);
  //xtcp_bind_remote(tcp_svr, conn, host, rem_port);

  //httpd_init();
//  xtcp_listen(tcp_svr, 80, XTCP_PROTOCOL_TCP);
  xtcp_ask_for_event(tcp_svr);
  while(1) {
    select 
      {
      case xtcp_event(tcp_svr, conn):
				switch (conn.event) {
					case XTCP_NEW_CONNECTION:
						printf("XTCP_NEW_CONNECTION\n");
						httpd_init_state(tcp_svr, conn);
						printf("connection %d %d %d %d %d   proto=%d\n", conn.accepted, conn.id, conn.local_port,
																						conn.protocol, conn.remote_port, conn.protocol);
						xtcp_init_send(tcp_svr, conn);
						break;
					case XTCP_RECV_DATA:
						printf("XTCP_RECV_DATA\n");
						//httpd_recv(tcp_svr, conn);
					  len = xtcp_recv(tcp_svr, data);
					  printf("receieved %s\n", data);
						break;
					case XTCP_REQUEST_DATA:
						printf("XTCP_REQUEST_DATA\n");
						xtcp_send(tcp_svr, data, DATA_LEN);
						tmr :> t;	/* save the current timer value */
						break;
					case XTCP_RESEND_DATA:
						printf("XTCP_RESEND_DATA\n");
						xtcp_send(tcp_svr, data, DATA_LEN);
						tmr :> t;	/* save the current timer value */
						break;
					case XTCP_SENT_DATA:
//						printf("sending...\n");
							tmr when timerafter(t + DELAY) :> void;        /* wait till the send period is over */
			  	  x0ledB <: ledOn;  /* toggle the LED */
				    ledOn = !ledOn;
							xtcp_send(tcp_svr, data, DATA_LEN);
							tmr :> t;	/* save the current timer value */
						//httpd_send(tcp_svr, conn);
						break;
					case XTCP_TIMED_OUT:
					case XTCP_ABORTED:
					case XTCP_CLOSED:
						printf("XTCP_TIMED_OUT\n");
						httpd_free_state(conn);
						break;
				}
        xtcp_ask_for_event(tcp_svr);
        break;
      }
  }
}
User avatar
aleonard
Member
Posts: 15
Joined: Thu Sep 16, 2010 8:19 pm

Post by aleonard »

I had trouble figuring out how to get UDP working with xtcp as well. Here's an example of a UDP server I implemented. The code is based on the xhttpd and httpd files in the simple webserver example. In this example, the XMOS based server does not know the address for the remote client in advance, but establishes a connection when it receives a packet from the client.

based on xhttpd.c:

Code: Select all

void UDP_Server(chanend tcp_svr, chanend DataOut)
{
	int i, SendLength;
	xtcp_connection_t 	conn;
	 UDP_init();

	  // set UDP protocol and local port
	  xtcp_listen(tcp_svr, 8, XTCP_PROTOCOL_UDP);

   // check for inital event from xtcp server
	  xtcp_ask_for_event(tcp_svr);
	  while(1) {
		select
		  {
		// check if data is available to send (data prepared in main function)
			case DataOut :> SendLength:
				UDP_SetLength(SendLength);
			// if UDP channel is properly initialized, send data
			// initialization occurs when a first packet is received from the client
				if(conn.remote_port != 0)
					xtcp_init_send(tcp_svr, conn);
				break;
		// handle events from the xtcp server
			case xtcp_event(tcp_svr, conn):
				UDP_HandleEvent(tcp_svr, conn);
				xtcp_ask_for_event(tcp_svr);
				break;
			default:
				break;
		  }
  }
}
based on httpd.c:

Code: Select all

// The udp_state_t struct communicates state information between the
// UDP Server (manager) and the uip/xtcp functions
typedef struct udp_state_t {
  int active;
  int conn_id;
  int dlen;
  xtcp_transfer_state_t ts;
} udp_state_t;

// Globals
udp_state_t  		UDPs;
int 				Remote_Assigned;
int					SendLength;

// external Globals
extern unsigned char Dat_Out[];
extern unsigned char Dat_In[];
extern unsigned char DataInFlag[];

void UDP_HandleEvent(chanend tcp_svr,
        xtcp_connection_t *conn)
{

	switch (conn->event)
    {
    case XTCP_NEW_CONNECTION:
    	// initialize udp_state_t and xtcp appstate
    	UDPs.active = 1;
    	UDPs.conn_id = conn->id;
    	xtcp_set_connection_appstate(tcp_svr, conn, (xtcp_appstate_t) &UDPs);
      break;
    case XTCP_RECV_DATA:
      // receive data from remote source
      UDP_recv(tcp_svr, conn);
      // if not already assigned, bind UDP channel to remote port and IP address
      // this information is recieved in the client packet
      // in our case the embedded server does not know the client address information in advance
      // the UDP channel must be bound in order for data to be sent out correctly
      if((Remote_Assigned == 0) &&(conn->remote_addr != 0)){
			xtcp_bind_remote(tcp_svr, conn, conn->remote_addr, conn->remote_port);
			Remote_Assigned = 1;
      	}
      DataInFlag[0] = 1;
      break;
    case XTCP_SENT_DATA:
    case XTCP_REQUEST_DATA:
    case XTCP_RESEND_DATA:
      UDP_send(tcp_svr, conn);
      break;
    case XTCP_TIMED_OUT:
    case XTCP_ABORTED:
    case XTCP_CLOSED:
      break;
    }
}

void UDP_recv(chanend tcp_svr,
        xtcp_connection_t *conn)
{
  int len;

  // record new data in Dat_In array
  len = xtcp_recv(tcp_svr, Dat_In);
}

void UDP_send(chanend tcp_svr,
        xtcp_connection_t *conn)
{

  int finished;

  // send new data: will send only allowed packet length
  // if data is longer than packet length, an XTCP_SENT_DATA event
  // will occur such that the UDP_send function will be called again.
  // the function will return '1' when all data is sent
  // UDPs.ts holds dataset index information between function calls
   finished = xtcp_send_buffer_firefly(tcp_svr,
                               conn,
                               &(UDPs.ts),
                               Dat_Out,
                               UDPs.dlen);
   if (finished)
	   xtcp_close(tcp_svr, conn);
   return;
}