⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wwwapi.cpp

📁 一个功能强大的内存数据库源代码,c++编写,有详细的注释
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    char* page = con.unpack(buf + buf[0], length - sizeof length - buf[0]);    char* peer = con.get("peer");    con.peer = new char[strlen(peer)+1];    strcpy(con.peer, peer);    bool result = true;    if (page != NULL)  { 	con.extendBuffer(4);	result = dispatch(con, page);	*(int4*)con.reply_buf = con.reply_buf_used;	con.sock->write(con.reply_buf, con.reply_buf_used);        }    delete[] con.peer;    con.peer = NULL;    delete con.sock;    con.sock = NULL; // close connection    return result;}inline char* stristr(char* s, char* p) {     while (*s != '\0') { 	int i;	for (i = 0; (s[i] & ~('a'-'A')) == (p[i] & ~('a' - 'A')) && p[i] != '\0'; i++);	if (p[i] == '\0') { 	    return s;	}	s += 1;    }    return NULL;}bool HTTPapi::serve(WWWconnection& con){    const size_t inputBufferSize = 16*1024;    char buf[inputBufferSize];    bool result = false;    size_t size = 0;    con.peer = con.sock->get_peer_name();    while (true) { 	con.reset();	char* p = buf;	char prev_ch = 0;	do { 	    if (p == buf + size) { 		int rc = con.sock->read(buf + size, 5, sizeof(buf) - size - 1, 					connectionHoldTimeout);		if (rc < 0) { 		    delete con.sock;		    con.sock = NULL;		    return true;		}		if (rc < 5) {		    con.append(ERROR_TEXT("200 OK")); // connection closed due to timeout expiration		    break;		}		size += rc;	    }	    buf[size] = '\0';	    while (*p != '\0' && (prev_ch != '\n' || *p != '\r')) { 		prev_ch = *p++;	    }	} while (*p == '\0' && p == buf + size); // p now points to the message body	if (*p != '\r' || *(p+1) != '\n') { 	    con.append(ERROR_TEXT("400 Bad Request"));	    break;	}    	p += 2;	int length = INT_MAX;	char* lenptr = stristr(buf, "content-length: ");	bool  persistentConnection = 	    stristr(buf, "Connection: keep-alive") != NULL;	char* host = stristr(buf, "host: ");	if (host != NULL) { 	    char* q = host += 6;	    while (*q != '\n' && *q != '\r' && *q != '\0') q += 1;	    *q = '\0';	}	if (lenptr != NULL) { 	    sscanf(lenptr+15, "%d", &length);	}	if (strncmp(buf, "GET ", 4) == 0) { 	    char* file, *uri = buf;	    file = strchr(uri, '/');	    if (file == NULL) { 		con.append(ERROR_TEXT("400 Bad Request"));		break;	    }	    if (*++file == '/') { 		if (host != NULL) { 		    host = file+1;			}		file = strchr(uri, '/');		if (file == NULL) { 		    con.append(ERROR_TEXT("400 Bad Request"));		    break;		}			*file++ = '\0';	    }	    char* file_end = strchr(file, ' ');	    char index_html[] = "index.html";	    if (file_end == NULL) { 		con.append(ERROR_TEXT("400 Bad Request"));		break;	    }	    if (file_end == file) { 		file = index_html;	    } else {		*file_end = '\0';	    }	    char* params = strchr(file, '?');	    if (params != NULL) { 		if (host == NULL) { 		    host = "localhost";		}		if (!handleRequest(con, params+1, file_end, host, result)) { 		    delete con.sock;		    con.sock = NULL;		    return result;		} 	    } else { 		URL2ASCII(file);		FILE* f = fopen(file, "rb");		if (f == NULL) { 		    con.append(ERROR_TEXT("404 File Not Found"));		    break;		}		fseek(f, 0, SEEK_END);		size_t file_size = ftell(f);		fseek(f, 0, SEEK_SET);		char reply[1024];		sprintf(reply, "HTTP/1.1 200 OK\r\nContent-Length: %u\r\n"			"Content-Type: text/html\r\nConnection: %s\r\n\r\n", 			file_size, 			keepConnectionAlive ? "Keep-Alive" : "close");		con.append(reply);		size_t pos = con.reply_buf_used;		char* dst = con.extendBuffer(file_size);		if (dst == NULL) { 		    con.reset();		    con.append(ERROR_TEXT("413 Request Entity Too Large"));		    break;		}		if (fread(dst + pos, 1, file_size, f) != file_size) { 		    con.reset();		    con.append(ERROR_TEXT("500 Internal server error"));		    break;		}		fclose(f);		if (!con.sock->write(dst, con.reply_buf_used)		    || !keepConnectionAlive) 		{ 		    delete con.sock;		    con.sock = NULL;		    return true;		}	    }	} else if (strncmp(buf, "POST ", 5) == 0) { 	    char* body = p;	  ScanNextPart:	    int n = length < buf + size - p		? length : buf + size - p;	    while (--n >= 0 && *p != '\r' && *p != '\n') 	    { 		p += 1;	    }	    if (n < 0 && p - body != length) { 				if (size >= sizeof(buf) - 1) { 		    con.append(ERROR_TEXT("413 Request Entity Too Large"));		    break;		}			int rc = con.sock->read(p, 1, sizeof(buf) - size - 1, 					connectionHoldTimeout);		if (rc < 0) { 		    delete con.sock;		    con.sock = NULL;		    return true;		}		size += rc;		goto ScanNextPart;	    } else {		if (host == NULL) { 		    host = "localhost";		}		if (!handleRequest(con, body, p, host, result)) { 		    delete con.sock;		    con.sock = NULL;		    return result;		}		while (n >= 0 && (*p == '\n' || *p == '\r')) { 		    p += 1;		    n -= 1;		}	    }	} else { 	    con.append(ERROR_TEXT("405 Method not allowed"));	    break;	}	if (!persistentConnection) { 	    delete con.sock;	    con.sock = NULL;	    return true;	}	    	if (p - buf < (long)size) {	    size -= p - buf;	    memcpy(buf, p, size);	} else { 	    size = 0;	}    }    if (con.sock != NULL) { 	con.sock->write(con.reply_buf, con.reply_buf_used);	con.sock->shutdown();	delete con.sock;	con.sock = NULL;    }    return true;}bool HTTPapi::handleRequest(WWWconnection& con, char* begin, char* end,			    char* host, bool& result){    char buf[64];    char ch = *end;    char* page = con.unpack(begin, end - begin);    if (page != NULL)  { 	con.append("HTTP/1.1 200 OK\r\nContent-Length:       \r\n");	int length_pos = con.reply_buf_used - 8;	con.append(keepConnectionAlive 		   ? "Connection: Keep-Alive\r\n" 		   : "Connection: close\r\n");		sprintf(buf, "http://%s/", host);	con.stub = buf;	result = dispatch(con, page);	char* body = con.reply_buf + length_pos;	char prev_ch = 0;	con.reply_buf[con.reply_buf_used] = '\0';	while ((*body != '\n' || prev_ch != '\n') &&	       (*body != '\r' || prev_ch != '\n') && 	       *body != '\0')	{	    prev_ch = *body++;	}	if (*body == '\0') { 	    con.reset();	    con.append(ERROR_TEXT("500 Internal server error"));	    con.sock->write(con.reply_buf, con.reply_buf_used);	    return false;	}	body += *body == '\n' ? 1 : 2;	sprintf(buf, "%u", 		con.reply_buf_used - (body - con.reply_buf));	memcpy(con.reply_buf + length_pos, 	       buf, strlen(buf));	if (!con.sock->write(con.reply_buf, con.reply_buf_used)) { 	    return false;	}	*end = ch;	return result && keepConnectionAlive;    } else { 	con.append(ERROR_TEXT("Not acceptable"));	con.sock->write(con.reply_buf, con.reply_buf_used);	result = true;	*end = ch;	return false;    }}//----------------------------------------------------void thread_proc QueueManager::handleThread(void* arg){    ((QueueManager*)arg)->handle();}QueueManager::QueueManager(WWWapi&     api, 			   dbDatabase& dbase,			   int         nThreads, 			   int         connectionQueueLen): db(dbase){    assert(nThreads >= 1 && connectionQueueLen >= 1);    this->nThreads = nThreads;    go.open();    done.open();    threads = new dbThread[nThreads];    while (--nThreads >= 0) { 	threads[nThreads].create(handleThread, this);	threads[nThreads].detach();    }    connectionPool = new WWWconnection[connectionQueueLen];    connectionPool[--connectionQueueLen].next = NULL;    while (--connectionQueueLen >= 0) { 	connectionPool[connectionQueueLen].next = 	    &connectionPool[connectionQueueLen+1];    }    freeList = connectionPool;    waitList = NULL;    server = &api;}void QueueManager::start(){    mutex.lock();    while (server != NULL) { 	if (freeList == NULL) { 	    done.reset();	    done.wait(mutex);	    if (server == NULL) { 		break;	    }	    assert(freeList != NULL);	}	WWWconnection* con = freeList;	freeList = con->next;	WWWapi* srv = server;	mutex.unlock();	if (!srv->connect(*con) || server == NULL) { 	    return;	}	mutex.lock();	con->next = waitList;	waitList = con;	go.signal();    }    mutex.unlock();}void QueueManager::handle(){    db.attach();    mutex.lock();    while (true) { 	go.wait(mutex);	WWWapi* api = server;	if (api == NULL) { 	    break;	}	WWWconnection* con = waitList;	assert(con != NULL);	waitList = con->next;	mutex.unlock();	        if (!api->serve(*con)) { 	    stop();	}	mutex.lock();	if (freeList == NULL) { 	    done.signal();	}	con->next = freeList;	freeList = con;    }    mutex.unlock();    db.detach();}void QueueManager::stop() {    mutex.lock();    WWWapi* server = this->server;    this->server = NULL;    server->cancel();    while (--nThreads >= 0) { 	go.signal();    }    done.signal();    mutex.unlock();}QueueManager::~QueueManager(){    go.close();    done.close();    delete[] threads;    delete[] connectionPool;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -