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