Line data Source code
1 : /* TDSPool - Connection pooling for TDS based databases
2 : * Copyright (C) 2001 Brian Bruns
3 : *
4 : * This program is free software; you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation; either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program 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
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program; if not, write to the Free Software
16 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 : *
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdarg.h>
23 : #include <stdio.h>
24 : #include <assert.h>
25 :
26 : #if HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif /* HAVE_STDLIB_H */
29 :
30 : #if HAVE_UNISTD_H
31 : #include <unistd.h>
32 : #endif /* HAVE_UNISTD_H */
33 :
34 : #if HAVE_ERRNO_H
35 : #include <errno.h>
36 : #endif /* HAVE_ERRNO_H */
37 :
38 : #include <ctype.h>
39 :
40 : #include "pool.h"
41 : #include <freetds/utils/string.h>
42 : #include <freetds/checks.h>
43 : #include <freetds/bytes.h>
44 :
45 : void
46 720 : dump_login(TDSLOGIN * login)
47 : {
48 1440 : fprintf(stderr, "host %s\n", tds_dstr_cstr(&login->client_host_name));
49 1440 : fprintf(stderr, "user %s\n", tds_dstr_cstr(&login->user_name));
50 1440 : fprintf(stderr, "pass %s\n", tds_dstr_cstr(&login->password));
51 1440 : fprintf(stderr, "app %s\n", tds_dstr_cstr(&login->app_name));
52 1440 : fprintf(stderr, "srvr %s\n", tds_dstr_cstr(&login->server_name));
53 720 : fprintf(stderr, "vers %d.%d\n", TDS_MAJOR(login), TDS_MINOR(login));
54 1440 : fprintf(stderr, "lib %s\n", tds_dstr_cstr(&login->library));
55 1440 : fprintf(stderr, "lang %s\n", tds_dstr_cstr(&login->language));
56 1440 : fprintf(stderr, "char %s\n", tds_dstr_cstr(&login->server_charset));
57 720 : fprintf(stderr, "bsiz %d\n", login->block_size);
58 720 : }
59 :
60 : /**
61 : * Read part of packet. Function does not block.
62 : * @return true if packet is not complete and we must call again,
63 : * false on full packet or error.
64 : */
65 : bool
66 67344 : pool_packet_read(TDSSOCKET *tds)
67 : {
68 : unsigned int packet_len;
69 : int readed;
70 :
71 67344 : tdsdump_log(TDS_DBG_INFO1, "tds in_len %d in_pos %d\n", tds->in_len, tds->in_pos);
72 :
73 : // TODO MARS
74 :
75 : /* determine packet size */
76 67344 : packet_len = tds->in_len >= 4 ? TDS_GET_A2BE(&tds->in_buf[2]) : 8;
77 67344 : if (TDS_UNLIKELY(packet_len < 8)) {
78 0 : tds->in_len = 0;
79 0 : return false;
80 : }
81 :
82 : /* get another packet */
83 67344 : if (tds->in_len >= packet_len) {
84 : /* packet was not fully forwarded */
85 33517 : if (tds->in_pos < tds->in_len)
86 : return false;
87 33517 : tds->in_pos = 0;
88 33517 : tds->in_len = 0;
89 : }
90 :
91 : for (;;) {
92 : /* determine packet size */
93 134491 : packet_len = 8;
94 134491 : if (tds->in_len >= 4) {
95 68791 : packet_len = TDS_GET_A2BE(&tds->in_buf[2]);
96 68791 : if (packet_len < 8)
97 : break;
98 68791 : tdsdump_log(TDS_DBG_INFO1, "packet_len %u in_len %d\n", packet_len, tds->in_len);
99 : /* resize packet if not enough */
100 68791 : if (packet_len > tds->recv_packet->capacity) {
101 : TDSPACKET *packet;
102 :
103 279 : packet = tds_realloc_packet(tds->recv_packet, packet_len);
104 279 : if (!packet)
105 : break;
106 279 : tds->in_buf = packet->buf;
107 279 : tds->recv_packet = packet;
108 : }
109 68791 : CHECK_TDS_EXTRA(tds);
110 68791 : if (tds->in_len >= packet_len)
111 : return false;
112 : }
113 :
114 101692 : assert(packet_len > tds->in_len);
115 101692 : assert(packet_len <= tds->recv_packet->capacity);
116 101692 : assert(tds->in_len < tds->recv_packet->capacity);
117 :
118 101692 : readed = READSOCKET(tds_get_s(tds), &tds->in_buf[tds->in_len], packet_len - tds->in_len);
119 101692 : tdsdump_log(TDS_DBG_INFO1, "readed %d\n", readed);
120 :
121 : /* socket closed */
122 101692 : if (readed == 0)
123 : break;
124 :
125 : /* error */
126 100978 : if (readed < 0) {
127 33831 : int err = sock_errno;
128 33831 : if (err == EINTR)
129 0 : continue;
130 33831 : if (TDSSOCK_WOULDBLOCK(err))
131 : return true;
132 : break;
133 : }
134 :
135 : /* got some data */
136 67147 : tds->in_len += readed;
137 : }
138 :
139 : /* failure */
140 718 : tds->in_len = 0;
141 718 : return false;
142 : }
143 :
144 : int
145 32799 : pool_write(TDS_SYS_SOCKET sock, const void *buf, size_t len)
146 : {
147 : int ret;
148 32799 : const unsigned char *p = (const unsigned char *) buf;
149 :
150 98397 : while (len) {
151 32799 : ret = WRITESOCKET(sock, p, len);
152 32799 : if (ret <= 0) {
153 0 : int err = errno;
154 0 : if (TDSSOCK_WOULDBLOCK(err) || err == EINTR)
155 : break;
156 : return -1;
157 : }
158 32799 : p += ret;
159 32799 : len -= ret;
160 : }
161 32799 : return p - (const unsigned char *) buf;
162 : }
163 :
164 : void
165 1438 : pool_event_add(TDS_POOL *pool, TDS_POOL_EVENT *ev, TDS_POOL_EXECUTE execute)
166 : {
167 1438 : tds_mutex_lock(&pool->events_mtx);
168 1438 : ev->execute = execute;
169 1438 : ev->next = pool->events;
170 1438 : pool->events = ev;
171 1438 : tds_mutex_unlock(&pool->events_mtx);
172 1438 : WRITESOCKET(pool->event_fd, "x", 1);
173 1438 : }
174 :
175 : bool
176 32799 : pool_write_data(TDS_POOL_SOCKET *from, TDS_POOL_SOCKET *to)
177 : {
178 : int ret;
179 : TDSSOCKET *tds;
180 :
181 32799 : tdsdump_log(TDS_DBG_INFO1, "trying to send\n");
182 :
183 32799 : tds = from->tds;
184 32799 : tdsdump_log(TDS_DBG_INFO1, "sending %d bytes\n", tds->in_len);
185 : /* cf. net.c for better technique. */
186 32799 : ret = pool_write(tds_get_s(to->tds), tds->in_buf + tds->in_pos, tds->in_len - tds->in_pos);
187 : /* write failed, cleanup member */
188 32799 : if (ret < 0)
189 : return false;
190 :
191 32799 : tds->in_pos += ret;
192 32799 : if (tds->in_pos < tds->in_len) {
193 : /* partial write, schedule a future write */
194 0 : to->poll_send = true;
195 0 : from->poll_recv = false;
196 : } else {
197 32799 : to->poll_send = false;
198 32799 : from->poll_recv = true;
199 : }
200 : return true;
201 : }
|