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