Updated license
[anna.git] / source / diameter.comm / Message.cpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 // Local
38 #include <anna/diameter.comm/Message.hpp>
39 #include <anna/diameter.comm/ClientSession.hpp>
40 #include <anna/diameter.comm/ServerSession.hpp>
41 #include <anna/diameter/codec/functions.hpp>
42 #include <anna/diameter/defines.hpp>
43
44 #include <anna/xml/Node.hpp>
45 #include <anna/core/functions.hpp>
46 #include <anna/core/RuntimeException.hpp>
47 #include <anna/comm/ClientSocket.hpp>
48 #include <anna/core/tracing/Logger.hpp>
49
50 using namespace std;
51 using namespace anna::diameter;
52 using namespace anna::diameter::comm;
53
54
55
56 const char* Message::asText(const OnExpiry::_v rc)
57 throw() {
58   static const char* text [] = { "Abandon", "Ignore" };
59   return text [rc];
60 }
61
62 string Message::asString() const
63 throw() {
64   string result("diameter::comm::Message { ");
65   result += "ClassCode: ";
66   result += ClassCode::asText(a_classCode);
67   result += " | OnExpiry: ";
68   result += asText(a_onExpiry);
69   result += " | Retries: ";
70   result += anna::functions::asString(a_retries);
71   return result += " }";
72 }
73
74 anna::xml::Node* Message::asXML(anna::xml::Node* parent) const
75 throw() {
76   anna::xml::Node* result = parent->createChild("diameter.comm.Message");
77   result->createAttribute("ClassCode", ClassCode::asText(a_classCode));
78   result->createAttribute("OnExpiry", asText(a_onExpiry));
79   result->createAttribute("Retries", anna::functions::asString(a_retries));
80   //isRequest ...
81   return result;
82 }
83
84 //void Message::clear ()
85 //   throw ()
86 //{
87 //   ::clear();
88 ////   a_classCode = ClassCode::Undefined;
89 ////   a_onExpiry = OnExpiry::Ignore;
90 //}
91
92 bool Message::fixRequestSequence(HopByHop hbh, EndToEnd ete, bool freezeEndToEnd) throw() {
93   setRequestHopByHop(getHopByHop()); // original request hop-by-hop (backup)
94   setRequestEndToEnd(getEndToEnd()); // original request end-to-end (backup)
95   bool result = false;
96
97   if(hbh != getRequestHopByHop()) {
98     codec::functions::setHopByHop((anna::DataBlock&)getBody(), hbh);
99     result = true;
100   }
101
102   if(!freezeEndToEnd) {
103     if(ete != getRequestEndToEnd()) {
104       codec::functions::setEndToEnd((anna::DataBlock&)getBody(), ete);
105       result = true;
106     }
107   }
108
109   LOGDEBUG(
110     string msg("diameter::comm::fixRequestSequence { ");
111     msg += "Hop by hop: ";
112     msg += anna::functions::asString(getRequestHopByHop());
113     msg += " (original) -> ";
114     msg += anna::functions::asString(hbh);
115     msg += " (session)";
116     msg += freezeEndToEnd ? " | End to end [freezed]: " : " | End to end: ";
117     msg += anna::functions::asString(getRequestEndToEnd());
118     msg += " (original) -> ";
119     msg += anna::functions::asString(ete);
120     msg += " (session)";
121     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
122   );
123   return result;
124 }
125
126
127
128 void Message::restoreSequencesAfterFix() throw() {
129   LOGDEBUG(
130     string msg("diameter::comm::restoreSequencesAfterFix { ");
131     msg += "Hop by hop: ";
132     msg += anna::functions::asString(getHopByHop());
133     msg += " (session) -> ";
134     msg += anna::functions::asString(getRequestHopByHop());
135     msg += " (original)";
136     msg += " | End to end: ";
137     msg += anna::functions::asString(getEndToEnd());
138     msg += " (session) -> ";
139     msg += anna::functions::asString(getRequestEndToEnd());
140     msg += " (original)";
141     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
142   );
143   diameter::codec::functions::setHopByHop((anna::DataBlock&)getBody(), a_requestHopByHop);
144   diameter::codec::functions::setEndToEnd((anna::DataBlock&)getBody(), a_requestEndToEnd);
145 }
146
147
148 void Message::send(ClientSession& clientSession) const
149 throw(anna::RuntimeException) {
150   try {
151     clientSession.getServer()->send((Message *)this);
152   } catch(anna::RuntimeException&) {
153     throw;
154   }
155 }
156
157 void Message::send(ServerSession& serverSession) const
158 throw(anna::RuntimeException) {
159   try {
160     serverSession.getClientSocket()->send((Message *)this);
161   } catch(anna::RuntimeException&) {
162     throw;
163   }
164 }
165
166
167
168 anna::diameter::CommandId Message::getCommandId(bool &isRequest) const throw() {
169   diameter::CommandId result = diameter::codec::functions::getCommandId(getBody());
170   isRequest = result.second; // diameter::codec::functions::isRequest(result);
171   return result;
172 }
173
174 HopByHop Message::getHopByHop() const throw() {
175   return (diameter::codec::functions::getHopByHop(getBody()));
176 }
177
178 EndToEnd Message::getEndToEnd() const throw() {
179   return (diameter::codec::functions::getEndToEnd(getBody()));
180 }