Skip to content

Commit 6512d4c

Browse files
committed
Addressing ODR violation for message swap across compilation units.
The changes are meant to fix ODR violations when using HTTP server requests and responses, as well as client requests and responses. By moving the swap function into the message request/response types the generic namespace level swap implementation can delegate to the specific member swap implementation.
1 parent cfe2ced commit 6512d4c

File tree

2 files changed

+94
-97
lines changed

2 files changed

+94
-97
lines changed

boost/network/protocol/http/impl/request.hpp

+16-17
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,6 @@ namespace boost { namespace network { namespace http {
9191

9292
};
9393

94-
template <class Tag>
95-
inline void swap(basic_request<Tag> & lhs, basic_request<Tag> & rhs) {
96-
lhs.swap(rhs);
97-
}
98-
9994
/** This is the implementation of a POD request type
10095
* that is specificially used by the HTTP server
10196
* implementation. This fully specializes the
@@ -104,8 +99,7 @@ namespace boost { namespace network { namespace http {
10499
* reasons.
105100
*/
106101
template <>
107-
class basic_request<tags::http_server> {
108-
public:
102+
struct basic_request<tags::http_server> {
109103
typedef string<tags::http_server>::type string_type;
110104
typedef vector<tags::http_server>::apply<request_header>::type vector_type;
111105
string_type method;
@@ -114,23 +108,28 @@ namespace boost { namespace network { namespace http {
114108
boost::uint8_t http_version_minor;
115109
vector_type headers;
116110
string_type body;
117-
};
118111

119-
template <>
120-
inline void swap<tags::http_server>(basic_request<tags::http_server> & l, basic_request<tags::http_server> & r) {
121-
using std::swap;
122-
swap(l.method, r.method);
123-
swap(l.uri, r.uri);
124-
swap(l.http_version_major, r.http_version_major);
125-
swap(l.http_version_minor, r.http_version_minor);
126-
swap(l.headers, r.headers);
127-
swap(l.body, r.body);
112+
void swap(basic_request & r) {
113+
using std::swap;
114+
swap(method, r.method);
115+
swap(uri, r.uri);
116+
swap(http_version_major, r.http_version_major);
117+
swap(http_version_minor, r.http_version_minor);
118+
swap(headers, r.headers);
119+
swap(body, r.body);
120+
}
128121
};
129122

123+
template <class Tag>
124+
inline void swap(basic_request<Tag> & lhs, basic_request<Tag> & rhs) {
125+
lhs.swap(rhs);
126+
}
127+
130128
} // namespace http
131129

132130
} // namespace network
133131

134132
} // namespace boost
135133

136134
#endif // __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__
135+

boost/network/protocol/http/impl/response.ipp

+78-80
Original file line numberDiff line numberDiff line change
@@ -24,86 +24,90 @@
2424
#include <boost/network/protocol/http/header.hpp>
2525

2626
namespace boost { namespace network { namespace http {
27-
27+
2828
/// A reply to be sent to a client.
2929
template <>
3030
struct basic_response<tags::http_server> {
31+
/// The status of the reply.
32+
enum status_type {
33+
ok = 200,
34+
created = 201,
35+
accepted = 202,
36+
no_content = 204,
37+
multiple_choices = 300,
38+
moved_permanently = 301,
39+
moved_temporarily = 302,
40+
not_modified = 304,
41+
bad_request = 400,
42+
unauthorized = 401,
43+
forbidden = 403,
44+
not_found = 404,
45+
not_supported = 405,
46+
not_acceptable = 406,
47+
internal_server_error = 500,
48+
not_implemented = 501,
49+
bad_gateway = 502,
50+
service_unavailable = 503
51+
} status;
52+
53+
/// The headers to be included in the reply.
54+
typedef vector<tags::http_server>::apply<request_header>::type headers_vector;
55+
headers_vector headers;
3156

32-
/// The status of the reply.
33-
enum status_type
34-
{
35-
ok = 200,
36-
created = 201,
37-
accepted = 202,
38-
no_content = 204,
39-
multiple_choices = 300,
40-
moved_permanently = 301,
41-
moved_temporarily = 302,
42-
not_modified = 304,
43-
bad_request = 400,
44-
unauthorized = 401,
45-
forbidden = 403,
46-
not_found = 404,
47-
not_supported = 405,
48-
not_acceptable = 406,
49-
internal_server_error = 500,
50-
not_implemented = 501,
51-
bad_gateway = 502,
52-
service_unavailable = 503
53-
} status;
54-
55-
/// The headers to be included in the reply.
56-
typedef vector<tags::http_server>::apply<request_header>::type headers_vector;
57-
headers_vector headers;
57+
/// The content to be sent in the reply.
58+
typedef string<tags::http_server>::type string_type;
59+
string_type content;
5860

59-
/// The content to be sent in the reply.
60-
typedef string<tags::http_server>::type string_type;
61-
string_type content;
62-
63-
/// Convert the reply into a vector of buffers. The buffers do not own the
64-
/// underlying memory blocks, therefore the reply object must remain valid and
65-
/// not be changed until the write operation has completed.
66-
std::vector<boost::asio::const_buffer> to_buffers() {
67-
using boost::asio::const_buffer;
68-
using boost::asio::buffer;
69-
static const char name_value_separator[] = { ':', ' ' };
70-
static const char crlf[] = { '\r', '\n' };
71-
std::vector<const_buffer> buffers;
72-
buffers.push_back(to_buffer(status));
73-
for (std::size_t i = 0; i < headers.size(); ++i)
74-
{
75-
request_header& h = headers[i];
76-
buffers.push_back(buffer(h.name));
77-
buffers.push_back(buffer(name_value_separator));
78-
buffers.push_back(buffer(h.value));
61+
/// Convert the reply into a vector of buffers. The buffers do not own the
62+
/// underlying memory blocks, therefore the reply object must remain valid and
63+
/// not be changed until the write operation has completed.
64+
std::vector<boost::asio::const_buffer> to_buffers() {
65+
using boost::asio::const_buffer;
66+
using boost::asio::buffer;
67+
static const char name_value_separator[] = { ':', ' ' };
68+
static const char crlf[] = { '\r', '\n' };
69+
std::vector<const_buffer> buffers;
70+
buffers.push_back(to_buffer(status));
71+
for (std::size_t i = 0; i < headers.size(); ++i) {
72+
request_header& h = headers[i];
73+
buffers.push_back(buffer(h.name));
74+
buffers.push_back(buffer(name_value_separator));
75+
buffers.push_back(buffer(h.value));
76+
buffers.push_back(buffer(crlf));
77+
}
7978
buffers.push_back(buffer(crlf));
80-
}
81-
buffers.push_back(buffer(crlf));
82-
buffers.push_back(buffer(content));
83-
return buffers;
84-
}
79+
buffers.push_back(buffer(content));
80+
return buffers;
81+
}
8582

86-
/// Get a stock reply.
87-
static basic_response<tags::http_server> stock_reply(status_type status) {
88-
return stock_reply(status, to_string(status));
89-
}
83+
/// Get a stock reply.
84+
static basic_response<tags::http_server> stock_reply(status_type status) {
85+
return stock_reply(status, to_string(status));
86+
}
9087

91-
/// Get a stock reply with custom plain text data.
92-
static basic_response<tags::http_server> stock_reply(status_type status, string_type content) {
93-
using boost::lexical_cast;
94-
basic_response<tags::http_server> rep;
95-
rep.status = status;
96-
rep.content = content;
97-
rep.headers.resize(2);
98-
rep.headers[0].name = "Content-Length";
99-
rep.headers[0].value = lexical_cast<string_type>(rep.content.size());
100-
rep.headers[1].name = "Content-Type";
101-
rep.headers[1].value = "text/html";
102-
return rep;
103-
}
88+
/// Get a stock reply with custom plain text data.
89+
static basic_response<tags::http_server> stock_reply(status_type status, string_type content) {
90+
using boost::lexical_cast;
91+
basic_response<tags::http_server> rep;
92+
rep.status = status;
93+
rep.content = content;
94+
rep.headers.resize(2);
95+
rep.headers[0].name = "Content-Length";
96+
rep.headers[0].value = lexical_cast<string_type>(rep.content.size());
97+
rep.headers[1].name = "Content-Type";
98+
rep.headers[1].value = "text/html";
99+
return rep;
100+
}
104101

105-
private:
102+
/// Swap response objects
103+
void swap(basic_response<tags::http_server> &r) {
104+
using std::swap;
105+
swap(headers, r.headers);
106+
swap(content, r.content);
107+
}
106108

109+
private:
110+
107111
static string_type to_string(status_type status) {
108112
static const char ok[] = "";
109113
static const char created[] =
@@ -191,7 +195,7 @@ namespace boost { namespace network { namespace http {
191195
"<head><title>Service Unavailable</title></head>"
192196
"<body><h1>503 Service Unavailable</h1></body>"
193197
"</html>";
194-
198+
195199
switch (status)
196200
{
197201
case basic_response<tags::http_server>::ok:
@@ -234,7 +238,7 @@ namespace boost { namespace network { namespace http {
234238
return internal_server_error;
235239
}
236240
}
237-
241+
238242
boost::asio::const_buffer to_buffer(status_type status) {
239243
using boost::asio::buffer;
240244
static const string_type ok =
@@ -273,7 +277,7 @@ namespace boost { namespace network { namespace http {
273277
"HTTP/1.0 502 Bad Gateway\r\n";
274278
static const string_type service_unavailable =
275279
"HTTP/1.0 503 Service Unavailable\r\n";
276-
280+
277281
switch (status) {
278282
case basic_response<tags::http_server>::ok:
279283
return buffer(ok);
@@ -315,15 +319,9 @@ namespace boost { namespace network { namespace http {
315319
return buffer(internal_server_error);
316320
}
317321
}
318-
322+
319323
};
320324

321-
template <>
322-
void swap(basic_response<tags::http_server> &l, basic_response<tags::http_server> &r) {
323-
using std::swap;
324-
swap(l.headers, r.headers);
325-
swap(l.content, r.content);
326-
}
327325

328326
} // namespace http
329327

0 commit comments

Comments
 (0)