root/trunk/whisperlib/net/rpc/lib/rpc_util.cc

Revision 7, 6.3 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache
31
32 #include "common/base/log.h"
33 #include "net/url/url.h"
34 #include "net/rpc/lib/rpc_util.h"
35
36 namespace {
37
38 // These constants are used to encode/decode RPC URI.
39 // Many of these URIs are used in configuration files, so do NOT change
40 // these values!!
41 const char kRpcConnectionTypeTcp[] = "tcp";
42 const char kRpcConnectionTypeHttp[] = "http";
43 const char kRpcConnectionTypeUnknown[] = "unknown";
44
45 const char kRpcCodecIdBinary[] = "binary";
46 const char kRpcCodecIdJson[] = "json";
47 const char kRpcCodecIdUnknown[] = "unknown";
48
49 const char* RpcConnectionTypeToString(
50     rpc::CONNECTION_TYPE connection_type) {
51   switch ( connection_type ) {
52     case rpc::CONNECTION_TCP:  return kRpcConnectionTypeTcp;
53     case rpc::CONNECTION_HTTP: return kRpcConnectionTypeHttp;
54     default: {
55       LOG_FATAL << "no such connection_type: " << connection_type;
56       return kRpcConnectionTypeUnknown;
57     }
58   }
59 }
60
61 rpc::CONNECTION_TYPE RpcConnectionTypeFromString(const string& str) {
62   if ( str == kRpcConnectionTypeTcp ) {
63     return rpc::CONNECTION_TCP;
64   } else if ( str == kRpcConnectionTypeHttp ) {
65     return rpc::CONNECTION_HTTP;
66   } else {
67     return (rpc::CONNECTION_TYPE)(-1);
68   }
69 }
70
71 const char* RpcCodecIdToString(rpc::CODEC_ID codec_id) {
72   switch ( codec_id ) {
73     case rpc::CID_BINARY: return kRpcCodecIdBinary;
74     case rpc::CID_JSON:   return kRpcCodecIdJson;
75     default: {
76       LOG_FATAL << "no such codec_id: " << codec_id;
77       return kRpcCodecIdUnknown;
78     }
79   }
80 }
81
82 rpc::CODEC_ID RpcCodecIdFromString(const string& str) {
83   if ( str == kRpcCodecIdBinary ) {
84     return rpc::CID_BINARY;
85   } else if ( str == kRpcCodecIdJson ) {
86     return rpc::CID_JSON;
87   } else {
88     return (rpc::CODEC_ID)(-1);
89   }
90 }
91
92 }  // namespace
93
94
95 namespace rpc {
96
97 string CreateUri(const net::HostPort& host_port,
98                  const string& path,
99                  rpc::CONNECTION_TYPE connection_type,
100                  rpc::CODEC_ID codec_id) {
101   return strutil::StringPrintf(
102       "%s://%s/%s?codec=%s",
103       RpcConnectionTypeToString(connection_type),
104       host_port.ToString().c_str(),
105       path.c_str()[0] == '/' ? path.c_str() + 1 : path.c_str(),
106       RpcCodecIdToString(codec_id));
107 }
108
109 bool ParseUri(const string& address,
110               net::HostPort& host_port,
111               string& path,
112               rpc::CONNECTION_TYPE& connection_type,
113               rpc::CODEC_ID& codec_id) {
114   URL url(address);
115   if ( !url.is_valid() ) {
116     LOG_ERROR << "invalid address: " << address;
117     return false;
118   }
119   if ( url.port().empty() ) {
120     LOG_ERROR << "port not specified in address: " << address;
121     return false;
122   }
123   host_port = net::HostPort(url.host().c_str(), url.IntPort());
124   if ( host_port.port() == 0 ) {
125     LOG_ERROR << "invalid port in address: " << address;
126     return false;
127   }
128   path = url.path();
129   connection_type = RpcConnectionTypeFromString(url.scheme());
130   if ( connection_type == -1 ) {
131     LOG_ERROR << "invalid connection_type in address: " << address;
132     return false;
133   }
134   vector< pair<string, string> > qp;
135   url.GetQueryParameters(&qp, true);
136   bool codec_id_found = false;
137   for ( vector< pair<string, string> >::iterator it = qp.begin();
138         it != qp.end(); ++it ) {
139     const string& param = it->first;
140     const string& value = it->second;
141     if ( param == "codec" ) {
142       codec_id = RpcCodecIdFromString(value);
143       if ( codec_id == -1 ) {
144         LOG_ERROR << "invalid codec_id in address: " << address;
145         return false;
146       }
147       codec_id_found = true;
148       break;
149     }
150   }
151   if ( !codec_id_found ) {
152     LOG_ERROR << "missing codec_id in address: " << address;
153     return false;
154   }
155   return true;
156 }
157 }
158 namespace rpc_util {
159
160 void AppendToRpcArray(const vector<string>& v, rpc::Array<rpc::String>& out) {
161   uint32 i = out.Size();
162   out.Resize(out.Size() + v.size());
163   for ( vector<string>::const_iterator it = v.begin();
164         it != v.end(); ++it, ++i ) {
165     out.Set(i, rpc::String(*it));
166   }
167 }
168 void AppendToRpcArray(const set<string>& v, rpc::Array<rpc::String>& out) {
169   uint32 i = out.Size();
170   out.Resize(out.Size() + v.size());
171   for ( set<string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i ) {
172     out.Set(i, rpc::String(*it));
173   }
174 }
175
176 rpc::Array<rpc::String> MakeRpcArray(const vector<string>& v) {
177   rpc::Array<rpc::String> out;
178   AppendToRpcArray(v, out);
179   return out;
180 }
181 rpc::Array<rpc::String> MakeRpcArray(const set<string>& v) {
182   rpc::Array<rpc::String> out;
183   AppendToRpcArray(v, out);
184   return out;
185 }
186
187 void AppendToStdArray(const rpc::Array<rpc::String>& v, vector<string>& out) {
188   out.reserve(out.size() + v.Size());
189   for ( uint32 i = 0; i < v.Size(); ++i ) {
190     out.push_back(v.Get(i).StdStr());
191   }
192 }
193
194 vector<string> MakeStdArray(const rpc::Array<rpc::String>& v) {
195   vector<string> out;
196   AppendToStdArray(v, out);
197   return out;
198 }
199 }  // namespace rpc_util
Note: See TracBrowser for help on using the browser.