Beispiel #1
0
void
cvolsm_NameToObject (
  qcom_sGet		*get
)
{
  pwr_tStatus		sts;
  gdb_sObject		*op = NULL;
  cdh_sParseName	ParseName;
  cdh_sParseName	*pn;
  net_sNameToObject	*mp = get->data;

  gdb_AssumeUnlocked;

  pn = cdh_ParseName(&sts, &ParseName, mp->poid, mp->name, 0);
  if (pn == NULL) {
    respondError(get, pwr_cNObjid, sts);
    return;
  }

  gdb_ScopeLock {

    /* Don't allow mount translation.  */

    op = vol_NameToObject(&sts, pn, gdb_mLo_owned, mp->trans & ~vol_mTrans_mount);
    if (op == NULL) {
      respondError(get, pwr_cNObjid, sts);
    } else {
      respondObject(get, op, mp->lcount, mp->rcount);
    }

  } gdb_ScopeUnlock;
}
Beispiel #2
0
	void startRetry()
	{
		connect(zhttpRequest, SIGNAL(error()), SLOT(zhttpRequest_error()));
		connect(zhttpRequest, SIGNAL(paused()), SLOT(zhttpRequest_paused()));

		state = WaitingForResponse;

		bool isHttps = (requestData.uri.scheme() == "https");
		QString host = requestData.uri.host();

		QByteArray encPath = requestData.uri.path(QUrl::FullyEncoded).toUtf8();

		// look up the route
		route = domainMap->entry(DomainMap::Http, isHttps, host, encPath);
		if(route.isNull())
		{
			log_warning("requestsession: %p %s has 0 routes", q, qPrintable(host));

			state = WaitingForResponse;
			respondError(502, "Bad Gateway", QString("No route for host: %1").arg(host));
			return;
		}

		log_debug("proxysession: %p %s has %d routes", q, qPrintable(host), route.targets.count());
	}
Beispiel #3
0
	void handleSocket(Session *s)
	{
		if(s->path == "/websocket")
		{
			s->pending = true;
			pendingSessions += s;
			emit q->sessionReady();
			return;
		}
		else
		{
			QList<QByteArray> parts = s->path.mid(1).split('/');
			if(parts.count() == 3)
			{
				QByteArray sid = parts[1];
				QByteArray lastPart = parts[2];

				s->sid = sid;
				s->lastPart = lastPart;
				s->pending = true;
				pendingSessions += s;
				emit q->sessionReady();
				return;
			}

			respondError(s->sock, 404, "Not Found", "Not Found");
		}
	}
ConnCheckWorker::ConnCheckWorker(ZrpcRequest *req, ZrpcManager *proxyControlClient, StatsManager *stats, QObject *parent) :
	Deferred(parent),
	req_(req)
{
	req_->setParent(this);

	QVariantHash args = req_->args();

	if(!args.contains("ids") || args["ids"].type() != QVariant::List)
	{
		respondError("bad-request");
		return;
	}

	QVariantList vids = args["ids"].toList();

	foreach(const QVariant &vid, vids)
	{
		if(vid.type() != QVariant::ByteArray)
		{
			respondError("bad-request");
			return;
		}

		cids_ += QString::fromUtf8(vid.toByteArray());
	}

	foreach(const QString &cid, cids_)
	{
		if(!stats->checkConnection(cid.toUtf8()))
			missing_ += cid;
	}

	if(!missing_.isEmpty())
	{
		// ask the proxy about any cids we don't know about
		Deferred *d = ControlRequest::connCheck(proxyControlClient, missing_, this);
		connect(d, SIGNAL(finished(const DeferredResult &)), SLOT(proxyConnCheck_finished(const DeferredResult &)));
		return;
	}

	doFinish();
}
Beispiel #5
0
	void processRequestInput(Session *s)
	{
		s->reqBody += s->req->readBody(MAX_REQUEST_BODY - s->reqBody.size() + 1);
		if(s->reqBody.size() > MAX_REQUEST_BODY)
		{
			respondError(s->req, 400, "Bad Request", "Request too large.");
			return;
		}

		if(s->req->isInputFinished())
			handleRequest(s);
	}
