Net Streams

This forum is about you. Feel free to discuss anything is related to embedded and electronics, your awesome projects, your ideas, your announcements, not necessarily related to ChibiOS but to embedded in general. This forum is NOT for support.
User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Net Streams

Postby Giovanni » Fri Aug 09, 2013 1:05 pm

Hi,

The following code has been contributed via email by W.S.

It looks pretty useful: lwIP sockets wrapped in ChibiOS streams.

Giovanni

netstream.c

Code: Select all

#include "netstream.h"
#include "lwip/sockets.h"

static size_t writes(void *ip, const uint8_t *bp, size_t n) {
  NetStream *sp = ip;

  return lwip_write(sp->socket, bp, n);
}

static size_t reads(void *ip, uint8_t *bp, size_t n) {
  NetStream *sp = ip;

  return lwip_read(sp->socket, bp, n);
}

static msg_t put(void *ip, uint8_t b) {
  return (writes(ip, &b, 1) == 1 ? Q_OK : Q_RESET);
}

static msg_t get(void *ip) {
  uint8_t b;

  return (reads(ip, &b, 1) == 1 ? b : Q_RESET);
}

static const struct NetStreamVMT vmt = {writes, reads, put, get};

void nsObjectInit(NetStream *sp, int socket) {

  sp->vmt  = &vmt;
  sp->socket = socket;

}


netstream.h

Code: Select all

#ifndef NETSTREAM_H_
#define NETSTREAM_H_

#include <stddef.h>
#include <stdint.h>
#include <chtypes.h>
#include <chstreams.h>

#define _net_stream_data                                                 \
  _base_sequential_stream_data                                              \
   int socket;

struct NetStreamVMT {
  _base_sequential_stream_methods
};

/**
 * @extends BaseSequentialStream
 *
 * @brief Memory stream object.
 */
typedef struct {
  const struct NetStreamVMT *vmt;
  _net_stream_data
} NetStream;

#ifdef __cplusplus
extern "C" {
#endif
  void nsObjectInit(NetStream *sp, int socket);
#ifdef __cplusplus
}
#endif

#endif /* NETSTREAM_H_ */


Giovanni

User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: Net Streams

Postby Tectu » Fri Aug 09, 2013 4:27 pm

Do I understand this correctly - you can actually chprintf() over TCP/IP? :o


~ Tectu

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Net Streams

Postby Giovanni » Fri Aug 09, 2013 7:20 pm

or even use a shell

Giovanni

User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: Net Streams

Postby Tectu » Fri Aug 09, 2013 10:58 pm

This sounds very awesome... sadly I don't know anything about ethernet nor LwIP :(


~ Tectu

tinito
Posts: 112
Joined: Tue Jun 07, 2011 10:32 am
Has thanked: 1 time
Been thanked: 1 time

Re: Net Streams

Postby tinito » Fri Sep 20, 2013 12:19 pm

Really loved the idea, and played around a little with it to remove dependency from the sockets API, relying only on the more efficient netconn API.
Not sure if I did everything in the correct/best way, but it seems to work ;)

netstream.h

Code: Select all

#ifndef NETSTREAM_H_
#define NETSTREAM_H_

#include "ch.h"

#define _net_stream_data \
   _base_sequential_stream_data \
   struct netconn * conn; \
   struct netbuf * inbuf; \
   size_t in_offset;

struct NetStreamVMT {
   _base_sequential_stream_methods
};

/**
 * @extends BaseSequentialStream
 */
typedef struct {
   const struct NetStreamVMT *vmt;_net_stream_data
} NetStream;

#ifdef __cplusplus
extern "C" {
#endif
void nsObjectInit(NetStream *sp);
void nsStart(NetStream *sp, struct netconn * conn);
#ifdef __cplusplus
}
#endif

#endif /* NETSTREAM_H_ */



netstream.c

Code: Select all

#include "netstream.h"
#include "lwip/api.h"

#include "ch.h"
#include "hal.h"

static size_t write(void *ip, const uint8_t *bp, size_t n) {
   NetStream *sp = ip;

   return netconn_write_partly(sp->conn, bp, n, NETCONN_COPY, NULL);
}

static size_t read(void *ip, uint8_t *bp, size_t n) {
   NetStream *sp = ip;
   err_t err;

   /* If last input buffer was completely consumed, wait for a new packet. */
   while (sp->inbuf == NULL) {
      /* Wait for new packet. */
      err = netconn_recv(sp->conn, &sp->inbuf);
      if (err != ERR_OK) {
         /* Connection closed (or any other errors). */
         return 0;
      }
   }

   netbuf_copy_partial(sp->inbuf, bp, n, sp->in_offset);
   sp->in_offset += n;

   /* Check if there is more data to read. */
   if (sp->in_offset >= netbuf_len(sp->inbuf)) {
      n -= (sp->in_offset - netbuf_len(sp->inbuf));
      netbuf_delete(sp->inbuf);
      sp->in_offset = 0;
      sp->inbuf = NULL;
   }

   return n;
}

static msg_t put(void *ip, uint8_t b) {
   return (write(ip, &b, 1) == 1 ? Q_OK : Q_RESET);
}

static msg_t get(void *ip) {
   uint8_t b;

   return (read(ip, &b, 1) == 1 ? b : Q_RESET);
}

static const struct NetStreamVMT vmt = { write, read, put, get };

void nsObjectInit(NetStream *sp) {

   sp->vmt = &vmt;
   sp->inbuf = NULL;
   sp->in_offset = 0;
}

void nsStart(NetStream *sp, struct netconn * conn) {

   sp->conn = conn;
}



Then I can spawn a shell for each connection like this:

Code: Select all

/*
 * TCP server thread.
 */
static msg_t server_thread(void *arg) {
   uint16_t port = *((uint16_t *) arg);
   struct netconn *conn, *newconn;
   err_t err;

   chRegSetThreadName("server");

   /* Create a new TCP connection handle */
   conn = netconn_new(NETCONN_TCP);
   LWIP_ERROR("TCP server: invalid conn", (conn != NULL), return RDY_RESET;);

   /* Bind to a port. */
   netconn_bind(conn, NULL, port);

   /* Listen for connections. */
   netconn_listen(conn);

   while (TRUE) {
      err = netconn_accept(conn, &newconn);
      if (err != ERR_OK)
         continue;

      /* Dynamic allocation to allow multiple shell instances. */
      NetStream * nsp = chHeapAlloc(NULL, sizeof(NetStream));
      ShellConfig * shell_cfgp = chHeapAlloc(NULL, sizeof(ShellConfig));

      if(nsp && shell_cfgp) {
         nsObjectInit(nsp);
         nsStart(nsp, newconn);

         shell_cfgp->sc_channel = (BaseSequentialStream *) nsp;
         shell_cfgp->sc_commands = commands;

         shellCreate(shell_cfgp, SHELL_WA_SIZE, NORMALPRIO - 1);
      }
   }
   return RDY_OK;
}



Simple and impressive!

fzahn
Posts: 1
Joined: Wed Jan 01, 2014 6:40 pm

Re: Net Streams

Postby fzahn » Wed Jan 01, 2014 6:47 pm

Hi,

this is exactly what i was looking for and I can access the shell via "nc -c ip_address".

Unfortunately I did not find a useful way, to exit the shell and close the tcp-connection to it...
I tried combinations of "shellExit(RDY_OK)" and netconn_close(newconn) but without success.
When executing the netconn_close the system hangs, when not doing shellExit....
But after shellExit the following commands are not executed anymore.


Any ideas?


Thanks and best regards

Florian


Return to “User Projects”

Who is online

Users browsing this forum: No registered users and 6 guests