Added SILC Server library.
[silc.git] / lib / silcutil / win32 / silcwin32sockconn.c
1 /*
2
3   silcwin32sockconn.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2005 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12   
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22
23 /* Writes data from encrypted buffer to the socket connection. If the
24    data cannot be written at once, it will be written later with a timeout. 
25    The data is written from the data section of the buffer, not from head
26    or tail section. This automatically pulls the data section towards end
27    after writing the data. */
28
29 int silc_socket_write(SilcSocketConnection sock)
30 {
31   int ret = 0, err;
32   SOCKET fd = sock->sock;
33   SilcBuffer src = sock->outbuf;
34
35   if (!src)
36     return -2;
37   if (SILC_IS_DISABLED(sock))
38     return -1;
39
40   SILC_LOG_DEBUG(("Writing data to socket %d", fd));
41
42   if (src->len > 0) {
43     ret = send(fd, src->data, src->len,  0);
44     if (ret == SOCKET_ERROR) {
45       err = WSAGetLastError();
46       if (err == WSAEWOULDBLOCK) {
47         SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
48         return -2;
49       }
50       SILC_LOG_ERROR(("Cannot write to socket: %d", (int)fd));
51       sock->sock_error = err;
52       return -1;
53     }
54
55     if (ret < src->len) {
56       SILC_LOG_DEBUG(("Wrote data %d of %d bytes, will write rest later",
57                       ret, src->len));
58       silc_buffer_pull(src, ret);
59       return -2;
60     }
61
62     silc_buffer_pull(src, ret);
63   }
64
65   SILC_LOG_DEBUG(("Wrote data %d bytes", ret));
66
67   return ret;
68 }
69
70 /* Reads data from the socket connection into the incoming data buffer.
71    It reads as much as possible from the socket connection. This returns
72    amount of bytes read or -1 on error or -2 on case where all of the
73    data could not be read at once. */
74
75 int silc_socket_read(SilcSocketConnection sock)
76 {
77   int len = 0, err;
78   unsigned char buf[SILC_SOCKET_READ_SIZE];
79   SOCKET fd = sock->sock;
80   int argp;
81
82   if (SILC_IS_DISABLED(sock))
83     return -1;
84
85   SILC_LOG_DEBUG(("Reading data from socket %d", fd));
86
87   /* Check whether there is data available, without calling recv(). */
88   ioctlsocket(fd, FIONREAD, (unsigned long *)&argp);
89   if (argp == 0) {
90     /* Is this kludge or what? Without this thing this contraption
91        does not work at all!?. */
92     SleepEx(1, TRUE);
93     SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
94     return -2;
95   }
96
97   /* Read the data from the socket. */
98   len = recv(fd, buf, sizeof(buf), 0);
99   if (len == SOCKET_ERROR) {
100     err = WSAGetLastError();
101     if (err == WSAEWOULDBLOCK || err == WSAEINTR) {
102       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
103       return -2;
104     }
105     SILC_LOG_ERROR(("Cannot read from socket: %d", (int)fd));
106     sock->sock_error = err;
107     return -1;
108   }
109
110   if (!len)
111     return 0;
112
113   /* Insert the data to the buffer. */
114
115   if (!sock->inbuf)
116     sock->inbuf = silc_buffer_alloc(SILC_SOCKET_BUF_SIZE);
117   
118   /* If the data does not fit to the buffer reallocate it */
119   if ((sock->inbuf->end - sock->inbuf->tail) < len)
120     sock->inbuf = silc_buffer_realloc(sock->inbuf, sock->inbuf->truelen + 
121                                       (len * 2));
122   silc_buffer_put_tail(sock->inbuf, buf, len);
123   silc_buffer_pull_tail(sock->inbuf, len);
124
125   SILC_LOG_DEBUG(("Read %d bytes", len));
126
127   return len;
128 }
129
130 /* Returns human readable socket error message */
131
132 SilcBool silc_socket_get_error(SilcSocketConnection sock, char *error,
133                            SilcUInt32 error_len)
134 {
135   /* XXX TODO */
136   return FALSE;
137 }