Beispiel #6
0
void
cvolsm_OidToObject (
  qcom_sGet		*get
)
{
  pwr_tStatus		sts;
  gdb_sObject		*op;
  net_sOidToObject	*mp = get->data;

  gdb_AssumeUnlocked;

  gdb_ScopeLock {

    op = hash_Search(&sts, gdbroot->oid_ht, &mp->oid);
    if (op == NULL || !op->l.flags.b.isOwned) {
      respondError(get, pwr_cNObjid, GDH__NOSUCHOBJ);
    } else {
      respondObject(get, op, mp->lcount, mp->rcount);
    }

  } gdb_ScopeUnlock;
}
Beispiel #7
0
	// emits signals, but safe to delete after
	void trySend()
	{
		QPointer<QObject> self = this;

		stuffToRead = false;

		ZurlResponsePacket resp;

		if(!sentHeader)
		{
			resp.code = hreq->responseCode();
			resp.reason = hreq->responseStatus();
			resp.headers = hreq->responseHeaders();
			sentHeader = true;
		}

		// note: we always set body, even if empty

		if(outStream)
		{
			// note: we skip credits handling if quiet mode

			QByteArray buf;

			if(!quiet)
				buf = hreq->readResponseBody(outCredits);
			else
				buf = hreq->readResponseBody(); // all

			if(!buf.isEmpty())
			{
				if(maxResponseSize != -1 && bytesReceived + buf.size() > maxResponseSize)
				{
					respondError("max-size-exceeded");
					return;
				}
			}

			if(!buf.isNull())
				resp.body = buf;
			else
				resp.body = "";

			bytesReceived += resp.body.size();

			if(!quiet)
				outCredits -= resp.body.size();

			resp.more = (hreq->bytesAvailable() > 0 || !hreq->isFinished());

			if(hreq->bytesAvailable() > 0)
				stuffToRead = true;
		}
		else
		{
			if(!inbuf.isNull())
			{
				resp.body = inbuf;
				inbuf.clear();
			}
			else
				resp.body = "";
		}

		writeResponse(resp);
		if(!self)
			return;

		if(!resp.more)
		{
			cleanup();
			emit q->finished();
		}
	}
Beispiel #8
0
	void respondCannotAccept()
	{
		respondError(500, "Internal Server Error", "Accept service unavailable.");
	}
Beispiel #9
0
	void respondBadRequest(const QString &errorString)
	{
		respondError(400, "Bad Request", errorString);
	}
Beispiel #10
0
	void processIncomingRequest()
	{
		if(state == Prefetching)
		{
			if(prefetchSize > 0)
				in += zhttpRequest->readBody(prefetchSize - in.size());

			if(in.size() >= prefetchSize || zhttpRequest->isInputFinished())
			{
				// we've read enough body to start inspection

				disconnect(zhttpRequest, SIGNAL(readyRead()), this, SLOT(zhttpRequest_readyRead()));

				state = Inspecting;
				requestData.body = in.toByteArray();
				bool truncated = (!zhttpRequest->isInputFinished() || zhttpRequest->bytesAvailable() > 0);

				assert(!inspectRequest);

				if(inspectManager)
				{
					inspectRequest = new InspectRequest(inspectManager, this);

					if(inspectChecker->isInterfaceAvailable())
					{
						connect(inspectRequest, SIGNAL(finished()), SLOT(inspectRequest_finished()));
						inspectChecker->watch(inspectRequest);
						inspectRequest->start(requestData, truncated, route.session);
					}
					else
					{
						inspectChecker->watch(inspectRequest);
						inspectChecker->give(inspectRequest);
						inspectRequest->start(requestData, truncated, route.session);
						inspectRequest = 0;
					}
				}

				if(!inspectRequest)
				{
					log_debug("inspect not available");
					QMetaObject::invokeMethod(this, "doInspectError", Qt::QueuedConnection);
				}
			}
		}
		else if(state == Receiving)
		{
			in += zhttpRequest->readBody(MAX_SHARED_REQUEST_BODY - in.size());

			if(in.size() >= MAX_SHARED_REQUEST_BODY || zhttpRequest->isInputFinished())
			{
				// we've read as much as we can for now. if there is still
				//   more to read, then the engine will notice this and
				//   disallow sharing before passing to proxysession. at that
				//   point, proxysession will read the remainder of the data

				disconnect(zhttpRequest, SIGNAL(readyRead()), this, SLOT(zhttpRequest_readyRead()));

				state = WaitingForResponse;
				requestData.body = in.take();
				emit q->inspected(idata);
			}
		}
		else if(state == ReceivingForAccept)
		{
			QByteArray buf = zhttpRequest->readBody();
			if(in.size() + buf.size() > MAX_ACCEPT_REQUEST_BODY)
			{
				respondError(413, "Request Entity Too Large", QString("Body must not exceed %1 bytes").arg(MAX_ACCEPT_REQUEST_BODY));
				return;
			}

			in += buf;

			if(zhttpRequest->isInputFinished())
			{
				if(acceptManager)
					zhttpRequest->pause();
				else
					respondCannotAccept();
			}
		}
	}
