Exemplo n.º 1
0
/**--------------------------------------------------------------------------
 * update  NOT ALLOWED.
 * \param   L    The lua state.
 * \lparam  Http.Message instance.
 * \lparam  key   string/integer
 * \lparam  value LuaType
 * \return  int    # of values pushed onto the stack.
 * --------------------------------------------------------------------------*/
static int
lt_htp_str__newindex( lua_State *L )
{
	t_htp_str_check_ud( L, -3, 1 );

	return t_push_error( L, "Can't change values in `T.Http.Stream`" );
}
Exemplo n.º 2
0
/**--------------------------------------------------------------------------
 * Access Field Values in T.Http.Message by accessing proxy table.
 * \param   L    The lua state.
 * \lparam  Http.Message instance.
 * \lparam  key   string/integer
 * \lparam  value LuaType
 * \return  int    # of values pushed onto the stack.
 * --------------------------------------------------------------------------*/
static int
lt_htp_str__index( lua_State *L )
{
	struct t_htp_str *s = t_htp_str_check_ud( L, -2, 1 );

	lua_rawgeti( L, LUA_REGISTRYINDEX, s->pR );  // fetch the proxy table
	lua_pushvalue( L, -2 );                      // repush the key
	lua_gettable( L, -2 );
	return 1;
}
Exemplo n.º 3
0
/**--------------------------------------------------------------------------
 * Handle incoming chunks from T.Http.Connection socket.
 * Called anytime the client socket returns from the poll for read event.
 * \param   L     lua Virtual Machine.
 * \lparam  userdata  struct t_htp_con.
 * \return  int    # of values pushed onto the stack.
 *  -------------------------------------------------------------------------*/
int
t_htp_con_rcv( lua_State *L )
{
	struct t_htp_con *c    = t_htp_con_check_ud( L, 1, 1 );
	struct t_htp_str *s;
	int               rcvd;
	int               res;   // return result

	// read
	rcvd = t_net_tcp_recv( L, c->sck, &(c->buf[ c->read ]), BUFSIZ - c->read );
	printf( "RCVD: %d bytes\n", rcvd );

	if (! rcvd)    // peer has closed
		return lt_htp_con__gc( L );
	// negotiate which stream object is responsible
	// if HTTP1.0 or HTTP1.1 this is the last, HTTP2.0 has a stream identifier
	lua_rawgeti( L, LUA_REGISTRYINDEX, c->sR );
	lua_rawgeti( L, -1, c->cnt );         // S:c,sR,s
	if (lua_isnoneornil( L, -1 ))
	{          // create new stream and put into stream table
		lua_pop( L, 1 );                   // pop nil( failed stream )
		s = t_htp_str_create_ud( L, c );   // S:c,sR,str
		lua_rawgeti( L, LUA_REGISTRYINDEX, s->pR );
		lua_pushstring( L, "connection" );
		lua_pushvalue( L, -1 );            // S:c,sR.str,pR,'connection',c
		lua_rawset( L, -3 );
		lua_pop( L, 1 );                   // remove s->pR
		lua_rawseti( L, -2, c->cnt );      // S:c,sR
		lua_rawgeti( L, -1, c->cnt );      // S:c,sR,str
	}
	else
	{
		s = t_htp_str_check_ud( L, -1, 0 );
	}
	lua_remove( L, -2 );       // pop the stream table

	//printf( "Received %d  \n'%s'\n", rcvd, &(m->buf[ m->read ]) );
	// TODO: set or reset c-read

	c->b = &( c->buf[ 0 ] );

	res = t_htp_str_rcv( L, s, c->read + rcvd );
	switch (res)
	{
		case 0:
			c->read = 0;
		default:
			break;
	}

	return 0;
}
Exemplo n.º 4
0
/**--------------------------------------------------------------------------
 * Write a response to the T.Http.Message.
 * \param   L    The lua state.
 * \lparam  Http.Message instance.
 * \lparam  string.
 * \return  int    # of values pushed onto the stack.
 * --------------------------------------------------------------------------*/
