Ejemplo n.º 1
0
/************************************************************************
* NAME: fnet_timer_delay
*
* DESCRIPTION: Do delay for a given number of timer ticks.
*              
*************************************************************************/
void fnet_timer_delay( unsigned long delay_ticks )
{
    unsigned long start = fnet_current_time;

    while(fnet_timer_get_interval(start, fnet_timer_ticks()) < delay_ticks)
    { };
}
Ejemplo n.º 2
0
/************************************************************************
* NAME: fnet_timer_delay
*
* DESCRIPTION: Do delay for a given number of timer ticks.
*              
*************************************************************************/
void fnet_timer_delay( fnet_time_t delay_ticks )
{
    fnet_time_t start_ticks = fnet_current_time;

    while(fnet_timer_get_interval(start_ticks, fnet_timer_ticks()) < delay_ticks)
    {}
}
Ejemplo n.º 3
0
/************************************************************************
* NAME: fnet_nd6_dad_timer
* RETURS: None.
* DESCRIPTION: Timer routine used to detect increase of PMTU
*************************************************************************/
static void fnet_netif_pmtu_timer( void *cookie )
{
    fnet_netif_t    *netif = (fnet_netif_t *)cookie;
    
    if( fnet_timer_get_interval(netif->pmtu_timestamp, fnet_timer_ms()) > FNET_NETIF_PMTU_TIMEOUT)
    {
        fnet_netif_set_pmtu(netif, netif->mtu);
    }
}
Ejemplo n.º 4
0
/************************************************************************
* NAME: fnet_timer_handler_bottom
*
* DESCRIPTION: Handles timer interrupts 
*              
*************************************************************************/
void fnet_timer_handler_bottom(void *cookie)
{
    struct fnet_net_timer *timer = fnet_tl_head;
    
    FNET_COMP_UNUSED_ARG(cookie);
    
    while(timer)
    {
        if(fnet_timer_get_interval(timer->timer_cnt, fnet_current_time) >= timer->timer_rv)
        {
            timer->timer_cnt = fnet_current_time;

            if(timer->handler)
                timer->handler(timer->cookie);
        }

        timer = timer->next;
    }
}
Ejemplo n.º 5
0
/************************************************************************
* DESCRIPTION:
************************************************************************/
static void fnet_telnet_send(struct fnet_telnet_session_if *session)
{
    fnet_int32_t    res;
    fnet_index_t    tx_buffer_tail_index = 0u;
    fnet_time_t     timeout = fnet_timer_get_ticks();

    /* Send all data in the buffer.*/
    while((tx_buffer_tail_index != session->tx_buffer_head_index) && (session->state != FNET_TELNET_STATE_CLOSING))
    {
        if((res = fnet_socket_send(session->socket_foreign, &session->tx_buffer[tx_buffer_tail_index], (fnet_size_t)session->tx_buffer_head_index - tx_buffer_tail_index, 0u)) != FNET_ERR)
        {
            if(res) /* >0 */
            {
                /* Update buffer pointers. */
                tx_buffer_tail_index += (fnet_index_t)res;

                /* Reset timeout. */
                timeout = fnet_timer_get_ticks();
            }
            else if( fnet_timer_get_interval(timeout, fnet_timer_get_ticks())
                     > (FNET_TELNET_WAIT_SEND_MS / FNET_TIMER_PERIOD_MS) ) /* Check timeout */
            {
                FNET_DEBUG_TELNET("TELNET:Send timeout.");
                break; /* Time-out. */
            }
            else
            {}
        }
        else /* Error.*/
        {
            FNET_DEBUG_TELNET("TELNET:Send error.");
            session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
        }
    }

    /* Reset TX buffer index. */
    session->tx_buffer_head_index = 0u;
}
Ejemplo n.º 6
0
/************************************************************************
* NAME: fapp_bench_print_results
*
* DESCRIPTION: Print Benchmark results. 
************************************************************************/
static void fapp_bench_print_results (fnet_shell_desc_t desc)
{
/* Print benchmark results.*/
    unsigned long interval = fnet_timer_get_interval(fapp_bench.first_time, fapp_bench.last_time);
    
    fnet_shell_println(desc, "Results:");
    
    if(fapp_bench.remote_bytes == 0)
    {
        fnet_shell_println(desc, "\t%d bytes in %d.%d seconds = %d Kbits/sec\n", fapp_bench.bytes, 
            ((interval*FNET_TIMER_PERIOD_MS)/1000),
            ((interval*FNET_TIMER_PERIOD_MS)%1000)/100,
            (interval == 0) ? -1 : (int)((fapp_bench.bytes*8/**(1000*//FNET_TIMER_PERIOD_MS/*)*/)/interval)/*/1000*/); 
    }
    else /* UDP TX only */
    {
        fnet_shell_println(desc, "\t%d [%d] bytes in %d.%d seconds = %d [%d] Kbits/sec\n", fapp_bench.bytes, fapp_bench.remote_bytes, 
            ((interval*FNET_TIMER_PERIOD_MS)/1000),
            ((interval*FNET_TIMER_PERIOD_MS)%1000)/100,
            (interval == 0) ? -1 : (int)((fapp_bench.bytes*8/**(1000*//FNET_TIMER_PERIOD_MS/*)*/)/interval)/*/1000*/,
            (interval == 0) ? -1 : (int)((fapp_bench.remote_bytes*8/**(1000*//FNET_TIMER_PERIOD_MS/*)*/)/interval)/*/1000*/);     
    }
}
Ejemplo n.º 7
0
/************************************************************************
* NAME: fnet_telnet_send
*
* DESCRIPTION: 
************************************************************************/
static void fnet_telnet_send(struct fnet_telnet_session_if *session)
{
    int             res;
    int             tx_buffer_tail_index = 0;
    unsigned long   timeout = fnet_timer_ticks();
    
    /* Send all data in the buffer.*/
    while(tx_buffer_tail_index != session->tx_buffer_head_index)
    {
        if((res = send(session->socket_foreign, &session->tx_buffer[tx_buffer_tail_index], session->tx_buffer_head_index - tx_buffer_tail_index, 0)) != SOCKET_ERROR)
        {
            if(res) /* >0 */
            {
                /* Update buffer pointers. */
                tx_buffer_tail_index += res;

                /* Reset timeout. */
                timeout = fnet_timer_ticks();           
            }
            else if( fnet_timer_get_interval(timeout, fnet_timer_ticks())
                         > (FNET_TELNET_WAIT_SEND_MS / FNET_TIMER_PERIOD_MS) ) /* Check timeout */
            {
                FNET_DEBUG_TELNET("TELNET:Send timeout.");
                break; /* Time-out. */
            }
        }
        else /* Error.*/
        {
            FNET_DEBUG_TELNET("TELNET:Send error.");
            session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */
            break; 
        }
    }
    
    /* Reset TX buffer index. */ 
    session->tx_buffer_head_index = 0;
}
Ejemplo n.º 8
0
/************************************************************************
* NAME: fapp_bench_udp_rx
*
* DESCRIPTION: Start Benchmark UDP server. 
************************************************************************/
static void fapp_bench_udp_rx (fnet_shell_desc_t desc, fnet_address_family_t family, struct sockaddr *multicast_address /* optional, set to 0*/)
{
	struct sockaddr         local_addr;
	const unsigned long     bufsize_option = FAPP_BENCH_SOCKET_BUF_SIZE;
	int                     received;
	char                    ip_str[FNET_IP_ADDR_STR_SIZE];
	struct sockaddr         addr;
    unsigned int            addr_len;
	int                     is_first = 1;
	int                     exit_flag = 0;
	

	/* Create listen socket */
    if((fapp_bench.socket_listen = socket(family, SOCK_DGRAM, 0)) == SOCKET_INVALID)
    {
        FNET_DEBUG("BENCH: Socket creation error.\n");
        goto ERROR_1;
    }
    
    /*Bind.*/
    fnet_memset_zero(&local_addr, sizeof(local_addr));
    
    local_addr.sa_port = FAPP_BENCH_PORT;    
    local_addr.sa_family = family;
    
    if(bind(fapp_bench.socket_listen, &local_addr, sizeof(local_addr)) == SOCKET_ERROR)
    {
        FNET_DEBUG("BENCH: Socket bind error.\n");
        goto ERROR_2;
    }


	/* Set socket options. */    
	if( 
		/* Set socket buffer size. */
		(setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ||
		(setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) 
	)
	{
    	FNET_DEBUG("BENCH: Socket setsockopt error.\n");
        goto ERROR_2;		
	}
    
    /* Join multicast group, if set. */
    if(multicast_address)
    {
    
    #if FNET_CFG_IP4
        if(multicast_address->sa_family == AF_INET)
        {
            struct ip_mreq mreq; /* Multicast group information.*/
            
            mreq.imr_multiaddr.s_addr = ((struct sockaddr_in*)multicast_address)->sin_addr.s_addr;
            mreq.imr_interface.s_addr = FNET_HTONL(INADDR_ANY); /* Default Interface.*/
            
            /* Join multicast group. */
            if(setsockopt(fapp_bench.socket_listen, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR) 
    	    {
            	FNET_DEBUG("BENCH: Joining to multicast group is failed.\n");
                goto ERROR_2;		
        	}
    	}
    #endif
    #if FNET_CFG_IP6
        if(multicast_address->sa_family == AF_INET6)
        {
            struct ipv6_mreq mreq6; /* Multicast group information.*/
            
            FNET_IP6_ADDR_COPY(&((struct sockaddr_in6*)multicast_address)->sin6_addr.s6_addr, &mreq6.ipv6imr_multiaddr.s6_addr);
            mreq6.ipv6imr_interface = ((struct sockaddr_in6*)multicast_address)->sin6_scope_id;
            
            /* Join multicast group. */
            if(setsockopt(fapp_bench.socket_listen, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq6, sizeof(mreq6)) == SOCKET_ERROR) 
    	    {
            	FNET_DEBUG("BENCH: Joining to multicast group is failed.\n");
                goto ERROR_2;		
        	}
        }
    #endif    	
        
    }
    
     /* ------ Start test.----------- */
    fnet_shell_println(desc, FAPP_DELIMITER_STR);
    fnet_shell_println(desc, " UDP RX Test" );
    fnet_shell_println(desc, FAPP_DELIMITER_STR);
    fapp_netif_addr_print(desc, family, fapp_default_netif, FNET_FALSE);
    if(multicast_address)
    {
        fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_S, "Multicast Group", fnet_inet_ntop(multicast_address->sa_family, (char*)(multicast_address->sa_data), ip_str, sizeof(ip_str)) );
    }       
    fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Local Port", FNET_NTOHS(FAPP_BENCH_PORT));
    fnet_shell_println(desc, FAPP_TOCANCEL_STR);
    fnet_shell_println(desc, FAPP_DELIMITER_STR);
  
    
    while(exit_flag == 0) /* Main loop */
    {
        fnet_shell_println(desc, "Waiting.");
        
        fapp_bench.bytes = 0;
        fapp_bench.remote_bytes = 0;
        addr_len = sizeof(addr);
        is_first = 1;
        
        while(exit_flag == 0) /* Test loop. */
        {

    		/* Receive data */
            received = recvfrom  (fapp_bench.socket_listen, (char*)(&fapp_bench.buffer[0]), FAPP_BENCH_BUFFER_SIZE, 0,
                                &addr, &addr_len );

            if(received >= FAPP_BENCH_UDP_END_BUFFER_LENGTH)
            {   
      
                /* Reset timeout. */
                fapp_bench.last_time = fnet_timer_ticks();
                
                if(is_first)
                {
                    if( received > FAPP_BENCH_UDP_END_BUFFER_LENGTH )
                    {
                        fnet_shell_println(desc,"Receiving from %s:%d",  fnet_inet_ntop(addr.sa_family, (char*)(addr.sa_data), ip_str, sizeof(ip_str)), fnet_ntohs(addr.sa_port));
                        fapp_bench.first_time = fnet_timer_ticks();
                        is_first = 0;
                    }
                }
                else
                {
                    if(received == FAPP_BENCH_UDP_END_BUFFER_LENGTH ) /* End of transfer. */
                    {
                        /* Send ACK containing amount of received data.*/
                        unsigned long ack_bytes = fnet_htonl(fapp_bench.bytes);
                        
                        /* Send several times, just to be sure that it is received/not lost.*/
                        sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr));
                        sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr));
                        sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr));
                        
                        
                        /* Print benchmark results.*/
                        fapp_bench_print_results (desc);           		
    					
                        break;    	
                    }
                    else
                        fapp_bench.bytes += received; 
                }
            }
            else
            {
                /* Check error. Check timeout */
                if(received == SOCKET_ERROR)
                {
                    fnet_shell_println(desc, "BENCH: Error (%d).", fnet_error_get());                   
                    break;
                }
                /* Check timeout. */
                if((is_first == 0) &&
                    (fnet_timer_get_interval(fapp_bench.last_time, fnet_timer_ticks()) > (FAPP_UDP_TIMEOUT_MS/FNET_TIMER_PERIOD_MS)))
                {
                    fnet_shell_println(desc, "BENCH: Exit on timeout.");
                    fapp_bench_print_results (desc);            
                    break;
                }
            }
            
            exit_flag = fnet_shell_ctrlc (desc);
        }
    }

