<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>MQX Software Solutions中的主题 HTTP Cookies</title>
    <link>https://community.nxp.com/t5/MQX-Software-Solutions/HTTP-Cookies/m-p/496778#M16072</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I thought I would share this to give something back to the community.&lt;BR /&gt;I have added support for one time HTTP headers that I use to send cookies to the client and support for reading cookies from received headers.&lt;BR /&gt;I am using this for an alternative authentication solution that better fits my needs but it is pretty generic.&lt;BR /&gt;The steps are based on the KSDK 1.3 with MQX version of the RTCS. I modified the KSDK / MQX source and then rebuilt the library which is then included in my project.&lt;BR /&gt;I have added my name in a comment on the new lines / blocks of code and included small sections of the original surrounding code to help find the locations.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;1. Add two extra char pointers to the HTTPSRV_SESSION_STRUCT:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568345177851307 jive_text_macro" data-renderedposition="290_50_798_400" jivemacro_uid="_14568345177851307"&gt;&lt;P&gt;/*
* HTTP session structure
*/
typedef struct httpsrv_session_struct
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SES_FUNC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; process_func;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session process function */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SES_STATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; state;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* HTTP session state */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; valid;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Any value different than HTTPSRV_SESSION_VALID means session is invalid */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session socket */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; time;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session time. Updated when there is some activity in session. Used for timeout detection. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeout;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session timeout in ms. timeout_time = time + timeout */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_BUFF_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; buffer;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session internal read/write buffer */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_REQ_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; request;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Data read from the request */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_RES_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Response data */
&amp;nbsp;&amp;nbsp;&amp;nbsp; LWSEM_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session lock */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile _task_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; script_tid;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session script handler */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_PLUGIN_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp; *plugin;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Plugin to be invoked for session. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; WS_HANDSHAKE_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *ws_handshake;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* WebSocket hand-shake */
&amp;nbsp;&amp;nbsp;&amp;nbsp; #if RTCSCFG_ENABLE_SSL
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ssl_sock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* SSL context handle */
&amp;nbsp;&amp;nbsp;&amp;nbsp; #endif
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; flags;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session flags */
&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onetimeHTTPHdrs;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Adrian:- Extra headers to be returned to the client for the next transaction
&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recievedCookies;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Adrian:- Cookies received from client
} HTTPSRV_SESSION_STRUCT;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_supp.c at the end of httpsrv_sendhdr add the block between the //Adrian comments:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568408123996439 jive_text_macro" data-renderedposition="742_50_798_240" jivemacro_uid="_14568408123996439"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Handle transfer encoding. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;flags &amp;amp; HTTPSRV_FLAG_IS_TRANSCODED)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, "Transfer-Encoding: chunked\r\n");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;onetimeHTTPHdrs)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, session-&amp;gt;onetimeHTTPHdrs);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; free( session-&amp;gt;onetimeHTTPHdrs );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; //End Adrian&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* End of header */
&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, "\r\n");&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c - httpsrv_ses_alloc add line 27:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568408343283641 jive_text_macro" data-renderedposition="1034_50_798_448" jivemacro_uid="_14568408343283641"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_set_type(session, MEM_TYPE_HTTPSRV_SESSION_STRUCT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Alloc URI */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.path = _mem_alloc_zero(server-&amp;gt;params.max_uri + 1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;request.path)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_set_type(session-&amp;gt;request.path, MEM_TYPE_HTTPSRV_URI);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Alloc session buffer */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;buffer.data = _mem_alloc_zero(sizeof(char)*HTTPSRV_SES_BUF_SIZE_PRV);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;buffer.data)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #if RTCSCFG_ENABLE_SSL
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (server-&amp;gt;ssl_ctx != 0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;ssl_sock = RTCS_ssl_socket(server-&amp;gt;ssl_ctx, sock);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;ssl_sock == RTCS_ERROR)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endif&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = NULL; //Adrian&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_supp.c - httpsrv_req_hdr add the last else if block:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568347258035422 jive_text_macro" data-renderedposition="1534_50_798_608" jivemacro_uid="_14568347258035422"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (strncmp(buffer, "Cookie: ", 8) == 0) //Adrian:- Cookie support
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr = buffer+8;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free( session-&amp;gt;recievedCookies );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Allocate memory for cookies plus two NULL characters at the end
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;recievedCookies = _mem_alloc_zero( sizeof(char) * strlen( param_ptr ) + (2 * sizeof(char)) );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;recievedCookies == NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; retval = HTTPSRV_ERR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto EXIT;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Copy to the session buffer and replace all ';' with NULL to separate strings (final entry will have 2 NULL), also remove spaces before cookie name.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char* sessionPtr = session-&amp;gt;recievedCookies;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (*param_ptr != 0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (*param_ptr == ';')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Terminate entry with a NULL in the session buffer
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *sessionPtr = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (*param_ptr == ' ')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Skip past space before next cookie name
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Copy the character to the session buffer
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *sessionPtr = *param_ptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sessionPtr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c -&amp;nbsp; httpsrv_ses_free add the block between //Adrian:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568348188745094 jive_text_macro" data-renderedposition="2194_50_798_176" jivemacro_uid="_14568348188745094"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;ws_handshake)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;ws_handshake);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free( session-&amp;gt;recievedCookies );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian end&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session);&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv.h near to the end add:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14568349201996472" data-renderedposition="2422_50_798_512" jivemacro_uid="_14568349201996472"&gt;&lt;P&gt;//Adrian
char* HTTPSRV_GetCookie( uint32_t ses_handle, char* CookieName );&lt;/P&gt;&lt;P&gt;In httpsrv.c near to the end add:&lt;/P&gt;&lt;P&gt;//Retrieve the data for the specified cookie.
//IN:&amp;nbsp; uint32_t ses_handle - session containing the cookie data
// char* Name - the name of the cookie including the '='
//
//OUT: char* - pointer to the cookie data or NULL if cookie not found
//
char* HTTPSRV_GetCookie( uint32_t ses_handle, char* Name )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SESSION_STRUCT* session = (HTTPSRV_SESSION_STRUCT*) ses_handle;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* entry = session-&amp;gt;recievedCookies;
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t nameLen = strlen( Name );

&amp;nbsp;&amp;nbsp;&amp;nbsp; while( (*entry != NULL) &amp;amp;&amp;amp; (strncmp( Name, entry, nameLen ) != NULL))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry += strlen( entry ) + 1;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; if (*entry == NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Not found
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; return (entry + nameLen);
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To add headers via you code use something like (this adds two cookies called uid and sid during my login cgi call-back):&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568350800655273 jive_macro_code jive_text_macro" data-renderedposition="2986_50_798_112" jivemacro_uid="_14568350800655273"&gt;&lt;P&gt;//Add HTTP header so client stores the user name and password cookies
HTTPSRV_SESSION_STRUCT* session = (HTTPSRV_SESSION_STRUCT*)param-&amp;gt;ses_handle;
if (NULL == session-&amp;gt;onetimeHTTPHdrs)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = (char*)malloc( 500 );
}
sprintf( session-&amp;gt;onetimeHTTPHdrs, "Set-Cookie: uid=%s; Path=/\r\nSet-Cookie: sid=%s; Path=/; HttpOnly\r\n", gActiveEnetUser.UserID, gActiveEnetUser.SessionID );&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To get the cookies back use something like during a client request:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568387902822738 jive_macro_code jive_text_macro" data-renderedposition="3150_50_798_48" jivemacro_uid="_14568387902822738"&gt;&lt;P&gt;//Locate the start of the required cookies in the combined string
char* uid = HTTPSRV_GetCookie( ses_handle, "uid=" );
char* sid = HTTPSRV_GetCookie( ses_handle, "sid=" );&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I also incorporated a new authentication method that uses the cookies by adding call-back function support to the realm table as follows.&lt;/P&gt;&lt;P&gt;In httpsrv.h add a new type define and add it to the realm table:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568395080254297 jive_text_macro" data-renderedposition="3302_50_798_208" jivemacro_uid="_14568395080254297"&gt;&lt;P&gt;// Adrian:- Call-back authentication call-back prototype
typedef int32_t(*HTTPSRV_AUTH_CALLBACK_FN)( uint32_t ses_handle, const char* remote_ip );&lt;/P&gt;&lt;P&gt;/*
** Authentication realm structure
*/
typedef struct httpsrv_auth_realm_struct
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; const char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Name of realm. Send to client so user know which login/pass should be used. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; path;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Path to file/directory to protect. Relative to root directory */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_TYPE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; auth_type;&amp;nbsp; /* Authentication type to use. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_USER_STRUCT* users;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Table of allowed users. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_CALLBACK_FN&amp;nbsp; auth_func; // Adrian:- call-back used to authenticate user
} HTTPSRV_AUTH_REALM_STRUCT;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c - httpsrv_req_do add the following block:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14568396347598494" data-renderedposition="3562_50_798_512" jivemacro_uid="_14568396347598494"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.auth_realm != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian:- Implement call-back authentication
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;response.auth_realm-&amp;gt;auth_func)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char remote_ip[RTCS_IP_ADDR_STR_SIZE];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct sockaddr l_address;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct sockaddr r_address;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint16_t length = sizeof(sockaddr);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; getsockname(session-&amp;gt;sock, &amp;amp;l_address, &amp;amp;length);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; getpeername(session-&amp;gt;sock, &amp;amp;r_address, &amp;amp;length);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (l_address.sa_family == AF_INET)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inet_ntop(r_address.sa_family, &amp;amp;((struct sockaddr_in*) &amp;amp;r_address)-&amp;gt;sin_addr.s_addr, remote_ip, sizeof(remote_ip));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (l_address.sa_family == AF_INET6)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inet_ntop(r_address.sa_family, ((struct sockaddr_in6*) &amp;amp;r_address)-&amp;gt;sin6_addr.s6_addr, remote_ip, sizeof(remote_ip));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;response.status_code = session-&amp;gt;response.auth_realm-&amp;gt;auth_func( (uint32_t)session, remote_ip );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.status_code != HTTPSRV_CODE_OK)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.auth.user_id != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;request.auth.user_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.user_id = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.password = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto EXIT;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }//Adrian End
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!httpsrv_check_auth(session-&amp;gt;response.auth_realm, &amp;amp;session-&amp;gt;request.auth))&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In my app I only want one user logged in at a time and I have a database of users that is configured dynamically. So I added the call back functions to the table definition as follows:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568397114307000 jive_macro_code jive_text_macro" data-renderedposition="4152_50_798_848" jivemacro_uid="_14568397114307000"&gt;&lt;P&gt;int32_t auth_Protect( uint32_t ses_handle, const char* remote_ip );
int32_t auth_Admin( uint32_t ses_handle, const char* remote_ip );&lt;/P&gt;&lt;P&gt;/*
 * Authentication information.
 */
static const HTTPSRV_AUTH_REALM_STRUCT auth_realms[] =
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; { "Users", "protect", HTTPSRV_AUTH_BASIC, NULL, auth_Protect},
&amp;nbsp;&amp;nbsp;&amp;nbsp; { "Admin", "admin", HTTPSRV_AUTH_BASIC, NULL, auth_Admin},
&amp;nbsp;&amp;nbsp;&amp;nbsp; { NULL, NULL, HTTPSRV_AUTH_INVALID, NULL, NULL} /* Array terminator */
};&lt;/P&gt;&lt;P&gt;int32_t auth_Protect( uint32_t ses_handle, const char* remote_ip )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((gActiveEnetUser.UserID[ 0 ] == 0) || (strcmp( remote_ip, gActiveEnetUser.ClientIP ) != 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Either no user logged in or the request is from a different IP source
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; //Locate the required cookies
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* uid = HTTPSRV_GetCookie( ses_handle, "uid=" );
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* sid = HTTPSRV_GetCookie( ses_handle, "sid=" );
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((NULL == uid) || (NULL == sid))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //No user or session id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((*uid == 0) || (*sid == 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //No user id or session id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
 
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((strcmp( gActiveEnetUser.UserID, uid ) == 0) &amp;amp;&amp;amp;(strcmp( gActiveEnetUser.SessionID, sid ) == 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_OK;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
}&lt;/P&gt;&lt;P&gt;int32_t auth_Admin( uint32_t ses_handle, const char* remote_ip )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; int32_t response = auth_Protect( ses_handle, remote_ip );
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (response == HTTPSRV_CODE_OK)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Passed basic authentication so check user permissions
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (gActiveEnetUser.Level &amp;lt; ENET_LEVEL_ADMIN)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; return response;
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Hopefully I have remembered all the steps and not missed anything.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;Adrian&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Tue, 01 Mar 2016 13:49:12 GMT</pubDate>
    <dc:creator>adyr</dc:creator>
    <dc:date>2016-03-01T13:49:12Z</dc:date>
    <item>
      <title>HTTP Cookies</title>
      <link>https://community.nxp.com/t5/MQX-Software-Solutions/HTTP-Cookies/m-p/496778#M16072</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I thought I would share this to give something back to the community.&lt;BR /&gt;I have added support for one time HTTP headers that I use to send cookies to the client and support for reading cookies from received headers.&lt;BR /&gt;I am using this for an alternative authentication solution that better fits my needs but it is pretty generic.&lt;BR /&gt;The steps are based on the KSDK 1.3 with MQX version of the RTCS. I modified the KSDK / MQX source and then rebuilt the library which is then included in my project.&lt;BR /&gt;I have added my name in a comment on the new lines / blocks of code and included small sections of the original surrounding code to help find the locations.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;1. Add two extra char pointers to the HTTPSRV_SESSION_STRUCT:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568345177851307 jive_text_macro" data-renderedposition="290_50_798_400" jivemacro_uid="_14568345177851307"&gt;&lt;P&gt;/*
* HTTP session structure
*/
typedef struct httpsrv_session_struct
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SES_FUNC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; process_func;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session process function */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SES_STATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; state;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* HTTP session state */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; valid;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Any value different than HTTPSRV_SESSION_VALID means session is invalid */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session socket */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; time;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session time. Updated when there is some activity in session. Used for timeout detection. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeout;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session timeout in ms. timeout_time = time + timeout */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_BUFF_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; buffer;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session internal read/write buffer */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_REQ_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; request;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Data read from the request */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_RES_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Response data */
&amp;nbsp;&amp;nbsp;&amp;nbsp; LWSEM_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session lock */
&amp;nbsp;&amp;nbsp;&amp;nbsp; volatile _task_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; script_tid;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session script handler */
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_PLUGIN_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp; *plugin;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Plugin to be invoked for session. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; WS_HANDSHAKE_STRUCT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *ws_handshake;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* WebSocket hand-shake */
&amp;nbsp;&amp;nbsp;&amp;nbsp; #if RTCSCFG_ENABLE_SSL
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ssl_sock;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* SSL context handle */
&amp;nbsp;&amp;nbsp;&amp;nbsp; #endif
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; flags;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Session flags */
&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onetimeHTTPHdrs;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Adrian:- Extra headers to be returned to the client for the next transaction
&amp;nbsp;&amp;nbsp;&amp;nbsp; char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recievedCookies;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Adrian:- Cookies received from client
} HTTPSRV_SESSION_STRUCT;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_supp.c at the end of httpsrv_sendhdr add the block between the //Adrian comments:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568408123996439 jive_text_macro" data-renderedposition="742_50_798_240" jivemacro_uid="_14568408123996439"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Handle transfer encoding. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;flags &amp;amp; HTTPSRV_FLAG_IS_TRANSCODED)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, "Transfer-Encoding: chunked\r\n");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;onetimeHTTPHdrs)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, session-&amp;gt;onetimeHTTPHdrs);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; free( session-&amp;gt;onetimeHTTPHdrs );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; //End Adrian&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* End of header */
&amp;nbsp;&amp;nbsp;&amp;nbsp; httpsrv_print(session, "\r\n");&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c - httpsrv_ses_alloc add line 27:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568408343283641 jive_text_macro" data-renderedposition="1034_50_798_448" jivemacro_uid="_14568408343283641"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_set_type(session, MEM_TYPE_HTTPSRV_SESSION_STRUCT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Alloc URI */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.path = _mem_alloc_zero(server-&amp;gt;params.max_uri + 1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;request.path)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_set_type(session-&amp;gt;request.path, MEM_TYPE_HTTPSRV_URI);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Alloc session buffer */
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;buffer.data = _mem_alloc_zero(sizeof(char)*HTTPSRV_SES_BUF_SIZE_PRV);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;buffer.data)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #if RTCSCFG_ENABLE_SSL
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (server-&amp;gt;ssl_ctx != 0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;ssl_sock = RTCS_ssl_socket(server-&amp;gt;ssl_ctx, sock);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;ssl_sock == RTCS_ERROR)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto ERROR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endif&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = NULL; //Adrian&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_supp.c - httpsrv_req_hdr add the last else if block:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568347258035422 jive_text_macro" data-renderedposition="1534_50_798_608" jivemacro_uid="_14568347258035422"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (strncmp(buffer, "Cookie: ", 8) == 0) //Adrian:- Cookie support
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr = buffer+8;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free( session-&amp;gt;recievedCookies );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Allocate memory for cookies plus two NULL characters at the end
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;recievedCookies = _mem_alloc_zero( sizeof(char) * strlen( param_ptr ) + (2 * sizeof(char)) );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;recievedCookies == NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; retval = HTTPSRV_ERR;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto EXIT;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Copy to the session buffer and replace all ';' with NULL to separate strings (final entry will have 2 NULL), also remove spaces before cookie name.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char* sessionPtr = session-&amp;gt;recievedCookies;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (*param_ptr != 0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (*param_ptr == ';')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Terminate entry with a NULL in the session buffer
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *sessionPtr = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (*param_ptr == ' ')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Skip past space before next cookie name
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Copy the character to the session buffer
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *sessionPtr = *param_ptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param_ptr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sessionPtr++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c -&amp;nbsp; httpsrv_ses_free add the block between //Adrian:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568348188745094 jive_text_macro" data-renderedposition="2194_50_798_176" jivemacro_uid="_14568348188745094"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;ws_handshake)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;ws_handshake);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free( session-&amp;gt;recievedCookies );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian end&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session);&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv.h near to the end add:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14568349201996472" data-renderedposition="2422_50_798_512" jivemacro_uid="_14568349201996472"&gt;&lt;P&gt;//Adrian
char* HTTPSRV_GetCookie( uint32_t ses_handle, char* CookieName );&lt;/P&gt;&lt;P&gt;In httpsrv.c near to the end add:&lt;/P&gt;&lt;P&gt;//Retrieve the data for the specified cookie.
//IN:&amp;nbsp; uint32_t ses_handle - session containing the cookie data
// char* Name - the name of the cookie including the '='
//
//OUT: char* - pointer to the cookie data or NULL if cookie not found
//
char* HTTPSRV_GetCookie( uint32_t ses_handle, char* Name )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTPSRV_SESSION_STRUCT* session = (HTTPSRV_SESSION_STRUCT*) ses_handle;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == session-&amp;gt;recievedCookies)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* entry = session-&amp;gt;recievedCookies;
&amp;nbsp;&amp;nbsp;&amp;nbsp; uint32_t nameLen = strlen( Name );

&amp;nbsp;&amp;nbsp;&amp;nbsp; while( (*entry != NULL) &amp;amp;&amp;amp; (strncmp( Name, entry, nameLen ) != NULL))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry += strlen( entry ) + 1;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; if (*entry == NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Not found
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; return (entry + nameLen);
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To add headers via you code use something like (this adds two cookies called uid and sid during my login cgi call-back):&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568350800655273 jive_macro_code jive_text_macro" data-renderedposition="2986_50_798_112" jivemacro_uid="_14568350800655273"&gt;&lt;P&gt;//Add HTTP header so client stores the user name and password cookies
HTTPSRV_SESSION_STRUCT* session = (HTTPSRV_SESSION_STRUCT*)param-&amp;gt;ses_handle;
if (NULL == session-&amp;gt;onetimeHTTPHdrs)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;onetimeHTTPHdrs = (char*)malloc( 500 );
}
sprintf( session-&amp;gt;onetimeHTTPHdrs, "Set-Cookie: uid=%s; Path=/\r\nSet-Cookie: sid=%s; Path=/; HttpOnly\r\n", gActiveEnetUser.UserID, gActiveEnetUser.SessionID );&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;To get the cookies back use something like during a client request:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568387902822738 jive_macro_code jive_text_macro" data-renderedposition="3150_50_798_48" jivemacro_uid="_14568387902822738"&gt;&lt;P&gt;//Locate the start of the required cookies in the combined string
char* uid = HTTPSRV_GetCookie( ses_handle, "uid=" );
char* sid = HTTPSRV_GetCookie( ses_handle, "sid=" );&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I also incorporated a new authentication method that uses the cookies by adding call-back function support to the realm table as follows.&lt;/P&gt;&lt;P&gt;In httpsrv.h add a new type define and add it to the realm table:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code _jivemacro_uid_14568395080254297 jive_text_macro" data-renderedposition="3302_50_798_208" jivemacro_uid="_14568395080254297"&gt;&lt;P&gt;// Adrian:- Call-back authentication call-back prototype
typedef int32_t(*HTTPSRV_AUTH_CALLBACK_FN)( uint32_t ses_handle, const char* remote_ip );&lt;/P&gt;&lt;P&gt;/*
** Authentication realm structure
*/
typedef struct httpsrv_auth_realm_struct
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; const char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Name of realm. Send to client so user know which login/pass should be used. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const char*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; path;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Path to file/directory to protect. Relative to root directory */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_TYPE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; auth_type;&amp;nbsp; /* Authentication type to use. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_USER_STRUCT* users;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Table of allowed users. */
&amp;nbsp;&amp;nbsp;&amp;nbsp; const HTTPSRV_AUTH_CALLBACK_FN&amp;nbsp; auth_func; // Adrian:- call-back used to authenticate user
} HTTPSRV_AUTH_REALM_STRUCT;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In httpsrv_task.c - httpsrv_req_do add the following block:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="jive_macro_code jive_text_macro _jivemacro_uid_14568396347598494" data-renderedposition="3562_50_798_512" jivemacro_uid="_14568396347598494"&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.auth_realm != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Adrian:- Implement call-back authentication
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL != session-&amp;gt;response.auth_realm-&amp;gt;auth_func)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; char remote_ip[RTCS_IP_ADDR_STR_SIZE];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct sockaddr l_address;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct sockaddr r_address;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uint16_t length = sizeof(sockaddr);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; getsockname(session-&amp;gt;sock, &amp;amp;l_address, &amp;amp;length);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; getpeername(session-&amp;gt;sock, &amp;amp;r_address, &amp;amp;length);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (l_address.sa_family == AF_INET)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inet_ntop(r_address.sa_family, &amp;amp;((struct sockaddr_in*) &amp;amp;r_address)-&amp;gt;sin_addr.s_addr, remote_ip, sizeof(remote_ip));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (l_address.sa_family == AF_INET6)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inet_ntop(r_address.sa_family, ((struct sockaddr_in6*) &amp;amp;r_address)-&amp;gt;sin6_addr.s6_addr, remote_ip, sizeof(remote_ip));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;response.status_code = session-&amp;gt;response.auth_realm-&amp;gt;auth_func( (uint32_t)session, remote_ip );
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;response.status_code != HTTPSRV_CODE_OK)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (session-&amp;gt;request.auth.user_id != NULL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mem_free(session-&amp;gt;request.auth.user_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.user_id = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; session-&amp;gt;request.auth.password = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto EXIT;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }//Adrian End
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!httpsrv_check_auth(session-&amp;gt;response.auth_realm, &amp;amp;session-&amp;gt;request.auth))&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;In my app I only want one user logged in at a time and I have a database of users that is configured dynamically. So I added the call back functions to the table definition as follows:&lt;/P&gt;&lt;PRE __default_attr="c++" __jive_macro_name="code" class="_jivemacro_uid_14568397114307000 jive_macro_code jive_text_macro" data-renderedposition="4152_50_798_848" jivemacro_uid="_14568397114307000"&gt;&lt;P&gt;int32_t auth_Protect( uint32_t ses_handle, const char* remote_ip );
int32_t auth_Admin( uint32_t ses_handle, const char* remote_ip );&lt;/P&gt;&lt;P&gt;/*
 * Authentication information.
 */
