[asterisk-commits] russell: branch russell/dtls r207353 - /team/russell/dtls/main/dtls.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Jul 19 21:20:13 CDT 2009


Author: russell
Date: Sun Jul 19 21:20:11 2009
New Revision: 207353

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=207353
Log:
Update doxygen docs, make API compatible with not having OpenSSL (in theory)

Modified:
    team/russell/dtls/main/dtls.c

Modified: team/russell/dtls/main/dtls.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/russell/dtls/main/dtls.c?view=diff&rev=207353&r1=207352&r2=207353
==============================================================================
--- team/russell/dtls/main/dtls.c (original)
+++ team/russell/dtls/main/dtls.c Sun Jul 19 21:20:11 2009
@@ -109,6 +109,7 @@
  * \section DTLStodo TODO
  *
  * \todo Figure out how to handle timing out connections.
+ * \todo Add support for multiple address bindings
  *
  *
  * \section DTLSlinks Useful Links
@@ -193,8 +194,35 @@
 	unsigned char stop;
 };
 
+/*!
+ * \brief DTLS connection state.
+ *
+ * We must maintain some connection state so that we know if we can send out
+ * application level messages now, or if we must wait until some DTLS negotiation
+ * completes before continuing with application data.
+ */
 enum dtls_connection_state {
+	/*!
+	 * \brief Base state for a DTLS connection.
+	 *
+	 * In this state, frames are queued up to the DTLS handler thread for
+	 * encryption and writing out to the network.
+	 */
 	DTLS_CONN_STATE_CHILLIN,
+	/*!
+	 * \brief State for waiting for data from the far end of the connection.
+	 *
+	 * If OpenSSL returns the WANT_READ error from SSL_read() or SSL_write(),
+	 * this means that it expects to receive data from the far end of the
+	 * connection and we must wait for that to occur before we can proceed
+	 * with the operation that we just attempted.
+	 *
+	 * In this state, frames to be sent out on the network are put into a
+	 * queue on the dtls_connection object.  Any frames queued up here will
+	 * be moved to the DTLS handler frame queue once the required data has
+	 * been received from the far end and the state has gone back to the
+	 * base state.
+	 */
 	DTLS_CONN_STATE_WANT_READ,
 };
 
@@ -225,6 +253,15 @@
 
 #define dtls_connection_unref(c) ({ ao2_ref(c, -1); (NULL); })
 
+/*!
+ * \internal
+ * \brief Hash function for dtls_connection
+ *
+ * \param obj a dtls_connection
+ * \param flags unused
+ *
+ * \return an integer to be used as a hash value.
+ */
 static int conn_hash(const void *obj, const int flags)
 {
 	const struct dtls_connection *conn = obj;
@@ -232,6 +269,19 @@
 	return conn->sin_remote.sin_addr.s_addr ^ conn->sin_remote.sin_port;
 }
 
+/*!
+ * \internal
+ * \brief Comparison function for dtls_connection
+ *
+ * \param obj a dtls_connection
+ * \param arg a dtls_connection
+ * \param flags unused
+ *
+ * Compare IP address and port number of 2 dtls_connection objects.
+ *
+ * \retval COMP_MATCH|CMP_STOP match
+ * \retval 0 not a match
+ */
 static int conn_cmp(void *obj, void *arg, int flags)
 {
 	const struct dtls_connection *conn1 = obj;
@@ -241,6 +291,14 @@
 				CMP_MATCH | CMP_STOP : 0;
 }
 
+/*!
+ * \internal
+ * \brief Destructor for dtls_connection
+ *
+ * \param obj a dtls_connection
+ *
+ * \return nothing
+ */
 static void conn_destructor(void *obj)
 {
 	struct dtls_connection *conn = obj;
@@ -269,11 +327,27 @@
 	}
 }
 
+/*!
+ * \brief Whether a packet is being sent or received.
+ */
 enum direction {
 	SEND,
 	RECV
 };
 
