📄 chttpsvr.cpp
字号:
/*******************************************************************
* cHttpsvr.cpp
* DESCRIPTION:chttpsvr类的实现文件
*
* AUTHOR:yyc
*
* HISTORY:
*
* DATE:2002-6-28
*
*******************************************************************/
#include "cHttpsvr.h"
#include <memory>
#include <cstdio>
#include "logout.h"
RW_DEFINE_LOG("cHttpsvr")
using namespace std;
using namespace yyc;
/**
* 添加URL和此URL的处理函数
*
* @param url
* @param pfunc
*
* @return
*/
int cHttpsvr::add_url(const char *url,FUNC_DOREQ *pfunc)
{
int retv=0;
if (url==NULL||url[0]==0||pfunc==NULL) return ENULL_SOCK;
m_mapUrlfunc[url]=pfunc;
retv=m_mapUrlfunc.size();
return retv;
}
//得到某个url的处理地址
FUNC_DOREQ *cHttpsvr::get_url_addr(const char *url)
{
FUNC_DOREQ *pfunc=NULL;
if(m_mapUrlfunc.count(url)>=1)
{
pfunc=m_mapUrlfunc[url];
}
return pfunc;
}
/**
* 从MAP表中删除某个URL的处理
*
* @param url
*
* @return
*/
int cHttpsvr::del_url(const char *url)
{
int retv=0;
if (url==NULL||url[0]==0) return ENULL_SOCK;
m_mapUrlfunc.erase(url);
retv=m_mapUrlfunc.size();
return retv;
}
/**
* 启动http服务
*
* @param port_p http服务端口,如果为0,则系统自动分配
*
* @return http服务侦听端口,<0发生错误
*/
int cHttpsvr::start(int iPort)
{
int retv=0;
if (iPort>0) m_iPort=iPort;
if (m_pSocksvr!=NULL)
{
retv=m_pSocksvr->listen(m_iPort);
}
else
retv=ENULL_SOCK;
if(retv>=0)
{
m_iPort=retv;
RW_LOG_DEBUG("HTTP server have started,port=%d\n",retv);
}
else
{
RW_LOG_DEBUG("HTTP server start failed,errno=%d\n",retv);
}
return retv;
}
/**
* 停止http server
*
* @return
*/
int cHttpsvr::stop()
{
if (m_pSocksvr!=NULL)
m_pSocksvr->close();
m_reqmap.clear();
RW_LOG_DEBUG("HTTP server have stopped,port=%d\n",m_iPort);
return 0;
}
/**
* socket接收数据处理
* 判断是否为http请求,创建HTTPREQ对象
* 处理http请求,调用设定的URL处理函数
* 此函数为csocket对象的回调函数
*
* @param buf 收到数据的指针
* @param len 收到数据大小
* @param args 相关联的csocket对象指针
*
* @return 详见csocket的接收数据处理回调函数说明
*/
int cHttpsvr::do_browserreq(char *buf,int len,cSocket *psock)
{
int ret;
cHttpsvr * phttpsvr=NULL;
cHttpreq * phttpreq=NULL;
if(NULL==buf||len<=0) return 1;//错误,关闭此socket
if (NULL==psock) return 1;//错误,关闭此socket
phttpsvr=(cHttpsvr *)psock->get_pArgs();
if (NULL==phttpsvr) return 1;//错误,关闭此socket
RW_LOG_DEBUG("HTTP Request:len=%d\n\t%s",len,buf);
//判断是否为http请求头
if (strncmp(buf,"GET",3)!=0&&strncmp(buf,"POST",4)!=0)
{
if((phttpreq=phttpsvr->m_reqmap.get(psock))!=NULL)
{
ret=phttpreq->do_reqdata(buf,len);
if(ret>=0)
{
if (!phttpreq->is_end()) return 0;//数据未接收完,继续接收
//删除映射表中的此选项,但并不释放value所指向空间
phttpsvr->m_reqmap.remove(psock);
//phhtpreq后续处理,处理完后会释放
}
else
{
phttpsvr->m_reqmap.remove(psock);
RW_LOG_WARN("do_reqdata() return error,errno=%d\n",ret);
//phhtpreq后续处理,处理完后会释放
}//?if(ret>=0) else
}//?if((phttpreq=phttpsvr->m_reqmap.get(psock))!=NULL)
else
{
//无法定位到HTTP请求开始,接收错误的数据
RW_LOG_WARN("receive wrong http request,len=%d\n",len);
return 1;//错误,关闭此socket
}
}
else
{
//如果是http请求头
phttpreq=new(nothrow) cHttpreq;
if(phttpreq!=NULL)
{
if((ret=phttpreq->do_reqdata(buf,len))>=0)
{
if (!phttpreq->is_end()){
if(phttpsvr->m_reqmap.add(psock,phttpreq)<0)
{
delete phttpreq;phttpreq=NULL;
RW_LOG_WARN("add cSocket *<----->HTTPREQ * MAP pair error!\n");
}
else
return 0;//数据未接收完,继续接收
}
}//?if((ret=phttpreq->do_reqdata(buf,len))>=0)
else
{
delete phttpreq;phttpreq=NULL;
RW_LOG_WARN("[new] do_reqdata() return error,errno=%d\n",ret);
}
}//?if(phttpreq!=NULL)
}//?是http请求头
//请求处理
if(phttpreq!=NULL) {
FUNC_DOREQ *pfunc=NULL;
phttpreq->dump();
if (phttpsvr->m_mapUrlfunc.count(phttpreq->m_strUrl)>=1)
pfunc=phttpsvr->m_mapUrlfunc[phttpreq->m_strUrl];
if (pfunc!=NULL) {
psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
ret=(*pfunc)(psock,phttpreq);
}//?if (pfunc!=NULL)
else
{
char *ptr=strchr(phttpreq->m_strUrl+1,'.');
if (ptr!=NULL)
{
if (strcmp(ptr,".txt")==0||strcmp(ptr,".log")==0||strcmp(ptr,".c")==0||strcmp(ptr,".h")==0)
{
psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
cHttpsvr::send_text_file(psock,phttpreq->m_strUrl+1);
}
else if (strcmp(ptr,".gif")==0||strcmp(ptr,".jpg")==0)
{
psock->send("HTTP/1.1 200 OK\nContent-Type: image/gif\nAccept-Ranges: bytes\n\n");
cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
}
else
{
psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
}
}
else //其他文件
{
psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
}
}//?if (pfunc!=NULL) else
delete phttpreq;
//如果返回-1的话则不关闭
if (ret==-1) return 0;
}//?if(phttpreq!=NULL)
else
return 1;//错误,关闭此socket
return 3;//发送数据并关闭socket
}
/**
* 发送二进制文件
*
* @param psock
* @param filename
*/
void cHttpsvr::send_file(cSocket *psock,const char * filename)
{
FILE * fd;
char * ptr;
int len=0;
if (psock==NULL) return;
if (filename==NULL) return;
if (filename[0]==0) return;
ptr=(char *)malloc(cBuffer::MAX_BUF_SIZE);
memset((void *)ptr,0,cBuffer::MAX_BUF_SIZE);
fd=fopen(filename,"rb");
if (fd)
{
len=fread((void*)ptr,sizeof(char),cBuffer::MAX_BUF_SIZE,fd);
while(len>0)
{
psock->send(len,ptr);
if (len!=cBuffer::MAX_BUF_SIZE) break;
len=fread((void*)ptr,sizeof(char),cBuffer::MAX_BUF_SIZE,fd);
}
fclose(fd);
}
else
psock->send("Can not read file:%s!<br>", filename);
free(ptr);
}
/**
* 发送文本文件,将文件中的回车
* 转化为"<BR>"
*
* @param psock
* @param filename
*/
void cHttpsvr::send_text_file(cSocket *psock,const char * filename)
{
FILE * fd;
char buf[DEFAULT_BUF_SIZE];//vc++ not surpport char[cBuffer::MAX_BUF_SIZE]
int i,c,len=0;
if (psock==NULL) return;
if (filename==NULL) return;
if (filename[0]==0) return;
fd=fopen(filename,"rt");
if (fd)
{
memset((char *)buf,0,cBuffer::MAX_BUF_SIZE);
while(feof(fd)==0)
{
i=0;
while(i<(cBuffer::MAX_BUF_SIZE-5))
{
c=fgetc(fd);
if(c==10||c==EOF) break;
buf[i++]=(char)c;
}
buf[i]='<';buf[i+1]='b';buf[i+2]='r';buf[i+3]='>';buf[i+4]=0;
psock->send(buf);
}
fclose(fd);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -