Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 419821)
+++ channels/chan_sip.c	(working copy)
@@ -2695,156 +2695,6 @@
 }
 
 /*!
- * \brief Read a SIP request or response from a TLS connection
- *
- * Because TLS operations are hidden from view via a FILE handle, the
- * logic for reading data is a bit complex, and we have to make periodic
- * checks to be sure we aren't taking too long to perform the necessary
- * action.
- *
- * \todo XXX This should be altered in the future not to use a FILE pointer
- *
- * \param req The request structure to fill in
- * \param tcptls_session The TLS connection on which the data is being received
- * \param authenticated A flag indicating whether authentication has occurred yet.
- *        This is only relevant in a server role.
- * \param start The time at which we started attempting to read data. Used in
- *        determining if there has been a timeout.
- * \param me Thread info. Used as a means of determining if the session needs to be stoppped.
- * \retval -1 Failed to read data
- * \retval 0 Succeeded in reading data
- */
-static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, struct ast_tcptls_session_instance *tcptls_session,
-			int authenticated, time_t start, struct sip_threadinfo *me)
-{
-	int res, content_length, after_poll = 1, need_poll = 1;
-	size_t datalen = ast_str_strlen(req->data);
-	char buf[1024] = "";
-	int timeout = -1;
-
- 	/* Read in headers one line at a time */
-	while (datalen < 4 || strncmp(REQ_OFFSET_TO_STR(req, data->used - 4), "\r\n\r\n", 4)) {
- 		if (!tcptls_session->client && !authenticated) {
- 			if ((timeout = sip_check_authtimeout(start)) < 0) {
-				ast_debug(2, "SIP TLS server failed to determine authentication timeout\n");
-				return -1;
-			}
-
-			if (timeout == 0) {
-				ast_debug(2, "SIP TLS server timed out\n");
-				return -1;
-			}
-		} else {
-			timeout = -1;
-		}
-
-		/* special polling behavior is required for TLS
-		 * sockets because of the buffering done in the
-		 * TLS layer */
-		if (need_poll) {
-			need_poll = 0;
-			after_poll = 1;
-			res = ast_wait_for_input(tcptls_session->fd, timeout);
-			if (res < 0) {
-				ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res);
-				return -1;
-			} else if (res == 0) {
-				/* timeout */
-				ast_debug(2, "SIP TLS server timed out\n");
-				return -1;
-			}
-		}
-
-		ao2_lock(tcptls_session);
-		if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
-			ao2_unlock(tcptls_session);
-			if (after_poll) {
-				return -1;
-			} else {
-				need_poll = 1;
-				continue;
-			}
-		}
-		ao2_unlock(tcptls_session);
-		after_poll = 0;
-		if (me->stop) {
-			return -1;
-		}
-		ast_str_append(&req->data, 0, "%s", buf);
-
-		datalen = ast_str_strlen(req->data);
-		if (datalen > SIP_MAX_PACKET_SIZE) {
-			ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n",
-				ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
-			return -1;
-		}
-	}
-	copy_request(reqcpy, req);
-	parse_request(reqcpy);
-	/* In order to know how much to read, we need the content-length header */
-	if (sscanf(sip_get_header(reqcpy, "Content-Length"), "%30d", &content_length)) {
-		while (content_length > 0) {
-			size_t bytes_read;
-			if (!tcptls_session->client && !authenticated) {
-				if ((timeout = sip_check_authtimeout(start)) < 0) {
-					return -1;
-				}
-
-				if (timeout == 0) {
-					ast_debug(2, "SIP TLS server timed out\n");
-					return -1;
-				}
-			} else {
-				timeout = -1;
-			}
-
-			if (need_poll) {
-				need_poll = 0;
-				after_poll = 1;
-				res = ast_wait_for_input(tcptls_session->fd, timeout);
-				if (res < 0) {
-					ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res);
-					return -1;
-				} else if (res == 0) {
-					/* timeout */
-					ast_debug(2, "SIP TLS server timed out\n");
-					return -1;
-				}
-			}
-
-			ao2_lock(tcptls_session);
-			if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, content_length), tcptls_session->f))) {
-				ao2_unlock(tcptls_session);
-				if (after_poll) {
-					return -1;
-				} else {
-					need_poll = 1;
-					continue;
-				}
-			}
-			buf[bytes_read] = '\0';
-			ao2_unlock(tcptls_session);
-			after_poll = 0;
-			if (me->stop) {
-				return -1;
-			}
-			content_length -= strlen(buf);
-			ast_str_append(&req->data, 0, "%s", buf);
-
-			datalen = ast_str_strlen(req->data);
-			if (datalen > SIP_MAX_PACKET_SIZE) {
-				ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n",
-					ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
-				return -1;
-			}
-		}
-	}
-	/*! \todo XXX If there's no Content-Length or if the content-length and what
-					we receive is not the same - we should generate an error */
-	return 0;
-}
-
-/*!
  * \brief Indication of a TCP message's integrity
  */
 enum message_integrity {
@@ -3004,7 +2854,7 @@
  * \retval -1 Failed to read data
  * \retval 0 Successfully read data
  */
-static int sip_tcp_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session,
+static int sip_tcptls_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session,
 		int authenticated, time_t start)
 {
 	enum message_integrity message_integrity = MESSAGE_FRAGMENT;
@@ -3022,7 +2872,7 @@
 				}
 
 				if (timeout == 0) {
-					ast_debug(2, "SIP TCP server timed out\n");
+					ast_debug(2, "SIP TCP/TLS server timed out\n");
 					return -1;
 				}
 			} else {
@@ -3030,19 +2880,22 @@
 			}
 			res = ast_wait_for_input(tcptls_session->fd, timeout);
 			if (res < 0) {
-				ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res);
+				ast_debug(2, "SIP TCP/TLS server :: ast_wait_for_input returned %d\n", res);
 				return -1;
 			} else if (res == 0) {
-				ast_debug(2, "SIP TCP server timed out\n");
+				ast_debug(2, "SIP TCP/TLS server timed out\n");
 				return -1;
 			}
 