static int
lt_htp_str_write( lua_State *L )
{
	struct t_htp_str *s   = t_htp_str_check_ud( L, 1, 1 );
	size_t            sz;
	char             *b;
	size_t            c   = 0;
	luaL_Buffer       lB;
	luaL_buffinit( L, &lB );

	luaL_checklstring( L, 2, &sz );

	// this assumes first ever call is write -> chunked
	if (T_HTP_STR_SEND != s->state)
	{
		luaL_buffinit( L, &lB );
		c = t_htp_str_formHeader( L, &lB, s, 200, NULL, 0, 0 );
		b = luaL_prepbuffer( &lB );
		c = sprintf( b, "%zx\r\n", sz );
		luaL_addsize( &lB, c );
		lua_pushvalue( L, 2 );
		luaL_addvalue( &lB );
		luaL_addlstring( &lB, "\r\n", 2 );
		luaL_pushresult( &lB );
		s->state = T_HTP_STR_SEND;
	}
	else
	{
		// if the response Content-length is not known when we are sending
		// the encoding must be chunked
		if (! s->rsCl)
		{
			luaL_buffinit( L, &lB );
			b = luaL_prepbuffer( &lB );
			c = sprintf( b, "%zx\r\n", sz );
			luaL_addsize( &lB, c );
			lua_pushvalue( L, 2 );
			luaL_addvalue( &lB );
			luaL_addlstring( &lB, "\r\n", 2 );
			luaL_pushresult( &lB );
		}
		else
			lua_pushvalue( L, 2 );
	}
	// TODO: 
	t_htp_str_addbuffer( L, s, lB.n, 0 );

	return 0;
}
Exemplo n.º 5
0
/**--------------------------------------------------------------------------
 * Sets the onData method in T.Http.Message.
 * \param   L    The lua state.
 * \lparam  Http.Message instance.
 * \lparam  function to be executed when body data arrives on connection.
 * \return  int    # of values pushed onto the stack.
 * --------------------------------------------------------------------------*/
static int
lt_htp_str_onbody( lua_State *L )
{
	struct t_htp_str *m = t_htp_str_check_ud( L, 1, 1 );
	
	if (lua_isfunction( L, 2 ))
	{
		m->bR = luaL_ref( L, LUA_REGISTRYINDEX );
		return 0;
	}
	if (lua_isnoneornil( L, 2 ))
	{
		m->bR = LUA_NOREF;
		return 0;
	}
	else
		return t_push_error( L, "Argument must be function or nil" );
}
Exemplo n.º 6
0
/**-----------------------------------------------------------------------------
 * Set main values for HTTP response.
 * Takes different combinations of arguments.
 *     int                 - HTTP status code
 *     int,string          - HTTP status code, msg
 *     int,string,int      - HTTP status code, msg, length
 *     int,int             - HTTP status code, length
 * if there is a last argument being a table, it is treated as unordered key
 * value pair of header: value;
 * \param   L    The lua state.
 * \lparam  T.Http.Stream instance.
 * \lparam  int      HTTP status code.     // mandatory!
 * \lparam  int      length
 *           or
 * \lparam  string   HTTP message corresponding to HTTP status code.
 * \lparam  table    key:value pairs of HTTP headers.
 * \return  int    # of values pushed onto the stack.
 * ---------------------------------------------------------------------------*/
static int
lt_htp_str_writeHead( lua_State *L )
{
	struct t_htp_str *s = t_htp_str_check_ud( L, 1, 1 );
	int               i = lua_gettop( L );
	int               t = (LUA_TTABLE == lua_type( L, i )); // processing headers
	size_t            c = 0;
	luaL_Buffer       lB;

	luaL_buffinit( L, &lB );
	// indicate the Content-Length was provided
	if (LUA_TNUMBER == lua_type( L, 3 ) || LUA_TNUMBER == lua_type( L, 4 ))
	{
		c = t_htp_str_formHeader( L, &lB, s,
			(int) luaL_checkinteger( L, 2 ),   // HTTP Status code
			(LUA_TSTRING == lua_type( L, 3))   // HTTP Status message
				? lua_tostring( L, 3 )
				: t_htp_status( luaL_checkinteger( L, 2 ) ),
			(LUA_TNUMBER == lua_type( L, 3))   // Content-Length
				?  (int) luaL_checkinteger( L, 3 )
				:  (int) luaL_checkinteger( L, 4 ),
			(t) ? i : 0                            // position of optional header table on stack
			);
	}
	else     // Prepare headers for chunked encoding
	{
		c = t_htp_str_formHeader( L, &lB, s,
			(int) luaL_checkinteger( L, 2 ),   // HTTP Status code
			(LUA_TSTRING == lua_type( L, 3))   // HTTP Status message
				? lua_tostring( L, 3 )
				: t_htp_status( luaL_checkinteger( L, 2 ) ),
			0,                                     // Content-Length 0 -> chunked
			(t) ? i : 0                            // position of optional header table on stack
			);
	}
	luaL_pushresult( &lB );
	s->state = T_HTP_STR_SEND;
	t_htp_str_addbuffer( L, s, lB.n, 0 );
	return 0;
}
Exemplo n.º 7
0
/**--------------------------------------------------------------------------
 * Handle outgoing T.Http.Connection into it's socket.
 * \param   L     lua Virtual Machine.
 * \lparam  userdata  struct t_htp_con.
 * \param   pointer to the buffer to read from(already positioned).
 * \lreturn value from the buffer a packers position according to packer format.
 * \return  int    # of values pushed onto the stack.
 *  -------------------------------------------------------------------------*/
