Ejemplo n.º 1
0
/************************************************************************
* NAME: fapp_http_string_buffer_respond
*
* DESCRIPTION:
*************************************************************************/
static unsigned long fapp_http_string_buffer_respond(char * buffer, unsigned long buffer_size, char * eof, long *cookie)
{
    unsigned long result = 0;
   
    char *string_buffer_ptr = (char *) *cookie;
    
    unsigned long send_size = fnet_strlen(string_buffer_ptr);
    
    
    *eof = 1; /* No aditional send by default. */
    
    if(buffer && buffer_size)
    {
	    if(send_size>buffer_size)
	        send_size = buffer_size; 
	 
	    fnet_memcpy(buffer, string_buffer_ptr, send_size);

	    string_buffer_ptr += send_size;
	    if(*string_buffer_ptr!='\0') /* If any data for sending.*/ 
	        *eof = 0;    /* Need more itteration. */

	    result = send_size;
	    
	    *cookie = (long)string_buffer_ptr; /* Save cgi_buffer_ptr as cookie.*/
    }
    
    return result;    
}
Ejemplo n.º 2
0
/************************************************************************
* NAME: fnet_dns_init
*
* DESCRIPTION: Initializes DNS client service and starts the host 
*              name reolving.
************************************************************************/
static unsigned int fnet_dns_add_question( char *message, unsigned short type, char *host_name)
{
    unsigned int        total_length = 0U;
    unsigned int        label_length;
    fnet_dns_q_tail_t   *q_tail;
    char                *strtok_pos = FNET_NULL;
    

    /* Set Question section :    
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                     QNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QTYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QCLASS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    */ 
    /* QNAME */
    /* a domain name represented as a sequence of labels, where
    * each label consists of a length octet followed by that
    * number of octets. The domain name terminates with the
    * zero length octet for the null label of the root. Note
    * that this field may be an odd number of octets; no
    * padding is used.
    */
 
    /* Copy host_name string.*/
    fnet_strcpy(&message[1], host_name); 
 
    /* TBD PFI, use strtok_pos as pointer.*/
    
    /* Replace '.' by zero.*/
    fnet_strtok_r(&message[1], ".", &strtok_pos);

    while((label_length = fnet_strlen(&message[total_length]+1U)) > 0U)
    {
        message[total_length] = (char)label_length; /* Set length before (previous) label.*/
        total_length += label_length + 1U;
       
        fnet_strtok_r(FNET_NULL,".", &strtok_pos);
    }
    
    q_tail = (fnet_dns_q_tail_t *)&message[total_length];
    
    /* Skip 1 byte (zero). End of string. */

    /* QTYPE */
    q_tail->qtype =  type;
    
    /* QCLASS */
    q_tail->qclass = FNET_HTONS(FNET_DNS_HEADER_CLASS_IN);

    return (total_length+ sizeof(fnet_dns_q_tail_t)); 
}
Ejemplo n.º 3
0
/************************************************************************
* NAME: fapp_fs_view_cmd
*
* DESCRIPTION: 
*************************************************************************/
static void fapp_fs_view_cmd( fnet_shell_desc_t desc, fnet_index_t argc, fnet_char_t ** argv )
{
    FNET_FS_FILE    file;
    fnet_char_t    *path = argv[1];
    fnet_char_t    *path_end;
    fnet_size_t     size_cd = fnet_strlen (fapp_fs_current_path);
    fnet_size_t     size_path;
    fnet_char_t    splitter[] = {FNET_FS_SPLITTER,'\0'};
    fnet_uint8_t    data;
    struct          fnet_fs_dirent dirent;    

    FNET_COMP_UNUSED_ARG(desc);
    FNET_COMP_UNUSED_ARG(argc);
        
	if (*path != FNET_FS_SPLITTER) /* Realative path.*/
	{
	    /* Add splitter if not yet.*/
	    if(fapp_fs_current_path[size_cd-1U] != FNET_FS_SPLITTER) 
        {
	        fnet_strncat( &fapp_fs_current_path[0], splitter, FAPP_FS_DIR_PATH_MAX);
        }
	        
	    fnet_strncat( &fapp_fs_current_path[0], path, FAPP_FS_DIR_PATH_MAX);
	    path = fapp_fs_current_path; 
	}    
    else /* Full path. */
    {
        /* Strip possible repetitive leading slashes. */
        while ((path[0] == FNET_FS_SPLITTER) && (path[1] == FNET_FS_SPLITTER)) 
        {
            path++;	        
        }
    }
    
    /* Strip possible ending slashes. */
    if((size_path = fnet_strlen(path)) > 0U)
    {
        path_end = &path[size_path-1U]; 
        while(*path_end == FNET_FS_SPLITTER)
        {
            *path_end = '\0';
            path_end--;	        
        }
    }
    
    /* Open file. */
    file = fnet_fs_fopen(path,"r");
    
    if (file)
    {
        /* Print file info.*/
        fnet_fs_finfo (file, &dirent);
        
        fnet_shell_println(desc, FAPP_FS_DIR_STR, "Content of:", dirent.d_size, dirent.d_name);
        
        while(fnet_fs_fread(&data, sizeof(data), file))
        {
            fnet_shell_putchar(desc, data);
        }
                  
        /* Close file. */    
        fnet_fs_fclose(file);                  
    }
    else
    {
        fnet_shell_println(desc, FAPP_FS_VIEW_ERR, argv[1]);
    }
    
    /* Restore cur path. */
    fapp_fs_current_path[size_cd] = '\0'; 
                 
}
Ejemplo n.º 4
0
/************************************************************************
* NAME: fapp_fs_cd_cmd
*
* DESCRIPTION: Change the current directory.
*************************************************************************/
static void fapp_fs_cd_cmd( fnet_shell_desc_t desc, fnet_index_t argc, fnet_char_t ** argv )
{
    FNET_FS_DIR     dir;
    fnet_char_t    *path = argv[1];
    fnet_char_t    *path_end;
    fnet_size_t     size_cd = fnet_strlen (fapp_fs_current_path);
    fnet_size_t     size_path;
    fnet_char_t    splitter[] = {FNET_FS_SPLITTER,'\0'};    

    FNET_COMP_UNUSED_ARG(argc);
        
	if (*path != FNET_FS_SPLITTER) /* Realative path.*/
	{
	    /* Add splitter if not yet.*/
	    if(fapp_fs_current_path[size_cd-1U] != FNET_FS_SPLITTER) 
        {
	        fnet_strncat( &fapp_fs_current_path[0], splitter, FAPP_FS_DIR_PATH_MAX);
        }
	        
	    fnet_strncat( &fapp_fs_current_path[0], path, FAPP_FS_DIR_PATH_MAX);
	    path = fapp_fs_current_path; 
	}    
    else /* Full path. */
    {
        /* Strip possible repetitive leading slashes. */
        while ((path[0] == FNET_FS_SPLITTER) && (path[1] == FNET_FS_SPLITTER))
        {
            path++;	        
        }
    }
    
    /* Strip possible ending slashes. */
    if((size_path = fnet_strlen(path)) > 0U)
    {
        path_end = &path[size_path - 1U]; 
        while(*path_end == FNET_FS_SPLITTER)
        {
            *path_end = '\0';
            path_end--;	        
        }
    }
    
    /* Open dir. */
    dir = fnet_fs_opendir(path);
    
    if (dir)
    {
        /* Update cur path. */
        fnet_strncpy( &fapp_fs_current_path[0], path, FAPP_FS_DIR_PATH_MAX);
        if(fapp_fs_current_path[0] == '\0') /* root dir */
        {
            fnet_strncat( &fapp_fs_current_path[0], splitter, FAPP_FS_DIR_PATH_MAX);
        }
    
        /* Change shell prompt. */
        fnet_sprintf( FAPP_FS_PROMPT_STR, "%s%s%s", 
                  &FAPP_FS_PROMPT_STR_HEADER[0],
                  &fapp_fs_current_path[0],
                  &FAPP_FS_PROMPT_STR_TRAILER[0]);
                  
        /* Close dir. */    
        fnet_fs_closedir(dir);                  
    }
    else
    {
        /* Restore cur path. */
        fapp_fs_current_path[size_cd] = '\0'; 
        fnet_shell_println(desc, FAPP_FS_CD_ERR, argv[1]);
    }
                 
}
Ejemplo n.º 5
0
/************************************************************************
* NAME: fnet_dns_init
*
* DESCRIPTION: Initializes DNS client service and starts the host 
*              name resolving.
************************************************************************/
int fnet_dns_init( struct fnet_dns_params *params )
{
    const unsigned long bufsize_option = FNET_DNS_MESSAGE_SIZE;
    unsigned int        total_length;
    unsigned long       host_name_length;
    struct sockaddr     remote_addr;
    fnet_dns_header_t   *header;
  
    /* Check input parameters. */
    if((params == 0) 
        || (params->dns_server_addr.sa_family == AF_UNSPEC) 
        || fnet_socket_addr_is_unspecified(&params->dns_server_addr)
        || (params->handler == 0)
        /* Check length of host_name.*/
        || ((host_name_length = fnet_strlen(params->host_name)) == 0U) || (host_name_length >= FNET_DNS_MAME_SIZE))
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_PARAMS);
        goto ERROR;
    }

    /* Check if DNS service is free.*/
    if(fnet_dns_if.state != FNET_DNS_STATE_DISABLED)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_IS_INITIALIZED);
        goto ERROR;
    }
    
    /* Save input parmeters.*/
    fnet_dns_if.handler = params->handler;
    fnet_dns_if.handler_cookie = params->cookie;
    fnet_dns_if.addr_family = params->addr_family;
    fnet_dns_if.addr_number = 0;

    if(params->addr_family == AF_INET)
    {
        fnet_dns_if.dns_type = FNET_HTONS(FNET_DNS_TYPE_A);
    }
    else
    if(params->addr_family == AF_INET6)
    {
        fnet_dns_if.dns_type = FNET_HTONS(FNET_DNS_TYPE_AAAA);
    }
    else
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_PARAMS);
        goto ERROR;
    }
    
    fnet_dns_if.iteration = 0U;  /* Reset iteration counter.*/
    fnet_dns_if.id++;           /* Change query ID.*/
   
    /* Create socket */
    if((fnet_dns_if.socket_cln = socket(params->dns_server_addr.sa_family, SOCK_DGRAM, 0)) == SOCKET_INVALID)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SOCKET_CREATION);
        goto ERROR;
    }
    
    /* Set socket options */
    setsockopt(fnet_dns_if.socket_cln, SOL_SOCKET, SO_RCVBUF, (const char *)&bufsize_option, sizeof(bufsize_option));
    setsockopt(fnet_dns_if.socket_cln, SOL_SOCKET, SO_SNDBUF, (const char *)&bufsize_option, sizeof(bufsize_option));
    
    /* Bind/connect to the server.*/
    FNET_DEBUG_DNS("Connecting to DNS Server.");
    fnet_memset_zero(&remote_addr, sizeof(remote_addr));
    remote_addr = params->dns_server_addr;
    if(remote_addr.sa_port == 0U)
    {
        remote_addr.sa_port = FNET_CFG_DNS_PORT;
    }
   
    if(connect(fnet_dns_if.socket_cln, &remote_addr, sizeof(remote_addr))== FNET_ERR)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SOCKET_CONNECT);
        goto ERROR_1;
    }
    
    /* ==== Build message. ==== */
    fnet_memset_zero(fnet_dns_if.message, sizeof(fnet_dns_if.message)); /* Clear buffer.*/
     
    /* Set header fields:
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    */    
    
    header = (fnet_dns_header_t *)fnet_dns_if.message;
    
    header->id = fnet_dns_if.id;            /* Set ID. */
    
    header->flags = FNET_HTONS(FNET_DNS_HEADER_FLAGS_RD); /* Recursion Desired.*/
   
    header->qdcount = FNET_HTONS(1U);        /* One Question. */
    
    /* No Answer (ANCOUNT).*/ /* No Authority (NSCOUNT). */ /* No Additional (ARCOUNT). */


    total_length = sizeof(fnet_dns_header_t);
    total_length += fnet_dns_add_question( &fnet_dns_if.message[total_length], fnet_dns_if.dns_type, params->host_name);
    fnet_dns_if.message_size = (unsigned long)(total_length);
  
    /* Register DNS service. */
    fnet_dns_if.service_descriptor = fnet_poll_service_register(fnet_dns_state_machine, (void *) &fnet_dns_if);
    if(fnet_dns_if.service_descriptor == (fnet_poll_desc_t)FNET_ERR)
    {
        FNET_DEBUG_DNS(FNET_DNS_ERR_SERVICE);
        goto ERROR_1;
    }
    
    fnet_dns_if.state = FNET_DNS_STATE_TX; /* => Send request. */    
   
    return FNET_OK;
