2020-05-25 08:04:30 +00:00
/*
* $ Id $
*
Copyright ( c ) 2016 - 2020 Chung , Hyung - Hwan . All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE AUTHOR " AS IS " AND ANY EXPRESS OR
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WAfRRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "http-prv.h"
2020-07-24 17:29:52 +00:00
# include <mio-path.h>
2020-05-05 15:12:08 +00:00
/* ------------------------------------------------------------------------ */
2020-05-06 09:28:36 +00:00
static int client_htrd_peek_request ( mio_htrd_t * htrd , mio_htre_t * req )
{
2020-05-25 08:04:30 +00:00
mio_svc_htts_cli_htrd_xtn_t * htrdxtn = ( mio_svc_htts_cli_htrd_xtn_t * ) mio_htrd_getxtn ( htrd ) ;
2020-05-12 11:46:00 +00:00
mio_svc_htts_cli_t * sckxtn = ( mio_svc_htts_cli_t * ) mio_dev_sck_getxtn ( htrdxtn - > sck ) ;
2020-05-20 16:14:36 +00:00
return sckxtn - > htts - > proc_req ( sckxtn - > htts , htrdxtn - > sck , req ) ;
2020-05-06 09:28:36 +00:00
}
static mio_htrd_recbs_t client_htrd_recbs =
{
client_htrd_peek_request ,
2020-05-18 08:59:25 +00:00
MIO_NULL ,
MIO_NULL
2020-05-06 09:28:36 +00:00
} ;
2020-05-12 11:46:00 +00:00
static int init_client ( mio_svc_htts_cli_t * cli , mio_dev_sck_t * sck )
2020-05-06 09:28:36 +00:00
{
2020-05-25 08:04:30 +00:00
mio_svc_htts_cli_htrd_xtn_t * htrdxtn ;
2020-05-06 09:28:36 +00:00
2020-05-12 11:46:00 +00:00
/* the htts field must be filled with the same field in the listening socket upon accept() */
MIO_ASSERT ( sck - > mio , cli - > htts ! = MIO_NULL ) ;
2020-05-12 17:53:19 +00:00
MIO_ASSERT ( sck - > mio , cli - > sck = = cli - > htts - > lsck ) ; /* the field should still point to the listner socket */
2020-05-12 11:46:00 +00:00
MIO_ASSERT ( sck - > mio , sck - > mio = = cli - > htts - > mio ) ;
2020-05-06 09:28:36 +00:00
2020-07-16 10:46:17 +00:00
cli - > sck = sck ;
cli - > htrd = MIO_NULL ;
cli - > sbuf = MIO_NULL ;
cli - > rsrc = MIO_NULL ;
/* keep this linked regardless of success or failure because the disconnect() callback
* will call fini_client ( ) . the error handler code after ' oops : ' doesn ' t get this unlinked */
MIO_SVC_HTTS_CLIL_APPEND_CLI ( & cli - > htts - > cli , cli ) ;
2020-05-12 11:46:00 +00:00
cli - > htrd = mio_htrd_open ( sck - > mio , MIO_SIZEOF ( * htrdxtn ) ) ;
if ( MIO_UNLIKELY ( ! cli - > htrd ) ) goto oops ;
2020-05-06 09:28:36 +00:00
2020-05-19 09:11:39 +00:00
/* With MIO_HTRD_TRAILERS, htrd stores trailers in a separate place.
* Otherwise , it is merged to the headers . */
/*mio_htrd_setopt (cli->htrd, MIO_HTRD_REQUEST | MIO_HTRD_TRAILERS);*/
2020-05-12 11:46:00 +00:00
cli - > sbuf = mio_becs_open ( sck - > mio , 0 , 2048 ) ;
if ( MIO_UNLIKELY ( ! cli - > sbuf ) ) goto oops ;
2020-05-16 19:12:10 +00:00
2020-05-12 11:46:00 +00:00
htrdxtn = mio_htrd_getxtn ( cli - > htrd ) ;
htrdxtn - > sck = sck ; /* TODO: remember cli instead? */
2020-05-06 09:28:36 +00:00
2020-05-12 11:46:00 +00:00
mio_htrd_setrecbs ( cli - > htrd , & client_htrd_recbs ) ;
2020-08-02 16:07:42 +00:00
mio_gettime ( sck - > mio , & cli - > last_active ) ;
MIO_DEBUG3 ( sck - > mio , " HTTS(%p) - initialized client %p socket %p \n " , cli - > htts , cli , sck ) ;
2020-05-06 09:28:36 +00:00
return 0 ;
oops :
2020-07-16 10:46:17 +00:00
/* since this function is called in the on_connect() callback,
* fini_client ( ) is eventually called by on_disconnect ( ) . i don ' t do clean - up here .
2020-05-12 11:46:00 +00:00
if ( cli - > sbuf )
2020-05-06 09:28:36 +00:00
{
2020-05-12 11:46:00 +00:00
mio_becs_close ( cli - > sbuf ) ;
cli - > sbuf = MIO_NULL ;
2020-05-06 09:28:36 +00:00
}
2020-05-12 11:46:00 +00:00
if ( cli - > htrd )
2020-05-06 09:28:36 +00:00
{
2020-05-12 11:46:00 +00:00
mio_htrd_close ( cli - > htrd ) ;
cli - > htrd = MIO_NULL ;
2020-07-16 10:46:17 +00:00
} */
2020-05-06 09:28:36 +00:00
return - 1 ;
}
2020-05-12 11:46:00 +00:00
static void fini_client ( mio_svc_htts_cli_t * cli )
2020-05-06 09:28:36 +00:00
{
2020-05-12 17:53:19 +00:00
MIO_DEBUG3 ( cli - > sck - > mio , " HTTS(%p) - finalizing client %p socket %p \n " , cli - > htts , cli , cli - > sck ) ;
2020-05-18 16:40:00 +00:00
if ( cli - > rsrc )
{
mio_svc_htts_rsrc_kill ( cli - > rsrc ) ;
cli - > rsrc = MIO_NULL ;
}
2020-05-12 11:46:00 +00:00
if ( cli - > sbuf )
2020-05-06 09:28:36 +00:00
{
2020-05-12 11:46:00 +00:00
mio_becs_close ( cli - > sbuf ) ;
cli - > sbuf = MIO_NULL ;
2020-05-06 09:28:36 +00:00
}
2020-05-18 16:40:00 +00:00
2020-05-12 11:46:00 +00:00
if ( cli - > htrd )
2020-05-06 09:28:36 +00:00
{
2020-05-12 11:46:00 +00:00
mio_htrd_close ( cli - > htrd ) ;
cli - > htrd = MIO_NULL ;
2020-05-06 09:28:36 +00:00
}
2020-05-12 11:46:00 +00:00
2020-05-25 08:04:30 +00:00
MIO_SVC_HTTS_CLIL_UNLINK_CLI_CLEAN ( cli ) ;
2020-05-12 17:53:19 +00:00
/* are these needed? not symmetrical if done here.
* these fields are copied from the listener socket upon accept .
* init_client ( ) doesn ' t fill in these fields . let ' s comment out these lines
cli - > sck = MIO_NULL ;
cli - > htts = MIO_NULL ;
*/
2020-05-06 09:28:36 +00:00
}
/* ------------------------------------------------------------------------ */
2020-05-15 06:18:49 +00:00
static int listener_on_read ( mio_dev_sck_t * sck , const void * buf , mio_iolen_t len , const mio_skad_t * srcaddr )
2020-05-05 15:12:08 +00:00
{
2020-05-15 06:18:49 +00:00
/* unlike the function name, this callback is set on both the listener and the client.
* however , it must never be triggered for the listener */
2020-05-16 19:12:10 +00:00
mio_t * mio = sck - > mio ;
2020-05-12 11:46:00 +00:00
mio_svc_htts_cli_t * cli = mio_dev_sck_getxtn ( sck ) ;
2020-05-19 18:00:49 +00:00
mio_oow_t rem ;
2020-05-15 06:18:49 +00:00
int x ;
2020-05-16 19:12:10 +00:00
MIO_ASSERT ( mio , sck ! = cli - > htts - > lsck ) ;
2020-05-18 16:40:00 +00:00
MIO_ASSERT ( mio , cli - > rsrc = = MIO_NULL ) ; /* if a resource has been set, the resource must take over this handler */
2020-05-15 06:18:49 +00:00
2020-05-16 19:12:10 +00:00
if ( len < = - 1 )
{
2020-05-20 10:25:12 +00:00
MIO_DEBUG3 ( mio , " HTTS(%p) - unable to read client %p(%d) \n " , cli - > htts , sck , ( int ) sck - > hnd ) ;
2020-05-16 19:12:10 +00:00
goto oops ;
}
2020-05-20 10:25:12 +00:00
if ( len = = 0 )
{
MIO_DEBUG3 ( mio , " HTTS(%p) - EOF on client %p(%d) \n " , cli - > htts , sck , ( int ) sck - > hnd ) ;
goto oops ;
}
2020-05-16 19:12:10 +00:00
2020-08-02 16:07:42 +00:00
mio_gettime ( mio , & cli - > last_active ) ;
2020-05-19 18:00:49 +00:00
if ( ( x = mio_htrd_feed ( cli - > htrd , buf , len , & rem ) ) < = - 1 )
2020-05-05 15:12:08 +00:00
{
2020-07-28 10:21:10 +00:00
MIO_DEBUG3 ( mio , " HTTS(%p) - feed error onto client htrd %p(%d) \n " , cli - > htts , sck , ( int ) sck - > hnd ) ;
2020-05-18 16:40:00 +00:00
goto oops ;
2020-05-15 06:18:49 +00:00
}
2020-05-05 15:12:08 +00:00
2020-05-19 18:00:49 +00:00
if ( rem > 0 )
{
if ( cli - > rsrc )
{
/* TODO store this to client buffer. once the current resource is completed, arrange to call on_read() with it */
}
else
{
/* TODO: no resource in action. so feed one more time */
}
}
2020-05-05 15:12:08 +00:00
return 0 ;
2020-05-16 19:12:10 +00:00
oops :
mio_dev_sck_halt ( sck ) ;
2020-07-28 10:21:10 +00:00
return 0 ; /* still return success here. instead call halt() */
2020-05-05 15:12:08 +00:00
}
2020-05-15 06:18:49 +00:00
static int listener_on_write ( mio_dev_sck_t * sck , mio_iolen_t wrlen , void * wrctx , const mio_skad_t * dstaddr )
2020-05-05 15:12:08 +00:00
{
2020-05-15 06:18:49 +00:00
mio_svc_htts_cli_t * cli = mio_dev_sck_getxtn ( sck ) ;
MIO_ASSERT ( sck - > mio , sck ! = cli - > htts - > lsck ) ;
2020-05-18 16:40:00 +00:00
MIO_ASSERT ( sck - > mio , cli - > rsrc = = MIO_NULL ) ; /* if a resource has been set, the resource must take over this handler */
2020-05-10 16:20:39 +00:00
return 0 ;
2020-05-05 15:12:08 +00:00
}
static void listener_on_connect ( mio_dev_sck_t * sck )
{
2020-05-12 11:46:00 +00:00
mio_svc_htts_cli_t * cli = mio_dev_sck_getxtn ( sck ) ; /* the contents came from the listening socket */
2020-05-05 15:12:08 +00:00
if ( sck - > state & MIO_DEV_SCK_ACCEPTED )
{
/* accepted a new client */
2020-05-12 17:53:19 +00:00
MIO_DEBUG3 ( sck - > mio , " HTTS(%p) - accepted... %p %d \n " , cli - > htts , sck , sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
2020-05-12 11:46:00 +00:00
if ( init_client ( cli , sck ) < = - 1 )
2020-05-05 15:12:08 +00:00
{
2020-05-24 07:13:42 +00:00
MIO_DEBUG2 ( cli - > htts - > mio , " HTTS(%p) - halting client(%p) for client intiaialization failure \n " , cli - > htts , sck ) ;
2020-05-05 15:12:08 +00:00
mio_dev_sck_halt ( sck ) ;
}
}
else if ( sck - > state & MIO_DEV_SCK_CONNECTED )
{
/* this will never be triggered as the listing socket never call mio_dev_sck_connect() */
2020-05-12 17:53:19 +00:00
MIO_DEBUG3 ( sck - > mio , " ** HTTS(%p) - connected... %p %d \n " , cli - > htts , sck , sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
}
/* MIO_DEV_SCK_CONNECTED must not be seen here as this is only for the listener socket */
}
static void listener_on_disconnect ( mio_dev_sck_t * sck )
{
2020-05-20 10:25:12 +00:00
mio_t * mio = sck - > mio ;
2020-05-12 11:46:00 +00:00
mio_svc_htts_cli_t * cli = mio_dev_sck_getxtn ( sck ) ;
2020-05-05 15:12:08 +00:00
switch ( MIO_DEV_SCK_GET_PROGRESS ( sck ) )
{
case MIO_DEV_SCK_CONNECTING :
2020-05-07 10:10:33 +00:00
/* only for connecting sockets */
2020-05-20 10:25:12 +00:00
MIO_DEBUG1 ( mio , " OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER \n " , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
case MIO_DEV_SCK_CONNECTING_SSL :
2020-05-07 10:10:33 +00:00
/* only for connecting sockets */
2020-05-20 10:25:12 +00:00
MIO_DEBUG1 ( mio , " OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER \n " , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
2020-05-07 10:10:33 +00:00
case MIO_DEV_SCK_CONNECTED :
/* only for connecting sockets */
2020-05-20 10:25:12 +00:00
MIO_DEBUG1 ( mio , " OUTGOING CLIENT CONNECTION GOT TORN DOWN %p(%d)....... \n " , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
2020-05-07 10:10:33 +00:00
case MIO_DEV_SCK_LISTENING :
2020-05-20 10:25:12 +00:00
MIO_DEBUG2 ( mio , " LISTNER SOCKET %p(%d) - SHUTTUING DOWN \n " , sck , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
2020-05-12 17:53:19 +00:00
case MIO_DEV_SCK_ACCEPTING_SSL : /* special case. */
/* this progress code indicates that the ssl-level accept failed.
* on_disconnected ( ) with this code is called without corresponding on_connect ( ) .
* the cli extension are is not initialized yet */
2020-05-20 10:25:12 +00:00
MIO_ASSERT ( mio , sck ! = cli - > sck ) ;
MIO_ASSERT ( mio , cli - > sck = = cli - > htts - > lsck ) ; /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */
MIO_DEBUG2 ( mio , " LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p \n " , sck , ( int ) sck - > hnd ) ;
2020-05-12 17:53:19 +00:00
return ;
2020-05-05 15:12:08 +00:00
case MIO_DEV_SCK_ACCEPTED :
2020-05-07 10:10:33 +00:00
/* only for sockets accepted by the listeners. will never come here because
* the disconnect call for such sockets have been changed in listener_on_connect ( ) */
2020-05-20 10:25:12 +00:00
MIO_DEBUG2 ( mio , " ACCEPTED CLIENT SOCKET %p(%d) GOT DISCONNECTED....... \n " , sck , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
default :
2020-05-20 10:25:12 +00:00
MIO_DEBUG2 ( mio , " SOCKET %p(%d) DISCONNECTED AFTER ALL....... \n " , sck , ( int ) sck - > hnd ) ;
2020-05-05 15:12:08 +00:00
break ;
}
2020-05-12 17:53:19 +00:00
if ( sck = = cli - > htts - > lsck )
{
/* the listener socket has these fields set to NULL */
2020-05-20 10:25:12 +00:00
MIO_ASSERT ( mio , cli - > htrd = = MIO_NULL ) ;
MIO_ASSERT ( mio , cli - > sbuf = = MIO_NULL ) ;
2020-05-07 04:32:32 +00:00
2020-05-20 10:25:12 +00:00
MIO_DEBUG2 ( mio , " HTTS(%p) - listener socket disconnect %p \n " , cli - > htts , sck ) ;
2020-07-28 10:21:10 +00:00
printf ( " listener socket disconnect..................sck %p %d \n " , sck , sck - > hnd ) ;
2020-05-12 17:53:19 +00:00
cli - > htts - > lsck = MIO_NULL ; /* let the htts service forget about this listening socket */
}
else
{
/* client socket */
2020-05-20 10:25:12 +00:00
MIO_DEBUG2 ( mio , " HTTS(%p) - client socket disconnect %p \n " , cli - > htts , sck ) ;
MIO_ASSERT ( mio , cli - > sck = = sck ) ;
2020-05-12 17:53:19 +00:00
fini_client ( cli ) ;
}
2020-05-05 15:12:08 +00:00
}
2020-08-01 15:56:53 +00:00
/* ------------------------------------------------------------------------ */
2020-08-02 16:07:42 +00:00
# define MAX_CLIENT_IDLE 10
static void halt_idle_clients ( mio_t * mio , const mio_ntime_t * now , mio_tmrjob_t * job )
{
/* TODO: this idle client detector is far away from being accurate.
* enhance htrd to specify timeout on feed ( ) and utilize it . . .
* and remove this timer job */
mio_svc_htts_t * htts = ( mio_svc_htts_t * ) job - > ctx ;
mio_svc_htts_cli_t * cli ;
mio_ntime_t t ;
static mio_ntime_t max_client_idle = { MAX_CLIENT_IDLE , 0 } ;
for ( cli = MIO_SVC_HTTS_CLIL_FIRST_CLI ( & htts - > cli ) ; ! MIO_SVC_HTTS_CLIL_IS_NIL_CLI ( & htts - > cli , cli ) ; cli = cli - > cli_next )
{
if ( ! cli - > rsrc )
{
mio_ntime_t t ;
MIO_SUB_NTIME ( & t , now , & cli - > last_active ) ;
if ( MIO_CMP_NTIME ( & t , & max_client_idle ) > = 0 )
{
MIO_DEBUG3 ( mio , " HTTS(%p) - Halting idle client socket %p(client=%p) \n " , htts , cli - > sck , cli ) ;
mio_dev_sck_halt ( cli - > sck ) ;
}
}
}
MIO_INIT_NTIME ( & t , MAX_CLIENT_IDLE , 0 ) ;
MIO_ADD_NTIME ( & t , & t , now ) ;
if ( mio_schedtmrjobat ( mio , & t , halt_idle_clients , & htts - > idle_tmridx , htts ) < = - 1 )
{
MIO_INFO1 ( mio , " HTTS(%p) - unable to reschedule idle client detector. continuting \n " , htts ) ;
}
}
2020-05-05 15:12:08 +00:00
/* ------------------------------------------------------------------------ */
2020-07-19 18:55:35 +00:00
mio_svc_htts_t * mio_svc_htts_start ( mio_t * mio , mio_dev_sck_bind_t * sck_bind , mio_svc_htts_proc_req_t proc_req )
2020-05-05 15:12:08 +00:00
{
mio_svc_htts_t * htts = MIO_NULL ;
union
{
mio_dev_sck_make_t m ;
mio_dev_sck_listen_t l ;
} info ;
2020-05-12 11:46:00 +00:00
mio_svc_htts_cli_t * cli ;
2020-05-05 15:12:08 +00:00
htts = ( mio_svc_htts_t * ) mio_callocmem ( mio , MIO_SIZEOF ( * htts ) ) ;
if ( MIO_UNLIKELY ( ! htts ) ) goto oops ;
htts - > mio = mio ;
htts - > svc_stop = mio_svc_htts_stop ;
2020-05-20 16:14:36 +00:00
htts - > proc_req = proc_req ;
2020-08-02 16:07:42 +00:00
htts - > idle_tmridx = MIO_TMRIDX_INVALID ;
2020-05-05 15:12:08 +00:00
MIO_MEMSET ( & info , 0 , MIO_SIZEOF ( info ) ) ;
2020-07-19 18:55:35 +00:00
switch ( mio_skad_family ( & sck_bind - > localaddr ) )
2020-05-05 15:12:08 +00:00
{
case MIO_AF_INET :
info . m . type = MIO_DEV_SCK_TCP4 ;
break ;
case MIO_AF_INET6 :
info . m . type = MIO_DEV_SCK_TCP6 ;
break ;
default :
2020-07-26 09:21:05 +00:00
/*mio_seterrnum (mio, MIO_EINVAL);
goto oops ; */
info . m . type = MIO_DEV_SCK_QX ;
break ;
2020-05-05 15:12:08 +00:00
2020-07-26 09:21:05 +00:00
}
2020-07-29 10:04:14 +00:00
info . m . options = MIO_DEV_SCK_MAKE_LENIENT ;
2020-05-05 15:12:08 +00:00
info . m . on_write = listener_on_write ;
info . m . on_read = listener_on_read ;
info . m . on_connect = listener_on_connect ;
info . m . on_disconnect = listener_on_disconnect ;
2020-05-12 11:46:00 +00:00
htts - > lsck = mio_dev_sck_make ( mio , MIO_SIZEOF ( * cli ) , & info . m ) ;
2020-05-05 15:12:08 +00:00
if ( ! htts - > lsck ) goto oops ;
2020-05-12 11:46:00 +00:00
/* the name 'cli' for the listening socket is awkard.
2020-07-28 10:21:10 +00:00
* the listening socket will use the htts and sck fields for tracking only .
2020-05-12 11:46:00 +00:00
* each accepted client socket gets the extension size for this size as well .
* most of other fields are used for client management */
cli = ( mio_svc_htts_cli_t * ) mio_dev_sck_getxtn ( htts - > lsck ) ;
cli - > htts = htts ;
2020-05-12 17:53:19 +00:00
cli - > sck = htts - > lsck ;
2020-05-05 15:12:08 +00:00
2020-07-26 09:21:05 +00:00
if ( htts - > lsck - > type ! = MIO_DEV_SCK_QX )
{
if ( mio_dev_sck_bind ( htts - > lsck , sck_bind ) < = - 1 ) goto oops ;
2020-05-05 15:12:08 +00:00
2020-07-26 09:21:05 +00:00
MIO_MEMSET ( & info , 0 , MIO_SIZEOF ( info ) ) ;
info . l . backlogs = 4096 ;
2020-08-01 15:56:53 +00:00
MIO_INIT_NTIME ( & info . l . accept_tmout , 5 , 1 ) ; /* usedd for ssl accept */
2020-07-26 09:21:05 +00:00
if ( mio_dev_sck_listen ( htts - > lsck , & info . l ) < = - 1 ) goto oops ;
}
2020-05-05 15:12:08 +00:00
2020-05-07 10:10:33 +00:00
mio_fmttobcstr ( htts - > mio , htts - > server_name_buf , MIO_COUNTOF ( htts - > server_name_buf ) , " %s-%d.%d.%d " ,
MIO_PACKAGE_NAME , ( int ) MIO_PACKAGE_VERSION_MAJOR , ( int ) MIO_PACKAGE_VERSION_MINOR , ( int ) MIO_PACKAGE_VERSION_PATCH ) ;
htts - > server_name = htts - > server_name_buf ;
2020-08-02 16:07:42 +00:00
2020-05-05 15:12:08 +00:00
MIO_SVCL_APPEND_SVC ( & mio - > actsvc , ( mio_svc_t * ) htts ) ;
2020-05-25 08:04:30 +00:00
MIO_SVC_HTTS_CLIL_INIT ( & htts - > cli ) ;
2020-05-07 10:10:33 +00:00
2020-05-15 06:18:49 +00:00
MIO_DEBUG3 ( mio , " HTTS - STARTED SERVICE %p - LISTENER SOCKET %p(%d) \n " , htts , htts - > lsck , ( int ) htts - > lsck - > hnd ) ;
2020-08-02 16:07:42 +00:00
{
mio_ntime_t t ;
MIO_INIT_NTIME ( & t , MAX_CLIENT_IDLE , 0 ) ;
if ( mio_schedtmrjobafter ( mio , & t , halt_idle_clients , & htts - > idle_tmridx , htts ) < = - 1 )
{
MIO_INFO1 ( mio , " HTTS(%p) - unable to schedule idle client detector. continuting \n " , htts ) ;
/* don't care about failure */
}
}
2020-05-05 15:12:08 +00:00
return htts ;
oops :
if ( htts )
{
if ( htts - > lsck ) mio_dev_sck_kill ( htts - > lsck ) ;
mio_freemem ( mio , htts ) ;
}
return MIO_NULL ;
}
void mio_svc_htts_stop ( mio_svc_htts_t * htts )
{
mio_t * mio = htts - > mio ;
2020-05-15 06:18:49 +00:00
MIO_DEBUG3 ( mio , " HTTS - STOPPING SERVICE %p - LISTENER SOCKET %p(%d) \n " , htts , htts - > lsck , ( int ) ( htts - > lsck ? htts - > lsck - > hnd : - 1 ) ) ;
2020-05-07 10:10:33 +00:00
/* htts->lsck may be null if the socket has been destroyed for operational error and
* forgotten in the disconnect callback thereafter */
2020-05-05 15:12:08 +00:00
if ( htts - > lsck ) mio_dev_sck_kill ( htts - > lsck ) ;
2020-05-07 10:10:33 +00:00
2020-05-25 08:04:30 +00:00
while ( ! MIO_SVC_HTTS_CLIL_IS_EMPTY ( & htts - > cli ) )
2020-05-12 11:46:00 +00:00
{
2020-05-25 08:04:30 +00:00
mio_svc_htts_cli_t * cli = MIO_SVC_HTTS_CLIL_FIRST_CLI ( & htts - > cli ) ;
2020-05-12 11:46:00 +00:00
mio_dev_sck_kill ( cli - > sck ) ;
}
2020-05-05 15:12:08 +00:00
MIO_SVCL_UNLINK_SVC ( htts ) ;
2020-05-12 11:46:00 +00:00
if ( htts - > server_name & & htts - > server_name ! = htts - > server_name_buf ) mio_freemem ( mio , htts - > server_name ) ;
2020-08-02 16:07:42 +00:00
if ( htts - > idle_tmridx ! = MIO_TMRIDX_INVALID ) mio_deltmrjob ( mio , htts - > idle_tmridx ) ;
2020-05-05 15:12:08 +00:00
mio_freemem ( mio , htts ) ;
}
2020-05-07 10:10:33 +00:00
int mio_svc_htts_setservernamewithbcstr ( mio_svc_htts_t * htts , const mio_bch_t * name )
{
mio_t * mio = htts - > mio ;
mio_bch_t * tmp ;
if ( mio_copy_bcstr ( htts - > server_name_buf , MIO_COUNTOF ( htts - > server_name_buf ) , name ) = = mio_count_bcstr ( name ) )
{
tmp = htts - > server_name_buf ;
}
else
{
tmp = mio_dupbcstr ( mio , name , MIO_NULL ) ;
if ( ! tmp ) return - 1 ;
}
if ( htts - > server_name & & htts - > server_name ! = htts - > server_name_buf ) mio_freemem ( mio , htts - > server_name ) ;
htts - > server_name = tmp ;
return 0 ;
}
2020-05-05 15:12:08 +00:00
2020-05-08 09:48:26 +00:00
/* ----------------------------------------------------------------- */
2020-05-18 16:40:00 +00:00
mio_svc_htts_rsrc_t * mio_svc_htts_rsrc_make ( mio_svc_htts_t * htts , mio_oow_t rsrc_size , mio_svc_htts_rsrc_on_kill_t on_kill )
2020-05-07 15:47:33 +00:00
{
mio_t * mio = htts - > mio ;
2020-05-08 09:48:26 +00:00
mio_svc_htts_rsrc_t * rsrc ;
2020-05-18 16:40:00 +00:00
rsrc = mio_callocmem ( mio , rsrc_size ) ;
2020-05-08 09:48:26 +00:00
if ( MIO_UNLIKELY ( ! rsrc ) ) return MIO_NULL ;
rsrc - > htts = htts ;
2020-05-18 16:40:00 +00:00
rsrc - > rsrc_size = rsrc_size ;
rsrc - > rsrc_refcnt = 0 ;
rsrc - > rsrc_on_kill = on_kill ;
2020-05-08 09:48:26 +00:00
return rsrc ;
}
void mio_svc_htts_rsrc_kill ( mio_svc_htts_rsrc_t * rsrc )
{
mio_t * mio = rsrc - > htts - > mio ;
2020-05-18 16:40:00 +00:00
if ( rsrc - > rsrc_on_kill ) rsrc - > rsrc_on_kill ( rsrc ) ;
2020-05-08 09:48:26 +00:00
mio_freemem ( mio , rsrc ) ;
}
# if defined(MIO_HAVE_INLINE)
static MIO_INLINE void * mio_svc_htts_rsrc_getxtn ( mio_svc_htts_rsrc_t * rsrc ) { return rsrc + 1 ; }
# else
# define mio_svc_htts_rsrc_getxtn(rsrc) ((void*)((mio_svc_htts_rsrc_t*)rsrc + 1))
# endif
2020-05-12 11:46:00 +00:00
/* ----------------------------------------------------------------- */
2020-05-20 16:14:36 +00:00
2020-05-16 19:12:10 +00:00
/* ----------------------------------------------------------------- */
2020-05-12 11:46:00 +00:00
int mio_svc_htts_doproxy ( mio_svc_htts_t * htts , mio_dev_sck_t * csck , mio_htre_t * req , const mio_bch_t * upstream )
2020-05-06 09:28:36 +00:00
{
2020-05-12 11:46:00 +00:00
#if 0
2020-05-08 09:48:26 +00:00
1. attempt to connect to the proxy target . . .
2. in the mean time ,
mio_dev_watch ( csck , MIO_DEV_WATCH_UPDATE , 0 ) ; /* no input, no output watching */
3. once connected ,
mio_dev_watch ( csck , MIO_DEV_WATCH_RENEW , MIO_DEV_EVENT_IN ) ; /* enable input watching. if needed, enable output watching */
4. start proxying
2020-05-10 16:20:39 +00:00
5. if one side is stalled , donot read from another side . . . let the kernel slow the connection . . .
2020-05-08 09:48:26 +00:00
i need to know how may bytes are pending for this .
if pending too high , disable read watching . . . mio_dev_watch ( csck , MIO_DEV_WATCH_RENEW , 0 ) ;
# endif
2020-05-12 11:46:00 +00:00
return 0 ;
}
2020-05-18 16:40:00 +00:00
/* ----------------------------------------------------------------- */
void mio_svc_htts_fmtgmtime ( mio_svc_htts_t * htts , const mio_ntime_t * nt , mio_bch_t * buf , mio_oow_t len )
{
mio_ntime_t now ;
if ( ! nt )
{
mio_sys_getrealtime ( htts - > mio , & now ) ;
nt = & now ;
}
mio_fmt_http_time_to_bcstr ( nt , buf , len ) ;
}
2020-05-08 09:48:26 +00:00
2020-05-20 16:14:36 +00:00
mio_bch_t * mio_svc_htts_dupmergepaths ( mio_svc_htts_t * htts , const mio_bch_t * base , const mio_bch_t * path )
{
mio_bch_t * xpath ;
const mio_bch_t * ta [ 4 ] ;
mio_oow_t idx = 0 ;
ta [ idx + + ] = base ;
if ( path [ 0 ] ! = ' \0 ' )
{
ta [ idx + + ] = " / " ;
ta [ idx + + ] = path ;
}
ta [ idx + + ] = MIO_NULL ;
xpath = mio_dupbcstrs ( htts - > mio , ta , MIO_NULL ) ;
if ( MIO_UNLIKELY ( ! xpath ) ) return MIO_NULL ;
mio_canon_bcstr_path ( xpath , xpath , 0 ) ;
return xpath ;
}
2020-07-24 17:29:52 +00:00
int mio_svc_htts_writetosidechan ( mio_svc_htts_t * htts , const void * dptr , mio_oow_t dlen )
{
return mio_dev_sck_writetosidechan ( htts - > lsck , dptr , dlen ) ;
}