Beispiel #11
0
	/** Responds with messages that are in the json queue for this clients session
	* If the queue is empty, it doesnt send anything and returns false.
	* if it does respond with SOMETHING, even an error-response, it returns true.
    * Use abort to send an empty resonse without looking at the queue at all.
    * When longpoll is set to false, it always responds with data, even if the queue is empty. In this case if wont affect a waiting longpoll netid.
	*/
	bool respondJsonQueue(bool abort=false, bool longpoll=true)
	{
		string jsonStr;
		if (abort)
		{
			//to abort we need to reply with an empty json array:
			DEB(id << " cancelling longpoll");
			jsonStr="[]";
			httpSessionMan.endGet(id, mAuthCookie);
		}
		else
		{
			if (longpoll)
			{
				ThttpCookie authCookieClone=0;
				try
				{
					authCookieClone=mHeaders["x-synapse-authcookie-clone"];
				}
				catch(...){ };

				//check if there are messages in the queue, based on the authcookie from the current request:
				//This function will change authCookie if neccesary and fill jsonStr!
				httpSessionMan.getJsonQueue(id, mAuthCookie, jsonStr, authCookieClone);

				//authcookie was probably expired, respond with error
				if (!mAuthCookie)
				{
					respondError(400, "Session is expired, or session limit reached.");
					return(true);
				}
			}
			else
			{
				//we DO want to respond with something if its there, but we dont want to do long polling
				httpSessionMan.getJsonQueue(mAuthCookie, jsonStr);
				if (jsonStr=="")
					jsonStr="[]";
			}
		}

		if (jsonStr=="")
		{
			//nothing to reply (yet), return false
			return(false);
		}
		else
		{
			//send headers
			Cvar extraHeaders;
			extraHeaders["Content-Length"]=jsonStr.length();
			extraHeaders["Cache-Control"]="no-cache";
			extraHeaders["Content-Type"]="application/json";
			extraHeaders["X-Synapse-Authcookie"]=mAuthCookie;
			sendHeaders(200, extraHeaders);

			//write the json queue
			sendData(asio::buffer(jsonStr));
			return(true);
		}
	}
Beispiel #12
0
	void respondBadRequest(const QString &body)
	{
		respondError(400, "Bad Request", body);
	}
Beispiel #13
0
	void handleRequest(Session *s)
	{
		QString method = s->req->requestMethod();
		log_debug("sockjs request: path=[%s], asUri=[%s]", s->path.data(), s->asUri.toEncoded().data());

		if(method == "OPTIONS")
		{
			respondEmpty(s->req);
		}
		else if(method == "GET" && s->path == "/info")
		{
			quint32 x = (quint32)qrand();

			QVariantMap out;
			out["websocket"] = true;
			out["origins"] = QVariantList() << QString("*:*");
			out["cookie_needed"] = false;
			out["entropy"] = x;
			respondOk(s->req, out);
		}
		else if(method == "GET" && s->path.startsWith("/iframe") && s->path.endsWith(".html"))
		{
			HttpHeaders headers;
			headers += HttpHeader("ETag", iframeHtmlEtag);

			QByteArray ifNoneMatch = s->req->requestHeaders().get("If-None-Match");
			if(ifNoneMatch == iframeHtmlEtag)
			{
				respond(s->req, 304, "Not Modified", headers, QByteArray());
			}
			else
			{
				headers += HttpHeader("Content-Type", "text/html; charset=UTF-8");
				headers += HttpHeader("Cache-Control", "public, max-age=31536000");
				respond(s->req, 200, "OK", headers, iframeHtml);
			}
		}
		else
		{
			QList<QByteArray> parts = s->path.mid(1).split('/');
			if(parts.count() == 3)
			{
				QByteArray sid = parts[1];
				QByteArray lastPart = parts[2];

				Session *existing = sessionsById.value(sid);
				if(existing)
				{
					if(existing->ext)
					{
						// give to external session
						ZhttpRequest *req = s->req;
						QByteArray body = s->reqBody.toByteArray();
						QByteArray jsonpCallback = s->jsonpCallback;
						s->req->disconnect(this);
						s->req = 0;
						removeSession(s);

						existing->ext->handleRequest(req, jsonpCallback, lastPart, body);
					}
					else
					{
						if(existing->closeValue.isValid())
						{
							respondOk(s->req, existing->closeValue, "c", s->jsonpCallback);
						}
						else
						{
							QVariantList out;
							out += 2010;
							out += QString("Another connection still open");
							respondOk(s->req, out, "c", s->jsonpCallback);
						}
					}
					return;
				}

				if((method == "POST" && lastPart == "xhr") || ((method == "GET" || method == "POST") && lastPart == "jsonp"))
				{
					if(lastPart == "jsonp" && s->jsonpCallback.isEmpty())
					{
						respondError(s->req, 400, "Bad Request", "Bad Request");
						return;
					}

					s->sid = sid;
					s->lastPart = lastPart;
					sessionsById.insert(s->sid, s);
					s->pending = true;
					pendingSessions += s;
					emit q->sessionReady();
					return;
				}
			}

			respondError(s->req, 404, "Not Found", "Not Found");
		}
	}
