~ubuntu-branches/ubuntu/lucid/psqlodbc/lucid

« back to all changes in this revision

Viewing changes to socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-05-13 10:47:36 UTC
  • Revision ID: james.westby@ubuntu.com-20040513104736-a530gmn0p3knep89
Tags: upstream-07.03.0200
ImportĀ upstreamĀ versionĀ 07.03.0200

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------
 
2
 * Module:                      socket.c
 
3
 *
 
4
 * Description:         This module contains functions for low level socket
 
5
 *                                      operations (connecting/reading/writing to the backend)
 
6
 *
 
7
 * Classes:                     SocketClass (Functions prefix: "SOCK_")
 
8
 *
 
9
 * API functions:       none
 
10
 *
 
11
 * Comments:            See "notice.txt" for copyright and license information.
 
12
 *-------
 
13
 */
 
14
 
 
15
#include "socket.h"
 
16
 
 
17
#include "connection.h"
 
18
 
 
19
#ifndef WIN32
 
20
#include <stdlib.h>
 
21
#include <string.h>                             /* for memset */
 
22
#endif
 
23
 
 
24
extern GLOBAL_VALUES globals;
 
25
 
 
26
#ifndef BOOL
 
27
#define BOOL    int
 
28
#endif
 
29
#ifndef TRUE
 
30
#define TRUE    (BOOL)1
 
31
#endif
 
32
#ifndef FALSE
 
33
#define FALSE   (BOOL)0
 
34
#endif
 
35
 
 
36
 
 
37
void
 
38
SOCK_clear_error(SocketClass *self)
 
39
{
 
40
        self->errornumber = 0;
 
41
        self->errormsg = NULL;
 
42
}
 
43
 
 
44
 
 
45
SocketClass *
 
46
SOCK_Constructor(const ConnectionClass *conn)
 
47
{
 
48
        SocketClass *rv;
 
49
 
 
50
        rv = (SocketClass *) malloc(sizeof(SocketClass));
 
51
 
 
52
        if (rv != NULL)
 
53
        {
 
54
                rv->socket = (SOCKETFD) - 1;
 
55
                rv->buffer_filled_in = 0;
 
56
                rv->buffer_filled_out = 0;
 
57
                rv->buffer_read_in = 0;
 
58
 
 
59
                if (rv)
 
60
                        rv->buffer_size = conn->connInfo.drivers.socket_buffersize;
 
61
                else
 
62
                        rv->buffer_size = globals.socket_buffersize;
 
63
                rv->buffer_in = (unsigned char *) malloc(rv->buffer_size);
 
64
                if (!rv->buffer_in)
 
65
                {
 
66
                        free(rv);
 
67
                        return NULL;
 
68
                }
 
69
 
 
70
                rv->buffer_out = (unsigned char *) malloc(rv->buffer_size);
 
71
                if (!rv->buffer_out)
 
72
                {
 
73
                        free(rv->buffer_in);
 
74
                        free(rv);
 
75
                        return NULL;
 
76
                }
 
77
                rv->errormsg = NULL;
 
78
                rv->errornumber = 0;
 
79
                rv->reverse = FALSE;
 
80
        }
 
81
        return rv;
 
82
}
 
83
 
 
84
 
 
85
void
 
86
SOCK_Destructor(SocketClass *self)
 
87
{
 
88
        mylog("SOCK_Destructor\n");
 
89
        if (!self)
 
90
                return;
 
91
        if (self->socket != -1)
 
92
        {
 
93
                SOCK_put_char(self, 'X');
 
94
                SOCK_flush_output(self);
 
95
                closesocket(self->socket);
 
96
        }
 
97
 
 
98
        if (self->buffer_in)
 
99
                free(self->buffer_in);
 
100
 
 
101
        if (self->buffer_out)
 
102
                free(self->buffer_out);
 
103
 
 
104
        free(self);
 
105
}
 
106
 
 
107
 
 
108
char
 
109
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
 
