Ejemplo n.º 1
0
void sendStringEthernet( char * p, char newLine )
{

	int l = 0;
	WORD wMaxPut;
	
	// Make sure the Socket is connected to something!
	if(!TCPIsConnected(MySocket)) return;
	
	// Find the length of the string
	while (*(p+l) != 0x00) l++;
	
	if(l)
	{
		wMaxPut = TCPIsPutReady(MySocket);
		if(wMaxPut < l)
		{
			#ifdef __DEBUG
			while(1);	// Hold here while debugging
			#endif
		}
		else
		{
			// Transfer the data out of our local processing buffer and into the TCP TX FIFO.
			TCPPutArray(MySocket, (BYTE*)p, l);
		}		
	}
	if(newLine) TCPPut(MySocket, 10);
		
	
	TCPFlush(MySocket); // Send the data immediatly!

}	
Ejemplo n.º 2
0
/*********************************************************************
 * Function:        DWORD HTTPIncFile(TCP_SOCKET skt, 
 *						DWORD callbackPos, ROM BYTE* file)
 *
 * PreCondition:    curHTTP is loaded
 *
 * Input:           None
 *
 * Output:          Updates curHTTP.callbackPos
 *
 * Side Effects:    None
 *
 * Overview:        Writes an MPFS file to the socket and returns
 *
 * Note:            Provides rudimentary include support for dynamic
 *					files which allows them to use header, footer, 
 *					and/or menu inclusion files rather than
 *					duplicating code across all files.
 ********************************************************************/
void HTTPIncFile(ROM BYTE* file)
{
	WORD count, len;
	BYTE data[64];
	MPFS_HANDLE fp;
	
	// Check if this is a first round call
	if(curHTTP.callbackPos == 0x00)
	{// On initial call, open the file and save its ID
		fp = MPFSOpenROM(file);
		if(fp == MPFS_INVALID_HANDLE)
		{// File not found, so abort
			return;
		}
		((DWORD_VAL*)&curHTTP.callbackPos)->w[0] = MPFSGetID(fp);
	}
	else
	{// The file was already opened, so load up it's ID and seek
		fp = MPFSOpenID(((DWORD_VAL*)&curHTTP.callbackPos)->w[0]);
		if(fp == MPFS_INVALID_HANDLE)
		{// File not found, so abort
			curHTTP.callbackPos = 0x00;
			return;
		}
		MPFSSeek(fp, ((DWORD_VAL*)&curHTTP.callbackPos)->w[1], MPFS_SEEK_FORWARD);
	}
	
	// Get/put as many bytes as possible
	count = TCPIsPutReady(sktHTTP);
	while(count > 0)
	{
		len = MPFSGetArray(fp, data, mMIN(count, 64));
		if(len == 0)
		{// If no bytes were read, an EOF was reached
			MPFSClose(fp);
			curHTTP.callbackPos = 0x00;
			return;
		}
		else
		{// Write the bytes to the socket
			TCPPutArray(sktHTTP, data, len);
			count -= len;
		}
	}
	
	// Save the new address and close the file
	((DWORD_VAL*)&curHTTP.callbackPos)->w[1] = MPFSTell(fp);
	MPFSClose(fp);
	
	return;
}
Ejemplo n.º 3
0
/*********************************************************************
 * Function:        static BOOL HTTPSendFile(void)
 *
 * PreCondition:    curHTTP.file and curHTTP.offsets have both been
 *					opened for reading.
 *
 * Input:           None
 *
 * Output:          TRUE if EOF was reached and reading is done
 *					FALSE if more data remains
 *
 * Side Effects:    None
 *
 * Overview:        This function serves the next chunk of curHTTP's
 *					file, up to a) available TX FIFO or b) up to
 *					the next recorded callback index, whichever comes
 *					first.
 *
 * Note:            None
 ********************************************************************/
static BOOL HTTPSendFile(void)
{
	WORD numBytes, len;
	BYTE c, data[64];
	
	// Determine how many bytes we can read right now
	numBytes = mMIN(TCPIsPutReady(sktHTTP), curHTTP.nextCallback - curHTTP.byteCount);
	
	// Get/put as many bytes as possible
	curHTTP.byteCount += numBytes;
	while(numBytes > 0)
	{
		len = MPFSGetArray(curHTTP.file, data, mMIN(numBytes, 64));
		if(len == 0)
			return TRUE;
		else
			TCPPutArray(sktHTTP, data, len);
		numBytes -= len;
	}
	
	// Check if a callback index was reached
	if(curHTTP.byteCount == curHTTP.nextCallback)
	{
		// Update the state machine
		smHTTP = SM_HTTP_SEND_FROM_CALLBACK;
		curHTTP.callbackPos = 0;

		// Read past the variable name and close the MPFS
		MPFSGet(curHTTP.file, NULL);
		do
		{
			if(!MPFSGet(curHTTP.file, &c))
				break;
			curHTTP.byteCount++;
		} while(c != '~');
		curHTTP.byteCount++;
		
		// Read in the callback address and next offset
		MPFSGetLong(curHTTP.offsets, &(curHTTP.callbackID));
		if(!MPFSGetLong(curHTTP.offsets, &(curHTTP.nextCallback)))
		{
			curHTTP.nextCallback = 0xffffffff;
			MPFSClose(curHTTP.offsets);
			curHTTP.offsets = MPFS_INVALID_HANDLE;
		}
	}

    // We are not done sending a file yet...
    return FALSE;
}
Ejemplo n.º 4
0
/*****************************************************************************
*
*  exoHAL_SocketSend
*
*  \param  socket - socket handle; buffer - string buffer containing info to
*          send; len - size of string in bytes;
*
*  \return Number of bytes sent
*
*  \brief  Sends data out to the internet
*
*****************************************************************************/
unsigned char
exoHAL_SocketSend(long socket, char * buffer, unsigned char len)
{
  int send_len = 0;

  if (GenericTCPState == EX_PACKAGE_SEND)
  {
    if (TCPIsPutReady((TCP_SOCKET)exSocket) < len)
        return -1;
    send_len = TCPPutArray((TCP_SOCKET)exSocket, (BYTE *)buffer, len);
    send_count ++;
    wait_count = 0;
    socket = (long)exSocket;
  }

  return send_len;
}
Ejemplo n.º 5
0
void ModbusTcpRxHandle(TCP_SOCKET MySocket)
{
	BYTE RX_Buffer[TCP_MODBUS_RX_MAX_LEN];
	WORD wMaxPut, wMaxGet;
	wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
	if(wMaxGet == 0) {
		return ;
	}
	wMaxGet = (sizeof(RX_Buffer) >= wMaxGet)?wMaxGet:sizeof(RX_Buffer);
	if(wMaxGet > 0) {
	    TCPGetArray(MySocket, &RX_Buffer[0], wMaxGet);
		wMaxGet = ModbusCmdPrase((void *)RX_Buffer,(unsigned int)wMaxGet); //解析和TCP包,返回一定长度的应答包,然后返回给客户端
    	wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
	    if(wMaxGet > 0 && wMaxPut >= wMaxGet) {
			TCPPutArray(MySocket, RX_Buffer, wMaxGet);
			TCPFlush(MySocket);
		}
	}
}
Ejemplo n.º 6
0
size_t TcpClient::writeStream(const byte *rgbWrite, size_t cbWrite, unsigned long msBlockMax, DNETcK::STATUS * pStatus)
{
    unsigned long tStart = 0;
    size_t cbWritten = 0;
    size_t cbReady = 0;

    tStart = millis();
    do
    {
        // make sure we are Connected
        // this will also run the stack
        if(!isConnected(DNETcK::msImmediate, pStatus))
        {
            return(cbWritten);
        }

        if((cbReady = TCPIsPutReady(_hTCP)) > 0)
        {
            cbReady = cbReady < cbWrite ? cbReady : cbWrite;
            cbReady = TCPPutArray(_hTCP, &rgbWrite[cbWritten], cbReady);
            cbWritten += cbReady;
            cbWrite -= cbReady;

            // flush out what we are trying to write
            TCPFlush(_hTCP);
        }
 
    } while(cbWrite > 0 && !hasTimeElapsed(tStart, msBlockMax, millis()));

    // put in the status
    if(cbWritten < cbWrite && pStatus != NULL)
    {
        *pStatus = DNETcK::WriteTimeout;
    }

    // make sure the last flush runs
    EthernetPeriodicTasks();

   return(cbWritten);
}
Ejemplo n.º 7
0
Archivo: EOL.c Proyecto: oden65/xPL_PIC
//******************************************************************************
/// Prints the analogue value read from the zone, calls CheckEOL() to determine the value
void HTTPPrint_EOLValue (WORD num) {
	
	char EOLOutput[5];
	Zone_States Ignore;
	WORD EOLValue;
	
	// Set a flag to indicate not finished
	curHTTP.callbackPos = 1;
	
	// Make sure there's enough output space
	if(TCPIsPutReady(sktHTTP) < (unsigned int)5)
		return;
	
	Ignore = CheckEOL(num, &EOLValue);
	uitoa(EOLValue, EOLOutput);
	
	TCPPutArray(sktHTTP, (BYTE*)EOLOutput, (WORD) strlen(EOLOutput));
	
	// Indicate that we're done
	curHTTP.callbackPos = 0x00;
	return;
	
}
Ejemplo n.º 8
0
Archivo: HTTP.c Proyecto: sonite/mGit
/*********************************************************************
 * Manage an HTML output buffer for use when dumping variable contents
 * through the configuration writer
 *********************************************************************/
