1 /*
2  *	(c) 1998-01 Jirka Hanika <geo@cuni.cz>
3  *
4  *	This single source file src/client.h, but NOT THE REST OF THIS PACKAGE,
5  *	is considered to be in Public Domain. Parts of this single source file may be
6  *	freely incorporated into any commercial or other software.
7  *
8  *	Most files in this package are covered strictly by the General Public
9  *	License version 2, to be found in doc/COPYING. Should GPL and the paragraph
10  *	above come into any sort of legal conflict, GPL takes precendence.
11  *
12  *	This file implements supporting functions for a simple TTSCP client.
13  *	See doc/english/ttscp.doc for a preliminary technical specification.
14  *
15  *	Note: the functions declared here often trash the scratch buffer.
16  */
17 
18 #ifndef EPOS_CLIENT_H
19 #define EPOS_CLIENT_H
20 
21 #if defined(HAVE_WINSOCK_H) || defined(HAVE_WINSOCK2_H)
22 	#define HAVE_WINSOCK
23 	#define socky unsigned
24 #else
25 	#define socky signed
26 #endif
27 
28 /*
29  *	The just_connect_socket() routine returns -1 if it cannot return a connected
30  *	socket. The connect_socket() routine additionally checks if the remote side
31  *	announces the TTSCP protocol of an acceptable version and calls shriek(4xx)
32  *	if it doesn't.  Use 0 for address for localhost, 0 for port to attempt to
33  *	locate a public TTSCP server if no local one can be found.
34  *
35  *	Byte order: host byte order for the port number, network byte order for the addr.
36  *	This is because the address has typically been acquired through gethostbyname(),
37  *	while the port number is probably constant or directly specified by the user.
38  */
39 
40 int just_connect_socket(unsigned int ipaddr, int port);	// returns -1 if not connected
41 int connect_socket(unsigned int ipaddr, int port);	// as above, check protocol, shriek if bad
42 bool running_at_localhost();
43 
44 /*
45  *	getaddrbyname() converts an Internet host name (or address in the dotted
46  *	format) to the host byte order IP address.
47  */
48 
49 int getaddrbyname(const char *inet_name);
50 
51 /*
52  *	xmit_option() send the "set" command appropriate for setting a named
53  *	option to a specified value.
54  */
55 void xmit_option(const char *name, const char *value, int sd);
56 
57 /*
58  *	get_handle() should be called before any TTSCP command is issued.
59  *	It returns strdup(connection handle) after having skipped protocol
60  *	configuration sent by the server.
61  */
62 
63 char *get_handle(int sd);
64 
65 /*
66  *	sync_finish_command() can be used to wait for the completion code
67  *	for a command. It will block until it is received.
68  *	Returns zero if a successful reply has been received;
69  *	otherwise the error code received is returned.
70  *	The 649 error code (never issued in TTSCP) implies
71  *	a broken connection due to end of file or error condition,
72  *	such as a network disconnection.
73  *
74  *	If you are looking for a more complex client-side apply command
75  *	handling example, one where the data produced by the server
76  *	is also correctly received via a data connection, see
77  *	tcpsyn_appl() in tcpsyn.cc
78  */
79 
80 int sync_finish_command(int ctrld);	// wait for the completion code
81 
82 /*
83  *	async_close() function is equivalent to close(), except that
84  *	it returns immediately (and without a return value, which may
85  *	be still unknown at the moment). Doing the close is left to
86  *	a child process; as soon, as the child holds the only file
87  *	descriptor copy in question, it is killed, which implies
88  *	closing its file descriptors.
89  *
90  *	yread() and write() are wrappers for read() and write(),
91  *	respectively.  On non-UNIX systems (as guessed by the absence
92  *	of the unistd.h file) these functions try calling recv or send
93  *	before the read or write.  This behavior is necessary with
94  *	the poor clumsy windows sockets, but unistd.h doesn't
95  *	necessarily imply UNIX, Windows may not necessarily imply
96  *	broken sockets, and the absence of unistd.h doesn't imply
97  *	anything.  It would be nice to know whether one can
98  *	read/write sockets under OS/2 or Hurd.
99  */
100 
101 #ifdef HAVE_UNISTD_H
102 
103 	#include <unistd.h>
104 
105 	#ifdef HAVE_SIGNAL_H
106 		#include <signal.h>
107 	#endif
108 
109 	#ifdef HAVE_ERRNO_H
110 		#include <errno.h>
111 	#endif
112 
async_close(int fd)113 	inline void async_close(int fd)
114 	{
115 		int pid = scfg->asyncing ? fork() : -1;
116 		switch(pid)
117 		{
118 			case -1:
119 				if(close(fd)) shriek(465,"Error on close()");
120 				return;
121 			case 0:
122 				sleep(1800);	/* will be killed by the parent soon */
123 				abort();	/* hopefully impossible */
124 			default:
125 				if(close(fd)) shriek(465, "Error on close()");
126 				kill(pid, SIGKILL);
127 		}
128 	}
129 
ywrite(int fd,const void * buffer,int size)130 	inline int ywrite(int fd, const void *buffer, int size)
131 	{
132 		return write(fd, (const char *)buffer, size);
133 	}
134 
yread(int fd,void * buffer,int size)135 	inline int yread(int fd, void *buffer, int size)
136 	{
137 		return read(fd, (char *)buffer, size);
138 	}
139 
140 	#if defined(HAVE_WINSOCK2_H) || defined(HAVE_WINSOCK_H)
141 		#error Funny - UNIX does not rhyme with winsock
142 	#endif
143 
144 #else
145 	#ifdef HAVE_WINSOCK2_H
146 		#include <winsock2.h>
147 	#else
148 		#ifdef HAVE_WINSOCK_H
149 			#include <winsock.h>
150 		#endif
151 	#endif
152 
153 
154 	#ifdef HAVE_IO_H
155 		#include <io.h>
156 	#endif
157 
158 	#ifdef HAVE_ERRNO_H
159 		#include <errno.h>
160 	#endif
161 
async_close(int fd)162 	inline void async_close(int fd)
163 	{
164 		if (close(fd) && closesocket(fd)) shriek(465,"Error on close()");
165 		return;
166 	}
167 
ywrite(int fd,const void * buffer,int size)168 	inline int ywrite(int fd, const void *buffer, int size)
169 	{
170 		int result = send(fd, (const char *)buffer, size, 0);
171 		if (result == -1) {
172 			if (WSAGetLastError() == WSAEWOULDBLOCK) {
173 				errno = EAGAIN;
174 				return -1;
175 			}
176 			return write(fd, (const char *)buffer, size);
177 		}
178 		return result;
179 	}
180 
yread(int fd,void * buffer,int size)181 	inline int yread(int fd, void *buffer, int size)
182 	{
183 		int result = recv(fd, (char *)buffer, size, 0);
184 		if (result == -1) {
185 			if (WSAGetLastError() == WSAEWOULDBLOCK) {
186 				errno = EAGAIN;
187 				return -1;
188 			}
189 			return read(fd, (char *)buffer, size);
190 		}
191 		return result;
192 	}
193 
194 #endif	// HAVE_UNISTD_H
195 
196 /*
197  *	close_and_invalidate() is NOT supplied in client.cc and
198  *	may only be used by server-side code, or the client side
199  *	code can define it to call just async_close.  The purpose
200  *	of close_and_invalidate() is to remove all references to
201  *	the descriptor from the scheduler before closing it.
202  */
203 
204 void close_and_invalidate(socky int sd);
205 
206 /*
207  *	The sgets() and sputs() routines provide a slow get line and put line
208  *	interface, especially on TTSCP control connections. They are suitable
209  *	for the client. sgets blocks until a line is received, which is a problem for
210  *	tcpsyn. sputs can be replaced by a callback fn assigned to sputs_replacement,
211  *	which is what the server side does to make it non-blocking.
212  */
213 
214 extern int (*sputs_replacement)(socky int sd, const char *, int);
215 
216 int sgets(char *buffer, int buffer_size, int sd);
217 int sputs(const char *buffer, int sd);
218 
219 
220 #endif		// EPOS_CLIENT_H
221 
222