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

Dependents:   pop3demo

Committer:
hlipka
Date:
Sat Jan 29 22:42:14 2011 +0000
Revision:
0:f2727a16072f
Child:
1:28416a5a4ec5
initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hlipka 0:f2727a16072f 1 #include "Timer.h"
hlipka 0:f2727a16072f 2
hlipka 0:f2727a16072f 3 #include "tcplinestream.h"
hlipka 0:f2727a16072f 4
hlipka 0:f2727a16072f 5 #include "dnsresolve.h"
hlipka 0:f2727a16072f 6
hlipka 0:f2727a16072f 7 void TCPLineStream::onTCPSocketEvent(TCPSocketEvent e) {
hlipka 0:f2727a16072f 8 // printf("New TCPSocketEvent: %d\n",e);
hlipka 0:f2727a16072f 9 switch (e) {
hlipka 0:f2727a16072f 10 case TCPSOCKET_CONNECTED:
hlipka 0:f2727a16072f 11 _connected = true;
hlipka 0:f2727a16072f 12 _connecting=false;
hlipka 0:f2727a16072f 13 break;
hlipka 0:f2727a16072f 14
hlipka 0:f2727a16072f 15 case TCPSOCKET_READABLE:
hlipka 0:f2727a16072f 16 break;
hlipka 0:f2727a16072f 17 case TCPSOCKET_WRITEABLE:
hlipka 0:f2727a16072f 18 break;
hlipka 0:f2727a16072f 19
hlipka 0:f2727a16072f 20 case TCPSOCKET_CONTIMEOUT:
hlipka 0:f2727a16072f 21 case TCPSOCKET_CONRST:
hlipka 0:f2727a16072f 22 case TCPSOCKET_CONABRT:
hlipka 0:f2727a16072f 23 case TCPSOCKET_ERROR:
hlipka 0:f2727a16072f 24 case TCPSOCKET_DISCONNECTED: {
hlipka 0:f2727a16072f 25 // don't close the real socket here, as this may skip the already received data
hlipka 0:f2727a16072f 26 _connected = false;
hlipka 0:f2727a16072f 27 _connecting=false;
hlipka 0:f2727a16072f 28 }
hlipka 0:f2727a16072f 29 break;
hlipka 0:f2727a16072f 30 }
hlipka 0:f2727a16072f 31 }
hlipka 0:f2727a16072f 32
hlipka 0:f2727a16072f 33 TCPLineStream::TCPLineStream(const char *server, int port, const char* term) {
hlipka 0:f2727a16072f 34 _server=server;
hlipka 0:f2727a16072f 35 _port=port;
hlipka 0:f2727a16072f 36 _term=term;
hlipka 0:f2727a16072f 37 }
hlipka 0:f2727a16072f 38
hlipka 0:f2727a16072f 39 bool TCPLineStream::open() {
hlipka 0:f2727a16072f 40 _closed=false;
hlipka 0:f2727a16072f 41 _readpos=0;
hlipka 0:f2727a16072f 42 _readlen=0;
hlipka 0:f2727a16072f 43
hlipka 0:f2727a16072f 44 _socket=new TCPSocket();
hlipka 0:f2727a16072f 45 _socket->setOnEvent(this,&TCPLineStream::onTCPSocketEvent);
hlipka 0:f2727a16072f 46
hlipka 0:f2727a16072f 47 IpAddr addr;
hlipka 0:f2727a16072f 48 // ignore IP adress - is !null even if it is 0.0.0.0
hlipka 0:f2727a16072f 49 // so do DNS if a name is given
hlipka 0:f2727a16072f 50 if (NULL!=_server) {
hlipka 0:f2727a16072f 51 // printf("do DNS request for %s\n",_server);
hlipka 0:f2727a16072f 52 DNSResolver dr;
hlipka 0:f2727a16072f 53 addr=dr.resolveName(_server);
hlipka 0:f2727a16072f 54 }
hlipka 0:f2727a16072f 55 // printf("server=%i.%i.%i.%i/%i\n",addr[0],addr[1],addr[2],addr[3],_port);
hlipka 0:f2727a16072f 56
hlipka 0:f2727a16072f 57 Host host(addr, _port);
hlipka 0:f2727a16072f 58
hlipka 0:f2727a16072f 59 // printf("connect\n");
hlipka 0:f2727a16072f 60 TCPSocketErr bindErr = _socket->connect(host);
hlipka 0:f2727a16072f 61
hlipka 0:f2727a16072f 62 if (bindErr != 0) {
hlipka 0:f2727a16072f 63 printf("connection bind error %i\n", bindErr);
hlipka 0:f2727a16072f 64 return false;
hlipka 0:f2727a16072f 65 }
hlipka 0:f2727a16072f 66 // printf("connecting\n");
hlipka 0:f2727a16072f 67 // wait for connection established
hlipka 0:f2727a16072f 68 _connecting=true;
hlipka 0:f2727a16072f 69 mbed::Timer tmr;
hlipka 0:f2727a16072f 70 tmr.start();
hlipka 0:f2727a16072f 71 tmr.reset();
hlipka 0:f2727a16072f 72
hlipka 0:f2727a16072f 73 while (_connecting) {
hlipka 0:f2727a16072f 74 Net::poll();
hlipka 0:f2727a16072f 75 wait_us(100);
hlipka 0:f2727a16072f 76 if (tmr.read()>20) {
hlipka 0:f2727a16072f 77 printf("error: reached timeout\n");
hlipka 0:f2727a16072f 78 break;
hlipka 0:f2727a16072f 79 }
hlipka 0:f2727a16072f 80 }
hlipka 0:f2727a16072f 81 if (!_connected) {
hlipka 0:f2727a16072f 82 printf("error - could not connect (timeout)\n");
hlipka 0:f2727a16072f 83 return false;
hlipka 0:f2727a16072f 84 }
hlipka 0:f2727a16072f 85 // printf("connected\n");
hlipka 0:f2727a16072f 86 return true;
hlipka 0:f2727a16072f 87 }
hlipka 0:f2727a16072f 88
hlipka 0:f2727a16072f 89 void TCPLineStream::sendLine(string line) {
hlipka 0:f2727a16072f 90 // printf("send request[%s]\n",line.c_str());
hlipka 0:f2727a16072f 91 _socket->send(line.append(_term).c_str(),line.length()+strlen(_term));
hlipka 0:f2727a16072f 92 Net::poll();
hlipka 0:f2727a16072f 93 }
hlipka 0:f2727a16072f 94
hlipka 0:f2727a16072f 95 void TCPLineStream::close() {
hlipka 0:f2727a16072f 96 if (_closed)
hlipka 0:f2727a16072f 97 return;
hlipka 0:f2727a16072f 98
hlipka 0:f2727a16072f 99 while (_connected) {
hlipka 0:f2727a16072f 100 Net::poll();
hlipka 0:f2727a16072f 101 // read remaining data
hlipka 0:f2727a16072f 102 int err=_socket->recv(_readbuf,BUFSIZE-1);
hlipka 0:f2727a16072f 103 if (err<=0)
hlipka 0:f2727a16072f 104 break;
hlipka 0:f2727a16072f 105 }
hlipka 0:f2727a16072f 106
hlipka 0:f2727a16072f 107 while (true) {
hlipka 0:f2727a16072f 108 Net::poll();
hlipka 0:f2727a16072f 109 // read remaining data
hlipka 0:f2727a16072f 110 int err=_socket->recv(_readbuf,BUFSIZE-1);
hlipka 0:f2727a16072f 111 if (err<=0)
hlipka 0:f2727a16072f 112 break;
hlipka 0:f2727a16072f 113 }
hlipka 0:f2727a16072f 114
hlipka 0:f2727a16072f 115 _socket->resetOnEvent();
hlipka 0:f2727a16072f 116 _socket->close();
hlipka 0:f2727a16072f 117 delete _socket;
hlipka 0:f2727a16072f 118 _closed=true;
hlipka 0:f2727a16072f 119 }
hlipka 0:f2727a16072f 120
hlipka 0:f2727a16072f 121 string TCPLineStream::readLine(int strLen) {
hlipka 0:f2727a16072f 122 string r;
hlipka 0:f2727a16072f 123 r.reserve(strLen);
hlipka 0:f2727a16072f 124
hlipka 0:f2727a16072f 125 int emptyCount=0;
hlipka 0:f2727a16072f 126 int lineendPos=0;
hlipka 0:f2727a16072f 127 while (true) {
hlipka 0:f2727a16072f 128 Net::poll();
hlipka 0:f2727a16072f 129 if (_readlen>_readpos) {
hlipka 0:f2727a16072f 130 while (_readbuf[_readpos]!=0 && _readpos<_readlen) {
hlipka 0:f2727a16072f 131 char c=_readbuf[_readpos++];
hlipka 0:f2727a16072f 132 //if the current char is the right one of the line terminator sequence
hlipka 0:f2727a16072f 133 if (c==_term[lineendPos]) {
hlipka 0:f2727a16072f 134 lineendPos++;
hlipka 0:f2727a16072f 135 if (0==_term[lineendPos]) { // last char of term sequence -> finished
hlipka 0:f2727a16072f 136 return r;
hlipka 0:f2727a16072f 137 }
hlipka 0:f2727a16072f 138 } else { // other characters
hlipka 0:f2727a16072f 139 int i=0;
hlipka 0:f2727a16072f 140 while (i<lineendPos) // add missed characters from term to string, if there are any
hlipka 0:f2727a16072f 141 r.push_back(_term[i++]);
hlipka 0:f2727a16072f 142 lineendPos=0;
hlipka 0:f2727a16072f 143 r.push_back(c);
hlipka 0:f2727a16072f 144 }
hlipka 0:f2727a16072f 145 }
hlipka 0:f2727a16072f 146 } else {
hlipka 0:f2727a16072f 147 int err=_socket->recv(_readbuf,BUFSIZE-1);
hlipka 0:f2727a16072f 148 if (err < 0) {
hlipka 0:f2727a16072f 149 printf("error while receiving data: %i!\n",err);
hlipka 0:f2727a16072f 150 break;
hlipka 0:f2727a16072f 151 } else if (err>0) {
hlipka 0:f2727a16072f 152 emptyCount=0;
hlipka 0:f2727a16072f 153 _readbuf[err]=0;
hlipka 0:f2727a16072f 154 _readlen=err;
hlipka 0:f2727a16072f 155 _readpos=0;
hlipka 0:f2727a16072f 156 // printf("r=%s\n",_readbuf);
hlipka 0:f2727a16072f 157 } else {
hlipka 0:f2727a16072f 158 // when we don't receive any data, and are not connected
hlipka 0:f2727a16072f 159 // we stop because there isn't anything left
hlipka 0:f2727a16072f 160 if (emptyCount++>2)
hlipka 0:f2727a16072f 161 if (!_connected)
hlipka 0:f2727a16072f 162 break;
hlipka 0:f2727a16072f 163 }
hlipka 0:f2727a16072f 164 }
hlipka 0:f2727a16072f 165 wait_us(100);
hlipka 0:f2727a16072f 166 }
hlipka 0:f2727a16072f 167 return r;
hlipka 0:f2727a16072f 168 }
hlipka 0:f2727a16072f 169