static size_t HTTP_WriteSocket(void)
{
	if(Cfg_BufPtr)
	{
		unsigned char ch;
		char *head, *tail;

		*Cfg_BufPtr = '\0';

		head = HTTP_Data;
		tail = HTTP_Data;

		while(ch = *tail++, ch)
		{
			// Escape any special characters
			if(ch <= '&' || ch == '<' || ch == '>')
			{
				TCPPutArray(HTTP.socket, (BYTE *) head, tail - head);

				Num_Buffer[0] = '&';
				Num_Buffer[1] = '#';
				head = Num_Integer(&Num_Buffer[2], ch);
				*head++ = ';';

				TCPPutString(HTTP.socket, (BYTE *) Num_Buffer);

				head = tail;
			}
		}

		TCPPutString(HTTP.socket, (BYTE *) head);
	}

	Cfg_BufPtr = HTTP_Data;
	return HTTP_MAX_DATA_LEN;
}
Ejemplo n.º 9
0
/*********************************************************************
 * Function:        void CAN2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void CAN2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#else
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#endif

			
			// Abort operation if no TCP socket of type TCP_PURPOSE_CAN_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the CAN FIFOs
				RXHeadPtr = vCANRXFIFO;
				RXTailPtr = vCANRXFIFO;
				TXHeadPtr = vCANTXFIFO;
				TXTailPtr = vCANTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			

			// Read FIFO pointers into a local shadow copy.  Some pointers are volatile 
			// (modified in the ISR), so we must do this safely by disabling interrupts
			RXTailPtrShadow = (BYTE*)RXTailPtr;
			TXHeadPtrShadow = (BYTE*)TXHeadPtr;
				

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);

			RXHeadPtrShadow = (BYTE*)RXHeadPtr;
			TXTailPtrShadow = (BYTE*)TXTailPtr;
			

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);		
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);
			//
			// Transmit pending data that has been placed into the CAN RX FIFO (in the ISR)
			//
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
			wMaxGet = RXHeadPtrShadow - RXTailPtrShadow;	// Get CAN RX FIFO byte count
			if(RXHeadPtrShadow < RXTailPtrShadow)
				wMaxGet += sizeof(vCANRXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANRXFIFO 
				// end to start address.
				w = vCANRXFIFO + sizeof(vCANRXFIFO) - RXTailPtrShadow;
				if(wMaxPut >= w)
				{
					TCPPutArray(MySocket, RXTailPtrShadow, w);
					RXTailPtrShadow = vCANRXFIFO;
					wMaxPut -= w;
				}
				TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
				RXTailPtrShadow += wMaxPut;

				// No flush.  The stack will automatically flush and do 
				// transmit coallescing to minimize the number of TCP 
				// packets that get sent.  If you explicitly call TCPFlush()
				// here, latency will go down, but so will max throughput 
				// and bandwidth efficiency.
			
			}

			//
			// Transfer received TCP data into the CAN TX FIFO for future transmission (in the ISR)
			//
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get CAN TX FIFO free space
			if(TXHeadPtrShadow >= TXTailPtrShadow)
				wMaxPut += sizeof(vCANTXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANTXFIFO 
				// end to start address.
				w = vCANTXFIFO + sizeof(vCANTXFIFO) - TXHeadPtrShadow;
				if(wMaxPut >= w)
				{
					TCPGetArray(MySocket, TXHeadPtrShadow, w);
					TXHeadPtrShadow = vCANTXFIFO;
					wMaxPut -= w;
				}
				TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
				TXHeadPtrShadow += wMaxPut;
			}
			
			// Write local shadowed FIFO pointers into the volatile FIFO pointers.
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);
			
			RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
			TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);

			break;
	}
}
Ejemplo n.º 10
0
/*****************************************************************************
*
* Cloud_GetCmd
*
*  \param  pbuf - string buffer containing data to be sent
*          bufsize - number of bytes to send
*
*  \return 1 success; 0 failure
*
*  \brief  Writes data to Exosite cloud
*
*****************************************************************************/
int
Cloud_GetCmd()
{
  int length;
  char DataLen[10];
//  int http_status = 0;
  char *cmp_ss = "Content-Length:";
  char *cmp = cmp_ss;
  DWORD serverip = 0;
  const unsigned char server[6] = SERVERIP ;
  serverip = (server[3] << 24 & 0xff000000) | (server[2] << 16 & 0xff0000)
          | (server[1] << 8 & 0xff00) | (server[0] & 0xff);
  long w, r;
  char rev[300];
  unsigned char len;
  char *p;
  unsigned char crlf = 0;
  int  time_out = 0;
  int tx_buff_size = 250;

  int  tmp_len =0 ;

  if(status_code == STATUS_INIT||status_code == STATUS_END){

      if (sock == INVALID_SOCKET)
      {
        sock = TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, HTTP_PORT, TCP_PURPOSE_TCP_CLIENT);

      // TCP_OPEN_RAM_HOST for using dns name as server name
     //  TCPOpen(serverip, TCP_OPEN_IP_ADDRESS, server_port, TCP_PURPOSE_GENERIC_TCP_CLIENT);

       if (sock  == INVALID_SOCKET) {
             status_code = STATUS_INIT;
       //      LEDS_OFF();
        //     LEDS_ON();
            return 0;
         }
       status_code = STATUS_READY;

      }
      else  status_code == STATUS_READY;
  }
  else if(status_code == STATUS_READY)
  {
       if(sent_header) DelayMs(20);
        w = TCPIsPutReady(sock);

       if(w<=250ul) {
              return 0; }

       if(sent_header){

             memset(header, 0, sizeof(header));
             length = PostHeaderGenerate("/sendcmd.php", command, 0, 0);
             remain_count =0 ;
             sent_header = FALSE;
             sent_count = 0;
       }
    //    LED2_ON(); LED1_OFF();

       int send_len = strlen(&header[remain_count]);

   //   LED2_ON(); LED1_OFF();
      //if(send_len > 254)  {LED2_ON(); LED1_OFF()};
      /*  The max size of sliding window for TCP packet is 254? after testing.
       *  Don't know the reason, but if we set the number of sending data to 250,
       * the program works fine.
       *
       */
      tmp_len = send_len>250? 250:send_len;
  //    int tmp_len = IHMS_SocketSend(sock, &header[sent_count], send_len );

      tmp_len = TCPPutArray(sock, (BYTE *) &header[remain_count], tmp_len);

      TCPFlush((TCP_SOCKET)sock);

      LED2_ON(); LED1_OFF();

     if(tmp_len<send_len)
     {
         remain_count += tmp_len;
         return 0;
     }
     memset(header, 0, sizeof(header));
     sent_count = 0;
     remain_count = 0;
     status_code = STATUS_RCV;

  }
   else if(status_code == STATUS_RCV)
  {
     DelayMs(20);
     r = TCPIsGetReady((TCP_SOCKET) sock);

     if(r<200u){ LED2_ON();  return 0;}
     // now read all data in RX buffer

    int count = 0;
    do
    {
        r = TCPGetArray((TCP_SOCKET)sock, (BYTE *)&rev[count], 300);
        count  = count + r;
        rev[count]=0;

        r = TCPIsGetReady((TCP_SOCKET) sock);

     }while(r>0u);

    rev[count] = 0 ;

    TCPClose((TCP_SOCKET)sock);
    status_code = STATUS_END;
    sock = INVALID_SOCKET;
    status_code = STATUS_END;

    sent_header = TRUE;
    //now it's time to read time

    command = GetServerCmd(rev, "cmd=");
    cmd_no = GetServerCmd(rev, "no=");

    return 1;

  }

  return 0;
}
Ejemplo n.º 11
0
/****************************************************************************
  Function:
    unsigned int ChipKITClientPutBuff(TCP_SOCKET hTCP, const BYTE * rgBuff, unsigned short cbWrite, unsigned int cSecTimeout)

  Description:
    This routine write out a buffer onto the wire

  Precondition:
    hTCP must be open and valid.

  Parameters:
    hTCP - The socket to check
	rgBuff - the buffer to write out.
	cbWrite - the number of bytes to write out.
	cSecTimout - The number of seconds to wait before aborting the write.

  Returns:
    Returns the number of bytes written, zero if none.

  Remarks:
	This is to match functionality of the Arduino Client class write method
	A flush to push the bytes out on the wire is done.
  ***************************************************************************/