Beispiel #14
0
	// Received new data:
	void received(int id, asio::streambuf &readBuffer, std::size_t bytesTransferred)
	{
		string dataStr(boost::asio::buffer_cast<const char*>(readBuffer.data()), readBuffer.size());
		string error;

		//we're expecting a new request:
		if (mState==REQUEST || mState==WAIT_LONGPOLL)
		{
			//if there is still an outstanding longpoll, cancel it:
			if (mState==WAIT_LONGPOLL)
			{
				respond(true);
			}

			//resize data to first delimiter:
			dataStr.resize(dataStr.find(delimiter)+delimiter.length());
			readBuffer.consume(dataStr.length());

			DEB(id << " got http REQUEST: \n" << dataStr);

			//determine the kind of request:
 			smatch what;
 			if (!regex_search(
 				dataStr,
 				what,
 				boost::regex("^(GET|POST) ([^? ]*)([^ ]*) HTTP/(1..)$")
 			))
 			{
				error="Cant parse request.";
 			}
			else
			{
				mRequestType=what[1];
				mRequestUrl=what[2];
				mRequestQuery=what[3];
				mRequestVersion=what[4];
				DEB("REQUEST query: " << mRequestQuery);

				//create a regex iterator for http headers
				mHeaders.clear();
				boost::sregex_iterator headerI(
					dataStr.begin(),
					dataStr.end(),
					boost::regex("^([[:alnum:]-]*): (.*?)$")
				);

				//parse http headers
				while (headerI!=sregex_iterator())
				{
					string header=(*headerI)[1].str();
					string value=(*headerI)[2].str();

					//headers handling is lowercase in synapse!
					transform(header.begin(), header.end(), header.begin(), ::tolower);

					mHeaders[header]=value;
					headerI++;
				}

				//this header MUST be set on longpoll requests:
				//if the client doesnt has one yet, httpSessionMan will assign a new one.
				try
				{
					mAuthCookie=mHeaders["x-synapse-authcookie"];
				}
				catch(...)
				{
					mAuthCookie=0;
				}

				//proceed based on requestType:
				//a GET or empty POST:
				if (mRequestType=="GET" || (int)mHeaders["content-length"]==0)
				{
					if (respond())
					{
						mState=REQUEST;
					}
					else
					{
						DEB(id << " is now waiting for longpoll results");
						mState=WAIT_LONGPOLL;
					}
					return;
				}
				//a POST with content:
				else
				{
					if ( (int)mHeaders["content-length"]<0  || (int)mHeaders["content-length"] > config["maxContent"] )
					{
						error="Invalid Content-Length";
					}
					else
					{
						//change state to read the contents of the POST:
						mState=CONTENT;
						return;
					}
				}
			}
		}
		else
		//we're expecting the contents of a POST request.
		if (mState==CONTENT)
		{
			if (readBuffer.size() < mHeaders["content-length"])
			{
				error="Didn't receive enough content-bytes!";
				DEB(id <<  " ERROR: Expected " << mHeaders["content-length"].str() << " bytes, but only got: " << bytesTransferred);
			}
			else
			{
				dataStr.resize(mHeaders["content-length"]);
				readBuffer.consume(mHeaders["content-length"]);
				DEB(id << " got http CONTENT with length=" << dataStr.size() << ": \n" << dataStr);

				//POST to the special send url?
				if (mRequestUrl=="/synapse/send")
				{
					error=httpSessionMan.sendMessage(mAuthCookie, dataStr);
					if (error=="")
					{
						//DONT:respond with jsondata if we have something in the queue anyways
						//DONT:respondJsonQueue(false,false);
						//we cant do this, because then the order of messages isnt garanteed. so just respond with a boring empty string:
						respondString(200, "");
					}
					else
						respondError(400, error);

					mState=REQUEST;
					return;
				}
				else
				{
					//ignore whatever is posted, and just respond normally:
					DEB(id << " ignored POST content");
					if (respond())
						mState=REQUEST;
					else
						mState=WAIT_LONGPOLL;
					return;
				}
			}
		}

		//ERROR(id << " had error while processing http data: " << error);
		error="Bad request: "+error;
		respondError(400, error);
		doDisconnect();
		return;

	}
