![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3core.h File Reference
Functions | |
| const char * | __get_header (const struct sip_request *req, const char *name, int *start) |
| void | __sip_ack (struct sip_pvt *p, int seqno, int resp, int sipmethod, int reset) |
| int | __sip_autodestruct (void *data) |
| void | __sip_destroy (struct sip_pvt *p, int lockowner) |
| int | __sip_do_register (struct sip_registry *r) |
| void | __sip_pretend_ack (struct sip_pvt *p) |
| int | __sip_semi_ack (struct sip_pvt *p, int seqno, int resp, int sipmethod) |
| int | __sip_show_channels (int fd, int argc, char *argv[], int subscriptions) |
| int | __transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable) |
| int | _sip_show_peer (int type, int fd, struct mansession *s, struct message *m, int argc, char *argv[]) |
| int | _sip_show_peers (int fd, int *total, struct mansession *s, struct message *m, int argc, char *argv[]) |
| static void | add_blank (struct sip_request *req) |
| add a blank line if no body | |
| void | add_codec_to_sdp (const struct sip_pvt *p, int codec, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug) |
| int | add_digit (struct sip_request *req, char digit) |
| int | add_header (struct sip_request *req, const char *var, const char *value) |
| Add header to SIP message. | |
| int | add_header_contentLength (struct sip_request *req, int len) |
| Add 'Content-Length' header to SIP message. | |
| int | add_line (struct sip_request *req, const char *line) |
| Add content (not header) to SIP message. | |
| void | add_noncodec_to_sdp (const struct sip_pvt *p, int format, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug) |
| sip_auth * | add_realm_authentication (struct sip_auth *authlist, char *configuration, int lineno) |
| Add realm authentication in list. | |
| void | add_route (struct sip_request *req, struct sip_route *route) |
| Add route header into request per learned route. | |
| int | add_sdp (struct sip_request *resp, struct sip_pvt *p) |
| int | add_sip_domain (const char *domain, const enum domain_mode mode, const char *context) |
| Add SIP domain to list of domains we are responsible for. | |
| int | add_text (struct sip_request *req, const char *text) |
| Add text body to SIP message. | |
| int | add_vidupdate (struct sip_request *req) |
| void | append_date (struct sip_request *req) |
| Append date to SIP message. | |
| void | append_history_full (struct sip_pvt *p, const char *fmt,...) |
| void | ast_quiet_chan (struct ast_channel *chan) |
| Turn off generator data XXX Does this function belong in the SIP channel? | |
| int | ast_sip_ouraddrfor (struct in_addr *them, struct in_addr *us) |
| int | attempt_transfer (struct sip_dual *transferer, struct sip_dual *target) |
| int | auto_congest (void *nothing) |
| void | build_callid_pvt (struct sip_pvt *pvt) |
| void | build_callid_registry (struct sip_registry *reg, struct in_addr ourip, const char *fromdomain) |
| void | build_contact (struct sip_pvt *p) |
| int | build_reply_digest (struct sip_pvt *p, int method, char *digest, int digest_len) |
| void | build_route (struct sip_pvt *p, struct sip_request *req, int backwards) |
| void | build_rpid (struct sip_pvt *p) |
| void | build_via (struct sip_pvt *p) |
| int | cb_extensionstate (char *context, char *exten, int state, void *data) |
| enum check_auth_result | check_auth (struct sip_pvt *p, struct sip_request *req, const char *username, const char *secret, const char *md5secret, int sipmethod, char *uri, enum xmittype reliable, int ignore) |
| void | check_pendings (struct sip_pvt *p) |
| int | check_sip_domain (const char *domain, char *context, size_t len) |
| check_sip_domain: Check if domain part of uri is local to our server | |
| int | check_user (struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin) |
| enum check_auth_result | check_user_full (struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_peer **authpeer) |
| void | check_via (struct sip_pvt *p, struct sip_request *req) |
| void | cleanup_stale_contexts (char *new, char *old) |
| int | clear_realm_authentication (struct sip_auth *authlist) |
| Clear realm authentication list (at reload). | |
| void | clear_sip_domains (void) |
| Clear our domain list (at reload). | |
| char * | complete_sip_debug_peer (const char *line, const char *word, int pos, int state) |
| char * | complete_sip_peer (const char *word, int state, int flags2) |
| char * | complete_sip_prune_realtime_peer (const char *line, const char *word, int pos, int state) |
| char * | complete_sip_prune_realtime_user (const char *line, const char *word, int pos, int state) |
| char * | complete_sip_show_peer (const char *line, const char *word, int pos, int state) |
| char * | complete_sip_show_user (const char *line, const char *word, int pos, int state) |
| char * | complete_sip_user (const char *word, int state, int flags2) |
| char * | complete_sipch (const char *line, const char *word, int pos, int state) |
| char * | complete_sipnotify (const char *line, const char *word, int pos, int state) |
| int | copy_all_header (struct sip_request *req, const struct sip_request *orig, const char *field) |
| int | copy_header (struct sip_request *req, const struct sip_request *orig, const char *field) |
| void | copy_request (struct sip_request *dst, const struct sip_request *src) |
| copy SIP request (mostly used to save request for responses) | |
| int | copy_via_headers (struct sip_pvt *p, struct sip_request *req, const struct sip_request *orig, const char *field) |
| int | create_addr (struct sip_pvt *dialog, const char *opeer) |
| int | create_addr_from_peer (struct sip_pvt *r, struct sip_peer *peer) |
| void | destroy_association (struct sip_peer *peer) |
| int | determine_firstline_parts (struct sip_request *req) |
| Parse first line of incoming SIP request. | |
| void * | do_monitor (void *data) |
| int | does_peer_need_mwi (struct sip_peer *peer) |
| const char * | domain_mode_to_text (const enum domain_mode mode) |
| Print domain mode to cli. | |
| const char * | dtmfmode2str (int mode) attribute_const |
| int | expire_register (void *data) |
| Expire registration of SIP peer. | |
| void | extract_uri (struct sip_pvt *p, struct sip_request *req) |
| const char * | find_alias (const char *name, const char *_default) |
| Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP. | |
| sip_pvt * | find_call (struct sip_request *req, struct sockaddr_in *sin, const int intended_method) |
| sip_peer * | find_peer (const char *peer, struct sockaddr_in *sin, int realtime) |
| sip_auth * | find_realm_authentication (struct sip_auth *authlist, const char *realm) |
| Find authentication for a specific realm. | |
| int | find_sdp (struct sip_request *req) |
| Determine whether a SIP message contains an SDP in its body. | |
| int | find_sip_method (const char *msg) |
| find_sip_method: Find SIP method from header | |
| sip_peer * | find_user (const char *name, int realtime) |
| void | free_old_route (struct sip_route *route) |
| Remove route from route list. | |
| int | func_check_sipdomain (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| Dial plan function to check if domain is local. | |
| int | func_header_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len) |
| int | function_sipchaninfo_read (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| int | function_sippeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| char * | generate_random_string (char *buf, size_t size) |
| Generate 32 byte random string for callid's etc. | |
| int | get_also_info (struct sip_pvt *p, struct sip_request *oreq) |
| char * | get_calleridname (const char *input, char *output, size_t outputsize) |
| Get caller id name from SIP headers. | |
| int | get_destination (struct sip_pvt *p, struct sip_request *oreq) |
| const char * | get_header (const struct sip_request *req, const char *name) |
| char * | get_in_brackets (char *tmp) |
| Pick out text in brackets from character string. | |
| int | get_msg_text (char *buf, int len, struct sip_request *req) |
| int | get_rdnis (struct sip_pvt *p, struct sip_request *oreq) |
| int | get_refer_info (struct sip_pvt *transferer, struct sip_request *outgoing_req) |
| int | get_rpid_num (const char *input, char *output, int maxlen) |
| Get caller id number from Remote-Party-ID header field Returns true if number should be restricted (privacy setting found) output is set to NULL if no number found. | |
| sip_pvt * | get_sip_pvt_byid_locked (const char *callid, const char *totag, const char *fromtag) |
| const char * | gettag (const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize) |
| int | handle_common_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v) |
| int | handle_invite_replaces (struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr_in *sin) |
| int | handle_request (struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock) |
| int | handle_request_bye (struct sip_pvt *p, struct sip_request *req) |
| int | handle_request_cancel (struct sip_pvt *p, struct sip_request *req) |
| void | handle_request_info (struct sip_pvt *p, struct sip_request *req) |
| int | handle_request_invite (struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e) |
| int | handle_request_message (struct sip_pvt *p, struct sip_request *req) |
| int | handle_request_notify (struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e) |
| int | handle_request_options (struct sip_pvt *p, struct sip_request *req) |
| int | handle_request_refer (struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, int *nounlock) |
| int | handle_request_register (struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e) |
| int | handle_request_subscribe (struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e) |
| void | handle_response (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| void | handle_response_invite (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| int | handle_response_peerpoke (struct sip_pvt *p, int resp, struct sip_request *req) |
| void | handle_response_refer (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| int | handle_response_register (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| const char * | hangup_cause2sip (int cause) |
| Convert Asterisk hangup causes to SIP codes. | |
| int | hangup_sip2cause (int cause) |
| Convert SIP hangup causes to Asterisk hangup causes. | |
| int | init_req (struct sip_request *req, int sipmethod, const char *recip) |
| Initialize SIP request. | |
| int | init_resp (struct sip_request *resp, const char *msg) |
| Initialize SIP response, based on SIP request. | |
| void | initialize_initreq (struct sip_pvt *p, struct sip_request *req) |
| void | initreqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod) |
| const char * | insecure2str (int port, int invite) attribute_const |
| void | list_route (struct sip_route *route) |
| int | local_attended_transfer (struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno) |
| int | lws2sws (char *msgbuf, int len) |
| Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled. | |
| void | make_our_tag (char *tagbuf, size_t len) |
| Make our SIP dialog tag. | |
| int | manager_sip_show_peer (struct mansession *s, struct message *m) |
| int | manager_sip_show_peers (struct mansession *s, struct message *m) |
| int | method_match (enum sipmethod id, const char *name) |
| returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send | |
| char * | nat2str (int nat) attribute_const |
| void | parse_copy (struct sip_request *dst, const struct sip_request *src) |
| void | parse_moved_contact (struct sip_pvt *p, struct sip_request *req) |
| int | parse_ok_contact (struct sip_pvt *pvt, struct sip_request *req) |
| enum parse_register_result | parse_register_contact (struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req) |
| void | parse_request (struct sip_request *req) |
| Parse a SIP message. | |
| unsigned int | parse_sip_options (struct sip_pvt *pvt, const char *supported) |
| int | peer_status (struct sip_peer *peer, char *status, int statuslen) |
| void | print_codec_to_cli (int fd, struct ast_codec_pref *pref) |
| void | print_group (int fd, ast_group_t group, int crlf) |
| Print call group and pickup group. | |
| void | realtime_update_peer (const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey) |
| Update peer object in realtime storage If the Asterisk system name is set in asterisk.conf, we will use that name and store that in the "regserver" field in the sippeers table to facilitate multi-server setups. | |
| void | receive_message (struct sip_pvt *p, struct sip_request *req) |
| void | reg_source_db (struct sip_peer *peer) |
| void | register_peer_exten (struct sip_peer *peer, int onoff) |
| enum check_auth_result | register_verify (struct sip_pvt *p, struct sockaddr_in *sin, struct sip_request *req, char *uri) |
| char * | regstate2str (enum sipregistrystate regstate) attribute_const |
| Convert registration state status to string. | |
| int | reqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod, int seqno, int newbranch) |
| int | respprep (struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| int | restart_monitor (void) |
| Start the channel monitor thread. | |
| int | send_request (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno) |
| int | set_address_from_contact (struct sip_pvt *pvt) |
| void | set_destination (struct sip_pvt *p, char *uri) |
| void | set_device_defaults (struct sip_peer *peer) |
| int | sip_addheader (struct ast_channel *chan, void *data) |
| int | sip_addrcmp (char *name, struct sockaddr_in *sin) |
| sip_pvt * | sip_alloc (ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method) |
| Allocate SIP_PVT structure and set defaults. | |
| void | sip_cancel_destroy (struct sip_pvt *p) |
| int | sip_debug_test_addr (const struct sockaddr_in *addr) |
| See if we pass debug IP filter. | |
| int | sip_debug_test_pvt (struct sip_pvt *p) |
| void | sip_destroy (struct sip_pvt *p) |
| void | sip_destroy_device (struct sip_peer *peer) |
| int | sip_devicestate (void *data) |
| int | sip_do_debug (int fd, int argc, char *argv[]) |
| int | sip_do_debug_ip (int fd, int argc, char *argv[]) |
| int | sip_do_debug_peer (int fd, int argc, char *argv[]) |
| int | sip_do_history (int fd, int argc, char *argv[]) |
| int | sip_do_reload (enum channelreloadreason reason) |
| int | sip_dtmfmode (struct ast_channel *chan, void *data) |
| void | sip_dump_history (struct sip_pvt *dialog) |
| int | sip_get_codec (struct ast_channel *chan) |
| ast_udptl * | sip_get_udptl_peer (struct ast_channel *chan) |
| int | sip_handle_t38_reinvite (struct ast_channel *chan, struct sip_pvt *pvt, int reinvite) |
| const char * | sip_nat_mode (const struct sip_pvt *p) |
| int | sip_no_debug (int fd, int argc, char *argv[]) |
| int | sip_no_history (int fd, int argc, char *argv[]) |
| int | sip_notify (int fd, int argc, char *argv[]) |
| int | sip_park (struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno) |
| void * | sip_park_thread (void *stuff) |
| void | sip_peer_hold (struct sip_pvt *p, int hold) |
| void | sip_poke_all_peers (void) |
| Send a poke to all known peers Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions? | |
| int | sip_poke_noanswer (void *data) |
| React to lack of answer to Qualify poke. | |
| int | sip_poke_peer (struct sip_peer *peer) |
| int | sip_poke_peer_s (void *data) |
| Poke peer (send qualify to check if peer is alive and well). | |
| int | sip_prune_realtime (int fd, int argc, char *argv[]) |
| Remove temporary realtime objects from memory (CLI). | |
| const struct sockaddr_in * | sip_real_dst (const struct sip_pvt *p) |
| int | sip_refer_allocate (struct sip_pvt *p) |
| int | sip_reg_timeout (void *data) |
| int | sip_register (char *value, int lineno) |
| void | sip_registry_destroy (struct sip_registry *reg) |
| Destroy registry object Objects created with the register= statement in static configuration. | |
| int | sip_reload (int fd, int argc, char *argv[]) |
| int | sip_reregister (void *data) |
| ast_frame * | sip_rtp_read (struct ast_channel *ast, struct sip_pvt *p, int *faxdetect) |
| void | sip_scheddestroy (struct sip_pvt *p, int ms) |
| void | sip_send_all_registers (void) |
| Send all known registrations. | |
| int | sip_send_mwi_to_peer (struct sip_peer *peer) |
| int | sip_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active) |
| Set the RTP peer for this call. | |
| int | sip_set_udptl_peer (struct ast_channel *chan, struct ast_udptl *udptl) |
| int | sip_show_channel (int fd, int argc, char *argv[]) |
| int | sip_show_channels (int fd, int argc, char *argv[]) |
| int | sip_show_domains (int fd, int argc, char *argv[]) |
| CLI command to list local domains. | |
| int | sip_show_history (int fd, int argc, char *argv[]) |
| int | sip_show_inuse (int fd, int argc, char *argv[]) |
| int | sip_show_objects (int fd, int argc, char *argv[]) |
| int | sip_show_peer (int fd, int argc, char *argv[]) |
| int | sip_show_peers (int fd, int argc, char *argv[]) |
| int | sip_show_registry (int fd, int argc, char *argv[]) |
| int | sip_show_settings (int fd, int argc, char *argv[]) |
| int | sip_show_subscriptions (int fd, int argc, char *argv[]) |
| int | sip_show_user (int fd, int argc, char *argv[]) |
| int | sip_show_users (int fd, int argc, char *argv[]) |
| int | sip_sipredirect (struct sip_pvt *p, const char *dest) |
| sip_peer * | temp_peer (const char *name) |
| char * | transfermode2str (enum transfermodes mode) attribute_const |
| void | transmit_fake_auth_response (struct sip_pvt *p, struct sip_request *req, int reliable) |
| int | transmit_info_with_digit (struct sip_pvt *p, const char digit) |
| int | transmit_info_with_vidupdate (struct sip_pvt *p) |
| int | transmit_invite (struct sip_pvt *p, int sipmethod, int sdp, int init) |
| int | transmit_message_with_text (struct sip_pvt *p, const char *text) |
| int | transmit_notify_with_mwi (struct sip_pvt *p, int newmsgs, int oldmsgs, char *vmexten) |
| int | transmit_notify_with_sipfrag (struct sip_pvt *p, int cseq, char *message, int terminate) |
| int | transmit_refer (struct sip_pvt *p, const char *dest) |
| int | transmit_register (struct sip_registry *r, int sipmethod, const char *auth, const char *authheader) |
| Transmit register to SIP proxy or UA. | |
| int | transmit_reinvite_with_sdp (struct sip_pvt *p) |
| int | transmit_reinvite_with_t38_sdp (struct sip_pvt *p) |
| int | transmit_request (struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch) |
| int | transmit_request_with_auth (struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch) |
| int | transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| int | transmit_response_reliable (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| int | transmit_response_with_allow (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable) |
| int | transmit_response_with_auth (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale) |
| int | transmit_response_with_date (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| int | transmit_response_with_sdp (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable) |
| int | transmit_response_with_t38_sdp (struct sip_pvt *p, char *msg, struct sip_request *req, int retrans) |
| int | transmit_response_with_unsupported (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported) |
| int | transmit_sip_request (struct sip_pvt *p, struct sip_request *req) |
| int | transmit_state_notify (struct sip_pvt *p, int state, int full) |
| void | try_suggested_sip_codec (struct sip_pvt *p) |
| int | update_call_counter (struct sip_pvt *fup, int event) |
| void | update_peer (struct sip_peer *p, int expiry) |
|
||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||
|
|
|
|
add a blank line if no body
Definition at line 128 of file sip3_compose.c. 00129 { 00130 if (!req->lines) { 00131 /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ 00132 snprintf(req->data + req->len, req->data_size - req->len, "\r\n"); 00133 req->len += strlen(req->data + req->len); 00134 } 00135 }
|
|
||||||||||||||||||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Add header to SIP message.
Definition at line 89 of file sip3_compose.c. 00090 { 00091 int maxlen = req->data_size - 4 - req->len; /* 4 bytes are for two \r\n ? */ 00092 00093 if (req->headers == SIP_MAX_HEADERS) { 00094 ast_log(LOG_WARNING, "Out of SIP header space\n"); 00095 return -1; 00096 } 00097 00098 if (req->lines) { 00099 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 00100 return -1; 00101 } 00102 00103 if (maxlen <= 0) { 00104 ast_log(LOG_WARNING, "Out of space, can't add anymore (%s:%s)\n", var, value); 00105 if (option_debug > 2) 00106 ast_log(LOG_DEBUG, " ==== Req->len %d, req->data size %d Maxlen %d\n", req->len, (int) req->data_size, maxlen); 00107 return -1; 00108 } 00109 00110 req->header[req->headers] = req->data + req->len; 00111 00112 if (global.compactheaders) 00113 var = find_alias(var, var); 00114 00115 snprintf(req->header[req->headers], maxlen, "%s: %s\r\n", var, value); 00116 req->len += strlen(req->header[req->headers]); 00117 req->headers++; 00118 if (req->headers < SIP_MAX_HEADERS) 00119 req->headers++; 00120 else 00121 ast_log(LOG_WARNING, "Out of SIP header space... Will generate broken SIP message\n"); 00122 00123 return 0; 00124 }
|
|
||||||||||||
|
Add 'Content-Length' header to SIP message.
Definition at line 362 of file sip3_compose.c. 00363 { 00364 char clen[10]; 00365 00366 snprintf(clen, sizeof(clen), "%d", len); 00367 return add_header(req, "Content-Length", clen); 00368 }
|
|
||||||||||||
|
Add content (not header) to SIP message.
Definition at line 399 of file sip3_compose.c. 00400 { 00401 if (req->lines == SIP_MAX_LINES) { 00402 ast_log(LOG_WARNING, "Out of SIP line space\n"); 00403 return -1; 00404 } 00405 if (!req->lines) { 00406 /* Add extra empty return */ 00407 snprintf(req->data + req->len, req->data_size - req->len, "\r\n"); 00408 req->len += strlen(req->data + req->len); 00409 } 00410 if (req->len >= req->data_size - 4) { 00411 ast_log(LOG_WARNING, "Out of space, can't add anymore: Len %d Data %dd\n", req->len, (int) req->data_size); 00412 return -1; 00413 } 00414 req->line[req->lines] = req->data + req->len; 00415 snprintf(req->line[req->lines], req->data_size - req->len, "%s", line); 00416 req->len += strlen(req->line[req->lines]); 00417 req->lines++; 00418 return 0; 00419 }
|
|
||||||||||||||||||||||||||||||||||||
|
|
|
||||||||||||||||
|
Add realm authentication in list.
Definition at line 495 of file sip3_auth.c. 00496 { 00497 char authcopy[256]; 00498 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 00499 char *stringp; 00500 struct sip_auth *a, *b, *auth; 00501 00502 if (ast_strlen_zero(configuration)) 00503 return authlist; 00504 00505 if (option_debug) 00506 ast_log(LOG_DEBUG, "Auth config :: %s\n", configuration); 00507 00508 ast_copy_string(authcopy, configuration, sizeof(authcopy)); 00509 stringp = authcopy; 00510 00511 username = stringp; 00512 realm = strrchr(stringp, '@'); 00513 if (realm) 00514 *realm++ = '\0'; 00515 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 00516 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 00517 return authlist; 00518 } 00519 stringp = username; 00520 username = strsep(&stringp, ":"); 00521 if (username) { 00522 secret = strsep(&stringp, ":"); 00523 if (!secret) { 00524 stringp = username; 00525 md5secret = strsep(&stringp,"#"); 00526 } 00527 } 00528 if (!(auth = ast_calloc(1, sizeof(*auth)))) 00529 return authlist; 00530 00531 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 00532 ast_copy_string(auth->username, username, sizeof(auth->username)); 00533 if (secret) 00534 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 00535 if (md5secret) 00536 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 00537 00538 /* find the end of the list */ 00539 for (b = NULL, a = authlist; a ; b = a, a = a->next) 00540 ; 00541 if (b) 00542 b->next = auth; /* Add structure add end of list */ 00543 else 00544 authlist = auth; 00545 00546 if (option_verbose > 2) 00547 ast_verbose("Added authentication for realm %s\n", realm); 00548 00549 return authlist; 00550 00551 }
|
|
||||||||||||
|
Add route header into request per learned route.
Definition at line 371 of file sip3_compose.c. 00372 { 00373 char r[BUFSIZ*2], *p; 00374 int n, rem = sizeof(r); 00375 00376 if (!route) 00377 return; 00378 00379 p = r; 00380 for (;route ; route = route->next) { 00381 n = strlen(route->hop); 00382 if (rem < n+3) /* we need room for ",<route>" */ 00383 break; 00384 if (p != r) { /* add a separator after fist route */ 00385 *p++ = ','; 00386 --rem; 00387 } 00388 *p++ = '<'; 00389 ast_copy_string(p, route->hop, rem); /* cannot fail */ 00390 p += n; 00391 *p++ = '>'; 00392 rem -= (n+2); 00393 } 00394 *p = '\0'; 00395 add_header(req, "Route", r); 00396 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Add SIP domain to list of domains we are responsible for.
Definition at line 95 of file sip3_domain.c. 00096 { 00097 struct domain *d; 00098 00099 if (ast_strlen_zero(domain)) { 00100 ast_log(LOG_WARNING, "Zero length domain.\n"); 00101 return 1; 00102 } 00103 00104 if (!(d = ast_calloc(1, sizeof(*d)))) 00105 return 0; 00106 00107 ast_copy_string(d->domain, domain, sizeof(d->domain)); 00108 00109 if (!ast_strlen_zero(context)) 00110 ast_copy_string(d->context, context, sizeof(d->context)); 00111 00112 d->mode = mode; 00113 00114 AST_LIST_LOCK(&domain_list); 00115 AST_LIST_INSERT_TAIL(&domain_list, d, list); 00116 AST_LIST_UNLOCK(&domain_list); 00117 00118 if (option_debug > 2) 00119 ast_log(LOG_DEBUG, "Added local SIP domain '%s'\n", domain); 00120 00121 return 1; 00122 }
|
|
||||||||||||
|
Add text body to SIP message.
Definition at line 195 of file sip3_compose.c. 00196 { 00197 /* XXX Convert \n's to \r\n's XXX */ 00198 add_header(req, "Content-Type", "text/plain"); 00199 add_header_contentLength(req, strlen(text)); 00200 add_line(req, text); 00201 return 0; 00202 }
|
|
|
|
|
|
Append date to SIP message.
Definition at line 175 of file sip3_compose.c. 00176 { 00177 char tmpdat[256]; 00178 struct tm tm; 00179 time_t t = time(NULL); 00180 00181 gmtime_r(&t, &tm); 00182 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 00183 add_header(req, "Date", tmpdat); 00184 }
|
|
||||||||||||||||
|
|
|
|
Turn off generator data XXX Does this function belong in the SIP channel?
Definition at line 4034 of file chan_sip3.c. 04035 { 04036 if (chan && chan->_state == AST_STATE_UP) { 04037 if (chan->generatordata) 04038 ast_deactivate_generator(chan); 04039 } 04040 }
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
||||||||||||||||
|
check_sip_domain: Check if domain part of uri is local to our server
Definition at line 132 of file sip3_domain.c. 00133 { 00134 struct domain *d; 00135 int result = 0; 00136 00137 AST_LIST_LOCK(&domain_list); 00138 AST_LIST_TRAVERSE(&domain_list, d, list) { 00139 if (strcasecmp(d->domain, domain)) 00140 continue; 00141 00142 if (len && !ast_strlen_zero(d->context)) 00143 ast_copy_string(context, d->context, len); 00144 00145 result = 1; 00146 break; 00147 } 00148 AST_LIST_UNLOCK(&domain_list); 00149 00150 return result; 00151 }
|
|
||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
|
Clear realm authentication list (at reload).
Definition at line 554 of file sip3_auth.c. 00555 { 00556 struct sip_auth *a = authlist; 00557 struct sip_auth *b; 00558 00559 while (a) { 00560 b = a; 00561 a = a->next; 00562 free(b); 00563 } 00564 00565 return 1; 00566 }
|
|
|
Clear our domain list (at reload).
Definition at line 154 of file sip3_domain.c. 00155 { 00156 struct domain *d; 00157 00158 AST_LIST_LOCK(&domain_list); 00159 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 00160 free(d); 00161 AST_LIST_UNLOCK(&domain_list); 00162 }
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
copy SIP request (mostly used to save request for responses)
Definition at line 238 of file sip3_parse.c. 00239 { 00240 long offset; 00241 int x; 00242 00243 offset = ((void *)dst) - ((void *)src); 00244 /* First copy stuff */ 00245 memcpy(dst, src, sizeof(*dst)); 00246 00247 /* Now, fix data part */ 00248 if (dst->data) 00249 free(dst->data); 00250 dst->data = ast_calloc(1, src->data_size); 00251 dst->data_size = src->data_size; 00252 memcpy(dst->data, src->data, src->data_size); 00253 00254 /* Now fix pointer arithmetic */ 00255 for (x=0; x < src->headers; x++) 00256 dst->header[x] += offset; 00257 for (x=0; x < src->lines; x++) 00258 dst->line[x] += offset; 00259 00260 if (option_debug > 3) 00261 ast_log(LOG_DEBUG, "==== Copied request... \n"); 00262 }
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
|
|
|
|
Parse first line of incoming SIP request.
Definition at line 865 of file sip3_parse.c. 00866 { 00867 char *e = ast_skip_blanks(req->header[0]); /* there shouldn't be any */ 00868 00869 if (!*e) 00870 return -1; 00871 req->rlPart1 = e; /* method or protocol */ 00872 e = ast_skip_nonblanks(e); 00873 if (*e) 00874 *e++ = '\0'; 00875 /* Get URI or status code */ 00876 e = ast_skip_blanks(e); 00877 if ( !*e ) 00878 return -1; 00879 ast_trim_blanks(e); 00880 00881 if (!strcasecmp(req->rlPart1, "SIP/2.0") ) { /* We have a response */ 00882 if (strlen(e) < 3) /* status code is 3 digits */ 00883 return -1; 00884 req->rlPart2 = e; 00885 } else { /* We have a request */ 00886 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 00887 ast_log(LOG_WARNING, "bogus uri in <> %s\n", e); 00888 e++; 00889 if (!*e) 00890 return -1; 00891 } 00892 req->rlPart2 = e; /* URI */ 00893 e = ast_skip_nonblanks(e); 00894 if (*e) 00895 *e++ = '\0'; 00896 e = ast_skip_blanks(e); 00897 if (strcasecmp(e, "SIP/2.0") ) { 00898 ast_log(LOG_WARNING, "Bad request protocol %s\n", e); 00899 return -1; 00900 } 00901 } 00902 return 1; 00903 }
|
|
|
|
|
|
|
|
|
Print domain mode to cli.
Definition at line 191 of file sip3_domain.c. 00192 { 00193 switch (mode) { 00194 case SIP_DOMAIN_AUTO: 00195 return "[Automatic]"; 00196 case SIP_DOMAIN_CONFIG: 00197 return "[Configured]"; 00198 } 00199 00200 return ""; 00201 }
|
|
|
|
|
|
Expire registration of SIP peer.
Definition at line 391 of file sip3_objects.c. 00392 { 00393 struct sip_device *device = data; 00394 00395 if (!device) /* Hmmm. We have no peer. Weird. */ 00396 return 0; 00397 00398 memset(&device->addr, 0, sizeof(device->addr)); 00399 00400 destroy_association(device); /* remove registration data from storage */ 00401 00402 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", device->name); 00403 register_peer_exten(device, FALSE); /* Remove regexten */ 00404 device->expire = -1; 00405 ast_device_state_changed("SIP/%s", device->name); 00406 00407 /* Do we need to release this peer from memory? 00408 Only for realtime peers and autocreated peers 00409 */ 00410 if (ast_test_flag(&device->flags[1], SIP_PAGE2_SELFDESTRUCT) || 00411 ast_test_flag(&device->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 00412 device = ASTOBJ_CONTAINER_UNLINK(&devicelist, device); /* Remove from peer list */ 00413 device_unref(device); 00414 } 00415 00416 return 0; 00417 }
|
|
||||||||||||
|
|
|
||||||||||||
|
Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP.
Definition at line 320 of file sip3_parse.c. 00321 { 00322 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 00323 static const struct cfalias { 00324 char * const fullname; 00325 char * const shortname; 00326 } aliases[] = { 00327 { "Content-Type", "c" }, 00328 { "Content-Encoding", "e" }, 00329 { "From", "f" }, 00330 { "Call-ID", "i" }, 00331 { "Contact", "m" }, 00332 { "Content-Length", "l" }, 00333 { "Subject", "s" }, 00334 { "To", "t" }, 00335 { "Supported", "k" }, 00336 { "Refer-To", "r" }, 00337 { "Referred-By", "b" }, 00338 { "Allow-Events", "u" }, 00339 { "Event", "o" }, 00340 { "Via", "v" }, 00341 { "Accept-Contact", "a" }, 00342 { "Reject-Contact", "j" }, 00343 { "Request-Disposition", "d" }, 00344 { "Session-Expires", "x" }, 00345 { "Identity", "y" }, 00346 { "Identity-Info", "n" }, 00347 }; 00348 int x; 00349 00350 for (x=0; x<sizeof(aliases) / sizeof(aliases[0]); x++) 00351 if (!strcasecmp(aliases[x].fullname, name)) 00352 return aliases[x].shortname; 00353 00354 return _default; 00355 }
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
Find authentication for a specific realm.
Definition at line 569 of file sip3_auth.c. 00570 { 00571 struct sip_auth *a; 00572 00573 for (a = authlist; a; a = a->next) { 00574 if (!strcasecmp(a->realm, realm)) 00575 break; 00576 } 00577 00578 return a; 00579 }
|
|
|
Determine whether a SIP message contains an SDP in its body.
Definition at line 880 of file sip3_sdprtp.c. 00881 { 00882 const char *content_type; 00883 const char *search; 00884 char *boundary; 00885 unsigned int x; 00886 00887 content_type = get_header(req, "Content-Type"); 00888 00889 /* if the body contains only SDP, this is easy */ 00890 if (!strcasecmp(content_type, "application/sdp")) { 00891 req->sdp_start = 0; 00892 req->sdp_end = req->lines; 00893 return TRUE; 00894 } 00895 00896 /* if it's not multipart/mixed, there cannot be an SDP */ 00897 if (strncasecmp(content_type, "multipart/mixed", 15)) 00898 return FALSE; 00899 00900 /* if there is no boundary marker, it's invalid */ 00901 if (!(search = strcasestr(content_type, ";boundary="))) 00902 return FALSE; 00903 00904 search += 10; 00905 00906 if (ast_strlen_zero(search)) 00907 return FALSE; 00908 00909 /* make a duplicate of the string, with two extra characters 00910 at the beginning */ 00911 boundary = ast_strdupa(search - 2); 00912 boundary[0] = boundary[1] = '-'; 00913 00914 /* search for the boundary marker, but stop when there are not enough 00915 lines left for it, the Content-Type header and at least one line of 00916 body */ 00917 for (x = 0; x < (req->lines - 2); x++) { 00918 if (!strncasecmp(req->line[x], boundary, strlen(boundary)) && 00919 !strcasecmp(req->line[x + 1], "Content-Type: application/sdp")) { 00920 x += 2; 00921 req->sdp_start = x; 00922 /* search for the end of the body part */ 00923 for ( ; x < req->lines; x++) { 00924 if (!strncasecmp(req->line[x], boundary, strlen(boundary))) 00925 break; 00926 } 00927 req->sdp_end = x; 00928 return TRUE; 00929 } 00930 } 00931 00932 return FALSE; 00933 }
|
|
|
find_sip_method: Find SIP method from header
Definition at line 163 of file sip3_parse.c. 00164 { 00165 int i, res = 0; 00166 00167 if (ast_strlen_zero(msg)) 00168 return 0; 00169 for (i = 1; i < (sizeof(sip_methods) / sizeof(sip_methods[0])) && !res; i++) { 00170 if (method_match(i, msg)) 00171 res = sip_methods[i].id; 00172 } 00173 return res; 00174 }
|
|
||||||||||||
|
|
|
|
Remove route from route list.
Definition at line 2084 of file chan_sip3.c. 02085 { 02086 struct sip_route *next; 02087 02088 while (route) { 02089 next = route->next; 02090 free(route); 02091 route = next; 02092 } 02093 }
|
|
||||||||||||||||||||||||
|
Dial plan function to check if domain is local.
Definition at line 166 of file sip3_domain.c. 00167 { 00168 if (ast_strlen_zero(data)) { 00169 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 00170 return -1; 00171 } 00172 if (check_sip_domain(data, NULL, 0)) 00173 ast_copy_string(buf, data, len); 00174 else 00175 buf[0] = '\0'; 00176 return 0; 00177 }
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||
|
Generate 32 byte random string for callid's etc.
Definition at line 852 of file sip3_parse.c. 00853 { 00854 long val[4]; 00855 int x; 00856 00857 for (x=0; x<4; x++) 00858 val[x] = ast_random(); 00859 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 00860 00861 return buf; 00862 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Get caller id name from SIP headers.
Definition at line 130 of file sip3_callerid.c. 00131 { 00132 const char *end = strchr(input,'<'); /* first_bracket */ 00133 const char *tmp = strchr(input,'"'); /* first quote */ 00134 int bytes = 0; 00135 int maxbytes = outputsize - 1; 00136 00137 if (!end || end == input) /* we require a part in brackets */ 00138 return NULL; 00139 00140 /* move away from "<" */ 00141 end--; 00142 00143 /* we found "name" */ 00144 if (tmp && tmp < end) { 00145 end = strchr(tmp+1, '"'); 00146 if (!end) 00147 return NULL; 00148 bytes = (int) (end - tmp); 00149 /* protect the output buffer */ 00150 if (bytes > maxbytes) 00151 bytes = maxbytes; 00152 ast_copy_string(output, tmp + 1, bytes); 00153 } else { 00154 /* we didn't find "name" */ 00155 /* clear the empty characters in the begining*/ 00156 input = ast_skip_blanks(input); 00157 /* clear the empty characters in the end */ 00158 while(*end && *end < 33 && end > input) 00159 end--; 00160 if (end >= input) { 00161 bytes = (int) (end - input) + 2; 00162 /* protect the output buffer */ 00163 if (bytes > maxbytes) 00164 bytes = maxbytes; 00165 ast_copy_string(output, input, bytes); 00166 } else 00167 return NULL; 00168 } 00169 return output; 00170 }
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
|
Pick out text in brackets from character string.
Definition at line 771 of file sip3_parse.c. 00772 { 00773 const char *parse = tmp; 00774 char *first_bracket; 00775 00776 /* 00777 * Skip any quoted text until we find the part in brackets. 00778 * On any error give up and return the full string. 00779 */ 00780 while ( (first_bracket = strchr(parse, '<')) ) { 00781 char *first_quote = strchr(parse, '"'); 00782 00783 if (!first_quote || first_quote > first_bracket) 00784 break; /* no need to look at quoted part */ 00785 /* the bracket is within quotes, so ignore it */ 00786 parse = find_closing_quote(first_quote + 1, NULL); 00787 if (!*parse) { /* not found, return full string ? */ 00788 /* XXX or be robust and return in-bracket part ? */ 00789 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); 00790 break; 00791 } 00792 parse++; 00793 } 00794 if (first_bracket) { 00795 char *second_bracket = strchr(first_bracket + 1, '>'); 00796 if (second_bracket) { 00797 *second_bracket = '\0'; 00798 tmp = first_bracket + 1; 00799 } else { 00800 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); 00801 } 00802 } 00803 return tmp; 00804 }
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Get caller id number from Remote-Party-ID header field Returns true if number should be restricted (privacy setting found) output is set to NULL if no number found.
Definition at line 102 of file sip3_callerid.c. 00103 { 00104 char *start; 00105 char *end; 00106 00107 start = strchr(input,':'); 00108 if (!start) { 00109 output[0] = '\0'; 00110 return 0; 00111 } 00112 start++; 00113 00114 /* we found "number" */ 00115 ast_copy_string(output,start,maxlen); 00116 output[maxlen-1] = '\0'; 00117 00118 end = strchr(output,'@'); 00119 if (end) 00120 *end = '\0'; 00121 else 00122 output[0] = '\0'; 00123 if (strstr(input,"privacy=full") || strstr(input,"privacy=uri")) 00124 return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 00125 00126 return 0; 00127 }
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
|
Convert Asterisk hangup causes to SIP codes.
Possible values from causes.h
AST_CAUSE_NOTDEFINED AST_CAUSE_NORMAL AST_CAUSE_BUSY
AST_CAUSE_FAILURE AST_CAUSE_CONGESTION AST_CAUSE_UNALLOCATED
In addition to these, a lot of PRI codes is defined in causes.h
...should we take care of them too ?
Quote RFC 3398
ISUP Cause value SIP response
---------------- ------------
1 unallocated number 404 Not Found
2 no route to network 404 Not found
3 no route to destination 404 Not found
16 normal call clearing --- (*)
17 user busy 486 Busy here
18 no user responding 408 Request Timeout
19 no answer from the user 480 Temporarily unavailable
20 subscriber absent 480 Temporarily unavailable
21 call rejected 403 Forbidden (+)
22 number changed (w/o diagnostic) 410 Gone
22 number changed (w/ diagnostic) 301 Moved Permanently
23 redirection to new destination 410 Gone
26 non-selected user clearing 404 Not Found (=)
27 destination out of order 502 Bad Gateway
28 address incomplete 484 Address incomplete
29 facility rejected 501 Not implemented
31 normal unspecified 480 Temporarily unavailable
Definition at line 681 of file sip3_dialog.c. 00682 { 00683 switch (cause) { 00684 case AST_CAUSE_UNALLOCATED: /* 1 */ 00685 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 00686 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 00687 return "404 Not Found"; 00688 case AST_CAUSE_CONGESTION: /* 34 */ 00689 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 00690 return "503 Service Unavailable"; 00691 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 00692 return "408 Request Timeout"; 00693 case AST_CAUSE_NO_ANSWER: /* 19 */ 00694 return "480 Temporarily unavailable"; 00695 case AST_CAUSE_CALL_REJECTED: /* 21 */ 00696 return "403 Forbidden"; 00697 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 00698 return "410 Gone"; 00699 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 00700 return "480 Temporarily unavailable"; 00701 case AST_CAUSE_INVALID_NUMBER_FORMAT: 00702 return "484 Address incomplete"; 00703 case AST_CAUSE_USER_BUSY: 00704 return "486 Busy here"; 00705 case AST_CAUSE_FAILURE: 00706 return "500 Server internal failure"; 00707 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 00708 return "501 Not Implemented"; 00709 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 00710 return "503 Service Unavailable"; 00711 /* Used in chan_iax2 */ 00712 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 00713 return "502 Bad Gateway"; 00714 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 00715 return "488 Not Acceptable Here"; 00716 00717 case AST_CAUSE_NOTDEFINED: 00718 default: 00719 if (option_debug) 00720 ast_log(LOG_DEBUG, "AST hangup cause %d (no match found in SIP)\n", cause); 00721 return NULL; 00722 } 00723 00724 /* Never reached */ 00725 return 0; 00726 }
|
|
|
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 567 of file sip3_dialog.c. 00568 { 00569 /* Possible values taken from causes.h */ 00570 00571 switch(cause) { 00572 case 401: /* Unauthorized */ 00573 return AST_CAUSE_CALL_REJECTED; 00574 case 403: /* Not found */ 00575 return AST_CAUSE_CALL_REJECTED; 00576 case 404: /* Not found */ 00577 return AST_CAUSE_UNALLOCATED; 00578 case 405: /* Method not allowed */ 00579 return AST_CAUSE_INTERWORKING; 00580 case 407: /* Proxy authentication required */ 00581 return AST_CAUSE_CALL_REJECTED; 00582 case 408: /* No reaction */ 00583 return AST_CAUSE_NO_USER_RESPONSE; 00584 case 409: /* Conflict */ 00585 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 00586 case 410: /* Gone */ 00587 return AST_CAUSE_UNALLOCATED; 00588 case 411: /* Length required */ 00589 return AST_CAUSE_INTERWORKING; 00590 case 413: /* Request entity too large */ 00591 return AST_CAUSE_INTERWORKING; 00592 case 414: /* Request URI too large */ 00593 return AST_CAUSE_INTERWORKING; 00594 case 415: /* Unsupported media type */ 00595 return AST_CAUSE_INTERWORKING; 00596 case 420: /* Bad extension */ 00597 return AST_CAUSE_NO_ROUTE_DESTINATION; 00598 case 480: /* No answer */ 00599 return AST_CAUSE_NO_ANSWER; 00600 case 481: /* No answer */ 00601 return AST_CAUSE_INTERWORKING; 00602 case 482: /* Loop detected */ 00603 return AST_CAUSE_INTERWORKING; 00604 case 483: /* Too many hops */ 00605 return AST_CAUSE_NO_ANSWER; 00606 case 484: /* Address incomplete */ 00607 return AST_CAUSE_INVALID_NUMBER_FORMAT; 00608 case 485: /* Ambigous */ 00609 return AST_CAUSE_UNALLOCATED; 00610 case 486: /* Busy everywhere */ 00611 return AST_CAUSE_BUSY; 00612 case 487: /* Request terminated */ 00613 return AST_CAUSE_INTERWORKING; 00614 case 488: /* No codecs approved */ 00615 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 00616 case 491: /* Request pending */ 00617 return AST_CAUSE_INTERWORKING; 00618 case 493: /* Undecipherable */ 00619 return AST_CAUSE_INTERWORKING; 00620 case 500: /* Server internal failure */ 00621 return AST_CAUSE_FAILURE; 00622 case 501: /* Call rejected */ 00623 return AST_CAUSE_FACILITY_REJECTED; 00624 case 502: 00625 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 00626 case 503: /* Service unavailable */ 00627 return AST_CAUSE_CONGESTION; 00628 case 504: /* Gateway timeout */ 00629 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 00630 case 505: /* SIP version not supported */ 00631 return AST_CAUSE_INTERWORKING; 00632 case 600: /* Busy everywhere */ 00633 return AST_CAUSE_USER_BUSY; 00634 case 603: /* Decline */ 00635 return AST_CAUSE_CALL_REJECTED; 00636 case 604: /* Does not exist anywhere */ 00637 return AST_CAUSE_UNALLOCATED; 00638 case 606: /* Not acceptable */ 00639 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 00640 default: 00641 return AST_CAUSE_NORMAL; 00642 } 00643 /* Never reached */ 00644 return 0; 00645 }
|
|
||||||||||||||||
|
Initialize SIP request.
Definition at line 150 of file sip3_compose.c. 00151 { 00152 /* Initialize a request */ 00153 req->method = sipmethod; 00154 if (option_debug > 3) 00155 ast_log(LOG_DEBUG,"!!!!!! Size of request data in init_req: %d\n", (int) req->data_size); 00156 req->header[0] = req->data; 00157 snprintf(req->header[0], req->data_size, "%s %s SIP/2.0\r\n", sip_method2txt(sipmethod), recip); 00158 req->len = strlen(req->header[0]); 00159 req->headers++; 00160 return 0; 00161 }
|
|
||||||||||||
|
Initialize SIP response, based on SIP request.
Definition at line 138 of file sip3_compose.c. 00139 { 00140 /* Initialize a response */ 00141 resp->method = SIP_RESPONSE; 00142 resp->header[0] = resp->data; 00143 snprintf(resp->header[0], resp->data_size, "SIP/2.0 %s\r\n", msg); 00144 resp->len = strlen(resp->header[0]); 00145 resp->headers++; 00146 return 0; 00147 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled.
Definition at line 807 of file sip3_parse.c. 00808 { 00809 int h = 0, t = 0; 00810 int lws = 0; 00811 00812 for (; h < len;) { 00813 /* Eliminate all CRs */ 00814 if (msgbuf[h] == '\r') { 00815 h++; 00816 continue; 00817 } 00818 /* Check for end-of-line */ 00819 if (msgbuf[h] == '\n') { 00820 /* Check for end-of-message */ 00821 if (h + 1 == len) 00822 break; 00823 /* Check for a continuation line */ 00824 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 00825 /* Merge continuation line */ 00826 h++; 00827 continue; 00828 } 00829 /* Propagate LF and start new line */ 00830 msgbuf[t++] = msgbuf[h++]; 00831 lws = 0; 00832 continue; 00833 } 00834 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 00835 if (lws) { 00836 h++; 00837 continue; 00838 } 00839 msgbuf[t++] = msgbuf[h++]; 00840 lws = 1; 00841 continue; 00842 } 00843 msgbuf[t++] = msgbuf[h++]; 00844 if (lws) 00845 lws = 0; 00846 } 00847 msgbuf[t] = '\0'; 00848 return t; 00849 }
|
|
||||||||||||
|
Make our SIP dialog tag.
Definition at line 729 of file sip3_dialog.c. 00730 { 00731 if (sipdebug) 00732 snprintf(tagbuf, len, "asterisk%08lx", ast_random()); 00733 else 00734 snprintf(tagbuf, len, "%08lx", ast_random()); 00735 }
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send
Definition at line 152 of file sip3_parse.c. 00153 { 00154 int len = strlen(sip_methods[id].text); 00155 int l_name = name ? strlen(name) : 0; 00156 00157 /* true if the string is long enough, and ends with whitespace, and matches */ 00158 return (l_name >= len && name[len] < 33 && 00159 !strncasecmp(sip_methods[id].text, name, len)); 00160 }
|
|
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||
|
|
|
|
Parse a SIP message.
Definition at line 964 of file sip3_parse.c. 00965 { 00966 char *c = req->data, **dst = req->header; 00967 int i = 0, lim = SIP_MAX_HEADERS - 1; 00968 int seqno = 0; 00969 00970 req->header[0] = c; 00971 req->headers = -1; /* mark that we are working on the header */ 00972 for (; *c; c++) { 00973 if (*c == '\r') /* remove \r */ 00974 *c = '\0'; 00975 else if (*c == '\n') { /* end of this line */ 00976 *c = '\0'; 00977 if (sipdebug && option_debug > 3) 00978 ast_log(LOG_DEBUG, "%7s %2d [%3d]: %s\n", 00979 req->headers < 0 ? "Header" : "Body", 00980 i, (int)strlen(dst[i]), dst[i]); 00981 if (ast_strlen_zero(dst[i]) && req->headers < 0) { 00982 req->headers = i; /* record number of header lines */ 00983 dst = req->line; /* start working on the body */ 00984 i = 0; 00985 lim = SIP_MAX_LINES - 1; 00986 } else { /* move to next line, check for overflows */ 00987 if (i++ >= lim) 00988 break; 00989 } 00990 dst[i] = c + 1; /* record start of next line */ 00991 } 00992 } 00993 /* update count of header or body lines */ 00994 if (req->headers >= 0) /* we are in the body */ 00995 req->lines = i; 00996 else { /* no body */ 00997 req->headers = i; 00998 req->lines = 0; 00999 req->line[0] = ""; 01000 } 01001 01002 if (*c) 01003 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 01004 /* Split up the first line parts */ 01005 determine_firstline_parts(req); 01006 /* Determine the seqno of this request once and for all */ 01007 01008 ast_set_flag(req, SIP_PKT_PARSED); 01009 01010 req->callid = get_header(req, "Call-ID"); 01011 req->from = get_header(req, "From"); 01012 req->to = get_header(req, "To"); 01013 req->via = get_header(req, "Via"); /* Get the first via header only */ 01014 req->cseqheader = get_header(req, "CSeq"); 01015 /* Seqno can be zero, but anyway... */ 01016 if (!req->seqno && sscanf(req->cseqheader, "%d ", &seqno) != 1) 01017 req->seqno = seqno; 01018 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Print call group and pickup group.
Definition at line 174 of file sip3_cliami.c. 00175 { 00176 char buf[256]; 00177 ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); 00178 }
|
|
||||||||||||||||||||||||
|
Update peer object in realtime storage If the Asterisk system name is set in asterisk.conf, we will use that name and store that in the "regserver" field in the sippeers table to facilitate multi-server setups.
Definition at line 112 of file sip3_objects.c. 00113 { 00114 char port[10]; 00115 char ipaddr[INET_ADDRSTRLEN]; 00116 char regseconds[20]; 00117 00118 char *sysname = ast_config_AST_SYSTEM_NAME; 00119 char *syslabel = NULL; 00120 00121 time_t nowtime = time(NULL) + expiry; 00122 const char *fc = fullcontact ? "fullcontact" : NULL; 00123 00124 snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */ 00125 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 00126 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 00127 00128 if (ast_strlen_zero(sysname)) /* No system name, disable this */ 00129 sysname = NULL; 00130 else if (ast_test_flag(&global.flags[1], SIP_PAGE2_RTSAVE_SYSNAME)) 00131 syslabel = "regserver"; 00132 00133 if (fc) 00134 ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, 00135 "port", port, "regseconds", regseconds, 00136 "defaultuser", username, fc, fullcontact, syslabel, sysname, NULL); /* note fc and syslabel _can_ be NULL */ 00137 else 00138 ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, 00139 "port", port, "regseconds", regseconds, 00140 "defaultuser", username, syslabel, sysname, NULL); /* note syslabel _can_ be NULL */ 00141 }
|
|
||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
|
Convert registration state status to string.
Definition at line 101 of file sip3_services.c. 00102 { 00103 switch(regstate) { 00104 case REG_STATE_FAILED: 00105 return "Failed"; 00106 case REG_STATE_UNREGISTERED: 00107 return "Unregistered"; 00108 case REG_STATE_REGSENT: 00109 return "Request Sent"; 00110 case REG_STATE_AUTHSENT: 00111 return "Auth. Sent"; 00112 case REG_STATE_REGISTERED: 00113 return "Registered"; 00114 case REG_STATE_REJECTED: 00115 return "Rejected"; 00116 case REG_STATE_TIMEOUT: 00117 return "Timeout"; 00118 case REG_STATE_NOAUTH: 00119 return "No Authentication"; 00120 default: 00121 return "Unknown"; 00122 } 00123 }
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
|
Start the channel monitor thread.
Definition at line 126 of file sip3_monitor.c. 00127 { 00128 /* If we're supposed to be stopped -- stay stopped */ 00129 if (monitor_thread == AST_PTHREADT_STOP) 00130 return 0; 00131 /* Lock the monitor lock to keep the new monitor thread under control */ 00132 ast_mutex_lock(&monlock); 00133 if (monitor_thread == pthread_self()) { 00134 ast_mutex_unlock(&monlock); 00135 ast_log(LOG_WARNING, "Cannot kill myself\n"); 00136 return -1; 00137 } 00138 if (monitor_thread != AST_PTHREADT_NULL) { 00139 /* Wake up the thread */ 00140 pthread_kill(monitor_thread, SIGURG); 00141 } else { 00142 /* Start a new monitor */ 00143 if (ast_pthread_create_background(&monitor_thread, NULL, do_sip_monitor, NULL) < 0) { 00144 ast_mutex_unlock(&monlock); 00145 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 00146 return -1; 00147 } 00148 } 00149 00150 /* Let the monitor run by itself now */ 00151 ast_mutex_unlock(&monlock); 00152 return 0; 00153 }
|
|
||||||||||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||
|
Allocate SIP_PVT structure and set defaults.
Definition at line 803 of file sip3_dialog.c. 00805 { 00806 struct sip_dialog *dialog; 00807 00808 if (!(dialog = ast_calloc(1, sizeof(*dialog)))) 00809 return NULL; 00810 00811 if (ast_string_field_init(dialog, 512)) { 00812 free(dialog); 00813 return NULL; 00814 } 00815 sipcounters.dialog_objects++; 00816 if (option_debug > 3) 00817 ast_log(LOG_DEBUG, "--DIALOGS-- Counter %d\n", sipcounters.dialog_objects); 00818 00819 ast_mutex_init(&dialog->lock); 00820 00821 dialog->method = intended_method; 00822 dialog->initid = -1; 00823 dialog->autokillid = -1; 00824 dialog->subscribed = NONE; 00825 dialog->stateid = -1; 00826 dialog->prefs = global.default_prefs; /* Set default codecs for this call */ 00827 00828 if (intended_method != SIP_OPTIONS) /* Peerpoke has it's own system */ 00829 dialog->timer_t1 = global.t1default; /* 500 ms Default SIP retransmission timer T1 (RFC 3261) */ 00830 00831 if (sin) { 00832 dialog->sa = *sin; 00833 if (sip_ouraddrfor(&dialog->sa.sin_addr, &dialog->ourip)) 00834 dialog->ourip = sipnet.__ourip; 00835 } else 00836 dialog->ourip = sipnet.__ourip; 00837 00838 /* Copy global flags to this PVT at setup. */ 00839 ast_copy_flags(&dialog->flags[0], &global.flags[0], SIP_FLAGS_TO_COPY); 00840 ast_copy_flags(&dialog->flags[1], &global.flags[1], SIP_PAGE2_FLAGS_TO_COPY); 00841 00842 ast_set2_flag(&dialog->flags[0], !global.recordhistory, SIP_NO_HISTORY); 00843 00844 make_our_tag(dialog->tag, sizeof(dialog->tag)); 00845 dialog->ocseq = INITIAL_CSEQ; 00846 00847 /* Activate media streams */ 00848 if (sip_method_needrtp(intended_method)) { 00849 if (!dialog_activate_media(dialog, &sipnet)) { 00850 ast_mutex_destroy(&dialog->lock); 00851 if (dialog->chanvars) { 00852 ast_variables_destroy(dialog->chanvars); 00853 dialog->chanvars = NULL; 00854 } 00855 free(dialog); 00856 return NULL; 00857 } 00858 } 00859 00860 if (useglobal_nat && sin) { 00861 /* Setup NAT structure according to global settings if we have an address */ 00862 ast_copy_flags(&dialog->flags[0], &global.flags[0], SIP_NAT); 00863 dialog->recv = *sin; 00864 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 00865 } 00866 00867 if (dialog->method != SIP_REGISTER) 00868 ast_string_field_set(dialog, fromdomain, global.default_fromdomain); 00869 00870 build_via(dialog, TRUE); 00871 if (!callid) /* Make sure we have a unique call ID */ 00872 build_callid_pvt(dialog); 00873 else 00874 ast_string_field_set(dialog, callid, callid); 00875 00876 dialogstatechange(dialog, DIALOG_STATE_TRYING); /* Set dialog state */ 00877 00878 /* Assign default music on hold class */ 00879 ast_string_field_set(dialog, mohinterpret, global.default_mohinterpret); 00880 ast_string_field_set(dialog, mohsuggest, global.default_mohsuggest); 00881 00882 dialog->capability = global.capability; /* Set default codec settings */ 00883 00884 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 00885 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 00886 dialog->noncodeccapability |= AST_RTP_DTMF; 00887 00888 ast_string_field_set(dialog, context, global.default_context); 00889 dialog->allowtransfer = global.allowtransfer; /* Default transfer mode */ 00890 00891 /* Add to active dialog list */ 00892 dialoglist_lock(); 00893 dialog->next = dialoglist; 00894 dialoglist = dialog; 00895 dialoglist_unlock(); 00896 if (option_debug) 00897 ast_log(LOG_DEBUG, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_method2txt(intended_method), dialog->rtp ? "With RTP" : "No RTP"); 00898 return dialog; 00899 }
|
|
|
|
|
|
See if we pass debug IP filter.
Definition at line 758 of file sip3_network.c. 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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
T38 negotiation helper function |
|
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
|
Send a poke to all known peers Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions?
Definition at line 239 of file sip3_pokedevice.c. 00240 { 00241 int ms = 0; 00242 00243 if (!sipcounters.static_peers) /* No peers, just give up */ 00244 return; 00245 00246 ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do { 00247 ASTOBJ_WRLOCK(iterator); 00248 if (iterator->pokeexpire > -1) 00249 ast_sched_del(sched, iterator->pokeexpire); 00250 ms += 100; 00251 iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, iterator); 00252 ASTOBJ_UNLOCK(iterator); 00253 } while (0) 00254 ); 00255 }
|
|
|
React to lack of answer to Qualify poke.
Definition at line 155 of file sip3_pokedevice.c. 00156 { 00157 struct sip_device *peer = data; 00158 00159 peer->pokeexpire = -1; 00160 if (peer->lastms > -1) { 00161 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms); 00162 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1); 00163 } 00164 if (peer->call) 00165 sip_destroy(peer->call); 00166 peer->call = NULL; 00167 peer->lastms = -1; 00168 ast_device_state_changed("SIP/%s", peer->name); 00169 /* Try again quickly */ 00170 peer->pokeexpire = ast_sched_add(sched, global.default_qualifycheck_notok, sip_poke_peer_s, peer); 00171 return 0; 00172 }
|
|
|
|
|
|
Poke peer (send qualify to check if peer is alive and well).
Definition at line 93 of file sip3_pokedevice.c. 00094 { 00095 struct sip_device *peer = data; 00096 00097 peer->pokeexpire = -1; 00098 sip_poke_peer(peer); 00099 return 0; 00100 }
|
|
||||||||||||||||
|
Remove temporary realtime objects from memory (CLI).
Definition at line 2937 of file chan_sip3.c. 02938 { 02939 struct sip_device *device; 02940 int prunepeer = FALSE; 02941 int multi = FALSE; 02942 char *name = NULL; 02943 regex_t regexbuf; 02944 02945 switch (argc) { 02946 case 4: 02947 if (!strcasecmp(argv[3], "peer")) 02948 return RESULT_SHOWUSAGE; 02949 if (!strcasecmp(argv[3], "like")) 02950 return RESULT_SHOWUSAGE; 02951 if (!strcasecmp(argv[3], "all")) { 02952 multi = TRUE; 02953 prunepeer = TRUE; 02954 } else { 02955 prunepeer = TRUE; 02956 name = argv[3]; 02957 } 02958 break; 02959 case 5: 02960 if (!strcasecmp(argv[4], "like")) 02961 return RESULT_SHOWUSAGE; 02962 if (!strcasecmp(argv[3], "all")) 02963 return RESULT_SHOWUSAGE; 02964 if (!strcasecmp(argv[3], "like")) { 02965 multi = TRUE; 02966 name = argv[4]; 02967 prunepeer = TRUE; 02968 } else if (!strcasecmp(argv[3], "peer")) { 02969 prunepeer = TRUE; 02970 if (!strcasecmp(argv[4], "all")) 02971 multi = TRUE; 02972 else 02973 name = argv[4]; 02974 } else 02975 return RESULT_SHOWUSAGE; 02976 break; 02977 case 6: 02978 if (strcasecmp(argv[4], "like")) 02979 return RESULT_SHOWUSAGE; 02980 if (!strcasecmp(argv[3], "peer")) { 02981 prunepeer = TRUE; 02982 name = argv[5]; 02983 } else 02984 return RESULT_SHOWUSAGE; 02985 break; 02986 default: 02987 return RESULT_SHOWUSAGE; 02988 } 02989 02990 if (multi && name) { 02991 if (regcomp(®exbuf, name, REG_EXTENDED | REG_NOSUB)) 02992 return RESULT_SHOWUSAGE; 02993 } 02994 02995 if (multi) { 02996 if (prunepeer) { 02997 int pruned = 0; 02998 02999 ASTOBJ_CONTAINER_WRLOCK(&devicelist); 03000 ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do { 03001 ASTOBJ_RDLOCK(iterator); 03002 if (name && regexec(®exbuf, iterator->name, 0, NULL, 0)) { 03003 ASTOBJ_UNLOCK(iterator); 03004 continue; 03005 }; 03006 if (ast_test_flag(&iterator->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 03007 ASTOBJ_MARK(iterator); 03008 pruned++; 03009 } 03010 ASTOBJ_UNLOCK(iterator); 03011 } while (0) ); 03012 if (pruned) { 03013 ASTOBJ_CONTAINER_PRUNE_MARKED(&devicelist, sip_destroy_device); 03014 ast_cli(fd, "%d peers pruned.\n", pruned); 03015 } else 03016 ast_cli(fd, "No peers found to prune.\n"); 03017 ASTOBJ_CONTAINER_UNLOCK(&devicelist); 03018 } 03019 } else { 03020 if (prunepeer) { 03021 if ((device = ASTOBJ_CONTAINER_FIND_UNLINK(&devicelist, name))) { 03022 if (!ast_test_flag((&device->flags[1]), SIP_PAGE2_RTCACHEFRIENDS)) { 03023 ast_cli(fd, "Device '%s' is not a Realtime peer, cannot be pruned.\n", name); 03024 ASTOBJ_CONTAINER_LINK(&devicelist, device); 03025 } else 03026 ast_cli(fd, "Peer '%s' pruned.\n", name); 03027 device_unref(device); 03028 } else 03029 ast_cli(fd, "Device '%s' not found.\n", name); 03030 } 03031 } 03032 03033 return RESULT_SUCCESS; 03034 }
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
|
|
|
Destroy registry object Objects created with the register= statement in static configuration.
Definition at line 271 of file sip3_services.c. 00272 { 00273 /* Really delete */ 00274 if (option_debug > 2) 00275 ast_log(LOG_DEBUG, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname); 00276 00277 if (reg->call) { 00278 /* Clear registry before destroying to ensure 00279 we don't get reentered trying to grab the registry lock */ 00280 reg->call->registry = NULL; 00281 if (option_debug > 2) 00282 ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname); 00283 sip_destroy(reg->call); 00284 } 00285 if (reg->expire > -1) 00286 ast_sched_del(sched, reg->expire); 00287 if (reg->timeout > -1) 00288 ast_sched_del(sched, reg->timeout); 00289 if (reg->peer) 00290 reg->peer->registry = NULL; /* XXX ASTOBJ_UNREF ??? */ 00291 ast_string_field_free_pools(reg); 00292 sipcounters.registry_objects--; 00293 free(reg); 00294 00295 }
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
|
Send all known registrations.
Definition at line 139 of file sip3_services.c. 00140 { 00141 int ms; 00142 int regspacing; 00143 if (!sipcounters.registry_objects) 00144 return; 00145 regspacing = expiry.default_expiry * 1000/sipcounters.registry_objects; 00146 if (regspacing > 100) 00147 regspacing = 100; 00148 ms = regspacing; 00149 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 00150 ASTOBJ_WRLOCK(iterator); 00151 if (iterator->expire > -1) 00152 ast_sched_del(sched, iterator->expire); 00153 ms += regspacing; 00154 iterator->expire = ast_sched_add(sched, ms, sip_reregister, iterator); 00155 ASTOBJ_UNLOCK(iterator); 00156 } while (0) 00157 ); 00158 }
|
|
|
|
|
||||||||||||||||||||||||
|
Set the RTP peer for this call.
Definition at line 760 of file sip3_sdprtp.c. 00761 { 00762 struct sip_dialog *p; 00763 int changed = 0; 00764 00765 p = chan->tech_pvt; 00766 if (!p) 00767 return -1; 00768 dialog_lock(p, TRUE); 00769 if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE)) { 00770 /* If we're destroyed, don't bother */ 00771 dialog_lock(p, FALSE); 00772 return 0; 00773 } 00774 00775 /* if this peer cannot handle reinvites of the media stream to devices 00776 that are known to be behind a NAT, then stop the process now 00777 */ 00778 if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) { 00779 dialog_lock(p, FALSE); 00780 return 0; 00781 } 00782 00783 if (rtp) { 00784 changed |= ast_rtp_get_peer(rtp, &p->redirip); 00785 } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) { 00786 memset(&p->redirip, 0, sizeof(p->redirip)); 00787 changed = 1; 00788 } 00789 if (vrtp) { 00790 changed |= ast_rtp_get_peer(vrtp, &p->vredirip); 00791 } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) { 00792 memset(&p->vredirip, 0, sizeof(p->vredirip)); 00793 changed = 1; 00794 } 00795 if (codecs && (p->redircodecs != codecs)) { 00796 p->redircodecs = codecs; 00797 changed = 1; 00798 } 00799 if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 00800 if (chan->_state != AST_STATE_UP) { /* We are in early state */ 00801 if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) 00802 append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal."); 00803 if (option_debug) 00804 ast_log(LOG_DEBUG, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip)); 00805 } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 00806 if (option_debug > 2) { 00807 ast_log(LOG_DEBUG, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip)); 00808 } 00809 transmit_reinvite_with_sdp(p, FALSE); 00810 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 00811 if (option_debug > 2) { 00812 ast_log(LOG_DEBUG, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip)); 00813 } 00814 /* We have a pending Invite. Send re-invite when we're done with the invite */ 00815 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 00816 } 00817 } 00818 /* Reset lastrtprx timer */ 00819 p->lastrtprx = p->lastrtptx = time(NULL); 00820 dialog_lock(p, FALSE); 00821 return 0; 00822 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
CLI command to list local domains.
Definition at line 204 of file sip3_domain.c. 00205 { 00206 struct domain *d; 00207 #define FORMAT "%-40.40s %-20.20s %-16.16s\n" 00208 00209 if (domains_configured()) { 00210 ast_cli(fd, "SIP Domain support not enabled.\n\n"); 00211 return RESULT_SUCCESS; 00212 } else { 00213 ast_cli(fd, FORMAT, "Our local SIP domains:", "Context", "Set by"); 00214 AST_LIST_LOCK(&domain_list); 00215 AST_LIST_TRAVERSE(&domain_list, d, list) 00216 ast_cli(fd, FORMAT, d->domain, S_OR(d->context, "(default)"), 00217 domain_mode_to_text(d->mode)); 00218 AST_LIST_UNLOCK(&domain_list); 00219 ast_cli(fd, "\n"); 00220 return RESULT_SUCCESS; 00221 } 00222 }
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
|
|
||||||||||||
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||||||
|
Transmit register to SIP proxy or UA.
Definition at line 372 of file sip3_services.c. 00373 { 00374 struct sip_request *req; 00375 char from[256]; 00376 char to[256]; 00377 char tmp[80]; 00378 char addr[80]; 00379 struct sip_dialog *dialog; 00380 00381 req = siprequest_alloc(SIP_MAX_PACKET, &sipnet); 00382 00383 /* exit if we are already in process with this registrar ?*/ 00384 if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) { 00385 ast_log(LOG_NOTICE, "Strange, trying to register %s@%s when registration already pending\n", r->username, r->hostname); 00386 return 0; 00387 } 00388 00389 if (r->call) { /* We have a registration */ 00390 if (!auth) { 00391 ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname); 00392 return 0; 00393 } else { 00394 dialog = r->call; 00395 make_our_tag(dialog->tag, sizeof(dialog->tag)); /* create a new local tag for every register attempt */ 00396 ast_string_field_free(dialog, theirtag); /* forget their old tag, so we don't match tags when getting response */ 00397 } 00398 } else { 00399 /* Build callid for registration if we haven't registered before */ 00400 if (!r->callid_valid) { 00401 build_callid_registry(r, sipnet.__ourip, global.default_fromdomain); 00402 r->callid_valid = TRUE; 00403 } 00404 /* Allocate SIP packet for registration */ 00405 if (!(dialog = sip_alloc( r->callid, NULL, 0, SIP_REGISTER))) { 00406 ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n"); 00407 return 0; 00408 } 00409 if (!ast_test_flag(&dialog->flags[0], SIP_NO_HISTORY)) 00410 append_history(dialog, "RegistryInit", "Account: %s@%s", r->username, r->hostname); 00411 /* Find address to hostname */ 00412 if (create_addr(dialog, NULL, r->hostname, NULL)) { 00413 /* we have what we hope is a temporary network error, 00414 * probably DNS. We need to reschedule a registration try */ 00415 sip_destroy(dialog); 00416 if (r->timeout > -1) { 00417 ast_sched_del(sched, r->timeout); 00418 r->timeout = ast_sched_add(sched, global.reg_timeout*1000, sip_reg_timeout, r); 00419 ast_log(LOG_WARNING, "Still have a registration timeout for %s@%s (create_addr() error), %d\n", r->username, r->hostname, r->timeout); 00420 } else { 00421 r->timeout = ast_sched_add(sched, global.reg_timeout*1000, sip_reg_timeout, r); 00422 ast_log(LOG_WARNING, "Probably a DNS error for registration to %s@%s, trying REGISTER again (after %d seconds)\n", r->username, r->hostname, global.reg_timeout); 00423 } 00424 r->regattempts++; 00425 return 0; 00426 } 00427 /* Copy back Call-ID in case create_addr changed it */ 00428 ast_string_field_set(r, callid, dialog->callid); 00429 if (r->portno) 00430 dialog->sa.sin_port = htons(r->portno); 00431 else /* Set registry port to the port set from the peer definition/srv or default */ 00432 r->portno = ntohs(dialog->sa.sin_port); 00433 ast_set_flag(&dialog->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ 00434 r->call = dialog; /* Save pointer to SIP packet */ 00435 dialog->registry = ASTOBJ_REF(r); /* Add pointer to registry in packet */ 00436 if (!ast_strlen_zero(r->secret)) /* Secret (password) */ 00437 ast_string_field_set(dialog, peersecret, r->secret); 00438 if (!ast_strlen_zero(r->md5secret)) 00439 ast_string_field_set(dialog, peermd5secret, r->md5secret); 00440 /* User name in this realm 00441 - if authuser is set, use that, otherwise use username */ 00442 if (!ast_strlen_zero(r->authuser)) { 00443 ast_string_field_set(dialog, peername, r->authuser); 00444 ast_string_field_set(dialog, authname, r->authuser); 00445 } else if (!ast_strlen_zero(r->username)) { 00446 ast_string_field_set(dialog, peername, r->username); 00447 ast_string_field_set(dialog, authname, r->username); 00448 ast_string_field_set(dialog, fromuser, r->username); 00449 } 00450 if (!ast_strlen_zero(r->username)) 00451 ast_string_field_set(dialog, username, r->username); 00452 /* Save extension in packet */ 00453 00454 /* If we have a peer relationship, fetch som more data from taht peer. 00455 */ 00456 if (r->peer) { 00457 if (!ast_strlen_zero(r->peer->extra.fromdomain)) 00458 ast_string_field_set(dialog, fromdomain, r->peer->extra.fromdomain); 00459 } 00460 ast_string_field_set(dialog, exten, r->contact); 00461 00462 /* 00463 check which address we should use in our contact header 00464 based on whether the remote host is on the external or 00465 internal network so we can register through nat 00466 */ 00467 if (sip_ouraddrfor(&dialog->sa.sin_addr, &dialog->ourip)) 00468 dialog->ourip = sipnet.bindaddr.sin_addr; 00469 build_contact(dialog); 00470 } 00471 00472 /* set up a timeout */ 00473 if (auth == NULL) { 00474 if (r->timeout > -1) { 00475 ast_log(LOG_WARNING, "Still have a registration timeout, #%d - deleting it\n", r->timeout); 00476 ast_sched_del(sched, r->timeout); 00477 } 00478 r->timeout = ast_sched_add(sched, global.reg_timeout * 1000, sip_reg_timeout, r); 00479 if (option_debug) 00480 ast_log(LOG_DEBUG, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); 00481 } 00482 00483 if (strchr(r->username, '@')) { 00484 snprintf(from, sizeof(from), "<sip:%s>;tag=%s", r->username, dialog->tag); 00485 if (!ast_strlen_zero(dialog->theirtag)) 00486 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, dialog->theirtag); 00487 else 00488 snprintf(to, sizeof(to), "<sip:%s>", r->username); 00489 } else { 00490 snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, dialog->tohost, dialog->tag); 00491 if (!ast_strlen_zero(dialog->theirtag)) 00492 snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, dialog->tohost, dialog->theirtag); 00493 else 00494 snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, dialog->tohost); 00495 } 00496 00497 /* Fromdomain is what we are registering to, regardless of actual 00498 host name from SRV */ 00499 snprintf(addr, sizeof(addr), "sip:%s", S_OR(dialog->fromdomain, r->hostname)); 00500 ast_string_field_set(dialog, uri, addr); 00501 00502 init_req(req, sipmethod, addr); 00503 00504 /* Add to CSEQ */ 00505 snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_method2txt(sipmethod)); 00506 req->seqno = dialog->ocseq = r->ocseq; 00507 build_via(dialog, TRUE); 00508 add_header(req, "Via", dialog->via); 00509 add_header(req, "From", from); 00510 add_header(req, "To", to); 00511 add_header(req, "Call-ID", dialog->callid); 00512 add_header(req, "CSeq", tmp); 00513 add_header(req, "User-Agent", global.useragent); 00514 append_maxforwards(req); 00515 00516 if (auth) /* Add auth header */ 00517 add_header(req, authheader, auth); 00518 else if (!ast_strlen_zero(r->nonce)) { 00519 char digest[1024]; 00520 00521 /* We have auth data to reuse, build a digest header! */ 00522 if (sipdebug) 00523 ast_log(LOG_DEBUG, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); 00524 ast_string_field_set(dialog, realm, r->realm); 00525 ast_string_field_set(dialog, nonce, r->nonce); 00526 ast_string_field_set(dialog, domain, r->domain); 00527 ast_string_field_set(dialog, opaque, r->opaque); 00528 ast_string_field_set(dialog, qop, r->qop); 00529 dialog->noncecount = r->noncecount++; 00530 00531 memset(digest, 0, sizeof(digest)); 00532 if(!build_reply_digest(dialog, sipmethod, digest, sizeof(digest))) 00533 add_header(req, "Authorization", digest); 00534 else 00535 ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); 00536 00537 } 00538 00539 snprintf(tmp, sizeof(tmp), "%d", r->expiry); 00540 add_header(req, "Expires", tmp); 00541 add_header(req, "Contact", dialog->our_contact); 00542 add_header(req, "Event", "registration"); 00543 add_header_contentLength(req, 0); 00544 00545 initialize_initreq(dialog, req); 00546 if (sip_debug_test_pvt(dialog)) 00547 ast_verbose("REGISTER %d headers, %d lines\n", dialog->initreq->headers, dialog->initreq->lines); 00548 r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT; 00549 r->regattempts++; /* Another attempt */ 00550 if (option_debug > 3) 00551 ast_verbose("REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname); 00552 return send_request(dialog, req, XMIT_CRITICAL); 00553 }
|
|
|
|
|
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||||||
|
|
|
||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||||||||||
|
|
|
||||||||||||
|
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||
|
|
|
||||||||||||
|
|