* harbour/include/hbstack.h
+ added socket error codes to HB_IOERRORS
* harbour/include/Makefile
+ harbour/include/hbsocket.ch
+ harbour/include/hbsocket.h
* harbour/source/rtl/Makefile
+ harbour/source/rtl/hbsocket.c
+ added new BSD socket functions: hb_socket*(). They should be quite
close to low level C socket interface with few modifications which
help to hide some platform differences. Unfortunately we do not use
autoconf so I had to arbitrary set which features are available
on some platforms. In practice it means that it reduces portability
to older OS-es, i.e. it should work with current Linux versions
but it will not without some modifications in macros used to control
supported features with older Linuxes using kernel 2.2 or 2.0.
The same can happen with other *nix ports like Darwin, SunOS, HP-UX
or with different versions of some Windows compilers. I also do not
know which functionality is available in OS2 GCC ports and I would
like to ask OS2 users to make tests and disable not working features.
We also need tests with HP-UX, Darwin and SunOS.
IP6 support is enabled only in *nixes. If Windows users are interested
in IP6 then please add support for it. Most of Windows compilers do
not support standard POSIX functions so I do not want to make it
myself using unknown for me API without testing.
In *nix builds PF_UNIX/PF_LOCAL sockets are also supported.
Support for other socket types can be easy added if someone is
interested in them.
The constant values used in hbsocket.ch are equal to original BSD
socket definitions. If it's necessary then it's possible to enable
their translation inside hbsocket.c code though I do not think we
will find such OS.
The list of hb_socket*() functions was designed to cover all existing
functionality in hbinet.c and socket.c. Most of functions supports
timeout parameter what effectively allows to hide direct select()
usage.
Please make test with real applications and report any problems
with hb_inet*() functions you will find.
* harbour/source/vm/hvm.c
* minor cleanup
* harbour/source/rtl/hbi18n1.c
* cleaned variable name
* harbour/source/rtl/hbinet.c
* harbour/examples/uhttpd2/socket.c
* harbour/contrib/hbssl/hbssl.c
* updated to use hb_socket*() functions
* harbour/include/hbextern.ch
* enabled HB_INET*() functions in DOS builds - they will simply return
errors
- harbour/include/hbapinet.h
- removed old header file
* harbour/source/pp/ppcore.c
! modified ENDTEXT marker to work also with comments in the same line
It's more closer to Clipper though intentionally we are not fully
CA-Cl*pper compatible here.
241 lines
5.9 KiB
C
241 lines
5.9 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
|
|
Function naming:
|
|
The intention of this library is to be as close as possible to the original
|
|
socket implementation. This supposed to be valid for function names also,
|
|
but some of the names are very platform dependent, ex., WSA*() functions.
|
|
select() function name is reserved for standard Harbour's function, so,
|
|
socket_*() prefix was used:
|
|
socket_init() - WSAStartup()
|
|
socket_exit() - WSACleanup()
|
|
socket_error() - WSALastError()
|
|
socket_select() - select()
|
|
Finally I renamed all functions to have socket_*() prefix to be more "prefix
|
|
compatible" and not to occupy a general function names like send(), bind(),
|
|
accept(), listen(), etc.:
|
|
socket_create() - socket()
|
|
socket_close() - closesocket()
|
|
socket_shutdown() - shutdown()
|
|
socket_bind() - bind()
|
|
socket_listen() - listen()
|
|
socket_accept() - accept()
|
|
socket_send() - send()
|
|
socket_recv() - recv()
|
|
socket_recv() - recv()
|
|
socket_getsockname() - getsockname()
|
|
socket_getpeername() - getpeername()
|
|
|
|
|
|
Types mapping:
|
|
SOCKET
|
|
UINT_PTR in Windows, let's map it to pointer type, and INVALID_SOCKET value to NIL
|
|
|
|
struct sockaddr
|
|
It is not only IP addresses, also can be IPX, etc. All network-host byte order
|
|
conversion should be hidden from Harbour API. So, let's map to:
|
|
{ adress_familly, ... }
|
|
AF_INET: { AF_INET, cAddr, nPort }
|
|
other: { AF_?, cAddressDump }
|
|
*/
|
|
|
|
#include "hbsocket.h"
|
|
#include "hbapiitm.h"
|
|
|
|
static int hb_parnidef( int iParam, int iValue )
|
|
{
|
|
return HB_ISNUM( iParam ) ? hb_parni( iParam ) : iValue;
|
|
}
|
|
|
|
static HB_SOCKET_T hb_parsocket( int iParam )
|
|
{
|
|
return HB_ISPOINTER( iParam ) ? ( HB_SOCKET_T ) ( HB_PTRDIFF )
|
|
hb_parptr( iParam ) : HB_NO_SOCKET;
|
|
}
|
|
|
|
static void hb_retsocket( HB_SOCKET_T hSocket )
|
|
{
|
|
if( hSocket == HB_NO_SOCKET )
|
|
hb_ret();
|
|
else
|
|
hb_retptr( ( void* ) ( HB_PTRDIFF ) hSocket );
|
|
}
|
|
|
|
static HB_SOCKET_T hb_itemGetSocket( PHB_ITEM pSocket )
|
|
{
|
|
if( pSocket && HB_IS_POINTER( pSocket ) )
|
|
return ( HB_SOCKET_T ) ( HB_PTRDIFF ) hb_itemGetPtr( pSocket );
|
|
else
|
|
return HB_NO_SOCKET;
|
|
}
|
|
|
|
HB_FUNC( SOCKET_INIT )
|
|
{
|
|
hb_retni( hb_socketInit() );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_EXIT )
|
|
{
|
|
hb_socketCleanup();
|
|
}
|
|
|
|
HB_FUNC( SOCKET_ERROR )
|
|
{
|
|
hb_retni( hb_socketGetError() );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_CREATE )
|
|
{
|
|
hb_retsocket( hb_socketOpen( hb_parnidef( 1, HB_SOCK_PF_INET ),
|
|
hb_parnidef( 2, HB_SOCK_STREAM ),
|
|
hb_parnidef( 3, HB_SOCK_IPPROTO_TCP ) ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_CLOSE )
|
|
{
|
|
hb_retni( hb_socketClose( hb_parsocket( 1 ) ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_BIND )
|
|
{
|
|
void * sa;
|
|
unsigned len;
|
|
|
|
if( hb_socketAddrFromItem( &sa, &len, hb_param( 2, HB_IT_ANY ) ) )
|
|
{
|
|
hb_retni( hb_socketBind( hb_parsocket( 1 ), sa, len ) );
|
|
hb_xfree( sa );
|
|
}
|
|
}
|
|
|
|
HB_FUNC( SOCKET_LISTEN )
|
|
{
|
|
hb_retni( hb_socketListen( hb_parsocket( 1 ), hb_parnidef( 2, 10 ) ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_ACCEPT )
|
|
{
|
|
if( HB_ISBYREF( 2 ) )
|
|
{
|
|
void * sa;
|
|
unsigned len;
|
|
PHB_ITEM pItem;
|
|
|
|
hb_retsocket( hb_socketAccept( hb_parsocket( 1 ), &sa, &len,
|
|
HB_ISNUM( 3 ) ? hb_parnint( 3 ) : -1 ) );
|
|
pItem = hb_socketAddrToItem( sa, len );
|
|
if( pItem )
|
|
{
|
|
hb_itemParamStoreForward( 2, pItem );
|
|
hb_itemRelease( pItem );
|
|
}
|
|
else
|
|
hb_stor( 2 );
|
|
|
|
if( sa )
|
|
hb_xfree( sa );
|
|
}
|
|
else
|
|
hb_retsocket( hb_socketAccept( hb_parsocket( 1 ), NULL, 0,
|
|
HB_ISNUM( 3 ) ? hb_parnint( 3 ) : -1 ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_SHUTDOWN )
|
|
{
|
|
hb_retni( hb_socketShutdown( hb_parsocket( 1 ),
|
|
hb_parnidef( 2, HB_SOCK_SHUT_RDWR ) ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_RECV )
|
|
{
|
|
char * pBuf;
|
|
long len;
|
|
|
|
len = hb_parni( 3 );
|
|
if( len <= 0 )
|
|
len = 4096;
|
|
pBuf = ( char* ) hb_xgrab( len + 1 );
|
|
len = hb_socketRecv( hb_parsocket( 1 ), pBuf, len, hb_parni( 4 ),
|
|
HB_ISNUM( 5 ) ? hb_parnint( 5 ) : -1 );
|
|
hb_retni( len );
|
|
hb_storclen( pBuf, len > 0 ? len : 0, 2 );
|
|
hb_xfree( pBuf );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_SEND )
|
|
{
|
|
hb_retni( hb_socketSend( hb_parsocket( 1 ), hb_parc( 2 ), hb_parclen( 2 ),
|
|
hb_parni( 4 ), HB_ISNUM( 5 ) ? hb_parnint( 5 ) : -1 ) );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_GETSOCKNAME )
|
|
{
|
|
void * sa;
|
|
unsigned len;
|
|
int iRet;
|
|
|
|
iRet = hb_socketGetSockName( hb_parsocket( 1 ), &sa, &len );
|
|
hb_retni( iRet );
|
|
if( HB_ISBYREF( 2 ) )
|
|
{
|
|
PHB_ITEM pItem = hb_socketAddrToItem( sa, len );
|
|
if( pItem )
|
|
{
|
|
hb_itemParamStoreForward( 2, pItem );
|
|
hb_itemRelease( pItem );
|
|
}
|
|
else
|
|
hb_stor( 2 );
|
|
}
|
|
if( sa )
|
|
hb_xfree( sa );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_GETPEERNAME )
|
|
{
|
|
void * sa;
|
|
unsigned len;
|
|
int iRet;
|
|
|
|
iRet = hb_socketGetPeerName( hb_parsocket( 1 ), &sa, &len );
|
|
hb_retni( iRet );
|
|
if( HB_ISBYREF( 2 ) )
|
|
{
|
|
PHB_ITEM pItem = hb_socketAddrToItem( sa, len );
|
|
if( pItem )
|
|
{
|
|
hb_itemParamStoreForward( 2, pItem );
|
|
hb_itemRelease( pItem );
|
|
}
|
|
else
|
|
hb_stor( 2 );
|
|
}
|
|
if( sa )
|
|
hb_xfree( sa );
|
|
}
|
|
|
|
HB_FUNC( SOCKET_CONNECT )
|
|
{
|
|
void * sa;
|
|
unsigned len;
|
|
|
|
if( hb_socketAddrFromItem( &sa, &len, hb_param( 2, HB_IT_ANY ) ) )
|
|
{
|
|
hb_retni( hb_socketConnect( hb_parsocket( 1 ), sa, len,
|
|
HB_ISNUM( 3 ) ? hb_parnint( 3 ) : -1 ) );
|
|
hb_xfree( sa );
|
|
}
|
|
}
|
|
|
|
HB_FUNC( SOCKET_SELECT )
|
|
{
|
|
hb_retni( hb_socketSelect( hb_param( 1, HB_IT_ARRAY ), HB_ISBYREF( 1 ),
|
|
hb_param( 2, HB_IT_ARRAY ), HB_ISBYREF( 2 ),
|
|
hb_param( 3, HB_IT_ARRAY ), HB_ISBYREF( 3 ),
|
|
HB_ISNUM( 4 ) ? hb_parnint( 4 ) : -1,
|
|
hb_itemGetSocket ) );
|
|
}
|