示例#1
0
/*****************************************************************************
  Function:
	bool TCPIP_SMTP_Put(char c)

  Description:
	Writes a single byte to the SMTP client.

  Precondition:
	TCPIP_SMTP_UsageBegin returned true on a previous call.

  Parameters:
	c - The byte to be written

  Return Values:
	true - The byte was successfully written
	false - The byte was not written, most likely because the buffer was full

  Remarks:
	This function should only be called externally when the SMTP client is
	generating an on-the-fly message.  (That is, TCPIP_SMTP_MailSend was called
	with SMTPClient.Body set to NULL.)
  ***************************************************************************/
bool TCPIP_SMTP_Put(char c)
{
	if(CRPeriod.State == CR_PERIOD_NEED_INSERTION)
	{
		if(TCPIP_TCP_Put(MySocket, '.'))
			CRPeriod.State = CR_PERIOD_SEEK_CR;
		else
			return false;
	}

	switch(CRPeriod.State)
	{
		case CR_PERIOD_SEEK_CR:
			if(c == '\r')
				CRPeriod.State++;
			break;

		case CR_PERIOD_SEEK_LF:
			if(c == '\n')
				CRPeriod.State++;
			else if(c != '\r')
				CRPeriod.State--;
			break;

		case CR_PERIOD_SEEK_PERIOD:
			if(c == '.')
				CRPeriod.State++;	// CR_PERIOD_NEED_INSERTION
			else if(c == '\r')
				CRPeriod.State--;
			else
				CRPeriod.State = CR_PERIOD_SEEK_CR;
			break;
		
		// Default case needed to supress compiler diagnostics 
		// (CR_PERIOD_NEED_INSERTION state already handled above)
		default:
			break;
	}

	if(!TCPIP_TCP_Put(MySocket, c))
		return false;

	return true;
}
示例#2
0
static void TCPIP_SMTP_ClientProcess(void)
{
    uint8_t			    i;
    uint16_t			w;
    uint8_t			    vBase64Buffer[4];
    static uint32_t	    SMTPTimer;

    static uint8_t		RXBuffer[4];
    static const uint8_t *ROMStrPtr, *ROMStrPtr2;
    static const uint8_t *RAMStrPtr;
    static uint16_t		wAddressLength;
    TCPIP_DNS_RESULT    dnsRes;
    DNS_RESOLVE_TYPE    dnsType;

    switch(TransportState)
    {
        case TRANSPORT_HOME:
            // TCPIP_SMTP_UsageBegin() is the only function which will kick
            // the state machine into the next state
            break;

        case TRANSPORT_BEGIN:
            // Wait for the user to program all the pointers and then
            // call TCPIP_SMTP_MailSend()
            if(!SMTPFlags.bits.ReadyToStart)
            {
                break;
            }

            SMTPClient.Server = FindEmailServer(&SMTPClient, &dnsType);
            // See if we found a hostname anywhere which we could resolve
            if(!(SMTPClient.Server))
            {
                ResponseCode = SMTP_RESOLVE_ERROR;
                TransportState = TRANSPORT_HOME;
                break;
            }

            // check for a plain IP address
            if(TCPIP_Helper_StringToIPAddress(SMTPClient.Server, &SMTPServer))
            {
                TransportState = TRANSPORT_OBTAIN_SOCKET;
                break;
            }

            // use DNS to resolve the name
            TCPIP_DNS_Resolve(SMTPClient.Server, dnsType);
            SMTPTimer = SYS_TMR_TickCountGet();

            TransportState++;
            break;

        case TRANSPORT_NAME_RESOLVE:
            // Wait for the DNS server to return the requested IP address
            dnsRes = TCPIP_DNS_IsResolved((const char*)SMTPClient.Server,&SMTPServer);
            if(dnsRes == DNS_RES_PENDING)
            {
                break;
            }
            if(dnsRes < 0)
            {   // some error occurred
                ResponseCode = SMTP_RESOLVE_ERROR;
                TransportState = TRANSPORT_HOME;
                break;
            }
            
            // DNS_RES_OK
            TransportState++;
            // No need to break here

        case TRANSPORT_OBTAIN_SOCKET:
            // Connect a TCP socket to the remote SMTP server
            MySocket = TCPIP_TCP_ClientOpen(IP_ADDRESS_TYPE_IPV4, SMTPClient.ServerPort, (IP_MULTI_ADDRESS*)&SMTPServer.Val);

            // Abort operation if no TCP socket could be opened.
            // If this ever happens, you need to update your tcp_config.h
            if(MySocket == INVALID_SOCKET)
                break;

            TCPIP_TCP_SignalHandlerRegister(MySocket, TCPIP_TCP_SIGNAL_RX_DATA, _SMTPSocketRxSignalHandler, 0);

            TransportState++;
            SMTPTimer = SYS_TMR_TickCountGet();

            // No break; fall into TRANSPORT_SOCKET_OBTAINED
			
        case TRANSPORT_SOCKET_OBTAINED:
            if(!TCPIP_TCP_IsConnected(MySocket))
            {
                // Don't stick around in the wrong state if the
                // server was connected, but then disconnected us.
                // Also time out if we can't establish the connection
                // to the SMTP server
                if(SMTPFlags.bits.ConnectedOnce || ((SYS_TMR_TickCountGet()-SMTPTimer) > (TCPIP_SMTP_SERVER_REPLY_TIMEOUT * SYS_TMR_TickCounterFrequencyGet())))
                {
                    ResponseCode = SMTP_CONNECT_ERROR;
                    TransportState = TRANSPORT_CLOSE;
                }

                break;
            }
            SMTPFlags.bits.ConnectedOnce = true;

            // See if the server sent us anything
            while(TCPIP_TCP_GetIsReady(MySocket))
            {
                TCPIP_TCP_Get(MySocket, &i);
                switch(RXParserState)
                {
                    case RX_BYTE_0:
                    case RX_BYTE_1:
                    case RX_BYTE_2:
                        RXBuffer[RXParserState] = i;
                        RXParserState++;
                        break;
	
                    case RX_BYTE_3:
                        switch(i)
                        {
                            case ' ':
                                SMTPFlags.bits.RXSkipResponse = false;
                                RXParserState++;
                                break;
                            case '-':
                                SMTPFlags.bits.RXSkipResponse = true;
                                RXParserState++;
                                break;
                            case '\r':
                                RXParserState = RX_SEEK_LF;
                                break;
                        }
                        break;
	
					case RX_SEEK_CR:
                                            if(i == '\r')
                                                    RXParserState++;
                                            break;
	
					case RX_SEEK_LF:
						// If we received the whole command
						if(i == '\n')
						{
							RXParserState = RX_BYTE_0;

							if(!SMTPFlags.bits.RXSkipResponse)
							{
								// The server sent us a response code
								// Null terminate the ASCII reponse code so we can convert it to an integer
								RXBuffer[3] = 0;
								ResponseCode = atoi((char*)RXBuffer);

								// Handle the response
								switch(SMTPState)
								{
									case SMTP_HELO_ACK:
										if(ResponseCode >= 200u && ResponseCode <= 299u)
										{
											if(SMTPClient.Username)
												SMTPState = SMTP_AUTH_LOGIN;
											else
												SMTPState = SMTP_MAILFROM;
										}
										else
											SMTPState = SMTP_QUIT_INIT;
										break;


									case SMTP_AUTH_LOGIN_ACK:
									case SMTP_AUTH_USERNAME_ACK:
										if(ResponseCode == 334u)
											SMTPState++;
										else
											SMTPState = SMTP_QUIT_INIT;
										break;

									case SMTP_AUTH_PASSWORD_ACK:
										if(ResponseCode == 235u)
											SMTPState++;
										else
											SMTPState = SMTP_QUIT_INIT;
										break;

									case SMTP_HOME:
									case SMTP_MAILFROM_ACK:
									case SMTP_RCPTTO_ACK:
									case SMTP_RCPTTOCC_ACK:
									case SMTP_RCPTTOBCC_ACK:
										if(ResponseCode >= 200u && ResponseCode <= 299u)
											SMTPState++;
										else
											SMTPState = SMTP_QUIT_INIT;
										break;
							
									case SMTP_DATA_ACK:
										if(ResponseCode == 354u)
											SMTPState++;
										else
											SMTPState = SMTP_QUIT_INIT;
										break;
							
									case SMTP_DATA_BODY_ACK:
										if(ResponseCode >= 200u && ResponseCode <= 299u)
											SMTPFlags.bits.SentSuccessfully = true;
							
										SMTPState = SMTP_QUIT_INIT;
										break;

									// Default case needed to supress compiler diagnostics
									default:
										break;
								}
							}
						}
						else if(i != '\r')
							RXParserState--;
	
						break;
				}
			}

			// Generate new data in the TX buffer, as needed, if possible
			if(TCPIP_TCP_PutIsReady(MySocket) < 64u)
				break;

			switch(SMTPState)
			{
				case SMTP_HELO:
					if(SMTPClient.Username == NULL)
						TCPIP_TCP_StringPut(MySocket, (uint8_t*)"HELO MCHPBOARD\r\n");
					else    
						TCPIP_TCP_StringPut(MySocket, (uint8_t*)"EHLO MCHPBOARD\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_AUTH_LOGIN:
					// Note: This state is only entered from SMTP_HELO_ACK if the application 
					// has specified a Username to use (SMTPClient.Username is non-NULL)
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"AUTH LOGIN\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_AUTH_USERNAME:
					// Base 64 encode and transmit the username.
                    RAMStrPtr = (uint8_t*)SMTPClient.Username;
                    w = strlen((char*)RAMStrPtr);

					while(w)
					{
						i = 0;
						while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
						{
                            vBase64Buffer[i] = *RAMStrPtr++;
							i++;
						}
						w -= i;					
						TCPIP_Helper_Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
						TCPIP_TCP_ArrayPut(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
					}
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_AUTH_PASSWORD:
					// Base 64 encode and transmit the password
                    RAMStrPtr = (uint8_t*)SMTPClient.Password;
                    w = strlen((char*)RAMStrPtr);

					while(w)
					{
						i = 0;
						while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
						{
                            vBase64Buffer[i] = *RAMStrPtr++;
							i++;
						}
						w -= i;					
						TCPIP_Helper_Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
						TCPIP_TCP_ArrayPut(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
					}
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_MAILFROM:
					// Send MAIL FROM header.  Note that this is for the SMTP server validation, 
					// not what actually will be displayed in the recipients mail client as a 
					// return address.
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"MAIL FROM:<");
                    RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.From, &wAddressLength);
                    TCPIP_TCP_ArrayPut(MySocket, RAMStrPtr, wAddressLength);
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)">\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_RCPTTO_INIT:
					// See if there are any (To) recipients to process
					if(SMTPClient.To)
					{
						RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.To, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTO;
							break;
						}
					}
					
					SMTPState = SMTP_RCPTTOCC_INIT;
					break;

				case SMTP_RCPTTO:
				case SMTP_RCPTTOCC:
				case SMTP_RCPTTOBCC:
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"RCPT TO:<");
                    TCPIP_TCP_ArrayPut(MySocket, RAMStrPtr, wAddressLength);
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)">\r\n");
					TCPIP_TCP_Flush(MySocket);
					SMTPState++;
					break;

				case SMTP_RCPTTO_ISDONE:
					// See if we have any more (To) recipients to process
					// If we do, we must roll back a couple of states
                    RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength);
	
					if(wAddressLength)
					{
						SMTPState = SMTP_RCPTTO;
						break;
					}

					// All done with To field
					SMTPState++;
					//No break

				case SMTP_RCPTTOCC_INIT:
					// See if there are any Carbon Copy (CC) recipients to process
					if(SMTPClient.CC)
					{
						RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.CC, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTOCC;
							break;
						}
					}
					
					SMTPState = SMTP_RCPTTOBCC_INIT;
					break;

				case SMTP_RCPTTOCC_ISDONE:
					// See if we have any more Carbon Copy (CC) recipients to process
					// If we do, we must roll back a couple of states
                    RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength);

					if(wAddressLength)
					{
						SMTPState = SMTP_RCPTTOCC;
						break;
					}

					// All done with CC field
					SMTPState++;
					//No break

				case SMTP_RCPTTOBCC_INIT:
					// See if there are any Blind Carbon Copy (BCC) recipients to process
					if(SMTPClient.BCC)
					{
						RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.BCC, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTOBCC;
							break;
						}
					}

					// All done with BCC field
					SMTPState = SMTP_DATA;
					break;

				case SMTP_RCPTTOBCC_ISDONE:
					// See if we have any more Blind Carbon Copy (CC) recipients to process
					// If we do, we must roll back a couple of states
                    RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength);

					if(wAddressLength)
					{
						SMTPState = SMTP_RCPTTOBCC;
						break;
					}

					// All done with BCC field
					SMTPState++;
					//No break

				case SMTP_DATA:
					TCPIP_TCP_StringPut(MySocket, (uint8_t*)"DATA\r\n");
					SMTPState++;
					PutHeadersState = PUTHEADERS_FROM_INIT;
					TCPIP_TCP_Flush(MySocket);
					break;

				case SMTP_DATA_HEADER:
					while((PutHeadersState != PUTHEADERS_DONE) && (TCPIP_TCP_PutIsReady(MySocket) > 64u))
					{
						switch(PutHeadersState)
						{
							case PUTHEADERS_FROM_INIT:
								if(SMTPClient.From)
								{
									PutHeadersState = PUTHEADERS_FROM;
									TCPIP_TCP_StringPut(MySocket, (uint8_t*)"From: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_TO_INIT;
								}
								break;
								
							case PUTHEADERS_FROM:
                                SMTPClient.From = (char*)TCPIP_TCP_StringPut(MySocket, (uint8_t*)SMTPClient.From);
                                if(*SMTPClient.From == 0u)
                                    PutHeadersState = PUTHEADERS_TO_INIT;
								break;

							case PUTHEADERS_TO_INIT:
								if(SMTPClient.To)
								{
									PutHeadersState = PUTHEADERS_TO;
									TCPIP_TCP_StringPut(MySocket, (uint8_t*)"\r\nTo: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_CC_INIT;
								}
								break;
								
							case PUTHEADERS_TO:
                                SMTPClient.To = (char*)TCPIP_TCP_StringPut(MySocket, (uint8_t*)SMTPClient.To);
                                if(*SMTPClient.To == 0u)
                                    PutHeadersState = PUTHEADERS_CC_INIT;
								break;

							case PUTHEADERS_CC_INIT:
								if(SMTPClient.CC)
								{
									PutHeadersState = PUTHEADERS_CC;
									TCPIP_TCP_StringPut(MySocket, (uint8_t*)"\r\nCC: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_SUBJECT_INIT;
								}
								break;
								
							case PUTHEADERS_CC:
                                SMTPClient.CC = (char*)TCPIP_TCP_StringPut(MySocket, (uint8_t*)SMTPClient.CC);
                                if(*SMTPClient.CC == 0u)
                                    PutHeadersState = PUTHEADERS_SUBJECT_INIT;
								break;

							case PUTHEADERS_SUBJECT_INIT:
								if(SMTPClient.Subject)
								{
									PutHeadersState = PUTHEADERS_SUBJECT;
									TCPIP_TCP_StringPut(MySocket, (uint8_t*)"\r\nSubject: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_OTHER_INIT;
								}
								break;
								
							case PUTHEADERS_SUBJECT:
                                SMTPClient.Subject = (char*)TCPIP_TCP_StringPut(MySocket, (uint8_t*)SMTPClient.Subject);
                                if(*SMTPClient.Subject == 0u)
                                    PutHeadersState = PUTHEADERS_OTHER_INIT;
								break;

							case PUTHEADERS_OTHER_INIT:
								TCPIP_TCP_ArrayPut(MySocket, (uint8_t*)"\r\n", 2);
								if(SMTPClient.OtherHeaders)
								{
									PutHeadersState = PUTHEADERS_OTHER;
								}
								else
								{
									TCPIP_TCP_ArrayPut(MySocket, (uint8_t*)"\r\n", 2);
									PutHeadersState = PUTHEADERS_DONE;
									SMTPState++;
								}
								break;
								
							case PUTHEADERS_OTHER:
                                SMTPClient.OtherHeaders = (char*)TCPIP_TCP_StringPut(MySocket, (uint8_t*)SMTPClient.OtherHeaders);
                                if(*SMTPClient.OtherHeaders == 0u)
                                {
                                    TCPIP_TCP_ArrayPut(MySocket, (uint8_t*)"\r\n", 2);
                                    PutHeadersState = PUTHEADERS_DONE;
                                    SMTPState++;
                                }
								break;
							
							// Default case needed to supress compiler diagnostics
							default:
								break;
						}
					}
					TCPIP_TCP_Flush(MySocket);
					break;
		
				case SMTP_DATA_BODY_INIT:
					SMTPState++;
					RAMStrPtr = (uint8_t*)SMTPClient.Body;
					ROMStrPtr2 = (const uint8_t*)"\r\n.\r\n";
					CRPeriod.Pos = NULL;
					if(RAMStrPtr)
						CRPeriod.Pos = (uint8_t*)strstr((char*)RAMStrPtr, (const char*)"\r\n.");
					// No break here
		
				case SMTP_DATA_BODY:
					if(SMTPClient.Body)
					{
						if(*ROMStrPtr2)
						{
							// Put the application data, doing the transparancy replacement of "\r\n." with "\r\n.."
							while(CRPeriod.Pos)
							{
								CRPeriod.Pos += 3;
								RAMStrPtr += TCPIP_TCP_ArrayPut(MySocket, RAMStrPtr, CRPeriod.Pos-RAMStrPtr);
								if(RAMStrPtr == CRPeriod.Pos)
								{
									if(!TCPIP_TCP_Put(MySocket, '.'))
									{
										CRPeriod.Pos -= 3;
										break;
									}
								}
								else
								{
									CRPeriod.Pos -= 3;
									break;
								}
								CRPeriod.Pos = (uint8_t*)strstr((char*)RAMStrPtr, (const char*)"\r\n.");
							}
							
							// If we get down here, either all replacements have been made or there is no remaining space in the TCP output buffer
							RAMStrPtr = TCPIP_TCP_StringPut(MySocket, RAMStrPtr);
							ROMStrPtr2 = TCPIP_TCP_StringPut(MySocket, (uint8_t*)ROMStrPtr2);
							TCPIP_TCP_Flush(MySocket);
						}
					}
					else
					{
						if(SMTPFlags.bits.ReadyToFinish)
						{
							if(*ROMStrPtr2)
							{
								ROMStrPtr2 = TCPIP_TCP_StringPut(MySocket, (uint8_t*)ROMStrPtr2);
								TCPIP_TCP_Flush(MySocket);
							}
		
						}
					}

					if(*ROMStrPtr2 == 0u)
					{
						SMTPState++;
					}
					break;
		
				case SMTP_QUIT_INIT:
					SMTPState++;
					ROMStrPtr = (const uint8_t*)"QUIT\r\n";
					// No break here

				case SMTP_QUIT:
					if(*ROMStrPtr)
					{
						ROMStrPtr = TCPIP_TCP_StringPut(MySocket, (uint8_t*)ROMStrPtr);
						TCPIP_TCP_Flush(MySocket);
					}

					if(*ROMStrPtr == 0u)
					{
						TransportState = TRANSPORT_CLOSE;
					}
					break;
				
				// Default case needed to supress compiler diagnostics
				default:
					break;
			}
			break;

		case TRANSPORT_CLOSE:
			// Close the socket so it can be used by other modules
			TCPIP_TCP_Close(MySocket);
			MySocket = INVALID_SOCKET;

			// Go back to doing nothing
			TransportState = TRANSPORT_HOME;
			break;
	}
}
示例#3
0
void TCPIP_HTTP_Print_(HTTP_CONN_HANDLE connHandle)
{
       TCP_SOCKET sktHTTP = TCPIP_HTTP_CurrentConnectionSocketGet(connHandle);
	TCPIP_TCP_Put(sktHTTP, '~');
	return;
}