Changeset 6 in chevmsgr


Ignore:
Timestamp:
08/29/15 02:20:50 (9 years ago)
Author:
cheese
Message:

modify client interface and message protocol

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/cf/network.cpp

    r4 r6  
    182182cf::network::tcp::~tcp()
    183183{
    184     close();
    185184}
    186185
  • trunk/msg.cpp

    r5 r6  
    55    makeTemplate(_obj, _type);                  \
    66
    7 namespace Message
     7#define DELIMITER   "$"
     8
     9namespace Protocol
    810{
    911    // parser
    10     void Parser::parse(const std::string & message)
     12    void Message::parse(const std::string & message)
    1113    {
    1214        mObject = json::Deserialize(message);
    1315    }
    1416
    15     std::string Parser::type() const
     17    std::string Message::type() const
    1618    {
    1719        return get<std::string>("type");
     
    3133    void Request::makeTemplate(json::Object & obj, const std::string & type) const
    3234    {
    33         obj["id"] = mID;
    34         obj["type"] = type;
    35     }
    36 
    37     std::string Request::command(const std::string & cmd) const
    38     {
    39         DECLARE_TEMPLATE_OBJECT(obj, "command");
    40 
    41         obj["command"] = cmd;
    42 
    43         return json::Serialize(obj);
     35        obj[ProtocolType::ID  ] = mID;
     36        obj[ProtocolType::TYPE] = type;
    4437    }
    4538
    4639    std::string Request::sms(const std::string & phone) const
    4740    {
    48         DECLARE_TEMPLATE_OBJECT(obj, "sms");
     41        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::SMS);
    4942
    50         obj["phone"] = phone;
     43        obj[ProtocolType::PHONE] = phone;
    5144
    5245        return json::Serialize(obj);
     
    5548    std::string Request::join(const std::string & id, const std::string & pw, const std::string & sms)
    5649    {
    57         DECLARE_TEMPLATE_OBJECT(obj, "join");
     50        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::JOIN);
    5851
    59         obj["id" ] = id;
    60         obj["pw" ] = pw;
    61         obj["sms"] = sms;
     52        obj[ProtocolType::ID ] = id;
     53        obj[ProtocolType::PW ] = pw;
     54        obj[ProtocolType::SMS] = sms;
    6255
    6356        return json::Serialize(obj);
     
    6659    std::string Request::login(const std::string & pw) const
    6760    {
    68         DECLARE_TEMPLATE_OBJECT(obj, "login");
     61        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::LOGIN);
    6962
    70         obj["pw"] = mID + "$" + pw;
     63        obj[ProtocolType::PW] = mID + DELIMITER + pw;
    7164
    7265        return json::Serialize(obj);
    7366    }
    7467
    75     std::string Request::chat(const std::string & to, const std::string & sessid, const std::string & message) const
     68    std::string Request::addFriend(const std::string & id) const
    7669    {
    77         DECLARE_TEMPLATE_OBJECT(obj, "chat");
     70        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::ADD_FRIEND);
    7871
    79         obj["from"   ] = mID;
    80         obj["to"     ] = to;
    81         obj["sess-id"] = sessid;
    82         obj["message"] = message;
     72        obj[ProtocolType::ID] = id;
    8373
    8474        return json::Serialize(obj);
    8575    }
    8676
    87     std::string Request::friendList() const
     77    std::string Request::openSession(const std::string & to) const
    8878    {
    89         DECLARE_TEMPLATE_OBJECT(obj, "friend-list");
     79        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::OPEN_SESSION);
     80
     81        obj[ProtocolType::TO] = to;
     82
     83        return json::Serialize(obj);
     84    }
     85
     86    std::string Request::chat(const std::string & sessid, const std::string & message, const int sensitive) const
     87    {
     88        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::CHAT);
     89
     90        obj[ProtocolType::FROM      ] = mID;
     91        obj[ProtocolType::SESSION_ID] = sessid;
     92        obj[ProtocolType::MESSAGE   ] = message;
     93        obj[ProtocolType::SENSITIVE ] = sensitive;
     94
     95        return json::Serialize(obj);
     96    }
     97
     98    std::string Request::getFriendList() const
     99    {
     100        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::GET_FRIEND_LIST);
    90101
    91102        return json::Serialize(obj);
     
    95106    void Response::makeTemplate(json::Object & obj, const std::string & type) const
    96107    {
    97         obj["type"] = type;
     108        obj[ProtocolType::TYPE] = type;
    98109    }
    99110
    100     std::string Response::result(const bool status) const
     111    std::string Response::result(const std::string & requestType, const bool status) const
    101112    {
    102         DECLARE_TEMPLATE_OBJECT(obj, "result");
     113        DECLARE_TEMPLATE_OBJECT(obj, ProtocolType::RESULT);
    103114
    104         obj["result"] = status;
     115        obj[ProtocolType::RESULT] = status;
    105116
    106117        return json::Serialize(obj);
  • trunk/msg.hpp

    r5 r6  
    88#include <string>
    99#include <vector>
     10
     11typedef struct SFriend
     12{
     13    std::string id;
     14    std::string name;
     15} SFriend;
     16
     17// --------------------------------------------------------------
     18
     19namespace ProtocolType
     20{
     21#define DECLARE_KEY(_t) static const std::string _t = #_t
     22
     23    DECLARE_KEY(ID);
     24    DECLARE_KEY(TYPE);
     25    DECLARE_KEY(SMS);
     26    DECLARE_KEY(PHONE);
     27    DECLARE_KEY(JOIN);
     28    DECLARE_KEY(PW);
     29    DECLARE_KEY(LOGIN);
     30    DECLARE_KEY(ADD_FRIEND);
     31    DECLARE_KEY(OPEN_SESSION);
     32    DECLARE_KEY(TO);
     33    DECLARE_KEY(CHAT);
     34    DECLARE_KEY(FROM);
     35    DECLARE_KEY(SESSION_ID);
     36    DECLARE_KEY(MESSAGE);
     37    DECLARE_KEY(SENSITIVE);
     38    DECLARE_KEY(GET_FRIEND_LIST);
     39    DECLARE_KEY(RESULT);
     40}
     41
     42namespace Protocol
     43{
     44    class Message
     45    {
     46    private:
     47        json::Object mObject;
     48
     49    public:
     50        void parse(const std::string & message);
     51
     52        template<typename T>
     53        inline T get(const std::string & key) const
     54        {
     55            return (T)mObject[key];
     56        }
     57
     58        std::string type() const;
     59    };
     60
     61    class IProtocol
     62    {
     63    public:
     64        virtual void makeTemplate(json::Object & obj, const std::string & type) const = 0;
     65    };
     66
     67    class Request : public IProtocol
     68    {
     69    private:
     70        std::string mID;
     71
     72    public:
     73        void setUserID(const std::string & id);
     74
     75        const std::string & getUserID();
     76
     77        void makeTemplate(json::Object & obj, const std::string & type) const;
     78
     79        std::string sms(const std::string & phone) const;
     80
     81        std::string join(const std::string & id, const std::string & pw, const std::string & sms);
     82
     83        std::string login(const std::string & pw) const;
     84
     85        std::string addFriend(const std::string & id) const;
     86
     87        std::string openSession(const std::string & to) const;
     88
     89        std::string chat(const std::string & sessid, const std::string & message, const int sensitive) const;
     90
     91        std::string getFriendList() const;
     92    };
     93
     94    class Response : public IProtocol
     95    {
     96    public:
     97        void makeTemplate(json::Object & obj, const std::string & type) const;
     98
     99        std::string result(const std::string & requestType, const bool status) const;
     100
     101        std::string friendList(const std::vector<SFriend> & friendList) const;
     102
     103        std::string openSession(const std::vector<std::string> & idList) const;
     104    };
     105};
     106
     107// --------------------------------------------------------------
    10108
    11109#define LOG(message)    log(__FILE__,__func__,__LINE__,message)
     
    30128              << message << std::endl;
    31129}
    32 
    33 // --------------------------------------------------------------
    34 namespace Message
    35 {
    36     class Parser
    37     {
    38     private:
    39         json::Object mObject;
    40 
    41     public:
    42         void parse(const std::string & message);
    43 
    44         template<typename T>
    45         inline T get(const std::string & key) const
    46         {
    47             return (T)mObject[key];
    48         }
    49 
    50         std::string type() const;
    51     };
    52 
    53     class IMessage
    54     {
    55     public:
    56         virtual void makeTemplate(json::Object & obj, const std::string & type) const = 0;
    57     };
    58 
    59     class Request : public IMessage
    60     {
    61     private:
    62         std::string mID;
    63 
    64     public:
    65         void setUserID(const std::string & id);
    66 
    67         const std::string & getUserID();
    68 
    69         void makeTemplate(json::Object & obj, const std::string & type) const;
    70 
    71         std::string command(const std::string & cmd) const;
    72 
    73         std::string sms(const std::string & phone) const;
    74 
    75         std::string Request::join(const std::string & id, const std::string & pw, const std::string & sms);
    76 
    77         std::string login(const std::string & pw) const;
    78 
    79         std::string Request::chat(const std::string & to, const std::string & sessid, const std::string & message) const;
    80 
    81         std::string friendList() const;
    82     };
    83 
    84     class Response : public IMessage
    85     {
    86     public:
    87         typedef struct friendInfo
    88         {
    89             std::string id;
    90             std::string name;
    91         } friendInfo;
    92 
    93     public:
    94         void makeTemplate(json::Object & obj, const std::string & type) const;
    95 
    96         std::string result(const bool status) const;
    97     };
    98 };
  • trunk/msgclnt.cpp

    r5 r6  
    1010{
    1111    cf::network::tcp * socket;
    12     SCallback * callback;
     12    MessageQ * messageQ;
    1313} SWorkerArg;
    1414
     
    1717    SWorkerArg * inst = (SWorkerArg *) arg;
    1818
    19     bool isError = false;
    20     Message::Parser parser;
     19    Protocol::Message parser;
    2120    cf::bin raw;
    2221
     
    2726            raw = inst->socket->receive();
    2827            parser.parse(raw.toString());
    29 
    30             isError = false;
    3128        }
    3229        catch (cf::exception & e)
     
    3734            if (raw.size() == 0)
    3835                break;
    39 
    40             isError = true;
    41         }
    42 
    43         if (parser.type() == "result")
    44         {
    45             SResultResponse recv;
    46 
    47             recv.result  = parser.get<bool>("result");
    48             recv.isError = isError;
    49 
    50             inst->callback->result(recv);
    51         }
    52         else if (parser.type() == "chat")
    53         {
    54             SReceivedMessage recv;
    55 
    56             recv.sessid  = parser.get<std::string>("sess-id");
    57             recv.sender  = parser.get<std::string>("from");
    58             recv.message = parser.get<std::string>("message");
    59             recv.isError = isError;
    60 
    61             inst->callback->message(recv);
    62         }
    63     }
    64 
    65     free(arg);
     36        }
     37
     38        inst->messageQ->push(parser);
     39    }
     40
     41    free(inst);
    6642
    6743    return 0;
     44}
     45
     46// --------------------------------------------------------------
     47
     48void MessageQ::push(const Protocol::Message & parser)
     49{
     50    SYNCHRONIZED(mutex)
     51    {
     52        messageQ.push_back(parser);
     53    }
     54}
     55
     56Protocol::Message MessageQ::pop(const std::string & requestType)
     57{
     58    while (true)
     59    {
     60        SYNCHRONIZED(mutex)
     61        {
     62            Protocol::Message parser = messageQ.front();
     63
     64            if (parser.type() == requestType)
     65            {
     66                messageQ.erase(messageQ.begin());
     67
     68                return parser;
     69            }
     70        }
     71    }
    6872}
    6973
     
    7579}
    7680
     81chev::~chev()
     82{
     83    socket.close();
     84}
     85
     86const std::string & chev::getLastError() const
     87{
     88    return error;
     89}
     90
    7791bool chev::connect(const std::string & host, const unsigned short port)
    7892{
     
    8195        socket.connect(host, port);
    8296
     97        SWorkerArg * arg = (SWorkerArg *)malloc(sizeof(SWorkerArg));
     98        if (!arg)
     99            return false;
     100
     101        arg->socket = &socket;
     102        arg->messageQ = &messageQ;
     103
     104        listener.start(arg);
     105
    83106        return true;
    84107    }
     
    97120        socket.send(request.join(id, pw, sms));
    98121
    99         std::string response = socket.receive().toString();
    100         Message::Parser parser;
    101         parser.parse(response);
    102 
    103         return parser.get<bool>("result");
     122        return messageQ.pop(ProtocolType::JOIN).get<bool>(ProtocolType::RESULT);
    104123    }
    105124    catch (cf::exception & e)
     
    119138        socket.send(request.login(pw));
    120139
    121         std::string response = socket.receive().toString();
    122         Message::Parser parser;
    123         parser.parse(response);
    124 
    125         return parser.get<bool>("result");
     140        return messageQ.pop(ProtocolType::LOGIN).get<bool>(ProtocolType::RESULT);
    126141    }
    127142    catch (cf::exception & e)
     
    139154        socket.send(request.sms(phone));
    140155
    141         std::string response = socket.receive().toString();
    142         Message::Parser parser;
    143         parser.parse(response);
    144 
    145         return parser.get<bool>("result");
    146     }
    147     catch (cf::exception & e)
    148     {
    149         LOG(e.what());
    150 
    151         return false;
    152     }
    153 }
    154 
    155 bool chev::runReceiver(const SCallback & cb)
    156 {
    157     if (listener.isRunning())
    158         return true;
    159 
    160     callback = cb;
    161 
    162     SWorkerArg * arg = (SWorkerArg *)malloc(sizeof(SWorkerArg));
    163     if (!arg)
    164         return false;
    165 
    166     arg->socket = &socket;
    167     arg->callback = &callback;
    168 
    169     listener.start(arg);
    170 
    171     return true;
    172 }
    173 
    174 bool chev::sendMessage(const std::string & friendid, const std::string & sessid, const std::string & message)
    175 {
    176     try
    177     {
    178         socket.send(request.chat(friendid, sessid, message));
    179 
    180         std::string response = socket.receive().toString();
    181         Message::Parser parser;
    182         parser.parse(response);
    183 
    184         return parser.get<bool>("result");
    185     }
    186     catch (cf::exception & e)
    187     {
    188         LOG(e.what());
    189 
    190         return false;
    191     }
    192 }
     156        return messageQ.pop(ProtocolType::SMS).get<bool>(ProtocolType::RESULT);
     157    }
     158    catch (cf::exception & e)
     159    {
     160        LOG(e.what());
     161
     162        return false;
     163    }
     164}
     165
     166bool chev::addFriend(const std::string & id)
     167{
     168    try
     169    {
     170        socket.send(request.addFriend(id));
     171
     172        return messageQ.pop(ProtocolType::ADD_FRIEND).get<bool>(ProtocolType::RESULT);
     173    }
     174    catch (cf::exception & e)
     175    {
     176        LOG(e.what());
     177
     178        return false;
     179    }
     180}
     181
     182std::vector<SFriend> chev::getFriendList()
     183{
     184    try
     185    {
     186        socket.send(request.getFriendList());
     187    }
     188    catch (cf::exception & e)
     189    {
     190        LOG(e.what());
     191    }
     192    return std::vector<SFriend>();
     193}
     194
     195std::string chev::getSessionID(const std::vector<std::string> & idList)
     196{
     197    try
     198    {
     199        std::string concat = idList[0];
     200
     201        for (int iter = 1 ; iter < idList.size() ; iter++)
     202            concat += "," + idList[iter];
     203
     204        if (sessionMap.find(concat) == sessionMap.end())
     205        {
     206            socket.send(request.openSession(concat));
     207
     208            std::string response = socket.receive().toString();
     209            Protocol::Message parser;
     210            parser.parse(response);
     211
     212            if (!parser.get<bool>("result"))
     213                THROW_EXCEPTION("failed to open session id");
     214
     215            sessionMap[concat] = parser.get<std::string>("sess-id");
     216        }
     217
     218        return sessionMap[concat];
     219    }
     220    catch (cf::exception & e)
     221    {
     222        LOG(e.what());
     223
     224        return "";
     225    }
     226}
     227
     228bool chev::tell(const SConversation & conversation)
     229{
     230    try
     231    {
     232        const SConversation & c = conversation;
     233
     234        socket.send(request.chat(c.sessid, c.message, c.sensitive));
     235
     236        return messageQ.pop(ProtocolType::CHAT).get<bool>(ProtocolType::RESULT);
     237    }
     238    catch (cf::exception & e)
     239    {
     240        LOG(e.what());
     241
     242        return false;
     243    }
     244}
     245
     246SConversation chev::listen()
     247{
     248    SConversation c;
     249    Protocol::Message parser = messageQ.pop(ProtocolType::CHAT);
     250
     251    c.sessid    = parser.get<std::string>(ProtocolType::SESSION_ID);
     252    c.message   = parser.get<std::string>(ProtocolType::MESSAGE);
     253    c.sensitive = parser.get<int>(ProtocolType::SENSITIVE);
     254    c.isError   = parser.get<bool>(ProtocolType::RESULT);
     255
     256    c.from      = parser.get<std::string>(ProtocolType::FROM);
     257
     258    return c;
     259}
  • trunk/msgclnt.h

    r5 r6  
    99#include "cf/task.h"
    1010
    11 typedef struct SFriend
     11typedef struct SConversation
    1212{
    13     std::string id;
    14     std::string name;
    15 } SFriend;
     13    // tell and listen
     14    std::string sessid;
     15    std::string message;
     16    int sensitive;
     17    bool isError;
    1618
    17 // for callback
     19    // only for listen
     20    std::string from;
     21} SConversation;
    1822
    19 typedef struct SResultResponse
     23class MessageQ
    2024{
    21     bool result;
    22     bool isError;
    23 } SResultResponse;
     25private:
     26    cf::task::mutex                 mutex;
     27    std::vector<Protocol::Message>  messageQ;
    2428
    25 typedef struct SReceivedMessage
    26 {
    27     std::string sessid;
    28     std::string sender;
    29     std::string message;
    30     bool isError;
    31 } SReceivedMessage;
     29public:
     30    void push(const Protocol::Message & parser);
    3231
    33 typedef int (* callback_onResultResponse)(SResultResponse &);
    34 typedef int (* callback_onReceiveMessage)(SReceivedMessage &);
    35 
    36 typedef struct SCallback
    37 {
    38     callback_onResultResponse result;
    39     callback_onReceiveMessage message;
    40 } SCallback;
     32    Protocol::Message pop(const std::string & requestType);
     33};
    4134
    4235class chev
    4336{
    4437private:
    45     Message::Request    request;
     38    Protocol::Request   request;
    4639    std::string         error;
    4740    cf::network::tcp    socket;
    4841    cf::task::thread    listener;
    49     SCallback           callback;
     42
     43    MessageQ            messageQ;
     44
     45    std::map<std::string, std::string>  sessionMap;
    5046
    5147public:
    5248    chev();
     49
     50    ~chev();
     51
     52    const std::string & getLastError() const;
    5353
    5454    bool connect(const std::string & host, unsigned short port);
     
    6464    std::vector<SFriend> getFriendList();
    6565
    66     bool sendMessage(const std::string & friendid, const std::string & sessionID, const std::string & message);
     66    std::string getSessionID(const std::vector<std::string> & idList);
    6767
    68     // call once
    69     bool runReceiver(const SCallback & cb);
     68    bool tell(const SConversation & conversation);
    7069
    71     const std::string & getLastError();
     70    SConversation listen();
    7271};
  • trunk/msgsrv.cpp

    r4 r6  
    283283}
    284284
    285 static bool command(const Message::Parser & parser)
     285static bool command(const Protocol::Message & parser)
    286286{
    287287    bool isContinued = true;
     
    305305}
    306306
    307 static std::string httpSMS(const Message::Parser & parser)
     307static std::string httpSMS(const Protocol::Message & parser)
    308308{
    309309    std::string phone = parser.get<std::string>("phone");
     
    319319        CRLF;
    320320
    321     Message::Response response;
     321    Protocol::Response response;
    322322    cf::network::tcp smsSock;
    323323    cf::network::host smsServer(url, 80);
     
    330330}
    331331
    332 static bool join(const Message::Parser & parser, const std::string & sms, const std::string & address)
     332static bool join(const Protocol::Message & parser, const std::string & sms, const std::string & address)
    333333    throw (cf::exception)
    334334{
     
    342342}
    343343
    344 static bool login(const Message::Parser & parser)
     344static bool login(const Protocol::Message & parser)
    345345    throw (cf::exception)
    346346{
     
    351351}
    352352
    353 static bool chat(const Message::Parser & parser,
     353static bool chat(const Protocol::Message & parser,
    354354                 const std::string & message)
    355355{
     
    381381        while (true)
    382382        {
    383             Message::Parser parser;
     383            Protocol::Message parser;
    384384            parser.parse(sock.receive().toString());
    385385
     
    417417        workerInitiator(*sock);
    418418
    419         Message::Response response;
     419        Protocol::Response response;
    420420        bool result = true;
    421421
     
    423423        {
    424424            std::string message = sock->receive().toString();
    425             Message::Parser parser;
     425            Protocol::Message parser;
    426426            parser.parse(message);
    427427
     
    433433                result = chat(parser, message);
    434434
    435             sock->send(response.result(result));
     435            sock->send(response.result(parser.type(), result));
    436436        }
    437437    }
Note: See TracChangeset for help on using the changeset viewer.