📄 50a731bed5b9001c180780c9bab1766d
字号:
return -1;
if((socket = accept(listen_socket,(struct sockaddr*)&rem,&len)) < 0)
{
//fprintf(stderr, "[http_handle_accept] accept failed (%d)\n", socket);
return socket;
}
(conn+i)->fd = socket;
(conn+i)->activity_time = alt_nticks();
return ret_code;
}
/*
* http_read_line()
*
* This routine will scan the RX data buffer for a newline, allowing us to
* parse an in-coming HTTP request line-by-line.
*/
int http_read_line(http_conn* conn)
{
alt_u8* lf_addr;
int ret_code = 0;
/* Find the Carriage return which marks the end of the header */
lf_addr = strchr(conn->rx_rd_pos, '\n');
if (lf_addr == NULL)
{
ret_code = -1;
}
else
{
/*
* Check that the line feed has a matching CR, if so zero that
* else zero the LF so we can use the string searching functions.
*/
if ((lf_addr > conn->rx_buffer) && (*(lf_addr-1) == '\r'))
{
*(lf_addr-1) = 0;
}
*lf_addr = 0;
conn->rx_rd_pos = lf_addr+1;
}
return ret_code;
}
/*
* http_process_headers()
*
* This routine looks for HTTP header commands, specified by a ":" character.
* We will look for "Connection: Close" and "Content-length: <len>" strings.
* A more advanced server would parse far more header information.
*
* This routine should be modified in the future not to use strtok() as its
* a bit invasive and is not thread-safe!
*/
int http_process_headers(http_conn* conn)
{
alt_u8* option;
alt_u8* orig_read_pos = conn->rx_rd_pos;
alt_u8* temp;
/* Skip the next section we'll chop with strtok(). Perl for Nios, anyone? */
if( (temp = strstr(conn->rx_rd_pos, ":")) )
{
conn->rx_rd_pos = temp + 1;
}
else
{
return -1;
}
option = strtok(orig_read_pos, ":");
if(stricmp(option,"Connection") == 0)
{
alt_u8 temp = *(option + 17);
*(option + 17) = 0;
if(stricmp((option+12), "close") == 0)
{
conn->close = 1;
}
*(option + 17) = temp;
}
else if (stricmp(option, "Content-Length") == 0)
{
conn->content_length = atoi(option+16);
}
return 0;
}
/*
* http_process_request()
*
* This routine parses the beginnings of an HTTP request to extract the
* command, version, and URI. Unsupported commands/versions/etc. will cause
* us to error out drop the connection.
*/
int http_process_request(http_conn* conn)
{
alt_u8* uri = 0;
alt_u8* version = 0;
alt_u8* temp = 0;
if( (temp = strstr(conn->rx_rd_pos, "GET")) )
{
conn->action = GET;
conn->rx_rd_pos = temp;
}
else if( (temp = strstr(conn->rx_rd_pos, "POST")) )
{
conn->action = POST;
conn->rx_rd_pos = temp;
}
else
{
//fprintf(stderr, "Unsupported (for now) request\n");
conn->action = UNKNOWN;
return -1;
}
/* First space char separates action from URI */
if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, " ")) )
{
conn->rx_rd_pos++;
uri = conn->rx_rd_pos;
}
else
{
return -1;
}
/* Second space char separates URI from HTTP version. */
if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, " ")) )
{
*conn->rx_rd_pos = 0;
conn->rx_rd_pos++;
version = conn->rx_rd_pos;
}
else
{
return -1;
}
/* Is this a HTTP version we support? */
if ((version == NULL) || (strncmp(version, "HTTP/", 5) != 0))
{
return -1;
}
if (!isdigit(version[5]) || version[6] != '.' || !isdigit(version[7]))
{
return -1;
}
/* Before v1.1 we close the connection after responding to the request */
if ( (((version[5] - '0')*10) + version[7] - '0') < 11)
{
conn->close = 1;
}
strcpy(conn->uri, uri);
return 0;
}
/*
* http_send_file_chunk()
*
* This routine will send the next chunk of a file during an open HTTP session
* where a file is being sent back to the client. This routine is called
* repeatedly until the file is completely sent, at which time the connection
* state will go to "COMPLETE". Doing this rather than sending the entire
* file allows us (in part) to multiplex between connections "simultaneously".
*/
int http_send_file_chunk(http_conn* conn)
{
int chunk_sent = 0, ret_code = 0, file_chunk_size = 0, result = 0;
alt_u8* tx_ptr;
if(conn->data_sent < conn->file_length)
{
file_chunk_size = hyread(conn->tx_buffer, 1,
MIN(HTTP_TX_BUF_SIZE, (conn->file_length - conn->data_sent)),
conn->file_handle);
tx_ptr = conn->tx_buffer;
while(chunk_sent < file_chunk_size)
{
result = send(conn->fd, tx_ptr, file_chunk_size, MSG_DONTWAIT);
/* Error - get out of here! */
if(result < 0)
{
//fprintf(stderr, "[http_send_file] file send returned %d\n", result);
ALT_DEBUG_ASSERT(1);
conn->state = RESET;
return result;
}
/*
* No errors, but the number of bytes sent might be less than we wanted.
*/
else
{
conn->activity_time = alt_nticks();
chunk_sent += result;
conn->data_sent += result;
tx_ptr += result;
file_chunk_size -= result;
}
} /* while(chunk_sent < file_chunk_size) */
} /* if(conn->data_sent < conn->file_length) */
/*
* We managed to send all of the file contents to the IP stack successfully.
* At this point we can mark our connection info as complete.
*/
if(conn->data_sent >= conn->file_length)
{
conn->state = COMPLETE;
}
return ret_code;
}
/*
* http_send_file_header()
*
* Construct and send an HTTP header describing the now-opened file that is
* about to be sent to the client.
*/
int http_send_file_header(http_conn* conn, const alt_u8* name, int code)
{
int result = 0, ret_code = 0;
alt_u8* tx_wr_pos = conn->tx_buffer;
fpos_t end, start;
const alt_u8* ext = strchr(name, '.');
tx_wr_pos += sprintf(tx_wr_pos, HTTP_VERSION_STRING);
switch(code)
{
/* HTTP Code: "200 OK\r\n" (we have opened the file successfully) */
case HTTP_OK:
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_OK_STRING);
break;
}
/* HTTP Code: "404 Not Found\r\n" (couldn't find requested file) */
case HTTP_NOT_FOUND:
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_NOT_FOUND_STRING);
break;
}
default:
{
//fprintf(stderr, "[http_send_file_header] Invalid HTTP code: %d\n", code);
conn->state = RESET;
return -1;
break;
}
}
/* Handle the various content types */
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE);
if (!strcasecmp(ext, ".html"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_HTML);
}
else if (!strcasecmp(ext, ".jpg"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_JPG);
}
else if (!strcasecmp(ext, ".gif"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_GIF);
}
else if (!strcasecmp(ext, ".js"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_JS);
}
else if (!strcasecmp(ext, ".css"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_CSS);
}
else if (!strcasecmp(ext, ".swf"))
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_TYPE_SWF);
}
else
// ++ hychu
{
tx_wr_pos += sprintf(tx_wr_pos, "application/x-javascript\r\n");
} // of unknown content type
#if 0
{
//fprintf(stderr, "[http_send_file] Unknown content type: \"%s\"\n", ext);
conn->state = RESET;
ALT_DEBUG_ASSERT(1);
return -1;
}
#endif
/* Get the file length and stash it into our connection info */
hyseek(conn->file_handle, 0, SEEK_END);
hygetpos(conn->file_handle, &end);
hyseek(conn->file_handle, 0, SEEK_SET);
hygetpos(conn->file_handle, &start);
conn->file_length = end - start;
/* "Content-Length: <length bytes>\r\n" */
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CONTENT_LENGTH);
tx_wr_pos += sprintf(tx_wr_pos, "%d\r\n", conn->file_length);
/*
* 'close' will be set during header parsing if the client either specified
* that they wanted the connection closed ("Connection: Close"), or if they
* are using an HTTP version prior to 1.1. Otherwise, we will keep the
* connection alive.
*
* We we send a specified number of files in a single keep-alive connection,
* we'll also close the connection. Its best to be polite and tell the client,
* though.
*/
if(!conn->keep_alive_count)
{
conn->close = 1;
}
if(conn->close)
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CLOSE);
}
else
{
tx_wr_pos += sprintf(tx_wr_pos, HTTP_KEEP_ALIVE);
}
/* "\r\n" (two \r\n's in a row means end of headers */
tx_wr_pos += sprintf(tx_wr_pos, HTTP_CR_LF);
/* Send the reply header */
result = send(conn->fd, conn->tx_buffer, (tx_wr_pos - conn->tx_buffer),
MSG_DONTWAIT);
if(result < 0)
{
//fprintf(stderr, "[http_send_file] header send returned %d\n", result);
conn->state = RESET;
return result;
}
else
{
conn->activity_time = alt_nticks();
}
return ret_code;
}
/*
* http_find_file()
*
* Try to find the file requested. If nothing is requested you get /index.html
* If we can't find it, send a "404 - Not found" message.
*/
int http_find_file(http_conn* conn)
{
alt_u8 filename[256];
int ret_code = 0;
strncpy( filename, ALTERA_RO_ZIPFS_NAME, strlen(ALTERA_RO_ZIPFS_NAME));
/* URI of "/" means get the default, usually index.html */
if ( (conn->uri[0] == '/') && (conn->uri[1] == '\0') )
{
strcpy(filename+strlen(ALTERA_RO_ZIPFS_NAME), HTTP_DEFAULT_FILE);
}
else
{
strcpy( filename+strlen(ALTERA_RO_ZIPFS_NAME), conn->uri);
}
// ++ hychu
/* Try to open the file */
// was: conn->file_handle = fopen(filename, "r");
//if(!strncmp(filename, "file?", 5))
conn->file_handle = hyopen(filename, "r");
//else conn->file_handle = fopen(filename, "r");
// -- hychu
/* Can't find the requested file? Try for a 404-page. */
if (conn->file_handle == NULL)
{
strcpy(filename, ALTERA_RO_ZIPFS_NAME);
strcpy(filename+strlen(ALTERA_RO_ZIPFS_NAME), HTTP_NOT_FOUND_FILE);
conn->file_handle = hyopen(filename, "r");
/* We located the specified "404: Not-Found" page */
if (conn->file_handle != NULL)
{
ALT_DEBUG_ASSERT(fd != NULL);
ret_code = http_send_file_header(conn, filename, HTTP_NOT_FOUND);
}
/* Can't find the 404 page: This likely means there is no file system */
else
{
//fprintf(stderr, "Can't open the Not found file.\n");
//fprintf(stderr, "Have you programmed the filing system into flash?\n");
send(conn->fd,(void*)canned_http_response,strlen(canned_http_response),0);
hyclose(conn->file_handle);
conn->state = RESET;
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -