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