2010-06-10 00:03 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)

* examples/uhttpd2/umain.prg
  * examples/uhttpd2/uhttpd2.hbp
  - examples/uhttpd2/socket.c
    + Changed to use core SOCKET API.

  * examples/uhttpd2/run.prg
    + Displays port it listens on.

  * examples/httpsrv/uhttpd.prg
    + Using hbsocket.ch constant instead of local one.
This commit is contained in:
Viktor Szakats
2010-06-09 22:04:01 +00:00
parent ea7e1d15b9
commit b602644e09
6 changed files with 55 additions and 330 deletions

View File

@@ -16,6 +16,18 @@
The license applies to all entries newer than 2009-04-28.
*/
2010-06-10 00:03 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* examples/uhttpd2/umain.prg
* examples/uhttpd2/uhttpd2.hbp
- examples/uhttpd2/socket.c
+ Changed to use core SOCKET API.
* examples/uhttpd2/run.prg
+ Displays port it listens on.
* examples/httpsrv/uhttpd.prg
+ Using hbsocket.ch constant instead of local one.
2010-06-09 23:38 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* include/hbsocket.ch
+ Added address info array positions.
@@ -35,7 +47,7 @@
* examples/httpsrv/uhttpd.hbp
* examples/httpsrv/uhttpd.prg
- examples/httpsrv/socket.c
+ Changed to use new natic SOCKET API.
+ Changed to use new native SOCKET API.
2010-06-09 22:38 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* utils/hbmk2/hbmk2.prg

View File

@@ -117,8 +117,6 @@
#define APP_VER_NUM "0.4.4"
#define APP_VERSION APP_VER_NUM + APP_GD_SUPPORT + APP_DT_SUPPORT
#define AF_INET 2
// default values - they can changes using line command switch or ini file
#define START_RUNNING_THREADS 6 // Start threads to serve connections
@@ -533,7 +531,7 @@ FUNCTION MAIN( ... )
// --------------------------------------------------------------------------
hListen := hb_socketOpen()
IF ! hb_socketBind( hListen, { AF_INET, "0.0.0.0", nPort } )
IF ! hb_socketBind( hListen, { HB_SOCKET_AF_INET, "0.0.0.0", nPort } )
? "bind() error", hb_socketGetError()
ELSEIF ! hb_socketListen( hListen )
? "listen() error", hb_socketGetError()

View File

@@ -92,6 +92,8 @@ LOCAL oServer
"/app/*" => {{|x| UProcWidgets(x, s_aMap)}, .T.}, ;
"/*" => {{|| URedirect("/app/login")}, .F.}}
? "Listening on port:", oServer:nPort
IF ! oServer:Run()
? "Server error:", oServer:cError
RETURN 1

View File

