A simple class to do line-based TCP communication. To be used with the NetServicesMin library-.

Dependents:   pop3demo

Files at this revision

API Documentation at this revision

Comitter:
hlipka
Date:
Sat Jan 29 22:42:14 2011 +0000
Child:
1:28416a5a4ec5
Commit message:
initial version

Changed in this revision

tcplinestream.cpp Show annotated file Show diff for this revision Revisions of this file
tcplinestream.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcplinestream.cpp	Sat Jan 29 22:42:14 2011 +0000
@@ -0,0 +1,169 @@
+#include "Timer.h"
+
+#include "tcplinestream.h"
+
+#include "dnsresolve.h"
+
+void TCPLineStream::onTCPSocketEvent(TCPSocketEvent e) {
+//    printf("New TCPSocketEvent: %d\n",e);
+    switch (e) {
+        case TCPSOCKET_CONNECTED:
+            _connected = true;
+            _connecting=false;
+            break;
+
+        case TCPSOCKET_READABLE:
+            break;
+        case TCPSOCKET_WRITEABLE:
+            break;
+
+        case TCPSOCKET_CONTIMEOUT:
+        case TCPSOCKET_CONRST:
+        case TCPSOCKET_CONABRT:
+        case TCPSOCKET_ERROR:
+        case TCPSOCKET_DISCONNECTED: {
+            // don't close the real socket here, as this may skip the already received data
+            _connected = false;
+            _connecting=false;
+        }
+        break;
+    }
+}
+
+TCPLineStream::TCPLineStream(const char *server, int port, const char* term) {
+    _server=server;
+    _port=port;
+    _term=term;
+}
+
+bool TCPLineStream::open() {
+    _closed=false;
+    _readpos=0;
+    _readlen=0;
+
+    _socket=new TCPSocket();
+    _socket->setOnEvent(this,&TCPLineStream::onTCPSocketEvent);
+
+    IpAddr addr;
+    // ignore IP adress - is !null even if it is 0.0.0.0
+    // so do DNS if a name is given
+    if (NULL!=_server) {
+//    printf("do DNS request for %s\n",_server);
+        DNSResolver dr;
+        addr=dr.resolveName(_server);
+    }
+//    printf("server=%i.%i.%i.%i/%i\n",addr[0],addr[1],addr[2],addr[3],_port);
+
+    Host host(addr, _port);
+
+//    printf("connect\n");
+    TCPSocketErr bindErr = _socket->connect(host);
+
+    if (bindErr != 0) {
+        printf("connection bind error %i\n", bindErr);
+        return false;
+    }
+//    printf("connecting\n");
+    // wait for connection established
+    _connecting=true;
+    mbed::Timer tmr;
+    tmr.start();
+    tmr.reset();
+
+    while (_connecting) {
+        Net::poll();
+        wait_us(100);
+        if (tmr.read()>20) {
+            printf("error: reached timeout\n");
+            break;
+        }
+    }
+    if (!_connected) {
+        printf("error - could not connect (timeout)\n");
+        return false;
+    }
+//    printf("connected\n");
+    return true;
+}
+
+void TCPLineStream::sendLine(string line) {
+//    printf("send request[%s]\n",line.c_str());
+    _socket->send(line.append(_term).c_str(),line.length()+strlen(_term));
+    Net::poll();
+}
+
+void TCPLineStream::close() {
+    if (_closed)
+        return;
+
+    while (_connected) {
+        Net::poll();
+        // read remaining data
+        int err=_socket->recv(_readbuf,BUFSIZE-1);
+        if (err<=0)
+            break;
+    }
+
+    while (true) {
+        Net::poll();
+        // read remaining data
+        int err=_socket->recv(_readbuf,BUFSIZE-1);
+        if (err<=0)
+            break;
+    }
+
+    _socket->resetOnEvent();
+    _socket->close();
+    delete _socket;
+    _closed=true;
+}
+
+string TCPLineStream::readLine(int strLen) {
+    string r;
+    r.reserve(strLen);
+
+    int emptyCount=0;
+    int lineendPos=0;
+    while (true) {
+        Net::poll();
+        if (_readlen>_readpos) {
+            while (_readbuf[_readpos]!=0 && _readpos<_readlen) {
+                char c=_readbuf[_readpos++];
+                //if the current char is the right one of the line terminator sequence
+                if (c==_term[lineendPos]) {
+                    lineendPos++;
+                    if (0==_term[lineendPos]) { // last char of term sequence -> finished
+                        return r;
+                    }
+                } else { // other characters
+                    int i=0;
+                    while (i<lineendPos) // add missed characters from term to string, if there are any
+                        r.push_back(_term[i++]);
+                    lineendPos=0;
+                    r.push_back(c);
+                }
+            }
+        } else {
+            int err=_socket->recv(_readbuf,BUFSIZE-1);
+            if (err < 0) {
+                printf("error while receiving data: %i!\n",err);
+                break;
+            } else if (err>0) {
+                emptyCount=0;
+                _readbuf[err]=0;
+                _readlen=err;
+                _readpos=0;
+//                printf("r=%s\n",_readbuf);
+            } else {
+                // when we don't receive any data, and are not connected
+                // we stop because there isn't anything left
+                if (emptyCount++>2)
+                    if (!_connected)
+                        break;
+            }
+        }
+        wait_us(100);
+    }
+    return r;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcplinestream.h	Sat Jan 29 22:42:14 2011 +0000
@@ -0,0 +1,41 @@
+#ifndef __TCPLINESTREAM__H__
+#define __TCPLINESTREAM__H__
+
+#include "TCPSocket.h"
+#include "string"
+
+#define BUFSIZE 1024
+
+using namespace std;
+
+class TCPLineStream
+{
+    public:
+        TCPLineStream(const char *host, int port, const char* _term="\r\n");
+        ~TCPLineStream(){close();};
+        bool open();
+        void close();
+        
+        string readLine(int strLen=64);
+        void sendLine(string line);
+        
+    private:
+        void init();
+        void onTCPSocketEvent(TCPSocketEvent e);
+        
+        const char *_server;
+        int _port;
+        
+        bool _connecting;
+        bool _connected;
+        bool _closed;
+        TCPSocket *_socket;
+
+        char _readbuf[BUFSIZE];
+        int _readpos;
+        int _readlen;
+        
+        const char* _term;
+};
+
+#endif
\ No newline at end of file