Beispiel #15
0
void Config::request(ServerRequest::ptr request, Access access)
{
    const std::string &method = request->request().requestLine.method;
    if (method == POST) {
        if (access != READWRITE) {
            respondError(request, FORBIDDEN);
            return;
        }
        if (request->request().entity.contentType.type != "application" ||
            request->request().entity.contentType.subtype != "x-www-form-urlencoded") {
            respondError(request, UNSUPPORTED_MEDIA_TYPE);
            return;
        }
        Stream::ptr requestStream = request->requestStream();
        requestStream.reset(new LimitedStream(requestStream, 65536));
        MemoryStream requestBody;
        transferStream(requestStream, requestBody);
        std::string queryString;
        queryString.resize(requestBody.buffer().readAvailable());
        requestBody.buffer().copyOut(&queryString[0], requestBody.buffer().readAvailable());

        bool failed = false;
        URI::QueryString qs(queryString);
        for (URI::QueryString::const_iterator it = qs.begin();
            it != qs.end();
            ++it) {
            ConfigVarBase::ptr var = Mordor::Config::lookup(it->first);
            if (var && !var->fromString(it->second))
                failed = true;
        }
        if (failed) {
            respondError(request, HTTP::FORBIDDEN,
                "One or more new values were not accepted");
            return;
        }
        // Fall through
    }
    if (method == GET || method == HEAD || method == POST) {
        Format format = HTML;
        URI::QueryString qs;
        if (request->request().requestLine.uri.queryDefined())
            qs = request->request().requestLine.uri.queryString();
        URI::QueryString::const_iterator it = qs.find("alt");
        if (it != qs.end() && it->second == "json")
            format = JSON;
        // TODO: use Accept to indicate JSON
        switch (format) {
            case HTML:
            {
                request->response().status.status = OK;
                request->response().entity.contentType = MediaType("text", "html");
                if (method == HEAD) {
                    if (request->request().requestLine.ver == Version(1, 1) &&
                        isAcceptable(request->request().request.te, "chunked", true)) {
                        request->response().general.transferEncoding.push_back("chunked");
                    }
                    return;
                }
                Stream::ptr response = request->responseStream();
                response.reset(new BufferedStream(response));
                response->write("<html><body><table>\n", 20);
                Mordor::Config::visit(boost::bind(access == READWRITE ?
                    &eachConfigVarHTMLWrite : &eachConfigVarHTML, _1,
                    response));
                response->write("</table></body></html>", 22);
                response->close();
                break;
            }
            case JSON:
            {
                JSON::Object root;
                Mordor::Config::visit(boost::bind(&eachConfigVarJSON, _1, boost::ref(root)));
                std::ostringstream os;
                os << root;
                std::string str = os.str();
                request->response().status.status = OK;
                request->response().entity.contentType = MediaType("application", "json");
                request->response().entity.contentLength = str.size();
                if (method != HEAD) {
                    request->responseStream()->write(str.c_str(), str.size());
                    request->responseStream()->close();
                }
                break;
            }
            default:
                MORDOR_NOTREACHED();
        }
    } else {
        respondError(request, METHOD_NOT_ALLOWED);
    }
}
Beispiel #16
0
	void respondLengthRequired(const QString &body)
	{
		respondError(411, "Length Required", body);
	}
