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