+/*!
+ * \internal
+ * \brief Find a dtls_connection for a given address and port number.
+ *
+ * \param handler the ast_dtls_handler
+ * \param sin the IP and port number associated with the lookup.
+ * \param dir whether a packet is being sent or received.  This is used if
+ *        the function allocates a connection, so that it knows whether to
+ *        initialize a client side or server side connection.
+ *
+ * \retval non-NULL a dtls_connection 
+ * \retval NULL if an error occurs.
+ */
 static struct dtls_connection *dtls_find_connection(struct ast_dtls_handler *handler,
 				const struct sockaddr_in *sin, enum direction dir)
 {
@@ -336,6 +410,16 @@
 	return NULL;
 }
 
+/*!
+ * \internal
+ * \brief Write an alert to the ast_dtls_handler alert pipe.
+ *
+ * \param handler the ast_dlts_handler
+ * \param alert the dtls_alert to send
+ *
+ * \retval 0 success
+ * \retval -1 write error
+ */
 static int dtls_handler_write_alert(struct ast_dtls_handler *handler,
 		enum dtls_alert alert)
 {
@@ -348,6 +432,14 @@
 	return 0;
 }
 
+/*!
+ * \internal
+ * \brief Destroy a dtls_frame
+ *
+ * \param dtls_fr the dtls_frame to destroy
+ *
+ * \return NULL for convenience to clear out an invalid pointer.
+ */
 static struct dtls_frame *dtls_frame_destroy(struct dtls_frame *dtls_fr)
 {
 	ast_free(dtls_fr);
@@ -358,9 +450,14 @@
 /*!
  * \internal
  * \brief Queue a frame to a DTLS handler
+ *
+ * \param handler the ast_dtls_handler
+ * \param dtls_fr the dtls_frame to queue on to the handler
  *
  * \pre handler is locked
  * \post handler is still locked
+ *
+ * \return nothing
  */
 static void dtls_handler_queue_frame(struct ast_dtls_handler *handler,
 		struct dtls_frame *dtls_fr)
@@ -369,9 +466,12 @@
 	dtls_handler_write_alert(handler, DTLS_ALERT_FRAME);
 }
 
+#endif /* HAVE_OPENSSL */
+
 int ast_dtls_send(struct ast_dtls_handler *handler,
 		const void *buf, size_t len, struct sockaddr_in *sin_remote)
 {
+#ifdef HAVE_OPENSSL
 	struct dtls_connection *conn;
 	struct dtls_frame *dtls_fr;
 	int res = 0;
@@ -409,18 +509,25 @@
 	conn = dtls_connection_unref(conn);
 
 	return res;
-}
-
+#else
+	return -1;
+#endif /* HAVE_OPENSSL */
+}
+
+#ifdef HAVE_OPENSSL
 /*!
  * \internal
  * \brief Set connection state to CHILLIN
  *
- * \param conn the DTLS connection
+ * \param handler the ast_dtls_handler
+ * \param conn the dtls_connection to set the state of
  *
  * \pre conn is locked
  * \post conn is still locked
  * \post Frames from the connection frame queue have now been queued up
  *       to the handler for transmission.
+ *
+ * \return nothing
  */
 static void dtls_connection_set_chillin(struct ast_dtls_handler *handler,
 		struct dtls_connection *conn)
@@ -442,10 +549,13 @@
  * \internal
  * \brief Handle pending writes from OpenSSL
  *
- * \param conn the associated connection
+ * \param handler the ast_dtls_handler
+ * \param conn the associated dtls_connection
  *
  * \pre conn is locked
  * \post conn is still locked
+ *
+ * \return nothing
  */
 static void dtls_handle_pending_writes(struct ast_dtls_handler *handler,
 		struct dtls_connection *conn)
@@ -536,8 +646,15 @@
  * \internal
  * \brief Handle frame from the network
  *
+ * \param handler the ast_dtls_handler
+ * \param conn the dtls_connection the frame was received on
+ * \param enc_buf the received frame in encrypted form
+ * \param len the length of the encrypted frame
+ *
  * \pre conn is locked
  * \post conn is still locked
