GNU libmicrohttpd  0.9.5
connection_https.c
Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007, 2008, 2010 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 */
00020 
00029 #include "internal.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 #include "response.h"
00033 #include "reason_phrase.h"
00034 #include <gnutls/gnutls.h>
00035 
00046 static void
00047 MHD_tls_connection_close (struct MHD_Connection *connection,
00048                           enum MHD_RequestTerminationCode termination_code)
00049 {
00050   gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR);
00051   MHD_connection_close (connection, termination_code);
00052 }
00053 
00054 
00072 static int
00073 MHD_tls_connection_handle_read (struct MHD_Connection *connection)
00074 {
00075   int ret;
00076 
00077   connection->last_activity = time (NULL);
00078   if (connection->state == MHD_TLS_CONNECTION_INIT)
00079     {
00080       ret = gnutls_handshake (connection->tls_session);
00081       if (ret == GNUTLS_E_SUCCESS) 
00082         {
00083           /* set connection state to enable HTTP processing */
00084           connection->state = MHD_CONNECTION_INIT;
00085           return MHD_YES;         
00086         }
00087       if ( (ret == GNUTLS_E_AGAIN) || 
00088            (ret == GNUTLS_E_INTERRUPTED) )
00089         {
00090           /* handshake not done */
00091           return MHD_YES;
00092         }
00093       /* handshake failed */
00094 #if HAVE_MESSAGES
00095       MHD_DLOG (connection->daemon,
00096                 "Error: received handshake message out of context\n");
00097 #endif
00098       MHD_tls_connection_close (connection,
00099                                 MHD_REQUEST_TERMINATED_WITH_ERROR);
00100       return MHD_NO;
00101     }
00102   return MHD_connection_handle_read (connection);
00103 }
00104 
00105 
00115 static int
00116 MHD_tls_connection_handle_write (struct MHD_Connection *connection)
00117 {
00118   int ret;
00119 
00120   connection->last_activity = time (NULL);
00121 #if DEBUG_STATES
00122   MHD_DLOG (connection->daemon, "%s: state: %s\n",
00123             __FUNCTION__, MHD_state_to_string (connection->state));
00124 #endif
00125   if (connection->state == MHD_TLS_CONNECTION_INIT)
00126     {
00127       ret = gnutls_handshake (connection->tls_session);
00128       if (ret == GNUTLS_E_SUCCESS)
00129         {
00130           /* set connection state to enable HTTP processing */
00131           connection->state = MHD_CONNECTION_INIT;
00132           return MHD_YES;         
00133         }
00134       if ( (ret == GNUTLS_E_AGAIN) || 
00135            (ret == GNUTLS_E_INTERRUPTED) )
00136         {
00137           /* handshake not done */
00138           return MHD_YES;
00139         }
00140       /* handshake failed */
00141 #if HAVE_MESSAGES
00142       MHD_DLOG (connection->daemon,
00143                 "Error: received handshake message out of context\n");
00144 #endif
00145       MHD_tls_connection_close (connection,
00146                                 MHD_REQUEST_TERMINATED_WITH_ERROR);
00147       return MHD_NO;
00148     }
00149   return MHD_connection_handle_write (connection);
00150 }
00151 
00152 
00163 static int
00164 MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
00165 {
00166   unsigned int timeout;
00167 
00168 #if DEBUG_STATES
00169   MHD_DLOG (connection->daemon, "%s: state: %s\n",
00170             __FUNCTION__, MHD_state_to_string (connection->state));
00171 #endif
00172   timeout = connection->daemon->connection_timeout;
00173   if ((connection->socket_fd != -1) && (timeout != 0)
00174       && (time (NULL) - timeout > connection->last_activity))
00175     {
00176       MHD_tls_connection_close (connection,
00177                                 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
00178       return MHD_NO;
00179     }
00180   switch (connection->state)
00181     {
00182       /* on newly created connections we might reach here before any reply has been received */
00183     case MHD_TLS_CONNECTION_INIT:
00184       return MHD_YES;
00185       /* close connection if necessary */
00186     case MHD_CONNECTION_CLOSED:
00187       if (connection->socket_fd != -1)
00188         MHD_tls_connection_close (connection,
00189                                   MHD_REQUEST_TERMINATED_COMPLETED_OK);
00190       return MHD_NO;
00191     default:
00192       if ( (0 != gnutls_record_check_pending (connection->tls_session)) &&
00193            (MHD_YES != MHD_tls_connection_handle_read (connection)) )
00194         return MHD_NO;
00195       return MHD_connection_handle_idle (connection);
00196     }
00197   return MHD_YES;
00198 }
00199 
00200 
00205 void
00206 MHD_set_https_callbacks (struct MHD_Connection *connection)
00207 {
00208   connection->read_handler = &MHD_tls_connection_handle_read;
00209   connection->write_handler = &MHD_tls_connection_handle_write;
00210   connection->idle_handler = &MHD_tls_connection_handle_idle;
00211 }
00212 
00213 /* end of connection_https.c */