@@ -1,281 +0,0 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
* socket API
*
* Copyright 2009 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* www - http://harbour-project.org
*
* 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, or (at your option)
* 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
/*
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 HB_SOCKET hb_parsocket( int iParam )
{
return HB_ISPOINTER( iParam ) ? ( HB_SOCKET ) ( HB_PTRDIFF )
hb_parptr( iParam ) : HB_NO_SOCKET;
}
static void hb_retsocket( HB_SOCKET hSocket )
{
if( hSocket != HB_NO_SOCKET )
hb_retptr( ( void * ) ( HB_PTRDIFF ) hSocket );
}
static HB_SOCKET hb_itemGetSocket( PHB_ITEM pSocket )
{
if( pSocket && HB_IS_POINTER( pSocket ) )
return ( HB_SOCKET ) ( 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_SOCKET_PF_INET ),
hb_parnidef( 2, HB_SOCKET_PT_STREAM ),
hb_parnidef( 3, HB_SOCKET_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_SOCKET_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 ) );
}

View File

@@ -3,7 +3,10 @@
#
-ouhttpd2
*.prg
*.c
app.prg
uhbext.prg
umain.prg
uwidgets.prg
-mt
-gui

View File

@@ -7,6 +7,8 @@
#include "fileio.ch"
#include "error.ch"
#include "hbsocket.ch"
#pragma -kM+
/*
@@ -18,7 +20,6 @@
*/
#define AF_INET 2
#define THREAD_COUNT_PREALLOC 0
#define THREAD_COUNT_MAX 50
#define SESSION_TIMEOUT 600
@@ -30,18 +31,6 @@ THREAD STATIC s_cResult, s_nStatusCode, s_aHeader, s_lSessionDestroy
MEMVAR server, get, post, cookie, session
INIT PROC SocketInit()
IF socket_init() != 0
? "socket_init() error"
ENDIF
RETURN
EXIT PROC Socketxit()
socket_exit()
RETURN
CLASS UHttpd
// Settings
DATA nPort INIT 80
@@ -111,24 +100,24 @@ LOCAL nWaiters
Self:hmtxLog := hb_mutexCreate()
Self:hmtxSession := hb_mutexCreate()
IF (Self:hListen := socket_create()) == NIL
Self:cError := "Socket create error " + LTRIM(STR(socket_error()))
IF Empty(Self:hListen := hb_socketOpen())
Self:cError := "Socket create error " + LTRIM(STR(hb_socketGetError()))
FCLOSE(Self:hErrorLog)
FCLOSE(Self:hAccessLog)
RETURN .F.
ENDIF
IF socket_bind(Self:hListen, {AF_INET, Self:cBindAddress, Self:nPort}) == -1
Self:cError := "Bind error " + LTRIM(STR(socket_error()))
socket_close(Self:hListen)
IF !hb_socketBind(Self:hListen, {HB_SOCKET_AF_INET, Self:cBindAddress, Self:nPort})
Self:cError := "Bind error " + LTRIM(STR(hb_socketGetError()))
hb_socketClose(Self:hListen)
FCLOSE(Self:hErrorLog)
FCLOSE(Self:hAccessLog)
RETURN .F.
ENDIF
IF socket_listen(Self:hListen) == -1
Self:cError := "Listen error " + LTRIM(STR(socket_error()))
socket_close(Self:hListen)
IF !hb_socketListen(Self:hListen)
Self:cError := "Listen error " + LTRIM(STR(hb_socketGetError()))
hb_socketClose(Self:hListen)
FCLOSE(Self:hErrorLog)
FCLOSE(Self:hAccessLog)
RETURN .F.
@@ -143,10 +132,10 @@ LOCAL nWaiters
Self:aSession := {=>}
DO WHILE .T.
IF (nI := socket_select({Self:hListen},,, 1000)) > 0
hSocket := socket_accept(Self:hListen)
IF (nI := hb_socketSelect({Self:hListen},,,,,, 1000)) > 0
hSocket := hb_socketAccept(Self:hListen)
IF hSocket == NIL
Self:LogError("[error] Accept error " + LTRIM(STR(socket_error())))
Self:LogError("[error] Accept error " + LTRIM(STR(hb_socketGetError())))
ELSE
hb_mutexQueueInfo( Self:hmtxQueue, @nWaiters )
? "New connection", hSocket
@@ -169,7 +158,7 @@ LOCAL nWaiters
ENDIF
ENDIF
ENDDO
socket_close(Self:hListen)
hb_socketClose(Self:hListen)
// End child threads
hb_mutexLock(Self:hmtxSession)
@@ -229,8 +218,9 @@ LOCAL hSocket, cRequest, cSend, aI, nLen, nI, nReqLen, cBuf
cRequest := ""
nLen := 1
DO WHILE AT(CR_LF + CR_LF, cRequest) == 0 .AND. nLen > 0
IF (nI := socket_select({hSocket},,, 10000)) > 0 /* Timeout */
nLen := socket_recv(hSocket, @cBuf)
IF (nI := hb_socketSelect({hSocket},,,,,, 10000)) > 0 /* Timeout */
cBuf := Space( 1 )
nLen := hb_socketRecv(hSocket, @cBuf)
cRequest += cBuf
ELSE
nLen := 0
@@ -239,7 +229,7 @@ LOCAL hSocket, cRequest, cSend, aI, nLen, nI, nReqLen, cBuf
ENDDO
IF nLen == -1
? "recv() error:", socket_error()
? "recv() error:", hb_socketGetError()
ELSEIF nLen == 0 /* connection closed */
ELSE
@@ -253,15 +243,15 @@ LOCAL hSocket, cRequest, cSend, aI, nLen, nI, nReqLen, cBuf
s_aHeader := {}
s_nStatusCode := 200
IF socket_getpeername(hSocket, @aI) != -1
server["REMOTE_ADDR"] := aI[2]
IF !Empty( aI := hb_socketGetPeerName(hSocket))
server["REMOTE_ADDR"] := aI[HB_SOCKET_ADINFO_ADDRESS]
server["REMOTE_HOST"] := server["REMOTE_ADDR"] // no reverse DNS
server["REMOTE_PORT"] := aI[3]
server["REMOTE_PORT"] := aI[HB_SOCKET_ADINFO_PORT]
ENDIF
IF socket_getsockname(hSocket, @aI) != -1
server["SERVER_ADDR"] := aI[2]
server["SERVER_PORT"] := aI[3]
IF !Empty( aI := hb_socketGetSockName(hSocket))
server["SERVER_ADDR"] := aI[HB_SOCKET_ADINFO_ADDRESS]
server["SERVER_PORT"] := aI[HB_SOCKET_ADINFO_PORT]
ENDIF
? LEFT(cRequest, AT(CR_LF + CR_LF, cRequest) + 1)
@@ -273,12 +263,13 @@ LOCAL hSocket, cRequest, cSend, aI, nLen, nI, nReqLen, cBuf
/* receive query body */
DO WHILE LEN(cRequest) < nReqLen .AND. nLen > 0
nLen := socket_recv(hSocket, @cBuf)
cBuf := Space( 1 )
nLen := hb_socketRecv(hSocket, @cBuf)
cRequest += cBuf
ENDDO
IF nLen == -1
? "recv() error:", socket_error()
? "recv() error:", hb_socketGetError()
ELSEIF nLen == 0 /* connection closed */
ELSE
? cRequest
@@ -315,8 +306,8 @@ LOCAL hSocket, cRequest, cSend, aI, nLen, nI, nReqLen, cBuf
ENDIF
ENDIF
? "Close connection1", hSocket
socket_shutdown(hSocket)
socket_close(hSocket)
hb_socketShutdown(hSocket)
hb_socketClose(hSocket)
END SEQUENCE
ENDDO
DBCLOSEALL()
@@ -402,8 +393,8 @@ LOCAL nI, cMount, cPath, cSID, hmtx, aData, bEval
IF LOWER(UGetHeader("Connection")) == "close" .OR. server["SERVER_PROTOCOL"] == "HTTP/1.0"
? "Close connection2", hSocket
socket_shutdown(hSocket)
socket_close(hSocket)
hb_socketShutdown(hSocket)
hb_socketClose(hSocket)
ELSE
/* pass connection to common queue */
hb_mutexNotify(oServer:hmtxQueue, {hSocket, cBuffer})
@@ -639,8 +630,8 @@ LOCAL cSend, nLen, cBuf
// ? cSend
DO WHILE LEN(cSend) > 0
IF (nLen := socket_send(hSocket, cSend)) == -1
? "send() error:", socket_error(), hSocket
IF (nLen := hb_socketSend(hSocket, cSend)) == -1
? "send() error:", hb_socketGetError(), hSocket
EXIT
ELSEIF nLen > 0
cSend := SUBSTR(cSend, nLen + 1)