add ASL to a handful of files

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@980145 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Bryan Duxbury 2010-07-28 18:23:22 +00:00
parent dcfb0025df
commit 23f2348fae
7 changed files with 89 additions and 321 deletions

View File

@ -58,7 +58,9 @@ libthrift_la_SOURCES = src/Thrift.cpp \
src/transport/TFDTransport.cpp \
src/transport/TFileTransport.cpp \
src/transport/TSimpleFileTransport.cpp \
src/transport/THttpTransport.cpp \
src/transport/THttpClient.cpp \
src/transport/THttpServer.cpp \
src/transport/TSocket.cpp \
src/transport/TSocketPool.cpp \
src/transport/TServerSocket.cpp \
@ -121,7 +123,9 @@ include_transport_HEADERS = \
src/transport/TSimpleFileTransport.h \
src/transport/TServerSocket.h \
src/transport/TServerTransport.h \
src/transport/THttpTransport.h \
src/transport/THttpClient.h \
src/transport/THttpServer.h \
src/transport/TSocket.h \
src/transport/TSocketPool.h \
src/transport/TTransport.h \

View File

@ -20,250 +20,38 @@
#include <cstdlib>
#include <sstream>
#include "THttpClient.h"
#include "TSocket.h"
#include <transport/THttpClient.h>
#include <transport/TSocket.h>
namespace apache { namespace thrift { namespace transport {
using namespace std;
/**
* Http client implementation.
*
*/
// Yeah, yeah, hacky to put these here, I know.
static const char* CRLF = "\r\n";
static const int CRLF_LEN = 2;
THttpClient::THttpClient(boost::shared_ptr<TTransport> transport, string host, string path) :
transport_(transport),
host_(host),
path_(path),
readHeaders_(true),
chunked_(false),
chunkedDone_(false),
chunkSize_(0),
contentLength_(0),
httpBuf_(NULL),
httpPos_(0),
httpBufLen_(0),
httpBufSize_(1024) {
init();
THttpClient::THttpClient(boost::shared_ptr<TTransport> transport, std::string host, std::string path) :
THttpTransport(transport), host_(host), path_(path) {
}
THttpClient::THttpClient(string host, int port, string path) :
host_(host),
path_(path),
readHeaders_(true),
chunked_(false),
chunkedDone_(false),
chunkSize_(0),
contentLength_(0),
httpBuf_(NULL),
httpPos_(0),
httpBufLen_(0),
httpBufSize_(1024) {
transport_ = boost::shared_ptr<TTransport>(new TSocket(host, port));
init();
THttpTransport(boost::shared_ptr<TTransport>(new TSocket(host, port))), host_(host), path_(path) {
}
void THttpClient::init() {
httpBuf_ = (char*)std::malloc(httpBufSize_+1);
if (httpBuf_ == NULL) {
throw TTransportException("Out of memory.");
THttpClient::~THttpClient() {}
void THttpClient::parseHeader(char* header) {
char* colon = strchr(header, ':');
if (colon == NULL) {
return;
}
httpBuf_[httpBufLen_] = '\0';
}
uint32_t sz = colon - header;
char* value = colon+1;
THttpClient::~THttpClient() {
if (httpBuf_ != NULL) {
std::free(httpBuf_);
}
}
uint32_t THttpClient::read(uint8_t* buf, uint32_t len) {
if (readBuffer_.available_read() == 0) {
readBuffer_.resetBuffer();
uint32_t got = readMoreData();
if (got == 0) {
return 0;
}
}
return readBuffer_.read(buf, len);
}
void THttpClient::readEnd() {
// Read any pending chunked data (footers etc.)
if (chunked_) {
while (!chunkedDone_) {
readChunked();
}
}
}
uint32_t THttpClient::readMoreData() {
// Get more data!
refill();
if (readHeaders_) {
readHeaders();
}
if (chunked_) {
return readChunked();
} else {
return readContent(contentLength_);
}
}
uint32_t THttpClient::readChunked() {
uint32_t length = 0;
char* line = readLine();
uint32_t chunkSize = parseChunkSize(line);
if (chunkSize == 0) {
readChunkedFooters();
} else {
// Read data content
length += readContent(chunkSize);
// Read trailing CRLF after content
readLine();
}
return length;
}
void THttpClient::readChunkedFooters() {
// End of data, read footer lines until a blank one appears
while (true) {
char* line = readLine();
if (strlen(line) == 0) {
chunkedDone_ = true;
break;
}
}
}
uint32_t THttpClient::parseChunkSize(char* line) {
char* semi = strchr(line, ';');
if (semi != NULL) {
*semi = '\0';
}
int size = 0;
sscanf(line, "%x", &size);
return (uint32_t)size;
}
uint32_t THttpClient::readContent(uint32_t size) {
uint32_t need = size;
while (need > 0) {
uint32_t avail = httpBufLen_ - httpPos_;
if (avail == 0) {
// We have given all the data, reset position to head of the buffer
httpPos_ = 0;
httpBufLen_ = 0;
refill();
// Now have available however much we read
avail = httpBufLen_;
}
uint32_t give = avail;
if (need < give) {
give = need;
}
readBuffer_.write((uint8_t*)(httpBuf_+httpPos_), give);
httpPos_ += give;
need -= give;
}
return size;
}
char* THttpClient::readLine() {
while (true) {
char* eol = NULL;
eol = strstr(httpBuf_+httpPos_, CRLF);
// No CRLF yet?
if (eol == NULL) {
// Shift whatever we have now to front and refill
shift();
refill();
} else {
// Return pointer to next line
*eol = '\0';
char* line = httpBuf_+httpPos_;
httpPos_ = (eol-httpBuf_) + CRLF_LEN;
return line;
}
}
}
void THttpClient::shift() {
if (httpBufLen_ > httpPos_) {
// Shift down remaining data and read more
uint32_t length = httpBufLen_ - httpPos_;
memmove(httpBuf_, httpBuf_+httpPos_, length);
httpBufLen_ = length;
} else {
httpBufLen_ = 0;
}
httpPos_ = 0;
httpBuf_[httpBufLen_] = '\0';
}
void THttpClient::refill() {
uint32_t avail = httpBufSize_ - httpBufLen_;
if (avail <= (httpBufSize_ / 4)) {
httpBufSize_ *= 2;
httpBuf_ = (char*)std::realloc(httpBuf_, httpBufSize_+1);
if (httpBuf_ == NULL) {
throw TTransportException("Out of memory.");
}
}
// Read more data
uint32_t got = transport_->read((uint8_t*)(httpBuf_+httpBufLen_), httpBufSize_-httpBufLen_);
httpBufLen_ += got;
httpBuf_[httpBufLen_] = '\0';
if (got == 0) {
throw TTransportException("Could not refill buffer");
}
}
void THttpClient::readHeaders() {
// Initialize headers state variables
contentLength_ = 0;
chunked_ = false;
chunkedDone_ = false;
chunkSize_ = 0;
// Control state flow
bool statusLine = true;
bool finished = false;
// Loop until headers are finished
while (true) {
char* line = readLine();
if (strlen(line) == 0) {
if (finished) {
readHeaders_ = false;
return;
} else {
// Must have been an HTTP 100, keep going for another status line
statusLine = true;
}
} else {
if (statusLine) {
statusLine = false;
finished = parseStatusLine(line);
} else {
parseHeader(line);
}
if (strncmp(header, "Transfer-Encoding", sz) == 0) {
if (strstr(value, "chunked") != NULL) {
chunked_ = true;
}
} else if (strncmp(header, "Content-Length", sz) == 0) {
chunked_ = false;
contentLength_ = atoi(value);
}
}
@ -295,28 +83,6 @@ bool THttpClient::parseStatusLine(char* status) {
}
}
void THttpClient::parseHeader(char* header) {
char* colon = strchr(header, ':');
if (colon == NULL) {
return;
}
uint32_t sz = colon - header;
char* value = colon+1;
if (strncmp(header, "Transfer-Encoding", sz) == 0) {
if (strstr(value, "chunked") != NULL) {
chunked_ = true;
}
} else if (strncmp(header, "Content-Length", sz) == 0) {
chunked_ = false;
contentLength_ = atoi(value);
}
}
void THttpClient::write(const uint8_t* buf, uint32_t len) {
writeBuffer_.write(buf, len);
}
void THttpClient::flush() {
// Fetch the contents of the write buffer
uint8_t* buf;
@ -331,7 +97,7 @@ void THttpClient::flush() {
"Content-Type: application/x-thrift" << CRLF <<
"Content-Length: " << len << CRLF <<
"Accept: application/x-thrift" << CRLF <<
"User-Agent: C++/THttpClient" << CRLF <<
"User-Agent: Thrift/" << VERSION << " (C++/THttpClient)" << CRLF <<
CRLF;
string header = h.str();

View File

@ -20,19 +20,11 @@
#ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_
#define _THRIFT_TRANSPORT_THTTPCLIENT_H_ 1
#include <transport/TBufferTransports.h>
#include <transport/THttpTransport.h>
namespace apache { namespace thrift { namespace transport {
/**
* HTTP client implementation of the thrift transport. This was irritating
* to write, but the alternatives in C++ land are daunting. Linking CURL
* requires 23 dynamic libraries last time I checked (WTF?!?). All we have
* here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue,
* chunked transfer encoding, keepalive, etc. Tested against Apache.
*
*/
class THttpClient : public TTransport {
class THttpClient : public THttpTransport {
public:
THttpClient(boost::shared_ptr<TTransport> transport, std::string host, std::string path="");
@ -40,69 +32,15 @@ class THttpClient : public TTransport {
virtual ~THttpClient();
void open() {
transport_->open();
}
bool isOpen() {
return transport_->isOpen();
}
bool peek() {
return transport_->peek();
}
void close() {
transport_->close();
}
uint32_t read(uint8_t* buf, uint32_t len);
void readEnd();
void write(const uint8_t* buf, uint32_t len);
void flush();
private:
void init();
virtual void flush();
protected:
boost::shared_ptr<TTransport> transport_;
TMemoryBuffer writeBuffer_;
TMemoryBuffer readBuffer_;
std::string host_;
std::string path_;
bool readHeaders_;
bool chunked_;
bool chunkedDone_;
uint32_t chunkSize_;
uint32_t contentLength_;
char* httpBuf_;
uint32_t httpPos_;
uint32_t httpBufLen_;
uint32_t httpBufSize_;
uint32_t readMoreData();
char* readLine();
void readHeaders();
void parseHeader(char* header);
bool parseStatusLine(char* status);
uint32_t readChunked();
void readChunkedFooters();
uint32_t parseChunkSize(char* line);
uint32_t readContent(uint32_t size);
void refill();
void shift();
virtual void parseHeader(char* header);
virtual bool parseStatusLine(char* status);
};

View File

@ -1,3 +1,22 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
Name: Thrift
Version: 0.1.1
Cabal-Version: >= 1.2

View File

@ -1,3 +1,6 @@
NOTE (bryanduxbury): OCamlMakefile is safe to include in the project after
https://issues.apache.org/jira/browse/LEGAL-58.
---------------------------------------------------------------------------
Distribution of "ocaml_make"

View File

@ -1,3 +1,22 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>

View File

@ -1,3 +1,22 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
Name: ThriftTutorial
Version: 0.1.0
Cabal-Version: >= 1.2