+ *
+ * \return nothing
  */
 static void dtls_connection_incoming(struct ast_dtls_handler *handler,
 		struct dtls_connection *conn, unsigned char *enc_buf, size_t len)
@@ -604,6 +721,23 @@
 	dtls_handle_pending_writes(handler, conn);
 }
 
+/*!
+ * \internal
+ * \brief Read a packet from a socket
+ *
+ * \param id I/O context ID
+ * \param fd socket descriptor
+ * \param events poll events that triggered this read
+ * \param data the associated ast_netsock
+ *
+ * This is an I/O context callback that gets called when poll() indicates
+ * that data is available for reading.  The data read will be in encrypted
+ * form and must be passed through the associated DTLS connection before
+ * being passed up to the application (if it is an application packet).
+ *
+ * \return non-zero to indicate that the I/O context should continue to
+ *         poll on this socket.
+ */
 static int dtls_socket_read(int *id, int fd, short events, void *data)
 {
 	struct ast_netsock *netsock = data;
@@ -648,6 +782,28 @@
 	return 1;
 }
 
+/*!
+ * \internal
+ * \brief Remove and handle a frame from the handler frame queue.
+ *
+ * \param handler the ast_dtls_handler
+ *
+ * This function removes the frame on the head of the handler frame queue
+ * and then handles writing it out.  The data in the frame has not yet been
+ * encrypted.  This code attempts to pass it through the DTLS connection to
+ * encrypt it and then send it out on the network.
+ *
+ * OpenSSL may indicate that it has additional pending messages to send
+ * out to the network.  In that case, we simply handle that synchronously and
+ * then try our write of this application message again.
+ *
+ * If OpenSSL indicates that it wants to receive some data from the far end
+ * before proceeding, this frame will go back on to the dtls_connection frame
+ * queue.  The connection state will be set to WANT_READ.  This will occur
+ * if DTLS negotiation is taking place, for example.
+ *
+ * \return nothing
+ */
 static void dtls_handler_dequeue_frame(struct ast_dtls_handler *handler)
 {
 	struct dtls_connection *conn;
@@ -715,6 +871,24 @@
 	conn = dtls_connection_unref(conn);
 }
 
+/*!
+ * \internal
+ * \brief Read an alert from the ast_dtls_handler alert pipe.
+ *
+ * \param id the I/O context DI
+ * \param fd the read end of the alert pipe
+ * \param events the events that poll() reported
+ * \param data the ast_dtls_handler
+ *
+ * This function gets called by the I/O context when poll() indicates that
+ * there is data available for reading on the alert pipe.  These alerts
+ * will indicate one of two possible things:
+ *  - A request to stop the DTLS handling thread has been initiated.
+ *  - A frame to be sent out has been queued up on the ast_dtls_handler.
+ *
+ * \return non-zero so that the I/O context knows that it should continue
+ *         polling on this fd.
+ */
 static int dtls_alert_pipe_read(int *id, int fd, short events, void *data)
 {
 	struct ast_dtls_handler *handler = data;
@@ -740,6 +914,17 @@
 	return 1;
 }
 
+/*!
+ * \internal
+ * \brief The ast_dtls_handler thread
+ *
+ * \param data the ast_dtls_handler
+ *
+ * This is the main function for the ast_dtls_handler thread.  It just runs
+ * the I/O context waiting for input on either the socket or the alert pipe.
+ *
+ * \return NULL
+ */
 static void *dtls_handler_thread(void *data)
 {
 	struct ast_dtls_handler *handler = data;
@@ -751,6 +936,15 @@
 	return NULL;
 }
 
+/*!
+ * \internal
+ * \brief Initialize the SSL_CTX for the server side
+ *
+ * \param config the ast_dtls_config
+ *
+ * \retval non-NULL an initialized server side SSL_CTX
+ * \retval NULL error
+ */
 static SSL_CTX *dtls_server_ssl_ctx_init(struct ast_dtls_config *config)
 {
 	SSL_CTX *server_ctx;
@@ -796,6 +990,15 @@
 	return NULL;
 }
 