Beispiel #17
0
	void handleRequest(ZhttpRequest *_req, const QByteArray &jsonpCallback, const QByteArray &lastPart, const QByteArray &body)
	{
		connect(_req, SIGNAL(bytesWritten(int)), SLOT(req_bytesWritten(int)));
		connect(_req, SIGNAL(error()), SLOT(req_error()));

		if(lastPart == "xhr" || lastPart == "jsonp")
		{
			if(req)
			{
				QVariantList out;
				out += 2010;
				out += QString("Another connection still open");

				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, out, "c", jsonpCallback);
				return;
			}

			if(peerClosed)
			{
				QVariantList out;
				out += 3000;
				out += QString("Client already closed connection");

				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, out, "c", jsonpCallback);
				return;
			}

			req = _req;
			requests.insert(req, new RequestItem(req, jsonpCallback, RequestItem::Receive));
			keepAliveTimer->start(KEEPALIVE_TIMEOUT * 1000);

			tryWrite();
		}
		else if(lastPart == "xhr_send" || lastPart == "jsonp_send")
		{
			// only allow one outstanding send request at a time
			if(findFirstSendRequest())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondError(_req, 400, "Bad Request", "Already sending");
				return;
			}

			QByteArray param;

			if(_req->requestMethod() == "POST")
			{
				if(lastPart == "xhr_send")
				{
					// assume json
					param = body;
				}
				else // jsonp_send
				{
					// assume form encoded
					foreach(const QByteArray &kv, body.split('&'))
					{
						int at = kv.indexOf('=');
						if(at == -1)
							continue;
						if(QUrl::fromPercentEncoding(kv.mid(0, at)) == "d")
						{
							param = QUrl::fromPercentEncoding(kv.mid(at + 1)).toUtf8();
							break;
						}
					}
				}
			}
			else // GET
			{
				QUrlQuery query(_req->requestUri());
				param = query.queryItemValue("d").toUtf8();
			}

			QJsonParseError error;
			QJsonDocument doc = QJsonDocument::fromJson(param, &error);
			if(error.error != QJsonParseError::NoError || !doc.isArray())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondError(_req, 400, "Bad Request", "Payload expected");
				return;
			}

			QVariantList messages = doc.array().toVariantList();

			QList<Frame> frames;
			int bytes = 0;
			foreach(const QVariant &vmessage, messages)
			{
				if(vmessage.type() != QVariant::String)
				{
					requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
					respondError(_req, 400, "Bad Request", "Payload expected");
					return;
				}

				QByteArray data = vmessage.toString().toUtf8();
				if(data.size() > BUFFER_SIZE)
				{
					requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
					respondError(_req, 400, "Bad Request", "Message too large");
					return;
				}

				frames += Frame(Frame::Text, data, false);
				bytes += data.size();
			}

			if(frames.isEmpty())
			{
				requests.insert(_req, new RequestItem(_req, jsonpCallback, RequestItem::Background, true));
				respondOk(_req, QString("ok"), jsonpCallback);
				return;
			}

			RequestItem *ri = new RequestItem(_req, jsonpCallback, RequestItem::Send);
			requests.insert(_req, ri);
			ri->sendFrames = frames;
			ri->sendBytes = bytes;

			tryRead();
		}