static const HTTPSRV_AUTH_REALM_STRUCT auth_realms[] =
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; { "Users", "protect", HTTPSRV_AUTH_BASIC, NULL, auth_Protect},
&amp;nbsp;&amp;nbsp;&amp;nbsp; { "Admin", "admin", HTTPSRV_AUTH_BASIC, NULL, auth_Admin},
&amp;nbsp;&amp;nbsp;&amp;nbsp; { NULL, NULL, HTTPSRV_AUTH_INVALID, NULL, NULL} /* Array terminator */
};&lt;/P&gt;&lt;P&gt;int32_t auth_Protect( uint32_t ses_handle, const char* remote_ip )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((gActiveEnetUser.UserID[ 0 ] == 0) || (strcmp( remote_ip, gActiveEnetUser.ClientIP ) != 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Either no user logged in or the request is from a different IP source
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; //Locate the required cookies
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* uid = HTTPSRV_GetCookie( ses_handle, "uid=" );
&amp;nbsp;&amp;nbsp;&amp;nbsp; char* sid = HTTPSRV_GetCookie( ses_handle, "sid=" );
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((NULL == uid) || (NULL == sid))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //No user or session id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((*uid == 0) || (*sid == 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //No user id or session id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
 
&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((strcmp( gActiveEnetUser.UserID, uid ) == 0) &amp;amp;&amp;amp;(strcmp( gActiveEnetUser.SessionID, sid ) == 0))
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_OK;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return HTTPSRV_CODE_FORBIDDEN;
}&lt;/P&gt;&lt;P&gt;int32_t auth_Admin( uint32_t ses_handle, const char* remote_ip )
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; int32_t response = auth_Protect( ses_handle, remote_ip );
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (response == HTTPSRV_CODE_OK)
&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Passed basic authentication so check user permissions
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (gActiveEnetUser.Level &amp;lt; ENET_LEVEL_ADMIN)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; response = HTTPSRV_CODE_FORBIDDEN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; return response;
}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Hopefully I have remembered all the steps and not missed anything.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;Adrian&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 01 Mar 2016 13:49:12 GMT</pubDate>
      <guid>https://community.nxp.com/t5/MQX-Software-Solutions/HTTP-Cookies/m-p/496778#M16072</guid>
      <dc:creator>adyr</dc:creator>
      <dc:date>2016-03-01T13:49:12Z</dc:date>
    </item>
  </channel>
</rss>

