summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Messenger.c546
-rw-r--r--core/Messenger.h134
-rw-r--r--core/friend_requests.c9
-rw-r--r--core/friend_requests.h2
4 files changed, 383 insertions, 308 deletions
diff --git a/core/Messenger.c b/core/Messenger.c
index 88f71b3d..58993a08 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -26,40 +26,8 @@
26 26
27#define MIN(a,b) (((a)<(b))?(a):(b)) 27#define MIN(a,b) (((a)<(b))?(a):(b))
28 28
29typedef struct { 29static void set_friend_status(Messenger *m, int friendnumber, uint8_t status);
30 uint8_t client_id[CLIENT_ID_SIZE]; 30static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length);
31 int crypt_connection_id;
32 uint64_t friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */
33 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
34 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
35 uint8_t name[MAX_NAME_LENGTH];
36 uint8_t name_sent; /* 0 if we didn't send our name to this friend 1 if we have. */
37 uint8_t *statusmessage;
38 uint16_t statusmessage_length;
39 uint8_t statusmessage_sent;
40 USERSTATUS userstatus;
41 uint8_t userstatus_sent;
42 uint16_t info_size; /* length of the info */
43 uint32_t message_id; /* a semi-unique id used in read receipts */
44 uint8_t receives_read_receipts; /* shall we send read receipts to this person? */
45} Friend;
46
47uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
48
49static uint8_t self_name[MAX_NAME_LENGTH];
50static uint16_t self_name_length;
51
52static uint8_t self_statusmessage[MAX_STATUSMESSAGE_LENGTH];
53static uint16_t self_statusmessage_length;
54
55static USERSTATUS self_userstatus;
56
57static Friend *friendlist;
58static uint32_t numfriends;
59
60
61static void set_friend_status(int friendnumber, uint8_t status);
62static int write_cryptpacket_id(int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length);
63 31
64/* 1 if we are online 32/* 1 if we are online
65 0 if we are offline 33 0 if we are offline
@@ -67,24 +35,24 @@ static int write_cryptpacket_id(int friendnumber, uint8_t packet_id, uint8_t *da
67 35
68/* set the size of the friend list to numfriends 36/* set the size of the friend list to numfriends
69 return -1 if realloc fails */ 37 return -1 if realloc fails */
70int realloc_friendlist(uint32_t num) { 38int realloc_friendlist(Messenger *m, uint32_t num) {
71 Friend *newfriendlist = realloc(friendlist, num*sizeof(Friend)); 39 Friend *newfriendlist = realloc(m->friendlist, num*sizeof(Friend));
72 if (newfriendlist == NULL) 40 if (newfriendlist == NULL)
73 return -1; 41 return -1;
74 memset(&newfriendlist[num-1], 0, sizeof(Friend)); 42 memset(&newfriendlist[num-1], 0, sizeof(Friend));
75 friendlist = newfriendlist; 43 m->friendlist = newfriendlist;
76 return 0; 44 return 0;
77} 45}
78 46
79/* return the friend id associated to that public key. 47/* return the friend id associated to that public key.
80 return -1 if no such friend */ 48 return -1 if no such friend */
81int getfriend_id(uint8_t *client_id) 49int getfriend_id(Messenger *m, uint8_t *client_id)
82{ 50{
83 uint32_t i; 51 uint32_t i;
84 52
85 for (i = 0; i < numfriends; ++i) { 53 for (i = 0; i < m->numfriends; ++i) {
86 if (friendlist[i].status > 0) 54 if (m->friendlist[i].status > 0)
87 if (memcmp(client_id, friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) 55 if (memcmp(client_id, m->friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0)
88 return i; 56 return i;
89 } 57 }
90 58
@@ -95,13 +63,13 @@ int getfriend_id(uint8_t *client_id)
95 make sure that client_id is of size CLIENT_ID_SIZE. 63 make sure that client_id is of size CLIENT_ID_SIZE.
96 return 0 if success 64 return 0 if success
97 return -1 if failure. */ 65 return -1 if failure. */
98int getclient_id(int friend_id, uint8_t *client_id) 66int getclient_id(Messenger *m, int friend_id, uint8_t *client_id)
99{ 67{
100 if (friend_id >= numfriends || friend_id < 0) 68 if (friend_id >= m->numfriends || friend_id < 0)
101 return -1; 69 return -1;
102 70
103 if (friendlist[friend_id].status > 0) { 71 if (m->friendlist[friend_id].status > 0) {
104 memcpy(client_id, friendlist[friend_id].client_id, CLIENT_ID_SIZE); 72 memcpy(client_id, m->friendlist[friend_id].client_id, CLIENT_ID_SIZE);
105 return 0; 73 return 0;
106 } 74 }
107 75
@@ -120,7 +88,7 @@ int getclient_id(int friend_id, uint8_t *client_id)
120 * return FAERR_ALREADYSENT if friend request already sent or already a friend 88 * return FAERR_ALREADYSENT if friend request already sent or already a friend
121 * return FAERR_UNKNOWN for unknown error 89 * return FAERR_UNKNOWN for unknown error
122 */ 90 */
123int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) 91int m_addfriend(Messenger *m, uint8_t *client_id, uint8_t *data, uint16_t length)
124{ 92{
125 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES 93 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
126 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES 94 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
@@ -130,57 +98,57 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
130 return FAERR_NOMESSAGE; 98 return FAERR_NOMESSAGE;
131 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) 99 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
132 return FAERR_OWNKEY; 100 return FAERR_OWNKEY;
133 if (getfriend_id(client_id) != -1) 101 if (getfriend_id(m, client_id) != -1)
134 return FAERR_ALREADYSENT; 102 return FAERR_ALREADYSENT;
135 103
136 /* resize the friend list if necessary */ 104 /* resize the friend list if necessary */
137 realloc_friendlist(numfriends + 1); 105 realloc_friendlist(m, m->numfriends + 1);
138 106
139 uint32_t i; 107 uint32_t i;
140 for (i = 0; i <= numfriends; ++i) { 108 for (i = 0; i <= m->numfriends; ++i) {
141 if (friendlist[i].status == NOFRIEND) { 109 if (m->friendlist[i].status == NOFRIEND) {
142 DHT_addfriend(client_id); 110 DHT_addfriend(client_id);
143 friendlist[i].status = FRIEND_ADDED; 111 m->friendlist[i].status = FRIEND_ADDED;
144 friendlist[i].crypt_connection_id = -1; 112 m->friendlist[i].crypt_connection_id = -1;
145 friendlist[i].friend_request_id = -1; 113 m->friendlist[i].friend_request_id = -1;
146 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 114 memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
147 friendlist[i].statusmessage = calloc(1, 1); 115 m->friendlist[i].statusmessage = calloc(1, 1);
148 friendlist[i].statusmessage_length = 1; 116 m->friendlist[i].statusmessage_length = 1;
149 friendlist[i].userstatus = USERSTATUS_NONE; 117 m->friendlist[i].userstatus = USERSTATUS_NONE;
150 memcpy(friendlist[i].info, data, length); 118 memcpy(m->friendlist[i].info, data, length);
151 friendlist[i].info_size = length; 119 m->friendlist[i].info_size = length;
152 friendlist[i].message_id = 0; 120 m->friendlist[i].message_id = 0;
153 friendlist[i].receives_read_receipts = 1; /* default: YES */ 121 m->friendlist[i].receives_read_receipts = 1; /* default: YES */
154 122
155 ++numfriends; 123 ++ m->numfriends;
156 return i; 124 return i;
157 } 125 }
158 } 126 }
159 return FAERR_UNKNOWN; 127 return FAERR_UNKNOWN;
160} 128}
161 129
162int m_addfriend_norequest(uint8_t * client_id) 130int m_addfriend_norequest(Messenger *m, uint8_t * client_id)
163{ 131{
164 if (getfriend_id(client_id) != -1) 132 if (getfriend_id(m, client_id) != -1)
165 return -1; 133 return -1;
166 134
167 /* resize the friend list if necessary */ 135 /* resize the friend list if necessary */
168 realloc_friendlist(numfriends + 1); 136 realloc_friendlist(m, m->numfriends + 1);
169 137
170 uint32_t i; 138 uint32_t i;
171 for (i = 0; i <= numfriends; ++i) { 139 for (i = 0; i <= m->numfriends; ++i) {
172 if(friendlist[i].status == NOFRIEND) { 140 if(m->friendlist[i].status == NOFRIEND) {
173 DHT_addfriend(client_id); 141 DHT_addfriend(client_id);
174 friendlist[i].status = FRIEND_REQUESTED; 142 m->friendlist[i].status = FRIEND_REQUESTED;
175 friendlist[i].crypt_connection_id = -1; 143 m->friendlist[i].crypt_connection_id = -1;
176 friendlist[i].friend_request_id = -1; 144 m->friendlist[i].friend_request_id = -1;
177 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 145 memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
178 friendlist[i].statusmessage = calloc(1, 1); 146 m->friendlist[i].statusmessage = calloc(1, 1);
179 friendlist[i].statusmessage_length = 1; 147 m->friendlist[i].statusmessage_length = 1;
180 friendlist[i].userstatus = USERSTATUS_NONE; 148 m->friendlist[i].userstatus = USERSTATUS_NONE;
181 friendlist[i].message_id = 0; 149 m->friendlist[i].message_id = 0;
182 friendlist[i].receives_read_receipts = 1; /* default: YES */ 150 m->friendlist[i].receives_read_receipts = 1; /* default: YES */
183 ++numfriends; 151 ++ m->numfriends;
184 return i; 152 return i;
185 } 153 }
186 } 154 }
@@ -190,23 +158,23 @@ int m_addfriend_norequest(uint8_t * client_id)
190/* remove a friend 158/* remove a friend
191 return 0 if success 159 return 0 if success
192 return -1 if failure */ 160 return -1 if failure */
193int m_delfriend(int friendnumber) 161int m_delfriend(Messenger *m, int friendnumber)
194{ 162{
195 if (friendnumber >= numfriends || friendnumber < 0) 163 if (friendnumber >= m->numfriends || friendnumber < 0)
196 return -1; 164 return -1;
197 165
198 DHT_delfriend(friendlist[friendnumber].client_id); 166 DHT_delfriend(m->friendlist[friendnumber].client_id);
199 crypto_kill(friendlist[friendnumber].crypt_connection_id); 167 crypto_kill(m->friendlist[friendnumber].crypt_connection_id);
200 free(friendlist[friendnumber].statusmessage); 168 free(m->friendlist[friendnumber].statusmessage);
201 memset(&friendlist[friendnumber], 0, sizeof(Friend)); 169 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
202 uint32_t i; 170 uint32_t i;
203 171
204 for (i = numfriends; i != 0; --i) { 172 for (i = m->numfriends; i != 0; --i) {
205 if (friendlist[i-1].status != NOFRIEND) 173 if (m->friendlist[i-1].status != NOFRIEND)
206 break; 174 break;
207 } 175 }
208 numfriends = i; 176 m->numfriends = i;
209 realloc_friendlist(numfriends + 1); 177 realloc_friendlist(m, m->numfriends + 1);
210 178
211 return 0; 179 return 0;
212} 180}
@@ -216,31 +184,31 @@ int m_delfriend(int friendnumber)
216 return FRIEND_REQUESTED if the friend request was sent 184 return FRIEND_REQUESTED if the friend request was sent
217 return FRIEND_ADDED if the friend was added 185 return FRIEND_ADDED if the friend was added
218 return NOFRIEND if there is no friend with that number */ 186 return NOFRIEND if there is no friend with that number */
219int m_friendstatus(int friendnumber) 187int m_friendstatus(Messenger *m, int friendnumber)
220{ 188{
221 if (friendnumber < 0 || friendnumber >= numfriends) 189 if (friendnumber < 0 || friendnumber >= m->numfriends)
222 return NOFRIEND; 190 return NOFRIEND;
223 return friendlist[friendnumber].status; 191 return m->friendlist[friendnumber].status;
224} 192}
225 193
226/* send a text chat message to an online friend 194/* send a text chat message to an online friend
227 return the message id if packet was successfully put into the send queue 195 return the message id if packet was successfully put into the send queue
228 return 0 if it was not */ 196 return 0 if it was not */
229uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) 197uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_t length)
230{ 198{
231 if (friendnumber < 0 || friendnumber >= numfriends) 199 if (friendnumber < 0 || friendnumber >= m->numfriends)
232 return 0; 200 return 0;
233 uint32_t msgid = ++friendlist[friendnumber].message_id; 201 uint32_t msgid = ++m->friendlist[friendnumber].message_id;
234 if (msgid == 0) 202 if (msgid == 0)
235 msgid = 1; /* otherwise, false error */ 203 msgid = 1; /* otherwise, false error */
236 if(m_sendmessage_withid(friendnumber, msgid, message, length)) { 204 if(m_sendmessage_withid(m, friendnumber, msgid, message, length)) {
237 return msgid; 205 return msgid;
238 } 206 }
239 207
240 return 0; 208 return 0;
241} 209}
242 210
243uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length) 211uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, uint8_t *message, uint32_t length)
244{ 212{
245 if (length >= (MAX_DATA_SIZE - sizeof(theid))) 213 if (length >= (MAX_DATA_SIZE - sizeof(theid)))
246 return 0; 214 return 0;
@@ -248,34 +216,34 @@ uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message
248 theid = htonl(theid); 216 theid = htonl(theid);
249 memcpy(temp, &theid, sizeof(theid)); 217 memcpy(temp, &theid, sizeof(theid));
250 memcpy(temp + sizeof(theid), message, length); 218 memcpy(temp + sizeof(theid), message, length);
251 return write_cryptpacket_id(friendnumber, PACKET_ID_MESSAGE, temp, length + sizeof(theid)); 219 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, length + sizeof(theid));
252} 220}
253 221
254/* send an action to an online friend 222/* send an action to an online friend
255 return 1 if packet was successfully put into the send queue 223 return 1 if packet was successfully put into the send queue
256 return 0 if it was not */ 224 return 0 if it was not */
257int m_sendaction(int friendnumber, uint8_t *action, uint32_t length) 225int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length)
258{ 226{
259 return write_cryptpacket_id(friendnumber, PACKET_ID_ACTION, action, length); 227 return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, action, length);
260} 228}
261 229
262/* send a name packet to friendnumber 230/* send a name packet to friendnumber
263 length is the length with the NULL terminator*/ 231 length is the length with the NULL terminator*/
264static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) 232static int m_sendname(Messenger *m, int friendnumber, uint8_t * name, uint16_t length)
265{ 233{
266 if(length > MAX_NAME_LENGTH || length == 0) 234 if(length > MAX_NAME_LENGTH || length == 0)
267 return 0; 235 return 0;
268 return write_cryptpacket_id(friendnumber, PACKET_ID_NICKNAME, name, length); 236 return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length);
269} 237}
270 238
271/* set the name of a friend 239/* set the name of a friend
272 return 0 if success 240 return 0 if success
273 return -1 if failure */ 241 return -1 if failure */
274static int setfriendname(int friendnumber, uint8_t * name) 242static int setfriendname(Messenger *m, int friendnumber, uint8_t * name)
275{ 243{
276 if (friendnumber >= numfriends || friendnumber < 0) 244 if (friendnumber >= m->numfriends || friendnumber < 0)
277 return -1; 245 return -1;
278 memcpy(friendlist[friendnumber].name, name, MAX_NAME_LENGTH); 246 memcpy(m->friendlist[friendnumber].name, name, MAX_NAME_LENGTH);
279 return 0; 247 return 0;
280} 248}
281 249
@@ -285,15 +253,15 @@ static int setfriendname(int friendnumber, uint8_t * name)
285 length is the length of name with the NULL terminator 253 length is the length of name with the NULL terminator
286 return 0 if success 254 return 0 if success
287 return -1 if failure */ 255 return -1 if failure */
288int setname(uint8_t * name, uint16_t length) 256int setname(Messenger *m, uint8_t * name, uint16_t length)
289{ 257{
290 if (length > MAX_NAME_LENGTH || length == 0) 258 if (length > MAX_NAME_LENGTH || length == 0)
291 return -1; 259 return -1;
292 memcpy(self_name, name, length); 260 memcpy(m->name, name, length);
293 self_name_length = length; 261 m->name_length = length;
294 uint32_t i; 262 uint32_t i;
295 for (i = 0; i < numfriends; ++i) 263 for (i = 0; i < m->numfriends; ++i)
296 friendlist[i].name_sent = 0; 264 m->friendlist[i].name_sent = 0;
297 return 0; 265 return 0;
298} 266}
299 267
@@ -301,10 +269,10 @@ int setname(uint8_t * name, uint16_t length)
301 put it in name 269 put it in name
302 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. 270 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
303 return the length of the name */ 271 return the length of the name */
304uint16_t getself_name(uint8_t *name) 272uint16_t getself_name(Messenger *m, uint8_t *name)
305{ 273{
306 memcpy(name, self_name, self_name_length); 274 memcpy(name, m->name, m->name_length);
307 return self_name_length; 275 return m->name_length;
308} 276}
309 277
310/* get name of friendnumber 278/* get name of friendnumber
@@ -312,272 +280,298 @@ uint16_t getself_name(uint8_t *name)
312 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. 280 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
313 return 0 if success 281 return 0 if success
314 return -1 if failure */ 282 return -1 if failure */
315int getname(int friendnumber, uint8_t * name) 283int getname(Messenger *m, int friendnumber, uint8_t * name)
316{ 284{
317 if (friendnumber >= numfriends || friendnumber < 0) 285 if (friendnumber >= m->numfriends || friendnumber < 0)
318 return -1; 286 return -1;
319 memcpy(name, friendlist[friendnumber].name, MAX_NAME_LENGTH); 287 memcpy(name, m->friendlist[friendnumber].name, MAX_NAME_LENGTH);
320 return 0; 288 return 0;
321} 289}
322 290
323int m_set_statusmessage(uint8_t *status, uint16_t length) 291int m_set_statusmessage(Messenger *m, uint8_t *status, uint16_t length)
324{ 292{
325 if (length > MAX_STATUSMESSAGE_LENGTH) 293 if (length > MAX_STATUSMESSAGE_LENGTH)
326 return -1; 294 return -1;
327 memcpy(self_statusmessage, status, length); 295 memcpy(m->statusmessage, status, length);
328 self_statusmessage_length = length; 296 m->statusmessage_length = length;
329 297
330 uint32_t i; 298 uint32_t i;
331 for (i = 0; i < numfriends; ++i) 299 for (i = 0; i < m->numfriends; ++i)
332 friendlist[i].statusmessage_sent = 0; 300 m->friendlist[i].statusmessage_sent = 0;
333 return 0; 301 return 0;
334} 302}
335 303
336int m_set_userstatus(USERSTATUS status) 304int m_set_userstatus(Messenger *m, USERSTATUS status)
337{ 305{
338 if (status >= USERSTATUS_INVALID) { 306 if (status >= USERSTATUS_INVALID) {
339 return -1; 307 return -1;
340 } 308 }
341 self_userstatus = status; 309 m->userstatus = status;
342 uint32_t i; 310 uint32_t i;
343 for (i = 0; i < numfriends; ++i) 311 for (i = 0; i < m->numfriends; ++i)
344 friendlist[i].userstatus_sent = 0; 312 m->friendlist[i].userstatus_sent = 0;
345 return 0; 313 return 0;
346} 314}
347 315
348/* return the size of friendnumber's user status 316/* return the size of friendnumber's user status
349 guaranteed to be at most MAX_STATUSMESSAGE_LENGTH */ 317 guaranteed to be at most MAX_STATUSMESSAGE_LENGTH */
350int m_get_statusmessage_size(int friendnumber) 318int m_get_statusmessage_size(Messenger *m, int friendnumber)
351{ 319{
352 if (friendnumber >= numfriends || friendnumber < 0) 320 if (friendnumber >= m->numfriends || friendnumber < 0)
353 return -1; 321 return -1;
354 return friendlist[friendnumber].statusmessage_length; 322 return m->friendlist[friendnumber].statusmessage_length;
355} 323}
356 324
357/* copy the user status of friendnumber into buf, truncating if needed to maxlen 325/* copy the user status of friendnumber into buf, truncating if needed to maxlen
358 bytes, use m_get_statusmessage_size to find out how much you need to allocate */ 326 bytes, use m_get_statusmessage_size to find out how much you need to allocate */
359int m_copy_statusmessage(int friendnumber, uint8_t * buf, uint32_t maxlen) 327int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t * buf, uint32_t maxlen)
360{ 328{
361 if (friendnumber >= numfriends || friendnumber < 0) 329 if (friendnumber >= m->numfriends || friendnumber < 0)
362 return -1; 330 return -1;
363 memset(buf, 0, maxlen); 331 memset(buf, 0, maxlen);
364 memcpy(buf, friendlist[friendnumber].statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1); 332 memcpy(buf, m->friendlist[friendnumber].statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1);
365 return 0; 333 return 0;
366} 334}
367 335
368int m_copy_self_statusmessage(uint8_t * buf, uint32_t maxlen) 336int m_copy_self_statusmessage(Messenger *m, uint8_t * buf, uint32_t maxlen)
369{ 337{
370 memset(buf, 0, maxlen); 338 memset(buf, 0, maxlen);
371 memcpy(buf, self_statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1); 339 memcpy(buf, m->statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1);
372 return 0; 340 return 0;
373} 341}
374 342
375USERSTATUS m_get_userstatus(int friendnumber) 343USERSTATUS m_get_userstatus(Messenger *m, int friendnumber)
376{ 344{
377 if (friendnumber >= numfriends || friendnumber < 0) 345 if (friendnumber >= m->numfriends || friendnumber < 0)
378 return USERSTATUS_INVALID; 346 return USERSTATUS_INVALID;
379 USERSTATUS status = friendlist[friendnumber].userstatus; 347 USERSTATUS status = m->friendlist[friendnumber].userstatus;
380 if (status >= USERSTATUS_INVALID) { 348 if (status >= USERSTATUS_INVALID) {
381 status = USERSTATUS_NONE; 349 status = USERSTATUS_NONE;
382 } 350 }
383 return status; 351 return status;
384} 352}
385 353
386USERSTATUS m_get_self_userstatus(void) 354USERSTATUS m_get_self_userstatus(Messenger *m)
387{ 355{
388 return self_userstatus; 356 return m->userstatus;
389} 357}
390 358
391static int send_statusmessage(int friendnumber, uint8_t * status, uint16_t length) 359static int send_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length)
392{ 360{
393 return write_cryptpacket_id(friendnumber, PACKET_ID_STATUSMESSAGE, status, length); 361 return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length);
394} 362}
395 363
396static int send_userstatus(int friendnumber, USERSTATUS status) 364static int send_userstatus(Messenger *m, int friendnumber, USERSTATUS status)
397{ 365{
398 uint8_t stat = status; 366 uint8_t stat = status;
399 return write_cryptpacket_id(friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat)); 367 return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat));
400} 368}
401 369
402static int set_friend_statusmessage(int friendnumber, uint8_t * status, uint16_t length) 370static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length)
403{ 371{
404 if (friendnumber >= numfriends || friendnumber < 0) 372 if (friendnumber >= m->numfriends || friendnumber < 0)
405 return -1; 373 return -1;
406 uint8_t *newstatus = calloc(length, 1); 374 uint8_t *newstatus = calloc(length, 1);
407 memcpy(newstatus, status, length); 375 memcpy(newstatus, status, length);
408 free(friendlist[friendnumber].statusmessage); 376 free(m->friendlist[friendnumber].statusmessage);
409 friendlist[friendnumber].statusmessage = newstatus; 377 m->friendlist[friendnumber].statusmessage = newstatus;
410 friendlist[friendnumber].statusmessage_length = length; 378 m->friendlist[friendnumber].statusmessage_length = length;
411 return 0; 379 return 0;
412} 380}
413 381
414static void set_friend_userstatus(int friendnumber, USERSTATUS status) 382static void set_friend_userstatus(Messenger *m, int friendnumber, USERSTATUS status)
415{ 383{
416 friendlist[friendnumber].userstatus = status; 384 m->friendlist[friendnumber].userstatus = status;
417} 385}
418 386
419/* Sets whether we send read receipts for friendnumber. */ 387/* Sets whether we send read receipts for friendnumber. */
420void m_set_sends_receipts(int friendnumber, int yesno) 388void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
421{ 389{
422 if (yesno != 0 || yesno != 1) 390 if (yesno != 0 || yesno != 1)
423 return; 391 return;
424 if (friendnumber >= numfriends || friendnumber < 0) 392 if (friendnumber >= m->numfriends || friendnumber < 0)
425 return; 393 return;
426 friendlist[friendnumber].receives_read_receipts = yesno; 394 m->friendlist[friendnumber].receives_read_receipts = yesno;
427} 395}
428 396
429/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); 397/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t);
430static uint8_t friend_request_isset = 0; */ 398static uint8_t friend_request_isset = 0; */
431/* set the function that will be executed when a friend request is received. */ 399/* set the function that will be executed when a friend request is received. */
432void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) 400void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata)
433{ 401{
434 callback_friendrequest(function); 402 callback_friendrequest(function, userdata);
435} 403}
436 404
437static void (*friend_message)(int, uint8_t *, uint16_t);
438static uint8_t friend_message_isset = 0;
439
440/* set the function that will be executed when a message from a friend is received. */ 405/* set the function that will be executed when a message from a friend is received. */
441void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)) 406void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
442{ 407{
443 friend_message = function; 408 m->friend_message = function;
444 friend_message_isset = 1; 409 m->friend_message_isset = 1;
410 m->friend_message_userdata = userdata;
445} 411}
446 412
447static void (*friend_action)(int, uint8_t *, uint16_t); 413void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
448static uint8_t friend_action_isset = 0;
449void m_callback_action(void (*function)(int, uint8_t *, uint16_t))
450{ 414{
451 friend_action = function; 415 m->friend_action = function;
452 friend_action_isset = 1; 416 m->friend_action_isset = 1;
417 m->friend_action_userdata = userdata;
453} 418}
454 419
455static void (*friend_namechange)(int, uint8_t *, uint16_t); 420void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
456static uint8_t friend_namechange_isset = 0;
457void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t))
458{ 421{
459 friend_namechange = function; 422 m->friend_namechange = function;
460 friend_namechange_isset = 1; 423 m->friend_namechange_isset = 1;
424 m->friend_namechange_userdata = userdata;
461} 425}
462 426
463static void (*friend_statusmessagechange)(int, uint8_t *, uint16_t); 427void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
464static uint8_t friend_statusmessagechange_isset = 0;
465void m_callback_statusmessage(void (*function)(int, uint8_t *, uint16_t))
466{ 428{
467 friend_statusmessagechange = function; 429 m->friend_statusmessagechange = function;
468 friend_statusmessagechange_isset = 1; 430 m->friend_statusmessagechange_isset = 1;
431 m->friend_statuschange_userdata = userdata;
469} 432}
470 433
471static void (*friend_userstatuschange)(int, USERSTATUS); 434void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata)
472static uint8_t friend_userstatuschange_isset = 0;
473void m_callback_userstatus(void (*function)(int, USERSTATUS))
474{ 435{
475 friend_userstatuschange = function; 436 m->friend_userstatuschange = function;
476 friend_userstatuschange_isset = 1; 437 m->friend_userstatuschange_isset = 1;
438 m->friend_userstatuschange_userdata = userdata;
477} 439}
478 440
479static void (*read_receipt)(int, uint32_t); 441void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata)
480static uint8_t read_receipt_isset = 0;
481void m_callback_read_receipt(void (*function)(int, uint32_t))
482{ 442{
483 read_receipt = function; 443 m->read_receipt = function;
484 read_receipt_isset = 1; 444 m->read_receipt_isset = 1;
445 m->read_receipt_userdata = userdata;
485} 446}
486 447
487static void (*friend_connectionstatuschange)(int, uint8_t); 448void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata)
488static uint8_t friend_connectionstatuschange_isset = 0;
489void m_callback_connectionstatus(void (*function)(int, uint8_t))
490{ 449{
491 friend_connectionstatuschange = function; 450 m->friend_connectionstatuschange = function;
492 friend_connectionstatuschange_isset = 1; 451 m->friend_connectionstatuschange_isset = 1;
452 m->friend_connectionstatuschange_userdata = userdata;
493} 453}
494 454
495static void check_friend_connectionstatus(int friendnumber, uint8_t status) 455static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
496{ 456{
497 if (!friend_connectionstatuschange_isset) 457 if (!m->friend_connectionstatuschange_isset)
498 return; 458 return;
499 if (status == NOFRIEND) 459 if (status == NOFRIEND)
500 return; 460 return;
501 const uint8_t was_connected = friendlist[friendnumber].status == FRIEND_ONLINE; 461 const uint8_t was_connected = m->friendlist[friendnumber].status == FRIEND_ONLINE;
502 const uint8_t is_connected = status == FRIEND_ONLINE; 462 const uint8_t is_connected = status == FRIEND_ONLINE;
503 if (is_connected != was_connected) 463 if (is_connected != was_connected)
504 friend_connectionstatuschange(friendnumber, is_connected); 464 m->friend_connectionstatuschange(m, friendnumber, is_connected, m->friend_connectionstatuschange_userdata);
505} 465}
506 466
507static void set_friend_status(int friendnumber, uint8_t status) 467void set_friend_status(Messenger *m, int friendnumber, uint8_t status)
508{ 468{
509 check_friend_connectionstatus(friendnumber, status); 469 check_friend_connectionstatus(m, friendnumber, status);
510 friendlist[friendnumber].status = status; 470 m->friendlist[friendnumber].status = status;
511} 471}
512 472
513static int write_cryptpacket_id(int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length) 473int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length)
514{ 474{
515 if (friendnumber < 0 || friendnumber >= numfriends) 475 if (friendnumber < 0 || friendnumber >= m->numfriends)
516 return 0; 476 return 0;
517 if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE) 477 if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE)
518 return 0; 478 return 0;
519 uint8_t packet[length + 1]; 479 uint8_t packet[length + 1];
520 packet[0] = packet_id; 480 packet[0] = packet_id;
521 memcpy(packet + 1, data, length); 481 memcpy(packet + 1, data, length);
522 return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, packet, length + 1); 482 return write_cryptpacket(m->friendlist[friendnumber].crypt_connection_id, packet, length + 1);
483}
484
485<<<<<<< HEAD
486=======
487#define PORT 33445
488/* run this at startup */
489Messenger * initMessenger(void)
490{
491 Messenger *m = calloc(1, sizeof(Messenger));
492 if( ! m )
493 return 0;
494
495 new_keys();
496 m_set_statusmessage(m, (uint8_t*)"Online", sizeof("Online"));
497 initNetCrypto();
498 IP ip;
499 ip.i = 0;
500
501 if(init_networking(ip,PORT) == -1)
502 return 0;
503
504 DHT_init();
505 LosslessUDP_init();
506 friendreq_init();
507 LANdiscovery_init();
508
509 return m;
523} 510}
524 511
512/* run this before closing shop */
513void cleanupMessenger(Messenger *m){
514 /* FIXME TODO it seems no one frees friendlist or all the elements status */
515 free(m);
516}
517
518>>>>>>> upstream/master
525//TODO: make this function not suck. 519//TODO: make this function not suck.
526static void doFriends(void) 520void doFriends(Messenger *m)
527{ 521{
528 /* TODO: add incoming connections and some other stuff. */ 522 /* TODO: add incoming connections and some other stuff. */
529 uint32_t i; 523 uint32_t i;
530 int len; 524 int len;
531 uint8_t temp[MAX_DATA_SIZE]; 525 uint8_t temp[MAX_DATA_SIZE];
532 for (i = 0; i < numfriends; ++i) { 526 for (i = 0; i < m->numfriends; ++i) {
533 if (friendlist[i].status == FRIEND_ADDED) { 527 if (m->friendlist[i].status == FRIEND_ADDED) {
534 int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 528 int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].info, m->friendlist[i].info_size);
535 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */ 529 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
536 set_friend_status(i, FRIEND_REQUESTED); 530 set_friend_status(m, i, FRIEND_REQUESTED);
537 else if (fr > 0) 531 else if (fr > 0)
538 set_friend_status(i, FRIEND_REQUESTED); 532 set_friend_status(m, i, FRIEND_REQUESTED);
539 } 533 }
540 if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */ 534 if (m->friendlist[i].status == FRIEND_REQUESTED || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
541 if (friendlist[i].status == FRIEND_REQUESTED) { 535 if (m->friendlist[i].status == FRIEND_REQUESTED) {
542 if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/ 536 if (m->friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
543 send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 537 send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].info, m->friendlist[i].info_size);
544 friendlist[i].friend_request_id = unix_time(); 538 m->friendlist[i].friend_request_id = unix_time();
545 } 539 }
546 } 540 }
547 IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); 541 IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id);
548 switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) { 542 switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) {
549 case 0: 543 case 0:
550 if (friendip.ip.i > 1) 544 if (friendip.ip.i > 1)
551 friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); 545 m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip);
552 break; 546 break;
553 case 3: /* Connection is established */ 547 case 3: /* Connection is established */
554 set_friend_status(i, FRIEND_ONLINE); 548 set_friend_status(m, i, FRIEND_ONLINE);
555 friendlist[i].name_sent = 0; 549 m->friendlist[i].name_sent = 0;
556 friendlist[i].userstatus_sent = 0; 550 m->friendlist[i].userstatus_sent = 0;
557 friendlist[i].statusmessage_sent = 0; 551 m->friendlist[i].statusmessage_sent = 0;
558 break; 552 break;
559 case 4: 553 case 4:
560 crypto_kill(friendlist[i].crypt_connection_id); 554 crypto_kill(m->friendlist[i].crypt_connection_id);
561 friendlist[i].crypt_connection_id = -1; 555 m->friendlist[i].crypt_connection_id = -1;
562 break; 556 break;
563 default: 557 default:
564 break; 558 break;
565 } 559 }
566 } 560 }
567 while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */ 561 while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
568 if (friendlist[i].name_sent == 0) { 562 if (m->friendlist[i].name_sent == 0) {
569 if (m_sendname(i, self_name, self_name_length)) 563 if (m_sendname(m, i, m->name, m->name_length))
570 friendlist[i].name_sent = 1; 564 m->friendlist[i].name_sent = 1;
571 } 565 }
572 if (friendlist[i].statusmessage_sent == 0) { 566 if (m->friendlist[i].statusmessage_sent == 0) {
573 if (send_statusmessage(i, self_statusmessage, self_statusmessage_length)) 567 if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length))
574 friendlist[i].statusmessage_sent = 1; 568 m->friendlist[i].statusmessage_sent = 1;
575 } 569 }
576 if (friendlist[i].userstatus_sent == 0) { 570 if (m->friendlist[i].userstatus_sent == 0) {
577 if (send_userstatus(i, self_userstatus)) 571 if (send_userstatus(m, i, m->userstatus))
578 friendlist[i].userstatus_sent = 1; 572 m->friendlist[i].userstatus_sent = 1;
579 } 573 }
580 len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); 574 len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp);
581 uint8_t packet_id = temp[0]; 575 uint8_t packet_id = temp[0];
582 uint8_t* data = temp + 1; 576 uint8_t* data = temp + 1;
583 int data_length = len - 1; 577 int data_length = len - 1;
@@ -586,10 +580,10 @@ static void doFriends(void)
586 case PACKET_ID_NICKNAME: { 580 case PACKET_ID_NICKNAME: {
587 if (data_length >= MAX_NAME_LENGTH || data_length == 0) 581 if (data_length >= MAX_NAME_LENGTH || data_length == 0)
588 break; 582 break;
589 if(friend_namechange_isset) 583 if(m->friend_namechange_isset)
590 friend_namechange(i, data, data_length); 584 m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);
591 memcpy(friendlist[i].name, data, data_length); 585 memcpy(m->friendlist[i].name, data, data_length);
592 friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ 586 m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
593 break; 587 break;
594 } 588 }
595 case PACKET_ID_STATUSMESSAGE: { 589 case PACKET_ID_STATUSMESSAGE: {
@@ -597,9 +591,10 @@ static void doFriends(void)
597 break; 591 break;
598 uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); 592 uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
599 memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); 593 memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
600 if (friend_statusmessagechange_isset) 594 if (m->friend_statusmessagechange_isset)
601 friend_statusmessagechange(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); 595 m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH),
602 set_friend_statusmessage(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); 596 m->friend_statuschange_userdata);
597 set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
603 free(status); 598 free(status);
604 break; 599 break;
605 } 600 }
@@ -607,9 +602,9 @@ static void doFriends(void)
607 if (data_length != 1) 602 if (data_length != 1)
608 break; 603 break;
609 USERSTATUS status = data[0]; 604 USERSTATUS status = data[0];
610 if (friend_userstatuschange_isset) 605 if (m->friend_userstatuschange_isset)
611 friend_userstatuschange(i, status); 606 m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);
612 set_friend_userstatus(i, status); 607 set_friend_userstatus(m, i, status);
613 break; 608 break;
614 } 609 }
615 case PACKET_ID_MESSAGE: { 610 case PACKET_ID_MESSAGE: {
@@ -617,16 +612,16 @@ static void doFriends(void)
617 uint8_t message_id_length = 4; 612 uint8_t message_id_length = 4;
618 uint8_t *message = data + message_id_length; 613 uint8_t *message = data + message_id_length;
619 uint16_t message_length = data_length - message_id_length; 614 uint16_t message_length = data_length - message_id_length;
620 if (friendlist[i].receives_read_receipts) { 615 if (m->friendlist[i].receives_read_receipts) {
621 write_cryptpacket_id(i, PACKET_ID_RECEIPT, message_id, message_id_length); 616 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
622 } 617 }
623 if (friend_message_isset) 618 if (m->friend_message_isset)
624 (*friend_message)(i, message, message_length); 619 (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata);
625 break; 620 break;
626 } 621 }
627 case PACKET_ID_ACTION: { 622 case PACKET_ID_ACTION: {
628 if (friend_action_isset) 623 if (m->friend_action_isset)
629 (*friend_action)(i, data, data_length); 624 (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata);
630 break; 625 break;
631 } 626 }
632 case PACKET_ID_RECEIPT: { 627 case PACKET_ID_RECEIPT: {
@@ -635,16 +630,16 @@ static void doFriends(void)
635 break; 630 break;
636 memcpy(&msgid, data, sizeof(msgid)); 631 memcpy(&msgid, data, sizeof(msgid));
637 msgid = ntohl(msgid); 632 msgid = ntohl(msgid);
638 if (read_receipt_isset) 633 if (m->read_receipt_isset)
639 (*read_receipt)(i, msgid); 634 (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
640 break; 635 break;
641 } 636 }
642 } 637 }
643 } else { 638 } else {
644 if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ 639 if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
645 crypto_kill(friendlist[i].crypt_connection_id); 640 crypto_kill(m->friendlist[i].crypt_connection_id);
646 friendlist[i].crypt_connection_id = -1; 641 m->friendlist[i].crypt_connection_id = -1;
647 set_friend_status(i, FRIEND_CONFIRMED); 642 set_friend_status(m, i, FRIEND_CONFIRMED);
648 } 643 }
649 break; 644 break;
650 } 645 }
@@ -652,20 +647,20 @@ static void doFriends(void)
652 } 647 }
653} 648}
654 649
655static void doInbound(void) 650void doInbound(Messenger *m)
656{ 651{
657 uint8_t secret_nonce[crypto_box_NONCEBYTES]; 652 uint8_t secret_nonce[crypto_box_NONCEBYTES];
658 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 653 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
659 uint8_t session_key[crypto_box_PUBLICKEYBYTES]; 654 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
660 int inconnection = crypto_inbound(public_key, secret_nonce, session_key); 655 int inconnection = crypto_inbound(public_key, secret_nonce, session_key);
661 if (inconnection != -1) { 656 if (inconnection != -1) {
662 int friend_id = getfriend_id(public_key); 657 int friend_id = getfriend_id(m, public_key);
663 if (friend_id != -1) { 658 if (friend_id != -1) {
664 crypto_kill(friendlist[friend_id].crypt_connection_id); 659 crypto_kill(m->friendlist[friend_id].crypt_connection_id);
665 friendlist[friend_id].crypt_connection_id = 660 m->friendlist[friend_id].crypt_connection_id =
666 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); 661 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
667 662
668 set_friend_status(friend_id, FRIEND_CONFIRMED); 663 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
669 } 664 }
670 } 665 }
671} 666}
@@ -676,7 +671,11 @@ static void doInbound(void)
676#define LAN_DISCOVERY_INTERVAL 60 671#define LAN_DISCOVERY_INTERVAL 60
677 672
678/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ 673/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
674<<<<<<< HEAD
679static int LANdiscovery_timercallback(timer* t, void* ignore) 675static int LANdiscovery_timercallback(timer* t, void* ignore)
676=======
677void LANdiscovery(Messenger *m)
678>>>>>>> upstream/master
680{ 679{
681 send_LANdiscovery(htons(PORT)); 680 send_LANdiscovery(htons(PORT));
682 timer_start(t, LAN_DISCOVERY_INTERVAL); 681 timer_start(t, LAN_DISCOVERY_INTERVAL);
@@ -707,9 +706,10 @@ int initMessenger(void)
707} 706}
708 707
709/* the main loop that needs to be run at least 200 times per second. */ 708/* the main loop that needs to be run at least 200 times per second. */
710void doMessenger(void) 709void doMessenger(Messenger *m)
711{ 710{
712 networking_poll(); 711 networking_poll();
712<<<<<<< HEAD
713 timer_poll(); 713 timer_poll();
714 714
715 doDHT(); 715 doDHT();
@@ -717,17 +717,26 @@ void doMessenger(void)
717 doNetCrypto(); 717 doNetCrypto();
718 doInbound(); 718 doInbound();
719 doFriends(); 719 doFriends();
720=======
721
722 doDHT();
723 doLossless_UDP();
724 doNetCrypto();
725 doInbound(m);
726 doFriends(m);
727 LANdiscovery(m);
728>>>>>>> upstream/master
720} 729}
721 730
722/* returns the size of the messenger data (for saving) */ 731/* returns the size of the messenger data (for saving) */
723uint32_t Messenger_size(void) 732uint32_t Messenger_size(Messenger *m)
724{ 733{
725 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES 734 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
726 + sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * numfriends; 735 + sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * m->numfriends;
727} 736}
728 737
729/* save the messenger in data of size Messenger_size() */ 738/* save the messenger in data of size Messenger_size() */
730void Messenger_save(uint8_t *data) 739void Messenger_save(Messenger *m, uint8_t *data)
731{ 740{
732 save_keys(data); 741 save_keys(data);
733 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 742 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
@@ -736,14 +745,14 @@ void Messenger_save(uint8_t *data)
736 data += sizeof(size); 745 data += sizeof(size);
737 DHT_save(data); 746 DHT_save(data);
738 data += size; 747 data += size;
739 size = sizeof(Friend) * numfriends; 748 size = sizeof(Friend) * m->numfriends;
740 memcpy(data, &size, sizeof(size)); 749 memcpy(data, &size, sizeof(size));
741 data += sizeof(size); 750 data += sizeof(size);
742 memcpy(data, friendlist, sizeof(Friend) * numfriends); 751 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends);
743} 752}
744 753
745/* load the messenger from data of size length. */ 754/* load the messenger from data of size length. */
746int Messenger_load(uint8_t * data, uint32_t length) 755int Messenger_load(Messenger *m, uint8_t * data, uint32_t length)
747{ 756{
748 if (length == ~0) 757 if (length == ~0)
749 return -1; 758 return -1;
@@ -775,11 +784,12 @@ int Messenger_load(uint8_t * data, uint32_t length)
775 uint32_t i; 784 uint32_t i;
776 for (i = 0; i < num; ++i) { 785 for (i = 0; i < num; ++i) {
777 if(temp[i].status != 0) { 786 if(temp[i].status != 0) {
778 int fnum = m_addfriend_norequest(temp[i].client_id); 787 int fnum = m_addfriend_norequest(m, temp[i].client_id);
779 setfriendname(fnum, temp[i].name); 788 setfriendname(m, fnum, temp[i].name);
780 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ 789 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
781 } 790 }
782 } 791 }
783 free(temp); 792 free(temp);
784 return 0; 793 return 0;
785} 794}
795
diff --git a/core/Messenger.h b/core/Messenger.h
index 9352cfbb..fa69d104 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -73,6 +73,66 @@ typedef enum {
73 USERSTATUS_INVALID 73 USERSTATUS_INVALID
74} USERSTATUS; 74} USERSTATUS;
75 75
76typedef struct {
77 uint8_t client_id[CLIENT_ID_SIZE];
78 int crypt_connection_id;
79 uint64_t friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */
80 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
81 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
82 uint8_t name[MAX_NAME_LENGTH];
83 uint8_t name_sent; /* 0 if we didn't send our name to this friend 1 if we have. */
84 uint8_t *statusmessage;
85 uint16_t statusmessage_length;
86 uint8_t statusmessage_sent;
87 USERSTATUS userstatus;
88 uint8_t userstatus_sent;
89 uint16_t info_size; /* length of the info */
90 uint32_t message_id; /* a semi-unique id used in read receipts */
91 uint8_t receives_read_receipts; /* shall we send read receipts to this person? */
92} Friend;
93
94typedef struct Messenger {
95 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
96
97 uint8_t name[MAX_NAME_LENGTH];
98 uint16_t name_length;
99
100 uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
101 uint16_t statusmessage_length;
102
103 USERSTATUS userstatus;
104
105 Friend *friendlist;
106 uint32_t numfriends;
107
108 void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
109 uint8_t friend_message_isset;
110 void* friend_message_userdata;
111 void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
112 uint8_t friend_action_isset;
113 void* friend_action_userdata;
114 void (*friend_namechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
115 uint8_t friend_namechange_isset;
116 void* friend_namechange_userdata;
117 void (*friend_statusmessagechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
118 uint8_t friend_statusmessagechange_isset;
119 void* friend_statusmessagechange_userdata;
120 void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void*);
121 uint8_t friend_userstatuschange_isset;
122 void* friend_userstatuschange_userdata;
123 void (*read_receipt)(struct Messenger *m, int, uint32_t, void*);
124 uint8_t read_receipt_isset;
125 void* read_receipt_userdata;
126 void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void*);
127 uint8_t friend_statuschange_isset;
128 void* friend_statuschange_userdata;
129 void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void*);
130 uint8_t friend_connectionstatuschange_isset;
131 void* friend_connectionstatuschange_userdata;
132
133
134} Messenger;
135
76/* 136/*
77 * add a friend 137 * add a friend
78 * set the data that will be sent along with friend request 138 * set the data that will be sent along with friend request
@@ -85,33 +145,33 @@ typedef enum {
85 * return -4 if friend request already sent or already a friend 145 * return -4 if friend request already sent or already a friend
86 * return -5 for unknown error 146 * return -5 for unknown error
87 */ 147 */
88int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); 148int m_addfriend(Messenger *m, uint8_t *client_id, uint8_t *data, uint16_t length);
89 149
90 150
91/* add a friend without sending a friendrequest. 151/* add a friend without sending a friendrequest.
92 returns the friend number if success 152 returns the friend number if success
93 return -1 if failure. */ 153 return -1 if failure. */
94int m_addfriend_norequest(uint8_t *client_id); 154int m_addfriend_norequest(Messenger *m, uint8_t *client_id);
95 155
96/* return the friend id associated to that client id. 156/* return the friend id associated to that client id.
97 return -1 if no such friend */ 157 return -1 if no such friend */
98int getfriend_id(uint8_t *client_id); 158int getfriend_id(Messenger *m, uint8_t *client_id);
99 159
100/* copies the public key associated to that friend id into client_id buffer. 160/* copies the public key associated to that friend id into client_id buffer.
101 make sure that client_id is of size CLIENT_ID_SIZE. 161 make sure that client_id is of size CLIENT_ID_SIZE.
102 return 0 if success 162 return 0 if success
103 return -1 if failure */ 163 return -1 if failure */
104int getclient_id(int friend_id, uint8_t *client_id); 164int getclient_id(Messenger *m, int friend_id, uint8_t *client_id);
105 165
106/* remove a friend */ 166/* remove a friend */
107int m_delfriend(int friendnumber); 167int m_delfriend(Messenger *m, int friendnumber);
108 168
109/* return 4 if friend is online 169/* return 4 if friend is online
110 return 3 if friend is confirmed 170 return 3 if friend is confirmed
111 return 2 if the friend request was sent 171 return 2 if the friend request was sent
112 return 1 if the friend was added 172 return 1 if the friend was added
113 return 0 if there is no friend with that number */ 173 return 0 if there is no friend with that number */
114int m_friendstatus(int friendnumber); 174int m_friendstatus(Messenger *m, int friendnumber);
115 175
116/* send a text chat message to an online friend 176/* send a text chat message to an online friend
117 returns the message id if packet was successfully put into the send queue 177 returns the message id if packet was successfully put into the send queue
@@ -120,13 +180,13 @@ int m_friendstatus(int friendnumber);
120 if one is received. 180 if one is received.
121 m_sendmessage_withid will send a message with the id of your choosing, 181 m_sendmessage_withid will send a message with the id of your choosing,
122 however we can generate an id for you by calling plain m_sendmessage. */ 182 however we can generate an id for you by calling plain m_sendmessage. */
123uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); 183uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_t length);
124uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length); 184uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, uint8_t *message, uint32_t length);
125 185
126/* send an action to an online friend 186/* send an action to an online friend
127 returns 1 if packet was successfully put into the send queue 187 returns 1 if packet was successfully put into the send queue
128 return 0 if it was not */ 188 return 0 if it was not */
129int m_sendaction(int friendnumber, uint8_t *action, uint32_t length); 189int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length);
130 190
131/* Set our nickname 191/* Set our nickname
132 name must be a string of maximum MAX_NAME_LENGTH length. 192 name must be a string of maximum MAX_NAME_LENGTH length.
@@ -134,73 +194,73 @@ int m_sendaction(int friendnumber, uint8_t *action, uint32_t length);
134 length is the length of name with the NULL terminator 194 length is the length of name with the NULL terminator
135 return 0 if success 195 return 0 if success
136 return -1 if failure */ 196 return -1 if failure */
137int setname(uint8_t *name, uint16_t length); 197int setname(Messenger *m, uint8_t *name, uint16_t length);
138 198
139/* get our nickname 199/* get our nickname
140 put it in name 200 put it in name
141 return the length of the name*/ 201 return the length of the name*/
142uint16_t getself_name(uint8_t *name); 202uint16_t getself_name(Messenger *m, uint8_t *name);
143 203
144/* get name of friendnumber 204/* get name of friendnumber
145 put it in name 205 put it in name
146 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. 206 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
147 return 0 if success 207 return 0 if success
148 return -1 if failure */ 208 return -1 if failure */
149int getname(int friendnumber, uint8_t *name); 209int getname(Messenger *m, int friendnumber, uint8_t *name);
150 210
151/* set our user status 211/* set our user status
152 you are responsible for freeing status after 212 you are responsible for freeing status after
153 returns 0 on success, -1 on failure */ 213 returns 0 on success, -1 on failure */
154int m_set_statusmessage(uint8_t *status, uint16_t length); 214int m_set_statusmessage(Messenger *m, uint8_t *status, uint16_t length);
155int m_set_userstatus(USERSTATUS status); 215int m_set_userstatus(Messenger *m, USERSTATUS status);
156 216
157/* return the length of friendnumber's status message, 217/* return the length of friendnumber's status message,
158 including null 218 including null
159 pass it into malloc */ 219 pass it into malloc */
160int m_get_statusmessage_size(int friendnumber); 220int m_get_statusmessage_size(Messenger *m, int friendnumber);
161 221
162/* copy friendnumber's status message into buf, truncating if size is over maxlen 222/* copy friendnumber's status message into buf, truncating if size is over maxlen
163 get the size you need to allocate from m_get_statusmessage_size 223 get the size you need to allocate from m_get_statusmessage_size
164 The self variant will copy our own status message. */ 224 The self variant will copy our own status message. */
165int m_copy_statusmessage(int friendnumber, uint8_t *buf, uint32_t maxlen); 225int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t *buf, uint32_t maxlen);
166int m_copy_self_statusmessage(uint8_t *buf, uint32_t maxlen); 226int m_copy_self_statusmessage(Messenger *m, uint8_t *buf, uint32_t maxlen);
167 227
168/* Return one of USERSTATUS values. 228/* Return one of USERSTATUS values.
169 * Values unknown to your application should be represented as USERSTATUS_NONE. 229 * Values unknown to your application should be represented as USERSTATUS_NONE.
170 * As above, the self variant will return our own USERSTATUS. 230 * As above, the self variant will return our own USERSTATUS.
171 * If friendnumber is invalid, this shall return USERSTATUS_INVALID. */ 231 * If friendnumber is invalid, this shall return USERSTATUS_INVALID. */
172USERSTATUS m_get_userstatus(int friendnumber); 232USERSTATUS m_get_userstatus(Messenger *m, int friendnumber);
173USERSTATUS m_get_self_userstatus(void); 233USERSTATUS m_get_self_userstatus(Messenger *m);
174 234
175/* Sets whether we send read receipts for friendnumber. 235/* Sets whether we send read receipts for friendnumber.
176 * This function is not lazy, and it will fail if yesno is not (0 or 1).*/ 236 * This function is not lazy, and it will fail if yesno is not (0 or 1).*/
177void m_set_sends_receipts(int friendnumber, int yesno); 237void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno);
178 238
179/* set the function that will be executed when a friend request is received. 239/* set the function that will be executed when a friend request is received.
180 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ 240 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
181void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); 241void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata);
182 242
183/* set the function that will be executed when a message from a friend is received. 243/* set the function that will be executed when a message from a friend is received.
184 function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ 244 function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
185void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); 245void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata);
186 246
187/* set the function that will be executed when an action from a friend is received. 247/* set the function that will be executed when an action from a friend is received.
188 function format is: function(int friendnumber, uint8_t * action, uint32_t length) */ 248 function format is: function(int friendnumber, uint8_t * action, uint32_t length) */
189void m_callback_action(void (*function)(int, uint8_t *, uint16_t)); 249void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata);
190 250
191/* set the callback for name changes 251/* set the callback for name changes
192 function(int friendnumber, uint8_t *newname, uint16_t length) 252 function(int friendnumber, uint8_t *newname, uint16_t length)
193 you are not responsible for freeing newname */ 253 you are not responsible for freeing newname */
194void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); 254void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata);
195 255
196/* set the callback for status message changes 256/* set the callback for status message changes
197 function(int friendnumber, uint8_t *newstatus, uint16_t length) 257 function(int friendnumber, uint8_t *newstatus, uint16_t length)
198 you are not responsible for freeing newstatus */ 258 you are not responsible for freeing newstatus */
199void m_callback_statusmessage(void (*function)(int, uint8_t *, uint16_t)); 259void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata);
200 260
201/* set the callback for status type changes 261/* set the callback for status type changes
202 function(int friendnumber, USERSTATUS kind) */ 262 function(int friendnumber, USERSTATUS kind) */
203void m_callback_userstatus(void (*function)(int, USERSTATUS)); 263void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata);
204 264
205/* set the callback for read receipts 265/* set the callback for read receipts
206 function(int friendnumber, uint32_t receipt) 266 function(int friendnumber, uint32_t receipt)
@@ -209,7 +269,7 @@ void m_callback_userstatus(void (*function)(int, USERSTATUS));
209 has been received on the other side. since core doesn't 269 has been received on the other side. since core doesn't
210 track ids for you, receipt may not correspond to any message 270 track ids for you, receipt may not correspond to any message
211 in that case, you should discard it. */ 271 in that case, you should discard it. */
212void m_callback_read_receipt(void (*function)(int, uint32_t)); 272void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata);
213 273
214/* set the callback for connection status changes 274/* set the callback for connection status changes
215 function(int friendnumber, uint8_t status) 275 function(int friendnumber, uint8_t status)
@@ -219,26 +279,30 @@ void m_callback_read_receipt(void (*function)(int, uint32_t));
219 note that this callback is not called when adding friends, thus the "after 279 note that this callback is not called when adding friends, thus the "after
220 being previously online" part. it's assumed that when adding friends, 280 being previously online" part. it's assumed that when adding friends,
221 their connection status is offline. */ 281 their connection status is offline. */
222void m_callback_connectionstatus(void (*function)(int, uint8_t)); 282void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata);
223 283
224/* run this at startup 284/* run this at startup
225 returns 0 if no connection problems 285 * returns allocated instance of Messenger on success
226 returns -1 if there are problems */ 286 * returns 0 if there are problems */
227int initMessenger(void); 287Messenger * initMessenger(void);
288
289/* run this before closing shop
290 * free all datastructures */
291void cleanupMessenger(Messenger *M);
228 292
229/* the main loop that needs to be run at least 200 times per second */ 293/* the main loop that needs to be run at least 200 times per second */
230void doMessenger(void); 294void doMessenger(Messenger *m);
231 295
232/* SAVING AND LOADING FUNCTIONS: */ 296/* SAVING AND LOADING FUNCTIONS: */
233 297
234/* returns the size of the messenger data (for saving) */ 298/* returns the size of the messenger data (for saving) */
235uint32_t Messenger_size(void); 299uint32_t Messenger_size(Messenger *m);
236 300
237/* save the messenger in data (must be allocated memory of size Messenger_size()) */ 301/* save the messenger in data (must be allocated memory of size Messenger_size()) */
238void Messenger_save(uint8_t *data); 302void Messenger_save(Messenger *m, uint8_t *data);
239 303
240/* load the messenger from data of size length */ 304/* load the messenger from data of size length */
241int Messenger_load(uint8_t *data, uint32_t length); 305int Messenger_load(Messenger *m, uint8_t *data, uint32_t length);
242 306
243#ifdef __cplusplus 307#ifdef __cplusplus
244} 308}
diff --git a/core/friend_requests.c b/core/friend_requests.c
index 422cc028..5e9b447c 100644
--- a/core/friend_requests.c
+++ b/core/friend_requests.c
@@ -57,14 +57,15 @@ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length)
57 return num; 57 return num;
58} 58}
59 59
60static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t); 60static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void*);
61static uint8_t handle_friendrequest_isset = 0; 61static uint8_t handle_friendrequest_isset = 0;
62 62static void* handle_friendrequest_userdata;
63/* set the function that will be executed when a friend request is received. */ 63/* set the function that will be executed when a friend request is received. */
64void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) 64void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata)
65{ 65{
66 handle_friendrequest = function; 66 handle_friendrequest = function;
67 handle_friendrequest_isset = 1; 67 handle_friendrequest_isset = 1;
68 handle_friendrequest_userdata = userdata;
68} 69}
69 70
70 71
@@ -121,7 +122,7 @@ static int friendreq_handlepacket(IP_Port source, uint8_t * packet, uint32_t len
121 return 1; 122 return 1;
122 123
123 addto_receivedlist(public_key); 124 addto_receivedlist(public_key);
124 (*handle_friendrequest)(public_key, data, len); 125 (*handle_friendrequest)(public_key, data, len, handle_friendrequest_userdata);
125 } else { /* if request is not for us, try routing it. */ 126 } else { /* if request is not for us, try routing it. */
126 if(route_packet(packet + 1, packet, length) == length) 127 if(route_packet(packet + 1, packet, length) == length)
127 return 0; 128 return 0;
diff --git a/core/friend_requests.h b/core/friend_requests.h
index 708d8f66..f18107ce 100644
--- a/core/friend_requests.h
+++ b/core/friend_requests.h
@@ -37,7 +37,7 @@ int send_friendrequest(uint8_t *public_key, uint8_t *data, uint32_t length);
37 37
38/* set the function that will be executed when a friend request for us is received. 38/* set the function that will be executed when a friend request for us is received.
39 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ 39 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
40void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); 40void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata);
41 41
42/* sets up friendreq packet handlers */ 42/* sets up friendreq packet handlers */
43void friendreq_init(void); 43void friendreq_init(void);