unsigned int ChipKITClientPutBuff(TCP_SOCKET hTCP, const BYTE * rgBuff, unsigned short cbWrite, unsigned int cSecTimeout)
{
	WORD cbReady = 0;
	WORD cbPut = 0;
	WORD cbToWrite = 0;
	WORD cbPutTotal = 0;
	DWORD t = 0;

	// loop until this is written out, or timeout
	t = TickGet();
	while(cbWrite > 0) 
	{
		// get out if we lost connection
		if(!TCPIsConnected(hTCP))
		{
			break;
		}

		// see how much buffer space is available
		if((cbReady = TCPIsPutReady(hTCP)) > 0)
		{
			// only put out what we can
			cbToWrite = cbWrite > cbReady ? cbReady : cbWrite;

			// put the data out
			cbPut = TCPPutArray(hTCP, (BYTE *) &rgBuff[cbPutTotal], cbToWrite);

			// update our loop counters
			cbPutTotal += cbPut;
			cbWrite -= cbPut;
		}

		// if we are done get out
		if(cbWrite == 0)
		{
			break;
		}

		// check to see if we are moving forward
		else if(cbPut > 0) 
		{
			t = TickGet();	// reset wait timer, we are moving forward
		}

		// didn't move forward, see if we are timing out
		else if((TickGet() - t) >= (cSecTimeout * TICK_SECOND)) 
		{
			break;
		}

		// run our tasks so things can be put out and come in.
		cbPut = 0;	// to see if we are moving forward
		ChipKITPeriodicTasks();
	}
	
	if(TCPIsConnected(hTCP))
	{
		TCPFlush(hTCP);				// flush any remaining stuff out
	}

	ChipKITPeriodicTasks();		// run tasks to do it
	return(cbPutTotal);
}
Ejemplo n.º 12
0
void TCPTXPerformanceTask(void)
{
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	static DWORD dwTimeStart;
	static DWORD dwBytesSent;
	static DWORD_VAL dwVLine;
	BYTE vBuffer[10];
	static BYTE vBytesPerSecond[12];
	WORD w;
	DWORD dw;
	QWORD qw;
	
	// Start the TCP server, listening on PERFORMANCE_PORT
	if(MySocket == INVALID_SOCKET)
	{
		MySocket = TCPOpen(0, TCP_OPEN_SERVER, TX_PERFORMANCE_PORT, TCP_PURPOSE_TCP_PERFORMANCE_TX);
	
		// Abort operation if no TCP socket of type TCP_PURPOSE_TCP_PERFORMANCE_TEST is available
		// If this ever happens, you need to go add one to TCPIPConfig.h
		if(MySocket == INVALID_SOCKET)
			return;
		
		dwVLine.Val = 0;
		dwTimeStart = TickGet();
		vBytesPerSecond[0] = 0;	// Initialize empty string right now
		dwBytesSent = 0;
	}
	
	// See how many bytes we can write to the TX FIFO
	// If we can't fit a single line of data in, then 
	// lets just wait for now.
	w = TCPIsPutReady(MySocket);
	if(w < 12+27+5+32u)
		return;

	vBuffer[0] = '0';
	vBuffer[1] = 'x';

	// Transmit as much data as the TX FIFO will allow
	while(w >= 12+27+5+32u)
	{
		// Convert line counter to ASCII hex string
		vBuffer[2] = btohexa_high(dwVLine.v[3]);
		vBuffer[3] = btohexa_low(dwVLine.v[3]);
		vBuffer[4] = btohexa_high(dwVLine.v[2]);
		vBuffer[5] = btohexa_low(dwVLine.v[2]);
		vBuffer[6] = btohexa_high(dwVLine.v[1]);
		vBuffer[7] = btohexa_low(dwVLine.v[1]);
		vBuffer[8] = btohexa_high(dwVLine.v[0]);
		vBuffer[9] = btohexa_low(dwVLine.v[0]);

		dwVLine.Val++;
	
		// Place all data in the TCP TX FIFO
		TCPPutArray(MySocket, vBuffer, sizeof(vBuffer));

		dw = TickGet() - dwTimeStart;

		// Calculate exact bytes/second, less truncation
		if((dwVLine.v[0] & 0x3F) == 0x00)
		{
			qw = (QWORD)dwBytesSent * (TICK_SECOND/100);
			qw /= dw;
			ultoa((DWORD)qw, vBytesPerSecond);
		}
		TCPPutROMString(MySocket, (ROM BYTE*)": We are currently achieving ");
		TCPPutROMArray(MySocket, (ROM BYTE*)"       ", 5-strlen((char*)vBytesPerSecond));
		TCPPutString(MySocket, vBytesPerSecond);
		TCPPutROMString(MySocket, (ROM BYTE*)"00 bytes/second TX throughput.\r\n");

		if(dw > TICK_SECOND)
		{
			dwBytesSent >>= 1;
			dwTimeStart += dw>>1;
		}
		
		w -= 12+27+5+32;
		dwBytesSent += 12+27+5+32;
	}
Ejemplo n.º 13
0
/*****************************************************************************
  Function:
	int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)

  Summary:
	This function used to send the data for both connection oriented and connection-less
	sockets.

  Description:
	The sendto function is used to send outgoing data on a socket.
	The destination address is given by to and tolen. Both 
	Datagram and stream sockets are supported.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data buffer containing data to transmit.
	len - length of data in bytes.
	flags - message flags. Currently this field is not supported.
	to - Optional pointer to the the sockaddr structure containing the
		destination address.  If NULL, the currently bound remote port and IP 
		address are used as the destination.
	tolen - length of the sockaddr structure.

  Returns:
	On success, sendto returns number of bytes sent. In case of
	error returns SOCKET_ERROR

  Remarks:
	None.
  ***************************************************************************/
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
{
	struct BSDSocket *socket;
	int size = SOCKET_ERROR;
	NODE_INFO remoteInfo;
//	static DWORD startTick;		// NOTE: startTick really should be a per socket BSDSocket structure member since other BSD calls can interfere with the ARP cycles
	WORD wRemotePort;
	struct sockaddr_in local;

	if( s >= BSD_SOCKET_COUNT )
		return SOCKET_ERROR;

	socket = &BSDSocketArray[s];

	if(socket->bsdState == SKT_CLOSED)
		return SOCKET_ERROR;

	if(socket->SocketType == SOCK_DGRAM) //UDP
	{
		// Decide the destination IP address and port
		remoteInfo.IPAddr.Val = socket->remoteIP;
		wRemotePort = socket->remotePort;
		if(to)
		{
			if((unsigned int)tolen != sizeof(struct sockaddr_in))
				return SOCKET_ERROR;
			wRemotePort = ((struct sockaddr_in*)to)->sin_port;
			remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr;
			
			// Implicitly bind the socket if it isn't already
			if(socket->bsdState == SKT_CREATED)
			{
				memset(&local, 0x00, sizeof(local));
				if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
					return SOCKET_ERROR;
			}
		}
		if(UDPIsOpened((UDP_SOCKET)s) != TRUE)
			return SOCKET_ERROR;
		
		if(remoteInfo.IPAddr.Val == IP_ADDR_ANY)
			remoteInfo.IPAddr.Val = 0xFFFFFFFFu;

#if 0
		// Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket
		if(UDPSocketInfo[socket->SocketID].remoteNode.IPAddr.Val != remoteInfo.IPAddr.Val)
		{
			if(ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
			{
				memcpy((void*)&UDPSocketInfo[socket->SocketID].remoteNode, (void*)&remoteInfo, sizeof(remoteInfo));
			}
			else
			{
				if(TickGet() - startTick > 1*TICK_SECOND)
				{
					ARPResolve(&remoteInfo.IPAddr);
					startTick = TickGet();
				}
				return SOCKET_ERROR;
			}
		}
#endif		
		// Select the UDP socket and see if we can write to it
		if(UDPIsPutReady(socket->SocketID))
		{
			// Set the proper remote port
			UDPSocketInfo[socket->SocketID].remotePort = wRemotePort;

			// Write data and send UDP datagram
			size = UDPPutArray((BYTE*)buf, len);
			UDPFlush();
			return size;
		}
	}
	else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket.
	{
		if(socket->bsdState != SKT_EST)
			return SOCKET_ERROR;

		if(HandlePossibleTCPDisconnection(s))
			return SOCKET_ERROR;
			
		// Handle special case were 0 return value is okay
		if(len == 0)
			return 0;

		// Write data to the socket. If one or more bytes were written, then 
		// return this value.  Otherwise, fail and return SOCKET_ERROR.
		size = TCPPutArray(socket->SocketID, (BYTE*)buf, len);
		if(size)
			return size;
	}
	return SOCKET_ERROR;
}
Ejemplo n.º 14
0
/****************************************************************************
  Function:
    void DDNSTask(void)

  Summary:
    Dynamic DNS client task/state machine.

  Description:
  	This function performs the background tasks of the Dynamic DNS Client.
  	Once the DDNSPointers structure is configured, this task attempt to 
  	update the Dynamic DNS hostname on a periodic schedule.
  	
  	The task first accesses the CheckIP server to determine the device's
  	current external IP address.  If the IP address has changed, it 
  	issues an update command to the dynamic DNS service to propagate the
  	change.  This sequence executes whenever dwUpdateAt elapses, which by
  	default is every 10 minutes, or when an update is forced.
    
  Precondition:
    DDNSInit() has been called.

  Parameters:
	None
	
  Returns:
    None

  Remarks:
	This function acts as a task (similar to one in an RTOS).  It
	performs its task in a co-operative manner, and the main application
	must call this function periodically to ensure that its tasks get 
	executed in a timely fashion.
  ***************************************************************************/
void DDNSTask(void)
{
	BYTE 				i;
	static TICK			Timer;
	static TCP_SOCKET	MySocket = INVALID_SOCKET;
	static char ROM * 	ROMStrPtr;
	static char * 		RAMStrPtr;

	static BYTE vBuffer[16];
	WORD wPos;
	static IP_ADDR ipParsed;
	
	static enum
	{
		SM_IDLE = 0u,
		SM_BEGIN_CHECKIP,				//0x1
		SM_CHECKIP_SKT_OBTAINED,		//0x2
		SM_CHECKIP_FIND_DELIMITER,		//0x3
		SM_CHECKIP_FIND_ADDRESS,		//0x4
		SM_CHECKIP_DISCONNECT,			//0x5
		SM_IP_UPDATE_HOME,				//0x6
		SM_IP_UPDATE_SKT_OBTAINED,		//0x7

		/*  
			HTTP request msg is divided into 6 parts 
			SM_IP_UPDATE_REQ_A,B,C,D,E,F as the tcp ip tx
			buffer is only able to carry 200 bytes at a time.
		*/
		
		SM_IP_UPDATE_REQ_A,				//0x8
		SM_IP_UPDATE_REQ_B,				//0x9
		SM_IP_UPDATE_REQ_C,				//0xa	
		SM_IP_UPDATE_REQ_D,				//0xb
		SM_IP_UPDATE_REQ_E,				//0xc
		SM_IP_UPDATE_REQ_F,				//0xd

		SM_IPUPDATE_FIND_RESPONSE,		//0xe
		SM_IPUPDATE_PARSE_RESPONSE,		//0xf
		SM_IPUDATE_DISCONNECT,			//0x10
		SM_DONE,						// Done, try again in 10 minutes
		SM_SOFT_ERROR,					// Soft error, try again in 30 seconds
		SM_SYSTEM_ERROR 				// System error, try again in 30 minutes
	} smDDNS = SM_IDLE;

	switch(smDDNS)
	{
		case SM_IDLE:

			// Wait for timeout to begin IP check
			if((LONG)(TickGet() - dwUpdateAt) < 0)
				break;
			
			// Otherwise, continue to next state
			smDDNS = SM_BEGIN_CHECKIP;
				
		case SM_BEGIN_CHECKIP:
			
			// If a fatal error has occurred, abort to the SM_DONE state and keep
			// the error message.
			if(lastStatus >= DDNS_STATUS_ABUSE && lastStatus <= DDNS_STATUS_911)
			{
				smDDNS = SM_DONE;
				break;
			}

			// If DDNSClient is not properly configured, abort
			if( 
				// Verify that each pointer is not null, and is not empty
				(DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szROM || *DDNSClient.Host.szROM == '\0') ) ||
				(!DDNSClient.ROMPointers.Host && (!DDNSClient.Host.szRAM || *DDNSClient.Host.szRAM == '\0') ) ||
				(DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szROM || *DDNSClient.Username.szROM == '\0') ) ||
				(!DDNSClient.ROMPointers.Username && (!DDNSClient.Username.szRAM || *DDNSClient.Username.szRAM == '\0') ) ||
				(DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szROM || *DDNSClient.Password.szROM == '\0') ) ||
				(!DDNSClient.ROMPointers.Password && (!DDNSClient.Password.szRAM || *DDNSClient.Password.szRAM == '\0') ) ||
				(DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szROM || *DDNSClient.CheckIPServer.szROM == '\0') ) ||
				(!DDNSClient.ROMPointers.CheckIPServer && (!DDNSClient.CheckIPServer.szRAM || *DDNSClient.CheckIPServer.szRAM == '\0') ) ||
				(DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szROM || *DDNSClient.UpdateServer.szROM == '\0') ) ||
				(!DDNSClient.ROMPointers.UpdateServer && (!DDNSClient.UpdateServer.szRAM || *DDNSClient.UpdateServer.szRAM == '\0') )
			)
			{
				smDDNS = SM_SOFT_ERROR;
				lastStatus = DDNS_STATUS_INVALID;
				break;
			}
			
			// Start with an invalidated IP String
			vBuffer[0] = '\0';
	
			// Connect a socket to the remote server
			if(DDNSClient.ROMPointers.CheckIPServer)
			{	
				MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.CheckIPServer.szROM, TCP_OPEN_ROM_HOST,
					DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT);
			}
			else
			{
				MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.CheckIPServer.szRAM, TCP_OPEN_RAM_HOST,
					DDNSClient.CheckIPPort, TCP_PURPOSE_DEFAULT);						
			}
			
			// If no socket available, try again on next loop
			if(MySocket == INVALID_SOCKET)
				break;

			smDDNS++;
			Timer = TickGet();
			break;

		case SM_CHECKIP_SKT_OBTAINED:

			// Wait for the remote server to accept our connection request
			if(!TCPIsConnected(MySocket))
			{
				// Time out if too much time is spent in this state
				if(TickGet()-Timer > 6*TICK_SECOND)
				{
					// Close the socket so it can be used by other modules
					// We will retry soon
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					lastStatus = DDNS_STATUS_CHECKIP_ERROR;
					smDDNS = SM_SOFT_ERROR;
				}
				break;
			}

			Timer = TickGet();

			// Make certain the socket can be written to
			if(TCPIsPutReady(MySocket) < 125)//125 = size of TCP Tx buffer
				break;
			
			// Transmit the request to the server
			TCPPutROMString(MySocket, (ROM BYTE*)"GET / HTTP/1.0\r\nHost: ");

			if(DDNSClient.ROMPointers.CheckIPServer)
			{
				TCPPutROMString(MySocket, DDNSClient.CheckIPServer.szROM);
			}
			else
			{
				TCPPutString(MySocket, DDNSClient.CheckIPServer.szRAM);
			}

			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n");

			// Send the packet
			TCPFlush(MySocket);
			smDDNS++;
			break;

		case SM_CHECKIP_FIND_DELIMITER:

			// Check if remote node is still connected.  If not, force to the disconnect state,
			// but don't break because data may still be waiting.
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
				smDDNS = SM_CHECKIP_DISCONNECT;

			// Search out the "Address: " delimiter in the response
			wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"Address: ", 9, 0, FALSE);
			
			// If not yet found, clear as much as possible and break
			if(wPos == 0xffff)
			{
				wPos = TCPIsGetReady(MySocket);
				if(wPos > 9)
					TCPGetArray(MySocket, NULL, wPos - 9);
				break;
			}
				
			// Clear up to and past that string
			TCPGetArray(MySocket, NULL, wPos + 9);
		
			// Continue on to read the IP
			Timer = TickGet();
			smDDNS++;
		
		case SM_CHECKIP_FIND_ADDRESS:
			
			// Check if remote node is still connected.  If not, force to the disconnect state,
			// but don't break because data may still be waiting.
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
				smDDNS = SM_CHECKIP_DISCONNECT;

			// Search out the "</body>" delimiter in the response
			wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"</body>", 7, 0, FALSE);
			
			// If not yet found, break
			if(wPos == 0xffff)
				break;
				
			// Read and terminate that string as the IP address (preventing buffer overflows)
			if(wPos > 15)
				wPos = 15;
			TCPGetArray(MySocket, vBuffer, wPos);
			vBuffer[wPos] = '\0';
			
			// Parse the IP address that was read, invalidating on failure
			if(!StringToIPAddress(vBuffer, &ipParsed))
				vBuffer[0] = '\0';

			// Continue on to close the socket			
			
		case SM_CHECKIP_DISCONNECT:

			// Close the socket
			TCPDisconnect(MySocket);
			MySocket = INVALID_SOCKET;

			// Determine if an update is necessary
			if(vBuffer[0] == '\0')
			{// CheckIP Failed
				lastStatus = DDNS_STATUS_CHECKIP_ERROR;
				smDDNS = SM_SOFT_ERROR;
				break;
			}

			if( (ipParsed.Val ==lastKnownIP.Val) && (!bForceUpdate))
			{
				// IP address has not changed and no update is forced
				lastStatus = DDNS_STATUS_UNCHANGED;
				smDDNS = SM_DONE;
				break;
			}
			
			// Need to perform an update
			lastKnownIP = ipParsed;
			bForceUpdate = FALSE;
			smDDNS++;
			break;
			 
		case SM_IP_UPDATE_HOME:

			// Connect a socket to the remote server
			if(DDNSClient.ROMPointers.UpdateServer)
			{
				MySocket = TCPOpen((DWORD)(ROM_PTR_BASE)DDNSClient.UpdateServer.szROM, TCP_OPEN_ROM_HOST, 
					DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT);
			}
			else
			{
				MySocket = TCPOpen((DWORD)(PTR_BASE)DDNSClient.UpdateServer.szRAM, TCP_OPEN_RAM_HOST,
					DDNSClient.UpdatePort, TCP_PURPOSE_DEFAULT);
			}
	
			// If no socket is available, try again on the next loop
			if(MySocket == INVALID_SOCKET)
				break;
			
			// Move on to the next state
			smDDNS++;
			Timer = TickGet();
			break;

		case SM_IP_UPDATE_SKT_OBTAINED:
		
			// Wait for the remote server to accept our connection request
			if(!TCPIsConnected(MySocket))
			{
				// Time out if too much time is spent in this state
				if(TickGet() - Timer > 6*TICK_SECOND)
				{
					// Close the socket so it can be used by other modules
					// We will try again immediately
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					lastStatus = DDNS_STATUS_UPDATE_ERROR;
					smDDNS--;
				}
				break;
			}
			
			// Reset timer and begin sending the request
			Timer = TickGet();
			smDDNS++;
			// No break needed...try to send first bit immediately.

		case SM_IP_UPDATE_REQ_A:
	
			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND))
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break;
			}
			
			if(TCPIsPutReady(MySocket) < 25u)  // 25 =~ 16+9
				break;

			TCPPutROMString(MySocket, (ROM BYTE*)"GET /nic/update?hostname=");
			smDDNS++;
			// No break needed...try to send next bit immediately.
			
		case SM_IP_UPDATE_REQ_B:

			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || (TickGet() - Timer > 10*TICK_SECOND))
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break; 
			}

			// Try to write, verifying that space is available first
			if(DDNSClient.ROMPointers.Host)
			{
				if(TCPIsPutReady(MySocket) < strlenpgm((ROM char*)DDNSClient.Host.szROM))
					break;
				TCPPutROMString(MySocket,DDNSClient.Host.szROM);
			}
			else
			{
				if(TCPIsPutReady(MySocket) < strlen((char*)DDNSClient.Host.szRAM))
					break;
				TCPPutString(MySocket,DDNSClient.Host.szRAM);
			}

			smDDNS++;
			// No break needed...try to send next bit immediately.
			
		case SM_IP_UPDATE_REQ_C:

			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break; 
			}

			if(TCPIsPutReady(MySocket) < 70u)
				break;
	
			TCPPutROMString(MySocket, (ROM BYTE*)"&myip=");
			TCPPutString(MySocket, vBuffer);
			TCPPutROMString(MySocket, (ROM BYTE*)"&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG HTTP/1.0");	

			TCPFlush(MySocket);
			smDDNS++;
			// No break needed...try to send next bit immediately.

		case SM_IP_UPDATE_REQ_D:

			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break; 
			}
			
			if(TCPIsPutReady(MySocket) < 131u) // 131 =~ 8+23 + dynamic dns server hostname
				break;

			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nHost: ");//8
			
			if(DDNSClient.ROMPointers.UpdateServer)
				TCPPutROMString(MySocket,DDNSClient.UpdateServer.szROM);
			else
				TCPPutString(MySocket,DDNSClient.UpdateServer.szRAM);
			
			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nAuthorization: Basic ");//23

			TCPFlush(MySocket);
			smDDNS++;
			// No break needed...try to send the next bit immediately.

		case SM_IP_UPDATE_REQ_E:

			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 6*TICK_SECOND)
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break; 
			}
			
			// User name and passwords for DynDNS.org can each be up to 24 characters
			// Base64 encoded data is always at least 25% bigger than the original
			if(TCPIsPutReady(MySocket) < 100u)
				break;	

			if(DDNSClient.ROMPointers.Username)
			{
				ROMStrPtr = (ROM char*)DDNSClient.Username.szROM;
				wPos = strlenpgm(ROMStrPtr);
			}
			else
			{
				RAMStrPtr = (char*)DDNSClient.Username.szRAM;
				wPos = strlen((char*)RAMStrPtr);
			}

			i = 0;
			while(wPos)
			{
				while(i < wPos && i < 3u)
				{
					if(DDNSClient.ROMPointers.Username)
						vBuffer[i] = *ROMStrPtr++;
					else
						vBuffer[i] = *RAMStrPtr++;
					i++;
				}
				wPos -= i; 				
										
				if(i == 3u)
				{
					Base64Encode(vBuffer, i, vBuffer, 4);
					TCPPutArray(MySocket, vBuffer, 4);
					i = 0;
				}
			}

			if(DDNSClient.ROMPointers.Password)
			{		
				ROMStrPtr = (ROM char*)DDNSClient.Password.szROM;
				wPos = strlenpgm(ROMStrPtr);
			}
			else
			{
				RAMStrPtr = (char*)DDNSClient.Password.szRAM;
				wPos = strlen((char*)RAMStrPtr);
			}

		  	// Increment for the ':' separator and i for bytes left in username
		  	wPos += i + 1;
			
			vBuffer[i++] = ':';

			while(wPos)
			{
				while(i < wPos && i < 3u)
				{
					if(DDNSClient.ROMPointers.Password)
						vBuffer[i] = *ROMStrPtr++;
					else
						vBuffer[i] = *RAMStrPtr++;
					i++;
				}
				wPos -= i; 				
				Base64Encode(vBuffer, i, vBuffer, 4);
				TCPPutArray(MySocket, vBuffer, 4);
				i = 0;
			}
			
			TCPFlush(MySocket);
			smDDNS++;
			break;

			
		case SM_IP_UPDATE_REQ_F:

			// Check for lost connections or timeouts
			if(!TCPIsConnected(MySocket) || TickGet() - Timer > 10*TICK_SECOND)
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break; 
			}
			
			if(TCPIsPutReady(MySocket) < 50)
				break;
			
			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nUser-Agent: Microchip - TCPIPSTACK - "VERSION"\r\n\r\n");
			TCPFlush(MySocket);
			smDDNS++;
			
			// Reset the timer to wait for a response
			Timer = TickGet();
			break;
								
		case SM_IPUPDATE_FIND_RESPONSE:
			// Locate the response string

			// Wait up to 10 seconds for a response
			if(TickGet() - Timer > 10*TICK_SECOND)
			{
				lastStatus = DDNS_STATUS_UPDATE_ERROR;
				smDDNS = SM_IPUDATE_DISCONNECT;
				break;
			}
		
			// According to HTTP, the response will start after the two CRLFs
			wPos = TCPFindROMArray(MySocket, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE);

			// If not yet found, eliminate everything up to
			if(wPos == 0xffff)
			{
				wPos = TCPIsGetReady(MySocket);
				if(wPos > 4)
					TCPGetArray(MySocket, NULL, wPos - 4);
				break;
			}
				
			TCPGetArray(MySocket, NULL, wPos+4);
			smDDNS++;
			// No break...continue to next state immediately
			
		case SM_IPUPDATE_PARSE_RESPONSE:
			// Try to parse the response text
			
			// Wait up to 10 seconds for the remote server to disconnect
			// so we know all data has been received
			if(TCPIsConnected(MySocket) && TickGet() - Timer < 10*TICK_SECOND)
				break;
			
			// Read the response code
		 	wPos = TCPIsGetReady(MySocket);
		 	if(wPos > sizeof(vBuffer) - 1)
		 		wPos = sizeof(vBuffer) - 1;

			wPos = TCPGetArray(MySocket, vBuffer, wPos);
			vBuffer[wPos] = '\0';
			for(i = 0; i < sizeof(vBuffer); i++)
				if(vBuffer[i] == ' ')
					vBuffer[i] = '\0';

			for(lastStatus = 0; lastStatus <= DDNS_STATUS_UPDATE_ERROR; lastStatus++)
				if(!strcmppgm2ram((char*)vBuffer, (ROM char*)_updateIpSrvrResponse[lastStatus]))
					break;
		
			smDDNS++;
			// No break...continue to finalization

		case SM_IPUDATE_DISCONNECT:
			// Close the socket so it can be used by other modules.
			if(MySocket != INVALID_SOCKET)
			{
				TCPDisconnect(MySocket);
				MySocket = INVALID_SOCKET;
			}
			
			// Determine what to do based on status
			if(lastStatus <= DDNS_STATUS_NUMHOST || lastStatus == DDNS_STATUS_UNCHANGED)
				smDDNS = SM_DONE;
			else if(lastStatus == DDNS_STATUS_911 || lastStatus == DDNS_STATUS_DNSERR)
				smDDNS = SM_SYSTEM_ERROR;
			else
				smDDNS = SM_SOFT_ERROR;
			
			smDDNS++;
			break;
			
		case SM_DONE:
			dwUpdateAt = TickGet() + 10*60*TICK_SECOND;	// 10 minutes
			smDDNS = SM_IDLE;
			break;
			
		case SM_SOFT_ERROR:
			dwUpdateAt = TickGet() + 30*TICK_SECOND; 		// 30 seconds
			smDDNS = SM_IDLE;
			break;
					
		case SM_SYSTEM_ERROR:
			dwUpdateAt = TickGet() + 30*60*TICK_SECOND;		// 30 minutes
			smDDNS = SM_IDLE;
			break;
	}
}
Ejemplo n.º 15
0
Archivo: HTTP.c Proyecto: sonite/mGit
/*********************************************************************
 * Transfer files to the client
 ********************************************************************/
