⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nedk_example_web_server.c

📁 包括基于Cyclone1C20芯片NiosII软件开发的各种模块的测试例子
💻 C
📖 第 1 页 / 共 2 页
字号:
// file: nedk_web_server.c
//
// This is a very simple web server
// that can be modified to include
// several kinds of pages in a "wosfs"
// file directory. (File structure
// smashed into flash memory, immutable.)
//
// dvb@altera.com 2002
//
// ex:set tabstop=4:
//

#include "excalibur.h"
#include "plugs.h"
#include "wosfs.h"
#include "plugs_example_designs.h"


#define k_http_port 80
#define k_string_length 256

#define k_tcp_timeout 5000 // milliseconds

typedef struct
	{
	int tcp_plug_handle;
	int inquiry_number;
	int button_presses[4];

	long tcp_opened_time; // So we can time out the connection
	                      // in case of a dangled-open connect.
	} globals;

static globals g; // (starts life as zeroes of course)

// +---------------------------------
// | prototypes

static int r_handle_http_request(int plug_handle,unsigned char *message, int message_length);
static void r_get_cgi_param(char *url_and_args,char *parameter, char *value_out);
static void r_set_7_pattern(int control);
static void r_increment_button_counts(void);
static char *r_printable_string(char *s);
static int r_get_html_from_wosfs(char *url,char *html_out,int *html_length_out);
static int r_get_html_404(char *url,char *html_out);
static int r_substitute_string(char *fmt,char *s);
static int r_get_html_dynamically(char *url,char *url_and_args,char *html_out);

static int r_tcp_proc(int plug_handle,
		void *context,
		ns_plugs_packet *p,
		void *payload,
		int payload_length);

static int r_listen_proc(int plug_handle,
		void *context,
		host_32 remote_ip_address,
		host_16 remote_port);

static int r_start_listening(void);

// +---------------------------------
// | meat



int main(void)
	{
	int result;

	printf("[Xnedk_example_web_server] starting\n");

	// |
	// | Initialize the plugs library
	// |
	//
	result = nr_plugs_initialize
			(
			0, 0,
			__adapter__,
			__adapter_irq__,
			__adapter_struct_addr__
			);

	if(result)
		goto error_exit;

	// |
	// | Print the IP address we're using
	// |
		{
		ns_plugs_network_settings settings;

		result = nr_plugs_get_settings(0,&settings);

		printf("[nedk_example_web_server] IP address = ");
		nr_plugs_print_ip_address(settings.ip_address);
		printf("\n");
		}

	result = nr_plugs_create
			(
			&g.tcp_plug_handle, // | Plug to create
			ne_plugs_tcp,       // | Kind of plug (tcp connection)
			k_http_port,        // | Port to listen on
			r_tcp_proc,         // | To call with incoming data
			0,                  // | Context for plug callback
			0                   // | Flags for plug (none)
			);
	if(result)
		goto error_exit;

	// |
	// | Accept incoming connections
	// |

	result = r_start_listening();
	if(result)
		goto error_exit;
	
	// |
	// | Main loop: spin through here forever
	// | All this application does is serve
	// | web pages and blink the 7-segment
	// | display a little. If there were other tasks
	// | to do, like operating your factory
	// | equipment or something, you could
	// | have it running here in this main
	// | event loop (if timing weren't important),
	// | or as a timer task.
	// |

	while(1)
		{
		nr_plugs_idle();
		r_set_7_pattern(0);

		// |
		// | Check if tcp connection's been opened too long
		// |

		if( g.tcp_opened_time
				&& ((nr_timer_milliseconds() - g.tcp_opened_time) > k_tcp_timeout) )
			{
			char *s = "nedk_web_server: Connection timing out. Bye.\n";
			result = nr_plugs_send(g.tcp_plug_handle,s,strlen(s),0);
			result = r_start_listening();
			}
		}
	
	// |
	// | Only get here on an error condition...
	// |

error_exit:
	nr_plugs_print_error_message("[nedk_example_web_server]", result);
	return result;
	}

// +--------------------------------------
// | r_set_7_pattern
// |
// | Advance the little blinky-pattern that
// | moves around the 7-segment display
// |
// | Control Values
// |  0 advance tick
// |  1 all segments on
// |

#define k_7_time 80 // mSec between frames
static void r_set_7_pattern(int control)
	{
	long x;
	static long last_time = 0;
	static long current_step = 0;
	static long d_pattern[] =  // 8 steps in the pattern
		{
		0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,  // outer edge
		0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xffffbfff,
		};
	
	x = nr_timer_milliseconds();
	if(x - last_time > k_7_time)
		{
		// |
		// | Time enough to update the LED?
		// |

		last_time = x;

		current_step = (current_step + 1) & 7;
		}

	if(control == 1)
		x = 0;
	else
		x = d_pattern[current_step];

	na_seven_seg_pio->np_piodirection = 0xffff;
	na_seven_seg_pio->np_piodata = x;
	}


// +----------------------------------
// | r_start_listening
// |
// | This routine closes the current tcp
// | connection (if any) and starts listening
// | again.
// |

static int r_start_listening(void)
	{
	int result;

	printf("\nlistening on port %d at t = %8d\n",k_http_port,nr_timer_milliseconds() );

	result = nr_plugs_listen(g.tcp_plug_handle,r_listen_proc,0);
	g.tcp_opened_time = 0; // so it looks like we're "closed"

	return result;
	}


// +----------------------------------
// | r_listen_proc
// |
// | This is a plugs listener callback proc.
// | It gets called when a remote client
// | requests a connection. We always accept
// | the connection, but we do take the opportunity
// | to note the time of the connection. Then, in
// | the main loop, we see if the connection has
// | been left open too long, and maybe force it closed.

