/*This file has been prepared for Doxygen automatic documentation generation.*/ | |
/*! \file ********************************************************************* | |
* | |
* \brief Basic SMTP Client for AVR32 UC3. | |
* | |
* - Compiler: GNU GCC for AVR32 | |
* - Supported devices: All AVR32 devices can be used. | |
* - AppNote: | |
* | |
* \author Atmel Corporation: http://www.atmel.com \n | |
* Support and FAQ: http://support.atmel.no/ | |
* | |
*****************************************************************************/ | |
/* Copyright (c) 2007, Atmel Corporation All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* | |
* 3. The name of ATMEL may not be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND | |
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, | |
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
/* | |
Implements a simplistic SMTP client. First time the task is started, connection is made and | |
email is sent. Mail flag is then reset. Each time you press the Push Button 0, a new mail will be sent. | |
*/ | |
#if (SMTP_USED == 1) | |
#include <string.h> | |
// Scheduler includes. | |
#include "FreeRTOS.h" | |
#include "task.h" | |
#include "BasicSMTP.h" | |
// Demo includes. | |
#include "portmacro.h" | |
#include "partest.h" | |
#include "intc.h" | |
#include "gpio.h" | |
// lwIP includes. | |
#include "lwip/api.h" | |
#include "lwip/tcpip.h" | |
#include "lwip/memp.h" | |
#include "lwip/stats.h" | |
#include "lwip/opt.h" | |
#include "lwip/api.h" | |
#include "lwip/arch.h" | |
#include "lwip/sys.h" | |
#include "lwip/sockets.h" | |
#include "netif/loopif.h" | |
//! SMTP default port | |
#define SMTP_PORT 25 | |
//! SMTP EHLO code answer | |
#define SMTP_EHLO_STRING "220" | |
//! SMTP end of transmission code answer | |
#define SMTP_END_OF_TRANSMISSION_STRING "221" | |
//! SMTP OK code answer | |
#define SMTP_OK_STRING "250" | |
//! SMTP start of transmission code answer | |
#define SMTP_START_OF_TRANSMISSION_STRING "354" | |
//! SMTP DATA<CRLF> | |
#define SMTP_DATA_STRING "DATA\r\n" | |
//! SMTP <CRLF>.<CRLF> | |
#define SMTP_MAIL_END_STRING "\r\n.\r\n" | |
//! SMTP QUIT<CRLFCRLF> | |
#define SMTP_QUIT_STRING "QUIT\r\n" | |
//! Server address | |
#error configure SMTP server address | |
char cServer[] = "192.168.0.1"; | |
//! Fill here the mailfrom with your mail address | |
#error configure SMTP mail sender | |
char cMailfrom[] = "MAIL FROM: <sender@domain.com>\r\n"; | |
//! Fill here the mailto with your contact mail address | |
#error configure SMTP mail recipient | |
char cMailto[] = "RCPT TO: <recipient@domain.com>\r\n"; | |
//! Fill here the mailcontent with the mail you want to send | |
#error configure SMTP mail content | |
char cMailcontent[] ="Subject: *** SPAM ***\r\nFROM: \"Your Name here\" <sender@domain.com>\r\nTO: \"Your Contact here\" <recipient@domain.com>\r\n\r\nSay what you want here."; | |
//! flag to send mail | |
Bool bSendMail = pdFALSE; | |
//! buffer for SMTP response | |
char cTempBuffer[200]; | |
//_____ D E C L A R A T I O N S ____________________________________________ | |
//! interrupt handler. | |
#if __GNUC__ | |
__attribute__((naked)) | |
#elif __ICCAVR32__ | |
#pragma shadow_registers = full // Naked. | |
#endif | |
void vpushb_ISR( void ); | |
//! soft interrupt handler. where treatment should be done | |
#if __GNUC__ | |
__attribute__((__noinline__)) | |
#endif | |
static portBASE_TYPE prvpushb_ISR_NonNakedBehaviour( void ); | |
//! Basic SMTP client task definition | |
portTASK_FUNCTION( vBasicSMTPClient, pvParameters ) | |
{ | |
struct sockaddr_in stServeurSockAddr; | |
long lRetval; | |
long lSocket = -1; | |
// configure push button 0 to produce IT on falling edge | |
gpio_enable_pin_interrupt(GPIO_PUSH_BUTTON_0 , GPIO_FALLING_EDGE); | |
// Disable all interrupts | |
vPortEnterCritical(); | |
// register push button 0 handler on level 3 | |
INTC_register_interrupt( (__int_handler)&vpushb_ISR, AVR32_GPIO_IRQ_0 + (GPIO_PUSH_BUTTON_0/8), INT3); | |
// Enable all interrupts | |
vPortExitCritical(); | |
for (;;) | |
{ | |
// wait for a signal to send a mail | |
while (bSendMail != pdTRUE) vTaskDelay(200); | |
// Disable all interrupts | |
vPortEnterCritical(); | |
// clear the flag | |
bSendMail = pdFALSE; | |
// Enable all interrupts | |
vPortExitCritical(); | |
// clear the LED | |
vParTestSetLED( 3 , pdFALSE ); | |
// Set up port | |
memset(&stServeurSockAddr, 0, sizeof(stServeurSockAddr)); | |
stServeurSockAddr.sin_len = sizeof(stServeurSockAddr); | |
stServeurSockAddr.sin_addr.s_addr = inet_addr(cServer); | |
stServeurSockAddr.sin_port = htons(SMTP_PORT); | |
stServeurSockAddr.sin_family = AF_INET; | |
// socket as a stream | |
if ( (lSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
{ | |
// socket failed, blink a LED and stay here | |
for (;;) { | |
vParTestToggleLED( 4 ); | |
vTaskDelay( 200 ); | |
} | |
} | |
// connect to the server | |
if(connect(lSocket,(struct sockaddr *)&stServeurSockAddr, sizeof(stServeurSockAddr)) < 0) | |
{ | |
// connect failed, blink a LED and stay here | |
for (;;) { | |
vParTestToggleLED( 6 ); | |
vTaskDelay( 200 ); | |
} | |
} | |
else | |
{ | |
//Server: 220 SMTP Ready | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_EHLO_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
//Client: EHLO smtp.domain.com | |
// send ehlo | |
send(lSocket, "HELO ", 5, 0); | |
send(lSocket, cServer, strlen(cServer), 0); | |
send(lSocket, "\r\n", 2, 0); | |
//Server: 250 | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_OK_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
//Client: MAIL FROM:<sender@domain.com> | |
// send MAIL FROM | |
send(lSocket, cMailfrom, strlen(cMailfrom), 0); | |
//Server: 250 OK | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_OK_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
//Client: RCPT TO:<receiver@domain.com> | |
// send RCPT TO | |
send(lSocket, cMailto, strlen(cMailto), 0); | |
//Server: 250 OK | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_OK_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
//Client: DATA<CRLF> | |
// send DATA | |
send(lSocket, SMTP_DATA_STRING, 6, 0); | |
//Server: 354 Start mail input; end with <CRLF>.<CRLF> | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_START_OF_TRANSMISSION_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
// send content | |
send(lSocket, cMailcontent, strlen(cMailcontent), 0); | |
//Client: <CRLF>.<CRLF> | |
// send "<CRLF>.<CRLF>" | |
send(lSocket, SMTP_MAIL_END_STRING, 5, 0); | |
//Server: 250 OK | |
// wait for SMTP Server answer | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_OK_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
//Client: QUIT<CRLFCRLF> | |
// send QUIT | |
send(lSocket, SMTP_QUIT_STRING, 8, 0); | |
//Server: 221 smtp.domain.com closing transmission | |
do | |
{ | |
lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0); | |
}while (lRetval <= 0); | |
if (strncmp(cTempBuffer, SMTP_END_OF_TRANSMISSION_STRING, sizeof(cTempBuffer)) >= 0) | |
{ | |
vParTestSetLED( 3 , pdTRUE ); | |
} | |
} | |
} | |
} | |
} | |
} | |
// close socket | |
close(lSocket); | |
} | |
} | |
} | |
} | |
/*! \brief push button naked interrupt handler. | |
* | |
*/ | |
#if __GNUC__ | |
__attribute__((naked)) | |
#elif __ICCAVR32__ | |
#pragma shadow_registers = full // Naked. | |
#endif | |
void vpushb_ISR( void ) | |
{ | |
/* This ISR can cause a context switch, so the first statement must be a | |
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any | |
variable declarations. */ | |
portENTER_SWITCHING_ISR(); | |
prvpushb_ISR_NonNakedBehaviour(); | |
portEXIT_SWITCHING_ISR(); | |
} | |
/*! \brief push button interrupt handler. Here, declarations should be done | |
* | |
*/ | |
#if __GNUC__ | |
__attribute__((__noinline__)) | |
#elif __ICCAVR32__ | |
#pragma optimize = no_inline | |
#endif | |
static portBASE_TYPE prvpushb_ISR_NonNakedBehaviour( void ) | |
{ | |
if (gpio_get_pin_interrupt_flag(GPIO_PUSH_BUTTON_0)) | |
{ | |
// set the flag | |
bSendMail = pdTRUE; | |
// allow new interrupt : clear the IFR flag | |
gpio_clear_pin_interrupt_flag(GPIO_PUSH_BUTTON_0); | |
} | |
// no context switch required, task is polling the flag | |
return( pdFALSE ); | |
} | |
#endif |