一、首先,我们要做的是继承QuicStream 和 QuicSession 并实现其虚函数。
QuicStream中必须要实现的接口是数据回调接口,如下:
// Called when new data is available from the sequencer. Subclasses must
// actively retrieve the data using the sequencer's Readv() or
// GetReadableRegions() method.
virtual void OnDataAvailable() = 0;
而QuicSession中必须要实现的接口则比较多,如下:
// Creates a new stream to handle a peer-initiated stream.
// Caller does not own the returned stream.
// Returns nullptr and does error handling if the stream can not be created.
virtual QuicStream* CreateIncomingDynamicStream(QuicStreamId id) = 0;
// Create a new stream to handle a locally-initiated stream.
// Caller does not own the returned stream.
// Returns nullptr if max streams have already been opened.
virtual QuicStream* CreateOutgoingDynamicStream(uint8_t priority) = 0;
// Return the reserved crypto stream.
virtual QuicCryptoStream* GetMutableCryptoStream() = 0;
// Return the reserved crypto stream as a constant pointer.
virtual const QuicCryptoStream* GetCryptoStream() const = 0;
// Unconditionally creates a stream. Subclasses should use this to
// provide streams appropriately subclassed from |QuicStream|,
// e.g. |QuicSpdySession::CreateStream()| creates a |QuicSpdyStream|.
virtual std::unique_ptr CreateStream(QuicStreamId id) = 0;
二、构建外部调用的接口,包括创建及初始化Session、通过session连接远端服务、创建Stream。
为了连接远端服务,我们需要使用一个加密流,即流ID为1。连接远端即发送握手信息,握手成功即为连接远端成功。
为了创建的Stream类型是自己实现的Stream类,需要在session中增加CreateStream接口,在该实现中创建stream类对象。
void InitializeSession(const QuicServerId& server_id,
QuicCryptoClientConfig* config);
bool CryptoConnect();
QuicClientStream* CreateClientStream(QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory, StreamVisitor*);
QuicClientStream* CreateClientStream(QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory, void(*fun)(void*, size_t, void*), void*);
三、具体代码如下:
client/quic_client_session.h
#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_
#define NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_
#include
#include "net/quic/core/crypto/quic_crypto_client_config.h"
#include "net/quic/core/quic_crypto_client_stream.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_config.h"
#include "google/protobuf/stubs/scoped_ptr.h"
using namespace google::protobuf;
using namespace net;
class QuicClientStream;
class StreamVisitor;
class QuicClientSession :
public QuicSession,
public QuicCryptoClientStream::ProofHandler,
public QuicSession::Visitor
{
public:
QuicClientSession(const QuicConfig& config, QuicConnection* connection, QuicSession::Visitor* vistor);
~QuicClientSession() override;
void InitializeSession(const QuicServerId& server_id,
QuicCryptoClientConfig* config);
bool CryptoConnect();
QuicClientStream* CreateClientStream(QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory, StreamVisitor*);
QuicClientStream* CreateClientStream(QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory, void(*fun)(void*, size_t, void*), void*);
/*---------------------openssl certification*/
virtual void OnProofValid (const QuicCryptoClientConfig::CachedState& cached) override {};
virtual void OnProofVerifyDetailsAvailable (const ProofVerifyDetails& verify_details) override {};
/*---------------------QuicSession */
virtual QuicStream* CreateOutgoingDynamicStream(SpdyPriority priority) { return nullptr; };
virtual QuicStream* CreateIncomingDynamicStream(QuicStreamId id) { return nullptr; };
virtual QuicCryptoStream* GetMutableCryptoStream() override { return crypto_stream_.get(); };
virtual const QuicCryptoStream* GetCryptoStream() const override { return crypto_stream_.get(); };
virtual std::unique_ptr CreateStream(QuicStreamId id) { return nullptr; }
/*---------------------QuicSession::Visitor */
virtual void OnConnectionClosed(QuicConnectionId conneciton_id,
QuicErrorCode err, const std::string& code_details) override;
virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override;
virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) override;
private:
scoped_ptr crypto_stream_;
};
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_
client/quic_client_session.cc
#include "client/quic_client_session.h"
#include "client/quic_client_stream.h"
QuicClientSession::QuicClientSession(const QuicConfig& config,
QuicConnection* connection, QuicSession::Visitor* visitor)
: QuicSession(connection, (visitor==NULL)?NULL:visitor/*mybe 'this' can be better */,config) {
}
QuicClientSession::~QuicClientSession() {
}
void QuicClientSession::InitializeSession(
const QuicServerId& server_id,
QuicCryptoClientConfig* crypto_config) {
crypto_stream_.reset(
new QuicCryptoClientStream(server_id, this, nullptr, crypto_config, this));
QuicSession::Initialize();
}
bool QuicClientSession::CryptoConnect() {
DCHECK(flow_controller());
return crypto_stream_->CryptoConnect();
}
QuicClientStream* QuicClientSession::CreateClientStream(
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory, StreamVisitor* visitor) {
QuicStream* stream = new QuicClientStream(GetNextOutgoingStreamId(), this, helper, alarm_factory, visitor);
ActivateStream(std::unique_ptr(stream));
return (QuicClientStream*) stream;
}
QuicClientStream* QuicClientSession::CreateClientStream(
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
void(*fun)(void*, size_t, void*), void* arg)
{
QuicStream* stream = new QuicClientStream(GetNextOutgoingStreamId(), this, helper,alarm_factory, fun, arg);
ActivateStream(std::unique_ptr(stream));
return (QuicClientStream*) stream;
}