Browse Source

- Changed forwarder implementation

- Added preparation for fixed forwading tables
- Updated TODO list (forwading+)
master
Artyom Beilis 14 years ago
parent
commit
83c884c061
7 changed files with 129 additions and 84 deletions
  1. +1
    -1
      CMakeLists.txt
  2. +4
    -0
      TODO
  3. +46
    -0
      cppcms/forwarder.h
  4. +0
    -40
      private/connection_forwarder.h
  5. +0
    -2
      src/cgi_api.cpp
  6. +69
    -39
      src/forwarder.cpp
  7. +9
    -2
      tests/forwarder_test.cpp

+ 1
- 1
CMakeLists.txt View File

@@ -303,7 +303,7 @@ set(CPPCMS_SOURCES
src/tcp_messenger.cpp
src/tcp_connector.cpp
src/tcp_cache_server.cpp
src/connection_forwarder.cpp
src/forwarder.cpp
src/session_pool.cpp
src/base_encryptor.cpp
src/hmac_encryptor.cpp


+ 4
- 0
TODO View File

@@ -5,7 +5,11 @@
- Sessions **Interface**
- Encoding Validators
- Url Dispatcher
- File upload:
- create better pre-upload validation
- create saving file to file
- Reintergrate Sessions over TCP/IP
- Forwarding management
- Prefork-support
- form.*
Date-Time

+ 46
- 0
cppcms/forwarder.h View File

@@ -0,0 +1,46 @@
#ifndef CPPCMS_FORWARDER_H
#define CPPCMS_FORWARDER_H

#include <cppcms/defs.h>
#include <booster/hold_ptr.h>
#include <booster/shared_ptr.h>
#include <booster/noncopyable.h>
#include <booster/thread.h>
#include <string>
#include <map>

namespace cppcms {
class mount_point;
namespace http {
class context;
}
class CPPCMS_API forwarder {
public:
forwarder();
~forwarder();
void add_forwarding_rule(booster::shared_ptr<mount_point> p,std::string const &ip,int port);
void remove_forwarding_rule(booster::shared_ptr<mount_point> p);

typedef std::pair<std::string,int> address_type;
address_type check_forwading_rules(std::string const &h,std::string const &s,std::string const &p);
private:
typedef std::map<booster::shared_ptr<mount_point> ,address_type> rules_type;
rules_type rules_;
booster::shared_mutex mutex_;
struct _data;
booster::hold_ptr<_data> d;
};

///
/// Forward the connection handled by \a cont to other node at IP \a ip listenning to on port \a port over
/// SCGI protocol.
///
/// The context must be released first by calling cppcms::application::release_context() and it should not
/// be used after this function call
///
void CPPCMS_API forward_connection(booster::shared_ptr<http::context> cont,std::string const &ip,int port);
}



#endif

+ 0
- 40
private/connection_forwarder.h View File

@@ -1,40 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCMS_CONNECTION_FORWARDER_H
#define CPPCMS_CONNECTION_FORWARDER_H

#include <cppcms/application.h>

namespace cppcms {

class CPPCMS_API connection_forwarder : public application {
public:
connection_forwarder(cppcms::service &srv,std::string const &ip,int port);
~connection_forwarder();
virtual void main(std::string);
private:

struct _data;
booster::hold_ptr<_data> d;
std::string ip_;
int port_;
};
}

#endif

+ 0
- 2
src/cgi_api.cpp View File

@@ -107,8 +107,6 @@ void connection::load_content(booster::system::error_code const &e,http::context
std::string content_type = getenv("CONTENT_TYPE");
std::string s_content_length=getenv("CONTENT_LENGTH");

BOOSTER_DEBUG("cgi") << getenv("REQUEST_METHOD") << " " << getenv("REQUEST_URI");

long long content_length = s_content_length.empty() ? 0 : atoll(s_content_length.c_str());

if(content_length < 0) {


src/connection_forwarder.cpp → src/forwarder.cpp View File

@@ -17,10 +17,11 @@
//
///////////////////////////////////////////////////////////////////////////////
#define CPPCMS_SOURCE
#include "connection_forwarder.h"
#include <cppcms/forwarder.h>
#include <cppcms/http_context.h>
#include <cppcms/http_request.h>
#include <cppcms/http_response.h>
#include <cppcms/mount_point.h>
#include <cppcms/service.h>
#include "service_impl.h"
#include <cppcms/url_dispatcher.h>
@@ -136,52 +137,81 @@ namespace cppcms {
io::socket socket_;
std::vector<char> input_;
};
} // impl

struct connection_forwarder::_data {};
std::string make_scgi_header(std::map<std::string,std::string> const &env,size_t addon_size)
{
std::string env_str;
env_str.reserve(1000);

connection_forwarder::connection_forwarder(cppcms::service &srv,std::string const &ip,int port) :
application(srv),
ip_(ip),
port_(port)
{
}
connection_forwarder::~connection_forwarder()
{
}
void connection_forwarder::main(std::string unused)
{
booster::shared_ptr<http::context> con = release_context();
std::string env_str;
env_str.reserve(1000);
std::map<std::string,std::string>::const_iterator cl;

std::pair<void *,size_t> post = con->request().raw_post_data();
std::map<std::string,std::string> const &env = con->connection().getenv();
std::map<std::string,std::string>::const_iterator cl;
cl=env.find("CONTENT_LENGTH");
if(cl!=env.end()) {
env_str.append(cl->first.c_str(),cl->first.size()+1);
env_str.append(cl->second.c_str(),cl->second.size()+1);
}
else {
env_str.append("CONTENT_LENGTH");
env_str.append("\0" "0",3);
}

cl=env.find("CONTENT_LENGTH");
if(cl!=env.end()) {
env_str.append(cl->first.c_str(),cl->first.size()+1);
env_str.append(cl->second.c_str(),cl->second.size()+1);
}
else {
env_str.append("CONTENT_LENGTH");
env_str.append("\0" "0",3);
for(std::map<std::string,std::string>::const_iterator p=env.begin();p!=env.end();++p) {
if(p==cl)
continue;
env_str.append(p->first.c_str(),p->first.size()+1);
env_str.append(p->second.c_str(),p->second.size()+1);
}
std::string header=(boost::format("%1%:",std::locale::classic()) % env_str.size()).str();
header.reserve(header.size()+env_str.size()+addon_size);
header+=env_str;
header+=',';
return header;
}

for(std::map<std::string,std::string>::const_iterator p=env.begin();p!=env.end();++p) {
if(p==cl)
continue;
env_str.append(p->first.c_str(),p->first.size()+1);
env_str.append(p->second.c_str(),p->second.size()+1);
}
std::string header=(boost::format("%1%:",std::locale::classic()) % env_str.size()).str();
header.reserve(header.size()+env_str.size()+post.second);
header+=env_str;
header+=',';
} // impl

void forward_connection(booster::shared_ptr<http::context> con,std::string const &ip,int port)
{

std::map<std::string,std::string> const &env = con->connection().getenv();
std::pair<void *,size_t> post = con->request().raw_post_data();
std::string header = impl::make_scgi_header(env,post.second);
header.append(reinterpret_cast<char *>(post.first),post.second);
booster::shared_ptr<impl::tcp_pipe> pipe(new impl::tcp_pipe(con,ip_,port_));
booster::shared_ptr<impl::tcp_pipe> pipe(new impl::tcp_pipe(con,ip,port));
pipe->async_send_receive(header);
}



struct forwarder::_data {};
forwarder::forwarder()
{
}
forwarder::~forwarder()
{
}
void forwarder::add_forwarding_rule(booster::shared_ptr<mount_point> p,std::string const &ip,int port)
{
booster::unique_lock<booster::shared_mutex> lock(mutex_);
rules_[p]=address_type(ip,port);
}
void forwarder::remove_forwarding_rule(booster::shared_ptr<mount_point> p)
{
booster::unique_lock<booster::shared_mutex> lock(mutex_);
rules_.erase(p);
}
forwarder::address_type forwarder::check_forwading_rules(std::string const &h,std::string const &s,std::string const &p)
{
booster::shared_lock<booster::shared_mutex> lock(mutex_);
for(rules_type::const_iterator it=rules_.begin();it!=rules_.end();++it) {
if(it->first->match(h,s,p).first)
return it->second;
}
return address_type(std::string(),0);
}


};

+ 9
- 2
tests/forwarder_test.cpp View File

@@ -23,7 +23,7 @@
#include <cppcms/http_response.h>
#include <cppcms/http_context.h>
#include <cppcms/json.h>
#include <connection_forwarder.h>
#include <cppcms/forwarder.h>
#include <iostream>
#include "client.h"

@@ -74,7 +74,7 @@ public:
settings["http"]["script_names"][0]="/test";

srv.reset(new cppcms::service(settings));
app_=new cppcms::connection_forwarder(*srv,"127.0.0.1",8081);
app_=new mini_forwarder(*srv);
srv->applications_pool().mount(app_);

}
@@ -97,6 +97,13 @@ public:
fw_ok=true;
}
private:
struct mini_forwarder : public cppcms::application {
mini_forwarder(cppcms::service &s) : cppcms::application(s) {}
virtual void main(std::string unused)
{
cppcms::forward_connection(release_context(),"127.0.0.1",8081);
}
};
booster::shared_ptr<cppcms::service> srv;
booster::intrusive_ptr<cppcms::application> app_;
};


Loading…
Cancel
Save