?? nedk_example_web_server.c
字號:
// 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 + -