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