ERROR_1:
    closesocket(fnet_dns_if.socket_cln);

ERROR:
    return FNET_ERR;
}
Ejemplo n.º 6
0
/************************************************************************
* NAME: fnet_http_state_machine
*
* DESCRIPTION: Http server state machine.
************************************************************************/
static void fnet_http_state_machine( void *http_if_p )
{
    struct sockaddr         foreign_addr;
    int                     len;
    int                     res;
    struct fnet_http_if     *http = (struct fnet_http_if *)http_if_p;
    int                     iteration;
    char                    *ch;
    int                     i;
    struct fnet_http_session_if   *session;
    
    for(i=0; i<FNET_CFG_HTTP_SESSION_MAX; i++) 
    { 
        session = &http->session[i];
        http->session_active = session;



    for(iteration = 0; iteration < FNET_HTTP_ITERATION_NUMBER; iteration++)
    {
        switch(session->state)
        {
            
            /*---- LISTENING ------------------------------------------------*/
            case FNET_HTTP_STATE_LISTENING:
                len = sizeof(foreign_addr);

                if((session->socket_foreign = accept(http->socket_listen, &foreign_addr, &len)) != SOCKET_INVALID)
                {
#if FNET_CFG_DEBUG_HTTP
                    {
                        char ip_str[FNET_IP_ADDR_STR_SIZE];
                        fnet_inet_ntop(foreign_addr.sa_family, (char*)(foreign_addr.sa_data), ip_str, sizeof(ip_str)); 
                        FNET_DEBUG_HTTP("");
                        FNET_DEBUG_HTTP("HTTP: RX Request From: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port));
                    }
#endif

                    /* Reset response & request parameters.*/
                    fnet_memset_zero(&session->response, sizeof(struct fnet_http_response));
                    fnet_memset_zero(&session->request, sizeof(struct fnet_http_request));

#if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/             
                    session->response.content_length = -1; /* No content length by default.*/ 
                    /* Default HTTP version response.*/
                    session->response.version.major = FNET_HTTP_VERSION_MAJOR;
                    session->response.version.minor = FNET_HTTP_VERSION_MINOR;
                    session->response.tx_data = fnet_http_tx_status_line;
#endif                    
                    session->state_time = fnet_timer_ticks();          /* Reset timeout. */
                    session->buffer_actual_size = 0;
                    session->state = FNET_HTTP_STATE_RX_REQUEST; /* => WAITING HTTP REQUEST */
                }
                break;
            /*---- RX_LINE -----------------------------------------------*/
            case FNET_HTTP_STATE_RX_REQUEST:    
                
                do
                {
                    /* Read character by character.*/
                    ch = &session->buffer[session->buffer_actual_size];
                    
                    if((res = recv(session->socket_foreign, ch, 1, 0) )!= SOCKET_ERROR)
                    {
                        if(res > 0) /* Received a data.*/
                        {
                            session->state_time = fnet_timer_ticks();  /* Reset timeout.*/
                            
                            session->buffer_actual_size++;
                        
                            if(*ch == '\r')
                                *ch = '\0';
                            else if(*ch == '\n')
                            /* Line received.*/
                            {
                                char * req_buf = &session->buffer[0];

                                *ch = '\0'; 
                                
                                if(session->request.method == 0)
                                /* Parse Request line.*/
                                {
                                    const struct fnet_http_method **method = &fnet_http_method_list[0];
                                    
                                    FNET_DEBUG_HTTP("HTTP: RX Request: %s", req_buf);
                                    
                                    /* Determine the method type. */
               	                    while(*method)
            	                    {
            			                if ( !fnet_strcmp_splitter(req_buf, (*method)->token, ' ') ) 
            			                {				 
            				                req_buf+=fnet_strlen((*method)->token);
            				                session->request.method = *method;
            				                break;
            			                }
            			                method++;
            			            }
            			            
            			            /* Check if the method is supported? */
            			            if(session->request.method && session->request.method->handle) 
        			                {
                			            /* Parse URI.*/
                			            req_buf = fnet_http_uri_parse(req_buf, &session->request.uri);
                			            
                			            FNET_DEBUG_HTTP("HTTP: URI Path = %s; Query = %s", http->request.uri.path, http->request.uri.query);
                			            
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/                            
                                        /* Parse HTTP/x.x version.*/
                                        fnet_http_version_parse(++req_buf, &session->response.version);
                                        
                                        /* Check the highest supported HTTP version.*/
                                        if(((session->response.version.major<<8)|session->response.version.minor) > ((FNET_HTTP_VERSION_MAJOR<<8)|FNET_HTTP_VERSION_MINOR))
                                        {
                                            session->response.version.major = FNET_HTTP_VERSION_MAJOR;
                                            session->response.version.minor = FNET_HTTP_VERSION_MINOR;
                                        }
                                        
                                        if(session->response.version.major == 0) 
                                        /* HTTP/0.x */
                                        {
                                            session->state = FNET_HTTP_STATE_CLOSING; /* Client does not support HTTP/1.x*/
                                            break;
                                        }
                                        
    #if FNET_CFG_HTTP_AUTHENTICATION_BASIC                                    
                                        /* Check Authentification.*/
                                        fnet_http_auth_validate_uri(http);
    #endif
    #endif/*FNET_CFG_HTTP_VERSION_MAJOR*/
                                         
                                        /* Call method initial handler.*/
                                        res = session->request.method->handle(http, &session->request.uri);
                                        
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/                                       
                                        if(fnet_http_status_ok(res) == FNET_OK)
    #else                                            
                                        if((res == FNET_OK))                     
    #endif                                    
                                           
                                        {
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
                                            session->buffer_actual_size = 0;
                                                /* => Parse Header line.*/ 
    #else /* HTTP/0.9 */
                    			            session->response.tx_data = session->request.method->send;
                    			            
                                            /* Reset buffer pointers.*/
            		                        session->buffer_actual_size = 0;
                                            session->state = FNET_HTTP_STATE_TX; /* Send data.*/
    #endif                    			                
                    			        }
                                        /* Method error.*/
            			                else /* Error.*/
            			                {
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
                                            /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */
                                            if(res != FNET_ERR)
                                                session->response.status.code = (fnet_http_status_code_t)res;
                                            
                                            /* Send status line.*/
                                            session->buffer_actual_size = 0;
                                            session->state = FNET_HTTP_STATE_TX; /* Send error.*/
    #else /* HTTP/0.9 */
            			                    session->state = FNET_HTTP_STATE_CLOSING;
    #endif     			                
            			                }
            			            }
            			            /* Method is not supported.*/
            			            else /* Error.*/
            			            {
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
                                        session->response.status.code = FNET_HTTP_STATUS_CODE_NOT_IMPLEMENTED;    
                                        /* Send status line.*/
                                        session->buffer_actual_size = 0;
                                        session->state = FNET_HTTP_STATE_TX; /* Send error.*/
    #else /* HTTP/0.9 */
                			            session->state = FNET_HTTP_STATE_CLOSING;
    #endif                			                
            			            } 
                                
                                }
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/                            
                                /* Parse Header line.*/
                                else
                                {
                                    if(session->request.skip_line == 0)
                                    {
                                        if(*req_buf == 0)
                                        /* === Empty line => End of the request header. ===*/
                                        {
    #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
                                            if(session->response.auth_entry)
                                                /* Send UNAUTHORIZED error.*/
                                                session->response.status.code = FNET_HTTP_STATUS_CODE_UNAUTHORIZED;
                                            else /* Send Data.*/
    #endif                                            
                                                session->response.status.code = FNET_HTTP_STATUS_CODE_OK;

    #if FNET_CFG_HTTP_POST
                                            if(session->request.content_length > 0)
                                            /* RX Entity-Body.*/
                                            {
                                                session->buffer_actual_size = 0;
                                                session->state = FNET_HTTP_STATE_RX; 
                                            }
                                            else
    #endif                                            
                                            /* TX Full-Responce.*/
                                            {
                                                /* Send status line.*/
                                                session->buffer_actual_size = 0;
                                                session->state = FNET_HTTP_STATE_TX; 
                                            }
                                            break;
                                        }
                                        else
                                        /* === Parse header fields. ===*/
                                        {
                                            
                                            FNET_DEBUG_HTTP("HTTP: RX Header: %s", req_buf);                                   
                                            
    #if FNET_CFG_HTTP_AUTHENTICATION_BASIC
                                            /* --- Authorization: ---*/
                                            if (session->response.auth_entry && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_AUTHORIZATION, sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1) == 0)
                                            /* Authetication is required.*/
                                            {
                                                char *auth_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1];
                                                
                                                /* Validate credentials.*/    
                                                if(fnet_http_auth_validate_credentials(http, auth_str) == FNET_OK)
                                                    session->response.auth_entry = 0; /* Authorization is succesful.*/
                                            }
    #endif                                             
    
    #if FNET_CFG_HTTP_POST                                            
                                            /* --- Content-Length: ---*/ 
                                            if (session->request.method->receive && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH, sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1) == 0)
                                            {
                                                char *p;
                                                char *length_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1];
                                                
                                                session->request.content_length = (long)fnet_strtoul(length_str,&p,10);
                                            }
    #endif                                            
                                        }
                                    }
                                    /* Line is skiped.*/
                                    else
                                        session->request.skip_line = 0; /* Reset the Skip flag.*/
                                    
                                    session->buffer_actual_size = 0; /* => Parse Next Header line.*/ 
                                }
    #endif/* FNET_CFG_HTTP_VERSION_MAJOR */                            
                            }
                            /* Not whole line received yet.*/
                            else if (session->buffer_actual_size == FNET_HTTP_BUF_SIZE) 
                            /* Buffer is full.*/
                            { 
    #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/
                                if(session->request.method != 0)
                                /* For header, skip the line.*/
                                {
                                    /* Skip line.*/
                                    session->request.skip_line = 1;
                                    session->buffer_actual_size = 0;
                                }
                                else /* Error.*/
                                {
                                    /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */ 
                                    session->buffer_actual_size = 0;
                                    session->state = FNET_HTTP_STATE_TX; /* Send error.*/
                                }
                                    
    #else /* HTTP/0.9 */ 
            			        session->state = FNET_HTTP_STATE_CLOSING;
    #endif            			                
                            }
                        }
                        /* No data.*/
                        else if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks()) /* Time out? */
                                      > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS))
                        {
                                session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                        }
                        /* else => WAITING REQUEST. */
                    }
                    /* recv() error.*/
                    else  
                    {
                        session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                    }
                }
                while ((res > 0) && (session->state == FNET_HTTP_STATE_RX_REQUEST)); /* Till receiving the request header.*/
                break;
    #if FNET_CFG_HTTP_POST
            /*---- RX --------------------------------------------------*/
            case FNET_HTTP_STATE_RX: /* Receive data (Entity-Body). */
                if((res = recv(session->socket_foreign, &session->buffer[session->buffer_actual_size], (int)(FNET_HTTP_BUF_SIZE-session->buffer_actual_size), 0) )!= SOCKET_ERROR)
                {
                    session->buffer_actual_size += res;
                    session->request.content_length -= res;
                    
                    if(res > 0)
                    /* Some Data.*/
                    {
                        session->state_time = fnet_timer_ticks();  /* Reset timeout.*/
                        res = session->request.method->receive(http); 
                        if(fnet_http_status_ok(res) != FNET_OK)
                        {
                            if(res != FNET_ERR)
                                session->response.status.code = (fnet_http_status_code_t)res;
                            else
                                session->response.status.code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR;    
                            
                            session->request.content_length = 0;
                        }
                        
                        if(session->request.content_length <= 0) /* The last data.*/
                        {
                            session->state = FNET_HTTP_STATE_TX; /* Send data.*/
                        }
                        
                        session->buffer_actual_size = 0;
                    }
                    else
                    /* No Data.*/
                    {
                        if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks())
                              > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS))
                        /* Time out.*/
                        {
                            session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                        }
                    }
                }
                else
                /* Socket error.*/
                {
                    session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                }
                
                break;            
    #endif /* FNET_CFG_HTTP_POST.*/
            /*---- TX --------------------------------------------------*/
            case FNET_HTTP_STATE_TX: /* Send data. */
                if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks())
                     < (FNET_HTTP_WAIT_TX_MS / FNET_TIMER_PERIOD_MS)) /* Check timeout */
                {
                    int send_size;
                  
                    if(session->buffer_actual_size == session->response.buffer_sent)
                    {
                        /* Reset counters.*/
                        session->buffer_actual_size =0;
                        session->response.buffer_sent = 0;
                        
                        if(session->response.send_eof || session->response.tx_data(http) == FNET_ERR) /* get data for sending */
                        {
                            session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                            break;
                        }
                    }
                   
                    send_size = (int)(session->buffer_actual_size - (int)session->response.buffer_sent);

                    if(send_size > http->send_max)
                        send_size = (int)http->send_max;
                    
                    if((res = send(session->socket_foreign, session->buffer
                                  + session->response.buffer_sent, send_size, 0)) != SOCKET_ERROR)
                    {
                        if(res)
                        {
                            FNET_DEBUG_HTTP("HTTP: TX %d bytes.", res);

                            session->state_time = fnet_timer_ticks();              /* reset timeout */
                            session->response.buffer_sent += res;
                        }
                        break; /* => SENDING */ 
                    }
                }

                session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */
                break;
                /*---- CLOSING --------------------------------------------------*/
            case FNET_HTTP_STATE_CLOSING:
                if(session->request.method && session->request.method->close)
                    session->request.method->close(http);

                closesocket(session->socket_foreign);
                session->socket_foreign = SOCKET_INVALID;
                    
                session->state = FNET_HTTP_STATE_LISTENING; /*=> LISTENING */
                break;
            default:
                break;                
        }
    }

    } /*for(sessions)*/
}