static BOOL HTTP_SendFile(void)
{
	ptrdiff_t read;
	size_t write;
	char *buffer;

	// First handle static file data, which is simply pushed through
	// with minimal processing
	if(!HTTP.dynamic)
	{
		write = TCPIsPutReady(HTTP.socket);

		while(write)
		{
			read = FSfreadbuf((void **) &buffer, write, HTTP.file);
			write -= TCPPutArray(HTTP.socket, (BYTE *) buffer, read);

			if(FSerror() != CE_GOOD)
				return true;
		}

		return false;
	}

	// Transfer data from the file to the socket while looking for escape
	// characters and substituting variable values
	while(read = FSfreadbuf((void **) &buffer, TCPIsPutReady(HTTP.socket), HTTP.file), read)
	{
		// Reserved output buffer space for (escaped) variable values
		enum { VARIABLE_SPACE = HTTP_MAX_DATA_LEN * 2 };

		char *escape;

		// Look for the escape characters within the buffer
		while(escape = memchr((const char *) buffer, '%', read), escape)
		{
			char ch;

			// First flush all data up to the escape character
			read -= TCPPutArray(HTTP.socket, (BYTE *) buffer, escape - buffer);

			// Abort if there isn't enough output buffer space available
			if(TCPIsPutReady(HTTP.socket) < VARIABLE_SPACE)
			{
				FSfseek(HTTP.file, -read, SEEK_CUR);
				return false;
			}

			// Eat the escape character itself
			--read;
			buffer = escape + 1;

			// Read the variable name into a buffer
			HTTP_Buffer.write = HTTP_Data;

			do
			{
				if(read)
					--read;
				else if(!FSfreadbuf((void **) &buffer, 1, HTTP.file))
					return true;

				ch = *buffer++;

				if(ch == '%')
					ch = '\0';

				HTTP_PutBuf(ch);
			}
			while(ch);

			// Two escape characters in a row are used to emit the '%'
			// character itself
			if(HTTP_Buffer.write == &HTTP_Data[1])
				TCPPut(HTTP.socket, '%');
			// Write the variable's value with appropriate escape characters
			else
			{
				Cfg_SaveOne(Microchip_Settings, HTTP_Data, HTTP_WriteSocket);
				HTTP_WriteSocket();
			}
		}

		// Write the remainder and check for EOF
		TCPPutArray(HTTP.socket, (BYTE *) buffer, read);

		if(FSerror() != CE_GOOD)
			return true;
	}

	// We're not done yet..
	return false;
}
Ejemplo n.º 16
0
/*********************************************************************
 * Function:        void UART2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void UART2TCPBridgeTask2(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet;  //, w;
	//BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	//BYTE *TXHeadPtrShadow, *TXTailPtrShadow;
	unsigned char buffer[PACK_MAX_RX_SIZE];
	DATA_RX_PACKET_T * prx;
	DATA_TX_PACKET_T * ptx;

	switch(BridgeState)
	{
	default:
		case SM_HOME:

			putrsUART((ROM char*)"\r\n IN UART2TCPBridgeTask() home");

			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#else
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART1TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
            #endif
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);

			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:

			//RELAY_OUT_1 = 0;

			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
			{	
				LED7_IO = 0;
				break;
			}
			
			LED7_IO = 1;

			// Make sure to clear UART errors so they don't block all future operations

			if(OERR2) //RCSTAbits.OERR)
			{
				//RCSTAbits.CREN = 0;
				CREN2 = 0;
				//RCSTAbits.CREN = 1;
				CREN2 = 1;
				LED1_IO ^= 1;
			}
			if(FERR2) //RCSTAbits.FERR)
			{
				BYTE dummy = RCREG2; //RCREG;
				LED2_IO ^= 1;
			}



			prx =  GetFinishedPacket();
			if(prx != NULL) {
				if(prx->finished) {
					if(prx->index > 0) {
						wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
						wMaxPut = (prx->index > wMaxPut)?wMaxPut:prx->index;
						if(wMaxPut > 0) {
							TCPPutArray(MySocket, &(prx->buffer[0]), wMaxPut);
							prx->index = 0;
							prx->finished = 0;
							TCPFlush(MySocket);
						}
					}
					prx->index = 0;
					prx->finished = 0;  //测试用
					//if(THISINFO)putrsUART((ROM char *)"\r\UART Bridge look at it");
				}
			}
			//PIE1bits.RCIE = 1;
			RC2IE = 1;



			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			if(wMaxGet > 0) {
				DATA_TX_PACKET_T * ptx = find_next_empty_tx_buffer();
				if(ptx != NULL) {
					wMaxGet = (wMaxGet > PACK_MAX_RX_SIZE)?PACK_MAX_RX_SIZE:wMaxGet;
				    TCPGetArray(MySocket,(BYTE *)&buffer[0],wMaxGet);
				    ptx = prase_in_buffer(buffer,wMaxGet);
				    if(ptx != NULL) {
					    if(ptx->index > 0) {
						    //启动发送
						    //PIE1bits.TXIE = 1;
							TX2IE = 1;
					    }
				    }
				}
			} else {
				TCPDiscard(MySocket);
			}
			break;
	}
}
Ejemplo n.º 17
0
/*********************************************************************
 * Function:        void UART2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void UART2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#else
				MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
			#endif
			
			// Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the UART FIFOs
				//RXHeadPtr = vUARTRXFIFO;
				//RXTailPtr = vUARTRXFIFO;
				//TXHeadPtr = vUARTTXFIFO;
				//TXTailPtr = vUARTTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			
			
			// Make sure to clear UART errors so they don't block all future operations
			#if defined(__18CXX)
			if(RCSTAbits.OERR)
			{
				RCSTAbits.CREN = 0;
				RCSTAbits.CREN = 1;
				LED1_IO ^= 1;
			}
			if(RCSTAbits.FERR)
			{
				BYTE dummy = RCREG;
				LED2_IO ^= 1;
			}
			#else
			if(U2STAbits.OERR)
				U2STAbits.OERR = 0;
			#endif
			

			// Read FIFO pointers into a local shadow copy.  Some pointers are volatile 
			// (modified in the ISR), so we must do this safely by disabling interrupts
			RXTailPtrShadow = (BYTE*)RXTailPtr;
			TXHeadPtrShadow = (BYTE*)TXHeadPtr;
			#if defined(__18CXX)
			PIE1bits.RCIE = 0;
			PIE1bits.TXIE = 0;
			#else
			IEC1bits.U2RXIE = 0;
			IEC1bits.U2TXIE = 0;
			#endif
			RXHeadPtrShadow = (BYTE*)RXHeadPtr;
			TXTailPtrShadow = (BYTE*)TXTailPtr;
			#if defined(__18CXX)
			PIE1bits.RCIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				PIE1bits.TXIE = 1;
			#else
			IEC1bits.U2RXIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				IEC1bits.U2TXIE = 1;
			#endif

			//
			// Transmit pending data that has been placed into the UART RX FIFO (in the ISR)
			//
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
			wMaxGet = RXHeadPtrShadow - RXTailPtrShadow;	// Get UART RX FIFO byte count
			if(RXHeadPtrShadow < RXTailPtrShadow)
				wMaxGet += sizeof(vUARTRXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vUARTRXFIFO 
				// end to start address.
				w = vUARTRXFIFO + sizeof(vUARTRXFIFO) - RXTailPtrShadow;
				if(wMaxPut >= w)
				{
					TCPPutArray(MySocket, RXTailPtrShadow, w);
					RXTailPtrShadow = vUARTRXFIFO;
					wMaxPut -= w;
				}
				TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
				RXTailPtrShadow += wMaxPut;

				// No flush.  The stack will automatically flush and do 
				// transmit coallescing to minimize the number of TCP 
				// packets that get sent.  If you explicitly call TCPFlush()
				// here, latency will go down, but so will max throughput 
				// and bandwidth efficiency.
			}

			//
			// Transfer received TCP data into the UART TX FIFO for future transmission (in the ISR)
			//
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get UART TX FIFO free space
			if(TXHeadPtrShadow >= TXTailPtrShadow)
				wMaxPut += sizeof(vUARTTXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vUARTTXFIFO 
				// end to start address.
				w = vUARTTXFIFO + sizeof(vUARTTXFIFO) - TXHeadPtrShadow;
				if(wMaxPut >= w)
				{
					TCPGetArray(MySocket, TXHeadPtrShadow, w);
					TXHeadPtrShadow = vUARTTXFIFO;
					wMaxPut -= w;
				}
				TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
				TXHeadPtrShadow += wMaxPut;
			}
			
			// Write local shadowed FIFO pointers into the volatile FIFO pointers.
			#if defined(__18CXX)
			PIE1bits.RCIE = 0;
			PIE1bits.TXIE = 0;
			#else
			IEC1bits.U2RXIE = 0;
			IEC1bits.U2TXIE = 0;
			#endif
			RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
			TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
			#if defined(__18CXX)
			PIE1bits.RCIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				PIE1bits.TXIE = 1;
			#else
			IEC1bits.U2RXIE = 1;
			if(TXHeadPtrShadow != TXTailPtrShadow)
				IEC1bits.U2TXIE = 1;
			#endif

			break;
	}
}
Ejemplo n.º 18
0
/*****************************************************************************
  Function:
	int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)

  Summary:
	This function used to send the data for both connection oriented and connection-less
	sockets.

  Description:
	The sendto function is used to send outgoing data on a socket.
	The destination address is given by to and tolen. Both
	Datagram and stream sockets are supported.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data buffer containing data to transmit.
	len - length of data in bytes.
	flags - message flags. Currently this field is not supported.
	to - Optional pointer to the the sockaddr structure containing the
		destination address.  If NULL, the currently bound remote port and IP
		address are used as the destination.
	tolen - length of the sockaddr structure.

  Returns:
	On success, sendto returns number of bytes sent. In case of
	error returns SOCKET_ERROR (and errno set accordingly).

  Remarks:
	None.
  ***************************************************************************/
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
{
    struct BSDSocket *socket;
    UDP_SOCKET_DCPT*  udpSkt;
    int size = SOCKET_ERROR;
    NODE_INFO remoteInfo;
    uint16_t wRemotePort;
    struct sockaddr_in local;

    if( s >= BSD_SOCKET_COUNT )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    socket = &BSDSocketArray[s];

    if(socket->bsdState == SKT_CLOSED)
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        // Decide the destination IP address and port
        remoteInfo.IPAddr.Val = socket->remoteIP;
        wRemotePort = socket->remotePort;
        if(to)
        {
            if((unsigned int)tolen != sizeof(struct sockaddr_in))
            {
                errno = EFAULT;
                return SOCKET_ERROR;
            }
            wRemotePort = ((struct sockaddr_in*)to)->sin_port;
            remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr;

            // Implicitly bind the socket if it isn't already
            if(socket->bsdState == SKT_CREATED)
            {
                memset(&local, 0x00, sizeof(local));
                if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
                    return SOCKET_ERROR;
            }
        }

        if(remoteInfo.IPAddr.Val == IP_ADDR_ANY)
            remoteInfo.IPAddr.Val = 0xFFFFFFFFu;

        // Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket
        udpSkt = UDPSocketDcpt + socket->SocketID;
        if(TCPIP_IPV4_GetDestAddress(udpSkt->pTxPkt).Val != remoteInfo.IPAddr.Val)
        {
            TCPIP_IPV4_SetDestAddress(udpSkt->pTxPkt, remoteInfo.IPAddr.Val);
            if(!ARPIsResolved(UDPSocketGetNet(socket->SocketID), &remoteInfo.IPAddr, &((IPV4_PACKET*)udpSkt->pTxPkt)->remoteMACAddr))
            {
                errno = EINPROGRESS;
                return SOCKET_ERROR;
            }
        }
        // Select the UDP socket and see if we can write to it
        if(UDPIsTxPutReady(socket->SocketID, len))
        {
            // Set the proper remote port
            udpSkt->remotePort = wRemotePort;

            // Write data and send UDP datagram
            size = UDPPutArray(socket->SocketID, (uint8_t*)buf, len);
            UDPFlush(socket->SocketID);
            return size;
        }
    }
    else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket.
    {
        if(socket->bsdState != SKT_EST)
        {
            errno = ENOTCONN;
            return SOCKET_ERROR;
        }

        if(HandlePossibleTCPDisconnection(s))
        {
            errno = ECONNRESET;
            return SOCKET_ERROR;
        }

        // Handle special case were 0 return value is okay
        if(len == 0)
            return 0;

        // Write data to the socket. If one or more bytes were written, then
        // return this value.  Otherwise, fail and return SOCKET_ERROR.
        size = TCPPutArray(socket->SocketID, (uint8_t*)buf, len);
        if(size)
            return size;
    }
    errno = EWOULDBLOCK;
    return SOCKET_ERROR;
}
Ejemplo n.º 19
0
static BOOL HTTPServeStaticAsset(void)
{


  static DWORD availbleTcpBuffSize,len;
  static DWORD cntr=0;
  static BYTE lock=0;
  static BYTE nameHashMatched=FALSE;
  static DWORD numBytes,dynVarCntr,dynVarRcrdOffset,dynVarCallBackID,bytesReadCount=0;
  DWORD UInt32DataFromBinFile;
  WORD UInt16DataFromBinFile,nameHashRcrd;
  DWORD recrdcntr=0;
  
  signed char chdirRetVal;

  static enum
  {
  	SM_IDLE = 0u,
    SM_SERVE_TEXT_DATA,     
    SM_CLOSE_FILE

  }smHTTPSendFile = SM_IDLE;

  switch(smHTTPSendFile)
  {

  	case SM_IDLE:
  		numBytes = FATFS_fsize(activeConnection.file);

    case SM_SERVE_TEXT_DATA:

      // If HashIndex do not match,that means no entry in the "FilRcrd.bin", means no dynamic variables for this wepage,
      //then proceed to serve the page as normal HTML text
    	memset(sendDataBuffer, 0, sizeof(sendDataBuffer));

      availbleTcpBuffSize = TCPIsPutReady(activeSocket);
      
      if(availbleTcpBuffSize >= 512)
      {
        if(numBytes >= 512)
        {
          len=FATFS_fread(sendDataBuffer, 1, 512, activeConnection.file);
          TCPPutArray(activeSocket, sendDataBuffer, len);
          numBytes -= len;
        }
        else
        {
          len=FATFS_fread(sendDataBuffer, 1, numBytes, activeConnection.file);
          TCPPutArray(activeSocket, sendDataBuffer, len);
          numBytes = 0;

        }
      }
      else if(availbleTcpBuffSize != 0)
      {
        if(numBytes >= availbleTcpBuffSize)
        {
          len=FATFS_fread(sendDataBuffer, 1, availbleTcpBuffSize, activeConnection.file);
          TCPPutArray(activeSocket, sendDataBuffer, len);
          numBytes -= len;
        }
        else 
        {
          len=FATFS_fread(sendDataBuffer, 1, numBytes, activeConnection.file);
          TCPPutArray(activeSocket, sendDataBuffer, numBytes);
          numBytes = 0;
          
        }
      }
      if(numBytes <= 100)
      {
        numBytes=numBytes;
      }
      if(numBytes == 0)
      {
        TCPFlush(activeSocket);

        FATFS_fclose(activeConnection.file);

        smHTTPSendFile=SM_IDLE;
        bytesReadCount=0;
        return TRUE;
      }

      TCPFlush(activeSocket);
      break;

    default:
      return FALSE;
        
  }

  if(FATFS_feof(activeConnection.file) || numBytes == 0)
  {
    TCPFlush(activeSocket);
    
    FATFS_fclose(activeConnection.file);
            
    smHTTPSendFile=SM_IDLE;
    return TRUE;
  }

  return FALSE;
}
Ejemplo n.º 20
0
/*****************************************************************************
  Function:
	int send( SOCKET s, const char* buf, int len, int flags )
	
  Summary:
	The send function is used to send outgoing data on an already
    connected socket.

  Description:
	The send function is used to send outgoing data on an already
    connected socket. This function is used to send a reliable,
    ordered stream of data bytes on a socket of type SOCK_STREAM
    but can also be used to send datagrams on a socket of type SOCK_DGRAM.

  Precondition:
	connect function should be called for TCP and UDP sockets.
	Server side, accept function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
    buf - application data buffer containing data to transmit.
    len - length of data in bytes.
    flags - message flags. Currently this field is not supported.
  
  Returns:
	On success, send returns number of bytes sent. In case of
    error, returns SOCKET_ERROR. a zero indicates no data send.

  Remarks:
	None.
  ***************************************************************************/