-			res = recv(tcptls_session->fd, readbuf, sizeof(readbuf) - 1, 0);
+			res = ast_tcptls_server_read(tcptls_session, readbuf, sizeof(readbuf) - 1);
+			while (res < 0 && errno == EAGAIN) {
+				res = ast_tcptls_server_read(tcptls_session, readbuf, sizeof(readbuf) - 1);
+			}
 			if (res < 0) {
-				ast_debug(2, "SIP TCP server error when receiving data\n");
+				ast_debug(2, "SIP TCP/TLS server error when receiving data\n");
 				return -1;
 			} else if (res == 0) {
-				ast_debug(2, "SIP TCP server has shut down\n");
+				ast_debug(2, "SIP TCP/TLS server has shut down\n");
 				return -1;
 			}
 			readbuf[res] = '\0';
@@ -3054,7 +2907,7 @@
 
 		datalen = ast_str_strlen(req->data);
 		if (datalen > SIP_MAX_PACKET_SIZE) {
-			ast_log(LOG_WARNING, "Rejecting TCP packet from '%s' because way too large: %zu\n",
+			ast_log(LOG_WARNING, "Rejecting TCP/TLS packet from '%s' because way too large: %zu\n",
 				ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
 			return -1;
 		}
@@ -3220,11 +3073,7 @@
 				req.socket.port = htons(ourport_tcp);
 			}
 			req.socket.fd = tcptls_session->fd;
-			if (tcptls_session->ssl) {
-				res = sip_tls_read(&req, &reqcpy, tcptls_session, authenticated, start, me);
-			} else {
-				res = sip_tcp_read(&req, tcptls_session, authenticated, start);
-			}
+			res = sip_tcptls_read(&req, tcptls_session, authenticated, start);
 
 			if (res < 0) {
 				goto cleanup;
