source: chevmsgr/trunk/msgclnt.cpp@ 14

Last change on this file since 14 was 14, checked in by cheese, 9 years ago

테스트 코드 추가
UI 모양 작업
채팅되는 상태까지 확인

File size: 6.0 KB
Line 
1
2#include "msgclnt.h"
3#include "msg.hpp"
4
5#include <algorithm>
6
7#include <stdlib.h>
8
9#include "cf/codec.h"
10
11// --------------------------------------------------------------
12
13typedef struct SMessageQWorkerArg
14{
15 cf::network::tcp * socket;
16 MessageQ * messageQ;
17} SMessageQWorkerArg;
18
19typedef struct SCallbackWorkerArg
20{
21 MessageQ * messageQ;
22 SCallback callback;
23} SCallbackWorkerArg;
24
25static int messageQworker(void * arg)
26{
27 SMessageQWorkerArg * inst = (SMessageQWorkerArg *)arg;
28
29 Protocol::Message message;
30 cf::size_t size;
31
32 while (true)
33 {
34 try
35 {
36 size = 0;
37
38 cf::bin raw = inst->socket->receive();
39 size = raw.size();
40
41 message.parse(raw.toString());
42 }
43 catch (cf::exception & e)
44 {
45 LOG(e.stackTrace());
46
47 // closed
48 if (size == 0)
49 {
50 // dummy logout
51 message.parse(Protocol::Request().logout());
52 inst->messageQ->push(message);
53 break;
54 }
55 }
56
57 inst->messageQ->push(message);
58 }
59
60 free(inst);
61
62 return 0;
63}
64
65static inline SConversation toConversation(const Protocol::Message & message)
66{
67 SConversation c;
68 std::string chat = message.get<std::string>(ProtocolType::MESSAGE);
69
70 if (chat.length() > 0)
71 c.message = cf::codec::hex::getInstance()->decode(chat).toString();
72
73 c.sessid = message.get<std::string>(ProtocolType::SESSION_ID);
74 c.sensitive = message.get<int>(ProtocolType::SENSITIVE);
75
76 c.from = message.get<std::string>(ProtocolType::FROM);
77
78 return c;
79}
80
81static inline SOpenSession toOpenSession(const Protocol::Message & message)
82{
83 SOpenSession o;
84
85 o.sessid = message.get<std::string>(ProtocolType::SESSION_ID);
86 o.idList = message.getList<std::string>(ProtocolType::ID_LIST);
87
88 return o;
89}
90
91static int callbackWorker(void * arg)
92{
93 SCallbackWorkerArg * inst = (SCallbackWorkerArg *)arg;
94
95 Protocol::Message message;
96
97 while (true)
98 {
99 message = inst->messageQ->pop(ProtocolType::LISTEN, false);
100 if (message.type() != ProtocolType::NONE)
101 inst->callback.onListen(toConversation(message));
102
103 message = inst->messageQ->pop(ProtocolType::OPEN_SESSION, false);
104 if (message.type() != ProtocolType::NONE)
105 inst->callback.onOpenSession(toOpenSession(message));
106
107 message = inst->messageQ->pop(ProtocolType::LOGOUT, false);
108 if (message.type() != ProtocolType::NONE)
109 break;
110 }
111
112 free(inst);
113
114 return 0;
115}
116
117// --------------------------------------------------------------
118
119void MessageQ::push(const Protocol::Message & message)
120{
121 mutex.lock();
122 messageQ.push_back(message);
123 mutex.unlock();
124}
125
126Protocol::Message MessageQ::pop(const std::string & requestType, bool isWait)
127{
128 do
129 {
130 mutex.lock();
131 if (messageQ.size() == 0)
132 {
133 mutex.unlock();
134 continue;
135 }
136
137 Protocol::Message message = messageQ.front();
138
139 if (message.type() == requestType)
140 {
141 messageQ.erase(messageQ.begin());
142 mutex.unlock();
143 return message;
144 }
145 mutex.unlock();
146 } while (isWait);
147
148 return Protocol::Message(); // return dummy NONE
149}
150
151// --------------------------------------------------------------
152
153chev::chev()
154 : listener(messageQworker),
155 caller(callbackWorker)
156{
157}
158
159chev::~chev()
160{
161 socket.close();
162 listener.join();
163 caller.join();
164}
165
166const std::string & chev::getLastError() const
167{
168 return error;
169}
170
171bool chev::connect(const std::string & host, const unsigned short port)
172{
173 try
174 {
175 socket.connect(host, port);
176
177 SMessageQWorkerArg * arg = (SMessageQWorkerArg *)malloc(sizeof(SMessageQWorkerArg));
178 if (!arg)
179 return false;
180
181 arg->socket = &socket;
182 arg->messageQ = &messageQ;
183
184 listener.start(arg);
185
186 return true;
187 }
188 catch (cf::exception & e)
189 {
190 LOG(e.what());
191
192 return false;
193 }
194}
195
196bool chev::join(const std::string & id, const std::string & pw, const std::string & sms)
197{
198 try
199 {
200 socket.send(request.join(id, pw, sms));
201
202 return messageQ.pop(ProtocolType::JOIN).get<bool>(ProtocolType::RESULT);
203 }
204 catch (cf::exception & e)
205 {
206 LOG(e.what());
207
208 return false;
209 }
210}
211
212bool chev::login(const std::string & id, const std::string & pw)
213{
214 try
215 {
216 request.setUserID(id);
217
218 socket.send(request.login(pw));
219
220 return messageQ.pop(ProtocolType::LOGIN).get<bool>(ProtocolType::RESULT);
221 }
222 catch (cf::exception & e)
223 {
224 LOG(e.what());
225
226 return false;
227 }
228}
229
230bool chev::sms(const std::string & phone)
231{
232 try
233 {
234 socket.send(request.sms(phone));
235
236 return messageQ.pop(ProtocolType::SMS).get<bool>(ProtocolType::RESULT);
237 }
238 catch (cf::exception & e)
239 {
240 LOG(e.what());
241
242 return false;
243 }
244}
245
246bool chev::addFriend(const std::string & id)
247{
248 try
249 {
250 socket.send(request.addFriend(id));
251
252 return messageQ.pop(ProtocolType::ADD_FRIEND).get<bool>(ProtocolType::RESULT);
253 }
254 catch (cf::exception & e)
255 {
256 LOG(e.what());
257
258 return false;
259 }
260}
261
262std::vector<SFriend> chev::getFriendList()
263{
264 std::vector<SFriend> friendList;
265
266 try
267 {
268 socket.send(request.getFriendList());
269
270 friendList = messageQ.pop(ProtocolType::FRIEND_LIST).getFriendList();
271 }
272 catch (cf::exception & e)
273 {
274 LOG(e.what());
275 }
276
277 return friendList;
278}
279
280std::string chev::getSessionID(const std::vector<std::string> & idList)
281{
282 try
283 {
284 std::vector<std::string> toList = idList;
285 toList.insert(toList.begin(), request.getUserID());
286
287 std::string concat = joinStrings(toList);
288
289 if (sessionMap.find(concat) == sessionMap.end())
290 {
291 socket.send(request.openSession(toList));
292
293 Protocol::Message message = messageQ.pop(ProtocolType::OPEN_SESSION);
294
295 sessionMap[concat] = message.get<std::string>(ProtocolType::SESSION_ID);
296 }
297
298 return sessionMap[concat];
299 }
300 catch (cf::exception & e)
301 {
302 LOG(e.what());
303
304 return "";
305 }
306}
307
308bool chev::tell(const SConversation & conversation)
309{
310 try
311 {
312 SConversation c = conversation;
313
314 if (c.message.length() > 0)
315 c.message = cf::codec::hex::getInstance()->encode(c.message);
316
317 socket.send(request.tell(c.sessid, c.message, c.sensitive));
318
319 return messageQ.pop(ProtocolType::TELL).get<bool>(ProtocolType::RESULT);
320 }
321 catch (cf::exception & e)
322 {
323 LOG(e.what());
324
325 return false;
326 }
327}
328
329bool chev::listen(const SCallback & callback)
330{
331 SCallbackWorkerArg * arg = (SCallbackWorkerArg *)malloc(sizeof(SCallbackWorkerArg));
332 if (!arg)
333 return false;
334
335 arg->messageQ = &messageQ;
336 arg->callback = callback;
337
338 caller.start(arg);
339
340 return true;
341}
Note: See TracBrowser for help on using the repository browser.