![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_network.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
Definition in file sip3_network.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"
Include dependency graph for sip3_network.c:

Go to the source code of this file.
Data Structures | |
| struct | sip_queue_item |
Functions | |
| static enum sip_result | __sip_reliable_xmit (struct sip_network *sipnet, struct sip_dialog *dialog, int resp, struct sip_request *req, int fatal) |
| Transmit packet with retransmits. | |
| static int | __sip_xmit (struct sip_network *sipnet, struct sip_dialog *p, struct sip_request *req) |
| Transmit SIP message. | |
| static void | append_send_history (struct sip_dialog *dialog, struct sip_request *req, struct sip_network *sipnet, int reliable, int response) |
| Append history of sending request or response to dialog. | |
| static | AST_LIST_HEAD_STATIC (sip_queue, sip_queue_item) |
| int | close_sip_sockets () |
| Close all open network sockets. | |
| static void | parse_copy (struct sip_request *dst, const struct sip_request *src) |
| Copy SIP request, pre-parse it. | |
| void | process_sip_queue () |
| Process one item off the SIP queue. | |
| static void | queue_sip_request (struct sip_request *request, struct sockaddr_in *sin) |
| queue incoming SIP request onto sip_queue for processing | |
| void | reset_ip_interface (struct sip_network *sipnet) |
| clear IP interfaces | |
| static int | retrans_pkt (void *data) |
| Retransmit SIP message if no answer (Called from scheduler). | |
| int | send_request (struct sip_dialog *p, struct sip_request *req, enum xmittype reliable) |
| Send SIP Request to the other part of the dialogue. | |
| int | send_response (struct sip_dialog *p, struct sip_request *req, enum xmittype reliable) |
| Transmit response on SIP request. | |
| int | sip_debug_test_addr (const struct sockaddr_in *addr) |
| See if we pass debug IP filter. | |
| int | sip_debug_test_level (int sipmethod) |
| int | sip_debug_test_pvt (struct sip_dialog *p) |
| Test PVT for debugging output. | |
| enum sip_result | sip_ouraddrfor (struct in_addr *them, struct in_addr *us) |
| NAT fix - decide which IP address to use for Asterisk server? | |
| const struct sockaddr_in * | sip_real_dst (const struct sip_dialog *p) |
| The real destination address for a write. | |
| void | sipnet_lock (struct sip_network *sipnet) |
| Lock netlock. | |
| static void | sipnet_lock_init (struct sip_network *sipnet) |
| Initialize network lock. | |
| int | sipnet_ourport (struct sip_network *sipnet) |
| read our port number | |
| void | sipnet_ourport_set (struct sip_network *sipnet, int port) |
| Set our port number. | |
| void | sipnet_unlock (struct sip_network *sipnet) |
| Unlock netlock. | |
| sip_request * | siprequest_alloc (size_t len, struct sip_network *sipnet) |
| Allocate SIP request structure. | |
| void | siprequest_free (struct sip_request *req) |
| Free SIP request. | |
| int | sipsock_init (struct sip_network *sipnet, struct sockaddr_in *old_bindaddr) |
| Initialize IP socket on configured address - the bind address. | |
| int | sipsock_read (int *id, int fd, short events, void *ignore) |
| Read data from SIP socket. | |
| int | sipsocket_initialized (struct sip_network *sipnet) |
| Check if network socket is open. | |
| int | sipsocket_open (struct sip_network *sipnet) |
| Open network socket, bind to address and set options (TOS). | |
Variables | |
| sip_globals | global |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| sip_network | sipnet |
|
||||||||||||||||||||||||
|
Transmit packet with retransmits.
Definition at line 623 of file sip3_network.c. References __sip_xmit(), AST_FAILURE, ast_log(), ast_sched_add_variable(), ast_set_flag, AST_SUCCESS, DEFAULT_RETRANS, sip_request::dialog, LOG_DEBUG, sip_request::next, option_debug, sip_dialog::packets, sip_dialog::pendinginvite, retrans_pkt(), SIP_INVITE, SIP_PKT_CONNECTED, SIP_PKT_FATAL, SIP_PKT_RESPONSE, sipdebug, sipnet, and sip_dialog::timer_t1. 00625 { 00626 int siptimer_a = DEFAULT_RETRANS; 00627 enum sip_result res= AST_FAILURE; 00628 00629 ast_set_flag(req, SIP_PKT_CONNECTED); /* Stop sipsock_read from free'ing this request */ 00630 req->next = dialog->packets; 00631 req->dialog = dialog; 00632 if (resp) 00633 ast_set_flag(req, SIP_PKT_RESPONSE); 00634 req->timer_t1 = dialog->timer_t1; /* Set SIP timer T1 */ 00635 /* If this is critical for the success of this transaction, mark it FATAL 00636 the dialog will fail if this is not accepted */ 00637 if (fatal) 00638 ast_set_flag(req, SIP_PKT_FATAL); 00639 if (req->timer_t1) 00640 siptimer_a = req->timer_t1 * 2; 00641 00642 /* Schedule retransmission */ 00643 req->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, req, 1); 00644 00645 if (option_debug > 3 && sipdebug) 00646 ast_log(LOG_DEBUG, "*** SIP TIMER: Initalizing retransmit timer on packet: Id #%d\n", req->retransid); 00647 /* XXX Are we locked? Any chance of messing up here? */ 00648 req->next = dialog->packets; 00649 dialog->packets = req; 00650 00651 /* Send packet */ 00652 if (!__sip_xmit(sipnet, req->dialog, req)) 00653 res = AST_FAILURE; 00654 else 00655 res = AST_SUCCESS; 00656 00657 00658 if (req->method == SIP_INVITE) { 00659 /* Note this is a pending invite */ 00660 dialog->pendinginvite = req->seqno; 00661 } 00662 return res; 00663 }
|
|
||||||||||||||||
|
Transmit SIP message.
Definition at line 480 of file sip3_network.c. References ast_inet_ntoa(), ast_log(), sip_request::data, sip_request::len, LOG_WARNING, sip_real_dst(), sipnet, and sip_network::sipsock. 00481 { 00482 int res; 00483 const struct sockaddr_in *dst = sip_real_dst(p); 00484 00485 /* XXX in the future, we need to make sure we follow the current flow for this dialog - TCP, UDP */ 00486 res = sendto(sipnet->sipsock, req->data, req->len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); 00487 00488 if (res != req->len) { 00489 ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", req->data, req->len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno)); 00490 /* If one of this errors are returned, we should propably 00491 cancel retransmits and give up */ 00492 if (errno == EHOSTUNREACH) { /* No route to host */ 00493 } 00494 if (errno == EHOSTDOWN) { /* No route to host */ 00495 } 00496 return -1; 00497 } 00498 return 0; 00499 }
|
|
||||||||||||||||||||||||
|
Append history of sending request or response to dialog.
Definition at line 691 of file sip3_network.c. References append_history, sip_request::data, sip_request::data_size, sip_request::dialog, get_header(), sip_request::method, parse_copy(), sip_request::rlPart2, sip_method2txt(), SIP_RESPONSE, SIP_UNKNOWN, sipnet, siprequest_alloc(), and siprequest_free(). Referenced by send_request(), and send_response(). 00692 { 00693 struct sip_request *tmp; 00694 00695 tmp = siprequest_alloc(req->data_size, sipnet); 00696 parse_copy(tmp, req); 00697 if (response) 00698 append_history(dialog, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp->data, get_header(tmp, "CSeq"), 00699 (tmp->method == SIP_RESPONSE || tmp->method == SIP_UNKNOWN) ? tmp->rlPart2 : sip_method2txt(tmp->method)); 00700 else 00701 append_history(dialog, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp->data, get_header(tmp, "CSeq"), sip_method2txt(tmp->method)); 00702 siprequest_free(tmp); 00703 }
|
|
||||||||||||
|
|
|
|
Close all open network sockets.
Definition at line 185 of file sip3_network.c. References sipnet, sip_network::sipsock, and TRUE.
|
|
||||||||||||
|
Copy SIP request, pre-parse it.
Definition at line 666 of file sip3_network.c. References ast_calloc, sip_request::data, sip_request::data_size, free, sip_request::len, and parse_request(). 00667 { 00668 memset(dst, 0, sizeof(*dst)); 00669 /* If we have data memory allocated in destination, check if it's 00670 enough. Otherwise, release it */ 00671 if (dst->data && dst->data_size <= src->data_size) 00672 free(dst->data); 00673 00674 /* Allocate memory if we don't have any or not enough */ 00675 if (!dst->data) { 00676 dst->data = ast_calloc(1, src->data_size); 00677 dst->data_size = src->data_size; 00678 } 00679 00680 /* Copy data block */ 00681 memcpy(dst->data, src->data, dst->data_size); 00682 00683 dst->len = src->len; 00684 parse_request(dst); 00685 }
|
|
|
Process one item off the SIP queue.
Definition at line 338 of file sip3_network.c. References append_history, ast_channel_trylock, ast_channel_unlock, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_test_flag, ast_update_use_count(), sip_request::data, dialog_lock(), FALSE, sip_dialog::flags, free, get_header(), handle_request(), sip_request::len, LOG_DEBUG, LOG_ERROR, match_or_create_dialog(), sip_request::method, option_debug, sip_dialog::owner, sip_dialog::recv, sip_queue_item::request, sip_request::rlPart2, sip_queue_item::sin, SIP_NO_HISTORY, SIP_PKT_CONNECTED, SIP_PKT_INITREQ, sipnet, sipnet_lock(), sipnet_unlock(), and transmit_response(). Referenced by sipsock_read(). 00339 { 00340 struct sip_request *req; 00341 struct sip_queue_item *item; 00342 struct sockaddr_in *sin; 00343 struct sip_dialog *p; 00344 int nounlock; 00345 int recount = 0; 00346 unsigned int lockretry = 100; 00347 00348 /* Anything to process? */ 00349 if (AST_LIST_EMPTY(&sip_queue)) 00350 return; 00351 00352 AST_LIST_LOCK(&sip_queue); 00353 item = AST_LIST_REMOVE_HEAD(&sip_queue, list); 00354 AST_LIST_UNLOCK(&sip_queue); 00355 00356 req = item->request; 00357 sin = &item->sin; 00358 00359 /* Process request, with netlock held */ 00360 retrylock: 00361 sipnet_lock(&sipnet); 00362 00363 /* Find the active SIP dialog or create a new one */ 00364 p = match_or_create_dialog(req, sin, req->method); /* returns p locked */ 00365 if (p == NULL) { 00366 if (option_debug) 00367 ast_log(LOG_DEBUG, "Invalid SIP message - rejected , no callid, len %d\n", req->len); 00368 } else { 00369 /* Go ahead and lock the owner if it has one -- we may need it */ 00370 /* becaues this is deadlock-prone, we need to try and unlock if failed */ 00371 if (p->owner && ast_channel_trylock(p->owner)) { 00372 if (option_debug) 00373 ast_log(LOG_DEBUG, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid); 00374 dialog_lock(p, FALSE); 00375 sipnet_unlock(&sipnet); 00376 /* Sleep for a very short amount of time */ 00377 usleep(1); 00378 if (--lockretry) 00379 goto retrylock; 00380 } 00381 p->recv = item->sin; 00382 00383 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) /* This is a request or response, note what it was for */ 00384 append_history(p, "Rx", "%s / %s / %s", req->data, get_header(req, "CSeq"), req->rlPart2); 00385 00386 if (!lockretry) { 00387 ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", p->owner->name ? p->owner->name : "- no channel name ??? - "); 00388 ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid); 00389 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 00390 /* XXX We could add retry-after to make sure they come back */ 00391 append_history(p, "LockFail", "Owner lock failed, transaction failed."); 00392 sipnet_unlock(&sipnet); 00393 return; 00394 } 00395 nounlock = 0; 00396 if (handle_request(p, req, sin, &recount, &nounlock) == -1) { 00397 /* Request failed */ 00398 if (option_debug) 00399 ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 00400 } 00401 00402 if (p->owner && !nounlock) 00403 ast_channel_unlock(p->owner); 00404 dialog_lock(p, FALSE); 00405 } 00406 sipnet_unlock(&sipnet); 00407 if (recount) 00408 ast_update_use_count(); 00409 00410 /* If this packet is not connected to a dialog, then free it. If it is connected, 00411 then let the dialog destroy it later */ 00412 if (!ast_test_flag(req, SIP_PKT_CONNECTED) && !ast_test_flag(req, SIP_PKT_INITREQ)) { 00413 free(req->data); 00414 free(req); 00415 } 00416 00417 return; 00418 }
|
|
||||||||||||
|
queue incoming SIP request onto sip_queue for processing
Definition at line 238 of file sip3_network.c. References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, sip_queue_item::request, and sip_queue_item::sin. Referenced by sipsock_read(). 00239 { 00240 struct sip_queue_item *item = ast_calloc(1, sizeof(struct sip_queue_item)); 00241 00242 item->request = request; 00243 /* Save IP address received from - hmm, maybe should be stored in the request instead */ 00244 item->sin = *sin; 00245 AST_LIST_LOCK(&sip_queue); 00246 AST_LIST_INSERT_TAIL(&sip_queue, item, list); 00247 AST_LIST_UNLOCK(&sip_queue); 00248 }
|
|
|
|
Retransmit SIP message if no answer (Called from scheduler).
Definition at line 503 of file sip3_network.c. References __sip_xmit(), append_history, ast_channel_trylock, ast_channel_unlock, ast_inet_ntoa(), ast_log(), ast_queue_hangup(), ast_set_flag, ast_test_flag, ast_verbose(), sip_request::data, DEFAULT_RETRANS, sip_request::dialog, dialog_lock(), FALSE, sip_dialog::flags, global, LOG_DEBUG, LOG_WARNING, MAX_RETRANS, sip_request::method, sip_request::next, option_debug, option_verbose, sip_dialog::owner, sip_dialog::packets, sip_request::retrans, sip_request::retransid, SIP_ALREADYGONE, sip_debug_test_pvt(), SIP_INVITE, sip_method2txt(), sip_nat_mode(), SIP_NEEDDESTROY, SIP_OPTIONS, SIP_PKT_FATAL, SIP_PKT_RESPONSE, sip_real_dst(), sipdebug, sipnet, siprequest_free(), sip_globals::t2default, sip_request::timer_a, sip_request::timer_t1, and TRUE. 00504 { 00505 struct sip_request *pkt = data, *prev, *cur = NULL; 00506 int reschedule = DEFAULT_RETRANS; 00507 00508 if (!pkt->dialog) { 00509 ast_log(LOG_WARNING, "Trying to retransmit packet without dialog owner... id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_method2txt(pkt->method), pkt->method); 00510 return 0; 00511 } 00512 /* Lock channel PVT */ 00513 dialog_lock(pkt->dialog, TRUE); 00514 00515 if (pkt->retrans < MAX_RETRANS) { 00516 pkt->retrans++; 00517 if (!pkt->timer_t1) { /* Re-schedule using timer_a and timer_t1 */ 00518 if (sipdebug && option_debug > 3) 00519 ast_log(LOG_DEBUG, "SIP TIMER: Not rescheduling id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_method2txt(pkt->method), pkt->method); 00520 } else { 00521 int siptimer_a; 00522 00523 if (sipdebug && option_debug > 3) 00524 ast_log(LOG_DEBUG, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_method2txt(pkt->method), pkt->method); 00525 if (!pkt->timer_a) 00526 pkt->timer_a = 2 ; 00527 else 00528 pkt->timer_a = 2 * pkt->timer_a; 00529 00530 /* For non-invites, a maximum of 4 secs */ 00531 siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ 00532 /* Timer T2 - maximum retransmit time for non-invite requests */ 00533 if (pkt->method != SIP_INVITE && siptimer_a > global.t2default) 00534 siptimer_a = global.t2default; /* T2 defaults to 4 secs */ 00535 00536 /* Reschedule re-transmit */ 00537 reschedule = siptimer_a; 00538 if (option_debug > 3) 00539 ast_log(LOG_DEBUG, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid); 00540 } 00541 00542 if (sip_debug_test_pvt(pkt->dialog)) { 00543 const struct sockaddr_in *dst = sip_real_dst(pkt->dialog); 00544 ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n", 00545 pkt->retrans, sip_nat_mode(pkt->dialog), 00546 ast_inet_ntoa(dst->sin_addr), 00547 ntohs(dst->sin_port), pkt->data); 00548 } 00549 00550 if(!__sip_xmit(&sipnet, pkt->dialog, pkt)) { 00551 append_history(pkt->dialog, "ReTx", "%d %s", reschedule, pkt->data); 00552 /* success. Go on as before */ 00553 dialog_lock(pkt->dialog, FALSE); 00554 return reschedule; 00555 } 00556 /* Houston, we do have a problem. give up and stop 00557 retransmitting. Issue a warning only if we have verbosity. 00558 */ 00559 if (option_verbose > 1) 00560 ast_log(LOG_WARNING, "Network failure transmitting to host, giving up retransmissions.\n"); 00561 append_history(pkt->dialog, "ReTxCancel", "Cancelled retransmits. Network problem."); 00562 /* Fall through */ 00563 } 00564 /* Too many retries */ 00565 if (pkt->dialog && pkt->method != SIP_OPTIONS) { 00566 if (ast_test_flag(pkt, SIP_PKT_FATAL) || sipdebug) /* Tell us if it's critical or if we're debugging */ 00567 ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s)\n", pkt->dialog->callid, pkt->seqno, (ast_test_flag(pkt, SIP_PKT_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, SIP_PKT_RESPONSE)) ? "Response" : "Request"); 00568 } else { 00569 if ((pkt->method == SIP_OPTIONS) && sipdebug) 00570 ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->dialog->callid); 00571 } 00572 if (pkt->retrans == MAX_RETRANS) 00573 append_history(pkt->dialog, "MaxRetries", "%s", (ast_test_flag(pkt, SIP_PKT_FATAL)) ? "(Critical)" : "(Non-critical)"); 00574 00575 pkt->retransid = -1; 00576 00577 if (ast_test_flag(pkt, SIP_PKT_FATAL)) { 00578 while(pkt->dialog->owner && ast_channel_trylock(pkt->dialog->owner)) { 00579 dialog_lock(pkt->dialog, FALSE); 00580 usleep(1); 00581 dialog_lock(pkt->dialog, TRUE); 00582 } 00583 if (pkt->dialog->owner) { 00584 ast_set_flag(&pkt->dialog->flags[0], SIP_ALREADYGONE); 00585 ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->dialog->callid); 00586 ast_queue_hangup(pkt->dialog->owner); 00587 ast_channel_unlock(pkt->dialog->owner); 00588 } else { 00589 /* If no channel owner, destroy now 00590 ...unless it's a SIP options packet, where 00591 we want the peerpoke expiry routine handle this. 00592 */ 00593 if (pkt->method != SIP_OPTIONS) 00594 ast_set_flag(&pkt->dialog->flags[0], SIP_NEEDDESTROY); 00595 } 00596 } 00597 /* In any case, go ahead and remove the packet */ 00598 for (prev = NULL, cur = pkt->dialog->packets; cur; prev = cur, cur = cur->next) { 00599 if (cur == pkt) 00600 break; 00601 } 00602 if (cur) { 00603 if (prev) 00604 prev->next = cur->next; 00605 else 00606 pkt->dialog->packets = cur->next; 00607 dialog_lock(pkt->dialog, FALSE); 00608 if (option_debug > 3) 00609 ast_log(LOG_DEBUG, "Deleting packet from dialog list...%s\n", pkt->dialog->callid); 00610 siprequest_free(cur); 00611 pkt = NULL; 00612 } else 00613 ast_log(LOG_WARNING, "Weird, couldn't find packet dialog!\n"); 00614 if (pkt) 00615 dialog_lock(pkt->dialog, FALSE); 00616 return 0; 00617 }
|
|
||||||||||||||||
|
Send SIP Request to the other part of the dialogue.
Definition at line 731 of file sip3_network.c. References __sip_reliable_xmit(), __sip_xmit(), add_blank(), append_send_history(), ast_inet_ntoa(), ast_test_flag, ast_verbose(), sip_request::data, FALSE, sip_dialog::flags, sip_request::len, sip_dialog::recv, sip_dialog::sa, sip_debug_test_pvt(), SIP_NAT_ROUTE, SIP_NO_HISTORY, and sipnet. 00732 { 00733 int res; 00734 00735 add_blank(req); 00736 if (sip_debug_test_pvt(p)) { 00737 if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) 00738 ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data); 00739 else 00740 ast_verbose("--- %sTransmitting (no NAT) to %s:%d (size %u):\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->len, req->data); 00741 } 00742 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) 00743 append_send_history(p, req, &sipnet, reliable, FALSE); 00744 res = (reliable) ? 00745 __sip_reliable_xmit(&sipnet, p, 0, req, (reliable > 1)) : 00746 __sip_xmit(&sipnet, p, req); 00747 return res; 00748 }
|
|
||||||||||||||||
|
Transmit response on SIP request.
Definition at line 706 of file sip3_network.c. References __sip_reliable_xmit(), __sip_xmit(), add_blank(), append_send_history(), ast_inet_ntoa(), ast_test_flag, ast_verbose(), sip_request::data, sip_dialog::flags, sip_debug_test_pvt(), sip_nat_mode(), SIP_NO_HISTORY, sip_real_dst(), sipnet, TRUE, and XMIT_CRITICAL. 00707 { 00708 int res; 00709 00710 add_blank(req); 00711 if (sip_debug_test_pvt(p)) { 00712 const struct sockaddr_in *dst = sip_real_dst(p); 00713 00714 ast_verbose("%sTransmitting (%s) to %s:%d:\n%s\n---\n", 00715 reliable ? "Reliably " : "", sip_nat_mode(p), 00716 ast_inet_ntoa(dst->sin_addr), 00717 ntohs(dst->sin_port), req->data); 00718 } 00719 /* This is stupid - allocate a copy of the request just to add history... */ 00720 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) 00721 append_send_history(p, req, &sipnet, reliable, TRUE); 00722 res = (reliable) ? 00723 __sip_reliable_xmit(&sipnet, p, 1, req, (reliable == XMIT_CRITICAL)) : 00724 __sip_xmit(&sipnet, p, req); 00725 if (res > 0) 00726 return 0; 00727 return res; 00728 }
|
|
|
See if we pass debug IP filter.
Definition at line 758 of file sip3_network.c. References sip_network::debugaddr, sipdebug, and sipnet. 00759 { 00760 if (!sipdebug) 00761 return 0; 00762 if (sipnet.debugaddr.sin_addr.s_addr) { 00763 if (((ntohs(sipnet.debugaddr.sin_port) != 0) 00764 && (sipnet.debugaddr.sin_port != addr->sin_port)) 00765 || (sipnet.debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00766 return 0; 00767 } 00768 return 1; 00769 }
|
|
|
Check if the method given is included in DEBUG Definition at line 772 of file sip3_network.c. References sip_globals::debuglevel, FALSE, global, SIP_ACK, SIP_BYE, SIP_CANCEL, SIP_INVITE, SIP_OPTIONS, SIP_REFER, SIPDEBUG_ALL, SIPDEBUG_NOPOKE, and TRUE. Referenced by sipsock_read(). 00773 { 00774 /* 00775 SIPDEBUG_ALL = 0, All requests and responses 00776 SIPDEBUG_CALLS, INVITE, CANCEL, ACK & BYE 00777 SIPDEBUG_NOPOKE, Everything BUT OPTIONS 00778 */ 00779 if (global.debuglevel == SIPDEBUG_ALL) { 00780 return TRUE; 00781 } 00782 if (global.debuglevel == SIPDEBUG_NOPOKE) { 00783 if (sipmethod == SIP_OPTIONS) 00784 return FALSE; 00785 return TRUE; 00786 } 00787 /* Ok, we need everything basic related to calls (no REGISTER, NOTIFY, OPTIONS or SUBSCRIBE stuff) */ 00788 if (sipmethod == SIP_INVITE || sipmethod == SIP_CANCEL || sipmethod == SIP_REFER || sipmethod == SIP_BYE || sipmethod == SIP_ACK) 00789 return TRUE; 00790 return FALSE; 00791 }
|
|
|
Test PVT for debugging output.
Definition at line 794 of file sip3_network.c. References sip_debug_test_addr(), sip_real_dst(), and sipdebug. 00795 { 00796 if (!sipdebug) 00797 return 0; 00798 return sip_debug_test_addr(sip_real_dst(p)); 00799 }
|
|
||||||||||||
|
NAT fix - decide which IP address to use for Asterisk server? Using the localaddr structure built up with localnet statements in sip.conf apply it to their address to see if we need to substitute our externip or can get away with our internal bindaddr Definition at line 807 of file sip3_network.c. References ahp, ast_apply_ha(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_ouraddrfor(), AST_SUCCESS, sip_network::bindaddr, sip_network::externexpire, sip_network::externhost, sip_network::externip, sip_network::externrefresh, hp, sip_network::localaddr, LOG_DEBUG, LOG_NOTICE, option_debug, and sipnet. Referenced by sip_alloc(), sip_poke_peer(), sip_send_mwi_to_peer(), transmit_register(), and transmit_response_using_temp(). 00808 { 00809 struct sockaddr_in theirs, ours; 00810 00811 /* Get our local information */ 00812 ast_ouraddrfor(them, us); 00813 theirs.sin_addr = *them; 00814 ours.sin_addr = *us; 00815 00816 if (sipnet.localaddr && sipnet.externip.sin_addr.s_addr && 00817 ast_apply_ha(sipnet.localaddr, &theirs) && 00818 !ast_apply_ha(sipnet.localaddr, &ours)) { 00819 if (sipnet.externexpire && time(NULL) >= sipnet.externexpire) { 00820 struct ast_hostent ahp; 00821 struct hostent *hp; 00822 00823 sipnet.externexpire = time(NULL) + sipnet.externrefresh; 00824 if ((hp = ast_gethostbyname(sipnet.externhost, &ahp))) { 00825 memcpy(&sipnet.externip.sin_addr, hp->h_addr, sizeof(sipnet.externip.sin_addr)); 00826 } else 00827 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", sipnet.externhost); 00828 } 00829 *us = sipnet.externip.sin_addr; 00830 if (option_debug) { 00831 ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", 00832 ast_inet_ntoa(*(struct in_addr *)&them->s_addr)); 00833 } 00834 } else if (sipnet.bindaddr.sin_addr.s_addr) 00835 *us = sipnet.bindaddr.sin_addr; 00836 return AST_SUCCESS; 00837 }
|
|
|
The real destination address for a write.
Definition at line 751 of file sip3_network.c. References ast_test_flag, sip_dialog::flags, sip_dialog::recv, sip_dialog::sa, SIP_NAT, and SIP_NAT_ROUTE. 00752 { 00753 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa; 00754 }
|
|
|
Lock netlock. Lock netlock mutex Definition at line 120 of file sip3_network.c. References ast_log(), ast_mutex_lock(), sip_network::lock, LOG_DEBUG, option_debug, sipdebug, and sipnet. Referenced by process_sip_queue(), sipsock_init(), and sipsock_read(). 00121 { 00122 if (option_debug > 3 && sipdebug) 00123 ast_log(LOG_DEBUG, "Locking sipnet :::::::::::::::::\n"); 00124 ast_mutex_lock(&sipnet->lock); 00125 }
|
|
|
Initialize network lock.
Definition at line 114 of file sip3_network.c. References ast_mutex_init(). Referenced by sipsock_init(). 00115 { 00116 ast_mutex_init(&sipnet->lock); 00117 }
|
|
|
read our port number Get current port number Definition at line 466 of file sip3_network.c. References sip_network::ourport, and sipnet. Referenced by build_contact(), build_via(), and reload_config().
|
|
||||||||||||
|
Set our port number. Set our port number Definition at line 472 of file sip3_network.c. References sip_network::ourport, and sipnet. Referenced by reload_config(), and reset_ip_interface().
|
|
|
Unlock netlock. Unlock netlock mutex Definition at line 128 of file sip3_network.c. References ast_log(), ast_mutex_unlock(), sip_network::lock, LOG_DEBUG, option_debug, sipdebug, and sipnet. Referenced by process_sip_queue(), sipsock_init(), and sipsock_read(). 00129 { 00130 if (option_debug > 3 && sipdebug) 00131 ast_log(LOG_DEBUG, "Unlocking sipnet :::::::::::::::::\n"); 00132 ast_mutex_unlock(&sipnet->lock); 00133 }
|
|
||||||||||||
|
Allocate SIP request structure.
Definition at line 196 of file sip3_network.c. References ast_calloc, ast_log(), free, LOG_DEBUG, LOG_WARNING, option_debug, sip_network::req_counter, and sipnet. Referenced by __transmit_response(), append_send_history(), sipsock_read(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_response_with_attachment(), transmit_response_with_auth(), transmit_response_with_unsupported(), and transmit_state_notify(). 00197 { 00198 struct sip_request *req; 00199 00200 if (len <= 0) { 00201 ast_log(LOG_WARNING, "#### Can't allocate negative or NULL memory for sip_request structure!!!\n"); 00202 return NULL; 00203 } 00204 00205 if (!(req = ast_calloc(1, sizeof(*req)))) { 00206 ast_log(LOG_WARNING, "#### Can't allocate memory for sip_request structure!!!\n"); 00207 return NULL; 00208 } 00209 00210 if (!(req->data = ast_calloc(1, len))) { 00211 ast_log(LOG_WARNING, "#### Can't allocate memory for sip_request data!!!\n"); 00212 free(req); 00213 return NULL; 00214 } 00215 req->data_size = len; 00216 00217 sipnet->req_counter++; 00218 00219 req->socket = sipnet; 00220 00221 if (option_debug > 2) 00222 ast_log(LOG_DEBUG, "+++ Allocating SIP request, size %d (Counter #%u)\n", (int) len, sipnet->req_counter); 00223 00224 return req; 00225 }
|
|
|
Free SIP request.
Definition at line 228 of file sip3_network.c. References ast_log(), sip_request::data, free, LOG_DEBUG, option_debug, sip_network::req_counter, and sip_request::socket. Referenced by __sip_ack(), __transmit_response(), append_send_history(), initialize_initreq(), retrans_pkt(), sip_park_thread(), sipsock_read(), transmit_invite(), transmit_request(), transmit_request_with_auth(), transmit_response_with_attachment(), transmit_response_with_auth(), and transmit_response_with_unsupported(). 00229 { 00230 req->socket->req_counter--; 00231 if (option_debug > 2) 00232 ast_log(LOG_DEBUG, "--- Deallocating SIP request (Counter now #%u)\n", req->socket->req_counter); 00233 free(req->data); 00234 free(req); 00235 }
|
|
||||||||||||
|
Initialize IP socket on configured address - the bind address.
Definition at line 156 of file sip3_network.c. References sip_network::__ourip, ast_find_ourip(), ast_log(), sip_network::bindaddr, DEFAULT_LISTEN_SIP_PORT, LOG_DEBUG, LOG_WARNING, option_debug, sipnet, sipnet_lock(), sipnet_lock_init(), sipnet_unlock(), sip_network::sipsock, sipsocket_initialized(), and sipsocket_open(). 00157 { 00158 sipnet_lock_init(sipnet); 00159 if (ast_find_ourip(&sipnet->__ourip, sipnet->bindaddr)) { 00160 ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n"); 00161 return -1; 00162 } 00163 if (!ntohs(sipnet->bindaddr.sin_port)) 00164 sipnet->bindaddr.sin_port = ntohs(DEFAULT_LISTEN_SIP_PORT); 00165 sipnet->bindaddr.sin_family = AF_INET; 00166 sipnet_lock(sipnet); 00167 if (sipsocket_initialized(sipnet) && (memcmp(old_bindaddr, &sipnet->bindaddr, sizeof(struct sockaddr_in)))) { 00168 close(sipnet->sipsock); 00169 sipnet->sipsock = -1; 00170 } 00171 if (!sipsocket_initialized(sipnet)) 00172 sipsocket_open(sipnet); /* Open socket, bind to address and set TOS option */ 00173 ast_log(LOG_DEBUG, "=== SIPNET sipsock_init after open \n"); 00174 sipnet_unlock(sipnet); 00175 if (option_debug > 2) { 00176 if (sipnet->sipsock > -1) 00177 ast_log(LOG_DEBUG, "=== SIPNET initialized and ready for business\n"); 00178 else 00179 ast_log(LOG_DEBUG, "=== SIPNET initialization failed. SIP3 not ready for business on this socket\n"); 00180 } 00181 return 0; 00182 }
|
|
||||||||||||||||||||
|
Read data from SIP socket.
Definition at line 260 of file sip3_network.c. References AST_FAILURE, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_verbose(), sip_request::data, find_sip_method(), len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, lws2sws(), sip_network::networkbuf, option_debug, parse_request(), process_sip_queue(), queue_sip_request(), sip_debug_test_addr(), sip_debug_test_level(), SIP_PKT_DEBUG, sipnet, sipnet_lock(), sipnet_unlock(), siprequest_alloc(), siprequest_free(), and sip_network::sipsock. 00261 { 00262 struct sip_request *req; 00263 struct sockaddr_in sin = { 0, }; 00264 int res; 00265 socklen_t len; 00266 00267 00268 len = sizeof(sin); 00269 //res = recvfrom(sipnet->sipsock, req->data, sizeof(req->data) - 1, 0, (struct sockaddr *)&sin, &len); 00270 00271 /* Lock sipnet, so we're the only ones using the network buffer for this socket */ 00272 sipnet_lock(&sipnet); 00273 res = recvfrom(sipnet.sipsock, sipnet.networkbuf, sizeof(sipnet.networkbuf) - 1, 0, (struct sockaddr *)&sin, &len); 00274 if (res < 0) { 00275 if (option_debug > 3) 00276 ast_log(LOG_DEBUG, "Nothing to read right now... Standing by\n"); 00277 #if !defined(__FreeBSD__) 00278 if (errno == EAGAIN) 00279 ast_log(LOG_NOTICE, "SIP: Received packet with bad UDP checksum\n"); 00280 else 00281 #endif 00282 if (errno != ECONNREFUSED) 00283 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 00284 sipnet_unlock(&sipnet); 00285 return 1; 00286 } 00287 if (option_debug > 4) 00288 ast_log(LOG_DEBUG, "::::::: Received SIP message, size %d\n", res); 00289 00290 /* Allocate sip request structure sized for this packet */ 00291 req = siprequest_alloc((size_t) res + 1, &sipnet); 00292 if (req == NULL) { 00293 ast_log(LOG_ERROR, "Allocation error\n"); 00294 sipnet_unlock(&sipnet); 00295 return AST_FAILURE; 00296 } 00297 00298 /* Copy the network buffer to the allocated request data buffer */ 00299 memcpy(req->data, sipnet.networkbuf, res); 00300 00301 00302 if(sip_debug_test_addr(&sin)) /* Set the debug flag early on packet level */ 00303 ast_set_flag(req, SIP_PKT_DEBUG); 00304 00305 sipnet.networkbuf[res] = req->data[res] = '\0'; 00306 00307 req->len = lws2sws(req->data, res); /* Fix multiline headers */ 00308 00309 00310 parse_request(req); 00311 req->method = find_sip_method(req->rlPart1); 00312 00313 if (ast_test_flag(req, SIP_PKT_DEBUG) && sip_debug_test_level(req->method)) { 00314 ast_verbose("\n<-- SIP read from %s:%d: \n%s\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), sipnet.networkbuf); 00315 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 00316 } 00317 00318 /* Release sipnet lock for a while, since we do not need the buffer any more */ 00319 sipnet_unlock(&sipnet); 00320 00321 if (req->headers < 2) { 00322 /* Must have at least two headers */ 00323 siprequest_free(req); 00324 return AST_FAILURE; 00325 } 00326 00327 /* The packet is ready to queue */ 00328 queue_sip_request(req, &sin); 00329 00330 /* For testing, process it quickly */ 00331 process_sip_queue(); 00332 00333 return 1; 00334 00335 }
|
|
|
Check if network socket is open.
Definition at line 421 of file sip3_network.c. References FALSE, sipnet, sip_network::sipsock, and TRUE. Referenced by do_sip_monitor(), and sipsock_init().
|
|
|
Open network socket, bind to address and set options (TOS).
Definition at line 429 of file sip3_network.c. References ast_enable_packet_fragmentation(), ast_inet_ntoa(), ast_log(), ast_tos2str(), ast_verbose(), sip_network::bindaddr, FALSE, global, LOG_WARNING, option_verbose, sipnet, sip_network::sipsock, sip_globals::tos_sip, TRUE, and VERBOSE_PREFIX_2. Referenced by sipsock_init(). 00430 { 00431 const int reuseFlag = 1; 00432 00433 00434 sipnet->sipsock = socket(AF_INET, SOCK_DGRAM, 0); 00435 if (sipnet->sipsock < 0) { 00436 ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno)); 00437 return FALSE; 00438 } 00439 /* Allow SIP clients on the same host to access us: */ 00440 setsockopt(sipnet->sipsock, SOL_SOCKET, SO_REUSEADDR, 00441 (const char*)&reuseFlag, 00442 sizeof reuseFlag); 00443 00444 ast_enable_packet_fragmentation(sipnet->sipsock); 00445 00446 if (bind(sipnet->sipsock, (struct sockaddr *)&sipnet->bindaddr, sizeof(sipnet->bindaddr)) < 0) { 00447 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 00448 ast_inet_ntoa(sipnet->bindaddr.sin_addr), ntohs(sipnet->bindaddr.sin_port), 00449 strerror(errno)); 00450 close(sipnet->sipsock); 00451 sipnet->sipsock = -1; 00452 return FALSE; 00453 } else { 00454 if (setsockopt(sipnet->sipsock, IPPROTO_IP, IP_TOS, &global.tos_sip, sizeof(global.tos_sip))) 00455 ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global.tos_sip)); 00456 else if (option_verbose > 1) { 00457 ast_verbose(VERBOSE_PREFIX_2 "SIP Listening on %s:%d\n", 00458 ast_inet_ntoa(sipnet->bindaddr.sin_addr), ntohs(sipnet->bindaddr.sin_port)); 00459 ast_verbose(VERBOSE_PREFIX_2 "Using SIP TOS: %s\n", ast_tos2str(global.tos_sip)); 00460 } 00461 } 00462 return TRUE; 00463 }
|
|
|