http.c
来自「一个vxworks下http任务socket层的实现代码」· C语言 代码 · 共 850 行 · 第 1/2 页
C
850 行
#include "vxWorks.h"
#include "stdio.h"
#include "ioLib.h"
#include "inetLib.h"
#include "include/sysdef.h"
#include "maintain/lpt.h"
#include "http.h"
//全局变量
HTTP_FILE_TABLE httpFileTable;
HTTP_ACTION_TABLE actionTable;
/*****************************************************************************************
HTTP模块与调用者的接口
1、addHttpFile 输入页面名称和创建此页面的回调函数
2、addHttpAction 输入动作名称和解析参数且执行动作的回调函数
*****************************************************************************************/
STATUS addHttpAction(UINT8 * pActionName, void * pFunction)
{
UINT16 i;
if(pActionName==NULL || pFunction==NULL)
{
lpt(PT_WARN,"param is NULL\n");
return ERROR;
}
if(actionTable.currentNo >= MAX_HTTP_ACTION)
{
lpt(PT_WARN,"http file table is full!\n");
return FALSE;
}
//Check the exist actions.If there already have been a same name action, return
for(i=0; i<actionTable.currentNo; i++)
{
if(strcmp(actionTable.actions[i].actionName, pActionName) == 0)
{
lpt1(PT_WARN,"action file %s is already exist\n",pActionName);
return FALSE;
}
}
actionTable.actions[actionTable.currentNo].onPostFunction = (onPostFunctionT)pFunction;
strcpy(actionTable.actions[actionTable.currentNo].actionName, pActionName);
actionTable.currentNo++;
return TRUE;
}
/* 记录安装HTTP文件索引 */
STATUS addHttpFile(UINT8 * pFileName, void * pFunction)
{
UINT32 i;
if (pFileName == NULL || pFunction == NULL)
{
lpt(PT_WARN, "addHttpFile inputerror \n");
return FALSE;
}
if(httpFileTable.currentNo == MAX_HTTP_FILE)
{
printf("Http file table is full!\n");
return FALSE;
}
//Check the exist files.If there already have been a same name file, return
for(i=0; i<httpFileTable.currentNo; i++)
{
if(strcmp(httpFileTable.files[i].fileName, pFileName) == 0)
{
return FALSE;
}
}
httpFileTable.files[httpFileTable.currentNo].createHtmlPage = (createHtmlPageT)pFunction;
strcpy(httpFileTable.files[httpFileTable.currentNo].fileName, pFileName);
httpFileTable.currentNo++;
//printf("addHttpFile:%s\n", pFileName);
return TRUE;
}
/*创建网页出现的状态*/
enum
{
// 一切正常,对GET和POST请求的应答文档跟在后面。
HTTP_STATUS_OK = 0,
// 没有新文档,浏览器应该继续显示原来的文档。
// 如果用户定期地刷新页面,而Servler可以确定用户文档足够新,这个状态代码是很有用的。
HTTP_STATUS_NOCONTENT, // 1
// 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
HTTP_STATUS_MOVEDPERM, // 2
// 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。
HTTP_STATUS_MOVEDTEMP, // 3
// 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。
// 服务器告诉客户,原来缓冲的文档还可以继续使用。
HTTP_STATUS_NOTMODIFIED, // 4
// 请求出现语法错误。
HTTP_STATUS_BADREQUEST, // 5
// 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,
// 浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
HTTP_STATUS_UNAUTHORIZED, // 6
// 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。
HTTP_STATUS_FORBIDDEN, // 7
// 无法找到指定位置的资源。这也是一个常用的应答。
HTTP_STATUS_NOTFOUND, // 8
// 服务器遇到了意料不到的情况,不能完成客户的请求。
HTTP_STATUS_SERVERERROR, // 9
// 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。
HTTP_STATUS_NOTIMPLEMENTED, // 10
HTTP_STATUS_END,
};
// HTTP状态描述,必须与E_HTTP_STATE对应。
static char httpStateDes[HTTP_STATUS_END][50] =
{
{"HTTP/1.1 200 OK\r\n"},
{"HTTP/1.1 204 No Content\r\n"},
{"HTTP/1.1 301 Moved Permanently\r\n"},
{"HTTP/1.1 302 Moved Temporarily\r\n"},
{"HTTP/1.1 304 Not Modified\r\n"},
{"HTTP/1.1 400 Bad Request\r\n"},
{"HTTP/1.1 401 Unauthorized\r\n"},
{"HTTP/1.1 403 Forbidden\r\n",},
{"HTTP/1.1 404 Not Found\r\n"},
{"HTTP/1.1 500 Internal Server Error\r\n"},
{"HTTP/1.1 501 Not Implemented\r\n"},
};
HTTP_CTRL_INFO httpCtrlInfo;
// HTTP回送应答状态
void httpSndState(int state)
{
if (state >= HTTP_STATUS_END)
{
lpt1(PT_WARN, "http state %d error \n", state);
return;
}
send(httpCtrlInfo.connectSock, httpStateDes[state], strlen(httpStateDes[state]), 0);
}
//采用标准的头格式,从而支持不同版本的IE和多种文件,如voip.sys,voip.log可以直接下载
void httpSndFileHead(char * fileName)
{
char stringBuf[200];
char fileType[30];
memset(fileType,0,sizeof(fileType));
if(fileName==NULL)
{
strcpy(fileType,"text/html");//默认的方式
}
/*******************XML和其样式表**********************/
else if((strstr(fileName, ".xml") !=0) || (strstr(fileName,".xsl" ) != 0))
{
strcpy(fileType,"text/xml");
}
/*******************html和其样式表**********************/
else if((strstr(fileName, ".html") !=0) ||(strstr(fileName, ".htm") !=0))
{
strcpy(fileType,"text/html");
}
else if(strstr(fileName, ".css") !=0)
{
strcpy(fileType,"text/css");
}
/*******************javascript**********************/
else if(strstr(fileName, ".js") !=0)
{
strcpy(fileType,"application/x-javascript");
}
/*******************常见的图象格式**********************/
else if(strstr(fileName, ".ico") !=0)
{
strcpy(fileType,"image/x-icon");
}
else if((strstr(fileName, ".jpg") !=0) || (strstr(fileName,".jpeg" ) != 0) || (strstr(fileName,".jpe" ) != 0))
{
strcpy(fileType,"image/jpeg");
}
else if(strstr(fileName, ".bmp") !=0)
{
strcpy(fileType,"image/bmp");
}
else if(strstr(fileName, ".gif") !=0)
{
strcpy(fileType,"image/gif");
}
else
{
strcpy(fileType,"application/x-msdownload");
}
memset(stringBuf, 0, sizeof(stringBuf));
strcpy(stringBuf, "Server: KEDACOM VoIP 4.0\r\n");
strcat(stringBuf,"Content-Type: ");
strcat(stringBuf, fileType);
strcat(stringBuf, "\r\n\r\n");
send(httpCtrlInfo.connectSock, stringBuf, strlen(stringBuf), 0);
}
//目前在发送大量数据的时候会出现发不成功的问题
void httpSndContent(char * buf, int len)
{
int i;
int sendSuccessBytes, sendOnceBytes, rv;
if (buf == NULL || len < 0)
{
lpt(PT_WARN, "httpSndContent input error \n");
return;
}
sendSuccessBytes = 0;
while (sendSuccessBytes < len)
{
sendOnceBytes = len - sendSuccessBytes;
if (sendOnceBytes > 1024)
{
// 一次不能发的太多
sendOnceBytes = 1024;
}
//rv可能发送失败,连续5次发包
for(i=0;i<5;i++)
{
rv = send(httpCtrlInfo.connectSock,buf+sendSuccessBytes,sendOnceBytes,0);
if(rv>0)
{
break;
}
else
{
taskDelay(i*5+10);
}
}
if(i==5)
{
lpt(PT_WARN ,"send error \n");
return;
}
sendSuccessBytes+=rv;
if (rv < sendOnceBytes)
{
// 实际发送成功的字节数小于准备发送的字节数,说明网络太忙,需延迟一下。
taskDelay(6);
}
}
}
//发送异常情况的页面------通常用到的几种
void httpSndNotFindFile(void)
{
UINT8 content[120];
memset(content,0,sizeof(content));
strcpy(content,"<html><head>");
strcat(content,"<title>Object Not Found</title></head>");
strcat(content,"<body><h1>HTTP/1.1 404 Object Not Found</h1></body>");
strcat(content,"</html>");
httpSndState(HTTP_STATUS_NOTFOUND);
httpSndFileHead("httperr404.html");
httpSndContent(content,strlen(content));
}
void httpSndNotAuthorization(void)
{
UINT8 stringBuf[200];
memset(stringBuf,0,sizeof(stringBuf));
strcpy(stringBuf, "Server: KEDACOM VoIP 4.0\r\n");
//strcat(stringBuf,"WWW-Authenticate: Negotiate\r\n");//对于NT的域认证,我们正常用不到
//strcat(stringBuf,"WWW-Authenticate: NTLM\r\n");
strcat(stringBuf,"WWW-Authenticate: Basic realm=苏 州 科 达 科 技\r\n");
strcat(stringBuf,"Cache-control: no-cache\r\n");
httpSndState(HTTP_STATUS_UNAUTHORIZED);
httpSndContent(stringBuf,strlen(stringBuf));
}
void httpSndForbiddenAccess(void)
{
UINT8 content[120];
memset(content,0,sizeof(content));
strcpy(content,"<html><head>");
strcat(content,"<title>Directory Listing Denied</title></head>");
strcat(content,"<body><h1>Directory Listing Denied</h1>This Virtual Directory does not allow contents to be listed.</body>");
strcat(content,"</html>");
httpSndState(HTTP_STATUS_FORBIDDEN);
httpSndFileHead("httperr403.html");
httpSndContent(content,strlen(content));
}
//action table fuction
void initActionTable(void)
{
UINT32 i;
memset(&actionTable, 0, sizeof(actionTable));
for(i=0; i<MAX_HTTP_ACTION; i++)
{
actionTable.actions[i].onPostFunction = NULL;
}
}
/* 初始化WEB服务要用到的文件索引 */
void initHttpFileTable(void)
{
UINT32 i;
memset(&httpFileTable, 0, sizeof(httpFileTable));
for(i=0; i<MAX_HTTP_FILE; i++)
{
httpFileTable.files[i].createHtmlPage = NULL;
}
}
//启动HTTP服务,创建SOCKET
int httpServListen(void )
{
struct sockaddr_in local;
int s;
const int on = 1;
local.sin_port = 80;
local.sin_addr.s_addr = htonl (INADDR_ANY);
if((s = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
{
printf("startHTTP socket:");
printErrno(errno);
return ERROR;
}
if(s<=0)
{
printf("socket call failed\n");
return ERROR;
}
if(bind(s, (struct sockaddr *) &local, sizeof(local)) == ERROR)
{
printf("startHTTP bind:");
printErrno(errno);
if(close(s) == ERROR)
{
printf("startHTTP close:");
printErrno(errno);
return ERROR;
}
return ERROR;
}
if(listen(s, 5) == ERROR )
{
printf("startHTTP listen:");printErrno(errno);
if(close(s) == ERROR)
{
printf("startHTTP listen close:");printErrno(errno);
return ERROR;
}
return ERROR;
}
return s;
}
int getHttpAction(UINT8 * pActionName)
{
UINT16 i;
if(pActionName==NULL)
{
lpt(PT_WARN,"param is NULL\n");
return -1;
}
if(pActionName == NULL)
{
lpt(PT_WARN,"param is NULL\n");
return -1;
}
for(i=0; i<actionTable.currentNo; i++)
{
if(strcmp(actionTable.actions[i].actionName, pActionName) == 0)
{
return i;
}
}
lpt1(PT_WARN,"can not find action %s\n",pActionName);
return -1;
}
int getHttpFile(UINT8 * pFileName)
{
UINT32 i;
if (pFileName == NULL)
{
lpt(PT_WARN, "getHttpFile input is null \n");
return ERROR;
}
for(i=0; i<httpFileTable.currentNo; i++)
{
if(strcmp(httpFileTable.files[i].fileName, pFileName) == 0)
{
return i;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?