OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/crypto/crypto_protocol.h" | |
6 | |
7 #include <stdarg.h> | |
8 #include <string.h> | |
9 | |
10 #include "base/memory/scoped_ptr.h" | |
11 | |
12 using base::StringPiece; | |
13 using std::string; | |
14 | |
15 namespace net { | |
16 | |
17 CryptoHandshakeMessage::CryptoHandshakeMessage() {} | |
18 CryptoHandshakeMessage::~CryptoHandshakeMessage() {} | |
19 | |
20 void CryptoHandshakeMessage::SetTaglist(CryptoTag tag, ...) { | |
21 // Warning, if sizeof(CryptoTag) > sizeof(int) then this function will break | |
22 // because the terminating 0 will only be promoted to int. | |
23 COMPILE_ASSERT(sizeof(CryptoTag) <= sizeof(int), | |
24 crypto_tag_not_be_larger_than_int_or_varargs_will_break); | |
25 | |
26 std::vector<CryptoTag> tags; | |
27 va_list ap; | |
28 | |
29 va_start(ap, tag); | |
30 for (;;) { | |
31 CryptoTag tag = va_arg(ap, CryptoTag); | |
32 if (tag == 0) { | |
33 break; | |
34 } | |
35 tags.push_back(tag); | |
36 } | |
37 | |
38 // Because of the way that we keep tags in memory, we can copy the contents | |
39 // of the vector and get the correct bytes in wire format. See | |
40 // crypto_protocol.h. This assumes that the system is little-endian. | |
41 SetVector(tag, tags); | |
42 | |
43 va_end(ap); | |
44 } | |
45 | |
46 QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag, | |
47 const CryptoTag** out_tags, | |
48 size_t* out_len) const { | |
49 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag); | |
50 QuicErrorCode ret = QUIC_NO_ERROR; | |
51 | |
52 if (it == tag_value_map.end()) { | |
53 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | |
54 } else if (it->second.size() % sizeof(CryptoTag) != 0) { | |
55 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
56 } | |
57 | |
58 if (ret != QUIC_NO_ERROR) { | |
59 *out_tags = NULL; | |
60 *out_len = 0; | |
61 return ret; | |
62 } | |
63 | |
64 *out_tags = reinterpret_cast<const CryptoTag*>(it->second.data()); | |
65 *out_len = it->second.size() / sizeof(CryptoTag); | |
66 return ret; | |
67 } | |
68 | |
69 bool CryptoHandshakeMessage::GetStringPiece(CryptoTag tag, | |
70 StringPiece* out) const { | |
71 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag); | |
72 if (it == tag_value_map.end()) { | |
73 return false; | |
74 } | |
75 *out = it->second; | |
76 return true; | |
77 } | |
78 | |
79 QuicErrorCode CryptoHandshakeMessage::GetNthValue16( | |
80 CryptoTag tag, | |
81 unsigned index, | |
82 StringPiece* out) const { | |
83 StringPiece value; | |
84 if (!GetStringPiece(tag, &value)) { | |
85 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | |
86 } | |
87 | |
88 for (unsigned i = 0;; i++) { | |
89 if (value.empty()) { | |
90 return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND; | |
91 } | |
92 if (value.size() < 2) { | |
93 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
94 } | |
95 | |
96 const unsigned char* data = | |
97 reinterpret_cast<const unsigned char*>(value.data()); | |
98 size_t size = static_cast<size_t>(data[0]) | | |
99 (static_cast<size_t>(data[1]) << 8); | |
100 value.remove_prefix(2); | |
101 | |
102 if (value.size() < size) { | |
103 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
104 } | |
105 | |
106 if (i == index) { | |
107 *out = StringPiece(value.data(), size); | |
108 return QUIC_NO_ERROR; | |
109 } | |
110 | |
111 value.remove_prefix(size); | |
112 } | |
113 } | |
114 | |
115 bool CryptoHandshakeMessage::GetString(CryptoTag tag, string* out) const { | |
116 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag); | |
117 if (it == tag_value_map.end()) { | |
118 return false; | |
119 } | |
120 *out = it->second; | |
121 return true; | |
122 } | |
123 | |
124 QuicErrorCode CryptoHandshakeMessage::GetUint16(CryptoTag tag, | |
125 uint16* out) const { | |
126 return GetPOD(tag, out, sizeof(uint16)); | |
127 } | |
128 | |
129 QuicErrorCode CryptoHandshakeMessage::GetUint32(CryptoTag tag, | |
130 uint32* out) const { | |
131 return GetPOD(tag, out, sizeof(uint32)); | |
132 } | |
133 | |
134 QuicErrorCode CryptoHandshakeMessage::GetPOD( | |
135 CryptoTag tag, void* out, size_t len) const { | |
136 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag); | |
137 QuicErrorCode ret = QUIC_NO_ERROR; | |
138 | |
139 if (it == tag_value_map.end()) { | |
140 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | |
141 } else if (it->second.size() != len) { | |
142 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
143 } | |
144 | |
145 if (ret != QUIC_NO_ERROR) { | |
146 memset(out, 0, len); | |
147 return ret; | |
148 } | |
149 | |
150 memcpy(out, it->second.data(), len); | |
151 return ret; | |
152 } | |
153 | |
154 } // namespace net | |
OLD | NEW |