You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
9.9 KiB
357 lines
9.9 KiB
15 years ago
|
#ifndef _KVI_SOCKET_H_
|
||
|
#define _KVI_SOCKET_H_
|
||
|
//=============================================================================
|
||
|
//
|
||
|
// File : kvi_socket.h
|
||
|
// Creation date : Thu Sep 20 03:50:22 2001 GMT by Szymon Stefanek
|
||
|
//
|
||
|
// This file is part of the KVirc irc client distribution
|
||
|
// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)
|
||
|
//
|
||
|
// This program is FREE software. You can redistribute it and/or
|
||
|
// modify it under the terms of the GNU General Public License
|
||
|
// as published by the Free Software Foundation; either version 2
|
||
|
// of the License, or (at your opinion) any later version.
|
||
|
//
|
||
|
// This program is distributed in the HOPE that it will be USEFUL,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
// See the GNU General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program. If not, write to the Free Software Foundation,
|
||
|
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
//
|
||
|
//=============================================================================
|
||
|
|
||
|
//=============================================================================
|
||
|
// Socket stuff abstraction layer
|
||
|
//=============================================================================
|
||
|
|
||
|
#include "kvi_settings.h"
|
||
|
#include "kvi_sockettype.h" // <--- this includes <winsock2.h> if needed
|
||
|
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include "kvi_inttypes.h"
|
||
|
|
||
|
//#ifndef _KVI_SOCKET_CPP_
|
||
|
extern KVILIB_API kvi_u64_t g_uOutgoingTraffic;
|
||
|
extern KVILIB_API kvi_u64_t g_uIncomingTraffic;
|
||
|
//#endif //!_KVI_SOCKET_CPP_
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
|
||
|
#define KVI_INVALID_SOCKET INVALID_SOCKET
|
||
|
|
||
|
#else
|
||
|
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/tcp.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#define KVI_INVALID_SOCKET (-1)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#ifndef MSG_NOSIGNAL
|
||
|
// At least solaris seems to not have it
|
||
|
#define MSG_NOSIGNAL 0
|
||
|
#endif
|
||
|
|
||
|
//#include "kvi_socketcalls.h"
|
||
|
|
||
|
|
||
|
//================================================================================================
|
||
|
// Constants for kvi_socket_create
|
||
|
//
|
||
|
|
||
|
#define KVI_SOCKET_PF_INET PF_INET
|
||
|
#define KVI_SOCKET_PF_INET6 PF_INET6
|
||
|
#define KVI_SOCKET_PF_UNIX PF_UNIX
|
||
|
|
||
|
#define KVI_SOCKET_TYPE_STREAM SOCK_STREAM
|
||
|
#define KVI_SOCKET_TYPE_DGRAM SOCK_DGRAM
|
||
|
|
||
|
#define KVI_SOCKET_PROTO_TCP 0
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_create
|
||
|
// kvi_socket_open
|
||
|
//
|
||
|
// Open a socket of the specified protocol family , type and protocol
|
||
|
// You should always use the KVI_SOCKET_* constants as parameters
|
||
|
// Returns KVI_INVALID_SOCKET if the socket creation has failed.
|
||
|
// The returned socket is in blocking mode!
|
||
|
//
|
||
|
|
||
|
#define kvi_socket_open kvi_socket_create
|
||
|
|
||
|
inline kvi_socket_t kvi_socket_create(int pf,int type,int proto)
|
||
|
{
|
||
|
return (kvi_socket_t)socket(pf,type,proto);
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_isValid
|
||
|
//
|
||
|
// Check if a socket is valid or not
|
||
|
//
|
||
|
|
||
|
inline void kvi_socket_flushTrafficCounters()
|
||
|
{
|
||
|
g_uOutgoingTraffic = 0;
|
||
|
g_uIncomingTraffic = 0;
|
||
|
}
|
||
|
|
||
|
inline bool kvi_socket_isValid(kvi_socket_t sock)
|
||
|
{
|
||
|
return (sock != ((kvi_socket_t)(KVI_INVALID_SOCKET)));
|
||
|
}
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_destroy
|
||
|
// kvi_socket_close
|
||
|
//
|
||
|
// Close a socket...that's all :)
|
||
|
//
|
||
|
|
||
|
#define kvi_socket_close kvi_socket_destroy
|
||
|
|
||
|
inline void kvi_socket_destroy(kvi_socket_t sock)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
closesocket(sock);
|
||
|
#else
|
||
|
close(sock);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_setNonBlocking
|
||
|
//
|
||
|
// Sets the socket in nonBlocking mode. Obviously returns false in case of failure
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_setNonBlocking(kvi_socket_t sock)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
unsigned long arg = 1;
|
||
|
return (ioctlsocket(sock,FIONBIO,(unsigned long FAR *)&arg) == 0);
|
||
|
#else
|
||
|
return (fcntl(sock,F_SETFL,O_NONBLOCK) == 0);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_bind
|
||
|
//
|
||
|
// Standard bind() call on the socket. Returns false in case of failure
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_bind(kvi_socket_t sock,const struct sockaddr * sa,int salen)
|
||
|
{
|
||
|
return (::bind(sock,sa,salen) == 0);
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_connect
|
||
|
//
|
||
|
// Starts a connection to the specified remote address
|
||
|
// returns false if the connection can not be started.
|
||
|
// You might take a look at kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_connect(kvi_socket_t sock,const struct sockaddr *sa,int salen)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return (WSAConnect(sock,sa,salen,0,0,0,0) == 0);
|
||
|
#else
|
||
|
return (::connect(sock,sa,salen) == 0);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
inline bool kvi_socket_recoverableConnectError(int err)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return ((err == WSAEINPROGRESS) || (err == WSAEWOULDBLOCK));
|
||
|
#else
|
||
|
return (err == EINPROGRESS);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
inline bool kvi_socket_recoverableError(int err)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return ((err == WSAEWOULDBLOCK) || (err == EINTR) || (err == EAGAIN));
|
||
|
#else
|
||
|
return ((err == EINTR) || (err = EAGAIN));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_accept
|
||
|
//
|
||
|
// Standard accept() call. Returns KVI_INVALID_SOCKET in case of failure
|
||
|
// You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline kvi_socket_t kvi_socket_accept(kvi_socket_t sock,struct sockaddr *sa,int * salen)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return (kvi_socket_t)::accept(sock,sa,salen);
|
||
|
#else
|
||
|
return (kvi_socket_t)::accept(sock,sa,(socklen_t *)salen);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_listen
|
||
|
//
|
||
|
// Standard listen() call. Returns false in case of failure
|
||
|
// You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_listen(kvi_socket_t sock,int backlog)
|
||
|
{
|
||
|
return (::listen(sock,backlog) == 0);
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_select
|
||
|
//
|
||
|
// Standard select() call. This is complex so here is a mini-reminder:
|
||
|
// nhpo is the number of the highest file descriptor in the sets plus one!
|
||
|
// Returns the number of sockets with data available (or space available)
|
||
|
// or something that is less than 0 in case of error. You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline int kvi_socket_select(int nhpo,fd_set *r,fd_set *w,fd_set *e,struct timeval * t)
|
||
|
{
|
||
|
return ::select(nhpo,r,w,e,t);
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_send
|
||
|
// kvi_socket_write
|
||
|
//
|
||
|
// Standard send() call. On UNIX ignores SIGPIPE. Returns the number of bytes sent or
|
||
|
// -1 in case of failure. You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
#define kvi_socket_write kvi_socket_send
|
||
|
|
||
|
inline int kvi_socket_send(kvi_socket_t sock,const void * buf,int size)
|
||
|
{
|
||
|
g_uOutgoingTraffic+=size;
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return ::send(sock,(const char *)buf,size,0);
|
||
|
#else
|
||
|
return ::send(sock,buf,size,MSG_NOSIGNAL | MSG_DONTWAIT);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_recv
|
||
|
// kvi_socket_read
|
||
|
//
|
||
|
// Standard read() call. On UNIX ignores SIGPIPE. Returns the number of bytes readed or
|
||
|
// -1 in case of failure. You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
#define kvi_socket_read kvi_socket_recv
|
||
|
|
||
|
inline int kvi_socket_recv(kvi_socket_t sock,void * buf,int maxlen)
|
||
|
{
|
||
|
int iReceived;
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
iReceived = ::recv(sock,(char *)buf,maxlen,0);
|
||
|
#else
|
||
|
iReceived = ::recv(sock,buf,maxlen,MSG_NOSIGNAL);
|
||
|
#endif
|
||
|
g_uIncomingTraffic+=iReceived;
|
||
|
return iReceived;
|
||
|
};
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_getsockopt
|
||
|
//
|
||
|
// Standard getsockopt() call. Returns false in case of failure.
|
||
|
// You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_getsockopt(kvi_socket_t sock,int level,int optname,void *optval,int *optlen)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return (::getsockopt(sock,level,optname,(char FAR *)optval,optlen) == 0);
|
||
|
#else
|
||
|
return (::getsockopt(sock,level,optname,optval,(socklen_t *)optlen) == 0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_setsockopt
|
||
|
//
|
||
|
// Standard setsockopt() call. Returns false in case of failure.
|
||
|
// You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_setsockopt(kvi_socket_t sock,int level,int optname,const void *optval,int optlen)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return (::setsockopt(sock,level,optname,(char FAR *)optval,optlen) == 0);
|
||
|
#else
|
||
|
return (::setsockopt(sock,level,optname,optval,optlen) == 0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_disableNagle
|
||
|
//
|
||
|
// Disables the nagle algorithm (sets TCP_NODELAY)
|
||
|
//
|
||
|
|
||
|
/*
|
||
|
unused for now
|
||
|
inline bool kvi_socket_disableNagle(kvi_socket_t sock)
|
||
|
{
|
||
|
int opt = 1;
|
||
|
return kvi_socket_setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof(opt));
|
||
|
};
|
||
|
*/
|
||
|
|
||
|
//================================================================================================
|
||
|
// kvi_socket_getsockname
|
||
|
//
|
||
|
// Standard getsockname() call. Returns false in case of failure.
|
||
|
// You should check kvi_socket_errno() then.
|
||
|
//
|
||
|
|
||
|
inline bool kvi_socket_getsockname(kvi_socket_t sock,struct sockaddr * addr,int * addrlen)
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return (::getsockname(sock,addr,addrlen) == 0);
|
||
|
#else
|
||
|
return (::getsockname(sock,addr,(socklen_t *)addrlen) == 0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
inline int kvi_socket_error()
|
||
|
{
|
||
|
#ifdef COMPILE_ON_WINDOWS
|
||
|
return WSAGetLastError();
|
||
|
#else
|
||
|
return errno;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif //_KVI_SOCKET_H_
|