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 96850 : tds_get_packet(TDSCONNECTION *conn, unsigned len)
65 : {
66 96850 : TDSPACKET *packet, *to_free = NULL;
67 :
68 96850 : tds_mutex_lock(&conn->list_mtx);
69 197286 : while ((packet = conn->packet_cache) != NULL) {
70 94515 : --conn->num_cached_packets;
71 94515 : conn->packet_cache = packet->next;
72 :
73 : /* return it */
74 94515 : if (packet->capacity >= len) {
75 90929 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
76 90929 : packet->next = NULL;
77 90919 : tds_packet_zero_data_start(packet);
78 90929 : packet->data_len = 0;
79 90929 : packet->sid = 0;
80 90929 : break;
81 : }
82 :
83 : /* discard packet if too small */
84 3586 : packet->next = to_free;
85 3586 : to_free = packet;
86 : }
87 96850 : tds_mutex_unlock(&conn->list_mtx);
88 :
89 96850 : if (to_free)
90 3369 : tds_free_packets(to_free);
91 :
92 96850 : if (!packet)
93 5921 : packet = tds_alloc_packet(NULL, len);
94 :
95 96850 : return packet;
96 : }
97 :
98 : /* append packets in cached list. must have the lock! */
99 : static void
100 96935 : tds_packet_cache_add(TDSCONNECTION *conn, TDSPACKET *packet)
101 : {
102 : TDSPACKET *last;
103 96935 : unsigned count = 1;
104 :
105 96935 : assert(conn && packet);
106 96935 : tds_mutex_check_owned(&conn->list_mtx);
107 :
108 96935 : if (conn->num_cached_packets >= 8) {
109 0 : tds_free_packets(packet);
110 0 : return;
111 : }
112 :
113 88 : for (last = packet; last->next; last = last->next)
114 88 : ++count;
115 :
116 96935 : last->next = conn->packet_cache;
117 96935 : conn->packet_cache = packet;
118 96935 : conn->num_cached_packets += count;
119 :
120 : #if ENABLE_EXTRA_CHECKS
121 96935 : count = 0;
122 196998 : for (packet = conn->packet_cache; packet; packet = packet->next)
123 100063 : ++count;
124 96935 : assert(count == conn->num_cached_packets);
125 : #endif
126 : }
127 :
128 : #if ENABLE_ODBC_MARS
129 : /* read partial packet */
130 : static bool
131 119984 : tds_packet_read(TDSCONNECTION *conn, TDSSOCKET *tds)
132 : {
133 119984 : TDSPACKET *packet = conn->recv_packet;
134 : int len;
135 :
136 : /* allocate some space to read data */
137 119984 : if (!packet) {
138 49118 : conn->recv_packet = packet = tds_get_packet(conn, MAX(conn->env.block_size + sizeof(TDS72_SMP_HEADER), 512));
139 49118 : if (!packet) goto Memory_Error;
140 49118 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
141 49118 : conn->recv_pos = 0;
142 49118 : packet->data_len = 8;
143 : }
144 :
145 119984 : assert(packet->data_start == 0);
146 :
147 119984 : assert(conn->recv_pos < packet->data_len && packet->data_len <= packet->capacity);
148 :
149 119984 : len = tds_connection_read(tds, packet->buf + conn->recv_pos, packet->data_len - conn->recv_pos);
150 119984 : if (len < 0)
151 : goto Severe_Error;
152 119973 : conn->recv_pos += len;
153 119973 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
154 :
155 : /* handle SMP */
156 119973 : 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 29562 : if (conn->recv_pos < sizeof(mars_header)) {
164 9913 : packet->data_len = sizeof(mars_header);
165 39475 : return false;
166 : }
167 :
168 19649 : memcpy(&mars_header, packet->buf, sizeof(mars_header));
169 19649 : tdsdump_dump_buf(TDS_DBG_HEADER, "Received MARS header", &mars_header, sizeof(mars_header));
170 19649 : sid = TDS_GET_A2LE(&mars_header.sid);
171 :
172 : /* FIXME this is done even by caller !! */
173 19649 : tds = NULL;
174 19649 : tds_mutex_lock(&conn->list_mtx);
175 19649 : if (sid < conn->num_sessions) {
176 19649 : tds = conn->sessions[sid];
177 19649 : packet->sid = sid;
178 : }
179 19649 : tds_mutex_unlock(&conn->list_mtx);
180 :
181 19649 : if (tds == BUSY_SOCKET) {
182 5 : 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 5 : tds_mutex_lock(&conn->list_mtx);
189 5 : conn->sessions[sid] = NULL;
190 5 : tds_mutex_unlock(&conn->list_mtx);
191 :
192 : /* reset packet to initial state to reuse it */
193 5 : packet->data_len = 8;
194 5 : conn->recv_pos = 0;
195 5 : return false;
196 : }
197 :
198 19644 : if (!tds) {
199 : /* server sent a unknown packet, close connection */
200 : goto Severe_Error;
201 : }
202 :
203 19644 : tds->send_wnd = TDS_GET_A4LE(&mars_header.wnd);
204 19644 : size = TDS_GET_A4LE(&mars_header.size);
205 19644 : if (mars_header.type == TDS_SMP_ACK) {
206 172 : if (size != sizeof(mars_header))
207 : goto Severe_Error;
208 19472 : } else if (mars_header.type == TDS_SMP_DATA) {
209 19472 : if (size < 0x18 || size > 0xffffu + sizeof(mars_header))
210 : goto Severe_Error;
211 : /* avoid recursive SMP */
212 19472 : 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 19472 : if (conn->recv_pos >= 20 && TDS_GET_A2BE(&packet->buf[18]) != size - 16)
216 : goto Severe_Error;
217 19472 : 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 19644 : if (mars_header.type != TDS_SMP_DATA)
231 172 : return conn->recv_pos >= size;
232 19472 : if (packet->data_len < size) {
233 9736 : packet = tds_realloc_packet(packet, size);
234 9736 : if (!packet)
235 : goto Memory_Error;
236 9736 : conn->recv_packet = packet;
237 : }
238 19472 : packet->data_len = size;
239 19472 : if (conn->recv_pos >= size) {
240 9736 : packet->data_start = sizeof(TDS72_SMP_HEADER);
241 9736 : packet->data_len -= sizeof(TDS72_SMP_HEADER);
242 9736 : 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 90411 : if (conn->recv_pos >= 8) {
250 84107 : len = TDS_GET_A2BE(&packet->buf[2]);
251 84107 : if (len < 8)
252 : goto Severe_Error;
253 84107 : if (packet->data_len < len) {
254 39198 : packet = tds_realloc_packet(packet, len);
255 39198 : if (!packet) goto Memory_Error;
256 39198 : conn->recv_packet = packet;
257 : }
258 84107 : packet->data_len = len;
259 84107 : return conn->recv_pos >= len;
260 : }
261 : return false;
262 :
263 11 : Memory_Error:
264 11 : Severe_Error:
265 11 : tds_connection_close(conn);
266 11 : tds_free_packets(packet);
267 11 : conn->recv_packet = NULL;
268 11 : return false;
269 : }
270 :
271 : static TDSPACKET*
272 120 : 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 120 : p = mars;
279 120 : if (buf[0] != TDS72_SMP && tds->conn->mars) {
280 40 : p->signature = TDS72_SMP;
281 40 : p->type = TDS_SMP_DATA;
282 40 : TDS_PUT_A2LE(&p->sid, tds->sid);
283 40 : TDS_PUT_A4LE(&p->size, len+16);
284 40 : ++tds->send_seq;
285 40 : TDS_PUT_A4LE(&p->seq, tds->send_seq);
286 : /* this is the acknowledge we give to server to stop sending !!! */
287 40 : tds->recv_wnd = tds->recv_seq + 4;
288 40 : TDS_PUT_A4LE(&p->wnd, tds->recv_wnd);
289 40 : p++;
290 : }
291 :
292 120 : start = (char*) p - (char *) mars;
293 120 : packet = tds_get_packet(tds->conn, len + start);
294 120 : if (TDS_LIKELY(packet)) {
295 120 : packet->sid = tds->sid;
296 120 : memcpy(packet->buf, mars, start);
297 120 : memcpy(packet->buf + start, buf, len);
298 120 : packet->data_len = len + start;
299 : }
300 120 : return packet;
301 : }
302 :
303 : static void
304 : tds_append_packet(TDSPACKET **p_packet, TDSPACKET *packet)
305 : {
306 97097 : while (*p_packet)
307 366 : p_packet = &((*p_packet)->next);
308 96731 : *p_packet = packet;
309 : }
310 :
311 : int
312 120 : tds_append_cancel(TDSSOCKET *tds)
313 : {
314 : unsigned char buf[8];
315 : TDSPACKET *packet;
316 :
317 120 : buf[0] = TDS_CANCEL;
318 120 : buf[1] = 1;
319 120 : TDS_PUT_A2BE(buf+2, 8);
320 120 : TDS_PUT_A4(buf+4, 0);
321 120 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
322 89 : buf[6] = 0x01;
323 :
324 120 : packet = tds_build_packet(tds, buf, 8);
325 120 : if (!packet)
326 : return TDS_FAIL;
327 :
328 120 : tds_mutex_lock(&tds->conn->list_mtx);
329 240 : tds_append_packet(&tds->conn->send_packets, packet);
330 120 : tds_mutex_unlock(&tds->conn->list_mtx);
331 :
332 120 : return TDS_SUCCESS;
333 : }
334 :
335 :
336 : static void
337 96928 : tds_connection_network(TDSCONNECTION *conn, TDSSOCKET *tds, int send)
338 : {
339 96928 : assert(!conn->in_net_tds);
340 96928 : conn->in_net_tds = tds;
341 96928 : tds_mutex_unlock(&conn->list_mtx);
342 :
343 : for (;;) {
344 : /* wait packets or update */
345 173327 : int rc = tds_select(tds, conn->send_packets ? TDSSELREAD|TDSSELWRITE : TDSSELREAD, tds->query_timeout);
346 :
347 173327 : if (rc < 0) {
348 : /* FIXME better error report */
349 53 : tds_connection_close(conn);
350 53 : break;
351 : }
352 :
353 : /* change notify */
354 : /* TODO async */
355 :
356 173274 : if (!rc) { /* timeout */
357 153 : tdsdump_log(TDS_DBG_INFO1, "timeout\n");
358 153 : switch (rc = tdserror(tds_get_ctx(tds), tds, TDSETIME, sock_errno)) {
359 128 : case TDS_INT_CONTINUE:
360 128 : continue;
361 25 : default:
362 : case TDS_INT_CANCEL:
363 25 : tds_close_socket(tds);
364 : }
365 25 : 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 173121 : if (conn->send_packets && (rc & POLLOUT) != 0) {
374 : TDSSOCKET *s;
375 :
376 53019 : int sid = tds_packet_write(conn);
377 53019 : if (sid < 0)
378 5266 : continue;
379 :
380 47753 : if (sid == tds->sid)
381 : break; /* return to caller */
382 :
383 10 : tds_mutex_lock(&conn->list_mtx);
384 10 : if (sid < conn->num_sessions) {
385 10 : s = conn->sessions[sid];
386 10 : if (TDSSOCKET_VALID(s))
387 0 : tds_cond_signal(&s->packet_cond);
388 : }
389 10 : tds_mutex_unlock(&conn->list_mtx);
390 : /* avoid using a possible closed connection */
391 10 : continue;
392 : }
393 :
394 : /* received */
395 120102 : if (rc & (POLLIN|POLLHUP)) {
396 : TDSPACKET *packet;
397 : TDSSOCKET *s;
398 :
399 : /* try to read a packet */
400 119984 : if (!tds_packet_read(conn, tds))
401 70877 : continue; /* packet not complete */
402 49107 : packet = conn->recv_packet;
403 49107 : conn->recv_packet = NULL;
404 49107 : conn->recv_pos = 0;
405 :
406 49107 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", packet->buf, packet->data_start + packet->data_len);
407 :
408 49107 : tds_mutex_lock(&conn->list_mtx);
409 49107 : if (packet->sid < conn->num_sessions) {
410 49107 : s = conn->sessions[packet->sid];
411 49107 : if (TDSSOCKET_VALID(s)) {
412 : /* append to correct session */
413 49107 : if (packet->buf[0] == TDS72_SMP && packet->buf[1] != TDS_SMP_DATA)
414 172 : tds_packet_cache_add(conn, packet);
415 : else
416 48935 : tds_append_packet(&conn->packets, packet);
417 49107 : packet = NULL;
418 : /* notify */
419 49107 : tds_cond_signal(&s->packet_cond);
420 : }
421 : }
422 49107 : tds_mutex_unlock(&conn->list_mtx);
423 49107 : tds_free_packets(packet);
424 : /* if we are receiving return the packet */
425 49107 : if (!send) break;
426 : }
427 : }
428 :
429 96928 : tds_mutex_lock(&conn->list_mtx);
430 96928 : conn->in_net_tds = NULL;
431 96928 : }
432 :
433 : static TDSRET
434 47102 : tds_connection_put_packet(TDSSOCKET *tds, TDSPACKET *packet)
435 : {
436 47102 : TDSCONNECTION *conn = tds->conn;
437 :
438 47102 : CHECK_TDS_EXTRA(tds);
439 :
440 47102 : packet->sid = tds->sid;
441 :
442 47102 : tds_mutex_lock(&conn->list_mtx);
443 47102 : tds->sending_packet = packet;
444 94644 : while (tds->sending_packet) {
445 : int wait_res;
446 :
447 47542 : if (IS_TDSDEAD(tds)) {
448 44 : 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 47498 : if (packet && (int32_t) (tds->send_seq - tds->send_wnd) < 0) {
454 : /* prepare MARS header if needed */
455 47098 : if (tds->conn->mars) {
456 : TDS72_SMP_HEADER *hdr;
457 :
458 : /* fill SMP data */
459 9450 : hdr = (TDS72_SMP_HEADER *) packet->buf;
460 9450 : hdr->signature = TDS72_SMP;
461 9450 : hdr->type = TDS_SMP_DATA;
462 9450 : TDS_PUT_A2LE(&hdr->sid, packet->sid);
463 9450 : TDS_PUT_A4LE(&hdr->size, packet->data_start + packet->data_len);
464 9450 : ++tds->send_seq;
465 9450 : TDS_PUT_A4LE(&hdr->seq, tds->send_seq);
466 : /* this is the acknowledge we give to server to stop sending */
467 9450 : tds->recv_wnd = tds->recv_seq + 4;
468 9450 : TDS_PUT_A4LE(&hdr->wnd, tds->recv_wnd);
469 : }
470 :
471 : /* append packet */
472 94196 : tds_append_packet(&conn->send_packets, packet);
473 47098 : packet = NULL;
474 : }
475 :
476 : /* network ok ? process network */
477 47498 : if (!conn->in_net_tds) {
478 47498 : tds_connection_network(conn, tds, packet ? 0 : 1);
479 47498 : if (tds->sending_packet)
480 440 : 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 47102 : tds->sending_packet = NULL;
504 47102 : tds_mutex_unlock(&conn->list_mtx);
505 47102 : if (TDS_UNLIKELY(packet)) {
506 4 : tds_free_packets(packet);
507 4 : return TDS_FAIL;
508 : }
509 47098 : if (IS_TDSDEAD(tds))
510 : return TDS_FAIL;
511 47058 : 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 97764 : tds_read_packet(TDSSOCKET * tds)
524 : {
525 : #if ENABLE_ODBC_MARS
526 48973 : TDSCONNECTION *conn = tds->conn;
527 :
528 48973 : tds_mutex_lock(&conn->list_mtx);
529 :
530 : for (;;) {
531 : int wait_res;
532 : TDSPACKET **p_packet;
533 :
534 98403 : if (IS_TDSDEAD(tds)) {
535 38 : 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 98517 : for (p_packet = &conn->packets; *p_packet; p_packet = &(*p_packet)->next)
541 49087 : if ((*p_packet)->sid == tds->sid)
542 : break;
543 :
544 98365 : if (*p_packet) {
545 : /* remove our packet from list */
546 48935 : TDSPACKET *packet = *p_packet;
547 48935 : *p_packet = packet->next;
548 48935 : tds_packet_cache_add(conn, tds->recv_packet);
549 48935 : tds_mutex_unlock(&conn->list_mtx);
550 :
551 48935 : packet->next = NULL;
552 48935 : tds->recv_packet = packet;
553 :
554 48935 : tds->in_buf = packet->buf + packet->data_start;
555 48935 : tds->in_len = packet->data_len;
556 48935 : tds->in_pos = 8;
557 48935 : tds->in_flag = tds->in_buf[0];
558 :
559 : /* send acknowledge if needed */
560 48935 : if ((int32_t) (tds->recv_seq + 2 - tds->recv_wnd) >= 0)
561 347 : tds_update_recv_wnd(tds, tds->recv_seq + 4);
562 :
563 48935 : return tds->in_len;
564 : }
565 :
566 : /* network ok ? process network */
567 49430 : if (!conn->in_net_tds) {
568 49430 : tds_connection_network(conn, tds, 0);
569 49430 : 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 38 : tds_mutex_unlock(&conn->list_mtx);
586 38 : return -1;
587 : #else /* !ENABLE_ODBC_MARS */
588 48791 : unsigned char *pkt = tds->in_buf, *p, *end;
589 :
590 48791 : if (IS_TDSDEAD(tds)) {
591 0 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD");
592 : return -1;
593 : }
594 :
595 48791 : tds->in_len = 0;
596 48791 : tds->in_pos = 0;
597 200776 : for (p = pkt, end = p+8; p < end;) {
598 103232 : int len = tds_connection_read(tds, p, end - p);
599 103232 : if (len <= 0) {
600 38 : tds_close_socket(tds);
601 38 : return -1;
602 : }
603 :
604 103194 : p += len;
605 103194 : if (p - pkt >= 4) {
606 103194 : unsigned pktlen = TDS_GET_A2BE(pkt+2);
607 : /* packet must at least contains header */
608 103194 : if (TDS_UNLIKELY(pktlen < 8)) {
609 0 : tds_close_socket(tds);
610 0 : return -1;
611 : }
612 103194 : if (TDS_UNLIKELY(pktlen > tds->recv_packet->capacity)) {
613 1320 : TDSPACKET *packet = tds_realloc_packet(tds->recv_packet, pktlen);
614 1320 : if (TDS_UNLIKELY(!packet)) {
615 0 : tds_close_socket(tds);
616 0 : return -1;
617 : }
618 1320 : tds->recv_packet = packet;
619 1320 : pkt = packet->buf;
620 1320 : p = pkt + (p-tds->in_buf);
621 1320 : tds->in_buf = pkt;
622 : }
623 103194 : end = pkt + pktlen;
624 : }
625 : }
626 :
627 : /* set the received packet type flag */
628 48753 : tds->in_flag = pkt[0];
629 :
630 : /* Set the length and pos (not sure what pos is used for now */
631 48753 : tds->in_len = p - pkt;
632 48753 : tds->in_pos = 8;
633 48753 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", tds->in_buf, tds->in_len);
634 :
635 48753 : return tds->in_len;
636 : #endif /* !ENABLE_ODBC_MARS */
637 : }
638 :
639 : #if ENABLE_ODBC_MARS
640 : static TDSRET
641 347 : tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd)
642 : {
643 : TDS72_SMP_HEADER *mars;
644 : TDSPACKET *packet;
645 :
646 347 : if (!tds->conn->mars)
647 : return TDS_SUCCESS;
648 :
649 347 : packet = tds_get_packet(tds->conn, sizeof(*mars));
650 347 : if (!packet)
651 : return TDS_FAIL; /* TODO check result */
652 :
653 347 : packet->data_len = sizeof(*mars);
654 347 : packet->sid = tds->sid;
655 :
656 347 : mars = (TDS72_SMP_HEADER *) packet->buf;
657 347 : mars->signature = TDS72_SMP;
658 347 : mars->type = TDS_SMP_ACK;
659 347 : TDS_PUT_A2LE(&mars->sid, tds->sid);
660 347 : mars->size = TDS_HOST4LE(16);
661 347 : TDS_PUT_A4LE(&mars->seq, tds->send_seq);
662 347 : tds->recv_wnd = new_recv_wnd;
663 347 : TDS_PUT_A4LE(&mars->wnd, tds->recv_wnd);
664 :
665 347 : tds_mutex_lock(&tds->conn->list_mtx);
666 694 : tds_append_packet(&tds->conn->send_packets, packet);
667 347 : tds_mutex_unlock(&tds->conn->list_mtx);
668 :
669 347 : return TDS_SUCCESS;
670 : }
671 :
672 : static TDSRET
673 231 : tds_append_fin_syn(TDSSOCKET *tds, uint8_t type)
674 : {
675 : TDS72_SMP_HEADER mars;
676 : TDSPACKET *packet;
677 :
678 231 : if (!tds->conn->mars)
679 : return TDS_SUCCESS;
680 :
681 231 : mars.signature = TDS72_SMP;
682 231 : mars.type = type;
683 231 : TDS_PUT_A2LE(&mars.sid, tds->sid);
684 231 : mars.size = TDS_HOST4LE(16);
685 231 : TDS_PUT_A4LE(&mars.seq, tds->send_seq);
686 231 : tds->recv_wnd = tds->recv_seq + 4;
687 231 : TDS_PUT_A4LE(&mars.wnd, tds->recv_wnd);
688 :
689 : /* do not use tds_get_packet as it require no lock ! */
690 231 : packet = tds_alloc_packet(&mars, sizeof(mars));
691 231 : if (!packet)
692 : return TDS_FAIL; /* TODO check result */
693 231 : packet->sid = tds->sid;
694 :
695 : /* we already hold lock so do not lock */
696 462 : tds_append_packet(&tds->conn->send_packets, packet);
697 :
698 231 : if (type == TDS_SMP_FIN) {
699 : /* now is no more an active session */
700 10 : tds->conn->sessions[tds->sid] = BUSY_SOCKET;
701 10 : 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 10 : tds_append_fin(TDSSOCKET *tds)
713 : {
714 10 : 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 221 : tds_append_syn(TDSSOCKET *tds)
723 : {
724 : TDSRET ret;
725 221 : tds_mutex_lock(&tds->conn->list_mtx);
726 221 : ret = tds_append_fin_syn(tds, TDS_SMP_SYN);
727 221 : tds_mutex_unlock(&tds->conn->list_mtx);
728 221 : return ret;
729 : }
730 : #endif /* ENABLE_ODBC_MARS */
731 :
732 :
733 : TDS_COMPILE_CHECK(additional, TDS_ADDITIONAL_SPACE != 0);
734 :
735 : TDSRET
736 93573 : tds_write_packet(TDSSOCKET * tds, unsigned char final)
737 : {
738 : TDSRET res;
739 93573 : unsigned int left = 0;
740 93573 : TDSPACKET *pkt = tds->send_packet, *pkt_next = NULL;
741 :
742 93573 : CHECK_TDS_EXTRA(tds);
743 :
744 : #if !ENABLE_ODBC_MARS
745 46425 : if (tds->frozen)
746 : #endif
747 : {
748 47265 : pkt->next = pkt_next = tds_get_packet(tds->conn, pkt->capacity);
749 47265 : if (!pkt_next)
750 : return TDS_FAIL;
751 :
752 : #if ENABLE_ODBC_MARS
753 47148 : if (tds->conn->mars)
754 9474 : pkt_next->data_start = sizeof(TDS72_SMP_HEADER);
755 : #endif
756 : }
757 :
758 93573 : if (tds->out_pos > tds->out_buf_max) {
759 496 : left = tds->out_pos - tds->out_buf_max;
760 243 : if (pkt_next)
761 262 : memcpy(pkt_next->buf + tds_packet_get_data_start(pkt_next) + 8, tds->out_buf + tds->out_buf_max, left);
762 496 : 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 93573 : tds->out_buf[0] = tds->out_flag;
769 93573 : tds->out_buf[1] = final;
770 93573 : TDS_PUT_A2BE(tds->out_buf+2, tds->out_pos);
771 93573 : TDS_PUT_A2BE(tds->out_buf+4, tds->conn->client_spid);
772 93573 : TDS_PUT_A2(tds->out_buf+6, 0);
773 93573 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
774 65293 : tds->out_buf[6] = 0x01;
775 :
776 93573 : if (tds->frozen) {
777 334 : pkt->data_len = tds->out_pos;
778 334 : tds_set_current_send_packet(tds, pkt_next);
779 334 : tds->out_pos = left + 8;
780 334 : CHECK_TDS_EXTRA(tds);
781 334 : return TDS_SUCCESS;
782 : }
783 :
784 : #if ENABLE_ODBC_MARS
785 46931 : pkt->data_len = tds->out_pos;
786 46931 : pkt->next = NULL;
787 46931 : tds_set_current_send_packet(tds, pkt_next);
788 46931 : res = tds_connection_put_packet(tds, pkt);
789 : #else /* !ENABLE_ODBC_MARS */
790 46308 : 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 92616 : res = tds_connection_write(tds, tds->out_buf, tds->out_pos, final) <= 0 ?
794 46308 : TDS_FAIL : TDS_SUCCESS;
795 :
796 46308 : memcpy(tds->out_buf + 8, tds->out_buf + tds->out_buf_max, left);
797 : #endif /* !ENABLE_ODBC_MARS */
798 :
799 93239 : tds->out_pos = left + 8;
800 :
801 93239 : if (TDS_UNLIKELY(tds->conn->encrypt_single_packet)) {
802 732 : tds->conn->encrypt_single_packet = 0;
803 732 : tds_ssl_deinit(tds->conn);
804 : }
805 :
806 : return res;
807 : }
808 :
809 : #if !ENABLE_ODBC_MARS
810 : int
811 543 : tds_put_cancel(TDSSOCKET * tds)
812 : {
813 : unsigned char out_buf[8];
814 : int sent;
815 :
816 543 : out_buf[0] = TDS_CANCEL; /* out_flag */
817 543 : out_buf[1] = 1; /* final */
818 543 : out_buf[2] = 0;
819 543 : out_buf[3] = 8;
820 543 : TDS_PUT_A4(out_buf+4, 0);
821 543 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
822 460 : out_buf[6] = 0x01;
823 :
824 543 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", out_buf, 8);
825 :
826 543 : sent = tds_connection_write(tds, out_buf, 8, 1);
827 :
828 543 : if (sent > 0)
829 537 : tds->in_cancel = 2;
830 :
831 : /* GW added in check for write() returning <0 and SIGPIPE checking */
832 543 : return sent <= 0 ? TDS_FAIL : TDS_SUCCESS;
833 : }
834 : #endif /* !ENABLE_ODBC_MARS */
835 :
836 :
837 : #if ENABLE_ODBC_MARS
838 : static int
839 53019 : tds_packet_write(TDSCONNECTION *conn)
840 : {
841 : int sent;
842 : int final;
843 53019 : TDSPACKET *packet = conn->send_packets;
844 :
845 53019 : assert(packet);
846 :
847 53019 : if (conn->send_pos == 0)
848 47793 : 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 53019 : if (packet->next != NULL)
852 : final = 0;
853 : /* take into account other packets for this session */
854 52735 : else if (packet->buf[0] != TDS72_SMP)
855 42929 : final = packet->buf[1] & 1;
856 : else
857 : final = 1;
858 :
859 53019 : sent = tds_connection_write(conn->in_net_tds, packet->buf + conn->send_pos,
860 53019 : packet->data_start + packet->data_len - conn->send_pos, final);
861 :
862 53019 : if (TDS_UNLIKELY(sent < 0)) {
863 : /* TODO tdserror called ?? */
864 40 : tds_connection_close(conn);
865 40 : return -1;
866 : }
867 :
868 : /* update sent data */
869 52979 : conn->send_pos += sent;
870 : /* remove packet if sent all data */
871 52979 : if (conn->send_pos >= packet->data_start + packet->data_len) {
872 47753 : uint16_t sid = packet->sid;
873 : TDSSOCKET *tds;
874 47753 : tds_mutex_lock(&conn->list_mtx);
875 47753 : tds = conn->sessions[sid];
876 47753 : if (TDSSOCKET_VALID(tds) && tds->sending_packet == packet)
877 47058 : tds->sending_packet = NULL;
878 47753 : conn->send_packets = packet->next;
879 47753 : packet->next = NULL;
880 47753 : tds_packet_cache_add(conn, packet);
881 47753 : tds_mutex_unlock(&conn->list_mtx);
882 47753 : conn->send_pos = 0;
883 47753 : 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 79424 : tds_freeze(TDSSOCKET *tds, TDSFREEZE *freeze, unsigned size_len)
904 : {
905 79424 : CHECK_TDS_EXTRA(tds);
906 79424 : tds_extra_assert(size_len <= 4 && size_len != 3);
907 :
908 79424 : if (tds->out_pos > tds->out_buf_max)
909 15 : tds_write_packet(tds, 0x0);
910 :
911 79424 : if (!tds->frozen)
912 54717 : tds->frozen_packets = tds->send_packet;
913 :
914 79424 : ++tds->frozen;
915 79424 : freeze->tds = tds;
916 79424 : freeze->pkt = tds->send_packet;
917 79424 : freeze->pkt_pos = tds->out_pos;
918 79424 : freeze->size_len = size_len;
919 79424 : if (size_len)
920 73658 : tds_put_n(tds, NULL, size_len);
921 :
922 79424 : CHECK_FREEZE_EXTRA(freeze);
923 79424 : }
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 69688 : tds_freeze_written(TDSFREEZE *freeze)
932 : {
933 69688 : TDSSOCKET *tds = freeze->tds;
934 69688 : TDSPACKET *pkt = freeze->pkt;
935 : size_t size;
936 :
937 69688 : CHECK_FREEZE_EXTRA(freeze);
938 :
939 : /* last packet needs special handling */
940 69688 : size = tds->out_pos;
941 :
942 : /* packets before last */
943 70070 : for (; pkt->next != NULL; pkt = pkt->next)
944 382 : size += pkt->data_len - 8;
945 :
946 69688 : 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 30 : tds_freeze_abort(TDSFREEZE *freeze)
958 : {
959 30 : TDSSOCKET *tds = freeze->tds;
960 30 : TDSPACKET *pkt = freeze->pkt;
961 :
962 30 : CHECK_FREEZE_EXTRA(freeze);
963 :
964 30 : if (pkt->next) {
965 15 : tds_mutex_lock(&tds->conn->list_mtx);
966 15 : tds_packet_cache_add(tds->conn, pkt->next);
967 15 : tds_mutex_unlock(&tds->conn->list_mtx);
968 15 : pkt->next = NULL;
969 :
970 : tds_set_current_send_packet(tds, pkt);
971 : }
972 30 : tds->out_pos = freeze->pkt_pos;
973 30 : pkt->data_len = 8;
974 :
975 30 : --tds->frozen;
976 30 : if (!tds->frozen)
977 30 : tds->frozen_packets = NULL;
978 30 : freeze->tds = NULL;
979 30 : 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 23862 : tds_freeze_close(TDSFREEZE *freeze)
993 : {
994 23862 : 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 14094 : tds_freeze_close_string(TDSFREEZE *freeze)
1009 : {
1010 14094 : size_t written = tds_freeze_written(freeze) - freeze->size_len;
1011 14094 : if (IS_TDS7_PLUS(freeze->tds->conn))
1012 14094 : written /= 2;
1013 14094 : 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 73628 : unsigned pos = freeze->pkt_pos;
1021 73628 : unsigned size_len = freeze->size_len;
1022 :
1023 73628 : pkt = freeze->pkt;
1024 : do {
1025 235574 : if (pos >= pkt->data_len && pkt->next) {
1026 15 : pkt = pkt->next;
1027 15 : pos = 8;
1028 : }
1029 235574 : pkt->buf[tds_packet_get_data_start(pkt) + pos] = size & 0xffu;
1030 235574 : size >>= 8;
1031 235574 : pos++;
1032 235574 : } 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 79394 : tds_freeze_close_len(TDSFREEZE *freeze, int32_t size)
1047 : {
1048 79394 : TDSSOCKET *tds = freeze->tds;
1049 : TDSPACKET *pkt;
1050 : #if !ENABLE_ODBC_MARS
1051 39583 : TDSPACKET *last_pkt_sent = NULL;
1052 : #endif
1053 :
1054 79394 : CHECK_FREEZE_EXTRA(freeze);
1055 :
1056 79394 : if (freeze->size_len)
1057 73628 : tds_freeze_update_size(freeze, size);
1058 :
1059 : /* if not last freeze we need just to update size */
1060 79394 : freeze->tds = NULL;
1061 79394 : if (--tds->frozen != 0)
1062 : return TDS_SUCCESS;
1063 :
1064 54687 : tds->frozen_packets = NULL;
1065 54687 : pkt = freeze->pkt;
1066 109609 : while (pkt->next) {
1067 262 : TDSPACKET *next = pkt->next;
1068 : TDSRET rc;
1069 : #if ENABLE_ODBC_MARS
1070 171 : pkt->next = NULL;
1071 171 : freeze->pkt = next;
1072 : /* packet will get owned by function, no need to release it */
1073 171 : rc = tds_connection_put_packet(tds, pkt);
1074 : #else
1075 182 : rc = tds_connection_write(tds, pkt->buf, pkt->data_len, 0) <= 0 ?
1076 91 : TDS_FAIL : TDS_SUCCESS;
1077 91 : last_pkt_sent = pkt;
1078 : #endif
1079 262 : if (TDS_UNLIKELY(TDS_FAILED(rc))) {
1080 54 : while (next->next) {
1081 : pkt = next;
1082 : next = pkt->next;
1083 : }
1084 27 : tds_extra_assert(pkt->next != NULL);
1085 27 : tds_extra_assert(pkt->next == tds->send_packet);
1086 :
1087 27 : pkt->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 27 : return rc;
1092 : }
1093 : pkt = next;
1094 : }
1095 :
1096 54660 : tds_extra_assert(pkt->next == NULL);
1097 54660 : tds_extra_assert(pkt == tds->send_packet);
1098 :
1099 : #if !ENABLE_ODBC_MARS
1100 27237 : if (last_pkt_sent) {
1101 33 : tds_extra_assert(last_pkt_sent->next == pkt);
1102 33 : last_pkt_sent->next = NULL;
1103 33 : tds_mutex_lock(&tds->conn->list_mtx);
1104 33 : tds_packet_cache_add(tds->conn, freeze->pkt);
1105 33 : tds_mutex_unlock(&tds->conn->list_mtx);
1106 : }
1107 : #endif
1108 :
1109 : /* keep final packet so we can continue to add data */
1110 27423 : return TDS_SUCCESS;
1111 : }
1112 :
1113 : /** @} */
|