Beispiel #18
0
static void
respondObject (
  qcom_sGet		*get,
  gdb_sObject		*op,
  pwr_tInt32		lcount,
  pwr_tInt32		rcount
)
{
  pwr_tStatus		sts;
  qcom_sPut		put;
  gdb_sObject		*pop;
  net_sObjectR		*rsp;
  net_sGobject		*gop;
  net_sGobject		*go[net_cObjectMaxCount];
  pwr_tUInt32		count;
  pwr_tUInt32		pcount;
  pwr_tUInt32		size;
  pwr_tInt32		i;
  pool_sQlink		*sol;
  gdb_sObject		*sop;
      
  gdb_AssumeLocked;

  /* The parents must be first in the message, so the receiver can link
     the cache objects. They must be in top-down-order. */

  pop = op;
  pcount = 0;
  count = 0;
  while (pop->g.oid.oix != pwr_cNObjectIx && count < net_cObjectMaxCount - 1) {
    pop = pool_Address(NULL, gdbroot->pool, pop->l.por);
    go[count++] = &pop->g;
  }

  pcount = count;
  pop = pool_Address(NULL, gdbroot->pool, op->l.por);

  if (pop != NULL) {
    /* Left siblings. (At most lcount of them.) */

    for (
      i = 0, sol = pool_Qpred(NULL, gdbroot->pool, &op->u.n.sib_ll);
      i < lcount && sol != &pop->u.n.sib_lh && count < net_cObjectMaxCount - 1;
      i++, sol = pool_Qpred(NULL, gdbroot->pool, sol)
    ) {
      sop = pool_Qitem(sol, gdb_sObject, u.n.sib_ll);
      go[count++] = &sop->g;
    }

    /* Right siblings. (At most rcount of them.) */

    for (
      i = 0, sol = pool_Qsucc(NULL, gdbroot->pool, &op->u.n.sib_ll);
      i < rcount && sol != &pop->u.n.sib_lh && count < net_cObjectMaxCount - 1;
      i++, sol = pool_Qsucc(NULL, gdbroot->pool, sol)
    ) {
      sop = pool_Qitem(sol, gdb_sObject, u.n.sib_ll);
      go[count++] = &sop->g;
    }
  }

  /* Build response message.  */

  size = sizeof(net_sObjectR) + count * sizeof(net_sGobject);
  rsp = net_Alloc(&sts, &put, size, net_eMsg_objectR);
  if (rsp == NULL) {
    printf("NETH: could not allocate pams buffer for Cache send response, sts: %d\n", sts);
    respondError(get, op->g.oid, sts);
    return;
  }
  gop = &rsp->g[0];

  /* Copy parent objects.  */
  for (i = pcount - 1; i >= 0; i--)
    *gop++ = *(go[i]);

  /* Copy target object.  */
  *gop++ = op->g;

  /* Copy sibling objects.  */
  for (i = pcount; i < count; i++)
    *gop++ = *(go[i]);

  rsp->sts    = sts;
  rsp->oid    = op->g.oid;
  rsp->count  = count + 1;

  if (!net_Reply(&sts, get, &put, 0))
    errh_Bugcheck(sts, "net_Reply");
}
Beispiel #19
0
	/** Respond by sending a file relative to the wwwdir/
	*/
	bool respondFile(string path)
	{
		Cvar extraHeaders;

		//FIXME: do a better way of checking/securing the path. Inode verification? Or compare with a filelist?
		if (path.find("..")!=string::npos)
		{
			respondError(403, "Path contains illegal characters");
			return(true);
		}

		//default path?
		if (path=="/")
		{
			path=config["indexFile"].str();
		}

		string localPath;
		localPath="wwwdir/"+path;

		struct stat statResults;
		int statError=stat(localPath.c_str(), &statResults);
		if (statError)
		{
			respondError(404, "Error while statting or file not found: " + path);
			return(true);
		}

		if (! (S_ISREG(statResults.st_mode)) )
		{
			respondError(404, "Path " + path + " is not a regular file");
			return(true);
		}

		ifstream inputFile(localPath.c_str(), std::ios::in | std::ios::binary);
		if (!inputFile.good() )
		{
			respondError(404, "Error while opening " + path );
			return(true);
		}

		//determine content-type
		smatch what;
		if (regex_search(
			path,
			what,
			boost::regex("([^.]*$)")
		))
		{
			string extention=what[1];
			if (config["contentTypes"].isSet(extention))
			{
				extraHeaders["content-type"]=config["contentTypes"][extention];
				DEB("Content type of ." << extention << " is " << config["contentTypes"][extention].str());
			}
			else
			{
				WARNING("Cannot determine content-type of ." << extention << " files");
			}
		}

		//determine filesize
		inputFile.seekg (0, ios::end);
		int fileSize=inputFile.tellg();
		inputFile.seekg (0, ios::beg);
		extraHeaders["Content-Length"]=fileSize;

		//enable browser caching with the right headers:
		extraHeaders["Cache-Control"]="public, max-age=290304000";
		getHttpDate(extraHeaders["Date"].str());

		sendHeaders(200, extraHeaders);



		DEB(id << " sending CONTENT of " << path);
		char buf[4096];
		//TODO: is there a better way to do this?
		int sendSize=0;
		while (inputFile.good())
		{
			inputFile.read(buf	,sizeof(buf));
			if (!sendData(asio::buffer(buf, inputFile.gcount())))
			{
				break;
			}
			sendSize+=inputFile.gcount();
		}

		if (sendSize!=fileSize)
		{
			ERROR(id <<  " error during file transfer, disconnecting");
			doDisconnect();
		}

		return true;
	}