// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/tools/flip_server/streamer_interface.h"
#include <string>
#include "net/tools/flip_server/balsa_frame.h"
#include "net/tools/flip_server/constants.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"
namespace net {
std::string StreamerSM::forward_ip_header_;
StreamerSM::StreamerSM(SMConnection* connection,
SMInterface* sm_other_interface,
EpollServer* epoll_server,
FlipAcceptor* acceptor)
: connection_(connection),
sm_other_interface_(sm_other_interface),
epoll_server_(epoll_server),
acceptor_(acceptor),
is_request_(false),
http_framer_(new BalsaFrame) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Creating StreamerSM object";
http_framer_->set_balsa_visitor(this);
http_framer_->set_balsa_headers(&headers_);
http_framer_->set_is_request(false);
}
StreamerSM::~StreamerSM() {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Destroying StreamerSM object";
Reset();
delete http_framer_;
}
void StreamerSM::set_is_request() {
is_request_ = true;
http_framer_->set_is_request(true);
}
void StreamerSM::InitSMInterface(SMInterface* sm_other_interface,
int32 server_idx) {
sm_other_interface_ = sm_other_interface;
}
void StreamerSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
SMInterface* sm_interface,
EpollServer* epoll_server,
int fd,
std::string server_ip,
std::string server_port,
std::string remote_ip,
bool use_ssl) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
<< "connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
epoll_server, fd, server_ip,
server_port, remote_ip, use_ssl);
}
size_t StreamerSM::ProcessReadInput(const char* data, size_t len) {
// For now we only want to parse http requests. Just stream responses
if (is_request_) {
return http_framer_->ProcessInput(data, len);
} else {
return sm_other_interface_->ProcessWriteInput(data, len);
}
}
size_t StreamerSM::ProcessWriteInput(const char* data, size_t len) {
char * dataPtr = new char[len];
memcpy(dataPtr, data, len);
DataFrame* df = new DataFrame;
df->data = (const char *)dataPtr;
df->size = len;
df->delete_when_done = true;
connection_->EnqueueDataFrame(df);
return len;
}
bool StreamerSM::Error() const {
return false;
}
const char* StreamerSM::ErrorAsString() const {
return "(none)";
}
bool StreamerSM::MessageFullyRead() const {
if (is_request_) {
return http_framer_->MessageFullyRead();
} else {
return false;
}
}
void StreamerSM::Reset() {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Reset";
connection_->Cleanup("Server Reset");
http_framer_->Reset();
}
void StreamerSM::ResetForNewConnection() {
http_framer_->Reset();
sm_other_interface_->Reset();
}
void StreamerSM::Cleanup() {
if (is_request_)
http_framer_->Reset();
}
int StreamerSM::PostAcceptHook() {
if (!sm_other_interface_) {
SMConnection *server_connection =
SMConnection::NewSMConnection(epoll_server_, NULL, NULL,
acceptor_, "server_conn: ");
if (server_connection == NULL) {
LOG(ERROR) << "StreamerSM: Could not create server conenction.";
return 0;
}
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Creating new server "
<< "connection.";
sm_other_interface_ = new StreamerSM(server_connection, this,
epoll_server_, acceptor_);
sm_other_interface_->InitSMInterface(this, 0);
}
// The Streamer interface is used to stream HTTPS connections, so we
// will always use the https_server_ip/port here.
sm_other_interface_->InitSMConnection(NULL, sm_other_interface_,
epoll_server_, -1,
acceptor_->https_server_ip_,
acceptor_->https_server_port_,
"",
false);
return 1;
}
size_t StreamerSM::SendSynStream(uint32 stream_id,
const BalsaHeaders& headers) {
return 0;
}
size_t StreamerSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
return 0;
}
void StreamerSM::ProcessBodyInput(const char *input, size_t size) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT
<< "StreamerHttpSM: Process Body Input Data: "
<< "size " << size;
sm_other_interface_->ProcessWriteInput(input, size);
}
void StreamerSM::MessageDone() {
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerHttpSM: MessageDone.";
// TODO(kelindsay): anything need to be done ehre?
} else {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StraemerHttpSM: MessageDone.";
}
}
void StreamerSM::ProcessHeaders(const BalsaHeaders& headers) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpStreamerSM: Process Headers";
BalsaHeaders mod_headers;
mod_headers.CopyFrom(headers);
if (forward_ip_header_.length()) {
LOG(INFO) << "Adding forward header: " << forward_ip_header_;
mod_headers.ReplaceOrAppendHeader(forward_ip_header_,
connection_->client_ip());
} else {
LOG(INFO) << "NOT adding forward header.";
}
SimpleBuffer sb;
char* buffer;
int size;
mod_headers.WriteHeaderAndEndingToBuffer(&sb);
sb.GetReadablePtr(&buffer, &size);
sm_other_interface_->ProcessWriteInput(buffer, size);
}
void StreamerSM::HandleHeaderError(BalsaFrame* framer) {
HandleError();
}
void StreamerSM::HandleChunkingError(BalsaFrame* framer) {
HandleError();
}
void StreamerSM::HandleBodyError(BalsaFrame* framer) {
HandleError();
}
void StreamerSM::HandleError() {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
}
} // namespace net