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

📄 http.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 3 页
字号:
// Copyright (c) Xerox Corporation 1998. All rights reserved.//// License is granted to copy, to use, and to make and to use derivative// works for research and evaluation purposes, provided that Xerox is// acknowledged in all documentation pertaining to any such copy or// derivative work. Xerox grants no other licenses expressed or// implied. The Xerox trade name should not be used in any advertising// without its written permission. //// XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE// MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE// FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without// express or implied warranty of any kind.//// These notices must be retained in any copies of any part of this// software. //// Implementation of the HTTP agent. We want a separate agent for HTTP because// we are interested in (detailed) HTTP headers, instead of just request and // response patterns.//// $Header: /nfs/jade/vint/CVSROOT/ns-2/webcache/http.cc,v 1.18 1999/08/24 04:16:23 haoboy Exp $#include <stdlib.h>#include <assert.h>#include <string.h>#include <stdarg.h>#include "tclcl.h"#include "agent.h"#include "app.h"#include "tcp-simple.h"#include "http.h"#include "http-aux.h"#include "trace.h"#include "tcpapp.h"#include "mcache.h"//----------------------------------------------------------------------// Http Application//// Allows multiple concurrent HTTP connections//----------------------------------------------------------------------static class HttpAppClass : public TclClass {public:        HttpAppClass() : TclClass("Http") {}        TclObject* create(int, const char*const*) {		return (new HttpApp());	}} class_http_app;// What states should be in a http agent?HttpApp::HttpApp() : log_(0){	bind("id_", &id_);	// Map a client address to a particular TCP agent	tpa_ = new Tcl_HashTable;	Tcl_InitHashTable(tpa_, TCL_ONE_WORD_KEYS);}HttpApp::~HttpApp(){	if (tpa_ != NULL) {		Tcl_DeleteHashTable(tpa_);		delete tpa_;	}}int HttpApp::add_cnc(HttpApp* client, TcpApp *agt){	int newEntry = 1;	Tcl_HashEntry *he = Tcl_CreateHashEntry(tpa_, 						(const char *)client->id(),						&newEntry);	if (he == NULL) 		return -1;	if (newEntry)		Tcl_SetHashValue(he, (ClientData)agt);	return 0;}void HttpApp::delete_cnc(HttpApp* client){	Tcl_HashEntry *he = Tcl_FindHashEntry(tpa_,(const char *)client->id());	if (he != NULL) {		TcpApp *cnc = (TcpApp *)Tcl_GetHashValue(he);		Tcl_DeleteHashEntry(he);		delete cnc;	}}TcpApp* HttpApp::lookup_cnc(HttpApp* client){	Tcl_HashEntry *he = 		Tcl_FindHashEntry(tpa_, (const char *)client->id());	if (he == NULL)		return NULL;	return (TcpApp *)Tcl_GetHashValue(he);}// Basic functionalities: int HttpApp::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "id") == 0) {			if (argc == 3) {				id_ = atoi(argv[2]);				tcl.resultf("%d", id_);			} else				tcl.resultf("%d", id_);			return TCL_OK;		} else if (strcmp(argv[1], "log") == 0) {			// Return the name of the log channel			if (log_ != NULL)				tcl.resultf("%s", Tcl_GetChannelName(log_));			else				tcl.result("");			return TCL_OK;		}	} else if (argc == 3) {		if (strcmp(argv[1], "get-modtime") == 0) {			double mt;			if (pool_->get_mtime(argv[2], mt) != -1) {				tcl.resultf("%.17g", mt);				return TCL_OK;			} else 				return TCL_ERROR;		} else if (strcmp(argv[1], "exist-page") == 0) { 			tcl.resultf("%d", pool_->exist_page(argv[2]));			return TCL_OK;		} else if (strcmp(argv[1], "get-size") == 0) {			int size;			if (pool_->get_size(argv[2], size) != -1) {				tcl.resultf("%d", size);				return TCL_OK;			} else 				return TCL_ERROR;		} else if (strcmp(argv[1], "get-age") == 0) {			double age;			if (pool_->get_age(argv[2], age) != -1) {				tcl.resultf("%.17g", age);				return TCL_OK;			} else 				return TCL_ERROR;		} else if (strcmp(argv[1], "get-cachetime") == 0) {			double et;			if (pool_->get_etime(argv[2], et) != -1) {				tcl.resultf("%.17g", et);				return TCL_OK;			} else 				return TCL_ERROR;		} else if (strcmp(argv[1], "get-page") == 0) {			char buf[4096];			if (pool_->get_pageinfo(argv[2], buf) != -1) {				tcl.resultf("%s", buf);				return TCL_OK;			} else 				return TCL_ERROR;		} else if (strcmp(argv[1], "get-cnc") == 0) {			/*			 * <http> get-cnc <client>			 *			 * Given the communication party, get the tcp agent 			 * connected to it.			 */			HttpApp *client = 				(HttpApp *)TclObject::lookup(argv[2]);			TcpApp *cnc = (TcpApp *)lookup_cnc(client);			if (cnc == NULL)				tcl.result("");			else 				tcl.resultf("%s", cnc->name());			return TCL_OK;		} else if (strcmp(argv[1], "set-pagepool") == 0) {			pool_ = (ClientPagePool*)TclObject::lookup(argv[2]);			if (pool_ != NULL) 				return TCL_OK;			else 				return TCL_ERROR;		} else if (strcmp(argv[1], "is-connected") == 0) {			/*			 * <http> is-connected <server>			 */			HttpApp *a = (HttpApp*)TclObject::lookup(argv[2]);			TcpApp *cnc = (TcpApp*)lookup_cnc(a);			if (cnc == NULL) 				tcl.result("0");			else 				tcl.result("1");			return TCL_OK;		} else if (strcmp(argv[1], "is-valid") == 0) {			ClientPage *pg = 				(ClientPage *)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d is-valid: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			tcl.resultf("%d", pg->is_valid());			return TCL_OK;		} else if (strcmp(argv[1], "log") == 0) {			int mode;			log_ = Tcl_GetChannel(tcl.interp(), 					      (char*)argv[2], &mode);			if (log_ == 0) {				tcl.resultf("%d: invalid log file handle %s\n",					    id_, argv[2]);				return TCL_ERROR;			}			return TCL_OK;		} else if (strcmp(argv[1], "disconnect") == 0) {			/*			 * <http> disconnect <client> 			 * Delete the association of source and sink TCP.			 */			HttpApp *client = 				(HttpApp *)TclObject::lookup(argv[2]);			delete_cnc(client);			return TCL_OK;		} else if (strcmp(argv[1], "get-pagetype") == 0) {			/*			 * <http> get-pagetype <pageid>			 * return the page type			 */			ClientPage *pg = 				(ClientPage*)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d get-pagetype: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			switch (pg->type()) {			case HTML:				tcl.result("HTML");				break;			case MEDIA:				tcl.result("MEDIA");				break;			default:				fprintf(stderr, "Unknown page type %d", 					pg->type());				return TCL_ERROR;			}			return TCL_OK;		} else if (strcmp(argv[1], "get-layer") == 0) {			// Assume the page is a MediaPage			MediaPage *pg = (MediaPage *)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d get-layer: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			if (pg->type() != MEDIA) {				tcl.resultf("%d get-layer %s not a media page",					    id_, argv[2]);				return TCL_ERROR;			}			tcl.resultf("%d", pg->num_layer());			return TCL_OK;		}	} else if (argc == 4) {		if (strcmp(argv[1], "connect") == 0) {			/*			 * <http> connect <client> <ts>			 *			 * Associate a TCP agent with the given client. 			 * <ts> is the agent used to send packets out.			 * We assume two-way TCP connection, therefore we 			 * only need one agent.			 */			HttpApp *client = 				(HttpApp *)TclObject::lookup(argv[2]);			TcpApp *cnc = (TcpApp *)TclObject::lookup(argv[3]);			if (add_cnc(client, cnc)) {				tcl.resultf("%s: failed to connect to %s", 					    name_, argv[2]);				return TCL_ERROR;			}			// Set data delivery target			cnc->target() = (Process*)this;			return TCL_OK;		} else if (strcmp(argv[1], "set-modtime") == 0) {			double mt = strtod(argv[3], NULL);			if (pool_->set_mtime(argv[2], mt) != -1)				return TCL_OK;			else 				return TCL_ERROR;		} else if (strcmp(argv[1], "set-cachetime") == 0) {			double et = Scheduler::instance().clock();			if (pool_->set_etime(argv[2], et) != -1)				return TCL_OK;			else 				return TCL_ERROR;		}	} else {		if (strcmp(argv[1], "send") == 0) {			/*			 * <http> send <client> <bytes> <callback> 			 */			HttpApp *client = 				(HttpApp *)TclObject::lookup(argv[2]);			if (client == NULL) {				tcl.add_errorf("%s: bad client name %s",					       name_, argv[2]);				return TCL_ERROR;			}			int bytes = atoi(argv[3]);			TcpApp *cnc = (TcpApp *)lookup_cnc(client);			if (cnc == NULL) {				//tcl.resultf("%s: no connection to client %s",				//	    name_, argv[2]);				// Tolerate it				return TCL_OK;			}			char *buf = strdup(argv[4]);			HttpNormalData *d = 				new HttpNormalData(id_, bytes, buf);			cnc->send(bytes, d);			// delete d;			free(buf);			return TCL_OK;				} else if (strcmp(argv[1], "enter-page") == 0) {			ClientPage* pg = pool_->enter_page(argc, argv);			if (pg == NULL)				return TCL_ERROR;			else 				return TCL_OK;		} else if (strcmp(argv[1], "evTrace") == 0) { 			char buf[1024], *p;			if (log_ != 0) {				sprintf(buf, TIME_FORMAT" i %d ", 				  Trace::round(Scheduler::instance().clock()), 					id_);				p = &(buf[strlen(buf)]);				for (int i = 2; i < argc; i++) {					strcpy(p, argv[i]);					p += strlen(argv[i]);					*(p++) = ' ';				}				// Stick in a newline.				*(p++) = '\n', *p = 0;				Tcl_Write(log_, buf, p-buf);			}			return TCL_OK;		}	}	return TclObject::command(argc, argv);}void HttpApp::log(const char* fmt, ...){	// Don't do anything if we don't have a log file.	if (log_ == 0) 		return;	char buf[10240], *p;	sprintf(buf, TIME_FORMAT" i %d ", 		Trace::round(Scheduler::instance().clock()), id_);	p = &(buf[strlen(buf)]);	va_list ap;	va_start(ap, fmt);	vsprintf(p, fmt, ap);	Tcl_Write(log_, buf, strlen(buf));}void HttpApp::process_data(int, AppData* data){	if (data == NULL) 		return;	switch (data->type()) {	case HTTP_NORMAL: {		HttpNormalData *tmp = (HttpNormalData*)data;		Tcl::instance().eval(tmp->str());		break;	}	default:		fprintf(stderr, "Bad http invalidation data type %d\n", 			data->type());		abort();		break;	}}//----------------------------------------------------------------------// Clients//----------------------------------------------------------------------static class HttpClientClass : public TclClass {public:	HttpClientClass() : TclClass("Http/Client") {}        TclObject* create(int, const char*const*) {		return (new HttpClient());	}} class_httpclient_app;//----------------------------------------------------------------------// Servers//----------------------------------------------------------------------static class HttpServerClass : public TclClass {public:        HttpServerClass() : TclClass("Http/Server") {}        TclObject* create(int, const char*const*) {		return (new HttpServer());	}} class_httpserver_app;static class HttpInvalServerClass : public TclClass {public:        HttpInvalServerClass() : TclClass("Http/Server/Inval") {}        TclObject* create(int, const char*const*) {		return (new HttpInvalServer());	}} class_httpinvalserver_app;static class HttpYucInvalServerClass : public TclClass {public:        HttpYucInvalServerClass() : TclClass("Http/Server/Inval/Yuc") {}        TclObject* create(int, const char*const*) {		return (new HttpYucInvalServer());	}} class_httpyucinvalserver_app;HttpYucInvalServer::HttpYucInvalServer() :	inv_sender_(0), invlist_(0), num_inv_(0){	bind("hb_interval_", &hb_interval_);	bind("enable_upd_", &enable_upd_);	bind("Ca_", &Ca_);	bind("Cb_", &Cb_);	bind("push_thresh_", &push_thresh_);	bind("push_high_bound_", &push_high_bound_);	bind("push_low_bound_", &push_low_bound_);}int HttpYucInvalServer::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	switch (argv[1][0]) {	case 'a': 		if (strcmp(argv[1], "add-inval-sender") == 0) {			HttpUInvalAgent *tmp = 				(HttpUInvalAgent *)TclObject::lookup(argv[2]);			if (tmp == NULL) {				tcl.resultf("Non-existent agent %s", argv[2]);				return TCL_ERROR;			}			inv_sender_ = tmp;			return TCL_OK;		} if (strcmp(argv[1], "add-inv") == 0) {			/*			 * <server> add-inv <pageid> <modtime>			 */			double mtime = strtod(argv[3], NULL);			add_inv(argv[2], mtime);			return TCL_OK;		}		break;	case 'c': 		if (strcmp(argv[1], "count-request") == 0) {			ClientPage *pg = 				(ClientPage *)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d count-request: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			pg->count_request(Cb_, push_high_bound_);			log("S NTF p %s v %d\n", argv[2], pg->counter());			return TCL_OK;		} else if (strcmp(argv[1], "count-inval") == 0) {			ClientPage *pg = 				(ClientPage *)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d count-inval: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			pg->count_inval(Ca_, push_low_bound_);			log("S NTF p %s v %d\n", argv[2], pg->counter());			return TCL_OK;		} 		break;	case 'i': 		if (strcmp(argv[1], "is-pushable") == 0) {			ClientPage *pg = 				(ClientPage *)pool_->get_page(argv[2]);			if (pg == NULL) {				tcl.resultf("%d is-pushable: No page %s", 					    id_, argv[2]);				return TCL_ERROR;			}			if (pg->is_mpush() && 			    (Scheduler::instance().clock() - pg->mpush_time() >			     HTTP_HBEXPIRE_COUNT*hb_interval_)) {				// If mandatory push timer expires, stop push				pg->clear_mpush();				fprintf(stderr, 					"server %d timeout mpush\n", id_);

⌨️ 快捷键说明

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