LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
netconn_fs.c
Go to the documentation of this file.
1 /*
2 * @brief Netconn implementation that gets data from filesystem
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include "lwip/opt.h"
35 #include "lwip/arch.h"
36 #include "lwip/api.h"
37 #include "fs.h"
38 
39 #include "lpc43xx_dualcore_config.h"
40 #include "httpserver-netconn.h"
41 #include "ipc_example.h"
42 
43 #if LWIP_NETCONN
44 
45 #ifndef HTTPD_DEBUG
46 #define HTTPD_DEBUG LWIP_DBG_OFF
47 #endif
48 
49 /* Default file content incase a valid filesystem is not present */
50 const static char http_html_hdr[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
51 const static char http_index_html[] = "<html><head><title>Congrats!</title></head><body><h1>Welcome to our lwIP HTTP server!</h1><p>This is a small test page, served by httpserver-netconn.</body></html>";
52 
53 /* Dynamic header generation based on Filename */
54 extern int GetHTTP_Header(const char *fName, char *buff);
55 
56 #ifndef CRLF
57 #define CRLF "\r\n"
58 #endif
59 
60 /* Function to check if the requested method is supported */
61 static int supported_method(const char *method)
62 {
63  if (strncmp(method, "GET", 3) == 0)
64  return 1;
65  if (strncmp(method, "POST", 4) == 0)
66  return 1;
67  return 0;
68 }
69 
70 /* Function to extract version information from URI */
71 static uint32_t get_version(const char *vstr)
72 {
73  int major = 0, minor = 0;
74  sscanf(vstr, "HTTP/%d.%d", &major, &minor);
75  return (major << 16) | minor;
76 }
77 
79 static void
80 http_server_netconn_serve(struct netconn *conn)
81 {
82  struct netbuf *inbuf;
83  char *buf, *tbuf;
84  u16_t buflen;
85  struct fs_file *fs;
86  err_t err;
87  static uint8_t file_buffer[1024];
88  int len;
89  uint32_t req_ver;
90 
91  /* Read the data from the port, blocking if nothing yet there.
92  We assume the request (the part we care about) is in one netbuf */
93  err = netconn_recv(conn, &inbuf);
94 
95  if (err != ERR_OK) return;
96 
97  netbuf_data(inbuf, (void**)&buf, &buflen);
98  if (buflen < 5 || strstr(buf, CRLF) == NULL) {
99  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Invalid Request Line\r\n"));
100  goto close_and_exit;
101  }
102 
103  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("HTTPD: Got URI %s\r\n", buf));
104 
105  tbuf = strchr(buf, ' ');
106  if (tbuf == NULL) {
107  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Parse error in Request Line\r\n"));
108  goto close_and_exit;
109  }
110 
111  *tbuf++ = 0;
112  if (!supported_method(buf)) {
113  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Un-supported method: %s\r\n", buf));
114  goto close_and_exit;
115  }
116  buf = tbuf;
117  tbuf = strchr(buf, ' ');
118  if (tbuf == NULL) {
119  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Version string not found: %s\r\n", buf));
120  } else {
121  *tbuf++ = 0;
122  req_ver = get_version(tbuf);
123  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("HTTPD: Request version %d.%d\r\n",
124  req_ver >> 16, req_ver & 0xFFFF));
125  }
126 
127  tbuf = strchr(buf, '?');
128  if (tbuf != NULL) {
129  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Arguements %s in URI ignored\r\n", tbuf));
130  *tbuf++ = 0;
131  }
132  if (strlen(buf) == 1 && *buf == '/') {
133  fs = fs_open("/index.htm");
134  if (fs == NULL)
135  fs = fs_open("/index.html");
136  if (fs == NULL) {
137  /* No home page, send if from buffer */
138  netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);
139  netconn_write(conn, http_index_html, sizeof(http_index_html)-1, NETCONN_NOCOPY);
140  goto close_and_exit;
141  }
142  } else {
143  fs = fs_open(buf);
144  }
145  if (fs == NULL) {
146  int len;
147  LWIP_DEBUGF(HTTPD_DEBUG, ("HTTPD: Unable to open file[%s]\r\n", buf));
148  len = GetHTTP_Header(NULL, (char *)file_buffer);
149  netconn_write(conn, file_buffer, len, NETCONN_NOCOPY);
150  goto close_and_exit;
151  }
152 
153  /***
154  * FIXME: There is a possible race condition while accessing
155  * file_buffer, must use a mutex to protect it.
156  **/
157  if (fs->http_header_included)
158  /* Send the header */
159  netconn_write(conn, fs->data, fs->index, NETCONN_NOCOPY);
160 
161  /* Read the file now */
162  while ((len = fs_read(fs, (char *)file_buffer, sizeof(file_buffer))) > 0) {
163  netconn_write(conn, file_buffer, len, NETCONN_NOCOPY);
164  }
165 
166 close_and_exit:
167  fs_close(fs);
168  /* Close the connection (server closes in HTTP) */
169  netconn_close(conn);
170 
171  /* Delete the buffer (netconn_recv gives us ownership,
172  so we have to make sure to deallocate the buffer) */
173  netbuf_delete(inbuf);
174 }
175 
177 static void
178 http_server_netconn_thread(void *arg)
179 {
180  struct netconn *conn, *newconn;
181  err_t err;
182  LWIP_UNUSED_ARG(arg);
183 
184  /* Create a new TCP connection handle */
185  conn = netconn_new(NETCONN_TCP);
186  LWIP_ERROR("http_server: invalid conn", (conn != NULL), return;);
187 
188  /* Bind to port 80 (HTTP) with default IP address */
189  netconn_bind(conn, NULL, 80);
190 
191  /* Put the connection into LISTEN state */
192  netconn_listen(conn);
193 
194  do {
195  err = netconn_accept(conn, &newconn);
196  if (err == ERR_OK) {
197  /* Push the remote IP info to other Core */
198  ip_addr_t remote_ip;
199  u16_t port_num;
200  err = netconn_getaddr(newconn, &remote_ip, &port_num, 0);
201  if(err == ERR_OK) {
202  ipcex_msgPush(IPCEX_ID_EMWIN, remote_ip.addr);
203  }
204 
205  http_server_netconn_serve(newconn);
206  netconn_delete(newconn);
207  }
208  } while(err == ERR_OK);
209  LWIP_DEBUGF(HTTPD_DEBUG,
210  ("http_server_netconn_thread: netconn_accept received error %d, shutting down",
211  err));
212  netconn_close(conn);
213  netconn_delete(conn);
214 }
215 
216 /*********************************************************************/
224 void
225 http_server_netconn_init()
226 {
227  sys_thread_new("http_server_netconn", http_server_netconn_thread, NULL, DEFAULT_THREAD_STACKSIZE + 128, DEFAULT_THREAD_PRIO);
228 }
229 
230 #endif /* LWIP_NETCONN*/