protocol.cpp

Go to the documentation of this file.
00001 /*
00002  * protocol.cpp
00003  *
00004  * Copyright (C) 2007,2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Base protocol objects.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "protocol.h"           // always include our own header first!
00036 
00037 #include <sstream>
00038 
00039 #include "common/wave_ex.h"
00040 #include "datahash/datahash_text.h"
00041 #include "datahash/datahash_util.h"
00042 #include "netlib/netlib.h"
00043 #include "perf/perf.h"
00044 
00045 
00046 namespace aesop {
00047 
00048 
00049 
00051 //
00052 //      static helper methods
00053 //
00055 
00056 static void
00057 addHeader
00058 (
00059 IO netlib::MessageBuffer * buffer,
00060 IN const char * namespace_,
00061 IN const char * command
00062 )
00063 {
00064         ASSERT(buffer, "null");
00065         ASSERT(namespace_, "null");
00066         ASSERT(command, "null");
00067 
00068         buffer->appendToken("header {\nnamespace ");
00069         buffer->appendToken(namespace_);
00070         buffer->appendToken("\ncommand ");
00071         buffer->appendToken(command);
00072         buffer->appendToken("\n}\n");
00073 }
00074 
00075 
00076 
00077 static smart_ptr<netlib::MessageBuffer>
00078 createMessageFromString
00079 (
00080 IN const char * namespace_,
00081 IN const char * command,
00082 IN const char * data
00083 )
00084 {
00085         perf::Timer timer("aesop::createMessageFromString");
00086         ASSERT(namespace_, "null");
00087         ASSERT(command, "null");
00088         ASSERT(data, "null");
00089 
00090         // even an empty message must at least contain a line return!
00091         static const long warnBytes = 1024;     // bigger than 1K is bad...
00092         long nBytes = strlen(data);
00093         ASSERT(nBytes > 0, "empty data string for message?");
00094         ASSERT('\n' == data[nBytes - 1],
00095             "data string must end in line return!\n%sEND", data);
00096         if (nBytes > warnBytes) {
00097                 DPRINTF("WARNING!  large message (%ld bytes)", nBytes);
00098                 DPRINTF("  namespace='%s'   command='%s'", namespace_, command);
00099         }
00100 
00101         // create buffer
00102         smart_ptr<netlib::MessageBuffer> buffer =
00103             netlib::MessageBuffer::create();
00104         ASSERT(buffer, "failed to create message buffer");
00105 
00106         // add payload (header + data)
00107         addHeader(buffer, namespace_, command);
00108         buffer->appendToken("data {\n");
00109         buffer->appendData(data, nBytes);
00110         buffer->appendToken("}\n");
00111         buffer->close();
00112 
00113         // DPRINTF("Message:\n%s", buffer->getData());
00114         return buffer;
00115 }
00116 
00117 
00118 
00119 static smart_ptr<netlib::MessageBuffer>
00120 createMessageFromSStream
00121 (
00122 IN const char * namespace_,
00123 IN const char * command,
00124 IN const std::ostringstream& oss
00125 )
00126 {
00127         ASSERT(namespace_, "null");
00128         ASSERT(command, "null");
00129 
00130         return createMessageFromString(namespace_, command, oss.str().c_str());
00131 }
00132 
00133 
00134 
00135 /*
00136 static smart_ptr<netlib::MessageBuffer>
00137 createMessageFromDatahash
00138 (
00139 IN const char * namespace_,
00140 IN const char * command,
00141 IN const Datahash * data
00142 )
00143 {
00144         ASSERT(namespace_, "null");
00145         ASSERT(command, "null");
00146 
00147         std::ostringstream oss;
00148         writeHashToStream(data, oss);
00149         oss << "\n";    // force termination in newline
00150 
00151         return createMessageFromString(namespace_, command, oss.str().c_str());
00152 }
00153 */
00154 
00155 
00156 
00158 //
00159 //      public API
00160 //
00162 
00163 
00164 
00166 //
00167 //      Message Constructors
00168 //
00170 
00172 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 smart_ptr<netlib::MessageBuffer>
00229 createTcpConnectMessage
00230 (
00231 IN long token
00232 )
00233 {
00234         ASSERT(token, "null");
00235 
00236         std::ostringstream oss;
00237         oss << "token " << token << "\n";
00238 
00239         return createMessageFromSStream("server", "tcp", oss);
00240 }
00241 
00242 
00243 
00261 smart_ptr<netlib::MessageBuffer>
00262 createNotifyErrorMessage
00263 (
00264 IN eErrorCode errorCode,
00265 IN const char * message
00266 )
00267 {
00268         // ASSERT(errorCode) -- don't care
00269         ASSERT(message, "null");
00270 
00271         std::ostringstream oss;
00272         oss << "errorCode " << errorCode << "\n";
00273         oss << "message " << message << "\n";
00274 
00275         return createMessageFromSStream("client", "error", oss);
00276 }
00277 
00278 
00279 
00315 smart_ptr<netlib::MessageBuffer>
00316 createConversationDialogMessage
00317 (
00318 IN int localPlayerId,
00319 IN const char * conversationGuid,
00320 IN int dialogId,
00321 IN const char * dialogData
00322 )
00323 {
00324         ASSERT(localPlayerId > 0, "Bad player ID: %d", localPlayerId);
00325         ASSERT(conversationGuid, "null");
00326         ASSERT(dialogId > 0, "Bad dialog id: %d", dialogId);
00327         ASSERT(dialogData, "null");
00328 
00329         std::ostringstream oss;
00330         oss << "playerId " << localPlayerId << "\n";
00331         oss << "conversationGuid " << conversationGuid << "\n";
00332         oss << "dialogId " << dialogId << "\n";
00333         oss << "dialog {\n";
00334         oss << dialogData;
00335         oss << "}\n";
00336 
00337         return createMessageFromSStream("client", "converse-dialog", oss);
00338 }
00339 
00340 
00341 
00367 smart_ptr<netlib::MessageBuffer>
00368 createConversationReplyMessage
00369 (
00370 IN int playerId,
00371 IN const char * conversationGuid,
00372 IN int dialogId,
00373 IN const char * reply
00374 )
00375 {
00376         ASSERT(playerId > 0, "Bad player id: %d", playerId);
00377         ASSERT(conversationGuid, "null");
00378         ASSERT(dialogId > 0, "Bad dialog id: %d", dialogId);
00379         ASSERT(reply, "null");
00380 
00381         std::ostringstream oss;
00382         oss << "playerId " << playerId << "\n";
00383         oss << "conversationGuid " << conversationGuid << "\n";
00384         oss << "dialogId " << dialogId << "\n";
00385         oss << "reply {\n";
00386         oss << reply << "\n";
00387         oss << "}\n";
00388 
00389         return createMessageFromSStream("server", "converse-reply", oss);
00390 }
00391 
00392 
00393 
00417 smart_ptr<netlib::MessageBuffer>
00418 createRefreshConversationMessage
00419 (
00420 IN int playerId,
00421 IN const char * conversationGuid
00422 )
00423 {
00424         ASSERT(conversationGuid, "null");
00425 
00426         std::ostringstream oss;
00427         oss << "playerId " << playerId << "\n";
00428         oss << "conversationGuid " << conversationGuid << "\n";
00429 
00430         return createMessageFromSStream("server", "converse-resend", oss);
00431 }
00432 
00433 
00434 
00458 smart_ptr<netlib::MessageBuffer>
00459 createTerminateConversationMessage
00460 (
00461 IN int playerId,
00462 IN const char * conversationGuid
00463 )
00464 {
00465         ASSERT(playerId > 0, "Bad player id: %d", playerId);
00466         ASSERT(conversationGuid, "null");
00467 
00468         std::ostringstream oss;
00469         oss << "playerId " << playerId << "\n";
00470         oss << "conversationGuid " << conversationGuid << "\n";
00471 
00472         return createMessageFromSStream("client", "converse-end", oss);
00473 }
00474 
00475 
00476 
00496 smart_ptr<netlib::MessageBuffer>
00497 createNewGameMessage
00498 (
00499 IN int playerId
00500 )
00501 {
00502         ASSERT(playerId > 0, "Bad player id: %d", playerId);
00503 
00504         std::ostringstream oss;
00505         oss << "playerId " << playerId << "\n";
00506 
00507         return createMessageFromSStream("server", "new-game", oss);
00508 }
00509 
00510 
00511 };      // aesop namespace
00512