static int r_listen_proc(int plug_handle,
		void *context,
		host_32 remote_ip_address,
		host_16 remote_port)
	{

	g.tcp_opened_time = nr_timer_milliseconds();

	printf("[tcp_listen_proc] Accepted connection from ");
	nr_plugs_print_ip_address(nr_h2n32(remote_ip_address));
	printf(" port %d at t = %8d\n",remote_port,g.tcp_opened_time);

	return 0;
	}

// +----------------------------------
// | r_tcp_proc
// |
// | This is a plugs receive callback proc.
// | It gets called when a remote client connects
// | to our web server and sends a request. We
// | assume that the request arrives in a single
// | packet (or, at least, that the first line
// | of it, containing the URL, does).
// |
// | If the payload length is zero, this means
// | for a tcp_plug that the remote network device
// | has disconnected from us, and we listen for
// | the next connection.
// |


static int r_tcp_proc
		(
		int plug_handle,
		void *context,
		ns_plugs_packet *p,
		void *payload,
		int payload_length
		)
	{
	unsigned char *w;
	int i;
	int c;

	if(payload_length)
		{
		// |
		// | Incoming message, it must be a http request
		// | We let the http_server handle this request.
		// |
		
		r_handle_http_request(plug_handle,payload, payload_length);
		}
	else
		{
		// |
		// | Zero-length payload means "they disconnected",
		// | so, begin listening again on same port.
		// |

		r_start_listening();
		}

go_home:
	return 0;
	}

// +-------------------------------------------
// | r_handle_http_request(plug_handle, http_request, http_request_length)
// |
// | Actually, we just assume that the message
// | is, in fact, an HTTP request. An HTTP
// | request is of the form:
// |
// |    GET <url>[ <http-version>](CR)(LF)
// |
// | It may also continue with more information
// | on subsequent lines, each of the form:
// |
// |    <variable>: <value>
// |
// | And eventually ends with two CR-LF's.
// | But we ignore everything past the first
// | line here.
// |
// | To reply, we send a status line and 
// | a content-type, followed by to CRLF's and the HTML.
// |
// |    HTTP/1.1 200 OK
// |    Content-type: <content-type>
// |
// |    <HTML>
// |
// | The content type is either "text/html" or "image/gif".
// | We presume that if the content comes from WOSFS,
// | and the last letter of the filename is 'f', then it's
// | a GIF image.
// |

static int r_handle_http_request(int plug_handle,unsigned char *message, int message_length)
	{
	unsigned char *message_end;
	unsigned char *w;
	int i;
	int result = 0;
	char url_and_args[k_string_length];
	char url[k_string_length];
	int url_and_args_length;

	r_set_7_pattern(1); // | flash the 7-seg display

	++g.inquiry_number;

	message_end = message + message_length;
	w = message;

	// |
	// | Find the url_and_args portion of the packet, by looking for the
	// | first space (just after the word "GET").
	// |

	while(w < message_end && *w++ != ' ')
		;

	w = w + 1; // | omit the omnipresent leading slash
	url_and_args_length = 0;
	
	// |
	// | Copy the URL and any CGI arguments into url_and_args.
	// | look for the end of the URL and CGI parameters as a ' ' or crlf
	// |

	while(w < message_end && *w > ' ') // | break on blank or ctrl char
		url_and_args[url_and_args_length++] = *w++;

	url_and_args[url_and_args_length] = 0;  // | Terminate string

	// |
	// | Asking for the root of the server, "/", means
	// | they want "index.html".
	// |

	if(url_and_args_length == 0) // empty url?
		{
		strcpy(url_and_args,"index.html");
		url_and_args_length = strlen(url_and_args);
		}

	r_get_cgi_param(url_and_args,0,url); // null param = URL

printf("\n");
printf("[r_handle_http_request] url_and_args_length = %d\n", url_and_args_length);
printf("[r_handle_http_request] url_and_args = %s\n", url_and_args);
printf("[r_handle_http_request] url = \"%s\"\n",r_printable_string(url));

	// |
	// | We've extracted the url with arguments, and just the url
	// | by itself. We'll now look for a file, a dynamic page, or a 404 error.

		{
		char html_response[30000];
		int html_response_length = 0;
		char *http_result_code_and_message;
		char *http_content_type;
		int file_index;

		// |
		// | Default to 200 OK status, and check last char of URL for content type
		// |

		http_result_code_and_message = "200 OK";
		http_content_type = url[strlen(url) - 1] == 'f'
				? "image/gif" : "text/html";
		html_response[0] = 0;

		// |
		// | Try to get the file from wosfs
		// |

		result = r_get_html_from_wosfs(url,html_response,&html_response_length);

		// |
		// | If not wosfs, try dynamic
		// |

		if(result)
			result = r_get_html_dynamically(url,url_and_args,html_response);

		// |
		// | And if even that fails, call our
		// | error generation routine.
		// |
		
		if(result)
			{
			http_result_code_and_message = "404 File Not Found";
			http_content_type = "text/html";
			r_get_html_404(url,html_response);
			result = 0; // above routine not allowed to fail
			}


		// |
		// | If nobody filled out the html_response_length,
		// | get it as a string length.
		// |
		if(html_response_length == 0)
			html_response_length = strlen(html_response);

printf("[r_handle_http_request] sending %d bytes of html out.\n",html_response_length);
			

		// |
		// | Lastly, send the HTTP response.
		// | The plugs library will not automatically
		// | break up the packet into ethernet-legal
		// | chunks, so we do it here.
		// |

			{
			char http_intro[k_string_length];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -