> :::: _sip_tcp_helper_thread > :::: sip_threadinfo_create > :::: _sip_tcp_helper_thread > sip_tcp_read > :::: sip_tcp_read > :::: sip_tcp_read while MESSAGE_FRAGMENT > :::: sip_tcp_read while MESSAGE_FRAGMENT overflow_buf is empty > :::: sip_tcp_read while MESSAGE_FRAGMENT read data size is 1789 INVITE sip:7799006148@10.51.50.154;transport=tcp;user=phone SIP/2.0 Via: SIP/2.0/TCP 10.34.100.10:5060;branch=z9hG4bKunaa1zuqvzvurvppx1vetvpe8;X-DispMsg=1430 Route: Call-ID: 8ssnrzp11evspguugpnqv1zasvqptttv@10.18.5.64 From: "99690130";tag=1rtevgxr-CC-1040-OFC-13 To: "7799006148" CSeq: 1 INVITE P-Access-Network-Info: GEN-ACCESS;"area-number=+965" Max-Forwards: 70 Contact: Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,INFO,PRACK,NOTIFY,MESSAGE,REFER,UPDATE P-Asserted-Identity: P-Early-Media: supported Supported: 100rel,timer,histinfo,precondition Min-SE: 90 Session-Expires: 1800;refresher=uac Content-Length: 924 Content-Type: multipart/mixed;boundary=ssboundary --ssboundary Content-Length: 699 Content-Type: application/sdp v=0 o=HuaweiSoftx3000 1073957350 1073957351 IN IP4 10.34.100.10 s=SipCall c=IN IP4 10.34.101.73 t=0 0 m=audio 53204 RTP/AVP 100 108 105 3 96 107 8 116 a=rtpmap:100 AMR/8000 a=fmtp:100 mode-set=0,2,4,7;mode-change-neighbor=1;mode-change-period=2 a=rtpmap:108 AMR/8000 a=fmtp:108 mode-set=7 a=rtpmap:105 GSM-EFR/8000 a=rtpmap:3 GSM/8000 a=rtpmap:96 AMR/8000 a=fmtp:96 mode-set=0,2,4;mode-change-neighbor=1;mode-change-period=2 a=rtpmap:107 AMR/8000 a=fmtp:107 mode-set=4 a=rtpmap:8 PCMA/8000 a=rtpmap:116 telephone-event/8000 a=ptime:20 a=maxptime:20 a=curr:qos local none a=curr:qos remote none a=des:qos mandatory local sendrecv a=des:qos optional remote sendrecv a=3gOoBTC --ssboundary Content-Length: 59 Content-Type: application/isup;version=CHN ` > :::: sip_tcp_read > 1719 INVITE sip:7799006148@10.51.50.154;transport=tcp;user=phone SIP/2.0 Via: SIP/2.0/TCP 10.34.100.10:5060;branch=z9hG4bKunaa1zuqvzvurvppx1vetvpe8;X-DispMsg=1430 Route: Call-ID: 8ssnrzp11evspguugpnqv1zasvqptttv@10.18.5.64 From: "99690130";tag=1rtevgxr-CC-1040-OFC-13 To: "7799006148" CSeq: 1 INVITE P-Access-Network-Info: GEN-ACCESS;"area-number=+965" Max-Forwards: 70 Contact: Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,INFO,PRACK,NOTIFY,MESSAGE,REFER,UPDATE P-Asserted-Identity: P-Early-Media: supported Supported: 100rel,timer,histinfo,precondition Min-SE: 90 Session-Expires: 1800;refresher=uac Content-Length: 924 Content-Type: multipart/mixed;boundary=ssboundary --ssboundary Content-Length: 699 Content-Type: application/sdp v=0 o=HuaweiSoftx3000 1073957350 1073957351 IN IP4 10.34.100.10 s=SipCall c=IN IP4 10.34.101.73 t=0 0 m=audio 53204 RTP/AVP 100 108 105 3 96 107 8 116 a=rtpmap:100 AMR/8000 a=fmtp:100 mode-set=0,2,4,7;mode-change-neighbor=1;mode-change-period=2 a=rtpmap:108 AMR/8000 a=fmtp:108 mode-set=7 a=rtpmap:105 GSM-EFR/8000 a=rtpmap:3 GSM/8000 a=rtpmap:96 AMR/8000 a=fmtp:96 mode-set=0,2,4;mode-change-neighbor=1;mode-change-period=2 a=rtpmap:107 AMR/8000 a=fmtp:107 mode-set=4 a=rtpmap:8 PCMA/8000 a=rtpmap:116 telephone-event/8000 a=ptime:20 a=maxptime:20 a=curr:qos local none a=curr:qos remote none a=des:qos mandatory local sendrecv a=des:qos optional remote sendrecv a=3gOoBTC --ssboundary Content-Length: 59 Content-Type: application/isup;version=CHN ` > :::: read_raw_content_length > ::::: lws2sws > :::: read_raw_content_length str[ 924 Content-Type: multipart/mixed;boundary=ssboundary ] int[924] > :::: check_message_integrity message_len[1719] body_len[854] > read_raw_content_length > content_length[924] > :::: check_message_integrity body_len[854] < content_length [924] < 0 i.e MESSAGE_FRAGMENT > :::: sip_tcp_read while MESSAGE_FRAGMENT > :::: sip_tcp_read while MESSAGE_FRAGMENT overflow_buf is empty !echo waiting $(date) waiting Wed Dec 7 12:02:18 AST 2016 *CLI> !echo waiting $(date) waiting Wed Dec 7 12:02:29 AST 2016 > :::: _sip_tcp_helper_thread > sip_tcp_read < back & data read is -1 > :::: sip_threadinfo_destructor > ::::: deinit_req > ::::: deinit_req ===================================================================================== /*! * \brief Check that a message received over TCP is a full message * * This will take the information read in and then determine if * 1) The message is a full SIP request * 2) The message is a partial SIP request * 3) The message contains a full SIP request along with another partial request * \param data The unparsed incoming SIP message. * \param request The resulting request with extra fragments removed. * \param overflow If the message contains more than a full request, this is the remainder of the message * \return The resulting integrity of the message */ static enum message_integrity check_message_integrity(struct ast_str **request, struct ast_str **overflow) { char *message = ast_str_buffer(*request); char *body; int content_length; int message_len = ast_str_strlen(*request); int body_len; /* Important pieces to search for in a SIP request are \r\n\r\n. This * marks either * 1) The division between the headers and body * 2) The end of the SIP request */ body = strstr(message, "\r\n\r\n"); if (!body) { ast_verb(4, " :::: check_message_integrity > body doesnot ends with 2 consecutive newline characters\n"); /* This is clearly a partial message since we haven't reached an end * yet. */ return MESSAGE_FRAGMENT; } body += sizeof("\r\n\r\n") - 1; body_len = message_len - (body - message); body[-1] = '\0'; content_length = read_raw_content_length(message); body[-1] = '\n'; ast_verb(4, " :::: check_message_integrity message_len[%d] body_len[%d] > read_raw_content_length > content_length[%d]\n", message_len, body_len, content_length); if (content_length < 0) { ast_verb(4, " :::: check_message_integrity body_len[%d] > content_length [%d] < 0 i.e MESSAGE_INVALID\n", body_len, content_length); return MESSAGE_INVALID; } else if (content_length == 0) { /* We've definitely received an entire message. We need * to check if there's also a fragment of another message * in addition. */ if (body_len == 0) { ast_verb(4, " :::: check_message_integrity body_len=content_length=0 i.e MESSAGE_COMPLETE\n"); return MESSAGE_COMPLETE; } else { ast_verb(4, " :::: check_message_integrity body_len<>0 BUT content_length=0 i.e MESSAGE_FRAGMENT_COMPLETE\n"); ast_str_append(overflow, 0, "%s", body); ast_str_truncate(*request, message_len - body_len); return MESSAGE_FRAGMENT_COMPLETE; } } /* Positive content length. Let's see what sort of * message body we're dealing with. */ if (body_len < content_length) { ast_verb(4, " :::: check_message_integrity body_len[%d] < content_length [%d] < 0 i.e MESSAGE_FRAGMENT\n", body_len, content_length); /* We don't have the full message body yet */ return MESSAGE_FRAGMENT; } else if (body_len > content_length) { ast_verb(4, " :::: check_message_integrity body_len[%d] > content_length [%d] < 0 i.e MESSAGE_FRAGMENT_COMPLETE\n", body_len, content_length); /* We have the full message plus a fragment of a further * message */ ast_str_append(overflow, 0, "%s", body + content_length); ast_str_truncate(*request, message_len - (body_len - content_length)); return MESSAGE_FRAGMENT_COMPLETE; } else { ast_verb(4, " :::: check_message_integrity ELSE i.e. MESSAGE_COMPLETE\n"); /* Yay! Full message with no extra content */ return MESSAGE_COMPLETE; } } /*! * \brief Read SIP request or response from a TCP connection * * \param req The request structure to be filled in * \param tcptls_session The TCP connection from which to read * \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, int authenticated, time_t start) { ast_verb(4, " :::: sip_tcp_read\n"); enum message_integrity message_integrity = MESSAGE_FRAGMENT; while (message_integrity == MESSAGE_FRAGMENT) { ast_verb(4, " :::: sip_tcp_read while MESSAGE_FRAGMENT\n"); size_t datalen; if (ast_str_strlen(tcptls_session->overflow_buf) == 0) { ast_verb(4, " :::: sip_tcp_read while MESSAGE_FRAGMENT overflow_buf is empty\n"); char readbuf[4097]; int timeout; int res; if (!tcptls_session->client && !authenticated) { if ((timeout = sip_check_authtimeout(start)) < 0) { return -1; } if (timeout == 0) { ast_debug(2, "SIP TCP server timed out\n"); return -1; } } else { timeout = -1; } 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); return -1; } else if (res == 0) { ast_debug(2, "SIP TCP server timed out\n"); return -1; } res = recv(tcptls_session->fd, readbuf, sizeof(readbuf) - 1, 0); if (res < 0) { // : copied from v13.4 in effort to solve the incomplete message-length issue :: did not help at all if (errno == EAGAIN || errno == EINTR) { continue; } ast_debug(2, "SIP TCP server error when receiving data\n"); return -1; } else if (res == 0) { ast_debug(2, "SIP TCP server has shut down\n"); return -1; } readbuf[res] = '\0'; ast_str_append(&req->data, 0, "%s", readbuf); ast_verb(4, " :::: sip_tcp_read while MESSAGE_FRAGMENT read data size is %d\n%s\n", res, readbuf); } else { ast_verb(4, " :::: sip_tcp_read while MESSAGE_FRAGMENT overflow_buf is NOT empty\n"); ast_str_append(&req->data, 0, "%s", ast_str_buffer(tcptls_session->overflow_buf)); ast_str_reset(tcptls_session->overflow_buf); } 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_sockaddr_stringify(&tcptls_session->remote_address), datalen); return -1; } ast_verb(4, " :::: sip_tcp_read > %zu\n%s<- ->\n", datalen, ast_str_buffer(req->data)); message_integrity = check_message_integrity(&req->data, &tcptls_session->overflow_buf); } return 0; }