ERROR_2:
    closesocket(fapp_bench.socket_listen);

ERROR_1:
 
    fnet_shell_println(desc, FAPP_BENCH_COMPLETED_STR);
}
Ejemplo n.º 9
0
/************************************************************************
* NAME: fnet_dns_state_machine
*
* DESCRIPTION: DNS-client state machine.
************************************************************************/
static void fnet_dns_state_machine( void *fnet_dns_if_p )
{
    int                     sent_size;
    int                     received;    
    unsigned int            i;
    fnet_dns_header_t       *header;
    fnet_dns_rr_header_t    *rr_header;
    fnet_dns_if_t           *dns_if = (fnet_dns_if_t *)fnet_dns_if_p;

    switch(dns_if->state)
    {
        /*---- TX --------------------------------------------*/
        case FNET_DNS_STATE_TX:

            FNET_DEBUG_DNS("Sending query...");
            sent_size = send(dns_if->socket_cln, dns_if->message, dns_if->message_size, 0U);
            
            if (sent_size != (int)dns_if->message_size)
        	{
        		dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */
        	}	
            else
            {
                dns_if->last_time = fnet_timer_ticks();
                dns_if->state = FNET_DNS_STATE_RX;
            }		
            break; 
        /*---- RX -----------------------------------------------*/
        case  FNET_DNS_STATE_RX:
            /* Receive data */
            
            received = recv(dns_if->socket_cln, dns_if->message, sizeof(dns_if->message), 0U);
            
            if(received > 0 )
            {
                header = (fnet_dns_header_t *)fnet_dns_if.message;
                
                if((header->id == dns_if->id) && /* Check the ID.*/
                   ((header->flags & FNET_DNS_HEADER_FLAGS_QR)==FNET_DNS_HEADER_FLAGS_QR)) /* Is response.*/
                {
                    for (i=(sizeof(fnet_dns_header_t)-1U); i < (unsigned int)received; i++)
                    {
                        /* [RFC1035 4.1.4.] In order to reduce the size of messages, the domain system utilizes a
                        * compression scheme which eliminates the repetition of domain names in a
                        * message. In this scheme, an entire domain name or a list of labels at
                        * the end of a domain name is replaced with a pointer to a prior occurance
                        * of the same name.
                        * The pointer takes the form of a two octet sequence:
                        * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                        * | 1  1|                OFFSET                   |
                        * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                        */
                        /* => Check for 0xC0. */
                        if ((unsigned char)dns_if->message[i] == FNET_DNS_NAME_COMPRESSED_MASK) /* look for the beginnig of the response (Question Name == 192 (label compression))*/
                        {
                            rr_header = (fnet_dns_rr_header_t *)&dns_if->message[i]; 


                            /* Check Question Type, Class and Resource Data Length. */
                            if ( (rr_header->type ==  dns_if->dns_type) && 
                                 (rr_header->rr_class == FNET_HTONS(FNET_DNS_HEADER_CLASS_IN))) 
                            {
                                /* Resolved.*/
                                if(rr_header->type == FNET_HTONS(FNET_DNS_TYPE_A))
                                {
                                	dns_if->resolved_ip4_addr[dns_if->addr_number].ip4_addr = *((fnet_ip4_addr_t*)(&rr_header->rdata));
                                    dns_if->resolved_ip4_addr[dns_if->addr_number].ttl = rr_header->ttl;
                                }
                                else /* AF_INET6 */
                                {
                                    FNET_IP6_ADDR_COPY( (fnet_ip6_addr_t*)(&rr_header->rdata), &dns_if->resolved_ip6_addr[dns_if->addr_number].ip6_addr );
                                    dns_if->resolved_ip6_addr[dns_if->addr_number].ttl = rr_header->ttl;
                                }
                                dns_if->addr_number++;
                            }
                            i+=(unsigned int)(sizeof(fnet_dns_rr_header_t)+fnet_ntohs(rr_header->rdlength)-4U-1U);
                        }
                    }
                }
                /* else = wrong message.*/
                
                dns_if->state = FNET_DNS_STATE_RELEASE;
            }
            else if(received == SOCKET_ERROR) /* Check error.*/
            {
                dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */
            }
            else /* No data. Check timeout */
            if(fnet_timer_get_interval(dns_if->last_time, fnet_timer_ticks()) > ((FNET_CFG_DNS_RETRANSMISSION_TIMEOUT*1000U)/FNET_TIMER_PERIOD_MS))
            {
                dns_if->iteration++;
                
                if(dns_if->iteration > FNET_CFG_DNS_RETRANSMISSION_MAX)
                {
                    dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */
                }
                else
                {
                    dns_if->state = FNET_DNS_STATE_TX;
                }
            }
            else
            {}
            break;
         /*---- RELEASE -------------------------------------------------*/    
        case FNET_DNS_STATE_RELEASE:
            {
                struct fnet_dns_resolved_addr   *addr_list = FNET_NULL;

                fnet_dns_release(); 

                /* Fill fnet_dns_resolved_addr */
                if(dns_if->addr_number > 0)
                {
                    if(dns_if->addr_family  == AF_INET)
                    {
                        for(i=0; i<dns_if->addr_number; i++)
                        {
                            fnet_memset_zero(&dns_if->resolved_ip4_addr_sock[i].resolved_addr, sizeof(dns_if->resolved_ip4_addr_sock[i].resolved_addr));

                            dns_if->resolved_ip4_addr_sock[i].resolved_addr.sa_family = AF_INET;
                            ((struct sockaddr_in*)(&dns_if->resolved_ip4_addr_sock[i].resolved_addr))->sin_addr.s_addr = dns_if->resolved_ip4_addr[i].ip4_addr;
                            dns_if->resolved_ip4_addr_sock[i].resolved_addr_ttl = dns_if->resolved_ip4_addr[i].ttl;
                        }
                        addr_list = dns_if->resolved_ip4_addr_sock;
                    }
                    else if(dns_if->addr_family == AF_INET6)
                    {
                        for(i=0; i<dns_if->addr_number; i++)
                        {
                            fnet_memset_zero(&dns_if->resolved_ip6_addr_sock[i].resolved_addr, sizeof(dns_if->resolved_ip4_addr_sock[i].resolved_addr));

                            dns_if->resolved_ip6_addr_sock[i].resolved_addr.sa_family = AF_INET6;
                            FNET_IP6_ADDR_COPY(&dns_if->resolved_ip6_addr[i].ip6_addr, &((struct sockaddr_in6*)(&dns_if->resolved_ip6_addr_sock[i].resolved_addr))->sin6_addr.s6_addr);
                            dns_if->resolved_ip6_addr_sock[i].resolved_addr_ttl = dns_if->resolved_ip6_addr[i].ttl;
                        }
                        addr_list = dns_if->resolved_ip6_addr_sock;
                    }
                    else
                    {}
                }

                dns_if->handler(addr_list, dns_if->addr_number, dns_if->handler_cookie); /* User Callback.*/
            }
            break;
        default:
            break;            
    }

}
Ejemplo n.º 10
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)*/
}
Ejemplo n.º 11
0
/************************************************************************
* NAME: fnet_ping_state_machine
*
* DESCRIPTION: PING service state machine.
************************************************************************/
static void fnet_ping_state_machine(void *fnet_ping_if_p)
{
    fnet_int32_t            received;    
    fnet_icmp_echo_header_t *hdr;
    fnet_ping_if_t          *ping_if = (fnet_ping_if_t *)fnet_ping_if_p;
    struct sockaddr         addr;
    fnet_size_t             addr_len = sizeof(addr);

    switch(ping_if->state)
    {
        /*===================================*/ 
        case FNET_PING_STATE_SENDING_REQUEST:
            /* Build message.*/
            hdr = (fnet_icmp_echo_header_t *)&fnet_ping_if.buffer[0];

            /* Fill ICMP Echo request header.*/
            fnet_memset_zero(hdr, sizeof(*hdr));
            hdr->header.type = (fnet_uint8_t)((fnet_ping_if.family == AF_INET) ? FNET_ICMP_ECHO: FNET_ICMP6_TYPE_ECHO_REQ);
            hdr->identifier = FNET_CFG_PING_IDENTIFIER;
            fnet_ping_if.sequence_number++;
            hdr->sequence_number = fnet_htons(fnet_ping_if.sequence_number);
            
            /* Fill payload data by pattern.*/
            fnet_memset(&fnet_ping_if.buffer[sizeof(*hdr)], ping_if->pattern, ping_if->packet_size);
                
            /* Checksum.*/
#if FNET_CFG_IP4
            if(ping_if->family == AF_INET)
            {
                hdr->header.checksum = fnet_checksum_buf(&fnet_ping_if.buffer[0], (sizeof(*hdr) + ping_if->packet_size));
            }
            else
#endif  
#if FNET_CFG_IP6
            if(ping_if->family == AF_INET6)
            {
                const fnet_ip6_addr_t   *src_ip = fnet_ip6_select_src_addr(FNET_NULL, (fnet_ip6_addr_t *)ping_if->target_addr.sa_data); /*TBD  Check result.*/

                hdr->header.checksum = fnet_checksum_pseudo_buf(&fnet_ping_if.buffer[0], 
                                                                (fnet_uint16_t)(sizeof(*hdr) + ping_if->packet_size), 
                                                                FNET_HTONS((fnet_uint16_t)IPPROTO_ICMPV6), 
                                                                (const fnet_uint8_t *)src_ip,
                                                                ping_if->target_addr.sa_data, 
                                                                sizeof(fnet_ip6_addr_t));
            }
            else
#endif 
            {}
            
            /* Send request.*/    
            fnet_socket_sendto(fnet_ping_if.socket_foreign, (fnet_uint8_t*)(&fnet_ping_if.buffer[0]), (sizeof(*hdr) + ping_if->packet_size), 0u,  &ping_if->target_addr, sizeof(ping_if->target_addr));
            ping_if->packet_count--;
           
            fnet_ping_if.send_time = fnet_timer_ticks();        
            
            ping_if->state = FNET_PING_STATE_WAITING_REPLY;
            break;
        /*===================================*/    
        case  FNET_PING_STATE_WAITING_REPLY:
            /* Receive data */
            
            received = fnet_socket_recvfrom(ping_if->socket_foreign, (fnet_uint8_t*)(&ping_if->buffer[0]), FNET_PING_BUFFER_SIZE, 0u, &addr, &addr_len );
            
            if(received > 0 )
            {
                fnet_uint16_t  checksum = 0u;
                
                hdr = (fnet_icmp_echo_header_t *)(ping_if->buffer);
                
                
                /* Check checksum.*/
#if FNET_CFG_IP4
                if(ping_if->family == AF_INET)
                {
                    checksum = fnet_checksum_buf(&fnet_ping_if.buffer[0], (fnet_size_t)received);
                }
                else
#endif  
#if 0 /* #if FNET_CFG_IP6  */ /* TBD case to receive from multicast address ff02::1*/
                if(ping_if->family == AF_INET6)
                {
                     checksum = fnet_checksum_pseudo_buf(&fnet_ping_if.buffer[0], 
                                                                (fnet_uint16_t)(received), 
                                                                IPPROTO_ICMPV6, 
                                                                ping_if->local_addr.sa_data,
                                                                ping_if->target_addr.sa_data, 
                                                                sizeof(fnet_ip6_addr_t));
                }
                else    
#endif                               
                {}
 
                /* Check header.*/
                if( checksum
                    ||(hdr->header.type != ((addr.sa_family == AF_INET) ? FNET_ICMP_ECHOREPLY: FNET_ICMP6_TYPE_ECHO_REPLY))
                    ||(hdr->identifier != FNET_CFG_PING_IDENTIFIER)
                    ||(hdr->sequence_number != fnet_htons(ping_if->sequence_number)) )
                {
                    goto NO_DATA;
                }     
                
                /* Call handler.*/
                if(ping_if->handler)   
                {
                    ping_if->handler(FNET_ERR_OK, ping_if->packet_count, &addr, ping_if->handler_cookie);
                }
                    
                if(ping_if->packet_count)
                {
                    ping_if->state = FNET_PING_STATE_WAITING_TIMEOUT;
                }
                else
                {
                    fnet_ping_release();              
                }
            }
            else if(received == FNET_ERR)
            {
                /* Call handler.*/
                if(ping_if->handler)
                {
                    fnet_error_t    sock_err ;
                    fnet_size_t     option_len;
                    
                    /* Get socket error.*/
                    option_len = sizeof(sock_err); 
                    fnet_socket_getopt(ping_if->socket_foreign, SOL_SOCKET, SO_ERROR, (fnet_uint8_t*)&sock_err, &option_len);
                                 
                    ping_if->handler(sock_err, ping_if->packet_count, FNET_NULL, ping_if->handler_cookie);
                }
               
                if(ping_if->packet_count)
                {
                    ping_if->state = FNET_PING_STATE_WAITING_TIMEOUT;
                }
                else
                {
                    fnet_ping_release();    
                }
            }
            else /* No data. Check timeout */
            {
NO_DATA:            
                if(fnet_timer_get_interval(fnet_ping_if.send_time, fnet_timer_ticks()) > fnet_ping_if.timeout_clk)
                {
                    /* Call handler.*/
                    if(ping_if->handler)   
                    {
                        ping_if->handler(FNET_ERR_TIMEDOUT, ping_if->packet_count, FNET_NULL, ping_if->handler_cookie);
                    }
                        
                    if(ping_if->packet_count)
                    {
                        ping_if->state = FNET_PING_STATE_SENDING_REQUEST;
                    }
                    else
                    {
                        fnet_ping_release();    
                    }
                }
            }
            break;
        /*===================================*/             
        case FNET_PING_STATE_WAITING_TIMEOUT:
            if(fnet_timer_get_interval(fnet_ping_if.send_time, fnet_timer_ticks()) > fnet_ping_if.timeout_clk)
            {
                ping_if->state = FNET_PING_STATE_SENDING_REQUEST;
            }
            break;

        default:
            break;  /* do nothing, avoid compiler warning "enumeration value not handled in switch" */
    }
}