A simple class to do line-based TCP communication. To be used with the NetServicesMin library-.
tcplinestream.cpp
- Committer:
- hlipka
- Date:
- 2011-02-18
- Revision:
- 1:28416a5a4ec5
- Parent:
- 0:f2727a16072f
File content as of revision 1:28416a5a4ec5:
/* * TcpLineStream library * Copyright (c) 2010 Hendrik Lipka * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #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; }