1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
/* system independent sockets (basically for unix and Win)
(C)2000,1 Simon Urbanek
conditional defines:
MAIN
should be defined in just one file that will contain the fn definitions and variables
USE_SNPRINTF
emulate snprintf on Win platforms (you will
lose the security which is provided under unix of course)
SOCK_ERRORS
include error code handling and checking functions
*/
#ifndef __SISOCKS_H__
#define __SISOCKS_H__
#if defined __GNUC__ && !defined unix && !defined Win32 /* MacOS X hack (gcc on any platform should behave as unix - except for Win32, where we need to keep using winsock) */
#define unix
#endif
#if defined SOCK_ERRORS || defined USE_SNPRINTF
#include <stdio.h>
#endif
#include <string.h>
#ifdef unix
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#define sockerrno errno
#define SOCKET int
#define INVALID_SOCKET (-1)
#define closesocket(A) close(A)
#else
#define windows
#include <windows.h>
#include <winsock.h>
#include <string.h>
#include <stdlib.h>
#define inet_aton(A,B) (0, B.s_addr=inet_addr(A))
#define sockerrno WSAGetLastError()
#define ECONNREFUSED WSAECONNREFUSED
#define EADDRINUSE WSAEADDRINUSE
#define ENOTSOCK WSAENOTSOCK
#define EISCONN WSAEISCONN
#define ETIMEDOUT WSAETIMEDOUT
#define ENETUNREACH WSAENETUNREACH
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EBADF WSAEBADF
#define EINVAL WSAEINVAL
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EFAULT WSAEFAULT
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EACCES WSAEACCES
#ifdef USE_SNPRINTF
#ifdef MAIN
int snprintf(char *buf, int len, char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsprintf(buf, fmt, argptr);
va_end(argptr);
return(cnt);
}
#else
extern int snprintf(char *buf, int len, char *fmt, ...);
#endif
#endif
#endif
#define SA struct sockaddr
#define SAIN struct sockaddr_in
#ifdef windows
#ifdef MAIN
int initsocks(void)
{
WSADATA dt;
/* initialize WinSock 1.1 */
return (WSAStartup(0x0101,&dt))?-1:0;
}
#else
extern int initsocks(void);
#endif
#define donesocks() WSACleanup()
#else
/* no stupid stuff necessary for unix */
#define initsocks()
#define donesocks()
#endif
#ifdef SOCK_ERRORS
#ifdef MAIN
int suppmode=0;
int socklasterr;
FILE *sockerrlog=0;
/* copy error description to buf or set *buf=0 if none */
int sockerrorchecks(char *buf, int blen, int res) {
*buf=0;
if (res==-1) {
switch(sockerrno) {
case EBADF: strncpy(buf,"bad descriptor",blen); break;
case EINVAL: strncpy(buf,"already in use",blen); break;
case EACCES: strncpy(buf,"access denied",blen); break;
case ENOTSOCK: strncpy(buf,"descriptor is not a socket",blen); break;
case EOPNOTSUPP: strncpy(buf,"operation not supported",blen); break;
case EFAULT: strncpy(buf,"fault",blen); break;
case EWOULDBLOCK: strncpy(buf,"operation would block",blen); break;
case EISCONN: strncpy(buf,"is already connected",blen); break;
case ECONNREFUSED: strncpy(buf,"connection refused",blen); break;
case ETIMEDOUT: strncpy(buf,"operation timed out",blen); break;
case ENETUNREACH: strncpy(buf,"network is unreachable",blen); break;
case EADDRINUSE: strncpy(buf,"address already in use",blen); break;
case EINPROGRESS: strncpy(buf,"in progress",blen); break;
case EALREADY: strncpy(buf,"previous connect request not completed yet",blen); break;
#ifdef unix
default: snprintf(buf,blen,"unknown socket error %d",sockerrno);
#else
default: sprintf(buf,"unknown socket error %d",sockerrno);
#endif
}
}
return res;
}
/* check socket error and add to log file if necessary */
int sockerrorcheck(char *sn, int rtb, int res) {
if (!sockerrlog) sockerrlog=stderr;
if ((signed int)res==-1) {
if (socklasterr==sockerrno) {
suppmode++;
} else {
if (suppmode>0) {
fprintf(sockerrlog,"##> REP: (last error has been repeated %d times.)\n",suppmode);
suppmode=0;
}
fprintf(sockerrlog,"##> SOCK_ERROR: %s error #%d",sn,sockerrno);
switch(sockerrno) {
case EBADF: fprintf(sockerrlog,"(bad descriptor)"); break;
case EINVAL: fprintf(sockerrlog,"(already in use)"); break;
case EACCES: fprintf(sockerrlog,"(access denied)"); break;
case ENOTSOCK: fprintf(sockerrlog,"(descriptor is not a socket)"); break;
case EOPNOTSUPP: fprintf(sockerrlog,"(operation not supported)"); break;
case EFAULT: fprintf(sockerrlog,"(fault)"); break;
case EWOULDBLOCK: fprintf(sockerrlog,"(operation would block)"); break;
case EISCONN: fprintf(sockerrlog,"(is already connected)"); break;
case ECONNREFUSED: fprintf(sockerrlog,"(connection refused)"); break;
case ETIMEDOUT: fprintf(sockerrlog,"(operation timed out)"); break;
case ENETUNREACH: fprintf(sockerrlog,"(network is unreachable)"); break;
case EADDRINUSE: fprintf(sockerrlog,"(address already in use)"); break;
case EINPROGRESS: fprintf(sockerrlog,"(in progress)"); break;
case EALREADY: fprintf(sockerrlog,"(previous connect request not completed yet)"); break;
default: fprintf(sockerrlog,"(?)");
}
fprintf(sockerrlog,"\n"); fflush(sockerrlog);
socklasterr=sockerrno;
}
if (rtb) exit(1);
}
return res;
}
#else
extern int suppmode=0;
extern int socklasterr;
extern FILE *sockerrlog=0;
int sockerrorchecks(char *buf, int blen, int res);
int sockerrorcheck(char *sn, int rtb, int res);
#endif
#define FCF(X,F) sockerrorcheck(X,1,F)
#define CF(X,F) sockerrorcheck(X,0,F)
#endif
#ifdef MAIN
struct sockaddr *build_sin(struct sockaddr_in *sa,char *ip,int port) {
memset(sa,0,sizeof(struct sockaddr_in));
sa->sin_family=AF_INET;
sa->sin_port=htons(port);
sa->sin_addr.s_addr=(ip)?inet_addr(ip):htonl(INADDR_ANY);
return (struct sockaddr*)sa;
}
#else
struct sockaddr *build_sin(struct sockaddr_in *sa,char *ip,int port);
#endif
#endif /* __SISOCKS_H__ */
|