int send( SOCKET s, const char* buf, int len, int flags )
{
    struct BSDSocket *socket;
    WORD size;
    NODE_INFO remoteInfo;
    static DWORD startTick;

    if( s >= BSD_SOCKET_COUNT )
        return SOCKET_ERROR;

    socket = &BSDSocketArray[s];

    if( socket->bsdState < SKT_BOUND )
        return SOCKET_ERROR;

    if(!TCPIsConnected(socket->SocketID))
        return SOCKET_ERROR; //Indicates the socket is disconnected.
      
    if(socket->SocketType == SOCK_STREAM) //TCP
    {
        // Make certain the socket can be written to
        if(TCPIsPutReady(socket->SocketID) > 0)
        {
            return TCPPutArray(socket->SocketID, (BYTE*)buf, len);
        }
        else
        {
            return SOCKET_ERROR;
        }
    }
    else if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        if((socket->bsdState >= SKT_READY) && (socket->bsdState != SKT_EST))//making sure that connect function is called
        {
            if(socket->bsdState != SKT_ARP_VERIFY)
            {
                remoteInfo.IPAddr.Val = socket->remoteIP;
                ARPResolve(&remoteInfo.IPAddr);
                startTick = TickGet();
                socket->bsdState = SKT_ARP_VERIFY;
            }
            else if(socket->bsdState == SKT_ARP_VERIFY)
            {
                // Wait for the MAC address to finish being obtained
                remoteInfo.IPAddr.Val = socket->remoteIP;
                if(!ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
                {
                    // Time out if too much time is spent in this state
    			    if(TickGet()- startTick > 1*TICK_SECOND)
    			    {
                        // Retransmit ARP request
                        socket->bsdState = SKT_ARP_RESOLVE;
    			    }
                 }
                 socket->SocketID = UDPOpen(socket->localPort, &remoteInfo, socket->remotePort);
                 socket->bsdState = SKT_EST;
            } 
        }
        
        if(socket->bsdState == SKT_EST)
        {
            if(UDPIsPutReady(socket->SocketID) > 0)
            {
                size = UDPPutArray((BYTE*)buf, len);
                UDPFlush();
                return size;
            }
        }
        else
        {
            return SOCKET_ERROR;
        }
    }
    return SOCKET_ERROR;
}
Ejemplo n.º 21
0
// ======================================
// = Sends the new/current SSID setting =
// ======================================
void HTTPPrint_ssid(void)
{
    TCPPutArray(sktHTTP, CPElements.ssid, CPElements.ssidLength);
}
Ejemplo n.º 22
0
/*********************************************************************
 * Function:        void GenericTCPServer(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void GenericTCPServer(void)
{
	BYTE i;
	WORD w, w2;
	BYTE AppBuffer[32];
	WORD wMaxGet, wMaxPut, wCurrentChunk;
	static TCP_SOCKET	MySocket;
	static enum _TCPServerState
	{
		SM_HOME = 0,
		SM_LISTENING,
	} TCPServerState = SM_HOME;

	switch(TCPServerState)
	{
		case SM_HOME:
			// Allocate a socket for this server to listen and accept connections on
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER);
			if(MySocket == INVALID_SOCKET)
			{
#ifdef USE_LCD
				strcpypgm2ram((char*)LCDText, "Error: Increase MAX_TCP_SOCKETS");
				LCDUpdate();
#endif
				return;
			}

			TCPServerState = SM_LISTENING;
			break;

		case SM_LISTENING:
			// See if anyone is connected to us
			if(!TCPIsConnected(MySocket))
				return;


			// Figure out how many bytes have been received and how many we can transmit.
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO free space

			// Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO
			if(wMaxPut < wMaxGet)
				wMaxGet = wMaxPut;

			// Process all bytes that we can
			// This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time.  
			// This limits memory usage while maximizing performance.  Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays.
			wCurrentChunk = sizeof(AppBuffer);
			for(w = 0; w < wMaxGet; w += sizeof(AppBuffer))
			{
				// Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly.
				if(w + sizeof(AppBuffer) > wMaxGet)
					wCurrentChunk = wMaxGet - w;

				// Transfer the data out of the TCP RX FIFO and into our local processing buffer.
				TCPGetArray(MySocket, AppBuffer, wCurrentChunk);
				
				// Perform the "ToUpper" operation on each data byte
				for(w2 = 0; w2 < wCurrentChunk; w2++)
				{
					i = AppBuffer[w2];
					if(i >= 'a' && i <= 'z')
					{
						i -= ('a' - 'A');
						AppBuffer[w2] = i;
					}
				}
				
				// Transfer the data out of our local processing buffer and into the TCP TX FIFO.
				TCPPutArray(MySocket, AppBuffer, wCurrentChunk);
			}

			// No need to perform any flush.  TCP data in TX FIFO will automatically transmit itself after it accumulates for a while.  If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API.

			break;
	}
}
Ejemplo n.º 23
0
/// @cond debug
//****************************************************************************
//	Only internal use:
//	cTCPWrite callback function
//****************************************************************************
int cTCPWrite()
{
	xWord = TCPPutArray(xSocket , xByte , xInt);
	TCPFlush(xSocket);
	return xWord;
}
Ejemplo n.º 24
0
/*****************************************************************************
  Function:
	void SMTPClientTask(void)

  Summary:
	Performs any pending SMTP client tasks

  Description:
	This function handles periodic tasks associated with the SMTP client,
	such as processing initial connections and command sequences.

  Precondition:
	None

  Parameters:
	None

  Returns:
	None

  Remarks:
	This function acts as a task (similar to one in an RTOS).  It
	performs its task in a co-operative manner, and the main application
	must call this function repeatedly to ensure that all open or new
	connections are served in a timely fashion.
  ***************************************************************************/
