First step: AutoIP compiled in and working

Dependencies:   mbed

Committer:
darran
Date:
Fri Jun 18 15:54:21 2010 +0000
Revision:
1:4218cacaf696
Parent:
0:55a05330f8cc

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darran 0:55a05330f8cc 1
darran 0:55a05330f8cc 2 /*
darran 0:55a05330f8cc 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
darran 0:55a05330f8cc 4
darran 0:55a05330f8cc 5 Permission is hereby granted, free of charge, to any person obtaining a copy
darran 0:55a05330f8cc 6 of this software and associated documentation files (the "Software"), to deal
darran 0:55a05330f8cc 7 in the Software without restriction, including without limitation the rights
darran 0:55a05330f8cc 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
darran 0:55a05330f8cc 9 copies of the Software, and to permit persons to whom the Software is
darran 0:55a05330f8cc 10 furnished to do so, subject to the following conditions:
darran 0:55a05330f8cc 11
darran 0:55a05330f8cc 12 The above copyright notice and this permission notice shall be included in
darran 0:55a05330f8cc 13 all copies or substantial portions of the Software.
darran 0:55a05330f8cc 14
darran 0:55a05330f8cc 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
darran 0:55a05330f8cc 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
darran 0:55a05330f8cc 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
darran 0:55a05330f8cc 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
darran 0:55a05330f8cc 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
darran 0:55a05330f8cc 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
darran 0:55a05330f8cc 21 THE SOFTWARE.
darran 0:55a05330f8cc 22 */
darran 0:55a05330f8cc 23
darran 0:55a05330f8cc 24 #include "SMTPClient.h"
darran 0:55a05330f8cc 25
darran 0:55a05330f8cc 26 #if 0
darran 0:55a05330f8cc 27
darran 0:55a05330f8cc 28 #include <stdio.h>
darran 0:55a05330f8cc 29
darran 0:55a05330f8cc 30 #define __DEBUG
darran 0:55a05330f8cc 31 #include "dbg.h"
darran 0:55a05330f8cc 32
darran 0:55a05330f8cc 33 #define BUF_SIZE 128
darran 0:55a05330f8cc 34 #define CHUNK_SIZE 512
darran 0:55a05330f8cc 35
darran 0:55a05330f8cc 36 SMTPClient::SMTPClient() : m_pMessage(NULL), m_nextState(SMTP_HELLO),
darran 0:55a05330f8cc 37 m_pCbItem(NULL), m_pCbMeth(NULL), m_watchdog(), m_timeout(0), m_posInMsg(0), m_closed(true), m_host()
darran 0:55a05330f8cc 38 {
darran 0:55a05330f8cc 39 setTimeout(SMTP_REQUEST_TIMEOUT);
darran 0:55a05330f8cc 40 }
darran 0:55a05330f8cc 41
darran 0:55a05330f8cc 42 SMTPClient::~SMTPClient()
darran 0:55a05330f8cc 43 {
darran 0:55a05330f8cc 44 close();
darran 0:55a05330f8cc 45 }
darran 0:55a05330f8cc 46
darran 0:55a05330f8cc 47 void SMTPClient::setHost(const Host& host)
darran 0:55a05330f8cc 48 {
darran 0:55a05330f8cc 49 m_host = host;
darran 0:55a05330f8cc 50 }
darran 0:55a05330f8cc 51
darran 0:55a05330f8cc 52 void SMTPClient::send(EmailMessage* pMessage)
darran 0:55a05330f8cc 53 {
darran 0:55a05330f8cc 54 init();
darran 0:55a05330f8cc 55 m_posInMsg = 0;
darran 0:55a05330f8cc 56 m_nextState = SMTP_HELLO;
darran 0:55a05330f8cc 57 if( !m_pTCPSocket->connect(m_host) )
darran 0:55a05330f8cc 58 {
darran 0:55a05330f8cc 59 close();
darran 0:55a05330f8cc 60 onResult(SMTP_DISC);
darran 0:55a05330f8cc 61 }
darran 0:55a05330f8cc 62 }
darran 0:55a05330f8cc 63
darran 0:55a05330f8cc 64 void SMTPClient::init() //Create and setup socket if needed
darran 0:55a05330f8cc 65 {
darran 0:55a05330f8cc 66 close(); //Remove previous elements
darran 0:55a05330f8cc 67 if(!m_closed) //Already opened
darran 0:55a05330f8cc 68 return;
darran 0:55a05330f8cc 69 m_nextState = SMTP_HELLO;
darran 0:55a05330f8cc 70 m_pTCPSocket = new TCPSocket;
darran 0:55a05330f8cc 71 m_pTCPSocket->setOnEvent(this, &SMTPClient::onTCPSocketEvent);
darran 0:55a05330f8cc 72 m_closed = false;
darran 0:55a05330f8cc 73 }
darran 0:55a05330f8cc 74
darran 0:55a05330f8cc 75 void SMTPClient::close()
darran 0:55a05330f8cc 76 {
darran 0:55a05330f8cc 77 if(m_closed)
darran 0:55a05330f8cc 78 return;
darran 0:55a05330f8cc 79 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
darran 0:55a05330f8cc 80 m_watchdog.detach();
darran 0:55a05330f8cc 81 m_pTCPSocket->resetOnEvent();
darran 0:55a05330f8cc 82 m_pTCPSocket->close();
darran 0:55a05330f8cc 83 delete m_pTCPSocket;
darran 0:55a05330f8cc 84 m_pTCPSocket = NULL;
darran 0:55a05330f8cc 85 }
darran 0:55a05330f8cc 86
darran 0:55a05330f8cc 87 int SMTPClient::rc(char* buf) //Parse return code
darran 0:55a05330f8cc 88 {
darran 0:55a05330f8cc 89 int rc;
darran 0:55a05330f8cc 90 int len = sscanf(buf, "%d %*[^\r\n]\r\n", &rc);
darran 0:55a05330f8cc 91 if(len != 1)
darran 0:55a05330f8cc 92 return -1;
darran 0:55a05330f8cc 93 return rc;
darran 0:55a05330f8cc 94 }
darran 0:55a05330f8cc 95
darran 0:55a05330f8cc 96 #define MIN(a,b) ((a)<(b))?(a):(b)
darran 0:55a05330f8cc 97 void SMTPClient::process(bool moreData) //Main state-machine
darran 0:55a05330f8cc 98 {
darran 0:55a05330f8cc 99 char buf[BUF_SIZE] = {0};
darran 0:55a05330f8cc 100 if(moreData)
darran 0:55a05330f8cc 101 {
darran 0:55a05330f8cc 102 if( m_nextState != SMTP_BODYMORE )
darran 0:55a05330f8cc 103 {
darran 0:55a05330f8cc 104 return;
darran 0:55a05330f8cc 105 }
darran 0:55a05330f8cc 106 }
darran 0:55a05330f8cc 107 if(!moreData) //Receive next frame
darran 0:55a05330f8cc 108 {
darran 0:55a05330f8cc 109 m_pTCPSocket->recv(buf, BUF_SIZE - 1);
darran 0:55a05330f8cc 110 }
darran 0:55a05330f8cc 111
darran 0:55a05330f8cc 112 IpAddr myIp(0,0,0,0);
darran 0:55a05330f8cc 113 string to;
darran 0:55a05330f8cc 114 int sendLen;
darran 0:55a05330f8cc 115
darran 0:55a05330f8cc 116 DBG("In state %d", m_nextState);
darran 0:55a05330f8cc 117
darran 0:55a05330f8cc 118 switch(m_nextState)
darran 0:55a05330f8cc 119 {
darran 0:55a05330f8cc 120 case SMTP_HELLO:
darran 0:55a05330f8cc 121 if( rc(buf) != 220 )
darran 0:55a05330f8cc 122 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 123 myIp = Net::getDefaultIf()->getIp();
darran 0:55a05330f8cc 124 sprintf(buf, "HELO %d.%d.%d.%d\r\n", myIp[0], myIp[1], myIp[2], myIp[3]);
darran 0:55a05330f8cc 125 m_nextState = SMTP_FROM;
darran 0:55a05330f8cc 126 break;
darran 0:55a05330f8cc 127 case SMTP_FROM:
darran 0:55a05330f8cc 128 if( rc(buf) != 250 )
darran 0:55a05330f8cc 129 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 130 sprintf(buf, "MAIL FROM:<%s>\r\n", m_pMessage->m_from.c_str());
darran 0:55a05330f8cc 131 break;
darran 0:55a05330f8cc 132 case SMTP_TO:
darran 0:55a05330f8cc 133 if( rc(buf) != 250 )
darran 0:55a05330f8cc 134 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 135 to = m_pMessage->m_lTo.front();
darran 0:55a05330f8cc 136 sprintf(buf, "RCPT TO:<%s>\r\n", to.c_str());
darran 0:55a05330f8cc 137 m_pMessage->m_lTo.pop();
darran 0:55a05330f8cc 138 if(m_pMessage->m_lTo.empty())
darran 0:55a05330f8cc 139 {
darran 0:55a05330f8cc 140 m_nextState = SMTP_DATA;
darran 0:55a05330f8cc 141 }
darran 0:55a05330f8cc 142 break;
darran 0:55a05330f8cc 143 case SMTP_DATA:
darran 0:55a05330f8cc 144 if( rc(buf) != 250 )
darran 0:55a05330f8cc 145 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 146 sprintf(buf, "DATA\r\n");
darran 0:55a05330f8cc 147 break;
darran 0:55a05330f8cc 148 case SMTP_BODY:
darran 0:55a05330f8cc 149 if( rc(buf) != 354 )
darran 0:55a05330f8cc 150 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 151 m_nextState = SMTP_BODYMORE;
darran 0:55a05330f8cc 152 case SMTP_BODYMORE:
darran 0:55a05330f8cc 153 sendLen = 0;
darran 0:55a05330f8cc 154 if( m_posInMsg < m_pMessage->m_content.length() )
darran 0:55a05330f8cc 155 {
darran 0:55a05330f8cc 156 sendLen = MIN( (m_pMessage->m_content.length() - m_posInMsg), CHUNK_SIZE );
darran 0:55a05330f8cc 157 m_pTCPSocket->send( m_pMessage->m_content.c_str() + m_posInMsg, sendLen );
darran 0:55a05330f8cc 158 m_posInMsg += sendLen;
darran 0:55a05330f8cc 159 }
darran 0:55a05330f8cc 160 if( m_posInMsg == m_pMessage->m_content.length() )
darran 0:55a05330f8cc 161 {
darran 0:55a05330f8cc 162 sprintf(buf, "\r\n.\r\n"); //EOF
darran 0:55a05330f8cc 163 m_nextState = SMTP_EOF;
darran 0:55a05330f8cc 164 }
darran 0:55a05330f8cc 165 break;
darran 0:55a05330f8cc 166 case SMTP_EOF:
darran 0:55a05330f8cc 167 if( rc(buf) != 250 )
darran 0:55a05330f8cc 168 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 169 sprintf(buf, "QUIT\r\n");
darran 0:55a05330f8cc 170 m_nextState = SMTP_BYE;
darran 0:55a05330f8cc 171 break;
darran 0:55a05330f8cc 172 case SMTP_BYE:
darran 0:55a05330f8cc 173 if( rc(buf) != 221 )
darran 0:55a05330f8cc 174 { close(); onResult(SMTP_PRTCL); return; }
darran 0:55a05330f8cc 175 close();
darran 0:55a05330f8cc 176 onResult(SMTP_OK);
darran 0:55a05330f8cc 177 break;
darran 0:55a05330f8cc 178 }
darran 0:55a05330f8cc 179
darran 0:55a05330f8cc 180 if( m_nextState != SMTP_BODYMORE )
darran 0:55a05330f8cc 181 {
darran 0:55a05330f8cc 182 m_pTCPSocket->send( buf, strlen(buf) );
darran 0:55a05330f8cc 183 }
darran 0:55a05330f8cc 184 }
darran 0:55a05330f8cc 185
darran 0:55a05330f8cc 186 void SMTPClient::setTimeout(int ms)
darran 0:55a05330f8cc 187 {
darran 0:55a05330f8cc 188 m_timeout = 1000*ms;
darran 0:55a05330f8cc 189 resetTimeout();
darran 0:55a05330f8cc 190 }
darran 0:55a05330f8cc 191
darran 0:55a05330f8cc 192 void SMTPClient::resetTimeout()
darran 0:55a05330f8cc 193 {
darran 0:55a05330f8cc 194 m_watchdog.detach();
darran 0:55a05330f8cc 195 m_watchdog.attach_us<SMTPClient>(this, &SMTPClient::onTimeout, m_timeout);
darran 0:55a05330f8cc 196 }
darran 0:55a05330f8cc 197
darran 0:55a05330f8cc 198 void SMTPClient::onTimeout() //Connection has timed out
darran 0:55a05330f8cc 199 {
darran 0:55a05330f8cc 200 close();
darran 0:55a05330f8cc 201 onResult(SMTP_TIMEOUT);
darran 0:55a05330f8cc 202 }
darran 0:55a05330f8cc 203
darran 0:55a05330f8cc 204 void SMTPClient::onTCPSocketEvent(TCPSocketEvent e)
darran 0:55a05330f8cc 205 {
darran 0:55a05330f8cc 206 switch(e)
darran 0:55a05330f8cc 207 {
darran 0:55a05330f8cc 208 case TCPSOCKET_READABLE:
darran 0:55a05330f8cc 209 resetTimeout();
darran 0:55a05330f8cc 210 process(false);
darran 0:55a05330f8cc 211 break;
darran 0:55a05330f8cc 212 case TCPSOCKET_WRITEABLE:
darran 0:55a05330f8cc 213 resetTimeout();
darran 0:55a05330f8cc 214 process(true);
darran 0:55a05330f8cc 215 break;
darran 0:55a05330f8cc 216 case TCPSOCKET_CONTIMEOUT:
darran 0:55a05330f8cc 217 case TCPSOCKET_CONRST:
darran 0:55a05330f8cc 218 case TCPSOCKET_CONABRT:
darran 0:55a05330f8cc 219 case TCPSOCKET_ERROR:
darran 0:55a05330f8cc 220 onResult(SMTP_DISC);
darran 0:55a05330f8cc 221 DBG("\r\nConnection error in SMTP Client.\r\n");
darran 0:55a05330f8cc 222 close();
darran 0:55a05330f8cc 223 break;
darran 0:55a05330f8cc 224 case TCPSOCKET_DISCONNECTED:
darran 0:55a05330f8cc 225 if(m_nextState != SMTP_BYE)
darran 0:55a05330f8cc 226 {
darran 0:55a05330f8cc 227 onResult(SMTP_DISC);
darran 0:55a05330f8cc 228 DBG("\r\nConnection error in SMTP Client.\r\n");
darran 0:55a05330f8cc 229 close();
darran 0:55a05330f8cc 230 }
darran 0:55a05330f8cc 231 break;
darran 0:55a05330f8cc 232 }
darran 0:55a05330f8cc 233 }
darran 0:55a05330f8cc 234
darran 0:55a05330f8cc 235 void SMTPClient::onResult(SMTPResult r) //Must be called by impl when the request completes
darran 0:55a05330f8cc 236 {
darran 0:55a05330f8cc 237 if(m_pCbItem && m_pCbMeth)
darran 0:55a05330f8cc 238 (m_pCbItem->*m_pCbMeth)(r);
darran 0:55a05330f8cc 239 }
darran 0:55a05330f8cc 240
darran 0:55a05330f8cc 241 #endif