// 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