1 Star 8 Fork 5

SSZL博客/webSocket_Libevent_ThreadPool

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ev_httpd.cpp 46.72 KB
一键复制 编辑 原始数据 按行查看 历史
SSZL 提交于 2019-01-23 10:53 . 修改
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
/*************************************************************************
# > File Name: ev_httpd.cpp
# > Author: SSZL
# > Blog: sszlbg.cn
# > Created Time: 2018-09-20 18:16:10
# > Revise Time: 2018-11-08 12:35:37
************************************************************************/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/time.h>
#include <event2/listener.h>
#include <map>
#include <string>
#include <iostream>
#include "include/debug.h"
#include "include/ev_websocket.h"
#include "include/ev_httpd.h"
#include "include/ev_httpd_content.h"
#include "include/config.h"
#ifndef HTTPSERVER_MIN_THREAD_NUM
#define HTTPSERVER_MIN_THREAD_NUM 10
#endif
#ifndef HTTPSERVER_BASE_MAX_MONITOR_NUM
#define HTTPSERVER_BASE_MAX_MONITOR_NUM 3000
#endif
#ifndef HTTPSERVER_SUPERVISE_TIME
#define HTTPSERVER_SUPERVISE_TIME 1000 //1s
#endif
#ifndef HTTPSERVER_IDLE_TIMEROUT
#define HTTPSERVER_IDLE_TIMEROUT 15 //10s
#endif
#ifndef HTTPSERVER_RECEIVE_BUFF_CHUNK_SIZE
#define HTTPSERVER_RECEIVE_BUFF_CHUNK_SIZE 256 //256kb
#endif
#ifndef SERVER_STRING
#define SERVER_STRING "WebSocket-HttpServer/1.0.0"
#endif
#ifndef METHOD_MAX_LEN
#define METHOD_MAX_LEN 125
#endif
#ifndef URL_MAX_LEN
#define URL_MAX_LEN 125
#endif
#ifndef HTTPVERSION_MAX_LEN
#define HTTPVERSION_MAX_LEN 10
#endif
#define BufferevMap std::map<struct bufferevent *, struct httpChilent_t *>
#define ISspace(x) isspace((int)(x))
typedef enum
{
REQUEST_ERROR = -1,
REQUEST_NOCONTENT = -2,
REQUEST_BADREQUEST = -3,
REQUEST_ENTITYTOOLARGE = -4,
REQUEST_INTERNAL = -5,
REQUEST_NOTIMPLEMENTED = -6
}Accept_Request_Error;
struct httpServer_t
{
pthread_mutex_t lock;
pthread_mutex_t clientMap_lock;
BufferevMap *clientMap;
event_base * http_listener_base;
evbase_threadpool_t * evb_thpool;
evconnlistener * http_listeber;
threadpool_t * pool;
pthread_t http_supervise_thread;
int port;
int shutdown;
httpd_handler_t handler;
webSocket_cb_t ws_read_cb;
webSocket_cb_t ws_weite_cb;
webSocket_cb_t ws_connect_cb;
webSocket_cb_t ws_disconnect_cb;
char *webSocket_url;
void *arg;//用于向 Http处理穿参
};
typedef enum
{
Ws_Cb_Type_read,
Ws_Cb_Type_write,
Ws_Cb_Type_connect,
Ws_Cb_Type_disconnect
}WebddSocket_Thread_Cb_Type;
typedef struct
{
httpChilent_t * client;
WebddSocket_Thread_Cb_Type type;
}WebddSocket_Thread_Cb_arg_t;
int httpChilent_free(struct httpChilent_t* client);
int accept_request(struct httpChilent_t * client);
void httpServer_setArg(void * arg);
int resqonse(struct httpChilent_t *client);
httpServer_t * startHttpServe(struct event_base* base, u_short *port);
int httpServer_free(httpServer_t * httpServer);
int http_resqonse_free(struct http_resqonse_t *resqonse);
int http_request_free(struct http_request_t *request);
void httpChilent_Close(struct httpChilent_t * client);
void httpChilent_Close_nolock(struct httpChilent_t * client);
int httpServer_setWebSocket_read_cb(httpServer_t * httpServer, webSocket_cb_t ws_read_cb,const char * url);
int httpServer_setHttpHandler(httpServer_t *httpServer, httpd_handler_t handler);
void *webSocke_thread_cb(void * arg);
threadpool_t * HttpServer_GetThreadPool(httpServer_t * httpServer)
{
pthread_mutex_lock(&httpServer->lock);
threadpool_t *pool = httpServer->pool;
pthread_mutex_unlock(&httpServer->lock);
return pool;
}
int resqonse(struct httpChilent_t *client)
{
struct evbuffer * evbuff = evbuffer_new();
HeadParameterMap::iterator v;
if(evbuff == NULL)
{
return -1;
}
pthread_mutex_lock(&client->lock);
gettimeofday(&client->final_optime, NULL);
do{
if(client->resqonse.resqonseCode == 0)
{
pthread_mutex_unlock(&client->lock);
return -1;
}
if(client->request.http_version == NULL)
{
client->request.http_version = (char *)malloc(strlen("HTTP/1.1"));
if(client->request.http_version == NULL)
{
pthread_mutex_unlock(&client->lock);
return -1;
}
strcpy(client->request.http_version,"HTTP/1.1");
}
if(client->resqonse.resqonseCode == HTTP_OK )
{
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version, HTTP_OK, HTTP_OK_VALUE);
}
else if(client->resqonse.resqonseCode == HTTP_SWITCHING_PROTOCOLS)
{
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version, HTTP_SWITCHING_PROTOCOLS, HTTP_SWITCHING_PROTOCOLS_VALUE);
evbuffer_add_printf(evbuff, "Upgrade: websocket\r\n");
evbuffer_add_printf(evbuff, "Connection: Upgrade\r\n");
v = client->resqonse.HeadParameter->find("Sec-WebSocket-Accept");
if(v == client->resqonse.HeadParameter->end())
{
evbuffer_free(evbuff);
return -1;
}
evbuffer_add_printf(evbuff, "%s: %s\r\n", v->first.c_str(),v->second.c_str());
client->resqonse.HeadParameter->erase(v);
time_t now;
struct tm *tm_now;
char timeStr[50] = {0};
time(&now);
tm_now = localtime(&now);
strftime(timeStr, sizeof(timeStr), "%a, %d %b %Y %T %Z", tm_now);
evbuffer_add_printf(evbuff, "Date: %s\r\n", timeStr);
evbuffer_add_printf(evbuff, "\r\n");
client->stat = HTTP_WS_DATA;
WebddSocket_Thread_Cb_arg_t * cb_arg = (WebddSocket_Thread_Cb_arg_t *)malloc(sizeof(WebddSocket_Thread_Cb_arg_t));
cb_arg->client = client;
cb_arg->type = Ws_Cb_Type_connect;
threadpool_add(evbase_threadpool_get_threadpool(client->httpServer->evb_thpool), webSocke_thread_cb, cb_arg);
break;
}
else
{
switch(client->resqonse.resqonseCode)
{
case HTTP_NOCONTENT:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_NOCONTENT, HTTP_NOCONTENT_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_NOCONTENT_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_NOCONTENT_CONTENT);
}
break;
case HTTP_MOVEPERM:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_MOVEPERM, HTTP_MOVEPERM_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_MOVEPERM_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_MOVEPERM_CONTENT);
}
break;
case HTTP_MOVETEMP:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_MOVETEMP, HTTP_MOVETEMP_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_MOVETEMP_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_MOVETEMP_CONTENT);
}
break;
case HTTP_NOTMODIFIED:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_NOTMODIFIED, HTTP_NOTMODIFIED_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
}
break;
case HTTP_BADREQUEST:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_BADREQUEST, HTTP_BADREQUEST_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_BADREQUEST_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_BADREQUEST_CONTENT);
}
break;
case HTTP_NOTFOUND:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_NOTFOUND, HTTP_NOTFOUND_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_NOTFOUND_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_NOTFOUND_CONTENT);
}
break;
case HTTP_BADMETHOD:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_BADMETHOD, HTTP_BADMETHOD_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_BADMETHOD_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_BADMETHOD_CONTENT);
}
break;
case HTTP_ENTITYTOOLARGE:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_ENTITYTOOLARGE, HTTP_ENTITYTOOLARGE_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_ENTITYTOOLARGE_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_ENTITYTOOLARGE_CONTENT);
}
break;
case HTTP_EXPECTATIONFAILED:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_EXPECTATIONFAILED, HTTP_EXPECTATIONFAILED_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_EXPECTATIONFAILED_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_EXPECTATIONFAILED_CONTENT);
}
break;
case HTTP_INTERNAL:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_INTERNAL, HTTP_INTERNAL_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_INTERNAL_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_INTERNAL_CONTENT);
}
break;
case HTTP_NOTIMPLEMENTED:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_NOTIMPLEMENTED, HTTP_NOTIMPLEMENTED_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_NOTFOUND_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_NOTFOUND_CONTENT);
}
break;
case HTTP_SERVUNAVAIL:
evbuffer_add_printf(evbuff, "%s %d %s\r\n", client->request.http_version,
HTTP_SERVUNAVAIL, HTTP_SERVUNAVAIL_VALUE);
if(client->resqonse.resqonse_data == NULL)
{
evbuffer_add_printf(evbuff, "Content-Type: text/html\r\n");
evbuffer_add_printf(evbuff, "Content-Length: %d\r\n", (int)strlen(HTTP_SERVUNAVAIL_CONTENT));
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
evbuffer_add_printf(evbuff, "\r\n");
evbuffer_add_printf(evbuff, HTTP_SERVUNAVAIL_CONTENT);
}
break;
}
}
if(client->resqonse.HeadParameter == NULL)
{
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
}
else
{
v = client->resqonse.HeadParameter->find("Server");
if(v != client->resqonse.HeadParameter->end())
{
evbuffer_add_printf(evbuff, "%s: %s\r\n", v->first.c_str(), v->second.c_str());
client->resqonse.HeadParameter->erase(v);
}
else
{
evbuffer_add_printf(evbuff, "%s: %s\r\n", "Server", SERVER_STRING);
}
v = client->resqonse.HeadParameter->begin();
while(v != client->resqonse.HeadParameter->end())
{
evbuffer_add_printf(evbuff, "%s: %s\r\n", v->first.c_str(), v->second.c_str());
v++;
}
}
evbuffer_add_printf(evbuff, "\r\n");
if(client->resqonse.resqonse_data != NULL)
{
unsigned add_len = 0;
while((evbuffer_add(evbuff, client->resqonse.resqonse_data + add_len, 1)) == 0)
{
add_len++;
if((add_len % HTTPSERVER_RECEIVE_BUFF_CHUNK_SIZE ) == 0)
gettimeofday(&client->final_optime, NULL);
if(add_len >= client->resqonse.Resqonse_data_len)
break;
}
}
}while(0);
if(client->stat != HTTP_WS_DATA)
client->stat = HTTP_RESQONSE;
bufferevent_lock(client->bev);
evbuffer_add_buffer(bufferevent_get_output(client->bev), evbuff);
bufferevent_unlock(client->bev);
pthread_mutex_unlock(&client->lock);
evbuffer_free(evbuff);
return 0;
}
/**********************************************************************/
/**********************************************************************/
/* A request has caused a call to accept() on the server port to
* return. Process the request appropriately.
* Parameters: the socket connected to the client */
/**********************************************************************/
int accept_request(struct httpChilent_t * client)
{
size_t numchars;
char * buf;
size_t i, j;
struct evbuffer * evbuff = NULL;
if(client == NULL)
return REQUEST_ERROR;
pthread_mutex_lock(&client->lock);
gettimeofday(&client->final_optime, NULL);
evbuff = client->receive_evbuff;
evbuffer_lock(client->receive_evbuff);
buf = evbuffer_readln(evbuff, &numchars, EVBUFFER_EOL_CRLF);
evbuffer_unlock(client->receive_evbuff);
if(buf == NULL)
{
pthread_mutex_unlock(&client->lock);
return REQUEST_NOCONTENT;
}
client->request.method = (char *)malloc(METHOD_MAX_LEN + 1);
client->request.url = (char *)malloc(URL_MAX_LEN + 1);
client->request.http_version = (char *)malloc(HTTPVERSION_MAX_LEN + 1);
if(client->request.method == NULL || client->request.url == NULL || client->request.http_version == NULL)
{
pthread_mutex_unlock(&client->lock);
return REQUEST_INTERNAL;
}
i = 0; j = 0;
while (!ISspace(buf[j]) && (i < METHOD_MAX_LEN) && (j < numchars))
{
client->request.method[i] = buf[j];
i++; j++;
}
if(j == numchars)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
client->request.method[i] = '\0';
if (strcasecmp(client->request.method, "GET") && strcasecmp(client->request.method, "POST"))
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_NOTIMPLEMENTED;
}
i = 0;
while (ISspace(buf[j]) && (j < numchars) )
j++;
if(j == numchars)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
while (!ISspace(buf[j]) && (i < URL_MAX_LEN) && (j < numchars))
{
client->request.url[i] = buf[j];
i++; j++;
}
if(j == numchars)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
client->request.url[i] = '\0';
if (strcasecmp(client->request.method, "GET") == 0)
{
client->request.query_string = client->request.url;
while ((*client->request.query_string != '?') && (*client->request.query_string != '\0'))
client->request.query_string++;
if (*client->request.query_string == '?')
{
*client->request.query_string = '\0';
client->request.query_string++;
}
}
else
{
if(strstr(client->request.url, "?"))
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
}
i = 0;
while (ISspace(buf[j]) && (j < numchars) )
j++;
if(j == numchars)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
while (!ISspace(buf[j]) && (i < HTTPVERSION_MAX_LEN) && (j < numchars))
{
client->request.http_version[i] = buf[j];
i++; j++;
}
if(strlen(client->request.http_version) < 8)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
free(buf);
while(1)
{
evbuffer_lock(client->receive_evbuff);
buf = evbuffer_readln(evbuff, &numchars, EVBUFFER_EOL_CRLF);
evbuffer_unlock(client->receive_evbuff);
if(buf == NULL)
break;
else if(strcasecmp(client->request.method, "POST") == 0 && numchars == 0)
{
client->request.request_data_len = evbuffer_get_length(evbuff);
client->request.request_data = (char *)malloc(client->request.request_data_len);
if(client->request.request_data == NULL)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_INTERNAL;
}
evbuffer_lock(client->receive_evbuff);
evbuffer_remove(evbuff, client->request.request_data, client->request.request_data_len);
evbuffer_unlock(client->receive_evbuff);
break;
}
else if(numchars == 0)
{
break;
}
if( client->request.HeadParameter == NULL)
client->request.HeadParameter = new HeadParameterMap();
char * key = buf;
char * v = strchr(buf,':');
if(v == NULL)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
*v = '\0';
v++;
i = 0;j = 0;
while (ISspace(*key) && (j < numchars) )
{
j++;
key++;
}
while (!ISspace(key[i]) && (i < strlen(key)))
{
i++; j++;
}
key[i] = '\0';
i = 0;j = 0;
numchars = v - buf;
while (ISspace(*v) && (j < numchars) )
{
j++;
v++;
}
while (!ISspace(v[i]) && (i < strlen(v)))
{
i++; j++;
}
v[i] = '\0';
client->request.HeadParameter->insert(std::pair<STRING, STRING>(key, v));
}
if(strcasecmp(client->request.method, "POST") == 0 && client->request.request_data == NULL)
{
http_request_free(&client->request);
pthread_mutex_unlock(&client->lock);
return REQUEST_BADREQUEST;
}
pthread_mutex_unlock(&client->lock);
return 0;
}
static void bufferev_write_cb(struct bufferevent *bev,void *ctx)
{
bev = (struct bufferevent *)bev;
httpChilent_t *client = (httpChilent_t *)ctx;
pthread_mutex_lock(&client->lock);
gettimeofday(&client->final_optime,NULL);
if( client->stat != HTTP_WS_DATA)
client->stat = HTTP_IDLE;
if(client->stat == HTTP_WS_DATA)
{
WebddSocket_Thread_Cb_arg_t * cb_arg = (WebddSocket_Thread_Cb_arg_t *)malloc(sizeof(WebddSocket_Thread_Cb_arg_t));
cb_arg->client = client;
cb_arg->type = Ws_Cb_Type_write;
threadpool_add(evbase_threadpool_get_threadpool(client->httpServer->evb_thpool), webSocke_thread_cb, cb_arg);
}
pthread_mutex_unlock(&client->lock);
}
void *httpd_handler_thread(void *arg)
{
struct httpChilent_t *client = (struct httpChilent_t *)arg;
struct httpServer_t *httpServer = client->httpServer;
struct bufferevent * bev = client->bev;
char respondKey[128];
char c = 0;
pthread_mutex_lock(&client->lock);
gettimeofday(&client->final_optime, NULL);
do
{
bufferevent_lock(bev);
evbuffer_lock(client->receive_evbuff);
bufferevent_disable(bev, EV_READ);
while(1)
{
if(bufferevent_read(bev,&c,1) == 0 )
{
break;
}
evbuffer_add(client->receive_evbuff, &c , 1);
}
bufferevent_enable(bev, EV_READ);
evbuffer_unlock(client->receive_evbuff);
bufferevent_unlock(bev);
pthread_mutex_unlock(&client->lock);
int ret = accept_request(client);
pthread_mutex_lock(&client->lock);
if(ret != 0)
{
switch(ret)
{
case REQUEST_ERROR:
client->resqonse.resqonseCode = HTTP_INTERNAL;
break;
case REQUEST_NOCONTENT:
client->resqonse.resqonseCode = HTTP_NOCONTENT;
break;
case REQUEST_BADREQUEST:
client->resqonse.resqonseCode = HTTP_BADREQUEST;
break;
case REQUEST_ENTITYTOOLARGE:
client->resqonse.resqonseCode = HTTP_ENTITYTOOLARGE;
break;
case REQUEST_INTERNAL:
client->resqonse.resqonseCode = HTTP_INTERNAL;
break;
case REQUEST_NOTIMPLEMENTED:
client->resqonse.resqonseCode = HTTP_NOTIMPLEMENTED;
break;
default:
client->resqonse.resqonseCode = HTTP_INTERNAL;
break;
}
pthread_mutex_unlock(&client->lock);
resqonse(client);
pthread_mutex_lock(&client->lock);
http_request_free(&client->request);
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
}
else
{
if(client->request.HeadParameter != NULL)
{
HeadParameterMap::iterator v = client->request.HeadParameter->find("Sec-WebSocket-Key");
HeadParameterMap::iterator v1 = client->request.HeadParameter->find("Sec-WebSocket-Version");
pthread_mutex_lock(&client->httpServer->lock);
if(strcasecmp(client->request.method, "GET") == 0 && v1 != client->request.HeadParameter->end() && strcmp(v1->second.c_str(), "13") == 0 && v != client->request.HeadParameter->end() && strcmp(client->httpServer->webSocket_url, client->request.url) == 0)
{
pthread_mutex_unlock(&client->httpServer->lock);
client->resqonse.resqonseCode = HTTP_SWITCHING_PROTOCOLS;
memset(respondKey, 0, sizeof(respondKey));
webSocket_buildRespondShakeKey((unsigned char *) v->second.c_str(), strlen(v->second.c_str()),( unsigned char *)respondKey);
client->resqonse.HeadParameter = new HeadParameterMap();
if(client->resqonse.HeadParameter == NULL)
{
client->resqonse.resqonseCode = HTTP_INTERNAL;
pthread_mutex_unlock(&client->lock);
resqonse(client);
pthread_mutex_lock(&client->lock);
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
break;
}
client->resqonse.HeadParameter->insert(HaedParameteMapPairi("Sec-WebSocket-Accept", respondKey));
pthread_mutex_unlock(&client->lock);
resqonse(client);
pthread_mutex_lock(&client->lock);
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
break;
}
pthread_mutex_unlock(&client->httpServer->lock);
}
if(client->httpServer->handler != NULL)
{
httpd_handler_t handler;
handler = client->httpServer->handler;
client->resqonse.HeadParameter = new HeadParameterMap();
pthread_mutex_unlock(&client->lock);
handler(client);
pthread_mutex_lock(&httpServer->clientMap_lock);
BufferevMap::iterator v = httpServer->clientMap->find(bev);
if(httpServer->clientMap->end() == v)
{
pthread_mutex_unlock(&httpServer->clientMap_lock);
return NULL;
}
pthread_mutex_unlock(&httpServer->clientMap_lock);
pthread_mutex_lock(&client->lock);
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
}
else
{
//503错误
client->resqonse.resqonseCode = HTTP_SERVUNAVAIL;
pthread_mutex_unlock(&client->lock);
resqonse(client);
pthread_mutex_lock(&client->lock);
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
}
}
}while(0);
pthread_mutex_unlock(&client->lock);
return NULL;
}
void *webSocke_thread_cb(void * arg)
{
if(arg != NULL)
{
WebddSocket_Thread_Cb_arg_t * cb_arg = (WebddSocket_Thread_Cb_arg_t *)arg;
switch(cb_arg->type)
{
case Ws_Cb_Type_connect:
if(cb_arg->client->httpServer->ws_connect_cb != NULL)
cb_arg->client->httpServer->ws_connect_cb(cb_arg->client);
break;
case Ws_Cb_Type_disconnect:
if(cb_arg->client->httpServer->ws_disconnect_cb != NULL)
cb_arg->client->httpServer->ws_disconnect_cb(cb_arg->client);
break;
case Ws_Cb_Type_write:
if(cb_arg->client->httpServer->ws_weite_cb != NULL)
cb_arg->client->httpServer->ws_weite_cb(cb_arg->client);
break;
case Ws_Cb_Type_read:
if(cb_arg->client->httpServer->ws_read_cb != NULL)
cb_arg->client->httpServer->ws_read_cb(cb_arg->client);
break;
}
free(arg);
}
return NULL;
}
void *ws_read_cb_thread(void *arg)
{
struct httpChilent_t *client = (struct httpChilent_t *)arg;
struct httpServer_t *httpServer = client->httpServer;
struct bufferevent * bev = client->bev;
unsigned char * buff = NULL;
unsigned int buff_len = 0;
Websocket_CommunicationType ws_data_type;
bufferevent_lock(client->bev);
int ret = ev_webSocket_recv(client->bev, &buff, &buff_len, &ws_data_type);
bufferevent_unlock(client->bev);
if(ret <= 0)
{
if(ret == WCT_DISCONN)
{
httpChilent_Close(client);
return NULL;
}
}
else
{
client->ws_data_type = ws_data_type;
if(client->stat == HTTP_WS_DATA && client->httpServer->ws_read_cb != NULL)
{
evbuffer_lock(client->receive_evbuff);
if(evbuffer_add(client->receive_evbuff, buff, buff_len) != 0)
{
De_fprintf(stderr, "evbuffer_add fail!\r\n");
evbuffer_unlock(client->receive_evbuff);
pthread_mutex_unlock(&client->lock);
free(buff);
return NULL;
}
evbuffer_unlock(client->receive_evbuff);
free(buff);
webSocket_cb_t ws_read_cb = client->httpServer->ws_read_cb;
pthread_mutex_unlock(&client->lock);
ws_read_cb(client);
pthread_mutex_lock(&httpServer->clientMap_lock);
BufferevMap::iterator v = httpServer->clientMap->find(bev);
if(httpServer->clientMap->end() == v)
{
pthread_mutex_unlock(&httpServer->clientMap_lock);
return NULL;
}
pthread_mutex_unlock(&httpServer->clientMap_lock);
pthread_mutex_lock(&client->lock);
client->ws_data_type = WCT_NULL;
}
else
free(buff);
pthread_mutex_unlock(&client->lock);
}
return NULL;
}
static void bufferev_read_cb(struct bufferevent *bev,void *ctx)
{
bev = (struct bufferevent *)bev;
struct httpChilent_t *client = (struct httpChilent_t *)ctx;
pthread_mutex_lock(&client->lock);
if(client->stat == HTTP_WS_DATA )
{
if(client->httpServer->ws_read_cb != NULL)
threadpool_add(client->httpServer->pool, ws_read_cb_thread, client);
pthread_mutex_unlock(&client->lock);
}
else
{
client->stat = HTTP_REQUEST;
if(client->httpServer->handler != NULL)
threadpool_add(client->httpServer->pool, httpd_handler_thread, client);
pthread_mutex_unlock(&client->lock);
}
}
void *http_supervise_thread(void * arg)
{
httpServer_t *httpServer=(httpServer_t *)arg;
pthread_mutex_lock(&httpServer->lock);
while(!httpServer->shutdown)
{
pthread_mutex_unlock(&httpServer->lock);
usleep(1000*HTTPSERVER_SUPERVISE_TIME);
pthread_mutex_lock(&httpServer->lock);
pthread_mutex_lock(&httpServer->clientMap_lock);
for(BufferevMap::iterator i = httpServer->clientMap->begin();
i != httpServer->clientMap->end();)
{
struct timeval date;
gettimeofday(&date, NULL);
pthread_mutex_lock(&i->second->lock);
if(((i->second->stat == HTTP_CONNECTED)
||(i->second->stat == HTTP_IDLE)
||(i->second->stat == HTTP_DISCONNECTED))
&&(date.tv_sec - (i->second)->final_optime.tv_sec) > HTTPSERVER_IDLE_TIMEROUT)
{
pthread_mutex_unlock(&i->second->lock);
httpChilent_Close_nolock((i++)->second);
}
else
{
pthread_mutex_unlock(&i->second->lock);
i++;
}
}
pthread_mutex_unlock(&httpServer->clientMap_lock);
}
pthread_mutex_unlock(&httpServer->lock);
return NULL;
}
int http_resqonse_free(struct http_resqonse_t *resqonse)
{
if(resqonse == NULL)
return -1;
if(resqonse->resqonse_data != NULL)
free(resqonse->resqonse_data);
if(resqonse->HeadParameter != NULL)
delete resqonse->HeadParameter;
memset(resqonse, 0, sizeof(http_resqonse_t));
return 0;
}
int http_request_free(struct http_request_t *request)
{
if(request == NULL)
return -1;
if(request->method != NULL)
free(request->method);
if(request->request_data != NULL)
free(request->request_data);
if(request->url != NULL)
free(request->url);
if(request->http_version != NULL)
free(request->http_version);
if(request->HeadParameter != NULL)
delete request->HeadParameter;
memset(request, 0, sizeof(http_request_t));
return 0;
}
int httpChilent_free(struct httpChilent_t* client)
{
if(client == NULL)
return-1;
pthread_mutex_lock(&client->lock);
if(client->receive_evbuff != NULL)
{
evbuffer_lock(client->receive_evbuff);
evbuffer_free(client->receive_evbuff);
}
http_request_free(&client->request);
http_resqonse_free(&client->resqonse);
pthread_mutex_destroy(&client->lock);
free(client);
return 0;
}
static void bufferev_event_cb(struct bufferevent *bev, short events,void *ctx)
{
httpChilent_t *client = (httpChilent_t *)ctx;
struct sockaddr_in *address = NULL;
char ip[INET_ADDRSTRLEN];
BufferevMap::iterator i;
do
{
if(client == NULL)
{
De_printf("httpChilent NULL\r\n");
break;
}
pthread_mutex_lock(&client->lock);
address = (struct sockaddr_in *)&(client->addr);
if(address != NULL)
{
inet_ntop(AF_INET, &address->sin_addr,ip, INET_ADDRSTRLEN);
}
if(events & BEV_EVENT_ERROR)
{
if(address != NULL)
De_printf("%s:%d[ Error from bufferevnt:%s\r\n", inet_ntop(AF_INET,&address->sin_addr, ip,(socklen_t) sizeof(ip)), ntohs(address->sin_port), strerror(errno));
else
De_printf("Unknown[ Error from bufferevnt:%s\r\n",strerror(errno));
}
else if(events & (BEV_EVENT_EOF))
{
if(address != NULL)
De_printf("Connection close:%s:%d\r\n", inet_ntop(AF_INET,&address->sin_addr, ip,(socklen_t) sizeof(ip)), ntohs(address->sin_port));
else
De_printf("Connection close: Unknown\r\n");
}
pthread_mutex_unlock(&client->lock);
}
while(0);
bufferevent_lock(bev);
bufferevent_disable(bev, EV_WRITE | EV_READ);
if(client != NULL)
{
if(client->stat == HTTP_WS_DATA && client->ws_weite_cb_flage)
{
WebddSocket_Thread_Cb_arg_t * cb_arg = (WebddSocket_Thread_Cb_arg_t *)malloc(sizeof(WebddSocket_Thread_Cb_arg_t));
cb_arg->client = client;
cb_arg->type = Ws_Cb_Type_disconnect;
threadpool_add(evbase_threadpool_get_threadpool(client->httpServer->evb_thpool), webSocke_thread_cb, cb_arg);
}
pthread_mutex_lock(&client->lock);
evbase_threadpool_close_event(client->httpServer->evb_thpool, bufferevent_get_base(bev));
pthread_mutex_lock(&client->httpServer->clientMap_lock);
client->httpServer->clientMap->erase(bev);
pthread_mutex_unlock(&client->httpServer->clientMap_lock);
pthread_mutex_unlock(&client->lock);
httpChilent_free(client);
}
//close(bufferevent_getfd(bev));
bufferevent_lock(bev);
bufferevent_free(bev);
/* bufferevent_unlock(bev); */
}
void httpChilent_Close_nolock(struct httpChilent_t * client)
{
struct sockaddr_in *address = NULL;
char ip[INET_ADDRSTRLEN];
BufferevMap::iterator i;
while(evbuffer_get_length(bufferevent_get_output(client->bev)) > 0);
do
{
if(client == NULL)
{
De_printf("httpChilent NULL\r\n");
break;
}
address = (struct sockaddr_in *)&(client->addr);
if(address != NULL)
{
inet_ntop(AF_INET, &address->sin_addr,ip, INET_ADDRSTRLEN);
}
if(address != NULL)
De_printf("Connection close:%s:%d\r\n", inet_ntop(AF_INET,&address->sin_addr, ip,(socklen_t) sizeof(ip)), ntohs(address->sin_port));
else
De_printf("Connection close: Unknown\r\n");
}
while(0);
bufferevent_lock(client->bev);
bufferevent_disable(client->bev, EV_WRITE | EV_READ);
if(client != NULL)
{
if(client->stat == HTTP_WS_DATA)
{
WebddSocket_Thread_Cb_arg_t * cb_arg = (WebddSocket_Thread_Cb_arg_t *)malloc(sizeof(WebddSocket_Thread_Cb_arg_t));
cb_arg->client = client;
cb_arg->type = Ws_Cb_Type_disconnect;
threadpool_add(evbase_threadpool_get_threadpool(client->httpServer->evb_thpool), webSocke_thread_cb, cb_arg);
}
evbase_threadpool_close_event(client->httpServer->evb_thpool, bufferevent_get_base(client->bev));
client->httpServer->clientMap->erase(client->bev);
httpChilent_free(client);
}
bufferevent_unlock(client->bev);
bufferevent_free(client->bev);
}
void httpChilent_Close(struct httpChilent_t * client)
{
if(client == NULL)
return;
while(evbuffer_get_length(bufferevent_get_output(client->bev)) > 0);
bufferev_event_cb(client->bev, BEV_EVENT_EOF, client);
}
static void listener_cd(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *arg)
{
httpServer_t *httpServer=(httpServer_t *)arg;
listener = (struct evconnlistener *)listener;
struct httpChilent_t *client;
char ip[INET_ADDRSTRLEN];
struct sockaddr_in * addr = (struct sockaddr_in *)sa;
inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN);
event_base *base = evbase_threadpool_add_event(httpServer->evb_thpool);
if(base == NULL)
{
De_fprintf(stderr, "%s:%d[ base get fall!\r\n",ip, ntohs(addr->sin_port));
return;
}
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if(bev == NULL)
{
De_fprintf(stderr, "%s:%d[ bufferevent new error:%s\r\n",ip, ntohs(addr->sin_port), evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
return;
}
client = (struct httpChilent_t *) malloc(sizeof(struct httpChilent_t));
if(client == NULL)
{
De_fprintf(stderr, "%s:%d[ httpChilent malloc fail!\r\n",ip, ntohs(addr->sin_port));
return;
}
memset(client, 0, sizeof(struct httpChilent_t));
memcpy(&client->addr, sa, sizeof(sizeof(struct sockaddr_in)));
client->ws_weite_cb_flage = 1;
client->bev = bev;
client->httpServer = httpServer;
if(gettimeofday(&client->final_optime, NULL) != 0)
{
De_fprintf(stderr, "%s:%d[ gettimeofday fail!\r\n",ip, ntohs(addr->sin_port));
return;
}
client->stat = HTTP_CONNECTED;
if(pthread_mutex_init(&client->lock, NULL)!=0)
{
De_fprintf(stderr, "client->lock init fail!\r\n");
httpChilent_free(client);
return;
}
client->receive_evbuff = evbuffer_new();
if(client->receive_evbuff == NULL)
{
De_fprintf(stderr, "%s:%d[ evbuffer_new fail!\r\n",ip, ntohs(addr->sin_port));
return;
}
evbuffer_enable_locking(client->receive_evbuff, NULL);
bufferevent_setcb(bev, bufferev_read_cb, bufferev_write_cb, bufferev_event_cb, client);
pthread_mutex_lock(&httpServer->clientMap_lock);
httpServer->clientMap->insert(std::pair<struct bufferevent *, httpChilent_t *>(bev ,client));
pthread_mutex_unlock(&httpServer->clientMap_lock);
bufferevent_enable(bev, EV_READ| EV_WRITE);
De_printf("client connection:%s:%d\r\n",ip, ntohs(addr->sin_port));
socklen = (int)socklen;
}
static void accpt_error_cb(struct evconnlistener *listener, void *ctx)
{
struct event_base *base = evconnlistener_get_base(listener);
int err = EVUTIL_SOCKET_ERROR();
ctx =(void *)ctx;//(消除警告)
fprintf(stderr, "Got an error %d (%s) the listener."
"Shuttinf sown.\r\n",err, evutil_socket_error_to_string(err));
event_base_loopexit(base, NULL);
}
int httpServer_setHttpHandler(httpServer_t *httpServer, httpd_handler_t handler)
{
if(httpServer == NULL)
return -1;
pthread_mutex_lock(&httpServer->lock);
httpServer->handler = handler;
pthread_mutex_unlock(&httpServer->lock);
return 0;
}
int HttpServer_webSocket_close(httpChilent_t *httpChilent)
{
return ev_webSocket_send(httpChilent->bev, NULL , 0, false, WCT_DISCONN);
}
int HttpServer_webSocket_close_on_cb(httpChilent_t *httpChilent)
{
httpChilent->ws_weite_cb_flage = 0;
return ev_webSocket_send(httpChilent->bev, NULL , 0, false, WCT_DISCONN);
}
int HttpServer_webSocket_send(httpChilent_t *httpChilent, const char *data, size_t dataLen)
{
return ev_webSocket_send(httpChilent->bev, (unsigned char *)data , dataLen, false, WCT_TXTDATA);
}
int httpServer_setWebSocket_cb(httpServer_t * httpServer, webSocket_cb_t ws_write_cb, webSocket_cb_t ws_connect_cb, webSocket_cb_t ws_disConnect_cb)
{
if(httpServer == NULL)
return -1;
pthread_mutex_lock(&httpServer->lock);
httpServer->ws_weite_cb = ws_write_cb;
httpServer->ws_connect_cb = ws_connect_cb;
httpServer->ws_disconnect_cb = ws_disConnect_cb;
pthread_mutex_unlock(&httpServer->lock);
return 0;
}
int httpServer_setWebSocket_read_cb(httpServer_t * httpServer, webSocket_cb_t ws_read_cb,const char * url)
{
if(httpServer == NULL)
return -1;
pthread_mutex_lock(&httpServer->lock);
httpServer->webSocket_url = (char *)malloc(strlen(url));
if(httpServer->webSocket_url == NULL)
{
return -1;
}
httpServer->ws_read_cb = ws_read_cb;
strcpy(httpServer->webSocket_url, url);
pthread_mutex_unlock(&httpServer->lock);
return 0;
}
int httpServer_free(httpServer_t * httpServer)
{
if(httpServer == NULL)
return -1;
httpServer->shutdown = true;
if(httpServer->http_supervise_thread != 0)
pthread_join(httpServer->http_supervise_thread, NULL);
if(httpServer->http_listeber)
{
evconnlistener_free(httpServer->http_listeber);
}
if(httpServer->evb_thpool)
{
evbase_threadpool_destroy(httpServer->evb_thpool);
}
pthread_mutex_lock(&httpServer->clientMap_lock);
if(httpServer->clientMap)
{
BufferevMap:: iterator i;
for(i=httpServer->clientMap->begin();i != httpServer->clientMap->end(); i++)
{
httpChilent_free(i->second);
}
delete httpServer->clientMap;
}
pthread_mutex_destroy(&httpServer->lock);
pthread_mutex_destroy(&httpServer->clientMap_lock);
if(httpServer)
{
free(httpServer);
}
return 0;
}
void* httpServer_getArg(httpServer_t *httpServer)
{
pthread_mutex_lock(&httpServer->lock);
void * arg = httpServer->arg;
pthread_mutex_unlock(&httpServer->lock);
return arg;
}
void httpServer_setArg(httpServer_t *httpServer, void * arg)
{
pthread_mutex_lock(&httpServer->lock);
httpServer->arg = arg;
pthread_mutex_unlock(&httpServer->lock);
}
httpServer_t * startHttpServe(struct event_base* base, u_short *port)
{
httpServer_t * httpServer = NULL;
struct sockaddr_in addr;
#ifdef DYNAMIC_CONFING
if(SERVER_STRING_VARIALE == NULL)
return NULL;
#endif
do
{
if(base == NULL)
{
De_fprintf(stderr, "event_base == NULL\r\n");
break;
}
httpServer = (httpServer_t *) malloc(sizeof(httpServer_t));
if(httpServer == NULL)
{
De_fprintf(stderr, "httpServer_t mallocl fail!");
break;
}
memset(httpServer, 0, (sizeof(httpServer_t)));
httpServer->http_listener_base = base;
httpServer->shutdown = false;
httpServer->evb_thpool = evbase_threadpool_new(HTTPSERVER_BASE_MAX_MONITOR_NUM, HTTPSERVER_MIN_THREAD_NUM);
if(httpServer->evb_thpool == NULL)
{
De_fprintf(stderr, "new evbase_threadpool fail!\r\n");
break;
}
if(pthread_mutex_init(&httpServer->lock, NULL) != 0)
{
De_fprintf(stderr, "httpServer->lock init fail\r\n");
break;
}
if(pthread_mutex_init(&httpServer->clientMap_lock, NULL) != 0)
{
De_fprintf(stderr, "httpServer->clientMap_lock init fail\r\n");
break;
}
httpServer->clientMap = new BufferevMap();
if(httpServer->clientMap == NULL)
{
De_fprintf(stderr, "httpServer->clientMap new fail\r\n");
break;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(*port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if ((httpServer->http_listeber = evconnlistener_new_bind(base , listener_cd , httpServer, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,(struct sockaddr *)&addr, sizeof(addr))) == NULL)
{
De_fprintf(stderr, "evconnlistener_new_bind fail!\r\n");
break;
}
httpServer->port = *port;
evconnlistener_set_error_cb(httpServer->http_listeber, accpt_error_cb);
httpServer->pool = evbase_threadpool_get_threadpool(httpServer->evb_thpool);
int ret = pthread_create(&httpServer->http_supervise_thread, NULL, http_supervise_thread, httpServer);
if(ret != 0)
{
De_fprintf(stderr, "creatd thread fail:%s\r\n", strerror(ret));
break;
}
return httpServer;
}while(0);
httpServer_free(httpServer);
return NULL;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/sszl_blog/webSocket_Libevent_ThreadPool.git
[email protected]:sszl_blog/webSocket_Libevent_ThreadPool.git
sszl_blog
webSocket_Libevent_ThreadPool
webSocket_Libevent_ThreadPool
master

搜索帮助