+/*!
+ * \internal
+ * \brief Initialize the SSL_CTX for the client side
+ *
+ * \param config the ast_dtls_config
+ *
+ * \retval non-NULL an initialized client side SSL_CTX
+ * \retval NULL error
+ */
 static SSL_CTX *dtls_client_ssl_ctx_init(struct ast_dtls_config *config)
 {
 	SSL_CTX *client_ctx;
@@ -824,6 +1027,17 @@
 	return NULL;
 }
 
+/*!
+ * \internal
+ * \brief Destructor for ast_dtls_handler
+ *
+ * \param obj the ast_dtls_handler to destroy
+ *
+ * This destructor will stop the DTLS handler thread before proceeding to
+ * destroy the ast_dtls_handler object.
+ *
+ * \return nothing
+ */
 static void handler_destructor(void *obj)
 {
 	struct ast_dtls_handler *handler = obj;
@@ -874,9 +1088,12 @@
 	}
 }
 
+#endif /* HAVE_OPENSSL */
+
 struct ast_dtls_handler *ast_dtls_handler_alloc(struct ast_dtls_config *config,
 		ast_dtls_recv_cb recv_cb, void *recv_user_data)
 {
+#ifdef HAVE_OPENSSL
 	struct ast_dtls_handler *handler;
 
 	if (!config->enabled) {
@@ -892,6 +1109,8 @@
 	handler->alert_pipe[1] = -1;
 
 	handler->config = ast_dtls_config_ref(config);
+
+	ao2_lock(handler->config);
 
 	if (!(handler->server_ctx = dtls_server_ssl_ctx_init(config))) {
 		goto return_unref;
@@ -947,14 +1166,31 @@
 		goto return_unref;
 	}
 
+	ao2_unlock(handler->config);
+
 	return handler;
 
 return_unref:
+	ao2_unlock(handler->config);
+
 	handler = ast_dtls_handler_unref(handler);
 
 	return NULL;
-}
-
+#else
+	return NULL;
+#endif /* HAVE_OPENSSL */
+}
+
+#ifdef HAVE_OPENSSL
+
+/*!
+ * \internal
+ * \brief Destructor for ast_dtls_config
+ *
+ * \param obj the ast_dtls_config to destroy
+ *
+ * \return Nothing
+ */
 static void config_destructor(void *obj)
 {
 	struct ast_dtls_config *config = obj;
@@ -962,8 +1198,11 @@
 	ast_string_field_free_memory(config);
 }
 
+#endif /* HAVE_OPENSSL */
+
 struct ast_dtls_config *ast_dtls_config_alloc(void)
 {
+#ifdef HAVE_OPENSSL
 	struct ast_dtls_config *config;
 
 	if (!(config = ao2_alloc(sizeof(struct ast_dtls_config), config_destructor))) {
@@ -976,17 +1215,27 @@
 	}
 
 	return config;
+#else
+	return NULL;
+#endif /* HAVE_OPENSSL */
 }
 
 unsigned int ast_dtls_config_get_enabled(const struct ast_dtls_config *config)
 {
+#ifdef HAVE_OPENSSL
 	return config->enabled;
+#else
+	return 0;
+#endif /* HAVE_OPENSSL */
 }
 
 int ast_dtls_config_parse(struct ast_dtls_config *config,
 			const char *var, const char *val)
 {
+#ifdef HAVE_OPENSSL
 	int res = 0;
+
+	ao2_lock(config);
 
 	CV_START(var, val);
 
@@ -1000,10 +1249,13 @@
 	CV_STRFIELD("dtlsdhfile", config, dh_params);
 
 	res = -1;
-
 	CV_END;
 
+	ao2_unlock(config);
+
 	return res;
-}
-
+#else
+	return -1;
 #endif /* HAVE_OPENSSL */
+}
+




More information about the asterisk-commits mailing list