mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 00:07:59 +02:00
committed latest 1.3 snapshot
This commit is contained in:
113
Net/src/AbstractHTTPRequestHandler.cpp
Normal file
113
Net/src/AbstractHTTPRequestHandler.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// AbstractHTTPRequestHandler.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/AbstractHTTPRequestHandler.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
// Module: AbstractHTTPRequestHandler
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/AbstractHTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/HTMLForm.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
|
||||
|
||||
using Poco::NumberFormatter;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
AbstractHTTPRequestHandler::AbstractHTTPRequestHandler():
|
||||
_pRequest(0),
|
||||
_pResponse(0),
|
||||
_pForm(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbstractHTTPRequestHandler::~AbstractHTTPRequestHandler()
|
||||
{
|
||||
delete _pForm;
|
||||
}
|
||||
|
||||
|
||||
void AbstractHTTPRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
|
||||
{
|
||||
_pRequest = &request;
|
||||
_pResponse = &response;
|
||||
if (authenticate())
|
||||
{
|
||||
run();
|
||||
}
|
||||
else
|
||||
{
|
||||
sendErrorResponse(HTTPResponse::HTTP_UNAUTHORIZED, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AbstractHTTPRequestHandler::authenticate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HTMLForm& AbstractHTTPRequestHandler::form()
|
||||
{
|
||||
if (!_pForm)
|
||||
_pForm = new HTMLForm(request(), request().stream());
|
||||
|
||||
return *_pForm;
|
||||
}
|
||||
|
||||
|
||||
void AbstractHTTPRequestHandler::sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message)
|
||||
{
|
||||
response().setStatusAndReason(status);
|
||||
std::string statusAndReason(NumberFormatter::format(static_cast<int>(response().getStatus())));
|
||||
statusAndReason += " - ";
|
||||
statusAndReason += response().getReason();
|
||||
std::string page("<HTML><HEAD><TITLE>");
|
||||
page += statusAndReason;
|
||||
page += "</TITLE></HEAD><BODY><H1>";
|
||||
page += statusAndReason;
|
||||
page += "</H1>";
|
||||
page += "<P>";
|
||||
page += message;
|
||||
page += "</P></BODY></HTML>";
|
||||
response().sendBuffer(page.data(), page.size());
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// FilePartSource.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/FilePartSource.cpp#7 $
|
||||
// $Id: //poco/Main/Net/src/FilePartSource.cpp#8 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Messages
|
||||
@@ -48,7 +48,7 @@ namespace Net {
|
||||
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path):
|
||||
_istr(path.c_str(), std::ios::in | std::ios::binary)
|
||||
_istr(path)
|
||||
{
|
||||
Path p(path);
|
||||
_filename = p.getFileName();
|
||||
@@ -59,7 +59,7 @@ FilePartSource::FilePartSource(const std::string& path):
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
|
||||
PartSource(mediaType),
|
||||
_istr(path.c_str(), std::ios::in | std::ios::binary)
|
||||
_istr(path)
|
||||
{
|
||||
Path p(path);
|
||||
_filename = p.getFileName();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPClientSession.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPClientSession.cpp#16 $
|
||||
// $Id: //poco/Main/Net/src/HTTPClientSession.cpp#18 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPClient
|
||||
@@ -57,6 +57,7 @@ namespace Net {
|
||||
HTTPClientSession::HTTPClientSession():
|
||||
_port(HTTPSession::HTTP_PORT),
|
||||
_proxyPort(HTTPSession::HTTP_PORT),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
_mustReconnect(false),
|
||||
_expectResponseBody(false),
|
||||
@@ -70,6 +71,7 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
|
||||
HTTPSession(socket),
|
||||
_port(HTTPSession::HTTP_PORT),
|
||||
_proxyPort(HTTPSession::HTTP_PORT),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
_mustReconnect(false),
|
||||
_expectResponseBody(false),
|
||||
@@ -83,6 +85,7 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
|
||||
_host(address.host().toString()),
|
||||
_port(address.port()),
|
||||
_proxyPort(HTTPSession::HTTP_PORT),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
_mustReconnect(false),
|
||||
_expectResponseBody(false),
|
||||
@@ -96,6 +99,7 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port)
|
||||
_host(host),
|
||||
_port(port),
|
||||
_proxyPort(HTTPSession::HTTP_PORT),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
_mustReconnect(false),
|
||||
_expectResponseBody(false),
|
||||
@@ -159,13 +163,19 @@ void HTTPClientSession::setProxyPort(Poco::UInt16 port)
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout)
|
||||
{
|
||||
_keepAliveTimeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
|
||||
{
|
||||
delete _pResponseStream;
|
||||
_pResponseStream = 0;
|
||||
|
||||
bool keepAlive = getKeepAlive();
|
||||
if (connected() && !keepAlive || _mustReconnect)
|
||||
if (connected() && !keepAlive || mustReconnect())
|
||||
{
|
||||
close();
|
||||
_mustReconnect = false;
|
||||
@@ -204,6 +214,7 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
|
||||
_pRequestStream = new HTTPOutputStream(*this);
|
||||
request.write(*_pRequestStream);
|
||||
}
|
||||
_lastRequest.update();
|
||||
return *_pRequestStream;
|
||||
}
|
||||
|
||||
@@ -250,7 +261,9 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length)
|
||||
{
|
||||
try
|
||||
{
|
||||
return HTTPSession::write(buffer, length);
|
||||
int rc = HTTPSession::write(buffer, length);
|
||||
_reconnect = false;
|
||||
return rc;
|
||||
}
|
||||
catch (NetException&)
|
||||
{
|
||||
@@ -258,11 +271,12 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length)
|
||||
{
|
||||
close();
|
||||
reconnect();
|
||||
return HTTPSession::write(buffer, length);
|
||||
int rc = HTTPSession::write(buffer, length);
|
||||
_reconnect = false;
|
||||
return rc;
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
_reconnect = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -319,4 +333,15 @@ void HTTPClientSession::setRequestStream(std::ostream* pRequestStream)
|
||||
}
|
||||
|
||||
|
||||
bool HTTPClientSession::mustReconnect() const
|
||||
{
|
||||
if (!_mustReconnect)
|
||||
{
|
||||
Poco::Timestamp now;
|
||||
return _keepAliveTimeout <= now - _lastRequest;
|
||||
}
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPServerConnection.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerConnection.cpp#9 $
|
||||
// $Id: //poco/Main/Net/src/HTTPServerConnection.cpp#10 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
@@ -36,8 +36,8 @@
|
||||
|
||||
#include "Poco/Net/HTTPServerConnection.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/HTTPServerResponseImpl.h"
|
||||
#include "Poco/Net/HTTPRequestHandler.h"
|
||||
#include "Poco/Net/HTTPRequestHandlerFactory.h"
|
||||
#include "Poco/Net/HTTPServerParams.h"
|
||||
@@ -76,8 +76,9 @@ void HTTPServerConnection::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
HTTPServerRequest request(session, _pParams);
|
||||
HTTPServerResponse response(session);
|
||||
HTTPServerResponseImpl response(session);
|
||||
HTTPServerRequestImpl request(response, session, _pParams);
|
||||
|
||||
response.setVersion(request.getVersion());
|
||||
response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive() && session.canKeepAlive());
|
||||
if (!server.empty())
|
||||
@@ -116,7 +117,7 @@ void HTTPServerConnection::run()
|
||||
|
||||
void HTTPServerConnection::sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status)
|
||||
{
|
||||
HTTPServerResponse response(session);
|
||||
HTTPServerResponseImpl response(session);
|
||||
response.setVersion(HTTPMessage::HTTP_1_1);
|
||||
response.setStatusAndReason(status);
|
||||
response.setKeepAlive(false);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPServerRequest.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerRequest.cpp#6 $
|
||||
// $Id: //poco/Main/Net/src/HTTPServerRequest.cpp#8 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
@@ -35,56 +35,19 @@
|
||||
|
||||
|
||||
#include "Poco/Net/HTTPServerRequest.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPStream.h"
|
||||
#include "Poco/Net/HTTPFixedLengthStream.h"
|
||||
#include "Poco/Net/HTTPChunkedStream.h"
|
||||
#include "Poco/Net/HTTPServerParams.h"
|
||||
#include "Poco/String.h"
|
||||
|
||||
|
||||
using Poco::icompare;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
HTTPServerRequest::HTTPServerRequest(HTTPServerSession& session, HTTPServerParams* pParams):
|
||||
_pStream(0),
|
||||
_pParams(pParams),
|
||||
_clientAddress(session.clientAddress()),
|
||||
_serverAddress(session.serverAddress())
|
||||
HTTPServerRequest::HTTPServerRequest()
|
||||
{
|
||||
poco_check_ptr (_pParams);
|
||||
|
||||
_pParams->duplicate();
|
||||
|
||||
HTTPHeaderInputStream hs(session);
|
||||
read(hs);
|
||||
|
||||
if (getChunkedTransferEncoding())
|
||||
_pStream = new HTTPChunkedInputStream(session);
|
||||
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
|
||||
_pStream = new HTTPFixedLengthInputStream(session, getContentLength());
|
||||
else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD)
|
||||
_pStream = new HTTPFixedLengthInputStream(session, 0);
|
||||
else
|
||||
_pStream = new HTTPInputStream(session);
|
||||
}
|
||||
|
||||
|
||||
HTTPServerRequest::~HTTPServerRequest()
|
||||
{
|
||||
_pParams->release();
|
||||
delete _pStream;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPServerRequest::expectContinue() const
|
||||
{
|
||||
return has("Expect") && icompare(get("Expect"), "100-continue") == 0;
|
||||
}
|
||||
|
||||
|
||||
|
92
Net/src/HTTPServerRequestImpl.cpp
Normal file
92
Net/src/HTTPServerRequestImpl.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// HTTPServerRequestImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerRequestImpl.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
// Module: HTTPServerRequestImpl
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPStream.h"
|
||||
#include "Poco/Net/HTTPFixedLengthStream.h"
|
||||
#include "Poco/Net/HTTPChunkedStream.h"
|
||||
#include "Poco/Net/HTTPServerParams.h"
|
||||
#include "Poco/String.h"
|
||||
|
||||
|
||||
using Poco::icompare;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponse& response, HTTPServerSession& session, HTTPServerParams* pParams):
|
||||
_response(response),
|
||||
_pStream(0),
|
||||
_pParams(pParams),
|
||||
_clientAddress(session.clientAddress()),
|
||||
_serverAddress(session.serverAddress())
|
||||
{
|
||||
poco_check_ptr (_pParams);
|
||||
|
||||
_pParams->duplicate();
|
||||
|
||||
HTTPHeaderInputStream hs(session);
|
||||
read(hs);
|
||||
|
||||
if (getChunkedTransferEncoding())
|
||||
_pStream = new HTTPChunkedInputStream(session);
|
||||
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
|
||||
_pStream = new HTTPFixedLengthInputStream(session, getContentLength());
|
||||
else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD)
|
||||
_pStream = new HTTPFixedLengthInputStream(session, 0);
|
||||
else
|
||||
_pStream = new HTTPInputStream(session);
|
||||
}
|
||||
|
||||
|
||||
HTTPServerRequestImpl::~HTTPServerRequestImpl()
|
||||
{
|
||||
_pParams->release();
|
||||
delete _pStream;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPServerRequestImpl::expectContinue() const
|
||||
{
|
||||
return has("Expect") && icompare(get("Expect"), "100-continue") == 0;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPServerResponse.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerResponse.cpp#10 $
|
||||
// $Id: //poco/Main/Net/src/HTTPServerResponse.cpp#12 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
@@ -35,135 +35,19 @@
|
||||
|
||||
|
||||
#include "Poco/Net/HTTPServerResponse.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPStream.h"
|
||||
#include "Poco/Net/HTTPFixedLengthStream.h"
|
||||
#include "Poco/Net/HTTPChunkedStream.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using Poco::File;
|
||||
using Poco::Timestamp;
|
||||
using Poco::NumberFormatter;
|
||||
using Poco::StreamCopier;
|
||||
using Poco::OpenFileException;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
HTTPServerResponse::HTTPServerResponse(HTTPServerSession& session):
|
||||
_session(session),
|
||||
_pStream(0)
|
||||
HTTPServerResponse::HTTPServerResponse()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HTTPServerResponse::~HTTPServerResponse()
|
||||
{
|
||||
delete _pStream;
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponse::sendContinue()
|
||||
{
|
||||
HTTPHeaderOutputStream hs(_session);
|
||||
hs << getVersion() << " 100 Continue\r\n\r\n";
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HTTPServerResponse::send()
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
if (getChunkedTransferEncoding())
|
||||
{
|
||||
HTTPHeaderOutputStream hs(_session);
|
||||
write(hs);
|
||||
_pStream = new HTTPChunkedOutputStream(_session);
|
||||
}
|
||||
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
|
||||
{
|
||||
Poco::CountingOutputStream cs;
|
||||
write(cs);
|
||||
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars());
|
||||
write(*_pStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
setKeepAlive(false);
|
||||
write(*_pStream);
|
||||
}
|
||||
return *_pStream;
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponse::sendFile(const std::string& path, const std::string& mediaType)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
File f(path);
|
||||
Timestamp dateTime = f.getLastModified();
|
||||
File::FileSize length = f.getSize();
|
||||
setDate(dateTime);
|
||||
setContentLength(static_cast<int>(length));
|
||||
setContentType(mediaType);
|
||||
setChunkedTransferEncoding(false);
|
||||
|
||||
std::ifstream istr(path.c_str(), std::ios::binary | std::ios::in);
|
||||
if (istr.good())
|
||||
{
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
StreamCopier::copyStream(istr, *_pStream);
|
||||
}
|
||||
else throw OpenFileException(path);
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponse::sendBuffer(const void* pBuffer, std::size_t length)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setContentLength(static_cast<int>(length));
|
||||
setChunkedTransferEncoding(false);
|
||||
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
_pStream->write(static_cast<const char*>(pBuffer), static_cast<std::streamsize>(length));
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponse::redirect(const std::string& uri)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setStatusAndReason(HTTPResponse::HTTP_FOUND);
|
||||
set("Location", uri);
|
||||
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponse::requireAuthentication(const std::string& realm)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED);
|
||||
std::string auth("Basic realm=\"");
|
||||
auth.append(realm);
|
||||
auth.append("\"");
|
||||
set("WWW-Authenticate", auth);
|
||||
}
|
||||
|
||||
|
||||
|
170
Net/src/HTTPServerResponseImpl.cpp
Normal file
170
Net/src/HTTPServerResponseImpl.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// HTTPServerResponseImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerResponseImpl.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
// Module: HTTPServerResponseImpl
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/HTTPServerResponseImpl.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/Net/HTTPStream.h"
|
||||
#include "Poco/Net/HTTPFixedLengthStream.h"
|
||||
#include "Poco/Net/HTTPChunkedStream.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/FileStream.h"
|
||||
|
||||
|
||||
using Poco::File;
|
||||
using Poco::Timestamp;
|
||||
using Poco::NumberFormatter;
|
||||
using Poco::StreamCopier;
|
||||
using Poco::OpenFileException;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
HTTPServerResponseImpl::HTTPServerResponseImpl(HTTPServerSession& session):
|
||||
_session(session),
|
||||
_pStream(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HTTPServerResponseImpl::~HTTPServerResponseImpl()
|
||||
{
|
||||
delete _pStream;
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponseImpl::sendContinue()
|
||||
{
|
||||
HTTPHeaderOutputStream hs(_session);
|
||||
hs << getVersion() << " 100 Continue\r\n\r\n";
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HTTPServerResponseImpl::send()
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
if (getChunkedTransferEncoding())
|
||||
{
|
||||
HTTPHeaderOutputStream hs(_session);
|
||||
write(hs);
|
||||
_pStream = new HTTPChunkedOutputStream(_session);
|
||||
}
|
||||
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
|
||||
{
|
||||
Poco::CountingOutputStream cs;
|
||||
write(cs);
|
||||
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars());
|
||||
write(*_pStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
setKeepAlive(false);
|
||||
write(*_pStream);
|
||||
}
|
||||
return *_pStream;
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string& mediaType)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
File f(path);
|
||||
Timestamp dateTime = f.getLastModified();
|
||||
File::FileSize length = f.getSize();
|
||||
setDate(dateTime);
|
||||
setContentLength(static_cast<int>(length));
|
||||
setContentType(mediaType);
|
||||
setChunkedTransferEncoding(false);
|
||||
|
||||
Poco::FileInputStream istr(path);
|
||||
if (istr.good())
|
||||
{
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
StreamCopier::copyStream(istr, *_pStream);
|
||||
}
|
||||
else throw OpenFileException(path);
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponseImpl::sendBuffer(const void* pBuffer, std::size_t length)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setContentLength(static_cast<int>(length));
|
||||
setChunkedTransferEncoding(false);
|
||||
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
_pStream->write(static_cast<const char*>(pBuffer), static_cast<std::streamsize>(length));
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponseImpl::redirect(const std::string& uri)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setStatusAndReason(HTTPResponse::HTTP_FOUND);
|
||||
set("Location", uri);
|
||||
|
||||
_pStream = new HTTPOutputStream(_session);
|
||||
write(*_pStream);
|
||||
}
|
||||
|
||||
|
||||
void HTTPServerResponseImpl::requireAuthentication(const std::string& realm)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED);
|
||||
std::string auth("Basic realm=\"");
|
||||
auth.append(realm);
|
||||
auth.append("\"");
|
||||
set("WWW-Authenticate", auth);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPServerSession.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerSession.cpp#7 $
|
||||
// $Id: //poco/Main/Net/src/HTTPServerSession.cpp#8 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTPServer
|
||||
@@ -48,6 +48,8 @@ HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParam
|
||||
_keepAliveTimeout(pParams->getKeepAliveTimeout()),
|
||||
_maxKeepAliveRequests(pParams->getMaxKeepAliveRequests())
|
||||
{
|
||||
setTimeout(pParams->getTimeout());
|
||||
this->socket().setReceiveTimeout(pParams->getTimeout());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPSession.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPSession.cpp#10 $
|
||||
// $Id: //poco/Main/Net/src/HTTPSession.cpp#12 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTP
|
||||
@@ -158,10 +158,7 @@ int HTTPSession::receive(char* buffer, int length)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_socket.poll(_timeout, Socket::SELECT_READ))
|
||||
return _socket.receiveBytes(buffer, length);
|
||||
else
|
||||
throw TimeoutException();
|
||||
return _socket.receiveBytes(buffer, length);
|
||||
}
|
||||
catch (Poco::Exception& exc)
|
||||
{
|
||||
@@ -192,6 +189,7 @@ bool HTTPSession::connected() const
|
||||
void HTTPSession::connect(const SocketAddress& address)
|
||||
{
|
||||
_socket.connect(address, _timeout);
|
||||
_socket.setReceiveTimeout(_timeout);
|
||||
_socket.setNoDelay(true);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// RemoteSyslogChannel.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/RemoteSyslogChannel.cpp#2 $
|
||||
// $Id: //poco/Main/Net/src/RemoteSyslogChannel.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Logging
|
||||
@@ -49,6 +49,8 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
const std::string RemoteSyslogChannel::BSD_TIMEFORMAT("%b %f %H:%M:%S");
|
||||
const std::string RemoteSyslogChannel::SYSLOG_TIMEFORMAT("%Y-%m-%dT%H:%M:%S.%i%z");
|
||||
const std::string RemoteSyslogChannel::PROP_NAME("name");
|
||||
const std::string RemoteSyslogChannel::PROP_FACILITY("facility");
|
||||
const std::string RemoteSyslogChannel::PROP_FORMAT("format");
|
||||
@@ -129,14 +131,14 @@ void RemoteSyslogChannel::log(const Message& msg)
|
||||
m += '>';
|
||||
if (_bsdFormat)
|
||||
{
|
||||
m += Poco::DateTimeFormatter::format(msg.getTime(), "%w %f %H:%M:%S");
|
||||
m += Poco::DateTimeFormatter::format(msg.getTime(), BSD_TIMEFORMAT);
|
||||
m += ' ';
|
||||
m += _host;
|
||||
}
|
||||
else
|
||||
{
|
||||
m += "1 "; // version
|
||||
m += Poco::DateTimeFormatter::format(msg.getTime(), "%Y-%m-%dT%H:%M:%S.%i%z");
|
||||
m += Poco::DateTimeFormatter::format(msg.getTime(), SYSLOG_TIMEFORMAT);
|
||||
m += ' ';
|
||||
m += _host;
|
||||
m += ' ';
|
||||
|
524
Net/src/RemoteSyslogListener.cpp
Normal file
524
Net/src/RemoteSyslogListener.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
//
|
||||
// RemoteSyslogListener.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/RemoteSyslogListener.cpp#6 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Logging
|
||||
// Module: RemoteSyslogListener
|
||||
//
|
||||
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/RemoteSyslogListener.h"
|
||||
#include "Poco/Net/RemoteSyslogChannel.h"
|
||||
#include "Poco/Net/DatagramSocket.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#include "Poco/Notification.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/LoggingFactory.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
//
|
||||
// MessageNotification
|
||||
//
|
||||
|
||||
|
||||
class MessageNotification: public Poco::Notification
|
||||
{
|
||||
public:
|
||||
MessageNotification(const std::string& msg)
|
||||
{
|
||||
_msg = msg;
|
||||
}
|
||||
|
||||
~MessageNotification()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& message() const
|
||||
{
|
||||
return _msg;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// RemoteUDPListener
|
||||
//
|
||||
|
||||
|
||||
class RemoteUDPListener: public Poco::Runnable
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
WAITTIME_MILLISEC = 1000,
|
||||
BUFFER_SIZE = 65536
|
||||
};
|
||||
|
||||
RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port);
|
||||
~RemoteUDPListener();
|
||||
|
||||
void run();
|
||||
void safeStop();
|
||||
|
||||
private:
|
||||
Poco::NotificationQueue& _queue;
|
||||
DatagramSocket _socket;
|
||||
bool _stopped;
|
||||
};
|
||||
|
||||
|
||||
RemoteUDPListener::RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port):
|
||||
_queue(queue),
|
||||
_socket(Poco::Net::SocketAddress(Poco::Net::IPAddress(), port)),
|
||||
_stopped(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RemoteUDPListener::~RemoteUDPListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void RemoteUDPListener::run()
|
||||
{
|
||||
poco_assert (_stopped);
|
||||
|
||||
Poco::Buffer<char> buffer(BUFFER_SIZE);
|
||||
_stopped = false;
|
||||
Poco::Timespan waitTime(WAITTIME_MILLISEC* 1000);
|
||||
while (!_stopped)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_socket.poll(waitTime, Socket::SELECT_READ))
|
||||
{
|
||||
int byteCnt = _socket.receiveBytes(buffer.begin(), BUFFER_SIZE);
|
||||
if (byteCnt > 0)
|
||||
{
|
||||
_queue.enqueueNotification(new MessageNotification(std::string(buffer.begin(), byteCnt)));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// lazy exception catching
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RemoteUDPListener::safeStop()
|
||||
{
|
||||
_stopped = true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SyslogParser
|
||||
//
|
||||
|
||||
|
||||
class SyslogParser: public Poco::Runnable
|
||||
{
|
||||
public:
|
||||
static const std::string NILVALUE;
|
||||
|
||||
enum
|
||||
{
|
||||
WAITTIME_MILLISEC = 1000
|
||||
};
|
||||
|
||||
SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener);
|
||||
~SyslogParser();
|
||||
|
||||
void run();
|
||||
void safeStop();
|
||||
|
||||
static Poco::Message::Priority convert(RemoteSyslogChannel::Severity severity);
|
||||
|
||||
private:
|
||||
void parse(const std::string& msg);
|
||||
void parsePrio(const std::string& msg, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac);
|
||||
void parseNew(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos);
|
||||
void parseBSD(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos);
|
||||
|
||||
static std::string parseUntilSpace(const std::string& msg, std::size_t& pos);
|
||||
/// Parses until it encounters the next space char, returns the string from pos, excluding space
|
||||
/// pos will point past the space char
|
||||
|
||||
private:
|
||||
Poco::NotificationQueue& _queue;
|
||||
bool _stopped;
|
||||
RemoteSyslogListener* _pListener;
|
||||
};
|
||||
|
||||
|
||||
const std::string SyslogParser::NILVALUE("-");
|
||||
|
||||
|
||||
SyslogParser::SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener):
|
||||
_queue(queue),
|
||||
_stopped(true),
|
||||
_pListener(pListener)
|
||||
{
|
||||
poco_check_ptr (_pListener);
|
||||
}
|
||||
|
||||
|
||||
SyslogParser::~SyslogParser()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::run()
|
||||
{
|
||||
poco_assert (_stopped);
|
||||
_stopped = false;
|
||||
while (!_stopped)
|
||||
{
|
||||
try
|
||||
{
|
||||
Poco::AutoPtr<Poco::Notification> pNf(_queue.waitDequeueNotification(WAITTIME_MILLISEC));
|
||||
if (pNf)
|
||||
{
|
||||
Poco::AutoPtr<MessageNotification> pMsgNf = pNf.cast<MessageNotification>();
|
||||
parse(pMsgNf->message());
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception&)
|
||||
{
|
||||
// parsing exception, what should we do?
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::safeStop()
|
||||
{
|
||||
_stopped = true;
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parse(const std::string& msg)
|
||||
{
|
||||
// <int> -> int: lower 3 bits severity, upper bits: facility
|
||||
std::size_t pos = 0;
|
||||
RemoteSyslogChannel::Severity severity;
|
||||
RemoteSyslogChannel::Facility fac;
|
||||
parsePrio(msg, pos, severity, fac);
|
||||
|
||||
// the next field decide if we parse an old BSD message or a new syslog message
|
||||
// BSD: expects a month value in string form: Jan, Feb...
|
||||
// SYSLOG expects a version number: 1
|
||||
|
||||
if (std::isdigit(msg[pos]))
|
||||
{
|
||||
parseNew(msg, severity, fac, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseBSD(msg, severity, fac, pos);
|
||||
}
|
||||
poco_assert (pos == msg.size());
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parsePrio(const std::string& msg, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac)
|
||||
{
|
||||
poco_assert (pos < msg.size());
|
||||
poco_assert (msg[pos] == '<');
|
||||
++pos;
|
||||
std::size_t start = pos;
|
||||
|
||||
while (pos < msg.size() && std::isdigit(msg[pos]))
|
||||
++pos;
|
||||
|
||||
poco_assert (msg[pos] == '>');
|
||||
poco_assert (pos - start > 0);
|
||||
std::string valStr = msg.substr(start, pos - start);
|
||||
++pos; // skip the >
|
||||
|
||||
int val = Poco::NumberParser::parse(valStr);
|
||||
poco_assert (val >= 0 && val <= (RemoteSyslogChannel::SYSLOG_LOCAL7 + RemoteSyslogChannel::SYSLOG_DEBUG));
|
||||
|
||||
Poco::UInt16 pri = static_cast<Poco::UInt16>(val);
|
||||
// now get the lowest 3 bits
|
||||
severity = static_cast<RemoteSyslogChannel::Severity>(pri & 0x0007u);
|
||||
fac = static_cast<RemoteSyslogChannel::Facility>(pri & 0xfff8u);
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parseNew(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos)
|
||||
{
|
||||
Poco::Message::Priority prio = convert(severity);
|
||||
// rest of the unparsed header is:
|
||||
// VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID
|
||||
std::string versionStr(parseUntilSpace(msg, pos));
|
||||
std::string timeStr(parseUntilSpace(msg, pos)); // can be the nilvalue!
|
||||
std::string hostName(parseUntilSpace(msg, pos));
|
||||
std::string appName(parseUntilSpace(msg, pos));
|
||||
std::string procId(parseUntilSpace(msg, pos));
|
||||
std::string msgId(parseUntilSpace(msg, pos));
|
||||
std::string message(msg.substr(pos));
|
||||
pos = msg.size();
|
||||
Poco::DateTime date;
|
||||
int tzd = 0;
|
||||
bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::SYSLOG_TIMEFORMAT, timeStr, date, tzd);
|
||||
Poco::Message logEntry(msgId, message, prio);
|
||||
logEntry["host"] = hostName;
|
||||
logEntry["app"] = appName;
|
||||
|
||||
if (hasDate)
|
||||
logEntry.setTime(date.timestamp());
|
||||
int lval(0);
|
||||
Poco::NumberParser::tryParse(procId, lval);
|
||||
logEntry.setPid(lval);
|
||||
_pListener->log(logEntry);
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos)
|
||||
{
|
||||
Poco::Message::Priority prio = convert(severity);
|
||||
// rest of the unparsed header is:
|
||||
// "%b %f %H:%M:%S" SP hostname|ipaddress
|
||||
// detect three spaces
|
||||
int spaceCnt = 0;
|
||||
std::size_t start = pos;
|
||||
while (spaceCnt < 3 && pos < msg.size())
|
||||
{
|
||||
if (msg[pos] == ' ')
|
||||
{
|
||||
spaceCnt++;
|
||||
if (spaceCnt == 1)
|
||||
{
|
||||
// size must be 3 chars for month
|
||||
if (pos - start != 3)
|
||||
{
|
||||
// probably a shortened time value, or the hostname
|
||||
// assume hostName
|
||||
Poco::Message logEntry(msg.substr(start, pos-start), msg.substr(pos+1), prio);
|
||||
_pListener->log(logEntry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (spaceCnt == 2)
|
||||
{
|
||||
// a day value!
|
||||
if (!(std::isdigit(msg[pos-1]) && (std::isdigit(msg[pos-2]) || std::isspace(msg[pos-2]))))
|
||||
{
|
||||
// assume the next field is a hostname
|
||||
spaceCnt = 3;
|
||||
}
|
||||
}
|
||||
if (pos + 1 < msg.size() && msg[pos+1] == ' ')
|
||||
{
|
||||
// we have two spaces when the day value is smaller than 10!
|
||||
++pos; // skip one
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
std::string timeStr(msg.substr(start, pos-start-1));
|
||||
int tzd(0);
|
||||
Poco::DateTime date;
|
||||
int year = date.year(); // year is not included, use the current one
|
||||
bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::BSD_TIMEFORMAT, timeStr, date, tzd);
|
||||
if (hasDate)
|
||||
{
|
||||
int m = date.month();
|
||||
int d = date.day();
|
||||
int h = date.hour();
|
||||
int min = date.minute();
|
||||
int sec = date.second();
|
||||
date = Poco::DateTime(year, m, d, h, min, sec);
|
||||
}
|
||||
// next entry is host SP
|
||||
std::string hostName(parseUntilSpace(msg, pos));
|
||||
|
||||
// TAG: at most 32 alphanumeric chars, ANY non alphannumeric indicates start of message content
|
||||
// ignore: treat everything as content
|
||||
std::string message(msg.substr(pos));
|
||||
pos = msg.size();
|
||||
Poco::Message logEntry(hostName, message, prio);
|
||||
logEntry.setTime(date.timestamp());
|
||||
_pListener->log(logEntry);
|
||||
}
|
||||
|
||||
|
||||
std::string SyslogParser::parseUntilSpace(const std::string& msg, std::size_t& pos)
|
||||
{
|
||||
std::size_t start = pos;
|
||||
while (pos < msg.size() && !std::isspace(msg[pos]))
|
||||
++pos;
|
||||
// skip space
|
||||
++pos;
|
||||
return msg.substr(start, pos-start-1);
|
||||
}
|
||||
|
||||
|
||||
Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case RemoteSyslogChannel::SYSLOG_EMERGENCY:
|
||||
return Poco::Message::PRIO_FATAL;
|
||||
case RemoteSyslogChannel::SYSLOG_ALERT:
|
||||
return Poco::Message::PRIO_FATAL;
|
||||
case RemoteSyslogChannel::SYSLOG_CRITICAL:
|
||||
return Poco::Message::PRIO_CRITICAL;
|
||||
case RemoteSyslogChannel::SYSLOG_ERROR:
|
||||
return Poco::Message::PRIO_ERROR;
|
||||
case RemoteSyslogChannel::SYSLOG_WARNING:
|
||||
return Poco::Message::PRIO_WARNING;
|
||||
case RemoteSyslogChannel::SYSLOG_NOTICE:
|
||||
return Poco::Message::PRIO_NOTICE;
|
||||
case RemoteSyslogChannel::SYSLOG_INFORMATIONAL:
|
||||
return Poco::Message::PRIO_INFORMATION;
|
||||
case RemoteSyslogChannel::SYSLOG_DEBUG:
|
||||
return Poco::Message::PRIO_DEBUG;
|
||||
}
|
||||
throw Poco::LogicException("Illegal severity value in message");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RemoteSyslogListener
|
||||
//
|
||||
|
||||
|
||||
const std::string RemoteSyslogListener::PROP_PORT("port");
|
||||
|
||||
|
||||
RemoteSyslogListener::RemoteSyslogListener():
|
||||
_pListener(0),
|
||||
_pParser(0),
|
||||
_listener(),
|
||||
_parser(),
|
||||
_queue(),
|
||||
_port(RemoteSyslogChannel::SYSLOG_PORT)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port):
|
||||
_pListener(0),
|
||||
_pParser(0),
|
||||
_listener(),
|
||||
_parser(),
|
||||
_queue(),
|
||||
_port(port)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RemoteSyslogListener::~RemoteSyslogListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void RemoteSyslogListener::setProperty(const std::string& name, const std::string& value)
|
||||
{
|
||||
if (name == PROP_PORT)
|
||||
{
|
||||
int val = Poco::NumberParser::parse(value);
|
||||
if (val > 0 && val < 65536)
|
||||
_port = static_cast<Poco::UInt16>(val);
|
||||
else
|
||||
throw Poco::InvalidArgumentException("Not a valid port number", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
SplitterChannel::setProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string RemoteSyslogListener::getProperty(const std::string& name) const
|
||||
{
|
||||
if (name == PROP_PORT)
|
||||
return Poco::NumberFormatter::format(_port);
|
||||
else
|
||||
return SplitterChannel::getProperty(name);
|
||||
}
|
||||
|
||||
|
||||
void RemoteSyslogListener::open()
|
||||
{
|
||||
SplitterChannel::open();
|
||||
_pParser = new SyslogParser(_queue, this);
|
||||
_pListener = new RemoteUDPListener(_queue, _port);
|
||||
_parser.start(*_pParser);
|
||||
_listener.start(*_pListener);
|
||||
}
|
||||
|
||||
|
||||
void RemoteSyslogListener::close()
|
||||
{
|
||||
if (_pListener && _pParser)
|
||||
{
|
||||
_pListener->safeStop();
|
||||
_pParser->safeStop();
|
||||
_queue.clear();
|
||||
_listener.join();
|
||||
_parser.join();
|
||||
delete _pListener;
|
||||
delete _pParser;
|
||||
_pListener = 0;
|
||||
_pParser = 0;
|
||||
}
|
||||
SplitterChannel::close();
|
||||
}
|
||||
|
||||
|
||||
void RemoteSyslogListener::registerChannel()
|
||||
{
|
||||
Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogListener", new Poco::Instantiator<RemoteSyslogListener, Poco::Channel>);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/SocketImpl.cpp#17 $
|
||||
// $Id: //poco/Main/Net/src/SocketImpl.cpp#19 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Sockets
|
||||
|
Reference in New Issue
Block a user