void SMTPClientTask(void)
{
    uint8_t			i;
    uint16_t			w;
    uint8_t			vBase64Buffer[4];
    static SYS_TICK	SMTPTimer;
    static uint8_t		RXBuffer[4];
    static const uint8_t *ROMStrPtr, *ROMStrPtr2;
    static const uint8_t *RAMStrPtr;
    static uint16_t		wAddressLength;
    DNS_RESULT      dnsRes;

    switch(TransportState)
    {
    case TRANSPORT_HOME:
        // SMTPBeginUsage() 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 SMTPSendMail()
        if(!SMTPFlags.bits.ReadyToStart)
            break;

        // Obtain ownership of the DNS resolution module
        if(DNSBeginUsage(0) != DNS_RES_OK)
        {
            break;
        }

        // Obtain the IP address associated with the SMTP mail server
        if(SMTPClient.Server)
        {
            DNSResolve((const char*)SMTPClient.Server, DNS_TYPE_A);
        }
        else
        {
            // If we don't have a mail server, try to send the mail
            // directly to the destination SMTP server
            if(SMTPClient.To)
            {
                SMTPClient.Server = strchr((char*)SMTPClient.To, '@');
            }

            if(!(SMTPClient.Server))
            {
                if(SMTPClient.CC)
                {
                    SMTPClient.Server = strchr((char*)SMTPClient.CC, '@');
                }
            }

            if(!(SMTPClient.Server))
            {
                if(SMTPClient.BCC)
                {
                    SMTPClient.Server = strchr((char*)SMTPClient.BCC, '@');
                }
            }

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

            // Skip over the @ sign and resolve the host name
            SMTPClient.Server++;
            DNSResolve((const char*)SMTPClient.Server, DNS_TYPE_MX);
        }

        SMTPTimer = SYS_TICK_Get();
        TransportState++;
        break;

    case TRANSPORT_NAME_RESOLVE:
        // Wait for the DNS server to return the requested IP address
        dnsRes = DNSIsResolved((const char*)SMTPClient.Server, &SMTPServer);

        if(dnsRes == DNS_RES_PENDING)
        {
            break;
        }

        // Release the DNS module
        DNSEndUsage(0);

        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 = TCPOpenClient(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;

        TransportState++;
        SMTPTimer = SYS_TICK_Get();
        // No break; fall into TRANSPORT_SOCKET_OBTAINED

#if defined(TCPIP_STACK_USE_SSL_CLIENT)
    case TRANSPORT_SECURING_SOCKET:
        if(!TCPIsConnected(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((SYS_TICK_Get()-SMTPTimer) > (SMTP_SERVER_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet()))
            {
                ResponseCode = SMTP_CONNECT_ERROR;
                TransportState = TRANSPORT_CLOSE;
            }

            break;
        }
        SMTPFlags.bits.ConnectedOnce = true;

        // Start SSL if needed for this connection
        if(SMTPClient.UseSSL && !TCPStartSSLClient(MySocket,NULL))
            break;

        // Move on to main state
        SMTPTimer = SYS_TICK_Get();
        TransportState++;
        break;
#endif

    case TRANSPORT_SOCKET_OBTAINED:
        if(!TCPIsConnected(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_TICK_Get()-SMTPTimer) > (SMTP_SERVER_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet())))
            {
                ResponseCode = SMTP_CONNECT_ERROR;
                TransportState = TRANSPORT_CLOSE;
            }

            break;
        }
        SMTPFlags.bits.ConnectedOnce = true;

#if defined(TCPIP_STACK_USE_SSL_CLIENT)
        // Make sure the SSL handshake has completed
        if(SMTPClient.UseSSL && TCPSSLIsHandshaking(MySocket))
            break;
#endif

        // See if the server sent us anything
        while(TCPIsGetReady(MySocket))
        {
            TCPGet(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(TCPIsPutReady(MySocket) < 64u)
            break;

        switch(SMTPState)
        {
        case SMTP_HELO:
            if(SMTPClient.Username == NULL)
                TCPPutString(MySocket, (uint8_t*)"HELO MCHPBOARD\r\n");
            else
                TCPPutString(MySocket, (uint8_t*)"EHLO MCHPBOARD\r\n");
            TCPFlush(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)
            TCPPutString(MySocket, (uint8_t*)"AUTH LOGIN\r\n");
            TCPFlush(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));
                TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
            }
            TCPPutString(MySocket, (uint8_t*)"\r\n");
            TCPFlush(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));
                TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
            }
            TCPPutString(MySocket, (uint8_t*)"\r\n");
            TCPFlush(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.
            TCPPutString(MySocket, (uint8_t*)"MAIL FROM:<");
            RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.From, &wAddressLength);
            TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
            TCPPutString(MySocket, (uint8_t*)">\r\n");
            TCPFlush(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:
            TCPPutString(MySocket, (uint8_t*)"RCPT TO:<");
            TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
            TCPPutString(MySocket, (uint8_t*)">\r\n");
            TCPFlush(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:
            TCPPutString(MySocket, (uint8_t*)"DATA\r\n");
            SMTPState++;
            PutHeadersState = PUTHEADERS_FROM_INIT;
            TCPFlush(MySocket);
            break;

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

                case PUTHEADERS_FROM:
                    SMTPClient.From = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.From);
                    if(*SMTPClient.From == 0u)
                        PutHeadersState = PUTHEADERS_TO_INIT;
                    break;

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

                case PUTHEADERS_TO:
                    SMTPClient.To = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.To);
                    if(*SMTPClient.To == 0u)
                        PutHeadersState = PUTHEADERS_CC_INIT;
                    break;

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

                case PUTHEADERS_CC:
                    SMTPClient.CC = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.CC);
                    if(*SMTPClient.CC == 0u)
                        PutHeadersState = PUTHEADERS_SUBJECT_INIT;
                    break;

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

                case PUTHEADERS_SUBJECT:
                    SMTPClient.Subject = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.Subject);
                    if(*SMTPClient.Subject == 0u)
                        PutHeadersState = PUTHEADERS_OTHER_INIT;
                    break;

                case PUTHEADERS_OTHER_INIT:
                    TCPPutArray(MySocket, (uint8_t*)"\r\n", 2);
                    if(SMTPClient.OtherHeaders)
                    {
                        PutHeadersState = PUTHEADERS_OTHER;
                    }
                    else
                    {
                        TCPPutArray(MySocket, (uint8_t*)"\r\n", 2);
                        PutHeadersState = PUTHEADERS_DONE;
                        SMTPState++;
                    }
                    break;

                case PUTHEADERS_OTHER:
                    SMTPClient.OtherHeaders = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.OtherHeaders);
                    if(*SMTPClient.OtherHeaders == 0u)
                    {
                        TCPPutArray(MySocket, (uint8_t*)"\r\n", 2);
                        PutHeadersState = PUTHEADERS_DONE;
                        SMTPState++;
                    }
                    break;

                // Default case needed to supress compiler diagnostics
                default:
                    break;
                }
            }
            TCPFlush(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 += TCPPutArray(MySocket, RAMStrPtr, CRPeriod.Pos-RAMStrPtr);
                        if(RAMStrPtr == CRPeriod.Pos)
                        {
                            if(!TCPPut(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 = TCPPutString(MySocket, RAMStrPtr);
                    ROMStrPtr2 = TCPPutString(MySocket, (uint8_t*)ROMStrPtr2);
                    TCPFlush(MySocket);
                }
            }
            else
            {
                if(SMTPFlags.bits.ReadyToFinish)
                {
                    if(*ROMStrPtr2)
                    {
                        ROMStrPtr2 = TCPPutString(MySocket, (uint8_t*)ROMStrPtr2);
                        TCPFlush(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 = TCPPutString(MySocket, (uint8_t*)ROMStrPtr);
                TCPFlush(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
        TCPClose(MySocket);
        MySocket = INVALID_SOCKET;

        // Go back to doing nothing
        TransportState = TRANSPORT_HOME;
        break;
    }
}
Ejemplo n.º 25
0
/*****************************************************************************
  Function:
	void SMTPTask(void)

  Summary:
	Performs any pending SMTP client tasks

  Description:
	This function handles periodic tasks associated with the SMTP client,
	such as processing initial connections and command sequences.

  Precondition:
	None

  Parameters:
	None

  Returns:
	None

  Remarks:
	This function acts as a task (similar to one in an RTOS).  It
	performs its task in a co-operative manner, and the main application
	must call this function repeatedly to ensure that all open or new
	connections are served in a timely fashion.
  ***************************************************************************/
void SMTPTask(void)
{
	BYTE			i;
	WORD			w;
	BYTE			vBase64Buffer[4];
	static DWORD	Timer;
	static BYTE		RXBuffer[4];
	static ROM BYTE *ROMStrPtr, *ROMStrPtr2;
	static BYTE 	*RAMStrPtr;
	static WORD		wAddressLength;

 WORD tmp;

	switch(TransportState)
	{
		case TRANSPORT_HOME:
			// SMTPBeginUsage() 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 SMTPSendMail()
			if(!SMTPFlags.bits.ReadyToStart)
				break;

			// Obtain ownership of the DNS resolution module
			if(!DNSBeginUsage())
				break;

			// Obtain the IP address associated with the SMTP mail server
			if(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)
			{
				if(SMTPClient.ROMPointers.Server)
					DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_A);
				else
					DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_A);
			}
			else
			{
				// If we don't have a mail server, try to send the mail 
				// directly to the destination SMTP server
				if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To)
				{
					SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.To.szRAM, '@');
					SMTPClient.ROMPointers.Server = 0;
				}
				else if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To)
				{
					SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.To.szROM, '@');
					SMTPClient.ROMPointers.Server = 1;
				}

				if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM))
				{
					if(SMTPClient.CC.szRAM && !SMTPClient.ROMPointers.CC)
					{
						SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.CC.szRAM, '@');
						SMTPClient.ROMPointers.Server = 0;
					}
					else if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC)
					{
						SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.CC.szROM, '@');
						SMTPClient.ROMPointers.Server = 1;
					}
				}

				if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM))
				{
					if(SMTPClient.BCC.szRAM && !SMTPClient.ROMPointers.BCC)
					{
						SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.BCC.szRAM, '@');
						SMTPClient.ROMPointers.Server = 0;
					}
					else if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC)
					{
						SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.BCC.szROM, '@');
						SMTPClient.ROMPointers.Server = 1;
					}
				}

				// See if we found a hostname anywhere which we could resolve
				if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM))
				{
					DNSEndUsage();
					ResponseCode = SMTP_RESOLVE_ERROR;
					TransportState = TRANSPORT_HOME;
					break;
				}

				// Skip over the @ sign and resolve the host name
				if(SMTPClient.ROMPointers.Server)
				{
					SMTPClient.Server.szROM++;
					DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_MX);
				}
				else
				{
					SMTPClient.Server.szRAM++;
					DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_MX);
				}
			}
			
			Timer = TickGet();
			TransportState++;
			break;

		case TRANSPORT_NAME_RESOLVE:
			// Wait for the DNS server to return the requested IP address
			if(!DNSIsResolved(&SMTPServer))
			{
				// Timeout after 6 seconds of unsuccessful DNS resolution
				if(TickGet() - Timer > 6*TICK_SECOND)
				{
					ResponseCode = SMTP_RESOLVE_ERROR;
					TransportState = TRANSPORT_HOME;
					DNSEndUsage();
				}
				break;
			}

			// Release the DNS module, we no longer need it
			if(!DNSEndUsage())
			{
				// An invalid IP address was returned from the DNS 
				// server.  Quit and fail permanantly if host is not valid.
				ResponseCode = SMTP_RESOLVE_ERROR;
				TransportState = TRANSPORT_HOME;
				break;
			}

			TransportState++;
			// No need to break here

		case TRANSPORT_OBTAIN_SOCKET:
			// Connect a TCP socket to the remote SMTP server
			MySocket = TCPOpen(SMTPServer.Val, TCP_OPEN_IP_ADDRESS, SMTPClient.ServerPort, TCP_PURPOSE_DEFAULT);
			
			// Abort operation if no TCP sockets are available
			// If this ever happens, add some more 
			// TCP_PURPOSE_DEFAULT sockets in TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			TransportState++;
			Timer = TickGet();
			// No break; fall into TRANSPORT_SOCKET_OBTAINED
			
		#if defined(STACK_USE_SSL_CLIENT)
		case TRANSPORT_SECURING_SOCKET:		
			if(!TCPIsConnected(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((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT))
				{
					ResponseCode = SMTP_CONNECT_ERROR;
					TransportState = TRANSPORT_CLOSE;
				}

				break;
			}
			SMTPFlags.bits.ConnectedOnce = TRUE;
			
			// Start SSL if needed for this connection
			if(SMTPClient.UseSSL && !TCPStartSSLClient(MySocket,NULL))
				break;
			
			// Move on to main state
			Timer = TickGet();
			TransportState++;
			break;		
		#endif

		case TRANSPORT_SOCKET_OBTAINED:
			if(!TCPIsConnected(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 || ((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT)))
				{
					ResponseCode = SMTP_CONNECT_ERROR;
					TransportState = TRANSPORT_CLOSE;
				}

				break;
			}
			SMTPFlags.bits.ConnectedOnce = TRUE;
			
			#if defined(STACK_USE_SSL_CLIENT)
			// Make sure the SSL handshake has completed
			if(SMTPClient.UseSSL && TCPSSLIsHandshaking(MySocket))
				break;
			#endif

			// See if the server sent us anything
			while(TCPIsGetReady(MySocket))
			{
				TCPGet(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.szRAM || SMTPClient.Username.szROM)
												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:
                                                                            tmp = SMTPState;
										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(TCPIsPutReady(MySocket) < 64u)
				break;

			switch(SMTPState)
			{
				case SMTP_HELO:
					if(SMTPClient.Username.szROM == NULL)
						TCPPutROMString(MySocket, (ROM BYTE*)"HELO MCHPBOARD\r\n");
					else
						TCPPutROMString(MySocket, (ROM BYTE*)"EHLO MCHPBOARD\r\n");
					TCPFlush(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 (either SMTPClient.Username.szROM or 
					// SMTPClient.Username.szRAM is non-NULL)
					TCPPutROMString(MySocket, (ROM BYTE*)"AUTH LOGIN\r\n");
					TCPFlush(MySocket);
					SMTPState++;
					break;

				case SMTP_AUTH_USERNAME:
					// Base 64 encode and transmit the username.
					if(SMTPClient.ROMPointers.Username)
					{
						ROMStrPtr = SMTPClient.Username.szROM;
						w = strlenpgm((ROM char*)ROMStrPtr);
					}
					else
					{
						RAMStrPtr = SMTPClient.Username.szRAM;
						w = strlen((char*)RAMStrPtr);
					}

					while(w)
					{
						i = 0;
						while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
						{
							if(SMTPClient.ROMPointers.Username)
								vBase64Buffer[i] = *ROMStrPtr++;
							else
								vBase64Buffer[i] = *RAMStrPtr++;
							i++;
						}
						w -= i;					
						Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
						TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
					}
					TCPPutROMString(MySocket, (ROM BYTE*)"\r\n");
					TCPFlush(MySocket);
					SMTPState++;
					break;

				case SMTP_AUTH_PASSWORD:
					// Base 64 encode and transmit the password
					if(SMTPClient.ROMPointers.Password)
					{
						ROMStrPtr = SMTPClient.Password.szROM;
						w = strlenpgm((ROM char*)ROMStrPtr);
					}
					else
					{
						RAMStrPtr = SMTPClient.Password.szRAM;
						w = strlen((char*)RAMStrPtr);
					}

					while(w)
					{
						i = 0;
						while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
						{
							if(SMTPClient.ROMPointers.Password)
								vBase64Buffer[i] = *ROMStrPtr++;
							else
								vBase64Buffer[i] = *RAMStrPtr++;
							i++;
						}
						w -= i;					
						Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
						TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
					}
					TCPPutROMString(MySocket, (ROM BYTE*)"\r\n");
					TCPFlush(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.
					TCPPutROMString(MySocket, (ROM BYTE*)"MAIL FROM:<");
					if(SMTPClient.ROMPointers.From)
					{
						ROMStrPtr = FindROMEmailAddress(SMTPClient.From.szROM, &wAddressLength);
						TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength);
					}
					else
					{
						RAMStrPtr = FindEmailAddress(SMTPClient.From.szRAM, &wAddressLength);
						TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
					}
					TCPPutROMString(MySocket, (ROM BYTE*)">\r\n");
					TCPFlush(MySocket);
					SMTPState++;
					break;

				case SMTP_RCPTTO_INIT:
					// See if there are any (To) recipients to process
					if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To)
					{
						RAMStrPtr = FindEmailAddress(SMTPClient.To.szRAM, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTO;
							break;
						}
					}
					if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To)
					{
						ROMStrPtr = FindROMEmailAddress(SMTPClient.To.szROM, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTO;
							break;
						}
					}
					
					SMTPState = SMTP_RCPTTOCC_INIT;
					break;

				case SMTP_RCPTTO:
				case SMTP_RCPTTOCC:
				case SMTP_RCPTTOBCC:
					TCPPutROMString(MySocket, (ROM BYTE*)"RCPT TO:<");
					if(	(SMTPClient.ROMPointers.To  && (SMTPState == SMTP_RCPTTO)) || 
						(SMTPClient.ROMPointers.CC  && (SMTPState == SMTP_RCPTTOCC)) || 
						(SMTPClient.ROMPointers.BCC && (SMTPState == SMTP_RCPTTOBCC)) )
						TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength);
					else
						TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
					TCPPutROMString(MySocket, (ROM BYTE*)">\r\n");
					TCPFlush(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
					if(SMTPClient.ROMPointers.To)
						ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength);
					else
						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.szRAM && !SMTPClient.ROMPointers.CC)
					{
						RAMStrPtr = FindEmailAddress(SMTPClient.CC.szRAM, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTOCC;
							break;
						}
					}
					if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC)
					{
						ROMStrPtr = FindROMEmailAddress(SMTPClient.CC.szROM, &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
					if(SMTPClient.ROMPointers.CC)
						ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength);
					else
						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.szRAM && !SMTPClient.ROMPointers.BCC)
					{
						RAMStrPtr = FindEmailAddress(SMTPClient.BCC.szRAM, &wAddressLength);
						if(wAddressLength)
						{
							SMTPState = SMTP_RCPTTOBCC;
							break;
						}
					}
					if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC)
					{
						ROMStrPtr = FindROMEmailAddress(SMTPClient.BCC.szROM, &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
					if(SMTPClient.ROMPointers.BCC)
						ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength);
					else
						RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength);

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

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

				case SMTP_DATA:
					TCPPutROMString(MySocket, (ROM BYTE*)"DATA\r\n");
					SMTPState++;
					PutHeadersState = PUTHEADERS_FROM_INIT;
					TCPFlush(MySocket);
					break;

				case SMTP_DATA_HEADER:
					while((PutHeadersState != PUTHEADERS_DONE) && (TCPIsPutReady(MySocket) > 64u))
					{
						switch(PutHeadersState)
						{
							case PUTHEADERS_FROM_INIT:
								if(SMTPClient.From.szRAM || SMTPClient.From.szROM)
								{
									PutHeadersState = PUTHEADERS_FROM;
									TCPPutROMString(MySocket, (ROM BYTE*)"From: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_TO_INIT;
								}
								break;
								
							case PUTHEADERS_FROM:
								if(SMTPClient.ROMPointers.From)
								{
									SMTPClient.From.szROM = TCPPutROMString(MySocket, SMTPClient.From.szROM);
									if(*SMTPClient.From.szROM == 0u)
										PutHeadersState = PUTHEADERS_TO_INIT;
								}
								else
								{
									SMTPClient.From.szRAM = TCPPutString(MySocket, SMTPClient.From.szRAM);
									if(*SMTPClient.From.szRAM == 0u)
										PutHeadersState = PUTHEADERS_TO_INIT;
								}
								break;

							case PUTHEADERS_TO_INIT:
								if(SMTPClient.To.szRAM || SMTPClient.To.szROM)
								{
									PutHeadersState = PUTHEADERS_TO;
									TCPPutROMString(MySocket, (ROM BYTE*)"\r\nTo: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_CC_INIT;
								}
								break;
								
							case PUTHEADERS_TO:
								if(SMTPClient.ROMPointers.To)
								{
									SMTPClient.To.szROM = TCPPutROMString(MySocket, SMTPClient.To.szROM);
									if(*SMTPClient.To.szROM == 0u)
										PutHeadersState = PUTHEADERS_CC_INIT;
								}
								else
								{
									SMTPClient.To.szRAM = TCPPutString(MySocket, SMTPClient.To.szRAM);
									if(*SMTPClient.To.szRAM == 0u)
										PutHeadersState = PUTHEADERS_CC_INIT;
								}
								break;

							case PUTHEADERS_CC_INIT:
								if(SMTPClient.CC.szRAM || SMTPClient.CC.szROM)
								{
									PutHeadersState = PUTHEADERS_CC;
									TCPPutROMString(MySocket, (ROM BYTE*)"\r\nCC: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_SUBJECT_INIT;
								}
								break;
								
							case PUTHEADERS_CC:
								if(SMTPClient.ROMPointers.CC)
								{
									SMTPClient.CC.szROM = TCPPutROMString(MySocket, SMTPClient.CC.szROM);
									if(*SMTPClient.CC.szROM == 0u)
										PutHeadersState = PUTHEADERS_SUBJECT_INIT;
								}
								else
								{
									SMTPClient.CC.szRAM = TCPPutString(MySocket, SMTPClient.CC.szRAM);
									if(*SMTPClient.CC.szRAM == 0u)
										PutHeadersState = PUTHEADERS_SUBJECT_INIT;
								}
								break;

							case PUTHEADERS_SUBJECT_INIT:
								if(SMTPClient.Subject.szRAM || SMTPClient.Subject.szROM)
								{
									PutHeadersState = PUTHEADERS_SUBJECT;
									TCPPutROMString(MySocket, (ROM BYTE*)"\r\nSubject: ");
								}
								else
								{
									PutHeadersState = PUTHEADERS_OTHER_INIT;
								}
								break;
								
							case PUTHEADERS_SUBJECT:
								if(SMTPClient.ROMPointers.Subject)
								{
									SMTPClient.Subject.szROM = TCPPutROMString(MySocket, SMTPClient.Subject.szROM);
									if(*SMTPClient.Subject.szROM == 0u)
										PutHeadersState = PUTHEADERS_OTHER_INIT;
								}
								else
								{
									SMTPClient.Subject.szRAM = TCPPutString(MySocket, SMTPClient.Subject.szRAM);
									if(*SMTPClient.Subject.szRAM == 0u)
										PutHeadersState = PUTHEADERS_OTHER_INIT;
								}
								break;

							case PUTHEADERS_OTHER_INIT:
								TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2);
								if(SMTPClient.OtherHeaders.szRAM || SMTPClient.OtherHeaders.szROM)
								{
									PutHeadersState = PUTHEADERS_OTHER;
								}
								else
								{
									TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2);
									PutHeadersState = PUTHEADERS_DONE;
									SMTPState++;
								}
								break;
								
							case PUTHEADERS_OTHER:
								if(SMTPClient.ROMPointers.OtherHeaders)
								{
									SMTPClient.OtherHeaders.szROM = TCPPutROMString(MySocket, SMTPClient.OtherHeaders.szROM);
									if(*SMTPClient.OtherHeaders.szROM == 0u)
									{
										TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2);
										PutHeadersState = PUTHEADERS_DONE;
										SMTPState++;
									}
								}
								else
								{
									SMTPClient.OtherHeaders.szRAM = TCPPutString(MySocket, SMTPClient.OtherHeaders.szRAM);
									if(*SMTPClient.OtherHeaders.szRAM == 0u)
									{
										TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2);
										PutHeadersState = PUTHEADERS_DONE;
										SMTPState++;
									}
								}
								break;
							
							// Default case needed to supress compiler diagnostics
							default:
								break;
						}
					}
					TCPFlush(MySocket);
					break;
		
				case SMTP_DATA_BODY_INIT:
					SMTPState++;
					RAMStrPtr = SMTPClient.Body.szRAM;
					ROMStrPtr2 = (ROM BYTE*)"\r\n.\r\n";
					CRPeriod.Pos = NULL;
					if(RAMStrPtr)
						CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM char*)"\r\n.");
					// No break here
		
				case SMTP_DATA_BODY:
					if(SMTPClient.Body.szRAM || SMTPClient.Body.szROM)
					{
						if(*ROMStrPtr2)
						{
							// Put the application data, doing the transparancy replacement of "\r\n." with "\r\n.."
							while(CRPeriod.Pos)
							{
								CRPeriod.Pos += 3;
								RAMStrPtr += TCPPutArray(MySocket, RAMStrPtr, CRPeriod.Pos-RAMStrPtr);
								if(RAMStrPtr == CRPeriod.Pos)
								{
									if(!TCPPut(MySocket, '.'))
									{
										CRPeriod.Pos -= 3;
										break;
									}
								}
								else
								{
									CRPeriod.Pos -= 3;
									break;
								}
								CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM 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 = TCPPutString(MySocket, RAMStrPtr);
							ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2);
							TCPFlush(MySocket);
						}
					}
					else
					{
						if(SMTPFlags.bits.ReadyToFinish)
						{
							if(*ROMStrPtr2)
							{
								ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2);
								TCPFlush(MySocket);
							}
		
						}
					}

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

				case SMTP_QUIT:
					if(*ROMStrPtr)
					{
						ROMStrPtr = TCPPutROMString(MySocket, ROMStrPtr);
						TCPFlush(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
			TCPDisconnect(MySocket);
			MySocket = INVALID_SOCKET;

			// Go back to doing nothing
			TransportState = TRANSPORT_HOME;
			break;
	}
}
Ejemplo n.º 26
0
/*****************************************************************************
  Function:
	void GenericTCPServer(void)

  Summary:
	Implements a simple ToUpper TCP Server.

  Description:
	This function implements a simple TCP server.  The function is invoked
	periodically by the stack to listen for incoming connections.  When a 
	connection is made, the server reads all incoming data, transforms it
	to uppercase, and echos it back.
	
	This example can be used as a model for many TCP server applications.

  Precondition:
	TCP is initialized.

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
void GenericTCPServer(void)
{
	BYTE i,j;
	WORD w, w2;
	BYTE AppBuffer[32];
	WORD wMaxGet, wMaxPut, wCurrentChunk;
	static TCP_SOCKET	MySocket;
	static enum _TCPServerState
	{
		SM_HOME = 0,
		SM_LISTENING,
        SM_CLOSING,
	} TCPServerState = SM_HOME;

	switch(TCPServerState)
	{
		case SM_HOME:
			// Allocate a socket for this server to listen and accept connections on
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER);
			if(MySocket == INVALID_SOCKET)
				return;
			tcptxbuffer[0]=0;tcptxbufferpoint=0;

			TCPServerState = SM_LISTENING;
			break;

		case SM_LISTENING:
			// See if anyone is connected to us
			if(!TCPIsConnected(MySocket))
			{
				setspeed(0,0);
				LED0_IO=1; LED1_IO=0;
				return;
			}

			// Figure out how many bytes have been received and how many we can transmit.
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO free space

			// Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO
//			if(wMaxPut < wMaxGet)
//				wMaxGet = wMaxPut;

			// Process all bytes that we can
			// This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time.  
			// This limits memory usage while maximizing performance.  Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays.
			wCurrentChunk = sizeof(AppBuffer);
			if (!wMaxGet)
				{
					w=tcptxbufferpoint;
					if (w>wMaxPut)
                        {
                          w=wMaxPut;
                        }
					if (w)
						{
						TCPPutArray(MySocket,  (BYTE*)&tcptxbuffer[0], w);
						if (tcptxbufferpoint!=w)
							{
		                        tcptxbufferpoint-=w;
								memcpy((BYTE*)&tcptxbuffer[0],(BYTE*)&tcptxbuffer[w],tcptxbufferpoint);
							}
							else   tcptxbufferpoint=0;

						}
				}
			for(w = 0; w < wMaxGet; w += sizeof(AppBuffer))
			{
				// Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly.
				if(w + sizeof(AppBuffer) > wMaxGet)
					wCurrentChunk = wMaxGet - w;

				// Transfer the data out of the TCP RX FIFO and into our local processing buffer.
				TCPGetArray(MySocket, AppBuffer, wCurrentChunk);
				
				j=0;
				for(w2 = 0; w2 < wCurrentChunk; w2++)
				{
					i = AppBuffer[w2];
					putcomsdata(i);
				}
				
				// Transfer the data out of our local processing buffer and into the TCP TX FIFO.
//				TCPPutArray(MySocket, AppBuffer, wCurrentChunk);
			}
TCPFlush(MySocket);

			// No need to perform any flush.  TCP data in TX FIFO will automatically transmit itself after it accumulates for a while.  If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API.

			break;

		case SM_CLOSING:
			// Close the socket connection.
            TCPClose(MySocket);

			TCPServerState = SM_HOME;
			break;
	}
}