Initial import
[umurmur.git] / src / messages.c
1 /* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "messages.h"
37 #include "pds.h"
38 #include "log.h"
39
40
41 void dumpmsg(uint8_t *data, int size);
42
43 int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize)
44 {
45         pds_t *pds = Pds_create(buffer, bufsize);
46         int len;
47         
48         Pds_add_numval(pds, msg->messageType);
49         Pds_add_numval(pds, msg->sessionId);
50         
51         switch (msg->messageType) {
52                 case Speex:
53                         Pds_add_numval(pds, msg->payload.speex.seq);
54                         Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
55                         break;
56                 case ServerReject:
57                         Pds_add_string(pds, msg->payload.serverReject.reason);
58                         Pds_add_numval(pds, msg->payload.serverReject.type);
59                         break;
60                 case ServerSync:
61                         Pds_add_numval(pds, msg->payload.serverSync.maxBandwidth);
62                         Pds_add_string(pds, msg->payload.serverSync.welcomeText);
63                         break;
64                 case ServerJoin:
65                         Pds_add_string(pds, msg->payload.serverJoin.playerName);                        
66                         Pds_add_numval(pds, msg->payload.serverJoin.id);
67                         break;
68                 case ChannelDescUpdate:
69                         Pds_add_numval(pds, msg->payload.channelDescUpdate.id);
70                         Pds_add_string(pds, msg->payload.channelDescUpdate.desc);                       
71                         break;
72                 case ChannelAdd:
73                         Pds_add_numval(pds, msg->payload.channelAdd.id);
74                         Pds_add_numval(pds, msg->payload.channelAdd.parentId);
75                         Pds_add_string(pds, msg->payload.channelAdd.name);
76                         break;
77                 case PlayerMove:
78                         Pds_add_numval(pds, msg->payload.playerMove.victim);
79                         Pds_add_numval(pds, msg->payload.playerMove.channel);
80                         break;
81                 case QueryUsers:
82                         break;
83                 case Ping:
84                         Pds_add_numval(pds, msg->payload.ping.timestamp);
85                         break;
86                 case PingStats:
87                         Pds_add_numval(pds, msg->payload.pingStats.timestamp);
88                         Pds_add_numval(pds, msg->payload.pingStats.good);
89                         Pds_add_numval(pds, msg->payload.pingStats.late);
90                         Pds_add_numval(pds, msg->payload.pingStats.lost);
91                         Pds_add_numval(pds, msg->payload.pingStats.resync);
92                         Pds_add_double(pds, msg->payload.pingStats.dUDPPingAvg);
93                         Pds_add_double(pds, msg->payload.pingStats.dUDPPingVar);
94                         Pds_add_numval(pds, msg->payload.pingStats.UDPPackets);
95                         Pds_add_double(pds, msg->payload.pingStats.dTCPPingAvg);
96                         Pds_add_double(pds, msg->payload.pingStats.dTCPPingVar);
97                         Pds_add_numval(pds, msg->payload.pingStats.TCPPackets);                 
98                         break;
99                 case PlayerMute:
100                         break;
101                 case PlayerDeaf:
102                         break;
103                 case PlayerSelfMuteDeaf:
104                         break;
105                 case TextMessage:
106                         Pds_add_numval(pds, msg->payload.textMessage.victim);                   
107                         Pds_add_numval(pds, msg->payload.textMessage.channel);                  
108                         Pds_add_numval(pds, msg->payload.textMessage.bTree);                    
109                         Pds_add_string(pds, msg->payload.textMessage.message);
110                         break;
111                 case PermissionDenied:
112                         Pds_add_string(pds, msg->payload.permissionDenied.reason);
113                         break;
114                 case CryptSetup:
115                         Pds_append_data(pds, msg->payload.cryptSetup.key, AES_BLOCK_SIZE);
116                         Pds_append_data(pds, msg->payload.cryptSetup.serverNonce, AES_BLOCK_SIZE);
117                         Pds_append_data(pds, msg->payload.cryptSetup.clientNonce, AES_BLOCK_SIZE);
118                         break;
119                 case CryptSync:
120                         if (!msg->payload.cryptSync.empty)
121                                 Pds_append_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE);                     
122                         break;
123                 case ServerLeave:
124                         /* No info to add */
125                         break;
126
127         default:
128                 Log_warn("Unsupported message %d", msg->messageType);
129                 break;
130         }
131         len = pds->offset;
132         Pds_free(pds);
133         return len;
134 }
135
136 message_t *Msg_create(messageType_t messageType)
137 {
138         message_t *msg = malloc(sizeof(message_t));
139
140         if (msg == NULL)
141                 Log_fatal("Out of memory");
142         memset(msg, 0, sizeof(message_t));
143         msg->refcount = 1;
144         msg->messageType = messageType;
145         init_list_entry(&msg->node);
146         
147         if (msg->messageType == Speex) {
148                 msg->payload.speex.data = malloc(SPEEX_DATA_SIZE);
149                 if (msg->payload.speex.data == NULL)
150                         Log_fatal("Out of memory");
151         }
152         return msg;
153 }
154
155 void Msg_inc_ref(message_t *msg)
156 {
157         msg->refcount++;
158 }
159
160 void Msg_free(message_t *msg)
161 {
162         if (msg->refcount) msg->refcount--;
163         if (msg->refcount > 0)
164                 return;
165         if (msg->messageType == Speex)
166                 free(msg->payload.speex.data);
167         free(msg);
168 }
169
170 void dumpmsg(uint8_t *data, int size)
171 {
172         int i, r = 0, offset = 0;
173         char buf[512];
174         
175         while (r * 8 + i < size) {
176                 for (i = 0; i < 8 && r * 8 + i < size; i++) {
177                         offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
178                 }
179                 sprintf(buf + offset, "\n");
180                 printf(buf);
181                 offset = 0;
182                 r++;
183                 i = 0;
184         } 
185 }
186
187 message_t *Msg_networkToMessage(uint8_t *data, int size)
188 {
189         message_t *msg = NULL;
190         int messageType;
191         int sessionId;
192         pds_t *pds;
193
194         pds = Pds_create(data, size);
195         messageType = Pds_get_numval(pds);
196         sessionId = Pds_get_numval(pds);
197         
198         switch (messageType) {
199                 case Speex:
200                         msg = Msg_create(Speex);
201                         msg->payload.speex.seq = Pds_get_numval(pds);
202                         msg->payload.speex.size = pds->maxsize - pds->offset;
203                         memcpy(msg->payload.speex.data, &pds->data[pds->offset], pds->maxsize - pds->offset);
204                         break;
205                 case ServerAuthenticate:
206                         msg = Msg_create(ServerAuthenticate);
207                         msg->payload.serverAuthenticate.version = Pds_get_numval(pds);
208                         Pds_get_string(pds, msg->payload.serverAuthenticate.userName, MAX_TEXT);
209                         Pds_get_string(pds, msg->payload.serverAuthenticate.password, MAX_TEXT);
210                         break;
211                 case ServerReject:
212                         msg = Msg_create(ServerReject);
213                         break;
214                 case ServerSync:
215                         msg = Msg_create(ServerSync);
216                         break;
217                 case ServerJoin:
218                         msg = Msg_create(ServerJoin);
219                         break;
220                 case ServerLeave:
221                         msg = Msg_create(ServerLeave);
222                         break;
223                 case QueryUsers:
224                         msg = Msg_create(QueryUsers);
225                         break;
226                 case Ping:
227                         msg = Msg_create(Ping);
228                         msg->payload.ping.timestamp = Pds_get_numval(pds);
229                         break;
230                 case PingStats:
231                         msg = Msg_create(PingStats);
232                         msg->payload.pingStats.timestamp = Pds_get_numval(pds);
233                         msg->payload.pingStats.good = Pds_get_numval(pds);
234                         msg->payload.pingStats.late = Pds_get_numval(pds);
235                         msg->payload.pingStats.lost = Pds_get_numval(pds);
236                         msg->payload.pingStats.resync = Pds_get_numval(pds);
237                         msg->payload.pingStats.dUDPPingAvg = Pds_get_double(pds);
238                         msg->payload.pingStats.dUDPPingVar = Pds_get_double(pds);
239                         msg->payload.pingStats.UDPPackets = Pds_get_numval(pds);
240                         msg->payload.pingStats.dTCPPingAvg = Pds_get_double(pds);
241                         msg->payload.pingStats.dTCPPingVar = Pds_get_double(pds);
242                         msg->payload.pingStats.TCPPackets = Pds_get_numval(pds);
243                         break;
244                 case PlayerMute:
245                         msg = Msg_create(PlayerMute);
246                         msg->payload.playerMute.victim = Pds_get_numval(pds);
247                         msg->payload.playerMute.bMute = Pds_get_numval(pds);
248                         break;
249                 case PlayerDeaf:
250                         msg = Msg_create(PlayerDeaf);
251                         msg->payload.playerDeaf.victim = Pds_get_numval(pds);
252                         msg->payload.playerDeaf.bDeaf = Pds_get_numval(pds);
253                         break;
254                 case PlayerSelfMuteDeaf:
255                         msg = Msg_create(PlayerSelfMuteDeaf);
256                         msg->payload.playerSelfMuteDeaf.bMute = Pds_get_numval(pds);
257                         msg->payload.playerSelfMuteDeaf.bDeaf = Pds_get_numval(pds);
258                         break;
259                 case TextMessage:
260                         msg = Msg_create(TextMessage);
261                         msg->payload.textMessage.victim = Pds_get_numval(pds);
262                         msg->payload.textMessage.channel = Pds_get_numval(pds);
263                         msg->payload.textMessage.bTree = Pds_get_numval(pds);
264                         Pds_get_string(pds, msg->payload.textMessage.message, MAX_TEXT);
265                         break;
266                 case PermissionDenied:
267                         Log_warn("Ignoring message PermissionDenied - not supported");
268                         break;
269                 case CryptSetup:
270                         Log_warn("Ignoring message CryptSetup - not supported");
271                         break;
272                 case CryptSync:
273                         msg = Msg_create(CryptSync);
274                         if (Pds_get_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE) == 0)
275                                 msg->payload.cryptSync.empty = true;
276                         else
277                                 msg->payload.cryptSync.empty = false;                           
278                         break;
279                 case PlayerMove:
280                         msg = Msg_create(PlayerMove);
281                         msg->payload.playerMove.victim = Pds_get_numval(pds);
282                         msg->payload.playerMove.channel = Pds_get_numval(pds);
283                         break;
284                         
285                         /* The commands below are not supported -> no need to read the parameters */
286                 case PlayerRename:
287                         msg = Msg_create(PlayerRename);
288                         break;                  
289                 case ChannelAdd:
290                         msg = Msg_create(ChannelAdd);
291                         break;
292                 case ChannelDescUpdate:
293                         msg = Msg_create(ChannelDescUpdate);
294                         break;
295                 case ContextAction:
296                         msg = Msg_create(ContextAction);
297                         break;
298                 case ContextAddAction:
299                         msg = Msg_create(ContextAddAction);
300                         break;
301                 case ServerBanList:
302                         msg = Msg_create(ServerBanList);
303                         break;
304                 case PlayerKick:
305                         msg = Msg_create(PlayerKick);
306                         break;
307                 case PlayerBan:
308                         msg = Msg_create(PlayerBan);
309                         break;
310                 case ChannelRemove:
311                         msg = Msg_create(ChannelRemove);
312                         break;
313                 case ChannelMove:
314                         msg = Msg_create(ChannelMove);
315                         break;
316                 case ChannelLink:
317                         msg = Msg_create(ChannelLink);
318                         break;
319                 case ChannelRename:
320                         msg = Msg_create(ChannelRename);
321                         break;
322                 case EditACL:
323                         msg = Msg_create(EditACL);
324                         break;
325                 case PlayerTexture:
326                         msg = Msg_create(PlayerTexture);
327                         break;
328                 default:
329                         Log_warn("Message: Type %d (session %d) is unknown type", messageType, sessionId);
330         }
331         if (msg) {
332                 msg->sessionId = sessionId;
333 #if 0
334                 if (!pds->bOk) {
335                         Msg_free(msg);
336                         msg = NULL;
337                         Log_warn("Message: Type %d (session %d, size %d) corrupt or short packet",
338                                          messageType, sessionId, pds->offset);
339                 } else if (pds->maxsize - pds->offset != 0) {
340                         Msg_free(msg);
341                         msg = NULL;
342                         Log_warn("Message: Type %d (session %d) Long packet: %d/%d leftover bytes",
343                                          messageType, sessionId, pds->overshoot, pds->offset);
344                 } else if (!pds->bOk) {
345                         Msg_free(msg);
346                         msg = NULL;
347                         Log_warn("Message: Type %d (session %d, size %d) failed to validate", messageType, sessionId, pds->maxsize);
348                 }
349 #endif
350         }
351         Pds_free(pds);
352         return msg;
353 }