Mercurial > pidgin.yaz
annotate src/protocols/oscar/rxqueue.c @ 13254:e9802db22b06
[gaim-migrate @ 15620]
This is the way we clean the code, clean the code, clean the code
This is the way we clean the code, clean the code, clean the code
So early in the morning
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 12 Feb 2006 22:14:38 +0000 |
parents | f260d319bbbc |
children | b08f8f3c9197 |
rev | line source |
---|---|
13234 | 1 /* |
2 * Gaim's oscar protocol plugin | |
3 * This file is the legal property of its developers. | |
4 * Please see the AUTHORS file distributed alongside this file. | |
5 * | |
6 * This library is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 2 of the License, or (at your option) any later version. | |
10 * | |
11 * This library is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with this library; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 */ | |
20 | |
2086 | 21 /* |
22 * This file contains the management routines for the receive | |
23 * (incoming packet) queue. The actual packet handlers are in | |
8880 | 24 * rxhandlers.c. |
2086 | 25 */ |
26 | |
13234 | 27 #include "oscar.h" |
2086 | 28 |
29 #ifndef _WIN32 | |
30 #include <sys/socket.h> | |
31 #endif | |
32 | |
33 /* | |
34 * | |
35 */ | |
36 faim_internal int aim_recv(int fd, void *buf, size_t count) | |
37 { | |
10267 | 38 int left, cur; |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
39 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
40 for (cur = 0, left = count; left; ) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
41 int ret; |
10267 | 42 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
43 ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); |
2808
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
44 |
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
45 /* Of course EOF is an error, only morons disagree with that. */ |
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
46 if (ret <= 0) |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
47 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
48 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
49 cur += ret; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
50 left -= ret; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
51 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
52 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
53 return cur; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
54 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
55 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
56 /* |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
57 * Read into a byte stream. Will not read more than count, but may read |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
58 * less if there is not enough room in the stream buffer. |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
59 */ |
13239 | 60 faim_internal int aim_bstream_recv(ByteStream *bs, int fd, size_t count) |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
61 { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
62 int red = 0; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
63 |
12427
c5c0f714d8bc
[gaim-migrate @ 14734]
Richard Laager <rlaager@wiktel.com>
parents:
11253
diff
changeset
|
64 if (!bs || (fd < 0)) |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
65 return -1; |
10267 | 66 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
67 if (count > (bs->len - bs->offset)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
68 count = bs->len - bs->offset; /* truncate to remaining space */ |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
69 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
70 if (count) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
71 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
72 red = aim_recv(fd, bs->data + bs->offset, count); |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
73 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
74 if (red <= 0) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
75 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
76 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
77 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
78 bs->offset += red; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
79 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
80 return red; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
81 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
82 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
83 /** |
13239 | 84 * Free an FlapFrame |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
85 * |
7806 | 86 * @param frame The frame to free. |
87 * @return -1 on error; 0 on success. | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
88 */ |
13239 | 89 faim_internal void aim_frame_destroy(FlapFrame *frame) |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
90 { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
91 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
92 free(frame->data.data); /* XXX aim_bstream_free */ |
3952 | 93 free(frame); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
94 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
95 return; |
3952 | 96 } |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
97 |
2086 | 98 /* |
13231 | 99 * Read a FLAP header from conn into fr, and return the number of |
7806 | 100 * bytes in the payload. |
101 * | |
102 * @return -1 on error, otherwise return the length of the payload. | |
2086 | 103 */ |
13239 | 104 static int aim_get_command_flap(OscarSession *sess, OscarConnection *conn, FlapFrame *fr) |
2086 | 105 { |
13234 | 106 guint8 hdr_raw[6]; |
13239 | 107 ByteStream hdr; |
10267 | 108 |
7806 | 109 fr->hdrtype = AIM_FRAMETYPE_FLAP; |
2086 | 110 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
111 /* |
7806 | 112 * Read FLAP header. Six bytes total. |
113 * | |
114 * Byte # | Description | |
115 * -------|------------- | |
116 * 0x00 | Always 0x2a | |
117 * 0x01 | Channel number, usually "2." "1" is used during login, | |
118 * | 4 is used during logoff. | |
119 * 0x02 | Sequence number, 2 bytes. | |
120 * 0x04 | Number of data bytes that follow, 2 bytes. | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
121 */ |
7806 | 122 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); |
123 if (aim_bstream_recv(&hdr, conn->fd, 6) < 6) { | |
13254 | 124 aim_conn_close(sess, conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
125 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
126 } |
2086 | 127 |
7806 | 128 aim_bstream_rewind(&hdr); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
129 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
130 /* |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
131 * This shouldn't happen unless the socket breaks, the server breaks, |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
132 * or we break. We must handle it just in case. |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
133 */ |
7806 | 134 if (aimbs_get8(&hdr) != 0x2a) { |
11253 | 135 gaim_debug_misc("oscar", "Invalid FLAP frame received on FLAP connection!"); |
13254 | 136 aim_conn_close(sess, conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
137 return -1; |
10267 | 138 } |
2086 | 139 |
7806 | 140 fr->hdr.flap.channel = aimbs_get8(&hdr); |
141 fr->hdr.flap.seqnum = aimbs_get16(&hdr); | |
3952 | 142 |
7806 | 143 return aimbs_get16(&hdr); |
3952 | 144 } |
145 | |
146 /* | |
13254 | 147 * Read a rendezvous header from conn into fr, and return the number of |
7806 | 148 * bytes in the payload. |
149 * | |
150 * @return -1 on error, otherwise return the length of the payload. | |
3952 | 151 */ |
13239 | 152 static int aim_get_command_rendezvous(OscarSession *sess, OscarConnection *conn, FlapFrame *fr) |
3952 | 153 { |
13234 | 154 guint8 hdr_raw[8]; |
13239 | 155 ByteStream hdr; |
7806 | 156 |
157 fr->hdrtype = AIM_FRAMETYPE_OFT; | |
3952 | 158 |
7806 | 159 /* |
160 * Read rendezvous header | |
161 */ | |
162 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); | |
163 if (aim_bstream_recv(&hdr, conn->fd, 8) < 8) { | |
13254 | 164 aim_conn_close(sess, conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
165 return -1; |
3952 | 166 } |
167 | |
7806 | 168 aim_bstream_rewind(&hdr); |
3952 | 169 |
7806 | 170 aimbs_getrawbuf(&hdr, fr->hdr.rend.magic, 4); |
171 fr->hdr.rend.hdrlen = aimbs_get16(&hdr); | |
172 fr->hdr.rend.type = aimbs_get16(&hdr); | |
3952 | 173 |
7806 | 174 return fr->hdr.rend.hdrlen - 8; |
3952 | 175 } |
2086 | 176 |
3952 | 177 /* |
13231 | 178 * Grab a single command sequence off the socket, and enqueue it in |
179 * the incoming event queue in a separate struct. | |
7806 | 180 * |
181 * @return 0 on success, otherwise return the error number. | |
13231 | 182 * "Success" doesn't mean we have new data, it just means |
183 * the connection isn't dead. | |
3952 | 184 */ |
13239 | 185 faim_export int aim_get_command(OscarSession *sess, OscarConnection *conn) |
3952 | 186 { |
13239 | 187 FlapFrame *fr; |
7806 | 188 int payloadlen; |
3952 | 189 |
190 if (!sess || !conn) | |
4617 | 191 return -EINVAL; |
3952 | 192 |
193 if (conn->fd == -1) | |
194 return -1; /* it's an aim_conn_close()'d connection */ | |
195 | |
11214 | 196 /* If stdin is closed, then zero becomes a valid fd |
197 if (conn->fd < 3) | |
3952 | 198 return -1; |
11214 | 199 */ |
3952 | 200 |
201 if (conn->status & AIM_CONN_STATUS_INPROGRESS) | |
202 return aim_conn_completeconnect(sess, conn); | |
203 | |
13239 | 204 if (!(fr = (FlapFrame *)calloc(sizeof(FlapFrame), 1))) |
4617 | 205 return -ENOMEM; |
3952 | 206 |
207 /* | |
13254 | 208 * Rendezvous (client to client) connections do not speak FLAP, so this |
3952 | 209 * function will break on them. |
210 */ | |
7806 | 211 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) |
212 payloadlen = aim_get_command_rendezvous(sess, conn, fr); | |
213 else if (conn->type == AIM_CONN_TYPE_LISTENER) { | |
11253 | 214 gaim_debug_misc("oscar", "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); |
7806 | 215 free(fr); |
216 return -1; | |
217 } else | |
218 payloadlen = aim_get_command_flap(sess, conn, fr); | |
5927 | 219 |
7806 | 220 if (payloadlen < 0) { |
221 free(fr); | |
222 return -1; | |
223 } | |
224 | |
225 if (payloadlen > 0) { | |
13234 | 226 guint8 *payload = NULL; |
7806 | 227 |
13234 | 228 if (!(payload = (guint8 *) malloc(payloadlen))) { |
7806 | 229 aim_frame_destroy(fr); |
5927 | 230 return -1; |
231 } | |
232 | |
7806 | 233 aim_bstream_init(&fr->data, payload, payloadlen); |
2086 | 234 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
235 /* read the payload */ |
7806 | 236 if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { |
237 aim_frame_destroy(fr); /* free's payload */ | |
13254 | 238 aim_conn_close(sess, conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
239 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
240 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
241 } else |
7806 | 242 aim_bstream_init(&fr->data, NULL, 0); |
2086 | 243 |
7806 | 244 aim_bstream_rewind(&fr->data); |
2086 | 245 |
7806 | 246 fr->conn = conn; |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
247 |
7806 | 248 /* Enqueue this puppy */ |
249 fr->next = NULL; /* this will always be at the bottom */ | |
250 if (sess->queue_incoming == NULL) | |
251 sess->queue_incoming = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
252 else { |
13239 | 253 FlapFrame *cur; |
7806 | 254 for (cur = sess->queue_incoming; cur->next; cur = cur->next); |
255 cur->next = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
256 } |
2086 | 257 |
7806 | 258 fr->conn->lastactivity = time(NULL); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
259 |
10267 | 260 return 0; |
2086 | 261 } |
262 | |
263 /* | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
7806
diff
changeset
|
264 * Purge receive queue of all handled commands (->handled==1). |
2086 | 265 * |
266 */ | |
13239 | 267 faim_export void aim_purge_rxqueue(OscarSession *sess) |
2086 | 268 { |
13239 | 269 FlapFrame *cur, **prev; |
2086 | 270 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
271 for (prev = &sess->queue_incoming; (cur = *prev); ) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
272 if (cur->handled) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
273 *prev = cur->next; |
7806 | 274 aim_frame_destroy(cur); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
275 } else |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
276 prev = &cur->next; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
277 } |
2086 | 278 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
279 return; |
2086 | 280 } |
281 | |
282 /* | |
283 * Since aim_get_command will aim_conn_kill dead connections, we need | |
284 * to clean up the rxqueue of unprocessed connections on that socket. | |
285 * | |
286 * XXX: this is something that was handled better in the old connection | |
287 * handling method, but eh. | |
288 */ | |
13239 | 289 faim_internal void aim_rxqueue_cleanbyconn(OscarSession *sess, OscarConnection *conn) |
2086 | 290 { |
13239 | 291 FlapFrame *currx; |
2086 | 292 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
293 for (currx = sess->queue_incoming; currx; currx = currx->next) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
294 if ((!currx->handled) && (currx->conn == conn)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
295 currx->handled = 1; |
10267 | 296 } |
7806 | 297 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
298 return; |
2086 | 299 } |