1 /* $Id: nst_protocol_utils.cpp 493945 2016-03-02 17:13:12Z satskyse $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Sergey Satskiy
27 *
28 * File Description: NetStorage communication protocol utils
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33 #include <corelib/request_ctx.hpp>
34 #include <connect/ncbi_socket.hpp>
35 #include <connect/services/netservice_api_expt.hpp>
36
37 #include "nst_protocol_utils.hpp"
38 #include "nst_exception.hpp"
39 #include "error_codes.hpp"
40
41
42
43 BEGIN_NCBI_SCOPE
44
45
SetSessionAndIPAndPHID(const CJsonNode & message,const CSocket & peer)46 void SetSessionAndIPAndPHID(const CJsonNode & message,
47 const CSocket & peer)
48 {
49 if (message.HasKey("SessionID")) {
50 string session = message.GetString("SessionID");
51 if (!session.empty())
52 CDiagContext::GetRequestContext().SetSessionID(
53 session);
54 }
55
56
57 string client_ip;
58 if (message.HasKey("ClientIP"))
59 client_ip = message.GetString("ClientIP");
60
61 if (client_ip.empty())
62 CDiagContext::GetRequestContext().SetClientIP(
63 peer.GetPeerAddress(eSAF_IP));
64 else
65 CDiagContext::GetRequestContext().SetClientIP(
66 client_ip);
67
68 // CXX-7893: ncbi_context has preference over ncbi_phid
69 bool ncbi_context_deserialized = false;
70 if (message.HasKey("ncbi_context")) {
71 try {
72 string context = message.GetString("ncbi_context");
73 CRequestContext_PassThrough().Deserialize(context,
74 CRequestContext_PassThrough::eFormat_UrlEncoded);
75
76 ncbi_context_deserialized = true;
77 } catch (const exception & ex) {
78 ERR_POST(ex.what());
79 }
80 }
81
82 if (ncbi_context_deserialized == false && message.HasKey("ncbi_phid")) {
83 try {
84 string ncbi_phid = message.GetString("ncbi_phid");
85 if (!ncbi_phid.empty())
86 CDiagContext::GetRequestContext().SetHitID(ncbi_phid);
87 } catch (const exception & ex) {
88 ERR_POST(ex.what());
89 }
90 }
91 }
92
93
94 SCommonRequestArguments
ExtractCommonFields(const CJsonNode & message)95 ExtractCommonFields(const CJsonNode & message)
96 {
97 SCommonRequestArguments result;
98 try {
99 result.m_SerialNumber = message.GetInteger("SN");
100 result.m_MessageType = message.GetString("Type");
101 }
102 catch (const std::exception & ex) {
103 // Converting to the CNetStorageServerException is done to
104 // have generic request status handling.
105 NCBI_THROW(CNetStorageServerException, eInvalidIncomingMessage,
106 ex.what());
107 }
108 return result;
109 }
110
111
112 TNetStorageFlags
ExtractStorageFlags(const CJsonNode & message)113 ExtractStorageFlags(const CJsonNode & message)
114 {
115 TNetStorageFlags result = 0;
116
117 if (message.HasKey("StorageFlags")) {
118 CJsonNode flags = message.GetByKey("StorageFlags");
119 if (flags.HasKey("Fast") && flags.GetBoolean("Fast"))
120 result |= fNST_Fast;
121 if (flags.HasKey("Persistent") && flags.GetBoolean("Persistent"))
122 result |= fNST_Persistent;
123 if (flags.HasKey("NetCache") && flags.GetBoolean("NetCache"))
124 result |= fNST_NetCache;
125 if (flags.HasKey("FileTrack") && flags.GetBoolean("FileTrack"))
126 result |= fNST_FileTrack;
127 if (flags.HasKey("Movable") && flags.GetBoolean("Movable"))
128 result |= fNST_Movable;
129 if (flags.HasKey("Cacheable") && flags.GetBoolean("Cacheable"))
130 result |= fNST_Cacheable;
131 if (flags.HasKey("NoMetaData") && flags.GetBoolean("NoMetaData"))
132 result |= fNST_NoMetaData;
133 }
134 return result;
135 }
136
137
138 SICacheSettings
ExtractICacheSettings(const CJsonNode & message)139 ExtractICacheSettings(const CJsonNode & message)
140 {
141 SICacheSettings result;
142
143 if (message.HasKey("ICache")) {
144 CJsonNode settings = message.GetByKey("ICache");
145 if (settings.HasKey("ServiceName"))
146 result.m_ServiceName = settings.GetString("ServiceName");
147 if (settings.HasKey("CacheName"))
148 result.m_CacheName = settings.GetString("CacheName");
149 }
150 return result;
151 }
152
153
154 SUserKey
ExtractUserKey(const CJsonNode & message)155 ExtractUserKey(const CJsonNode & message)
156 {
157 SUserKey result;
158
159 if (message.HasKey("UserKey")) {
160 CJsonNode user_key = message.GetByKey("UserKey");
161 if (user_key.HasKey("UniqueID"))
162 result.m_UniqueID = user_key.GetString("UniqueID");
163 if (user_key.HasKey("AppDomain"))
164 result.m_AppDomain = user_key.GetString("AppDomain");
165 }
166 return result;
167 }
168
169
170 CJsonNode
CreateResponseMessage(Int8 serial_number)171 CreateResponseMessage(Int8 serial_number)
172 {
173 CJsonNode reply_message(CJsonNode::NewObjectNode());
174
175 reply_message.SetString("Type", kMessageTypeReply);
176 reply_message.SetString("Status", kStatusOK);
177 reply_message.SetInteger("RE", serial_number);
178
179 return reply_message;
180 }
181
182
183 CJsonNode
CreateErrorResponseMessage(Int8 serial_number,Int8 error_code,const string & error_message,const string & scope,Int8 sub_code)184 CreateErrorResponseMessage(Int8 serial_number,
185 Int8 error_code,
186 const string & error_message,
187 const string & scope,
188 Int8 sub_code)
189 {
190 CJsonNode reply_message(CJsonNode::NewObjectNode());
191 CJsonNode errors(CJsonNode::NewArrayNode());
192
193 reply_message.SetString("Type", kMessageTypeReply);
194 reply_message.SetString("Status", kStatusError);
195 reply_message.SetInteger("RE", serial_number);
196
197 errors.Append(CreateIssue(error_code, error_message, scope, sub_code));
198
199 reply_message.SetByKey("Errors", errors);
200
201 return reply_message;
202 }
203
204
205 void
AppendWarning(CJsonNode & message,Int8 code,const string & warning_message,const string & scope,Int8 sub_code)206 AppendWarning(CJsonNode & message,
207 Int8 code,
208 const string & warning_message,
209 const string & scope,
210 Int8 sub_code)
211 {
212 CJsonNode warnings;
213 if (!message.HasKey("Warnings"))
214 message.SetByKey("Warnings", warnings = CJsonNode::NewArrayNode());
215 else
216 warnings = message.GetByKey("Warnings");
217
218 warnings.Append(CreateIssue(code, warning_message, scope, sub_code));
219 }
220
221
222 void
AppendError(CJsonNode & message,Int8 code,const string & error_message,const string & scope,Int8 sub_code,bool update_status)223 AppendError(CJsonNode & message,
224 Int8 code,
225 const string & error_message,
226 const string & scope,
227 Int8 sub_code,
228 bool update_status)
229 {
230 if (update_status)
231 message.SetString("Status", kStatusError);
232
233 CJsonNode errors;
234 if (!message.HasKey("Errors"))
235 message.SetByKey("Errors", errors = CJsonNode::NewArrayNode());
236 else
237 errors = message.GetByKey("Errors");
238
239 errors.Append(CreateIssue(code, error_message, scope, sub_code));
240 }
241
242
243 CJsonNode
CreateIssue(Int8 error_code,const string & error_message,const string & scope,Int8 sub_code)244 CreateIssue(Int8 error_code,
245 const string & error_message,
246 const string & scope,
247 Int8 sub_code)
248 {
249 CJsonNode issue_node(CJsonNode::NewObjectNode());
250
251 issue_node.SetInteger("Code", error_code);
252 issue_node.SetString("Message", error_message);
253 issue_node.SetString("Scope", scope);
254 issue_node.SetInteger("SubCode", sub_code);
255
256 return issue_node;
257 }
258
259
GetReplyMessageProperties(const exception & ex,string * error_scope,Int8 * error_code,unsigned int * error_sub_code)260 bool GetReplyMessageProperties(const exception & ex,
261 string * error_scope,
262 Int8 * error_code,
263 unsigned int * error_sub_code)
264 {
265 const CNetStorageException * p =
266 dynamic_cast<const CNetStorageException *>(&ex);
267 if (p != NULL) {
268 *error_scope = p->GetType();
269 *error_code = NCBI_ERRCODE_X_NAME(NetStorageException_ErrorCode);
270 *error_sub_code = p->GetErrCode();
271 return true;
272 }
273
274 const CNetServiceException * p1 =
275 dynamic_cast<const CNetServiceException *>(&ex);
276 if (p1 != NULL) {
277 *error_scope = p1->GetType();
278 *error_code = NCBI_ERRCODE_X_NAME(NetServiceException_ErrorCode);
279 *error_sub_code = p1->GetErrCode();
280 return true;
281 }
282
283 const CNetStorageServerException * p2 =
284 dynamic_cast<const CNetStorageServerException *>(&ex);
285 if (p2 != NULL) {
286 *error_scope = p2->GetType();
287 *error_code = NCBI_ERRCODE_X_NAME(NetStorageServer_ErrorCode);
288 *error_sub_code = p2->GetErrCode();
289 return true;
290 }
291
292 const CException * p3 =
293 dynamic_cast<const CException *>(&ex);
294 if (p3 != NULL) {
295 *error_scope = p3->GetType();
296 *error_code = NCBI_ERRCODE_X_NAME(NetStorageServer_ErrorCode);
297 *error_sub_code = 0;
298 return false;
299 }
300
301 *error_scope = kScopeStdException;
302 *error_code = NCBI_ERRCODE_X_NAME(NetStorageServer_ErrorCode);
303 *error_sub_code = 0;
304 return false;
305 }
306
307
308 END_NCBI_SCOPE
309
310