source: chevmsgr/trunk/msgclnt.cpp@ 12

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

add dialogs

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