int
t_htp_con_rsp( lua_State *L )
{
	struct t_htp_con *c    = t_htp_con_check_ud( L, 1, 1 );
	size_t            snt;
	const char       *b;
	struct t_htp_buf *buf  = c->buf_head;
	struct t_htp_str *str;

	// TODO: test for NULL
	// get tail buffer turn into char * array
	lua_rawgeti( L, LUA_REGISTRYINDEX, buf->bR );
	b = lua_tostring( L, -1 );
	// fetch the currently active stream for this buffer
	lua_rawgeti( L, LUA_REGISTRYINDEX, buf->sR );
	str = t_htp_str_check_ud( L, -1, 1 );
	//printf( "Send ResponseChunk: %s\n", b );

	snt = t_net_tcp_send( L,
			c->sck,
			&(b[ buf->sl ]),
			buf->bl - buf->sl );
	buf->sl   += snt;  // How much of current buffer is sent -> adjustment
	str->rsSl += snt;  // How much of current stream is sent -> adjustment

	//printf( "%zu   %zu  -- %u    %u\n", buf->sl, buf->bl,
	//   buf->sl==buf->bl, buf->sl!=buf->bl );

	if (buf->bl == buf->sl)      // current buffer is sent completly
	{
		if ( buf->last )
		{
			//printf( "EndOfStream\n" );
			lua_pushcfunction( L, lt_htp_str__gc );
			lua_rawgeti( L, LUA_REGISTRYINDEX, buf->sR );
			luaL_unref( L, LUA_REGISTRYINDEX, buf->sR ); // unref stream for gc
			lua_call( L, 1, 0 );
		}
		// free current buffer and go backwards in linked list
		luaL_unref( L, LUA_REGISTRYINDEX, buf->bR ); // unref string for gc
		c->buf_head = buf->nxt;
		free( buf );

		// TODO:  If there is no kpAlv discard connection
		//        If kpAlv and the buffers are empty, set up a timer to discard 
		//        on kpAlv timeout
		if (NULL == c->buf_head)       // current connection has no buffers left
		{
			printf( "remove "T_HTP_CON_TYPE" from Loop\n" );
			// remove this connections socket from evLoop
			t_ael_removehandle_impl( c->srv->ael, c->sck->fd, T_AEL_WR );
			c->srv->ael->fd_set[ c->sck->fd ]->t = T_AEL_RD;
			// done with current the stream has overall
			if ( T_HTP_STR_FINISH == str->state || str->rsSl == str->rsBl)
			{
				if (! c->kpAlv)
				{
					lua_pushcfunction( L, lt_htp_con__gc );
					lua_pushvalue( L, 1 );
					lua_call( L, 1, 0 );
					return 1;
				}
			}
		}

	}
	return 1;
}
Exemplo n.º 8
0
/**--------------------------------------------------------------------------
 * Finish of sending the T.Http.Message response.
 * \param   L    The lua state.
 * \lparam  Http.Message instance.
 * \lparam  string.
 * \return  int    # of values pushed onto the stack.
 * --------------------------------------------------------------------------*/
static int
lt_htp_str_finish( lua_State *L )
{
	struct t_htp_str *s = t_htp_str_check_ud( L, 1, 1 );
	size_t            sz;  /// length of optional string handed in
	char             *b;
	size_t            c   = 0;
	luaL_Buffer       lB;

	// the first action ever called on the stream, prep header first
	if (T_HTP_STR_SEND != s->state)
	{
		luaL_checklstring( L, 2, &sz );
		luaL_buffinit( L, &lB );
		c = t_htp_str_formHeader( L, &lB, s, 200, NULL, (int) sz, 0 );
		lua_pushvalue( L, 2 );
		luaL_addvalue( &lB );
		luaL_pushresult( &lB );
		t_htp_str_addbuffer( L, s, lB.n, 1 );
	}
	else
	{
		if (LUA_TSTRING == lua_type( L, 2 ))
		{
			luaL_checklstring( L, 2, &sz );
			if (! s->rsCl)   // chunked
			{
				luaL_buffinit( L, &lB );
				b = luaL_prepbuffer( &lB );
				c = sprintf( b, "%zx\r\n", sz );
				luaL_addsize( &lB, c );
				lua_pushvalue( L, 2 );
				luaL_addvalue( &lB );
				luaL_addlstring( &lB, "\r\n0\r\n\r\n", 7 );
				luaL_pushresult( &lB );
				t_htp_str_addbuffer( L, s, lB.n, 1 );
			}
			else
			{
				lua_pushvalue( L, 2 );
				t_htp_str_addbuffer( L, s, sz, 1 );
			}
		}
		else
		{
			if (! s->rsCl)   // chunked
			{
				lua_pushstring( L, "0\r\n\r\n" );
				t_htp_str_addbuffer( L, s, 5, 1 );
			}
		}
	}
	/*if ( 0 == s->obc )
	{
		if ( ! s->kpAlv)
		{
			lua_pushcfunction( L, lt_htp_str__gc );
			lua_pushvalue( L, 1 );
			lua_call( L, 1, 0 );
		}
		else
			s->state = T_htp_str_S_ZERO;
	}
	*/

	s->state = T_HTP_STR_FINISH;

	return 0;
}