Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2012 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdarg.h>
23 : #include <stdio.h>
24 : #include <assert.h>
25 :
26 : #if HAVE_ERRNO_H
27 : #include <errno.h>
28 : #endif /* HAVE_ERRNO_H */
29 :
30 : #if HAVE_STDLIB_H
31 : #include <stdlib.h>
32 : #endif /* HAVE_STDLIB_H */
33 :
34 : #if HAVE_STRING_H
35 : #include <string.h>
36 : #endif /* HAVE_STRING_H */
37 :
38 : #if HAVE_UNISTD_H
39 : #include <unistd.h>
40 : #endif /* HAVE_UNISTD_H */
41 :
42 : #include <freetds/tds.h>
43 : #include <freetds/bytes.h>
44 : #include <freetds/iconv.h>
45 : #include <freetds/replacements.h>
46 : #include <freetds/checks.h>
47 : #include <freetds/tls.h>
48 :
49 : #undef MAX
50 : #define MAX(a,b) (((a) > (b)) ? (a) : (b))
51 :
52 : /**
53 : * \addtogroup network
54 : * @{
55 : */
56 :
57 : #if ENABLE_ODBC_MARS
58 : static TDSRET tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd);
59 : static int tds_packet_write(TDSCONNECTION *conn);
60 : #endif
61 :
62 : /* get packet from the cache */
63 : static TDSPACKET *
64 76063 : tds_get_packet(TDSCONNECTION *conn, unsigned len)
65 : {
66 76063 : TDSPACKET *packet, *to_free = NULL;
67 :
68 76063 : tds_mutex_lock(&conn->list_mtx);
69 154995 : while ((packet = conn->packet_cache) != NULL) {
70 74066 : --conn->num_cached_packets;
71 74066 : conn->packet_cache = packet->next;
72 :
73 : /* return it */
74 74066 : if (packet->capacity >= len) {
75 71197 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
76 71197 : packet->next = NULL;
77 71189 : tds_packet_zero_data_start(packet);
78 71197 : packet->data_len = 0;
79 71197 : packet->sid = 0;
80 71197 : break;
81 : }
82 :
83 : /* discard packet if too small */
84 2869 : packet->next = to_free;
85 2869 : to_free = packet;
86 : }
87 76063 : tds_mutex_unlock(&conn->list_mtx);
88 :
89 76063 : if (to_free)
90 2763 : tds_free_packets(to_free);
91 :
92 76063 : if (!packet)
93 4866 : packet = tds_alloc_packet(NULL, len);
94 :
95 76063 : return packet;
96 : }
97 :
98 : /* append packets in cached list. must have the lock! */
99 : static void
100 76061 : tds_packet_cache_add(TDSCONNECTION *conn, TDSPACKET *packet)
101 : {
102 : TDSPACKET *last;
103 76061 : unsigned count = 1;
104 :
105 76061 : assert(conn && packet);
106 76061 : tds_mutex_check_owned(&conn->list_mtx);
107 :
108 76061 : if (conn->num_cached_packets >= 8) {
109 0 : tds_free_packets(packet);
110 0 : return;
111 : }
112 :
113 71 : for (last = packet; last->next; last = last->next)
114 71 : ++count;
115 :
116 76061 : last->next = conn->packet_cache;
117 76061 : conn->packet_cache = packet;
118 76061 : conn->num_cached_packets += count;
119 :
120 : #if ENABLE_EXTRA_CHECKS
121 76061 : count = 0;
122 154037 : for (packet = conn->packet_cache; packet; packet = packet->next)
123 77976 : ++count;
124 76061 : assert(count == conn->num_cached_packets);
125 : #endif
126 : }
127 :
128 : #if ENABLE_ODBC_MARS
129 : /* read partial packet */
130 : static bool
131 93566 : tds_packet_read(TDSCONNECTION *conn, TDSSOCKET *tds)
132 : {
133 93566 : TDSPACKET *packet = conn->recv_packet;
134 : int len;
135 :
136 : /* allocate some space to read data */
137 93566 : if (!packet) {
138 38632 : conn->recv_packet = packet = tds_get_packet(conn, MAX(conn->env.block_size + sizeof(TDS72_SMP_HEADER), 512));
139 38632 : if (!packet) goto Memory_Error;
140 38632 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
141 38632 : conn->recv_pos = 0;
142 38632 : packet->data_len = 8;
143 : }
144 :
145 93566 : assert(packet->data_start == 0);
146 :
147 93566 : assert(conn->recv_pos < packet->data_len && packet->data_len <= packet->capacity);
148 :
149 93566 : len = tds_connection_read(tds, packet->buf + conn->recv_pos, packet->data_len - conn->recv_pos);
150 93566 : if (len < 0)
151 : goto Severe_Error;
152 93557 : conn->recv_pos += len;
153 93557 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
154 :
155 : /* handle SMP */
156 93557 : if (conn->recv_pos > 0 && packet->buf[0] == TDS72_SMP) {
157 : TDS72_SMP_HEADER mars_header;
158 : uint16_t sid;
159 : TDSSOCKET *tds;
160 : TDS_UINT size;
161 :
162 : /* make sure we read the header */
163 14573 : if (conn->recv_pos < sizeof(mars_header)) {
164 4889 : packet->data_len = sizeof(mars_header);
165 19462 : return false;
166 : }
167 :
168 9684 : memcpy(&mars_header, packet->buf, sizeof(mars_header));
169 9684 : tdsdump_dump_buf(TDS_DBG_HEADER, "Received MARS header", &mars_header, sizeof(mars_header));
170 9684 : sid = TDS_GET_A2LE(&mars_header.sid);
171 :
172 : /* FIXME this is done even by caller !! */
173 9684 : tds = NULL;
174 9684 : tds_mutex_lock(&conn->list_mtx);
175 9684 : if (sid < conn->num_sessions) {
176 9684 : tds = conn->sessions[sid];
177 9684 : packet->sid = sid;
178 : }
179 9684 : tds_mutex_unlock(&conn->list_mtx);
180 :
181 9684 : if (tds == BUSY_SOCKET) {
182 2 : if (mars_header.type != TDS_SMP_FIN) {
183 0 : tdsdump_log(TDS_DBG_ERROR, "Received MARS with no session (%u)\n", sid);
184 0 : goto Severe_Error;
185 : }
186 :
187 : /* check if was just a "zombie" socket */
188 2 : tds_mutex_lock(&conn->list_mtx);
189 2 : conn->sessions[sid] = NULL;
190 2 : tds_mutex_unlock(&conn->list_mtx);
191 :
192 : /* reset packet to initial state to reuse it */
193 2 : packet->data_len = 8;
194 2 : conn->recv_pos = 0;
195 2 : return false;
196 : }
197 :
198 9682 : if (!tds) {
199 : /* server sent a unknown packet, close connection */
200 : goto Severe_Error;
201 : }
202 :
203 9682 : tds->send_wnd = TDS_GET_A4LE(&mars_header.wnd);
204 9682 : size = TDS_GET_A4LE(&mars_header.size);
205 9682 : if (mars_header.type == TDS_SMP_ACK) {
206 92 : if (size != sizeof(mars_header))
207 : goto Severe_Error;
208 9590 : } else if (mars_header.type == TDS_SMP_DATA) {
209 9590 : if (size < 0x18 || size > 0xffffu + sizeof(mars_header))
210 : goto Severe_Error;
211 : /* avoid recursive SMP */
212 9590 : if (conn->recv_pos > 16 && packet->buf[16] == TDS72_SMP)
213 : goto Severe_Error;
214 : /* TODO is possible to put 2 TDS packet inside a single DATA ?? */
215 9590 : if (conn->recv_pos >= 20 && TDS_GET_A2BE(&packet->buf[18]) != size - 16)
216 : goto Severe_Error;
217 9590 : tds->recv_seq = TDS_GET_A4LE(&mars_header.seq);
218 : /*
219 : * do not sent ACK here because this would lead to memory waste
220 : * if session is not able to handle all that packets
221 : */
222 0 : } else if (mars_header.type == TDS_SMP_FIN) {
223 0 : if (size != sizeof(mars_header))
224 : goto Severe_Error;
225 : /* this socket shold now not start another session */
226 : // tds_set_state(tds, TDS_DEAD);
227 : } else
228 : goto Severe_Error;
229 :
230 9682 : if (mars_header.type != TDS_SMP_DATA)
231 92 : return conn->recv_pos >= size;
232 9590 : if (packet->data_len < size) {
233 4795 : packet = tds_realloc_packet(packet, size);
234 4795 : if (!packet)
235 : goto Memory_Error;
236 4795 : conn->recv_packet = packet;
237 : }
238 9590 : packet->data_len = size;
239 9590 : if (conn->recv_pos >= size) {
240 4795 : packet->data_start = sizeof(TDS72_SMP_HEADER);
241 4795 : packet->data_len -= sizeof(TDS72_SMP_HEADER);
242 4795 : return true;
243 : }
244 : return false;
245 : }
246 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
247 :
248 : /* normal packet */
249 78984 : if (conn->recv_pos >= 8) {
250 73034 : len = TDS_GET_A2BE(&packet->buf[2]);
251 73034 : if (len < 8)
252 : goto Severe_Error;
253 73034 : if (packet->data_len < len) {
254 33735 : packet = tds_realloc_packet(packet, len);
255 33735 : if (!packet) goto Memory_Error;
256 33735 : conn->recv_packet = packet;
257 : }
258 73034 : packet->data_len = len;
259 73034 : return conn->recv_pos >= len;
260 : }
261 : return false;
262 :
263 9 : Memory_Error:
264 9 : Severe_Error:
265 9 : tds_connection_close(conn);
266 9 : tds_free_packets(packet);
267 9 : conn->recv_packet = NULL;
268 9 : return false;
269 : }
270 :
271 : static TDSPACKET*
272 98 : tds_build_packet(TDSSOCKET *tds, unsigned char *buf, unsigned len)
273 : {
274 : unsigned start;
275 : TDS72_SMP_HEADER mars[1], *p;
276 : TDSPACKET *packet;
277 :
278 98 : p = mars;
279 98 : if (buf[0] != TDS72_SMP && tds->conn->mars) {
280 20 : p->signature = TDS72_SMP;
281 20 : p->type = TDS_SMP_DATA;
282 20 : TDS_PUT_A2LE(&p->sid, tds->sid);
283 20 : TDS_PUT_A4LE(&p->size, len+16);
284 20 : ++tds->send_seq;
285 20 : TDS_PUT_A4LE(&p->seq, tds->send_seq);
286 : /* this is the acknowledge we give to server to stop sending !!! */
287 20 : tds->recv_wnd = tds->recv_seq + 4;
288 20 : TDS_PUT_A4LE(&p->wnd, tds->recv_wnd);
289 20 : p++;
290 : }
291 :
292 98 : start = (char*) p - (char *) mars;
293 98 : packet = tds_get_packet(tds->conn, len + start);
294 98 : if (TDS_LIKELY(packet)) {
295 98 : packet->sid = tds->sid;
296 98 : memcpy(packet->buf, mars, start);
297 98 : memcpy(packet->buf + start, buf, len);
298 98 : packet->data_len = len + start;
299 : }
300 98 : return packet;
301 : }
302 :
303 : static void
304 : tds_append_packet(TDSPACKET **p_packet, TDSPACKET *packet)
305 : {
306 76114 : while (*p_packet)
307 174 : p_packet = &((*p_packet)->next);
308 75940 : *p_packet = packet;
309 : }
310 :
311 : int
312 98 : tds_append_cancel(TDSSOCKET *tds)
313 : {
314 : unsigned char buf[8];
315 : TDSPACKET *packet;
316 :
317 98 : buf[0] = TDS_CANCEL;
318 98 : buf[1] = 1;
319 98 : TDS_PUT_A2BE(buf+2, 8);
320 98 : TDS_PUT_A4(buf+4, 0);
321 98 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
322 67 : buf[6] = 0x01;
323 :
324 98 : packet = tds_build_packet(tds, buf, 8);
325 98 : if (!packet)
326 : return TDS_FAIL;
327 :
328 98 : tds_mutex_lock(&tds->conn->list_mtx);
329 196 : tds_append_packet(&tds->conn->send_packets, packet);
330 98 : tds_mutex_unlock(&tds->conn->list_mtx);
331 :
332 98 : return TDS_SUCCESS;
333 : }
334 :
335 :
336 : static void
337 76058 : tds_connection_network(TDSCONNECTION *conn, TDSSOCKET *tds, int send)
338 : {
339 76058 : assert(!conn->in_net_tds);
340 76058 : conn->in_net_tds = tds;
341 76058 : tds_mutex_unlock(&conn->list_mtx);
342 :
343 : for (;;) {
344 : /* wait packets or update */
345 136297 : int rc = tds_select(tds, conn->send_packets ? TDSSELREAD|TDSSELWRITE : TDSSELREAD, tds->query_timeout);
346 :
347 136297 : if (rc < 0) {
348 : /* FIXME better error report */
349 43 : tds_connection_close(conn);
350 43 : break;
351 : }
352 :
353 : /* change notify */
354 : /* TODO async */
355 :
356 136254 : if (!rc) { /* timeout */
357 124 : tdsdump_log(TDS_DBG_INFO1, "timeout\n");
358 124 : switch (rc = tdserror(tds_get_ctx(tds), tds, TDSETIME, sock_errno)) {
359 104 : case TDS_INT_CONTINUE:
360 104 : continue;
361 20 : default:
362 : case TDS_INT_CANCEL:
363 20 : tds_close_socket(tds);
364 : }
365 20 : break;
366 : }
367 :
368 : /*
369 : * we must write first to catch write errors as
370 : * write errors, not as read
371 : */
372 : /* something to send */
373 136130 : if (conn->send_packets && (rc & POLLOUT) != 0) {
374 : TDSSOCKET *s;
375 :
376 42468 : int sid = tds_packet_write(conn);
377 42468 : if (sid < 0)
378 5091 : continue;
379 :
380 37377 : if (sid == tds->sid)
381 : break; /* return to caller */
382 :
383 5 : tds_mutex_lock(&conn->list_mtx);
384 5 : if (sid < conn->num_sessions) {
385 5 : s = conn->sessions[sid];
386 5 : if (TDSSOCKET_VALID(s))
387 0 : tds_cond_signal(&s->packet_cond);
388 : }
389 5 : tds_mutex_unlock(&conn->list_mtx);
390 : /* avoid using a possible closed connection */
391 5 : continue;
392 : }
393 :
394 : /* received */
395 93662 : if (rc & (POLLIN|POLLHUP)) {
396 : TDSPACKET *packet;
397 : TDSSOCKET *s;
398 :
399 : /* try to read a packet */
400 93566 : if (!tds_packet_read(conn, tds))
401 54943 : continue; /* packet not complete */
402 38623 : packet = conn->recv_packet;
403 38623 : conn->recv_packet = NULL;
404 38623 : conn->recv_pos = 0;
405 :
406 38623 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", packet->buf, packet->data_start + packet->data_len);
407 :
408 38623 : tds_mutex_lock(&conn->list_mtx);
409 38623 : if (packet->sid < conn->num_sessions) {
410 38623 : s = conn->sessions[packet->sid];
411 38623 : if (TDSSOCKET_VALID(s)) {
412 : /* append to correct session */
413 38623 : if (packet->buf[0] == TDS72_SMP && packet->buf[1] != TDS_SMP_DATA)
414 92 : tds_packet_cache_add(conn, packet);
415 : else
416 38531 : tds_append_packet(&conn->packets, packet);
417 38623 : packet = NULL;
418 : /* notify */
419 38623 : tds_cond_signal(&s->packet_cond);
420 : }
421 : }
422 38623 : tds_mutex_unlock(&conn->list_mtx);
423 38623 : tds_free_packets(packet);
424 : /* if we are receiving return the packet */
425 38623 : if (!send) break;
426 : }
427 : }
428 :
429 76058 : tds_mutex_lock(&conn->list_mtx);
430 76058 : conn->in_net_tds = NULL;
431 76058 : }
432 :
433 : static TDSRET
434 37032 : tds_connection_put_packet(TDSSOCKET *tds, TDSPACKET *packet)
435 : {
436 37032 : TDSCONNECTION *conn = tds->conn;
437 :
438 37032 : CHECK_TDS_EXTRA(tds);
439 :
440 37032 : packet->sid = tds->sid;
441 :
442 37032 : tds_mutex_lock(&conn->list_mtx);
443 37032 : tds->sending_packet = packet;
444 74299 : while (tds->sending_packet) {
445 : int wait_res;
446 :
447 37267 : if (IS_TDSDEAD(tds)) {
448 35 : tdsdump_log(TDS_DBG_NETWORK, "Write attempt when state is TDS_DEAD");
449 : break;
450 : }
451 :
452 : /* limit packet sending looking at sequence/window */
453 37232 : if (packet && (int32_t) (tds->send_seq - tds->send_wnd) < 0) {
454 : /* prepare MARS header if needed */
455 37029 : if (tds->conn->mars) {
456 : TDS72_SMP_HEADER *hdr;
457 :
458 : /* fill SMP data */
459 4700 : hdr = (TDS72_SMP_HEADER *) packet->buf;
460 4700 : hdr->signature = TDS72_SMP;
461 4700 : hdr->type = TDS_SMP_DATA;
462 4700 : TDS_PUT_A2LE(&hdr->sid, packet->sid);
463 4700 : TDS_PUT_A4LE(&hdr->size, packet->data_start + packet->data_len);
464 4700 : ++tds->send_seq;
465 4700 : TDS_PUT_A4LE(&hdr->seq, tds->send_seq);
466 : /* this is the acknowledge we give to server to stop sending */
467 4700 : tds->recv_wnd = tds->recv_seq + 4;
468 4700 : TDS_PUT_A4LE(&hdr->wnd, tds->recv_wnd);
469 : }
470 :
471 : /* append packet */
472 74058 : tds_append_packet(&conn->send_packets, packet);
473 37029 : packet = NULL;
474 : }
475 :
476 : /* network ok ? process network */
477 37232 : if (!conn->in_net_tds) {
478 37232 : tds_connection_network(conn, tds, packet ? 0 : 1);
479 37232 : if (tds->sending_packet)
480 235 : continue;
481 : /* here we are sure we sent the packet */
482 : break;
483 : }
484 :
485 : /* signal thread processing network to handle our packet */
486 : /* TODO check result */
487 0 : tds_wakeup_send(&conn->wakeup, 0);
488 :
489 : /* wait local condition */
490 0 : wait_res = tds_cond_timedwait(&tds->packet_cond, &conn->list_mtx, tds->query_timeout);
491 0 : if (wait_res != ETIMEDOUT)
492 0 : continue;
493 :
494 0 : tds_mutex_unlock(&conn->list_mtx);
495 0 : if (tdserror(tds_get_ctx(tds), tds, TDSETIME, ETIMEDOUT) != TDS_INT_CONTINUE) {
496 0 : tds->sending_packet = NULL;
497 0 : tds_close_socket(tds);
498 0 : tds_free_packets(packet);
499 0 : return TDS_FAIL;
500 : }
501 0 : tds_mutex_lock(&conn->list_mtx);
502 : }
503 37032 : tds->sending_packet = NULL;
504 37032 : tds_mutex_unlock(&conn->list_mtx);
505 37032 : if (TDS_UNLIKELY(packet)) {
506 3 : tds_free_packets(packet);
507 3 : return TDS_FAIL;
508 : }
509 37029 : if (IS_TDSDEAD(tds))
510 : return TDS_FAIL;
511 36997 : return TDS_SUCCESS;
512 : }
513 : #endif /* ENABLE_ODBC_MARS */
514 :
515 : /**
516 : * Read in one 'packet' from the server. This is a wrapped outer packet of
517 : * the protocol (they bundle result packets into chunks and wrap them at
518 : * what appears to be 512 bytes regardless of how that breaks internal packet
519 : * up. (tetherow\@nol.org)
520 : * @return bytes read or -1 on failure
521 : */
522 : int
523 77032 : tds_read_packet(TDSSOCKET * tds)
524 : {
525 : #if ENABLE_ODBC_MARS
526 38562 : TDSCONNECTION *conn = tds->conn;
527 :
528 38562 : tds_mutex_lock(&conn->list_mtx);
529 :
530 : for (;;) {
531 : int wait_res;
532 : TDSPACKET **p_packet;
533 :
534 77388 : if (IS_TDSDEAD(tds)) {
535 31 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD\n");
536 : break;
537 : }
538 :
539 : /* if there is a packet for me return it */
540 77420 : for (p_packet = &conn->packets; *p_packet; p_packet = &(*p_packet)->next)
541 38594 : if ((*p_packet)->sid == tds->sid)
542 : break;
543 :
544 77357 : if (*p_packet) {
545 : /* remove our packet from list */
546 38531 : TDSPACKET *packet = *p_packet;
547 38531 : *p_packet = packet->next;
548 38531 : tds_packet_cache_add(conn, tds->recv_packet);
549 38531 : tds_mutex_unlock(&conn->list_mtx);
550 :
551 38531 : packet->next = NULL;
552 38531 : tds->recv_packet = packet;
553 :
554 38531 : tds->in_buf = packet->buf + packet->data_start;
555 38531 : tds->in_len = packet->data_len;
556 38531 : tds->in_pos = 8;
557 38531 : tds->in_flag = tds->in_buf[0];
558 :
559 : /* send acknowledge if needed */
560 38531 : if ((int32_t) (tds->recv_seq + 2 - tds->recv_wnd) >= 0)
561 169 : tds_update_recv_wnd(tds, tds->recv_seq + 4);
562 :
563 38531 : return tds->in_len;
564 : }
565 :
566 : /* network ok ? process network */
567 38826 : if (!conn->in_net_tds) {
568 38826 : tds_connection_network(conn, tds, 0);
569 38826 : continue;
570 : }
571 :
572 : /* wait local condition */
573 0 : wait_res = tds_cond_timedwait(&tds->packet_cond, &conn->list_mtx, tds->query_timeout);
574 0 : if (wait_res != ETIMEDOUT)
575 0 : continue;
576 :
577 0 : tds_mutex_unlock(&conn->list_mtx);
578 0 : if (tdserror(tds_get_ctx(tds), tds, TDSETIME, ETIMEDOUT) != TDS_INT_CONTINUE) {
579 0 : tds_close_socket(tds);
580 0 : return -1;
581 : }
582 0 : tds_mutex_lock(&conn->list_mtx);
583 : }
584 :
585 31 : tds_mutex_unlock(&conn->list_mtx);
586 31 : return -1;
587 : #else /* !ENABLE_ODBC_MARS */
588 38470 : unsigned char *pkt = tds->in_buf, *p, *end;
589 :
590 38470 : if (IS_TDSDEAD(tds)) {
591 0 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD");
592 : return -1;
593 : }
594 :
595 38470 : tds->in_len = 0;
596 38470 : tds->in_pos = 0;
597 159359 : for (p = pkt, end = p+8; p < end;) {
598 82450 : int len = tds_connection_read(tds, p, end - p);
599 82450 : if (len <= 0) {
600 31 : tds_close_socket(tds);
601 31 : return -1;
602 : }
603 :
604 82419 : p += len;
605 82419 : if (p - pkt >= 4) {
606 82419 : unsigned pktlen = TDS_GET_A2BE(pkt+2);
607 : /* packet must at least contains header */
608 82419 : if (TDS_UNLIKELY(pktlen < 8)) {
609 0 : tds_close_socket(tds);
610 0 : return -1;
611 : }
612 82419 : if (TDS_UNLIKELY(pktlen > tds->recv_packet->capacity)) {
613 928 : TDSPACKET *packet = tds_realloc_packet(tds->recv_packet, pktlen);
614 928 : if (TDS_UNLIKELY(!packet)) {
615 0 : tds_close_socket(tds);
616 0 : return -1;
617 : }
618 928 : tds->recv_packet = packet;
619 928 : pkt = packet->buf;
620 928 : p = pkt + (p-tds->in_buf);
621 928 : tds->in_buf = pkt;
622 : }
623 82419 : end = pkt + pktlen;
624 : }
625 : }
626 :
627 : /* set the received packet type flag */
628 38439 : tds->in_flag = pkt[0];
629 :
630 : /* Set the length and pos (not sure what pos is used for now */
631 38439 : tds->in_len = p - pkt;
632 38439 : tds->in_pos = 8;
633 38439 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", tds->in_buf, tds->in_len);
634 :
635 38439 : return tds->in_len;
636 : #endif /* !ENABLE_ODBC_MARS */
637 : }
638 :
639 : #if ENABLE_ODBC_MARS
640 : static TDSRET
641 169 : tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd)
642 : {
643 : TDS72_SMP_HEADER *mars;
644 : TDSPACKET *packet;
645 :
646 169 : if (!tds->conn->mars)
647 : return TDS_SUCCESS;
648 :
649 169 : packet = tds_get_packet(tds->conn, sizeof(*mars));
650 169 : if (!packet)
651 : return TDS_FAIL; /* TODO check result */
652 :
653 169 : packet->data_len = sizeof(*mars);
654 169 : packet->sid = tds->sid;
655 :
656 169 : mars = (TDS72_SMP_HEADER *) packet->buf;
657 169 : mars->signature = TDS72_SMP;
658 169 : mars->type = TDS_SMP_ACK;
659 169 : TDS_PUT_A2LE(&mars->sid, tds->sid);
660 169 : mars->size = TDS_HOST4LE(16);
661 169 : TDS_PUT_A4LE(&mars->seq, tds->send_seq);
662 169 : tds->recv_wnd = new_recv_wnd;
663 169 : TDS_PUT_A4LE(&mars->wnd, tds->recv_wnd);
664 :
665 169 : tds_mutex_lock(&tds->conn->list_mtx);
666 338 : tds_append_packet(&tds->conn->send_packets, packet);
667 169 : tds_mutex_unlock(&tds->conn->list_mtx);
668 :
669 169 : return TDS_SUCCESS;
670 : }
671 :
672 : static TDSRET
673 113 : tds_append_fin_syn(TDSSOCKET *tds, uint8_t type)
674 : {
675 : TDS72_SMP_HEADER mars;
676 : TDSPACKET *packet;
677 :
678 113 : if (!tds->conn->mars)
679 : return TDS_SUCCESS;
680 :
681 113 : mars.signature = TDS72_SMP;
682 113 : mars.type = type;
683 113 : TDS_PUT_A2LE(&mars.sid, tds->sid);
684 113 : mars.size = TDS_HOST4LE(16);
685 113 : TDS_PUT_A4LE(&mars.seq, tds->send_seq);
686 113 : tds->recv_wnd = tds->recv_seq + 4;
687 113 : TDS_PUT_A4LE(&mars.wnd, tds->recv_wnd);
688 :
689 : /* do not use tds_get_packet as it require no lock ! */
690 113 : packet = tds_alloc_packet(&mars, sizeof(mars));
691 113 : if (!packet)
692 : return TDS_FAIL; /* TODO check result */
693 113 : packet->sid = tds->sid;
694 :
695 : /* we already hold lock so do not lock */
696 226 : tds_append_packet(&tds->conn->send_packets, packet);
697 :
698 113 : if (type == TDS_SMP_FIN) {
699 : /* now is no more an active session */
700 5 : tds->conn->sessions[tds->sid] = BUSY_SOCKET;
701 5 : tds_set_state(tds, TDS_DEAD);
702 : }
703 :
704 : return TDS_SUCCESS;
705 : }
706 :
707 : /**
708 : * Append a SMP FIN packet.
709 : * tds->conn->list_mtx must be locked.
710 : */
711 : TDSRET
712 5 : tds_append_fin(TDSSOCKET *tds)
713 : {
714 5 : return tds_append_fin_syn(tds, TDS_SMP_FIN);
715 : }
716 :
717 : /**
718 : * Append a SMP SYN packet.
719 : * tds->conn->list_mtx must be unlocked.
720 : */
721 : TDSRET
722 108 : tds_append_syn(TDSSOCKET *tds)
723 : {
724 : TDSRET ret;
725 108 : tds_mutex_lock(&tds->conn->list_mtx);
726 108 : ret = tds_append_fin_syn(tds, TDS_SMP_SYN);
727 108 : tds_mutex_unlock(&tds->conn->list_mtx);
728 108 : return ret;
729 : }
730 : #endif /* ENABLE_ODBC_MARS */
731 :
732 :
733 : TDS_COMPILE_CHECK(additional, TDS_ADDITIONAL_SPACE != 0);
734 :
735 : TDSRET
736 73610 : tds_write_packet(TDSSOCKET * tds, unsigned char final)
737 : {
738 : TDSRET res;
739 73610 : unsigned int left = 0;
740 73610 : TDSPACKET *pkt = tds->send_packet, *pkt_next = NULL;
741 :
742 73610 : CHECK_TDS_EXTRA(tds);
743 :
744 : #if !ENABLE_ODBC_MARS
745 36541 : if (tds->frozen)
746 : #endif
747 : {
748 37164 : pkt->next = pkt_next = tds_get_packet(tds->conn, pkt->capacity);
749 37164 : if (!pkt_next)
750 : return TDS_FAIL;
751 :
752 : #if ENABLE_ODBC_MARS
753 37069 : if (tds->conn->mars)
754 4718 : pkt_next->data_start = sizeof(TDS72_SMP_HEADER);
755 : #endif
756 : }
757 :
758 73610 : if (tds->out_pos > tds->out_buf_max) {
759 474 : left = tds->out_pos - tds->out_buf_max;
760 233 : if (pkt_next)
761 250 : memcpy(pkt_next->buf + tds_packet_get_data_start(pkt_next) + 8, tds->out_buf + tds->out_buf_max, left);
762 474 : tds->out_pos = tds->out_buf_max;
763 : }
764 :
765 : /* we must assure server can accept our packet looking at
766 : * send_wnd and waiting for proper send_wnd if send_seq > send_wnd
767 : */
768 73610 : tds->out_buf[0] = tds->out_flag;
769 73610 : tds->out_buf[1] = final;
770 73610 : TDS_PUT_A2BE(tds->out_buf+2, tds->out_pos);
771 73610 : TDS_PUT_A2BE(tds->out_buf+4, tds->conn->client_spid);
772 73610 : TDS_PUT_A2(tds->out_buf+6, 0);
773 73610 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
774 49198 : tds->out_buf[6] = 0x01;
775 :
776 73610 : if (tds->frozen) {
777 270 : pkt->data_len = tds->out_pos;
778 270 : tds_set_current_send_packet(tds, pkt_next);
779 270 : tds->out_pos = left + 8;
780 270 : CHECK_TDS_EXTRA(tds);
781 270 : return TDS_SUCCESS;
782 : }
783 :
784 : #if ENABLE_ODBC_MARS
785 36894 : pkt->data_len = tds->out_pos;
786 36894 : pkt->next = NULL;
787 36894 : tds_set_current_send_packet(tds, pkt_next);
788 36894 : res = tds_connection_put_packet(tds, pkt);
789 : #else /* !ENABLE_ODBC_MARS */
790 36446 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", tds->out_buf, tds->out_pos);
791 :
792 : /* GW added in check for write() returning <0 and SIGPIPE checking */
793 72892 : res = tds_connection_write(tds, tds->out_buf, tds->out_pos, final) <= 0 ?
794 36446 : TDS_FAIL : TDS_SUCCESS;
795 :
796 36446 : memcpy(tds->out_buf + 8, tds->out_buf + tds->out_buf_max, left);
797 : #endif /* !ENABLE_ODBC_MARS */
798 :
799 73340 : tds->out_pos = left + 8;
800 :
801 73340 : if (TDS_UNLIKELY(tds->conn->encrypt_single_packet)) {
802 728 : tds->conn->encrypt_single_packet = 0;
803 728 : tds_ssl_deinit(tds->conn);
804 : }
805 :
806 : return res;
807 : }
808 :
809 : #if !ENABLE_ODBC_MARS
810 : int
811 427 : tds_put_cancel(TDSSOCKET * tds)
812 : {
813 : unsigned char out_buf[8];
814 : int sent;
815 :
816 427 : out_buf[0] = TDS_CANCEL; /* out_flag */
817 427 : out_buf[1] = 1; /* final */
818 427 : out_buf[2] = 0;
819 427 : out_buf[3] = 8;
820 427 : TDS_PUT_A4(out_buf+4, 0);
821 427 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
822 344 : out_buf[6] = 0x01;
823 :
824 427 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", out_buf, 8);
825 :
826 427 : sent = tds_connection_write(tds, out_buf, 8, 1);
827 :
828 427 : if (sent > 0)
829 422 : tds->in_cancel = 2;
830 :
831 : /* GW added in check for write() returning <0 and SIGPIPE checking */
832 427 : return sent <= 0 ? TDS_FAIL : TDS_SUCCESS;
833 : }
834 : #endif /* !ENABLE_ODBC_MARS */
835 :
836 :
837 : #if ENABLE_ODBC_MARS
838 : static int
839 42468 : tds_packet_write(TDSCONNECTION *conn)
840 : {
841 : int sent;
842 : int final;
843 42468 : TDSPACKET *packet = conn->send_packets;
844 :
845 42468 : assert(packet);
846 :
847 42468 : if (conn->send_pos == 0)
848 37409 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", packet->buf, packet->data_start + packet->data_len);
849 :
850 : /* take into account other session packets */
851 42468 : if (packet->next != NULL)
852 : final = 0;
853 : /* take into account other packets for this session */
854 42329 : else if (packet->buf[0] != TDS72_SMP)
855 37446 : final = packet->buf[1] & 1;
856 : else
857 : final = 1;
858 :
859 42468 : sent = tds_connection_write(conn->in_net_tds, packet->buf + conn->send_pos,
860 42468 : packet->data_start + packet->data_len - conn->send_pos, final);
861 :
862 42468 : if (TDS_UNLIKELY(sent < 0)) {
863 : /* TODO tdserror called ?? */
864 32 : tds_connection_close(conn);
865 32 : return -1;
866 : }
867 :
868 : /* update sent data */
869 42436 : conn->send_pos += sent;
870 : /* remove packet if sent all data */
871 42436 : if (conn->send_pos >= packet->data_start + packet->data_len) {
872 37377 : uint16_t sid = packet->sid;
873 : TDSSOCKET *tds;
874 37377 : tds_mutex_lock(&conn->list_mtx);
875 37377 : tds = conn->sessions[sid];
876 37377 : if (TDSSOCKET_VALID(tds) && tds->sending_packet == packet)
877 36997 : tds->sending_packet = NULL;
878 37377 : conn->send_packets = packet->next;
879 37377 : packet->next = NULL;
880 37377 : tds_packet_cache_add(conn, packet);
881 37377 : tds_mutex_unlock(&conn->list_mtx);
882 37377 : conn->send_pos = 0;
883 37377 : return sid;
884 : }
885 :
886 : return -1;
887 : }
888 : #endif /* ENABLE_ODBC_MARS */
889 :
890 : /**
891 : * Stop writing to server and cache every packet not sending them to server.
892 : * This is used to write data without worrying to compute length before.
893 : * If size_len is provided the number of bytes written between ::tds_freeze and
894 : * ::tds_freeze_close will be written as a number of size size_len.
895 : * This call should be followed by a ::tds_freeze_close, ::tds_freeze_close_len or
896 : * a ::tds_freeze_abort. Failing to match ::tds_freeze with a close would possibly
897 : * result in a disconnection from the server.
898 : *
899 : * @param[out] freeze structure to initialize
900 : * @param size_len length of the size to automatically write on close (0, 1, 2, or 4)
901 : */
902 : void
903 57881 : tds_freeze(TDSSOCKET *tds, TDSFREEZE *freeze, unsigned size_len)
904 : {
905 57881 : CHECK_TDS_EXTRA(tds);
906 57881 : tds_extra_assert(size_len <= 4 && size_len != 3);
907 :
908 57881 : if (tds->out_pos > tds->out_buf_max)
909 12 : tds_write_packet(tds, 0x0);
910 :
911 57881 : if (!tds->frozen)
912 37233 : tds->frozen_packets = tds->send_packet;
913 :
914 57881 : ++tds->frozen;
915 57881 : freeze->tds = tds;
916 57881 : freeze->pkt = tds->send_packet;
917 57881 : freeze->pkt_pos = tds->out_pos;
918 57881 : freeze->size_len = size_len;
919 57881 : if (size_len)
920 53519 : tds_put_n(tds, NULL, size_len);
921 :
922 57881 : CHECK_FREEZE_EXTRA(freeze);
923 57881 : }
924 :
925 : /**
926 : * Compute how many bytes has been written from freeze
927 : *
928 : * @return bytes written since ::tds_freeze call
929 : */
930 : size_t
931 50767 : tds_freeze_written(TDSFREEZE *freeze)
932 : {
933 50767 : TDSSOCKET *tds = freeze->tds;
934 50767 : TDSPACKET *pkt = freeze->pkt;
935 : size_t size;
936 :
937 50767 : CHECK_FREEZE_EXTRA(freeze);
938 :
939 : /* last packet needs special handling */
940 50767 : size = tds->out_pos;
941 :
942 : /* packets before last */
943 51077 : for (; pkt->next != NULL; pkt = pkt->next)
944 310 : size += pkt->data_len - 8;
945 :
946 50767 : return size - freeze->pkt_pos;
947 : }
948 :
949 : /**
950 : * Discard all data written after the freeze
951 : *
952 : * After this call freeze should not be used.
953 : *
954 : * @param[in] freeze structure to work on
955 : */
956 : TDSRET
957 24 : tds_freeze_abort(TDSFREEZE *freeze)
958 : {
959 24 : TDSSOCKET *tds = freeze->tds;
960 24 : TDSPACKET *pkt = freeze->pkt;
961 :
962 24 : CHECK_FREEZE_EXTRA(freeze);
963 :
964 24 : if (pkt->next) {
965 12 : tds_mutex_lock(&tds->conn->list_mtx);
966 12 : tds_packet_cache_add(tds->conn, pkt->next);
967 12 : tds_mutex_unlock(&tds->conn->list_mtx);
968 12 : pkt->next = NULL;
969 :
970 : tds_set_current_send_packet(tds, pkt);
971 : }
972 24 : tds->out_pos = freeze->pkt_pos;
973 24 : pkt->data_len = 8;
974 :
975 24 : --tds->frozen;
976 24 : if (!tds->frozen)
977 24 : tds->frozen_packets = NULL;
978 24 : freeze->tds = NULL;
979 24 : return TDS_SUCCESS;
980 : }
981 :
982 : /**
983 : * Stop keeping data for this specific freeze.
984 : *
985 : * If size_len was used for ::tds_freeze this function write the written bytes
986 : * at position when ::tds_freeze was called.
987 : * After this call freeze should not be used.
988 : *
989 : * @param[in] freeze structure to work on
990 : */
991 : TDSRET
992 22100 : tds_freeze_close(TDSFREEZE *freeze)
993 : {
994 22100 : return tds_freeze_close_len(freeze, freeze->size_len ? tds_freeze_written(freeze) - freeze->size_len : 0);
995 : }
996 :
997 : /**
998 : * Stop keeping data for this specific freeze.
999 : *
1000 : * If size_len was used for ::tds_freeze this function write the written bytes
1001 : * at position when ::tds_freeze was called.
1002 : * After this call freeze should not be used.
1003 : * Similar to ::tds_freeze_close but count is written in unit, not bytes.
1004 : *
1005 : * @param[in] freeze structure to work on
1006 : */
1007 : TDSRET
1008 12914 : tds_freeze_close_string(TDSFREEZE *freeze)
1009 : {
1010 12914 : size_t written = tds_freeze_written(freeze) - freeze->size_len;
1011 12914 : if (IS_TDS7_PLUS(freeze->tds->conn))
1012 12914 : written /= 2;
1013 12914 : return tds_freeze_close_len(freeze, written);
1014 : }
1015 :
1016 : static void
1017 : tds_freeze_update_size(const TDSFREEZE *freeze, int32_t size)
1018 : {
1019 : TDSPACKET *pkt;
1020 53495 : unsigned pos = freeze->pkt_pos;
1021 53495 : unsigned size_len = freeze->size_len;
1022 :
1023 53495 : pkt = freeze->pkt;
1024 : do {
1025 158986 : if (pos >= pkt->data_len && pkt->next) {
1026 12 : pkt = pkt->next;
1027 12 : pos = 8;
1028 : }
1029 158986 : pkt->buf[tds_packet_get_data_start(pkt) + pos] = size & 0xffu;
1030 158986 : size >>= 8;
1031 158986 : pos++;
1032 158986 : } while (--size_len);
1033 : }
1034 :
1035 : /**
1036 : * Stop keeping data for this specific freeze.
1037 : *
1038 : * Similar to ::tds_freeze_close but specify the size to be written instead
1039 : * of letting ::tds_freeze_close compute it.
1040 : * After this call freeze should not be used.
1041 : *
1042 : * @param[in] freeze structure to work on
1043 : * @param[in] size size to write
1044 : */
1045 : TDSRET
1046 57857 : tds_freeze_close_len(TDSFREEZE *freeze, int32_t size)
1047 : {
1048 57857 : TDSSOCKET *tds = freeze->tds;
1049 : TDSPACKET *pkt;
1050 : #if !ENABLE_ODBC_MARS
1051 28860 : TDSPACKET *last_pkt_sent = NULL;
1052 : #endif
1053 :
1054 57857 : CHECK_FREEZE_EXTRA(freeze);
1055 :
1056 57857 : if (freeze->size_len)
1057 53495 : tds_freeze_update_size(freeze, size);
1058 :
1059 : /* if not last freeze we need just to update size */
1060 57857 : freeze->tds = NULL;
1061 57857 : if (--tds->frozen != 0)
1062 : return TDS_SUCCESS;
1063 :
1064 37209 : tds->frozen_packets = NULL;
1065 37209 : pkt = freeze->pkt;
1066 74608 : while (pkt->next) {
1067 212 : TDSPACKET *next = pkt->next;
1068 : TDSRET rc;
1069 : #if ENABLE_ODBC_MARS
1070 138 : pkt->next = NULL;
1071 138 : freeze->pkt = next;
1072 : /* packet will get owned by function, no need to release it */
1073 138 : rc = tds_connection_put_packet(tds, pkt);
1074 : #else
1075 148 : rc = tds_connection_write(tds, pkt->buf, pkt->data_len, 0) <= 0 ?
1076 74 : TDS_FAIL : TDS_SUCCESS;
1077 74 : last_pkt_sent = pkt;
1078 : #endif
1079 212 : if (TDS_UNLIKELY(TDS_FAILED(rc))) {
1080 44 : while (next->next) {
1081 : pkt = next;
1082 : next = pkt->next;
1083 : }
1084 22 : tds_extra_assert(pkt->next != NULL);
1085 22 : tds_extra_assert(pkt->next == tds->send_packet);
1086 :
1087 22 : pkt->next = NULL;
1088 22 : tds_mutex_lock(&tds->conn->list_mtx);
1089 22 : tds_packet_cache_add(tds->conn, freeze->pkt);
1090 22 : tds_mutex_unlock(&tds->conn->list_mtx);
1091 22 : return rc;
1092 : }
1093 : pkt = next;
1094 : }
1095 :
1096 37187 : tds_extra_assert(pkt->next == NULL);
1097 37187 : tds_extra_assert(pkt == tds->send_packet);
1098 :
1099 : #if !ENABLE_ODBC_MARS
1100 18540 : if (last_pkt_sent) {
1101 27 : tds_extra_assert(last_pkt_sent->next == pkt);
1102 27 : last_pkt_sent->next = NULL;
1103 27 : tds_mutex_lock(&tds->conn->list_mtx);
1104 27 : tds_packet_cache_add(tds->conn, freeze->pkt);
1105 27 : tds_mutex_unlock(&tds->conn->list_mtx);
1106 : }
1107 : #endif
1108 :
1109 : /* keep final packet so we can continue to add data */
1110 18647 : return TDS_SUCCESS;
1111 : }
1112 :
1113 : /** @} */
|