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 00036 00045 static int 00046 run_tls_handshake (struct MHD_Connection *connection) 00047 { 00048 int ret; 00049 00050 connection->last_activity = MHD_monotonic_time(); 00051 if (connection->state == MHD_TLS_CONNECTION_INIT) 00052 { 00053 ret = gnutls_handshake (connection->tls_session); 00054 if (ret == GNUTLS_E_SUCCESS) 00055 { 00056 /* set connection state to enable HTTP processing */ 00057 connection->state = MHD_CONNECTION_INIT; 00058 return MHD_YES; 00059 } 00060 if ( (ret == GNUTLS_E_AGAIN) || 00061 (ret == GNUTLS_E_INTERRUPTED) ) 00062 { 00063 /* handshake not done */ 00064 return MHD_YES; 00065 } 00066 /* handshake failed */ 00067 #if HAVE_MESSAGES 00068 MHD_DLOG (connection->daemon, 00069 "Error: received handshake message out of context\n"); 00070 #endif 00071 MHD_connection_close (connection, 00072 MHD_REQUEST_TERMINATED_WITH_ERROR); 00073 return MHD_YES; 00074 } 00075 return MHD_NO; 00076 } 00077 00078 00095 static int 00096 MHD_tls_connection_handle_read (struct MHD_Connection *connection) 00097 { 00098 if (MHD_YES == run_tls_handshake (connection)) 00099 return MHD_YES; 00100 return MHD_connection_handle_read (connection); 00101 } 00102 00103 00112 static int 00113 MHD_tls_connection_handle_write (struct MHD_Connection *connection) 00114 { 00115 if (MHD_YES == run_tls_handshake (connection)) 00116 return MHD_YES; 00117 return MHD_connection_handle_write (connection); 00118 } 00119 00120 00131 static int 00132 MHD_tls_connection_handle_idle (struct MHD_Connection *connection) 00133 { 00134 unsigned int timeout; 00135 00136 #if DEBUG_STATES 00137 MHD_DLOG (connection->daemon, "%s: state: %s\n", 00138 __FUNCTION__, MHD_state_to_string (connection->state)); 00139 #endif 00140 timeout = connection->connection_timeout; 00141 if ( (timeout != 0) && (MHD_monotonic_time() - timeout > connection->last_activity)) 00142 MHD_connection_close (connection, 00143 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); 00144 switch (connection->state) 00145 { 00146 /* on newly created connections we might reach here before any reply has been received */ 00147 case MHD_TLS_CONNECTION_INIT: 00148 return MHD_YES; 00149 /* close connection if necessary */ 00150 case MHD_CONNECTION_CLOSED: 00151 gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR); 00152 return MHD_connection_handle_idle (connection); 00153 default: 00154 if ( (0 != gnutls_record_check_pending (connection->tls_session)) && 00155 (MHD_YES != MHD_tls_connection_handle_read (connection)) ) 00156 return MHD_YES; 00157 return MHD_connection_handle_idle (connection); 00158 } 00159 return MHD_YES; 00160 } 00161 00162 00167 void 00168 MHD_set_https_callbacks (struct MHD_Connection *connection) 00169 { 00170 connection->read_handler = &MHD_tls_connection_handle_read; 00171 connection->write_handler = &MHD_tls_connection_handle_write; 00172 connection->idle_handler = &MHD_tls_connection_handle_idle; 00173 } 00174 00175 /* end of connection_https.c */