Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

/opentcp/pop3/pop3_client.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053 
00068 #include<inet/debug.h>
00069 #include<inet/datatypes.h>
00070 #include<inet/globalvariables.h>
00071 #include<inet/system.h>
00072 #include<inet/timers.h>
00073 #include<inet/tcp_ip.h>
00074 #include<inet/pop3/pop3_client.h>
00075 
00076 
00077 UINT8 pop3c_init_done = 0; 
00085 struct pop3c_struct pop3_client; 
00086 
00087 
00088 /* The applications that use TCP must implement following function stubs                        */
00089 /* void application_name_init (void) - call once when processor starts                          */
00090 /* void application_name_run (void) - call periodically on main loop                            */
00091 /* INT32 application_name_eventlistener (INT8, UINT8, UINT32, UINT32)                           */
00092 /* - called by TCP input process to inform arriving data, errors etc                            */
00093 
00094 
00095 /* POP3 Client application              */
00096 
00097 
00114 INT8 pop3c_connect (UINT32 ip, UINT16 port){
00115         /* Do we have socket    */
00116 
00117         if( pop3_client.sochandle < 0 ) {
00118                 DEBUGOUT("pop3c_connect() called but no socket\r\n");
00119                 return(-1);
00120         }
00121         
00122         if( pop3_client.state < POP3C_CLOSED ) {
00123                 DEBUGOUT("pop3c_connect() called but uninitialized\r\n");
00124                 return(-1);
00125         }
00126         
00127         if( pop3_client.state == POP3C_CLOSED ) {
00128                 DEBUGOUT("POP3 Connection request going to be processed\r\n");
00129                 pop3_client.remip = ip;
00130                 pop3_client.remport = port;
00131                 pop3c_changestate(POP3C_OPEN_REQUESTED);
00132                 return(1);
00133         }
00134         
00135         return(-1);     
00136         
00137 }
00138 
00148 void pop3c_init (void){
00149         
00150         if(pop3c_init_done) {
00151                 DEBUGOUT("POP3 client already initialized\r\n");
00152                 return;
00153         }
00154         
00155         
00156         /* Get timer handle     */
00157         
00158         pop3_client.tmrhandle = get_timer();
00159         
00160         /* Get TCP Socket       */
00161         
00162         pop3_client.sochandle = tcp_getsocket(TCP_TYPE_CLIENT, TCP_TOS_NORMAL, TCP_DEF_TOUT, pop3c_eventlistener);
00163         
00164         if( pop3_client.sochandle < 0 ) {
00165                 DEBUGOUT("pop3c_init() uncapable of getting socket\r\n");
00166                 RESET_SYSTEM();
00167         }       
00168         
00169         pop3c_changestate(POP3C_CLOSED);        
00170         pop3_client.remip = 0;
00171         pop3_client.remport = 0;
00172         pop3_client.unacked = 0;
00173         pop3_client.msgtotal = 0;
00174         pop3_client.curmsgindex = 0;
00175         pop3_client.curmsgtotlen = 0;
00176         pop3_client.curmsghlen = 0;
00177         pop3_client.headerbuf[0] = '\0';
00178         pop3_client.charsinheaderbuf = 0;
00179         pop3_client.from[0] = '\0';
00180         pop3_client.subject[0] = '\0';
00181         
00182         pop3c_init_done = 0x01;                         /* We are initialized now       */
00183 
00184 }
00194 UINT8 pop3c_getstate (void){
00195         return(pop3_client.state);
00196         
00197 }
00198 
00199 /********************************************************************************
00200 Function:               pop3c_eventlistener
00201 
00202 Parameters:             INT8 cbhandle - handle to TCP socket where event is coming from 
00203                                 UINT8 event - type of event
00204                                 UINT32 par1 - parameter the meaning of depends on event
00205                                 UINT32 par2 - parameter the meaning of depends on event
00206                                 
00207 Return val:             INT32 - depends on event but usually (-1) is error of some
00208                                                 kind and positive reply means OK
00209                                 
00210 Date:                   21.8.2002
00211 
00212 Desc:                   This function is given to TCP socket as function pointer to be
00213                                 used by TCP engine to make callbacks to inform about events
00214                                 on TCP e.g. arriving data. Main functionality of this function 
00215                                 is to parse data from TCP to detect POP3 server reply commands,
00216                                 handling out retransmissions and making state changes
00217 *********************************************************************************/
00218 
00219 
00220 INT32 pop3c_eventlistener (INT8 cbhandle, UINT8 event, UINT32 par1, UINT32 par2)
00221 {
00222         /* This function is called by TCP stack to inform about events  */
00223         
00224         UINT8 cmd;
00225         UINT16 i;
00226         static UINT16 len;
00227         static UINT16 match;
00228         static UINT8  end_detect;
00229         UINT8 ch;
00230         UINT8 j;
00231         UINT8 endbuf[4];
00232                 
00233         
00234         if( cbhandle != pop3_client.sochandle)          /* Not our handle       */
00235                 return(-1);
00236         
00237         switch( event ) {
00238         
00239                 case TCP_EVENT_CONREQ:
00240                 
00241                         /* We don't allow incoming connections  */
00242                         
00243                         return(-1);
00244         
00245                 case TCP_EVENT_ABORT:
00246                 
00247                         if(pop3_client.state > POP3C_CLOSED) {
00248                                 /* Inform application   */      
00249                                 pop3c_error();  
00250                         }
00251                 
00252                         pop3c_changestate(POP3C_CLOSED);
00253                         pop3_client.unacked = 0;
00254                         
00255                         return(1);
00256                 
00257                         break;
00258                 
00259                 case TCP_EVENT_CONNECTED:
00260                 
00261                         if(pop3_client.state == POP3C_CONNECTIONOPEN_SENT) {
00262                                 DEBUGOUT("POP3 TCP connection opened\r\n");
00263                                 pop3c_changestate(POP3C_CONNECTION_OPENED);
00264                                 pop3_client.unacked = 0;
00265                                 return(-1);
00266                         }
00267                                 
00268                         break;
00269                         
00270                 case TCP_EVENT_CLOSE:
00271                 
00272                         pop3c_changestate(POP3C_CLOSED);
00273                         pop3_client.unacked = 0;
00274                         return(1);
00275                 
00276                         break;
00277                         
00278                 case TCP_EVENT_ACK:
00279                 
00280                         /* Our message is acked */
00281                         
00282                         pop3_client.unacked = 0;
00283                         
00284                         break;
00285                         
00286                 case TCP_EVENT_DATA:
00287                 
00288                         /* Do we have unacked data?     */
00289                         
00290                         if(pop3_client.unacked)
00291                                 return(-1);
00292                 
00293                         /* Get reply from server        */
00294                         
00295                         if(par1 < 3)                                    /* Long enough? */
00296                                 return(-1);
00297                 
00298                         /* Get command                          */
00299                         
00300                         NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
00301                         cmd = RECEIVE_NETWORK_B();
00302                         NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
00303 
00304                         switch(pop3_client.state) {
00305                                 
00306                                 case POP3C_CONNECTION_OPENED:
00307                                 
00308                                         if(cmd == POP3C_OK)     {
00309                                                 DEBUGOUT("POP3 Server is ready\r\n");
00310                                                 pop3c_changestate(POP3C_SERVER_READY);
00311                                                 return(1);
00312                                         }
00313                                         
00314                                         break;
00315                                 
00316                                 case POP3C_USERNAME_SENT:
00317                                 
00318                                         if(cmd == POP3C_OK)     {       
00319                                                 DEBUGOUT("USER +OK by POP3 server\r\n");
00320                                                 pop3c_changestate(POP3C_USERNAME_ACKED);
00321                                                 return(1);
00322                                         }
00323                                         
00324                                         break;                          
00325                                         
00326                                 case POP3C_PASSWORD_SENT:
00327                                 
00328                                         if(cmd == POP3C_OK) {
00329                                                 DEBUGOUT("PASS +OK by POP3 server\r\n");
00330                                                 pop3c_changestate(POP3C_PASSWORD_ACKED);
00331                                                 return(1);
00332                                         }
00333                                         
00334                                         break;                  
00335                                         
00336                                 case POP3C_STAT_SENT: 
00337                                 
00338                                         if(cmd == POP3C_OK)     {
00339                                                 DEBUGOUT("STAT get from POP3 server\r\n");
00340                                                 
00341                                                 /* Parse number of messages     */
00342                                                 
00343                                                 NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
00344                                                         
00345                                                 pop3_client.msgtotal = 0;
00346                                                 pop3_client.curmsgindex = 0;
00347                                                 pop3_client.curmsgtotlen = 0;
00348                                                 pop3_client.curmsghlen = 0;
00349                                                 if( pop3c_parsestat() < 0 )     {
00350                                                         /* Error parsing STAT reply     */
00351                                                         /* Inform application           */      
00352                                                         pop3c_error();                                                  
00353                                                         tcp_abort(pop3_client.sochandle);
00354                                                         pop3c_changestate(POP3C_CLOSED);
00355                                                         pop3_client.unacked = 0;                                                        
00356                                                         return(1);
00357                                                 }
00358                                                 
00359                                                 /* Inform application about the nmbr of messages        */
00360                                                 pop3c_messages(pop3_client.msgtotal);
00361                                                 
00362                                                 pop3c_changestate(POP3C_STAT_GET);
00363                                                 return(1);
00364                                         }
00365                                         
00366                                         break;  
00367                                         
00368                                 case POP3C_LIST_SENT:
00369                                 
00370                                         if(cmd == POP3C_OK)     {
00371                                                 DEBUGOUT("LIST get from POP3 server\r\n");
00372                                                 
00373                                                 /* Parse message total len      */
00374                                                 
00375                                                 NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);      
00376                                                 
00377                                                 pop3_client.curmsgtotlen = 0;
00378                                                 
00379                                                 if(pop3c_parselist() < 0) {
00380                                                         /* Error parsing LIST reply     */
00381                                                         /* Inform application           */      
00382                                                         pop3c_error();                                                  
00383                                                         tcp_abort(pop3_client.sochandle);
00384                                                         pop3c_changestate(POP3C_CLOSED);
00385                                                         pop3_client.unacked = 0;                                                        
00386                                                         return(1);                                              
00387                                                 
00388                                                 }
00389                                                 
00390                                                 
00391                                                 pop3c_changestate(POP3C_LIST_GET);
00392                                                 return(1);
00393                                         }
00394                                         
00395                                         break;                                                                          
00396                                 
00397                                 case POP3C_TOP0_SENT:
00398                                 
00399                                         if(cmd == POP3C_OK) {
00400                                                 DEBUGOUT("TOP x 0 get from POP3 server\r\n");
00401                                                 
00402                                                 /* Continue imediately to receive header        */
00403                                                 pop3_client.curmsghlen = 0;
00404                                                 pop3_client.from[0] = '\0';
00405                                                 pop3_client.subject[0] = '\0';
00406                                                 match = 0;
00407                                                 
00408                                                 /* Receive untill LF found      */
00409                                         
00410                                                 for(i=0; i<(UINT16)par1; i++)
00411                                                 {
00412                                                         ch = RECEIVE_NETWORK_B();
00413                                                 
00414                                                         if(ch == '\n')
00415                                                         {       i++;
00416                                                                 break;
00417                                                         }
00418                                                 }
00419                                 
00420                                                 par1 = i;                                               
00421                                                 
00422                                                 
00423                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);      
00424                                         }else
00425                                                 break;
00426                                         
00427                                 case POP3C_RECEIVING_HEADER:
00428                                 case POP3C_RECEIVING_HDR_FROM:
00429                                 case POP3C_RECEIVING_HDR_SUBJ:
00430                                 
00431                                         pop3_client.curmsghlen += (UINT16)par1;
00432                                         
00433                                         if( pop3_client.curmsghlen > (pop3_client.curmsgtotlen + 100) ) {
00434                                                 /* Somebody tries to fool us    */
00435                                                 /* Move to next msg                             */
00436                                                 
00437                                                 pop3c_changestate(POP3C_MESSAGE_RECEIVED);
00438                                                 break;  
00439                                                 
00440                                         }
00441                                         
00442                                         /* We try to find 'from:', or 'subject:'        */
00443                                         
00444                                         NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
00445                                         
00446                                         for( i=0; i<(UINT16)par1; i++) {
00447                                                 
00448                                                 ch = RECEIVE_NETWORK_B();
00449                                                 
00450                                                 if( pop3_client.state == POP3C_RECEIVING_HEADER) {
00451                                                 
00452                                                         if( ch == '\r') {
00453                                                                 pop3_client.charsinheaderbuf = 0;
00454                                                                 continue;
00455                                                         }
00456                                                 
00457                                                         if( ch == '\n') {
00458                                                                 pop3_client.charsinheaderbuf = 0;
00459                                                                 continue;
00460                                                         }
00461                                                 
00462                                                         if( ch == ' ')          /* Remove spaces        */
00463                                                                 continue;
00464                                         
00465                                                         /* Buffer already full for this line?   */
00466                                         
00467                                                         if(pop3_client.charsinheaderbuf > 8)
00468                                                                 continue;
00469                                         
00470                                                         /* End of header? (parsing of that is not absolutely correct)   */
00471                                                         /* We detect it from CRLF. or LFCR. or CR. or LF.                               */
00472                                                         /* the correct indication being CRLF.CRLF                                               */
00473                                                         
00474                                                         if( (ch == '.') && (pop3_client.charsinheaderbuf == 0) ) {
00475                                                                 /* Remove CRLF.CRLF from header length  */
00476                                                                 
00477                                                                 if( pop3_client.curmsghlen >= 5 )
00478                                                                         pop3_client.curmsghlen -= 5;
00479                                                                 
00480                                                                 pop3c_changestate(POP3C_TOP0_GET);
00481                                                                 break;
00482                                                         }
00483                                         
00484                                         
00485                                                         ch = tolower(ch);
00486                                                 
00487                                                         pop3_client.headerbuf[pop3_client.charsinheaderbuf] = ch;
00488                                                         pop3_client.charsinheaderbuf++;
00489                                                         pop3_client.headerbuf[pop3_client.charsinheaderbuf] = '\0';
00490                                                 
00491                                                         /* Is it 'from:' ?      */
00492                                                 
00493                                                         if(bufsearch(&pop3_client.headerbuf[0],pop3_client.charsinheaderbuf,"from:") == 0) {
00494                                                                 /* Continue imidiately to read sender   */
00495                                                         
00496                                                                 pop3_client.from[0] = '\0';
00497                                                                 pop3_client.charsinheaderbuf = 0;
00498                                                                 pop3c_changestate(POP3C_RECEIVING_HDR_FROM);    
00499                                                                 continue;
00500                                                         }
00501                                                 
00502                                                         /* Is it 'subject:' ?   */
00503                                                 
00504                                                         if(bufsearch(&pop3_client.headerbuf[0],pop3_client.charsinheaderbuf,"subject:") == 0) {
00505                                                                 /* Continue imidiately to read subject  */
00506                                                                         
00507                                                                 pop3_client.subject[0] = '\0';
00508                                                                 pop3_client.charsinheaderbuf = 0;
00509                                                                 pop3c_changestate(POP3C_RECEIVING_HDR_SUBJ);    
00510                                                                 continue;
00511                                                         }
00512                                                 
00513                                                 }       /* of RECEIVING_HEADER  */
00514                                                 
00515                                                 
00516                                                 if( pop3_client.state == POP3C_RECEIVING_HDR_FROM) {
00517                                                         if( ch == ' '){         /* Remove spaces        */
00518                                                                 if(pop3_client.charsinheaderbuf == 0)
00519                                                                         continue;
00520                                                         }
00521                                                         
00522                                                         if( ch == '\r') {
00523                                                                 pop3_client.charsinheaderbuf = 0;
00524                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00525                                                                 continue;
00526                                                         }
00527                                                         
00528                                                         if( ch == '\n') {
00529                                                                 pop3_client.charsinheaderbuf = 0;
00530                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00531                                                                 continue;
00532                                                         }
00533                                                         
00534                                                         /* Store it     */
00535                                                         
00536                                                         pop3_client.from[pop3_client.charsinheaderbuf] = ch;
00537                                                         pop3_client.charsinheaderbuf++;
00538                                                         pop3_client.from[pop3_client.charsinheaderbuf] = '\0';
00539                                                         
00540                                                         if(pop3_client.charsinheaderbuf >= POP3C_SENDERMAXLEN) {
00541                                                                 /* The buffer is exeeded        */
00542                                                                 /* Mark it corrupted            */
00543                                                                 
00544                                                                 pop3_client.from[0] = '\0';
00545                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00546                                                                 continue;
00547                                                         }       
00548                                                                                                 
00549                                                 }       /* of RECEIVING_HDR_FROM        */
00550                                                 
00551                                                 
00552                                                 if( pop3_client.state == POP3C_RECEIVING_HDR_SUBJ) {
00553                                                         if( ch == ' '){         /* Remove spaces        */
00554                                                                 if(pop3_client.charsinheaderbuf == 0)
00555                                                                         continue;
00556                                                         }
00557                                                         
00558                                                         if( ch == '\r') {
00559                                                                 pop3_client.charsinheaderbuf = 0;
00560                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00561                                                                 continue;
00562                                                         }
00563                                                         
00564                                                         if( ch == '\n') {
00565                                                                 pop3_client.charsinheaderbuf = 0;
00566                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00567                                                                 continue;
00568                                                         }
00569                                                         
00570                                                         /* Store it     */
00571                                                         
00572                                                         pop3_client.subject[pop3_client.charsinheaderbuf] = ch;
00573                                                         pop3_client.charsinheaderbuf++;
00574                                                         pop3_client.subject[pop3_client.charsinheaderbuf] = '\0';
00575                                                         
00576                                                         if(pop3_client.charsinheaderbuf >= POP3C_SUBJECTMAXLEN) {
00577                                                                 /* The buffer is exeeded        */
00578                                                                 /* Mark it corrupted            */
00579                                                                 
00580                                                                 pop3_client.subject[0] = '\0';
00581                                                                 pop3c_changestate(POP3C_RECEIVING_HEADER);
00582                                                                 continue;
00583                                                         }       
00584                                                                                                 
00585                                                 }       /* of RECEIVING_HDR_SUBJ        */                                              
00586                                                 
00587                                         
00588                                         }
00589                                         
00590 
00591                                         break;
00592                                                                                         
00593                                         
00594                                 case POP3C_RETR_SENT:
00595                                 
00596                                         if(cmd == POP3C_OK)     {
00597                                                 DEBUGOUT("RETR +OK by POP3 server\r\n");
00598                                                 
00599                                                 /* Continue imidiately to receive message       */
00600                                                 
00601                                                 pop3c_changestate(POP3C_RECEIVING_MSG_HEADER);
00602                                         
00603                                         } else
00604                                                 break;
00605                                                 
00606                                 case POP3C_RECEIVING_MSG_HEADER:        
00607                                 
00608                                         /* Try to find empty row to detect the start of actual message  */
00609                                         
00610                                         match = 0;
00611                                         NETWORK_RECEIVE_INITIALIZE(received_tcp_packet.buf_index);
00612                                         
00613                                         for(i=0; i < (UINT16)par1; i++) {                                       
00614                                                 ch = RECEIVE_NETWORK_B();
00615                                                 
00616                                                 if(match == 0)  {
00617                                                         if( (ch == '\r') || (ch == '\n') )
00618                                                                 match++;
00619                                                         else
00620                                                                 match = 0;
00621                                                         continue;       
00622                                                 }
00623 
00624                                                 if(match == 1) {
00625                                                         if( (ch == '\r') || (ch == '\n'))
00626                                                                 match++;
00627                                                         else
00628                                                                 match = 0;
00629                                                         continue;       
00630                                                 }                                               
00631                                                 
00632                                                 if(match == 2) {
00633                                                         if( (ch == '\r') || (ch == '\n'))
00634                                                                 match++;
00635                                                         else
00636                                                                 match = 0;
00637                                                         continue;       
00638                                                 }                       
00639                                                 
00640                                                 if(match == 3) {
00641                                                         if( (ch == '\r') || (ch == '\n')) {
00642                                                                 match++;
00643                                                                 
00644                                                                 /* Continue to read the actual msg      */
00645                                                                 par1 -= (i + 1);
00646                                                                 pop3c_changestate(POP3C_RECEIVING_MSG);
00647                                                                 break;
00648                                                         } else
00649                                                                 match = 0;
00650                                                         continue;       
00651                                                 }                                               
00652                                                                         
00653                                         }
00654                                         
00655                                         /* If we don't find the end of header we will timeout   */
00656                                         /* on pop3c_run so no error handling here                               */
00657                                 
00658                                         if( pop3_client.state != POP3C_RECEIVING_MSG)
00659                                                 break;
00660                                         
00661                                         end_detect = 0; 
00662                                         case POP3C_RECEIVING_MSG:
00663                                         
00664                                                 /* Search is this packet end of msg and do not give     */
00665                                                 /* CRLF.CRLF to application                                                     */
00666                                                 for(i=0; i < (UINT16)par1; i++) {
00667                                                         ch = RECEIVE_NETWORK_B();
00668                                                         
00669                                                         pop3c_data(ch);
00670                                                         
00671                                                         if( (ch == '\r') && (end_detect != 3))
00672                                                                 end_detect = 0;
00673                                                         
00674                                                         
00675                                                         if( end_detect == 0 ) {
00676                                                                 if(ch == '\r')
00677                                                                         end_detect++;
00678                                                                 else
00679                                                                         end_detect = 0;
00680                                                                 
00681                                                                 continue;
00682                                                         }
00683                                                         
00684                                                         if( end_detect == 1 ){
00685                                                                 if(ch == '\n')
00686                                                                         end_detect++;
00687                                                                 else
00688                                                                         end_detect = 0;
00689                                                                 
00690                                                                 continue;
00691                                                         }                                                       
00692                                                         
00693                                                         if( end_detect == 2 ){
00694                                                                 if(ch == '.')
00695                                                                         end_detect++;
00696                                                                 else
00697                                                                         end_detect = 0;
00698                                                                 
00699                                                                 continue;
00700                                                         }       
00701                                                         
00702                                                         if( end_detect == 3 ){
00703                                                                 if(ch == '\r')
00704                                                                         end_detect++;
00705                                                                 else
00706                                                                         end_detect = 0;
00707                                                                 
00708                                                                 continue;
00709                                                         }                                                                                                       
00710                                                         
00711                                                         if( end_detect == 4 ){  
00712                                                                 if(ch == '\n') {                                                                                                        
00713                                                                         pop3c_changestate(POP3C_MESSAGE_RECEIVED);
00714                                                                         return(1);
00715                                                                 }
00716                                                                 else
00717                                                                         end_detect = 0;
00718                                                                 
00719                                                                 continue;
00720                                                         }
00721                                                 
00722                                                 }
00723                                                 
00724                                                 break;
00725                                                 
00726                                         case POP3C_DELE_SENT:
00727                                         
00728                                                 if(cmd == POP3C_OK)     {
00729                                                         DEBUGOUT("DELE +OK by POP3 server\r\n");
00730                                                         pop3c_changestate(POP3C_DELE_ACKED);
00731                                                         return(1);
00732                                                 }
00733                                         
00734                                                 break;  
00735                                                 
00736                                         case POP3C_QUIT_SENT:
00737                                         
00738                                                 if(cmd == POP3C_OK)     {
00739                                                         DEBUGOUT("QUIT +OK by POP3 server\r\n");
00740                                                         pop3c_changestate(POP3C_QUIT_ACKED);
00741                                                         return(1);
00742                                                 }
00743                                         
00744                                                 break;                                                                          
00745                                         
00746                                                 
00747                                 default:
00748                                         break;
00749 
00750                         
00751                         }
00752 
00753                 
00754                         return(1);
00755                 
00756                         
00757                 case TCP_EVENT_REGENERATE:
00758                 
00759                         /* Send last packet again       */
00760                 
00761                         DEBUGOUT("POP3C is regenerating...\r\n");
00762                 
00763                         switch (pop3_client.state) {
00764                         
00765                                 case POP3C_USERNAME_SENT:
00766                                         pop3c_senduser();
00767                                         return(1);
00768                                 
00769                                 case POP3C_PASSWORD_SENT:
00770                                         pop3c_sendpassword();
00771                                         return(1);
00772                                         
00773                                 case POP3C_STAT_SENT:
00774                                         pop3c_sendstat();
00775                                         return(1);
00776                                 
00777                                 case POP3C_LIST_SENT:
00778                                         pop3c_sendlist(pop3_client.curmsgindex);
00779                                         return(1);
00780                                 
00781                                 case POP3C_TOP0_SENT:
00782                                         pop3c_sendtop(0);
00783                                         return(1);      
00784                                 
00785                                 case POP3C_RETR_SENT:
00786                                         pop3c_sendretr(pop3_client.curmsgindex);
00787                                         return(1);
00788                                 
00789                                 case POP3C_DELE_SENT:   
00790                                         pop3c_senddele(pop3_client.curmsgindex);
00791                                         return(1);
00792                                 
00793                                 case POP3C_QUIT_SENT:
00794                                         pop3c_sendquit();
00795                                         return(1);
00796                                         
00797                                 default:
00798                                         return(-1);
00799                         }
00800                 
00801                 
00802                         break;
00803         
00804         
00805                 default:
00806                         return(-1);
00807         }       
00808 
00809         return(-1);
00810 
00811 }
00812 
00813 
00814 /********************************************************************************
00815 Function:               pop3c_run
00816 
00817 Parameters:             void            
00818                                 
00819 Return val:             void
00820                                 
00821 Date:                   11.9.2002
00822 
00823 Desc:                   This function should be called periodically from main loop
00824                                 in order to run pop3 client 'thread'.
00825 *********************************************************************************/
00826 
00827 void pop3c_run (void)
00828 {
00829         INT16 i;
00830 
00831         /* On that function we can send data when called by main loop   */
00832         
00833         if( pop3c_init_done == 0 )
00834                 return;
00835         
00836         if( pop3_client.state < POP3C_OPEN_REQUESTED)
00837                 return;
00838                 
00839         /* Is there timeout of some sort?       */
00840                 
00841         if(check_timer(pop3_client.tmrhandle) == 0) {
00842                 /* Yep  */
00843                 tcp_abort(pop3_client.sochandle);
00844                 pop3c_changestate(POP3C_CLOSED);
00845                         
00846                 /* Make user callback   */
00847                 pop3c_error();
00848                 return;
00849                 
00850         }
00851         
00852         if( pop3_client.state == POP3C_OPEN_REQUESTED) {
00853                 /* We are on this state because user has requested connection   */
00854                 /* but connection is not yet opened.                                                    */
00855                 /* Try to get TCP stack to accept our connection request                */
00856                 
00857                 tcp_abort(pop3_client.sochandle);               /* Release old connection       */
00858                 if(tcp_connect(pop3_client.sochandle, pop3_client.remip, pop3_client.remport, 0) >= 0)
00859                         pop3c_changestate(POP3C_CONNECTIONOPEN_SENT);
00860                 
00861                 return;
00862         }
00863         
00864         if( tcp_getstate(pop3_client.sochandle) != TCP_STATE_CONNECTED ) {
00865                 return;
00866         }       
00867         
00868         if( tcp_checksend(pop3_client.sochandle) < 0 )
00869                 return;
00870         
00871         /* It's connected and no unacked data so try to send    */      
00872         
00873         if(pop3_client.state == POP3C_SERVER_READY) {
00874                 /* Send USER    */
00875                 pop3c_senduser();
00876                 pop3c_changestate(POP3C_USERNAME_SENT);
00877                 DEBUGOUT("POP3C USER packet sent\r\n");
00878                 return;
00879         }       
00880         
00881         if(pop3_client.state == POP3C_USERNAME_ACKED) {
00882                 /* Send PASS    */
00883                 pop3c_sendpassword();
00884                 pop3c_changestate(POP3C_PASSWORD_SENT);
00885                 DEBUGOUT("POP3C PASS packet sent\r\n");
00886                 return;
00887         }       
00888         
00889         if(pop3_client.state == POP3C_PASSWORD_ACKED) {
00890                 /* Send STAT    */
00891                 pop3c_sendstat();
00892                 pop3c_changestate(POP3C_STAT_SENT);
00893                 DEBUGOUT("POP3C STAT packet sent\r\n");
00894                 return;
00895         }
00896         
00897         if(pop3_client.state == POP3C_STAT_GET) {
00898                 /* Still messages?              */
00899                 if( pop3_client.curmsgindex < pop3_client.msgtotal ) {
00900                         pop3_client.curmsgindex++;
00901                         pop3c_sendlist(pop3_client.curmsgindex);
00902                         pop3c_changestate(POP3C_LIST_SENT);
00903                         DEBUGOUT("POP3C LIST packet sent\r\n");
00904                         return;
00905                 }
00906                 
00907                 /* End of messages      */
00908                 
00909                 pop3c_sendquit();
00910                 pop3c_changestate(POP3C_QUIT_SENT);
00911                 DEBUGOUT("POP3C QUIT packet sent\r\n");
00912                 return;         
00913                 
00914         }
00915         
00916         if(pop3_client.state == POP3C_LIST_GET) {
00917                 /* Now we have the whole length of current message. Receive body        */
00918                 
00919                 pop3c_sendtop(pop3_client.curmsgindex);
00920                 pop3c_changestate(POP3C_TOP0_SENT);
00921                 DEBUGOUT("POP3C TOP packet sent\r\n");
00922                 return;
00923         }
00924         
00925         if(pop3_client.state == POP3C_TOP0_GET) {
00926                 /* Offer the e-mail to sender   */
00927                 
00928                 if((pop3_client.curmsgtotlen + 100 )> pop3_client.curmsghlen) {
00929                         if(pop3_client.curmsgtotlen < pop3_client.curmsghlen)
00930                                 i = pop3c_msgoffer(pop3_client.curmsgindex, 0, &pop3_client.from[0], &pop3_client.subject[0]);
00931                         else
00932                                 i = pop3c_msgoffer(pop3_client.curmsgindex, pop3_client.curmsgtotlen - pop3_client.curmsghlen, &pop3_client.from[0], &pop3_client.subject[0]);
00933                         
00934                         if( i == (-2) ) {
00935                                 /* User want's the mail to be deleted directly  */
00936                                 
00937                                 pop3c_senddele(pop3_client.curmsgindex);
00938                                 pop3c_changestate(POP3C_DELE_SENT);
00939                                 DEBUGOUT("POP3C deleting the e-mail\r\n");
00940                                 return;
00941                         }
00942                         
00943                         if( i == (-1) ) {
00944                                 /* User want's the mail to be left on server without reading it */
00945                                 /* So goto next one                                                                                             */
00946                                 
00947                                 pop3c_changestate(POP3C_STAT_GET);
00948                                 return;
00949                         }
00950                         
00951                         if( i >= 0 ) {
00952                                 /* User wants to read and delete the mail normally      */
00953                                 
00954                                 pop3c_sendretr(pop3_client.curmsgindex);
00955                                 pop3c_changestate(POP3C_RETR_SENT);
00956                                 DEBUGOUT("POP3C reading the e-mail\r\n");
00957                                 return; 
00958                         
00959                         }
00960                         
00961                         return;         
00962                 }
00963                 
00964                 /* The mail is somehow corrupted, just delete it        */
00965                 
00966                 pop3c_senddele(pop3_client.curmsgindex);
00967                 pop3c_changestate(POP3C_DELE_SENT);
00968                 DEBUGOUT("POP3C deleting CORRUPTED e-mail\r\n");
00969                 return;
00970                 
00971         
00972         }
00973         
00974         
00975         if(pop3_client.state == POP3C_MESSAGE_RECEIVED) {
00976                 /* Delete the readed message    */
00977                 
00978                 pop3c_senddele(pop3_client.curmsgindex);
00979                 pop3c_changestate(POP3C_DELE_SENT);
00980                 DEBUGOUT("POP3C deleting readed e-mail\r\n");
00981                 return;
00982         }
00983         
00984         if(pop3_client.state == POP3C_DELE_ACKED) {
00985                 /* Goto next one        */
00986                 pop3c_changestate(POP3C_STAT_GET);
00987                 return;
00988         }
00989         
00990         if(pop3_client.state == POP3C_QUIT_ACKED) {     
00991         
00992                 /* Try to close TCP     */
00993                 
00994                 if(tcp_close(pop3_client.sochandle) >= 0) {
00995                         pop3c_changestate(POP3C_CLOSED);
00996                         pop3c_allok();
00997                         DEBUGOUT("POP3C connection closed OK\r\n");
00998                         return;
00999                 }
01000                 
01001                 /* Close is not accepted by TCP. See if timeout */
01002                 
01003                 if(check_timer(pop3_client.tmrhandle) == 0) {
01004                         /* Use brute force              */
01005                         
01006                         tcp_abort(pop3_client.sochandle);
01007                         pop3c_changestate(POP3C_CLOSED);
01008                         pop3c_allok();
01009                         DEBUGOUT("POP3C connection closed by ABORT\r\n");
01010                         return;
01011                 }
01012                 
01013                 /* Keep trying untill timeout   */
01014                 
01015                 return; 
01016                 
01017         }
01018         
01019         return;
01020         
01021 }
01022 
01023 
01024 
01025 
01026 void pop3c_senduser (void)
01027 {
01028         INT8 i;
01029         UINT8* buf;
01030 
01031         /* Fill TCP Tx buffer with "USER " and use callback function    */
01032         /* pop3c_getusername in order to get the username                               */
01033         /* that combined "USER username" to POP3 server                                 */
01034         
01035         buf = &net_buf[TCP_APP_OFFSET];
01036         
01037         *buf++ = 'U';
01038         *buf++ = 'S';
01039         *buf++ = 'E';
01040         *buf++ = 'R';
01041         *buf++ = ' ';   
01042         
01043         i = pop3c_getusername(buf);
01044         
01045         if(i < 0)
01046                 return;
01047                 
01048         buf += i;       
01049         
01050         /* Insert >CRLF */
01051         
01052         *buf++ = '\r';
01053         *buf = '\n';
01054                 
01055 
01056         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 7);
01057 
01058 }
01059 
01060 
01061 
01062 void pop3c_sendpassword (void)
01063 {
01064         INT8 i;
01065         UINT8* buf;
01066 
01067         /* Fill TCP Tx buffer with "PASS " and use callback function    */
01068         /* pop3c_getpassword in order to get the password                               */
01069         /* that combined "PASS password" to POP3 server                                 */
01070         
01071         buf = &net_buf[TCP_APP_OFFSET];
01072         
01073         *buf++ = 'P';
01074         *buf++ = 'A';
01075         *buf++ = 'S';
01076         *buf++ = 'S';
01077         *buf++ = ' ';   
01078         
01079         i = pop3c_getpassword(buf);
01080         
01081         if(i < 0)
01082                 return;
01083                 
01084         buf += i;       
01085         
01086         /* Insert >CRLF */
01087         
01088         *buf++ = '\r';
01089         *buf = '\n';
01090                 
01091 
01092         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 7);
01093 
01094 }
01095 
01096 
01097 
01098 void pop3c_sendstat (void)
01099 {
01100         UINT8* buf;
01101 
01102         /* Fill TCP Tx buffer with "STAT\r\n" and send it to POP3 server        */
01103         
01104         buf = &net_buf[TCP_APP_OFFSET];
01105         
01106         *buf++ = 'S';
01107         *buf++ = 'T';
01108         *buf++ = 'A';
01109         *buf++ = 'T';
01110         *buf++ = '\r';
01111         *buf = '\n';
01112                 
01113 
01114         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, 6);
01115 
01116 }
01117 
01118 void pop3c_sendlist (UINT16 msgnbr)
01119 {
01120         UINT8* buf;
01121         INT16 i;
01122 
01123         /* Ask LIST of given message number in order to get the total len of it */
01124         
01125         buf = &net_buf[TCP_APP_OFFSET];
01126         
01127         *buf++ = 'L';
01128         *buf++ = 'I';
01129         *buf++ = 'S';
01130         *buf++ = 'T';
01131         *buf++ = ' ';
01132         
01133         ltoa( (UINT32)msgnbr, buf);
01134         
01135         i = strlen(buf,40);
01136         
01137         if(i<0)
01138                 return;
01139         
01140         buf += i;       
01141         
01142         *buf++ = '\r';
01143         *buf = '\n';
01144                 
01145 
01146         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 7);
01147 
01148 }
01149 
01150 
01151 void pop3c_sendtop (UINT16 msgnbr)
01152 {
01153         UINT8* buf;
01154         INT16 i;
01155 
01156         /* Ask TOP msgnbr 0 in order to get the header of msg   */
01157         
01158         buf = &net_buf[TCP_APP_OFFSET];
01159         
01160         *buf++ = 'T';
01161         *buf++ = 'O';
01162         *buf++ = 'P';
01163         *buf++ = ' ';
01164         
01165         ltoa( (UINT32)msgnbr, buf);
01166         
01167         i = strlen(buf,40);
01168         
01169         if(i<0)
01170                 return;
01171         
01172         buf += i;       
01173         
01174         *buf++ = ' ';
01175         *buf++ = '0';
01176         
01177         *buf++ = '\r';
01178         *buf = '\n';
01179                 
01180 
01181         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 8);
01182 
01183 }
01184 
01185 void pop3c_sendretr (UINT16 msgnbr)
01186 {
01187         UINT8* buf;
01188         INT16 i;
01189 
01190         /* Ask RETR of given message number in order to get the message */
01191         
01192         buf = &net_buf[TCP_APP_OFFSET];
01193         
01194         *buf++ = 'R';
01195         *buf++ = 'E';
01196         *buf++ = 'T';
01197         *buf++ = 'R';
01198         *buf++ = ' ';
01199         
01200         ltoa( (UINT32)msgnbr, buf);
01201         
01202         i = strlen(buf,40);
01203         
01204         if(i<0)
01205                 return;
01206         
01207         buf += i;       
01208         
01209         *buf++ = '\r';
01210         *buf = '\n';
01211                 
01212 
01213         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 7);
01214 
01215 }
01216 
01217 
01218 void pop3c_senddele (UINT16 msgnbr)
01219 {
01220         UINT8* buf;
01221         INT16 i;
01222 
01223         /* Ask DELE of given message number in order to delete it       */
01224         
01225         buf = &net_buf[TCP_APP_OFFSET];
01226         
01227         *buf++ = 'D';
01228         *buf++ = 'E';
01229         *buf++ = 'L';
01230         *buf++ = 'E';
01231         *buf++ = ' ';
01232         
01233         ltoa( (UINT32)msgnbr, buf);
01234         
01235         i = strlen(buf,40);
01236         
01237         if(i<0)
01238                 return;
01239         
01240         buf += i;       
01241         
01242         *buf++ = '\r';
01243         *buf = '\n';
01244                 
01245 
01246         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, i + 7);
01247 
01248 }
01249 
01250 
01251 
01252 void pop3c_sendquit (void)
01253 {
01254         UINT8* buf;
01255 
01256         /* Fill TCP Tx buffer with "QUIT\r\n" and send it to POP3 server        */
01257         
01258         buf = &net_buf[TCP_APP_OFFSET];
01259         
01260         *buf++ = 'Q';
01261         *buf++ = 'U';
01262         *buf++ = 'I';
01263         *buf++ = 'T';
01264         *buf++ = '\r';
01265         *buf = '\n';
01266 
01267         tcp_send(pop3_client.sochandle, &net_buf[TCP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - TCP_APP_OFFSET, 6);
01268 
01269 }
01270 
01271 
01272 INT16 pop3c_parsestat (void)
01273 {
01274         /* Parse total number of messages       */
01275         
01276         UINT8 i;
01277         UINT8 ch;
01278         
01279         if( RECEIVE_NETWORK_B() != '+')
01280                 return(-1);
01281         if( tolower(RECEIVE_NETWORK_B()) != 'o')
01282                 return(-1);     
01283         if( tolower(RECEIVE_NETWORK_B()) != 'k')
01284                 return(-1);     
01285         if( RECEIVE_NETWORK_B() != ' ')
01286                 return(-1);             
01287 
01288         pop3_client.msgtotal = 0;
01289 
01290         for(i=0; i<5; i++) {
01291                 ch = RECEIVE_NETWORK_B();
01292                 
01293                 if(ch == ' ')
01294                         return(1);
01295                 
01296                 if(     isnumeric(ch) == 0)
01297                         return(-1);
01298                 
01299                 ch = asciitohex(ch);
01300                 
01301                 pop3_client.msgtotal *= 10;
01302                 pop3_client.msgtotal += ch;     
01303                                 
01304         }
01305         
01306         /* If we get there the number of messages is too big    */
01307         
01308         return(-1);
01309         
01310 
01311 }
01312 
01313 INT16 pop3c_parselist (void)
01314 {
01315         /* Parse total length of current message        */
01316 
01317         UINT8 i;
01318         UINT8 ch;
01319 
01320         if( RECEIVE_NETWORK_B() != '+')
01321                 return(-1);
01322         if( tolower(RECEIVE_NETWORK_B()) != 'o')
01323                 return(-1);     
01324         if( tolower(RECEIVE_NETWORK_B()) != 'k')
01325                 return(-1);     
01326         if( RECEIVE_NETWORK_B() != ' ')
01327                 return(-1);
01328         
01329         /* Receive untill next space    */
01330         
01331         for(i=0; i<5; i++) {
01332                 ch = RECEIVE_NETWORK_B();
01333                 
01334                 if( ch == ' ')
01335                         break;
01336         }       
01337 
01338         /* Space not found?     */
01339 
01340         if( ch != ' ')
01341                 return(-1);
01342         
01343         pop3_client.curmsgtotlen = 0;
01344                 
01345         for(i=0; i<9; i++) {
01346                 ch = RECEIVE_NETWORK_B();       
01347                 
01348                 if(ch == '\r')
01349                         return(1);
01350                 if(ch == '\n')
01351                         return(1);      
01352                 
01353                 if(     isnumeric(ch) == 0)
01354                         return(-1);
01355                 
01356                 ch = asciitohex(ch);
01357                 
01358                 pop3_client.curmsgtotlen *= 10;
01359                 pop3_client.curmsgtotlen += ch;         
01360                 
01361         }       
01362         
01363         /* If all OK we are NOT here    */
01364         
01365         return(-1);
01366 
01367 }
01368 
01369 
01370 
01371 
01372 
01373 void pop3c_changestate (UINT8 nstate)
01374 {
01375         
01376         init_timer(pop3_client.tmrhandle, POP3C_TOUT*TIMERTIC);
01377         pop3_client.state = nstate;
01378 
01379 }
01380 

Generated on Sun Aug 3 20:33:00 2003 for OpenTCP by doxygen1.2.18