blob: 117710577851cd3b50bc69ca50070179d1d751e0 [file] [log] [blame]
sergeyucb90397c2015-08-04 18:14:411// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/p2p/quic_p2p_session.h"
6
7#include "base/callback_helpers.h"
8#include "net/base/io_buffer.h"
9#include "net/base/net_errors.h"
10#include "net/quic/p2p/quic_p2p_crypto_stream.h"
11#include "net/quic/p2p/quic_p2p_stream.h"
12#include "net/quic/quic_connection.h"
13#include "net/socket/socket.h"
14
15namespace net {
16
17QuicP2PSession::QuicP2PSession(const QuicConfig& config,
18 const QuicP2PCryptoConfig& crypto_config,
19 scoped_ptr<QuicConnection> connection,
20 scoped_ptr<net::Socket> socket)
21 : QuicSession(connection.release(), config),
22 socket_(socket.Pass()),
23 crypto_stream_(new QuicP2PCryptoStream(this, crypto_config)),
24 read_buffer_(new net::IOBuffer(static_cast<size_t>(kMaxPacketSize))) {
25 DCHECK(config.negotiated());
26
27 // Non-null IP address needs to be passed here because QuicConnection uses
28 // ToString() to format addresses for logging and ToString() is not allowed
29 // for empty addresses.
30 // TODO(sergeyu): Fix QuicConnection and remove SetSelfAddress() call below.
31 net::IPAddressNumber ip(net::kIPv4AddressSize, 0);
32 this->connection()->SetSelfAddress(net::IPEndPoint(ip, 0));
33}
34
35QuicP2PSession::~QuicP2PSession() {}
36
37void QuicP2PSession::Initialize() {
38 QuicSession::Initialize();
39 crypto_stream_->Connect();
40 DoReadLoop(OK);
41}
42
43void QuicP2PSession::SetDelegate(Delegate* delegate) {
44 delegate_ = delegate;
45}
46
47QuicCryptoStream* QuicP2PSession::GetCryptoStream() {
48 return crypto_stream_.get();
49}
50
51QuicP2PStream* QuicP2PSession::CreateIncomingDynamicStream(QuicStreamId id) {
52 QuicP2PStream* stream = new QuicP2PStream(id, this);
53 if (delegate_) {
54 delegate_->OnIncomingStream(stream);
55 }
56 return stream;
57}
58
jri86a3c602015-12-15 06:01:0359QuicP2PStream* QuicP2PSession::CreateOutgoingDynamicStream(
60 net::SpdyPriority priority) {
alyssarc39b80f2015-10-22 17:13:5861 QuicP2PStream* stream = new QuicP2PStream(GetNextOutgoingStreamId(), this);
sergeyucb90397c2015-08-04 18:14:4162 if (stream) {
63 ActivateStream(stream);
64 }
65 return stream;
66}
67
68void QuicP2PSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
69 QuicSession::OnConnectionClosed(error, from_peer);
70
sergeyu1c98349632015-08-14 18:38:1771 socket_.reset();
72
sergeyucb90397c2015-08-04 18:14:4173 if (delegate_) {
74 Delegate* delegate = delegate_;
75 delegate_ = nullptr;
76 delegate->OnConnectionClosed(error);
77 }
78}
79
80void QuicP2PSession::DoReadLoop(int result) {
81 while (error() == net::QUIC_NO_ERROR) {
82 switch (read_state_) {
83 case READ_STATE_DO_READ:
84 CHECK_EQ(result, OK);
85 result = DoRead();
86 break;
87 case READ_STATE_DO_READ_COMPLETE:
88 result = DoReadComplete(result);
89 break;
90 default:
91 NOTREACHED() << "read_state_: " << read_state_;
92 break;
93 }
94
95 if (result < 0)
96 break;
97 }
98}
99
100int QuicP2PSession::DoRead() {
101 DCHECK_EQ(read_state_, READ_STATE_DO_READ);
102 read_state_ = READ_STATE_DO_READ_COMPLETE;
103
sergeyu1c98349632015-08-14 18:38:17104 if (!socket_) {
105 return net::ERR_SOCKET_NOT_CONNECTED;
106 }
107
sergeyucb90397c2015-08-04 18:14:41108 return socket_->Read(
109 read_buffer_.get(), kMaxPacketSize,
110 base::Bind(&QuicP2PSession::DoReadLoop, base::Unretained(this)));
111}
112
113int QuicP2PSession::DoReadComplete(int result) {
114 DCHECK_EQ(read_state_, READ_STATE_DO_READ_COMPLETE);
115 read_state_ = READ_STATE_DO_READ;
116
117 if (result <= 0) {
118 connection()->CloseConnection(net::QUIC_PACKET_READ_ERROR, false);
119 return result;
120 }
121
122 QuicEncryptedPacket packet(read_buffer_->data(), result);
123 connection()->ProcessUdpPacket(connection()->self_address(),
124 connection()->peer_address(), packet);
125 return OK;
126}
127
128} // namespace net