1 /* CVS socket client stuff.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details. */
12 #include <sys/cdefs.h>
13 __RCSID("$NetBSD: socket-client.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
14
15 /***
16 *** THIS FILE SHOULD NEVER BE COMPILED UNLESS NO_SOCKET_TO_FD IS DEFINED.
17 ***/
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #ifdef CLIENT_SUPPORT
24
25 #include "cvs.h"
26 #include "buffer.h"
27
28 #include "socket-client.h"
29
30
31 /* Under certain circumstances, we must communicate with the server
32 via a socket using send() and recv(). This is because under some
33 operating systems (OS/2 and Windows 95 come to mind), a socket
34 cannot be converted to a file descriptor -- it must be treated as a
35 socket and nothing else.
36
37 We may also need to deal with socket routine error codes differently
38 in these cases. This is handled through the SOCK_ERRNO and
39 SOCK_STRERROR macros. */
40
41 /* These routines implement a buffer structure which uses send and
42 recv. The buffer is always in blocking mode so we don't implement
43 the block routine. */
44
45 /* Note that it is important that these routines always handle errors
46 internally and never return a positive errno code, since it would in
47 general be impossible for the caller to know in general whether any
48 error code came from a socket routine (to decide whether to use
49 SOCK_STRERROR or simply strerror to print an error message). */
50
51 /* We use an instance of this structure as the closure field. */
52
53 struct socket_buffer
54 {
55 /* The socket number. */
56 int socket;
57 };
58
59
60
61 /* The buffer input function for a buffer built on a socket. */
62
63 static int
socket_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)64 socket_buffer_input (void *closure, char *data, size_t need, size_t size,
65 size_t *got)
66 {
67 struct socket_buffer *sb = closure;
68 int nbytes;
69
70 /* I believe that the recv function gives us exactly the semantics
71 we want. If there is a message, it returns immediately with
72 whatever it could get. If there is no message, it waits until
73 one comes in. In other words, it is not like read, which in
74 blocking mode normally waits until all the requested data is
75 available. */
76
77 assert (size >= need);
78
79 *got = 0;
80
81 do
82 {
83
84 /* Note that for certain (broken?) networking stacks, like
85 VMS's UCX (not sure what version, problem reported with
86 recv() in 1997), and (according to windows-NT/config.h)
87 Windows NT 3.51, we must call recv or send with a
88 moderately sized buffer (say, less than 200K or something),
89 or else there may be network errors (somewhat hard to
90 produce, e.g. WAN not LAN or some such). buf_read_data
91 makes sure that we only recv() BUFFER_DATA_SIZE bytes at
92 a time. */
93
94 nbytes = recv (sb->socket, data + *got, size - *got, 0);
95 if (nbytes < 0)
96 error (1, 0, "reading from server: %s",
97 SOCK_STRERROR (SOCK_ERRNO));
98 if (nbytes == 0)
99 {
100 /* End of file (for example, the server has closed
101 the connection). If we've already read something, we
102 just tell the caller about the data, not about the end of
103 file. If we've read nothing, we return end of file. */
104 if (*got == 0)
105 return -1;
106 else
107 return 0;
108 }
109 *got += nbytes;
110 }
111 while (*got < need);
112
113 return 0;
114 }
115
116
117
118 /* The buffer output function for a buffer built on a socket. */
119
120 static int
socket_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)121 socket_buffer_output (void *closure, const char *data, size_t have,
122 size_t *wrote)
123 {
124 struct socket_buffer *sb = closure;
125
126 *wrote = have;
127
128 /* See comment in socket_buffer_input regarding buffer size we pass
129 to send and recv. */
130
131 # ifdef SEND_NEVER_PARTIAL
132 /* If send() never will produce a partial write, then just do it. This
133 is needed for systems where its return value is something other than
134 the number of bytes written. */
135 if (send (sb->socket, data, have, 0) < 0)
136 error (1, 0, "writing to server socket: %s",
137 SOCK_STRERROR (SOCK_ERRNO));
138 # else
139 while (have > 0)
140 {
141 int nbytes;
142
143 nbytes = send (sb->socket, data, have, 0);
144 if (nbytes < 0)
145 error (1, 0, "writing to server socket: %s",
146 SOCK_STRERROR (SOCK_ERRNO));
147
148 have -= nbytes;
149 data += nbytes;
150 }
151 # endif
152
153 return 0;
154 }
155
156
157
158 /* The buffer flush function for a buffer built on a socket. */
159
160 /*ARGSUSED*/
161 static int
socket_buffer_flush(void * closure)162 socket_buffer_flush (void *closure)
163 {
164 /* Nothing to do. Sockets are always flushed. */
165 return 0;
166 }
167
168
169
170 static int
socket_buffer_shutdown(struct buffer * buf)171 socket_buffer_shutdown (struct buffer *buf)
172 {
173 struct socket_buffer *n = buf->closure;
174 char tmp;
175
176 /* no need to flush children of an endpoint buffer here */
177
178 if (buf->input)
179 {
180 int err = 0;
181 if (! buf_empty_p (buf)
182 || (err = recv (n->socket, &tmp, 1, 0)) > 0)
183 error (0, 0, "dying gasps from %s unexpected",
184 current_parsed_root->hostname);
185 else if (err == -1)
186 error (0, 0, "reading from %s: %s", current_parsed_root->hostname,
187 SOCK_STRERROR (SOCK_ERRNO));
188
189 /* shutdown() socket */
190 # ifdef SHUTDOWN_SERVER
191 if (current_parsed_root->method != server_method)
192 # endif
193 if (shutdown (n->socket, 0) < 0)
194 {
195 error (1, 0, "shutting down server socket: %s",
196 SOCK_STRERROR (SOCK_ERRNO));
197 }
198
199 buf->input = NULL;
200 }
201 else if (buf->output)
202 {
203 /* shutdown() socket */
204 # ifdef SHUTDOWN_SERVER
205 /* FIXME: Should have a SHUTDOWN_SERVER_INPUT &
206 * SHUTDOWN_SERVER_OUTPUT
207 */
208 if (current_parsed_root->method == server_method)
209 SHUTDOWN_SERVER (n->socket);
210 else
211 # endif
212 if (shutdown (n->socket, 1) < 0)
213 {
214 error (1, 0, "shutting down server socket: %s",
215 SOCK_STRERROR (SOCK_ERRNO));
216 }
217
218 buf->output = NULL;
219 }
220
221 return 0;
222 }
223
224
225
226 /* Create a buffer based on a socket. */
227
228 struct buffer *
socket_buffer_initialize(int socket,int input,void (* memory)(struct buffer *))229 socket_buffer_initialize (int socket, int input,
230 void (*memory) (struct buffer *))
231 {
232 struct socket_buffer *sbuf = xmalloc (sizeof *sbuf);
233 sbuf->socket = socket;
234 return buf_initialize (input ? socket_buffer_input : NULL,
235 input ? NULL : socket_buffer_output,
236 input ? NULL : socket_buffer_flush,
237 NULL, NULL,
238 socket_buffer_shutdown,
239 memory,
240 sbuf);
241 }
242
243 #endif /* CLIENT_SUPPORT */
244