Ilya I / Mbed 2 deprecated iva2k_NetHttpServerTcpSockets

Dependencies:   mbed

Committer:
iva2k
Date:
Mon Jun 14 03:24:33 2010 +0000
Revision:
1:3ee499525aa5
Parent:
0:e614f7875b60

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iva2k 0:e614f7875b60 1
iva2k 0:e614f7875b60 2 /*
iva2k 0:e614f7875b60 3 Copyright (c) 2010 IVA2K
iva2k 0:e614f7875b60 4
iva2k 0:e614f7875b60 5 Permission is hereby granted, free of charge, to any person obtaining a copy
iva2k 0:e614f7875b60 6 of this software and associated documentation files (the "Software"), to deal
iva2k 0:e614f7875b60 7 in the Software without restriction, including without limitation the rights
iva2k 0:e614f7875b60 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
iva2k 0:e614f7875b60 9 copies of the Software, and to permit persons to whom the Software is
iva2k 0:e614f7875b60 10 furnished to do so, subject to the following conditions:
iva2k 0:e614f7875b60 11
iva2k 0:e614f7875b60 12 The above copyright notice and this permission notice shall be included in
iva2k 0:e614f7875b60 13 all copies or substantial portions of the Software.
iva2k 0:e614f7875b60 14
iva2k 0:e614f7875b60 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
iva2k 0:e614f7875b60 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
iva2k 0:e614f7875b60 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
iva2k 0:e614f7875b60 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
iva2k 0:e614f7875b60 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
iva2k 0:e614f7875b60 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
iva2k 0:e614f7875b60 21 THE SOFTWARE.
iva2k 0:e614f7875b60 22 */
iva2k 0:e614f7875b60 23
iva2k 0:e614f7875b60 24 #include "StreamServer.h"
iva2k 0:e614f7875b60 25
iva2k 0:e614f7875b60 26 #include "dbg/dbg.h"
iva2k 0:e614f7875b60 27
iva2k 0:e614f7875b60 28
iva2k 0:e614f7875b60 29 //BEGIN REQUEST DISPATCHER======================================================
iva2k 0:e614f7875b60 30 StreamRequestDispatcher::StreamRequestDispatcher(StreamServer* pSvr, TCPSocket* pTcpSocket)
iva2k 0:e614f7875b60 31 : NetService(), m_pSvr(pSvr), m_pTcpSocket(pTcpSocket), m_closed(false)
iva2k 0:e614f7875b60 32 {
iva2k 0:e614f7875b60 33 m_pTcpSocket->setOnEvent(this, &StreamRequestDispatcher::onTcpSocketEvent);
iva2k 0:e614f7875b60 34 }
iva2k 0:e614f7875b60 35
iva2k 0:e614f7875b60 36 StreamRequestDispatcher::~StreamRequestDispatcher()
iva2k 0:e614f7875b60 37 {
iva2k 1:3ee499525aa5 38 //DBG("deleting\r\n");
iva2k 0:e614f7875b60 39 close();
iva2k 0:e614f7875b60 40 }
iva2k 0:e614f7875b60 41
iva2k 0:e614f7875b60 42 int StreamRequestDispatcher::writeData(const char* buf, int len)
iva2k 0:e614f7875b60 43 {
iva2k 0:e614f7875b60 44 if(m_closed) {
iva2k 1:3ee499525aa5 45 //DBG("m_closed\r\n");
iva2k 0:e614f7875b60 46 return TCPSOCKET_RST;
iva2k 0:e614f7875b60 47 }
iva2k 0:e614f7875b60 48 int ret = m_pTcpSocket->send(buf, len);
iva2k 1:3ee499525aa5 49 if (ret != len) DBG("ret=%d\r\n", ret);
iva2k 0:e614f7875b60 50 return ret;
iva2k 0:e614f7875b60 51 }
iva2k 0:e614f7875b60 52
iva2k 0:e614f7875b60 53 //FIXME: Need implementation for StreamServer
iva2k 0:e614f7875b60 54 void StreamRequestDispatcher::dispatchRequest()
iva2k 0:e614f7875b60 55 {
iva2k 0:e614f7875b60 56 string request;
iva2k 0:e614f7875b60 57 const char* buf;
iva2k 0:e614f7875b60 58 int len, ret;
iva2k 1:3ee499525aa5 59 // DBG("\r\n");
iva2k 0:e614f7875b60 60
iva2k 1:3ee499525aa5 61 //FIXME: here is the place to implement custom request handler
iva2k 1:3ee499525aa5 62
iva2k 0:e614f7875b60 63 while ( getRequest(&request) )
iva2k 0:e614f7875b60 64 {
iva2k 0:e614f7875b60 65 // Just echo it back
iva2k 0:e614f7875b60 66 buf = request.c_str();
iva2k 0:e614f7875b60 67 len = strlen(buf);
iva2k 0:e614f7875b60 68 ret = writeData(buf,len);
iva2k 0:e614f7875b60 69 writeData("\r\n",2);
iva2k 1:3ee499525aa5 70 DBG("Received req (%s), write ret=%d\r\n", buf, ret);
iva2k 0:e614f7875b60 71 }
iva2k 0:e614f7875b60 72 }
iva2k 0:e614f7875b60 73
iva2k 0:e614f7875b60 74 void StreamRequestDispatcher::close() //Close socket and destroy data
iva2k 0:e614f7875b60 75 {
iva2k 1:3ee499525aa5 76 if(m_closed) {
iva2k 1:3ee499525aa5 77 //DBG("already closed\r\n");
iva2k 0:e614f7875b60 78 return;
iva2k 1:3ee499525aa5 79 }
iva2k 0:e614f7875b60 80 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
iva2k 1:3ee499525aa5 81 //DBG("removing from list\r\n");
iva2k 0:e614f7875b60 82 m_pSvr->m_lpClients.remove(this);
iva2k 0:e614f7875b60 83 if(m_pTcpSocket)
iva2k 0:e614f7875b60 84 {
iva2k 1:3ee499525aa5 85 //DBG("closing socket\r\n");
iva2k 0:e614f7875b60 86 m_pTcpSocket->resetOnEvent();
iva2k 1:3ee499525aa5 87 m_pTcpSocket->close(); // FIXME: in bad cause of events, getting "could not close properly, abort" log message
iva2k 0:e614f7875b60 88 delete m_pTcpSocket;
iva2k 0:e614f7875b60 89 }
iva2k 1:3ee499525aa5 90 //DBG("closing service\r\n");
iva2k 0:e614f7875b60 91 NetService::close();
iva2k 0:e614f7875b60 92 }
iva2k 0:e614f7875b60 93
iva2k 0:e614f7875b60 94 bool StreamRequestDispatcher::getRequest(string* request)
iva2k 0:e614f7875b60 95 {
iva2k 0:e614f7875b60 96 const int maxLen = 64;
iva2k 0:e614f7875b60 97 char req[maxLen];
iva2k 0:e614f7875b60 98 //Read Line
iva2k 0:e614f7875b60 99 int ret;
iva2k 0:e614f7875b60 100 int len = 0;
iva2k 0:e614f7875b60 101 char* p = req;
iva2k 0:e614f7875b60 102 for(int i = 0; i < maxLen - 1; i++)
iva2k 0:e614f7875b60 103 {
iva2k 0:e614f7875b60 104 ret = m_pTcpSocket->recv(p, 1);
iva2k 0:e614f7875b60 105 //FIXME: handle errors here (ret < 0)?
iva2k 0:e614f7875b60 106 if(!ret)
iva2k 0:e614f7875b60 107 {
iva2k 0:e614f7875b60 108 break;
iva2k 0:e614f7875b60 109 }
iva2k 0:e614f7875b60 110 #if 1
iva2k 0:e614f7875b60 111 // Consider incoming symbols - line ends etc.
iva2k 0:e614f7875b60 112 if( (len > 1) && *(p-1)=='\r' && *p=='\n' )
iva2k 0:e614f7875b60 113 {
iva2k 0:e614f7875b60 114 p--;
iva2k 0:e614f7875b60 115 len-=2;
iva2k 0:e614f7875b60 116 break;
iva2k 0:e614f7875b60 117 }
iva2k 0:e614f7875b60 118 else if( *p=='\n' )
iva2k 0:e614f7875b60 119 {
iva2k 0:e614f7875b60 120 len--;
iva2k 0:e614f7875b60 121 break;
iva2k 0:e614f7875b60 122 }
iva2k 0:e614f7875b60 123 #endif
iva2k 0:e614f7875b60 124 p++;
iva2k 0:e614f7875b60 125 len++;
iva2k 0:e614f7875b60 126 }
iva2k 0:e614f7875b60 127 *p = 0;
iva2k 0:e614f7875b60 128
iva2k 1:3ee499525aa5 129 DBG("Parsing request (%s) ret=%d\r\n", req, ret);
iva2k 0:e614f7875b60 130
iva2k 0:e614f7875b60 131 *request = string(req);
iva2k 0:e614f7875b60 132
iva2k 0:e614f7875b60 133 return (len > 0);
iva2k 0:e614f7875b60 134 }
iva2k 0:e614f7875b60 135
iva2k 0:e614f7875b60 136
iva2k 0:e614f7875b60 137 void StreamRequestDispatcher::onTcpSocketEvent(TCPSocketEvent e)
iva2k 0:e614f7875b60 138 {
iva2k 1:3ee499525aa5 139 DBG("Event %d\r\n", e);
iva2k 0:e614f7875b60 140
iva2k 0:e614f7875b60 141 if(m_closed)
iva2k 0:e614f7875b60 142 {
iva2k 1:3ee499525aa5 143 DBG("WARN: Discarded\r\n");
iva2k 0:e614f7875b60 144 return;
iva2k 0:e614f7875b60 145 }
iva2k 0:e614f7875b60 146
iva2k 0:e614f7875b60 147 switch(e)
iva2k 0:e614f7875b60 148 {
iva2k 0:e614f7875b60 149 case TCPSOCKET_READABLE:
iva2k 0:e614f7875b60 150 //Req arrived, dispatch :
iva2k 0:e614f7875b60 151 dispatchRequest();
iva2k 0:e614f7875b60 152 break;
iva2k 0:e614f7875b60 153 case TCPSOCKET_CONTIMEOUT:
iva2k 0:e614f7875b60 154 case TCPSOCKET_CONRST:
iva2k 0:e614f7875b60 155 case TCPSOCKET_CONABRT:
iva2k 0:e614f7875b60 156 case TCPSOCKET_ERROR:
iva2k 0:e614f7875b60 157 case TCPSOCKET_DISCONNECTED:
iva2k 0:e614f7875b60 158 close();
iva2k 0:e614f7875b60 159 break;
iva2k 0:e614f7875b60 160 }
iva2k 0:e614f7875b60 161
iva2k 0:e614f7875b60 162 }
iva2k 0:e614f7875b60 163 //END REQUEST DISPATCHER========================================================
iva2k 0:e614f7875b60 164
iva2k 0:e614f7875b60 165
iva2k 0:e614f7875b60 166 StreamServer::StreamServer()
iva2k 0:e614f7875b60 167 {
iva2k 0:e614f7875b60 168 m_pTcpSocket = new TCPSocket;
iva2k 0:e614f7875b60 169 m_pTcpSocket->setOnEvent(this, &StreamServer::onTcpSocketEvent);
iva2k 0:e614f7875b60 170 }
iva2k 0:e614f7875b60 171
iva2k 0:e614f7875b60 172 StreamServer::~StreamServer()
iva2k 0:e614f7875b60 173 {
iva2k 0:e614f7875b60 174 delete m_pTcpSocket;
iva2k 0:e614f7875b60 175 }
iva2k 0:e614f7875b60 176
iva2k 0:e614f7875b60 177 void StreamServer::bind(int port /*= 123*/)
iva2k 0:e614f7875b60 178 {
iva2k 0:e614f7875b60 179 Host h(IpAddr(127,0,0,1), port, "localhost");
iva2k 0:e614f7875b60 180 m_pTcpSocket->bind(h);
iva2k 0:e614f7875b60 181 m_pTcpSocket->listen(); //Listen
iva2k 0:e614f7875b60 182 }
iva2k 0:e614f7875b60 183
iva2k 0:e614f7875b60 184 #if 0 //Just for clarity
iva2k 0:e614f7875b60 185 template<typename T>
iva2k 0:e614f7875b60 186 void StreamServer::addHandler(const char* path)
iva2k 0:e614f7875b60 187 {
iva2k 0:e614f7875b60 188 // m_lpHandlers[path] = &T::inst;
iva2k 0:e614f7875b60 189 }
iva2k 0:e614f7875b60 190 #endif
iva2k 0:e614f7875b60 191
iva2k 0:e614f7875b60 192 void StreamServer::sendToAll(const char* buf, int len)
iva2k 0:e614f7875b60 193 {
iva2k 0:e614f7875b60 194 int ret;
iva2k 0:e614f7875b60 195 int i = 0;
iva2k 1:3ee499525aa5 196 tClients::iterator it;
iva2k 1:3ee499525aa5 197 for(it = m_lpClients.begin(); it != m_lpClients.end(); /* No increment here */ )
iva2k 0:e614f7875b60 198 {
iva2k 0:e614f7875b60 199 ret = (*it)->writeData(buf, len);
iva2k 0:e614f7875b60 200 if (
iva2k 0:e614f7875b60 201 ret == TCPSOCKET_RST // This is a safety valve. We should have self-removed from m_lpClients upon socket closure and not get here.
iva2k 0:e614f7875b60 202 || ret == TCPSOCKET_MEM // This probably means that network is not delivering packets, and we're backed up.
iva2k 0:e614f7875b60 203 ) {
iva2k 1:3ee499525aa5 204 DBG("(%s) Socket error 0x%04X - erasing socket %d\r\n", buf, ret, i);
iva2k 1:3ee499525aa5 205 // delete below will remove (*it) from the list we are iterating in. Prepare for that
iva2k 1:3ee499525aa5 206 tClients::iterator it_next = it;
iva2k 1:3ee499525aa5 207 it_next++;
iva2k 0:e614f7875b60 208 delete (*it);
iva2k 1:3ee499525aa5 209 it = it_next;
iva2k 1:3ee499525aa5 210 continue; // This ensures that for(...) above will continue properly.
iva2k 0:e614f7875b60 211 }
iva2k 0:e614f7875b60 212 i++;
iva2k 1:3ee499525aa5 213 it++; /* increment the iterator */
iva2k 0:e614f7875b60 214 }
iva2k 1:3ee499525aa5 215 }
iva2k 1:3ee499525aa5 216
iva2k 1:3ee499525aa5 217 int StreamServer::countClients(void)
iva2k 1:3ee499525aa5 218 {
iva2k 1:3ee499525aa5 219 return m_lpClients.size();
iva2k 0:e614f7875b60 220 }
iva2k 0:e614f7875b60 221
iva2k 0:e614f7875b60 222 void StreamServer::onTcpSocketEvent(TCPSocketEvent e)
iva2k 0:e614f7875b60 223 {
iva2k 0:e614f7875b60 224
iva2k 1:3ee499525aa5 225 DBG("Event %d\r\n", e);
iva2k 0:e614f7875b60 226
iva2k 0:e614f7875b60 227 if(e==TCPSOCKET_ACCEPT)
iva2k 0:e614f7875b60 228 {
iva2k 0:e614f7875b60 229 TCPSocket* pTcpSocket;
iva2k 0:e614f7875b60 230 Host client;
iva2k 0:e614f7875b60 231
iva2k 0:e614f7875b60 232 if( !!m_pTcpSocket->accept(&client, &pTcpSocket) )
iva2k 0:e614f7875b60 233 {
iva2k 1:3ee499525aa5 234 DBG("Could not accept connection.\r\n");
iva2k 0:e614f7875b60 235 return; //Error in accept, discard connection
iva2k 0:e614f7875b60 236 }
iva2k 0:e614f7875b60 237
iva2k 0:e614f7875b60 238 StreamRequestDispatcher* pDispatcher = new StreamRequestDispatcher(this, pTcpSocket); //TcpSocket ownership is passed to dispatcher
iva2k 0:e614f7875b60 239 //The dispatcher object will destroy itself when its socket closes, or will be destroyed on Server destruction
iva2k 0:e614f7875b60 240 m_lpClients.push_back(pDispatcher);
iva2k 0:e614f7875b60 241 }
iva2k 0:e614f7875b60 242 }
iva2k 1:3ee499525aa5 243
iva2k 1:3ee499525aa5 244 //END