110
{
 
111
#if defined (POSIX_MULTITHREAD_SUPPORT)
 
112
    const int bufsz = 8192; 
 
113
    char buf[bufsz];
 
114
    int error = 0;
 
115
    struct hostent host;
 
116
    struct hostent* hp = &host;
 
117
#else
 
118
    struct hostent* hp;
 
119
#endif 
 
120
        unsigned long iaddr;
 
121
 
 
122
        if (self->socket != -1)
 
123
        {
 
124
                self->errornumber = SOCKET_ALREADY_CONNECTED;
 
125
                self->errormsg = "Socket is already connected";
 
126
                return 0;
 
127
        }
 
128
 
 
129
        memset((char *) &(self->sadr), 0, sizeof(self->sadr));
 
130
 
 
131
        /*
 
132
         * If it is a valid IP address, use it. Otherwise use hostname lookup.
 
133
         */
 
134
        iaddr = inet_addr(hostname);
 
135
        if (iaddr == INADDR_NONE)
 
136
        {
 
137
#if defined (POSIX_MULTITHREAD_SUPPORT) 
 
138
  #if defined (HAVE_GETIPNODEBYNAME) /* Free-BSD ? */
 
139
        hp = getipnodebyname(hostname, AF_INET, 0, &error); 
 
140
  #elif defined (PGS_REENTRANT_API_1) /* solaris, irix */
 
141
        hp = gethostbyname_r(hostname, hp, buf, bufsz, &error);
 
142
  #elif defined (PGS_REENTRANT_API_2) /* linux */
 
143
        int result = 0;
 
144
        result = gethostbyname_r(hostname, hp, buf, bufsz, &hp, &error);
 
145
        if (result)
 
146
          hp = 0;
 
147
  #else
 
148
        hp = gethostbyname(hostname);
 
149
  #endif
 
150
#else
 
151
        hp = gethostbyname(hostname);
 
152
#endif
 
153
                if (hp == NULL)
 
154
                {
 
155
                        self->errornumber = SOCKET_HOST_NOT_FOUND;
 
156
                        self->errormsg = "Could not resolve hostname.";
 
157
                        return 0;
 
158
                }
 
159
                memcpy(&(self->sadr.sin_addr), hp->h_addr, hp->h_length);
 
160
        }
 
161
        else
 
162
                memcpy(&(self->sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
 
163
 
 
164
#if defined (HAVE_GETIPNODEBYNAME)
 
165
        freehostent(hp);
 
166
#endif /* HAVE_GETIPNODEBYNAME */
 
167
        self->sadr.sin_family = AF_INET;
 
168
        self->sadr.sin_port = htons(port);
 
169
 
 
170
        self->socket = socket(AF_INET, SOCK_STREAM, 0);
 
171
        if (self->socket == -1)
 
172
        {
 
173
                self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
 
174
                self->errormsg = "Could not create Socket.";
 
175
                return 0;
 
176
        }
 
177
 
 
178
        if (connect(self->socket, (struct sockaddr *) & (self->sadr),
 
179
                                sizeof(self->sadr)) < 0)
 
180
        {
 
181
                self->errornumber = SOCKET_COULD_NOT_CONNECT;
 
182
                self->errormsg = "Could not connect to remote socket.";
 
183
                closesocket(self->socket);
 
184
                self->socket = (SOCKETFD) - 1;
 
185
                return 0;
 
186
        }
 
187
        return 1;
 
188
}
 
189
 
 
190
 
 
191
void
 
192
SOCK_get_n_char(SocketClass *self, char *buffer, int len)
 
193
{
 
194
        int                     lf;
 
195
 
 
196
        if (!self)
 
197
                return;
 
198
        if (!buffer)
 
199
        {
 
200
                self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
 
201
                self->errormsg = "get_n_char was called with NULL-Pointer";
 
202
                return;
 
203
        }
 
204
 
 
205
        for (lf = 0; lf < len; lf++)
 
206
                buffer[lf] = SOCK_get_next_byte(self);
 
207
}
 
208
 
 
209
 
 
210
void
 
211
SOCK_put_n_char(SocketClass *self, char *buffer, int len)
 
212
{
 
213
        int                     lf;
 
214
 
 
215
        if (!self)
 
216
                return;
 
217
        if (!buffer)
 
218
        {
 
219
                self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
 
220
                self->errormsg = "put_n_char was called with NULL-Pointer";
 
221
                return;
 
222
        }
 
223
 
 
224
        for (lf = 0; lf < len; lf++)
 
225
                SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
 
226
}
 
227
 
 
228
 
 
229
/*
 
230
 *      bufsize must include room for the null terminator
 
231
 *      will read at most bufsize-1 characters + null.
 
232
 *      returns TRUE if truncation occurs.
 
233
 */
 
234
BOOL
 
235
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
 
236
{
 
237
        register int lf = 0;
 
238
 
 
239
        for (lf = 0; lf < bufsize - 1; lf++)
 
240
                if (!(buffer[lf] = SOCK_get_next_byte(self)))
 
241
                        return FALSE;
 
242
 
 
243
        buffer[bufsize - 1] = '\0';
 
244
        return TRUE;
 
245
}
 
246
 
 
247
 
 
248
void
 
249
SOCK_put_string(SocketClass *self, char *string)
 
250
{
 
251
        register int lf;
 
252
        int                     len;
 
253
 
 
254
        len = strlen(string) + 1;
 
255
 
 
256
        for (lf = 0; lf < len; lf++)
 
257
                SOCK_put_next_byte(self, (unsigned char) string[lf]);
 
258
}
 
259
 
 
260
 
 
261
int
 
262
SOCK_get_int(SocketClass *self, short len)
 
263
{
 
264
        if (!self)
 
265
                return 0;
 
266
        switch (len)
 
267
        {
 
268
                case 2:
 
269
                        {
 
270
                                unsigned short buf;
 
271
 
 
272
                                SOCK_get_n_char(self, (char *) &buf, len);
 
273
                                if (self->reverse)
 
274
                                        return buf;
 
275
                                else
 
276
                                        return ntohs(buf);
 
277
                        }
 
278
 
 
279
                case 4:
 
280
                        {
 
281
                                unsigned int buf;
 
282
 
 
283
                                SOCK_get_n_char(self, (char *) &buf, len);
 
284
                                if (self->reverse)
 
285
                                        return buf;
 
286
                                else
 
287
                                        return ntohl(buf);
 
288
                        }
 
289
 
 
290
                default:
 
291
                        self->errornumber = SOCKET_GET_INT_WRONG_LENGTH;
 
292
                        self->errormsg = "Cannot read ints of that length";
 
293
                        return 0;
 
294
        }
 
295
}
 
296
 
 
297
 
 
298
void
 
299
SOCK_put_int(SocketClass *self, int value, short len)
 
300
{
 
301
        unsigned int rv;
 
302
 
 
303
        if (!self)
 
304
                return;
 
305
        switch (len)
 
306
        {
 
307
                case 2:
 
308
                        rv = self->reverse ? value : htons((unsigned short) value);
 
309
                        SOCK_put_n_char(self, (char *) &rv, 2);
 
310
                        return;
 
311
 
 
312
                case 4:
 
313
                        rv = self->reverse ? value : htonl((unsigned int) value);
 
314
                        SOCK_put_n_char(self, (char *) &rv, 4);
 
315
                        return;
 
316
 
 
317
                default:
 
318
                        self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH;
 
319
                        self->errormsg = "Cannot write ints of that length";
 
320
                        return;
 
321
        }
 
322
}
 
323
 
 
324
 
 
325
void
 
326
SOCK_flush_output(SocketClass *self)
 
327
{
 
328
        int                     written;
 
329
 
 
330
        if (!self)
 
331
                return;
 
332
        written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
 
333
        if (written != self->buffer_filled_out)
 
334
        {
 
335
                self->errornumber = SOCKET_WRITE_ERROR;
 
336
                self->errormsg = "Could not flush socket buffer.";
 
337
        }
 
338
        self->buffer_filled_out = 0;
 
339
}
 
340
 
 
341
 
 
342
unsigned char
 
343
SOCK_get_next_byte(SocketClass *self)
 
344
{
 
345
        if (!self)
 
346
                return 0;
 
347
        if (self->buffer_read_in >= self->buffer_filled_in)
 
348
        {
 
349
                /*
 
350
                 * there are no more bytes left in the buffer so reload the buffer
 
351
                 */
 
352
                self->buffer_read_in = 0;
 
353
                self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, self->buffer_size, 0);
 
354
 
 
355
                mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);
 
356
 
 
357
                if (self->buffer_filled_in < 0)
 
358
                {
 
359
                        self->errornumber = SOCKET_READ_ERROR;
 
360
                        self->errormsg = "Error while reading from the socket.";
 
361
                        self->buffer_filled_in = 0;
 
362
                        return 0;
 
363
                }
 
364
                if (self->buffer_filled_in == 0)
 
365
                {
 
366
                        self->errornumber = SOCKET_CLOSED;
 
367
                        self->errormsg = "Socket has been closed.";
 
368
                        self->buffer_filled_in = 0;
 
369
                        return 0;
 
370
                }
 
371
        }
 
372
        return self->buffer_in[self->buffer_read_in++];
 
373
}
 
374
 
 
375
 
 
376
void
 
377
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
 
378
{
 
379
        int                     bytes_sent;
 
380
 
 
381
        if (!self)
 
382
                return;
 
383
        self->buffer_out[self->buffer_filled_out++] = next_byte;
 
384
 
 
385
        if (self->buffer_filled_out == self->buffer_size)
 
386
        {
 
387
                /* buffer is full, so write it out */
 
388
                bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0);
 
389
                if (bytes_sent != self->buffer_size)
 
390
                {
 
391
                        self->errornumber = SOCKET_WRITE_ERROR;
 
392
                        self->errormsg = "Error while writing to the socket.";
 
393
                }
 
394
                self->buffer_filled_out = 0;
 
395
        }
 
396
}