Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:54 2007

Asterisk developer's documentation :: Codename Pineapple


sip3funcs.h File Reference


Detailed Description

Definitions of functions in the sip3 library files used by chan_sip3.c.

Version 3 of chan_sip

Author:
Mark Spencer <markster@digium.com>

Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)

See Also:

Definition in file sip3funcs.h.

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define GNURK

Functions

GNURK const char * __get_header (struct sip_request *req, const char *name, int *start)
GNURK void __sip_ack (struct sip_dialog *dialog, int seqno, int resp, int sipmethod, int reset)
 For a reliable transmission, we need to get an reply to stop retransmission. Acknowledges receipt of a packet and stops retransmission.
GNURK void __sip_destroy (struct sip_dialog *p, int lockowner, int lockdialoglist)
 Execute destruction of SIP dialog structure, release memory.
GNURK void __sip_pretend_ack (struct sip_dialog *p)
 Pretend to ack all packets - nothing to do with SIP_ACK (the method) maybe the lock on p is not strictly necessary but there might be a race.
GNURK int __sip_semi_ack (struct sip_dialog *p, int seqno, int resp, int sipmethod)
 Acks receipt of packet, keep it around (used for provisional responses).
GNURK int __transmit_response (struct sip_dialog *p, const char *msg, struct sip_request *req, enum xmittype reliable)
 Base transmit response function.
GNURK void add_blank (struct sip_request *req)
 add a blank line if no body
GNURK int add_digit (struct sip_request *req, char digit, unsigned int duration)
 Add DTMF INFO tone to sip message.
GNURK int add_header (struct sip_request *req, const char *var, const char *value)
 Add header to SIP message.
GNURK int add_header_contentLength (struct sip_request *req, int len)
 Add 'Content-Length' header to SIP message.
GNURK int add_line (struct sip_request *req, const char *line)
 Add content (not header) to SIP message.
GNURK struct sip_authadd_realm_authentication (struct sip_auth *authlist, char *configuration, int lineno)
 Add realm authentication in list.
GNURK void add_route (struct sip_request *req, struct sip_route *route)
 Add route header into request per learned route.
GNURK int add_sdp (struct sip_request *resp, struct sip_dialog *p)
 Add Session Description Protocol message.
GNURK 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.
GNURK int add_t38_sdp (struct sip_request *resp, struct sip_dialog *p)
 Add T.38 Session Description Protocol message.
GNURK int add_text (struct sip_request *req, const char *text)
 Add text body to SIP message.
GNURK void append_date (struct sip_request *req)
 Append date to SIP message.
GNURK void append_history_full (struct sip_dialog *p, const char *fmt,...)
 Append to SIP dialog history with arg list.
GNURK void append_history_va (struct sip_dialog *p, const char *fmt, va_list ap)
 Append to SIP dialog history with arg list.
GNURK void append_maxforwards (struct sip_request *req)
 Append Max-Forwards header to request.
GNURK void ast_quiet_chan (struct ast_channel *chan)
 Turn off generator data XXX Does this function belong in the SIP channel?
GNURK void auth_headers (enum sip_auth_type code, char **header, char **respheader)
 return the request and response heade for a 401 or 407 code
GNURK void build_callid_pvt (struct sip_dialog *pvt)
 Build SIP Call-ID value for a non-REGISTER transaction.
GNURK void build_contact (struct sip_dialog *p)
 Build contact header - the contact header we send out.
GNURK int build_reply_digest (struct sip_dialog *p, int method, char *digest, int digest_len)
 Build reply digest.
GNURK void build_rpid (struct sip_dialog *p)
 Build the Remote Party-ID & From using callingpres options.
GNURK void build_via (struct sip_dialog *p, int forcenewbranch)
 Build a Via header for a request.
GNURK enum check_auth_result check_auth (struct sip_dialog *p, struct sip_request *req, const char *username, const char *secret, const char *md5secret, int sipmethod, char *uri, enum xmittype reliable, int ignore)
 Check user authorization from peer definition Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set).
GNURK 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
GNURK int clear_realm_authentication (struct sip_auth *authlist)
 Clear realm authentication list (at reload).
GNURK void clear_sip_domains (void)
 Clear our domain list (at reload).
GNURK int close_sip_sockets (void)
 Close all open network sockets.
GNURK char * complete_sip_device (const char *word, int state, int flags2)
 Do completion on peer name.
GNURK char * complete_sip_show_device (const char *line, const char *word, int pos, int state)
 Support routine for 'sip show peer' CLI.
GNURK int copy_all_header (struct sip_request *req, struct sip_request *orig, const char *field)
 Copy all headers from one request to another.
GNURK int copy_header (struct sip_request *req, struct sip_request *orig, const char *field)
 Copy one header field from one request to another.
GNURK void copy_request (struct sip_request *dst, const struct sip_request *src)
 copy SIP request (mostly used to save request for responses)
GNURK int copy_via_headers (struct sip_dialog *p, struct sip_request *req, struct sip_request *orig, const char *field)
 Copy SIP VIA Headers from the request to the response.
GNURK int create_addr (struct sip_dialog *dialog, const char *username, char *domain, const char *device)
 create address structure from peer name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success
GNURK void destroy_association (struct sip_device *peer)
 Remove registration data from realtime database or AST/DB when registration expires.
GNURK int determine_firstline_parts (struct sip_request *req)
 Parse first line of incoming SIP request.
GNURK struct sip_devicedevice_ref (struct sip_device *device)
 Add reference for device.
GNURK int device_status (struct sip_device *peer, char *status, int statuslen)
 Report Device status in character string.
GNURK void device_unref (struct sip_device *device)
 Remove reference for device. When we reach 0, device is removed from memory.
GNURK void dialog_lock (struct sip_dialog *dialog, int state)
 Helper function to lock and unlock, hiding the underlying locking mechanism.
GNURK void dialoglist_lock (void)
 Lock list of active SIP dialogs.
GNURK void dialoglist_unlock (void)
 Unlock list of active SIP dialogs.
GNURK const char * dialogstate2str (const enum dialogstate state)
 Convert SIP dialog states to string.
GNURK void dialogstatechange (struct sip_dialog *dialog, enum dialogstate newstate)
 Change dialog state for a SIP dialog and output to debug.
GNURK int do_proxy_auth (struct sip_dialog *p, struct sip_request *req, enum sip_auth_type code, int sipmethod, int init)
 Add authentication on outbound SIP packet.
GNURK int do_register_auth (struct sip_dialog *p, struct sip_request *req, enum sip_auth_type code)
 Authenticate for outbound registration.
GNURK void do_setnat (struct sip_dialog *p, int natflags)
 Set nat mode on the various media streams.
void * do_sip_monitor (void *data)
 The SIP monitoring thread.
GNURK const char * domain_mode_to_text (const enum domain_mode mode)
 Print domain mode to cli.
GNURK int domains_configured (void)
 return TRUE if any domains are configured for this server
GNURK int expire_register (void *data)
 Expire registration of SIP peer.
GNURK void extract_uri (struct sip_dialog *p, struct sip_request *req)
 Check Contact: URI of SIP message.
GNURK const char * find_alias (const char *name, const char *_default)
 Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP.
GNURK struct sip_devicefind_device (const char *peer, struct sockaddr_in *sin, int realtime)
 Locate peer by name or ip address This is used on incoming SIP message to find matching peer on ip or outgoing message to find matching peer on name.
GNURK struct sip_authfind_realm_authentication (struct sip_auth *authlist, const char *realm)
 Find authentication for a specific realm.
GNURK int find_sdp (struct sip_request *req)
 Determine whether a SIP message contains an SDP in its body.
GNURK int find_sip_method (const char *msg)
 find_sip_method: Find SIP method from header
GNURK const struct cfsubscription_typesfind_subscription_type (enum subscriptiontype subtype)
 Find subscription type in array.
GNURK void find_via_branch (struct sip_request *req, char *viabuf, size_t vialen)
 Find via branch parameter.
GNURK void free_old_route (struct sip_route *route)
 Remove route from route list.
GNURK 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.
GNURK char * generate_random_string (char *buf, size_t size)
 Generate 32 byte random string for callid's etc.
GNURK char * get_body (struct sip_request *req, char *name)
 Get the message body part identified by name=.
GNURK char * get_calleridname (const char *input, char *output, size_t outputsize)
 Get caller id name from SIP headers.
GNURK int get_destination (struct sip_dialog *p, struct sip_request *oreq)
 Find out who the call is for We use the INVITE request uri to find out Runs a dialplan lookup.
GNURK const char * get_header (struct sip_request *req, const char *name)
 Get header from SIP request.
GNURK char * get_in_brackets (char *tmp)
 Pick out text in brackets from character string.
GNURK int get_rdnis (struct sip_dialog *p, struct sip_request *oreq)
 Get referring dnis.
GNURK 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.
GNURK struct sip_dialogget_sip_dialog_byid_locked (const char *callid, const char *totag, const char *fromtag)
 Lock dialog list lock and find matching pvt lock
  • Their tag is fromtag, our tag is to-tag
  • This means that in some transactions, totag needs to be their tag :-) depending upon the direction.

GNURK const char * gettag (const char *header, char *tagbuf, int tagbufsize)
 Get tag from packet.
GNURK int handle_request (struct sip_dialog *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock)
 Handle incoming SIP requests (methods).
GNURK int handle_request_refer (struct sip_dialog *p, struct sip_request *req, int debug, int seqno, int *nounlock)
void handle_response_peerpoke (struct sip_dialog *p, int resp, struct sip_request *req)
 Handle qualification responses (OPTIONS).
GNURK int handle_response_register (struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno)
 Handle responses on REGISTER to services.
GNURK const char * hangup_cause2sip (int cause)
 Convert Asterisk hangup causes to SIP codes.
GNURK int hangup_sip2cause (int cause)
 Convert SIP hangup causes to Asterisk hangup causes.
GNURK int init_req (struct sip_request *req, int sipmethod, const char *recip)
 Initialize SIP request.
GNURK int init_resp (struct sip_request *resp, const char *msg)
 Initialize SIP response, based on SIP request.
GNURK void initialize_initreq (struct sip_dialog *p, struct sip_request *req)
 Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog.
GNURK void initreqprep (struct sip_request *req, struct sip_dialog *p, int sipmethod)
 Initiate new SIP request to peer/user.
void kill_monitor (void)
 kill monitor thread (only at module unload)
GNURK void logdebug (int level, const char *fmt,...)
 Append to SIP dialog history with arg list.
GNURK int lws2sws (char *msgbuf, int len)
 Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled.
GNURK void make_our_tag (char *tagbuf, size_t len)
 Make our SIP dialog tag.
GNURK int manager_sip_show_device (struct mansession *s, const struct message *m)
 Show SIP peers in the manager API.
GNURK int manager_sip_show_devices (struct mansession *s, const struct message *m)
 Show SIP peers in the manager API.
GNURK struct sip_dialogmatch_or_create_dialog (struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
GNURK 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
GNURK void parse_moved_contact (struct sip_dialog *p, struct sip_request *req)
 Parse 302 Moved temporalily response.
GNURK void parse_request (struct sip_request *req)
 Parse a SIP message.
GNURK unsigned int parse_sip_options (struct sip_dialog *pvt, const char *supported)
 Parse supported header in incoming packet.
GNURK void print_group (int fd, ast_group_t group, int crlf)
 Print call group and pickup group.
GNURK int process_sdp (struct sip_dialog *p, struct sip_request *req)
 Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call.
GNURK struct sip_devicerealtime_peer (const char *newpeername, struct sockaddr_in *sin)
 realtime_peer: Get peer from realtime storage Checks the "sippeers" realtime family from extconfig.conf
GNURK void realtime_update_peer (const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expiry)
 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.
GNURK const char * referstatus2str (enum referstatus rstatus) attribute_pure
 Convert transfer status to string.
GNURK void reg_source_db (struct sip_device *peer)
GNURK void register_peer_exten (struct sip_device *device, int onoff)
 Automatically add peer extension to dial plan.
GNURK void register_rtp_and_udptl (void)
 Register RTP and UDPTL to the subsystems.
GNURK char * regstate2str (enum sipregistrystate regstate) attribute_const
 Convert registration state status to string.
GNURK int reload_config (enum channelreloadreason reason)
 Re-read SIP.conf config file.
GNURK void replace_cid (struct sip_dialog *p, const char *rpid_num, const char *calleridname)
 helper function for check_{user|peer}_ok()
GNURK int reply_digest (struct sip_dialog *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len)
 reply to authentication for outbound registrations
GNURK int reqprep (struct sip_request *req, struct sip_dialog *p, int sipmethod, int seqno, int newbranch)
 Initialize a SIP request message (not the initial one in a dialog).
GNURK void reset_ip_interface (struct sip_network *sipsock)
 clear IP interfaces
GNURK int respprep (struct sip_request *resp, struct sip_dialog *p, const char *msg, struct sip_request *req)
 Prepare SIP response packet.
int restart_monitor (void)
 Start the channel monitor thread.
GNURK int send_request (struct sip_dialog *p, struct sip_request *req, enum xmittype reliable)
 Send SIP Request to the other part of the dialogue.
GNURK int send_response (struct sip_dialog *p, struct sip_request *req, enum xmittype reliable)
 Transmit response on SIP request.
GNURK void set_device_defaults (struct sip_device *device)
 Set peer defaults before configuring specific configurations.
GNURK void set_initreq (struct sip_dialog *dialog, struct sip_request *req)
 Set packet to initreq status. Set flag to avoid de-allocation until dialog is destroyed.
GNURK struct sip_dialogsip_alloc (ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method)
 Allocate SIP_PVT structure and set defaults.
GNURK void sip_cancel_destroy (struct sip_dialog *p)
 Cancel destruction of SIP dialog.
GNURK void sip_cli_and_manager_commands_register (void)
 Register cli and manager commands.
GNURK void sip_cli_and_manager_commands_unregister (void)
 Unregister cli and manager commands.
GNURK int sip_debug_test_addr (const struct sockaddr_in *addr)
 See if we pass debug IP filter.
GNURK int sip_debug_test_pvt (struct sip_dialog *p)
 Test PVT for debugging output.
GNURK void sip_destroy (struct sip_dialog *p)
 Destroy SIP call structure.
GNURK void sip_destroy_device (struct sip_device *peer)
 Destroy device object from memory.
GNURK int sip_do_reload (void)
 Reload module.
GNURK void sip_dump_history (struct sip_dialog *dialog)
 Dump SIP history to debug log file at end of lifespan for SIP dialog.
GNURK enum ast_rtp_get_result sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
 Returns null if we can't reinvite audio (part of RTP interface).
GNURK enum ast_rtp_get_result sip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
 Returns null if we can't reinvite video (part of RTP interface).
GNURK int sip_listconfigs (int fd)
 List all configuration options in sip.conf.
GNURK char * sip_method2txt (int method)
 return text string for sip method
GNURK int sip_method_needrtp (int method)
 Check whether method needs RTP.
GNURK const char * sip_nat_mode (const struct sip_dialog *p)
 Display SIP nat mode.
GNURK int sip_notify (int fd, int argc, char *argv[])
GNURK char * sip_option2text (int option)
 Return text representation of SIP option.
GNURK int sip_option_lookup (const char *optionlabel)
 Check if sip option is known to us, avoid x- options (non-standard).
GNURK void sip_options_print (int options, int fd)
 Print options to cli.
GNURK int sip_ouraddrfor (struct in_addr *them, struct in_addr *us)
 NAT fix - decide which IP address to use for Asterisk server?
GNURK void sip_peer_hold (struct sip_dialog *p, int hold)
 Change onhold state of a peer using a pvt structure.
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_device *peer)
 Check availability of peer, also keep NAT open.
int sip_poke_peer_s (void *data)
 Poke peer (send qualify to check if peer is alive and well).
GNURK int sip_prune_realtime (int fd, int argc, char *argv[])
 Remove temporary realtime objects from memory (CLI).
GNURK struct ast_framesip_read (struct ast_channel *ast)
 Read SIP RTP from channel.
GNURK const struct sockaddr_in * sip_real_dst (const struct sip_dialog *p)
 The real destination address for a write.
GNURK int sip_refer_allocate (struct sip_dialog *p)
 Allocate SIP refer structure.
GNURK int sip_register (char *value, int lineno, struct sip_device *peer)
 Parse register=> line in sip.conf and add to registry.
GNURK void sip_registry_destroy (struct sip_registry *reg)
 Destroy registry object Objects created with the register= statement in static configuration.
GNURK int sip_reload (int fd)
 Force reload of module from cli.
GNURK int sip_reload_check (void)
GNURK void sip_scheddestroy (struct sip_dialog *p, int ms)
 Schedule destruction of SIP dialog.
GNURK void sip_send_all_registers (void)
 Send all known registrations.
GNURK int sip_send_mwi_to_peer (struct sip_device *peer)
 Send message waiting indication to alert peer that they've got voicemail.
GNURK 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.
GNURK int sip_show_domains (int fd, int argc, char *argv[])
 CLI command to list local domains.
GNURK void sipnet_lock (struct sip_network *sipnet)
 Lock netlock.
GNURK int sipnet_ourport (struct sip_network *sipnet)
 read our port number
GNURK void sipnet_ourport_set (struct sip_network *sipnet, int port)
 Set our port number.
GNURK void sipnet_unlock (struct sip_network *sipnet)
 Unlock netlock.
GNURK struct sip_requestsiprequest_alloc (size_t len, struct sip_network *sipnet)
 Allocate SIP request structure.
GNURK void siprequest_free (struct sip_request *req)
 Free SIP request.
GNURK int sipsock_init (struct sip_network *sipsock, struct sockaddr_in *old_bindappr)
 Initialize IP socket on configured address - the bind address.
GNURK int sipsock_read (int *id, int fd, short events, void *ignore)
 Read data from SIP socket.
GNURK int sipsocket_initialized (struct sip_network *sipnet)
 Check if network socket is open.
GNURK int sipsocket_open (struct sip_network *sipnet)
 Open network socket, bind to address and set options (TOS).
GNURK void stop_media_flows (struct sip_dialog *dialog)
 Immediately stop RTP, VRTP and UDPTL as applicable.
GNURK const char * subscription_type2str (enum subscriptiontype subtype) attribute_pure
 Show subscription type in string format.
GNURK struct sip_devicetemp_device (const char *name)
 Create temporary peer (used in autocreatepeer mode).
GNURK void transmit_fake_auth_response (struct sip_dialog *p, struct sip_request *req, int reliable)
 Send a fake 401 Unauthorized response when the administrator wants to hide the names of local users/peers from fishers.
GNURK int transmit_final_response (struct sip_dialog *dialog, const char *msg, struct sip_request *req, enum xmittype reliable)
 Transmit final response to a request and close dialog Set dialog state to TERMINATED to avoid problems At some point, after debugging, we can remove the reliable flag. Only responses to INVITEs are sent reliably.
GNURK int transmit_info_with_digit (struct sip_dialog *p, const char digit, unsigned int duration)
 Send SIP INFO dtmf message, see Cisco documentation on cisco.com.
GNURK int transmit_info_with_vidupdate (struct sip_dialog *p)
 Send SIP INFO with video update request.
GNURK int transmit_invite (struct sip_dialog *p, int sipmethod, int sdp, int init)
 Build REFER/INVITE/OPTIONS message and transmit it.
GNURK int transmit_message_with_text (struct sip_dialog *p, const char *text)
 Transmit text with SIP MESSAGE method.
GNURK int transmit_notify_with_mwi (struct sip_dialog *p, int newmsgs, int oldmsgs, char *vmexten)
 Notify user of messages waiting in voicemail.
GNURK int transmit_notify_with_sipfrag (struct sip_dialog *p, int cseq, char *message, int terminate)
 Notify a transferring party of the status of transfer.
GNURK int transmit_refer (struct sip_dialog *p, const char *dest)
 Transmit SIP REFER message (initiated by the transfer() dialplan application.
GNURK int transmit_register (struct sip_registry *r, int sipmethod, const char *auth, const char *authheader)
 Transmit register to SIP proxy or UA.
GNURK int transmit_reinvite_with_sdp (struct sip_dialog *p, int t38version)
 Transmit reinvite with SDP.
GNURK int transmit_request (struct sip_dialog *p, int sipmethod, int inc, enum xmittype reliable, int newbranch)
 Transmit generic SIP request.
GNURK int transmit_request_with_auth (struct sip_dialog *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 Transmit SIP request, auth added.
GNURK int transmit_response (struct sip_dialog *p, const char *msg, struct sip_request *req)
 Transmit response, no retransmits.
GNURK int transmit_response_reliable (struct sip_dialog *p, const char *msg, struct sip_request *req)
 Transmit response, Make sure you get an ACK This is only used for responses to INVITEs, where we need to make sure we get an ACK.
GNURK int transmit_response_with_attachment (enum responseattach attach, struct sip_dialog *p, const char *msg, struct sip_request *req, enum xmittype reliable)
 Transmit responses with various attachments.
GNURK int transmit_response_with_auth (struct sip_dialog *p, const char *msg, struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale)
 Respond with authorization request.
GNURK int transmit_response_with_unsupported (struct sip_dialog *p, const char *msg, struct sip_request *req, const char *unsupported)
 Transmit response, no retransmits.
GNURK int transmit_sip_request (struct sip_dialog *p, struct sip_request *req)
 Transmit SIP request unreliably (only used in sip_notify subsystem).
GNURK int transmit_state_notify (struct sip_dialog *p, int state, int full, int timeout)
 Used in the SUBSCRIBE notification subsystem.
GNURK void try_suggested_sip_codec (struct sip_dialog *p)
GNURK void unregister_rtp_and_udptl (void)
 UNRegister RTP and UDPTL to the subsystems.
GNURK int update_call_counter (struct sip_dialog *fup, int event)
 update_call_counter: Handle call_limit for SIP users Setting a call-limit will cause calls above the limit not to be accepted.
GNURK void update_peer (struct sip_device *device, int expiry)
 Update peer data in database (if used).

Variables

GNURK struct ast_custom_function checksipdomain_function


Define Documentation

#define GNURK
 

Definition at line 40 of file sip3funcs.h.


Function Documentation

GNURK const char* __get_header struct sip_request req,
const char *  name,
int *  start
 

Definition at line 587 of file sip3_parse.c.

References ast_log(), ast_test_flag, sip_request::header, sip_request::headers, len, LOG_ERROR, parse_request(), SIP_PKT_CONNECTED, and SIP_PKT_PARSED.

00588 {
00589    int pass;
00590 
00591    if (!ast_test_flag(req, SIP_PKT_PARSED)) {
00592       /* Ok, so this req is not parse by parse_request yet. */
00593       /* Parsing it before we have finished re-transmit may be bad. */
00594       if (!ast_test_flag(req, SIP_PKT_CONNECTED))
00595          parse_request(req);
00596       else {
00597          ast_log(LOG_ERROR, "Can't get header %s from request before parsing. Hang in for a jumpy ride!\n", name);
00598          return "";
00599       }
00600          
00601    }
00602    /*
00603     * Technically you can place arbitrary whitespace both before and after the ':' in
00604     * a header, although RFC3261 clearly says you shouldn't before, and place just
00605     * one afterwards.  If you shouldn't do it, what absolute idiot decided it was 
00606     * a good idea to say you can do it, and if you can do it, why in the hell would.
00607     * you say you shouldn't.
00608     */
00609    for (pass = 0; name && pass < 2;pass++) {
00610       int x, len = strlen(name);
00611       for (x=*start; x<req->headers; x++) {
00612          if (!strncasecmp(req->header[x], name, len)) {
00613             char *r = req->header[x] + len;  /* skip name */
00614             r = ast_skip_blanks(r);
00615 
00616             if (*r == ':') {
00617                *start = x+1;
00618                return ast_skip_blanks(r+1);
00619             }
00620          }
00621       }
00622       if (pass == 0) /* Try aliases */
00623          name = find_alias(name, NULL);
00624    }
00625 
00626    /* Don't return NULL, so get_header is always a valid pointer */
00627    return "";
00628 }

GNURK void __sip_ack struct sip_dialog dialog,
int  seqno,
int  resp,
int  sipmethod,
int  reset
 

For a reliable transmission, we need to get an reply to stop retransmission. Acknowledges receipt of a packet and stops retransmission.

Note:
Assume that the dialog is locked.

Definition at line 261 of file sip3_dialog.c.

References ast_clear_flag, ast_log(), ast_sched_del(), ast_test_flag, sip_request::dialog, dialog_lock(), FALSE, LOG_DEBUG, sip_request::method, sip_request::next, option_debug, sip_dialog::packets, parse_request(), sip_dialog::pendinginvite, sip_request::retransid, sip_request::seqno, SIP_PKT_CONNECTED, SIP_PKT_INITREQ, SIP_PKT_PARSED, SIP_PKT_RESPONSE, sipdebug, siprequest_free(), TRUE, and UNLINK.

00262 {
00263    struct sip_request *cur, *prev = NULL;
00264    int res = FALSE;
00265 
00266    if (option_debug) {
00267       if (!resp)
00268          ast_log(LOG_DEBUG, "Trying to confirm pending invite %d Call ID %s\n", dialog->pendinginvite, dialog->callid);
00269       else
00270          ast_log(LOG_DEBUG, "Trying to confirm pending response on Call ID %s\n", dialog->callid);
00271    }
00272 
00273    dialog_lock(dialog, TRUE);
00274 
00275    /* Find proper transaction */
00276    for (cur = dialog->packets; cur; prev = cur, cur = cur->next) {
00277       if (option_debug > 2)
00278          ast_log(LOG_DEBUG, "--Checking packet with seqno %d against response with seqno %d\n", cur->seqno, seqno);
00279       /* Match on seqno AND req/resp AND method? */
00280       if ((cur->seqno == seqno) && ((ast_test_flag(cur, SIP_PKT_RESPONSE)) == resp) &&
00281          ((ast_test_flag(cur, SIP_PKT_RESPONSE)) || (cur->method == sipmethod))) {
00282          if (!resp && (seqno == dialog->pendinginvite)) {
00283             if (sipdebug && option_debug && !reset)
00284                ast_log(LOG_DEBUG, "Got reply to pending invite %d - Call Id %s\n", dialog->pendinginvite, dialog->callid);
00285             dialog->pendinginvite = 0;
00286          } else {
00287             if (sipdebug && option_debug && !reset)
00288                ast_log(LOG_DEBUG, "Got ACK on INVITE response Cseq %d Call Id %s\n", cur->seqno, dialog->callid);
00289          }
00290          /* this is our baby */
00291          res = TRUE;
00292          UNLINK(cur, dialog->packets, prev);
00293          if (cur->retransid > -1) {
00294             if (sipdebug && option_debug > 3 && !reset)
00295                ast_log(LOG_DEBUG, "Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
00296             ast_sched_del(sched, cur->retransid);
00297             cur->retransid = -1;
00298          }
00299          if (!reset) {
00300             if (!ast_test_flag(cur, SIP_PKT_INITREQ)) 
00301                siprequest_free(cur);   /* We might want to keep this somewhere else */
00302             else {
00303                if (sipdebug && option_debug > 3 && !reset)
00304                   ast_log(LOG_DEBUG, "This is the initial request, keeping it in memory - Cseq %d\n", cur->seqno);
00305                ast_clear_flag(cur, SIP_PKT_CONNECTED);
00306                if (!ast_test_flag(cur, SIP_PKT_PARSED))
00307                   parse_request(cur);  /* Parse initreq now, after we have answer */
00308             }
00309          }
00310          break;
00311       }
00312    }
00313    dialog_lock(dialog, FALSE);
00314    if (option_debug && sipdebug)
00315       ast_log(LOG_DEBUG, "Stopping retransmission on '%s' of %s %d: Match %s\n", dialog->callid, resp ? "Response" : "Request", seqno, res ? "Found" : "Not Found");
00316 }

GNURK void __sip_destroy struct sip_dialog p,
int  lockowner,
int  lockdialoglist
 

Execute destruction of SIP dialog structure, release memory.

Definition at line 366 of file sip3_dialog.c.

References ast_channel_lock, ast_channel_unlock, ast_extension_state_del(), AST_LIST_REMOVE_HEAD, ast_log(), ast_rtp_destroy(), ast_sched_del(), ast_test_flag, ast_udptl_destroy(), ast_verbose(), ASTOBJ_UNREF, DEC_CALL_LIMIT, DEC_CALL_RINGING, sip_request::dialog, dialoglist, dialoglist_lock(), sip_globals::dumphistory, sip_dialog::flags, free, free_old_route(), global, LOG_DEBUG, sip_dialog::next, option_debug, sip_debug_test_pvt(), sip_dump_history(), SIP_INC_COUNT, sip_method2txt(), SIP_PAGE2_INC_RINGING, sip_registry_destroy(), UNLINK, and update_call_counter().

00367 {
00368    struct sip_dialog *cur, *prev = NULL;
00369    struct sip_request *cp;
00370 
00371    if (ast_test_flag(&dialog->flags[0], SIP_INC_COUNT))        /* This dialog has incremented call count */
00372       update_call_counter(dialog, DEC_CALL_LIMIT);          /* Since it was forgotten, decrement call count */
00373 
00374    if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_INC_RINGING))         /* This dialog has incremented ring count */
00375       update_call_counter(dialog, DEC_CALL_RINGING);           /* Since it was forgotten, decrement ring count */
00376 
00377    if (sip_debug_test_pvt(dialog) || option_debug > 2)
00378       ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", dialog->callid, sip_method2txt(dialog->method));
00379 
00380 
00381    /* Remove link from peer to subscription of MWI */
00382    if (dialog->relatedpeer && dialog->relatedpeer->mailbox.mwipvt)
00383       dialog->relatedpeer->mailbox.mwipvt = NULL;
00384 
00385    if (global.dumphistory)
00386       sip_dump_history(dialog);
00387 
00388 
00389    if (dialog->stateid > -1)
00390       ast_extension_state_del(dialog->stateid, NULL);
00391    if (dialog->initid > -1)
00392       ast_sched_del(sched, dialog->initid);
00393    if (dialog->autokillid > -1)
00394       ast_sched_del(sched, dialog->autokillid);
00395 
00396    if (dialog->inviteoptions)
00397       free(dialog->inviteoptions);
00398 
00399    if (dialog->rtp)
00400       ast_rtp_destroy(dialog->rtp);
00401    if (dialog->vrtp)
00402       ast_rtp_destroy(dialog->vrtp);
00403    if (dialog->udptl)
00404       ast_udptl_destroy(dialog->udptl);
00405    if (dialog->refer)
00406       free(dialog->refer);
00407    if (dialog->route) {
00408       free_old_route(dialog->route);
00409       dialog->route = NULL;
00410    }
00411    if (dialog->registry) {
00412       if (dialog->registry->call == dialog)
00413          dialog->registry->call = NULL;
00414       ASTOBJ_UNREF(dialog->registry, sip_registry_destroy);
00415    }
00416 
00417    /* Unlink us from the owner if we have one */
00418    if (dialog->owner) {
00419       if (lockowner)
00420          ast_channel_lock(dialog->owner);
00421       if (option_debug)
00422          ast_log(LOG_DEBUG, "Detaching from %s\n", dialog->owner->name);
00423       dialog->owner->tech_pvt = NULL;
00424       if (lockowner)
00425          ast_channel_unlock(dialog->owner);
00426    }
00427    /* Clear history */
00428    if (dialog->history) {
00429       struct sip_history *hist;
00430       while( (hist = AST_LIST_REMOVE_HEAD(dialog->history, list)) )
00431          free(hist);
00432       free(dialog->history);
00433       dialog->history = NULL;
00434    }
00435 
00436 
00437    /* Unlink us from the dialog list */
00438    if (lockdialoglist)
00439       dialoglist_lock();
00440    for (prev = NULL, cur = dialoglist; cur; prev = cur, cur = cur->next) {
00441       if (cur == dialog) {
00442          UNLINK(cur, dialoglist, prev);
00443          break;
00444       }
00445    }
00446    if (lockdialoglist)
00447       dialoglist_unlock();
00448 
00449    if (!cur) {
00450       ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", dialog->callid);
00451       return;
00452    } 
00453 
00454    /* remove all current packets in this dialog */
00455    while((cp = dialog->packets)) {
00456       /* If one of the records in the packet list is the initreq, then release it */
00457       if (cp == dialog->initreq)
00458          dialog->initreq = NULL;
00459 
00460       dialog->packets = dialog->packets->next;
00461       if (cp->retransid > -1)
00462          ast_sched_del(sched, cp->retransid);
00463       free(cp);
00464    }
00465 
00466    if (dialog->initreq)
00467       siprequest_free(dialog->initreq);
00468 
00469    if (dialog->chanvars) {
00470       ast_variables_destroy(dialog->chanvars);
00471       dialog->chanvars = NULL;
00472    }
00473    ast_mutex_destroy(&dialog->lock);
00474 
00475    ast_string_field_free_pools(dialog);
00476 
00477    /* Finally, release the dialog */
00478    free(dialog);
00479 
00480    sipcounters.dialog_objects--;
00481    if (option_debug > 3)
00482       ast_log(LOG_DEBUG, "--DIALOGS-- Counter %d\n", sipcounters.dialog_objects);
00483 }

GNURK void __sip_pretend_ack struct sip_dialog p  ) 
 

Pretend to ack all packets - nothing to do with SIP_ACK (the method) maybe the lock on p is not strictly necessary but there might be a race.

Definition at line 320 of file sip3_dialog.c.

References __sip_ack(), ast_log(), ast_test_flag, sip_request::data, sip_request::dialog, FALSE, find_sip_method(), LOG_WARNING, sip_request::method, sip_dialog::packets, sip_request::seqno, sip_method2txt(), and SIP_PKT_RESPONSE.

00321 {
00322    struct sip_request *cur = NULL;
00323 
00324    while (dialog->packets) {
00325       int method;
00326       if (cur == dialog->packets) {
00327          ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_method2txt(cur->method));
00328          return;
00329       }
00330       cur = dialog->packets;
00331       method = (cur->method) ? cur->method : find_sip_method(cur->data);
00332       __sip_ack(dialog, cur->seqno, ast_test_flag(cur, SIP_PKT_RESPONSE), method, FALSE);
00333    }
00334 }

GNURK int __sip_semi_ack struct sip_dialog dialog,
int  seqno,
int  resp,
int  sipmethod
 

Acks receipt of packet, keep it around (used for provisional responses).

Note:
Assume that the dialog is locked.

Definition at line 339 of file sip3_dialog.c.

References ast_log(), ast_sched_del(), ast_test_flag, sip_request::data, sip_request::dialog, LOG_DEBUG, method_match(), sip_request::next, option_debug, sip_dialog::packets, sip_request::retransid, sip_request::seqno, sip_method2txt(), SIP_PKT_RESPONSE, and sipdebug.

00340 {
00341    struct sip_request *cur;
00342    int res = -1;
00343 
00344    for (cur = dialog->packets; cur; cur = cur->next) {
00345       if (option_debug > 2)
00346          ast_log(LOG_DEBUG, "--Checking packet with seqno %d against response with seqno %d\n", cur->seqno, seqno);
00347       if (cur->seqno == seqno && ast_test_flag(cur, SIP_PKT_RESPONSE) == resp &&
00348          (ast_test_flag(cur, SIP_PKT_RESPONSE) || method_match(sipmethod, cur->data))) {
00349          /* this is our baby */
00350          if (cur->retransid > -1) {
00351             if (option_debug > 3 && sipdebug)
00352                ast_log(LOG_DEBUG, "Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_method2txt(sipmethod));
00353             ast_sched_del(sched, cur->retransid);
00354          }
00355          cur->retransid = -1;
00356          res = 0;
00357          break;
00358       }
00359    }
00360    if (option_debug)
00361       ast_log(LOG_DEBUG, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %d: %s\n", dialog->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found");
00362    return res;
00363 }

GNURK int __transmit_response struct sip_dialog p,
const char *  msg,
struct sip_request req,
enum xmittype  reliable
 

Base transmit response function.

sip3_transmit.c

Definition at line 113 of file sip3_transmit.c.

References add_header(), add_header_contentLength(), ast_cause2str(), ast_log(), sip_request::data_size, get_header(), ast_channel::hangupcause, LOG_DEBUG, LOG_WARNING, sip_dialog::method, sip_dialog::owner, respprep(), send_response(), sip_request::seqno, SIP_INVITE, SIP_MAX_PACKET, sipnet, siprequest_alloc(), siprequest_free(), and XMIT_UNRELIABLE.

00114 {
00115    struct sip_request *resp;
00116    int seqno = 0;
00117    int res;
00118 
00119 
00120    if (reliable && (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1)) {
00121       ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
00122       return -1;
00123    }
00124 
00125    resp = siprequest_alloc(SIP_MAX_PACKET, &sipnet);
00126    ast_log(LOG_DEBUG, "   :::: Response data size: %d\n", (int) resp->data_size);
00127    resp->seqno = seqno;
00128    respprep(resp, p, msg, req);
00129    add_header_contentLength(resp, 0);
00130    /* If we are cancelling an incoming invite for some reason, add information
00131       about the reason why we are doing this in clear text */
00132    if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) {
00133       char buf[10];
00134 
00135       add_header(resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause));
00136       snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause);
00137       add_header(resp, "X-Asterisk-HangupCauseCode", buf);
00138    }
00139    res =  send_response(p, resp, reliable);
00140    if (reliable == XMIT_UNRELIABLE)
00141       siprequest_free(resp);
00142    return res;
00143 }

GNURK void add_blank struct sip_request req  ) 
 

add a blank line if no body

Definition at line 128 of file sip3_compose.c.

References sip_request::data, sip_request::data_size, sip_request::len, and sip_request::lines.

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 }

GNURK int add_digit struct sip_request req,
char  digit,
unsigned int  duration
 

Add DTMF INFO tone to sip message.

Definition at line 205 of file sip3_compose.c.

References add_header(), add_header_contentLength(), and add_line().

00206 {
00207    char tmp[256];
00208 
00209    snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
00210    add_header(req, "Content-Type", "application/dtmf-relay");
00211    add_header_contentLength(req, strlen(tmp));
00212    add_line(req, tmp);
00213    return 0;
00214 }

GNURK int add_header struct sip_request req,
const char *  var,
const char *  value
 

Add header to SIP message.

sip3_compose.c : Composing new SIP messages

Definition at line 89 of file sip3_compose.c.

References ast_log(), sip_globals::compactheaders, sip_request::data, sip_request::data_size, find_alias(), global, sip_request::header, sip_request::headers, sip_request::len, sip_request::lines, LOG_DEBUG, LOG_WARNING, option_debug, and SIP_MAX_HEADERS.

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 }

GNURK int add_header_contentLength struct sip_request req,
int  len
 

Add 'Content-Length' header to SIP message.

Definition at line 362 of file sip3_compose.c.

References add_header().

00363 {
00364    char clen[10];
00365 
00366    snprintf(clen, sizeof(clen), "%d", len);
00367    return add_header(req, "Content-Length", clen);
00368 }

GNURK int add_line struct sip_request req,
const char *  line
 

Add content (not header) to SIP message.

Definition at line 399 of file sip3_compose.c.

References ast_log(), sip_request::data, sip_request::data_size, sip_request::len, sip_request::line, sip_request::lines, LOG_WARNING, and SIP_MAX_LINES.

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 }

GNURK struct sip_auth* add_realm_authentication struct sip_auth authlist,
char *  configuration,
int  lineno
 

Add realm authentication in list.

Definition at line 495 of file sip3_auth.c.

References ast_calloc, ast_log(), ast_strlen_zero(), ast_verbose(), LOG_DEBUG, LOG_WARNING, sip_auth::md5secret, sip_auth::next, option_debug, option_verbose, sip_auth::realm, secret, strsep(), and sip_auth::username.

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 }

GNURK void add_route struct sip_request req,
struct sip_route route
 

Add route header into request per learned route.

Definition at line 371 of file sip3_compose.c.

References sip_route::hop, and sip_route::next.

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 }

GNURK int add_sdp struct sip_request resp,
struct sip_dialog p
 

Add Session Description Protocol message.

Todo:
XXX We need to select one codec, not many, since there's no transcoding

Definition at line 1029 of file sip3_sdprtp.c.

References add_codec_to_sdp(), ast_build_string(), ast_codec_pref_index(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname_multiple(), ast_inet_ntoa(), ast_log(), ast_test_flag, ast_verbose(), capability, FALSE, sip_dialog::flags, get_our_media_address(), sip_dialog::jointcapability, len, LOG_WARNING, sip_dialog::maxcallbitrate, option_debug, sip_dialog::ourip, sip_dialog::prefcodec, sip_dialog::prefs, sip_dialog::rtp, sip_dialog::sessionid, sip_dialog::sessionversion, sip_debug_test_pvt(), SIP_NOVIDEO, SIP_PAGE2_CALL_ONHOLD_INACTIVE, SIP_PAGE2_CALL_ONHOLD_ONEDIR, SIP_PAGE2_T38SUPPORT_RTP, sip_dialog::t38, t38properties::t38support, TRUE, and sip_dialog::vrtp.

01030 {
01031    int len = 0;
01032    int alreadysent = 0;
01033 
01034    struct sockaddr_in sin;
01035    struct sockaddr_in vsin;
01036    struct sockaddr_in dest;
01037    struct sockaddr_in vdest = { 0, };
01038 
01039    /* SDP fields */
01040    char *version =   "v=0\r\n";     /* Protocol version */
01041    char *subject =   "s=session\r\n";  /* Subject of the session */
01042    char owner[256];           /* Session owner/creator */
01043    char connection[256];            /* Connection data */
01044    char *stime = "t=0 0\r\n";          /* Time the session is active */
01045    char bandwidth[256] = "";        /* Max bitrate */
01046    char *hold;
01047    char m_audio[256];            /* Media declaration line for audio */
01048    char m_video[256];            /* Media declaration line for video */
01049    char a_audio[1024];           /* Attributes for audio */
01050    char a_video[1024];           /* Attributes for video */
01051    char *m_audio_next = m_audio;
01052    char *m_video_next = m_video;
01053    size_t m_audio_left = sizeof(m_audio);
01054    size_t m_video_left = sizeof(m_video);
01055    char *a_audio_next = a_audio;
01056    char *a_video_next = a_video;
01057    size_t a_audio_left = sizeof(a_audio);
01058    size_t a_video_left = sizeof(a_video);
01059 
01060    int x;
01061    int capability;
01062    int needvideo = FALSE;
01063    int debug = sip_debug_test_pvt(p);
01064    int min_audio_packet_size = 0;
01065    int min_video_packet_size = 0;
01066 
01067    m_video[0] = '\0';   /* Reset the video media string if it's not needed */
01068 
01069    if (!p->rtp) {
01070       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
01071       return -1;
01072    }
01073 
01074    /* Set RTP Session ID and version */
01075    if (!p->sessionid) {
01076       p->sessionid = getpid();
01077       p->sessionversion = p->sessionid;
01078    } else
01079       p->sessionversion++;
01080 
01081    /* Ok, let's start working with codec selection here */
01082    capability = p->jointcapability;
01083 
01084    if (option_debug > 1) {
01085       char codecbuf[BUFSIZ];
01086       ast_log(LOG_DEBUG, "** Our capability: %s Video flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), ast_test_flag(&p->flags[0], SIP_NOVIDEO) ? "True" : "False");
01087       ast_log(LOG_DEBUG, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
01088    }
01089    
01090 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS
01091    if ((ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP))) {
01092       ast_build_string(&m_audio_next, &m_audio_left, " %d", 191);
01093       ast_build_string(&a_audio_next, &a_audio_left, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
01094    }
01095 #endif
01096 
01097    /* Check if we need video in this call */
01098    if((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
01099       if (p->vrtp) {
01100          needvideo = TRUE;
01101          if (option_debug > 1)
01102             ast_log(LOG_DEBUG, "This call needs video offers! \n");
01103       } else if (option_debug > 1)
01104          ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled ! \n");
01105    }
01106 
01107    /* Get our media IP addresses for RTP */
01108    get_our_media_address(p, needvideo, &sin, &vsin, &dest, &vdest);
01109 
01110    /* Ok, we need video. Let's add what we need for video and set codecs.
01111       Video is handled differently than audio since we can not transcode. */
01112    if (needvideo) {
01113       ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
01114 
01115       /* Build max bitrate string */
01116       if (p->maxcallbitrate)
01117          snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
01118       if (debug) 
01119          ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));   
01120 
01121       /*! \todo XXX We need to select one codec, not many, since there's no transcoding */
01122    }
01123    if (debug) 
01124       ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port)); 
01125 
01126    /* Start building generic SDP headers */
01127 
01128    /* We break with the "recommendation" and send our IP, in order that our
01129       peer doesn't have to ast_gethostbyname() us */
01130 
01131    snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
01132    snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
01133    ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
01134 
01135    if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR))
01136       hold = "a=recvonly\r\n";
01137    else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE))
01138       hold = "a=inactive\r\n";
01139    else
01140       hold = "a=sendrecv\r\n";
01141 
01142    /* Now, start adding audio codecs. These are added in this order:
01143       - First what was requested by the calling channel
01144       - Then preferences in order from sip.conf device config for this peer/user
01145       - Then other codecs in capabilities, including video
01146    */
01147 
01148    /* Prefer the audio codec we were requested to use, first, no matter what 
01149       Note that p->prefcodec can include video codecs, so mask them out
01150     */
01151    if (capability & p->prefcodec) {
01152       add_codec_to_sdp(p, p->prefcodec & AST_FORMAT_AUDIO_MASK, 8000,
01153              &m_audio_next, &m_audio_left,
01154              &a_audio_next, &a_audio_left,
01155              debug, &min_audio_packet_size);
01156       alreadysent |= p->prefcodec & AST_FORMAT_AUDIO_MASK;
01157    }
01158 
01159 
01160    /* Start by sending our preferred audio codecs */
01161    for (x = 0; x < 32; x++) {
01162       int pref_codec;
01163 
01164       if (!(pref_codec = ast_codec_pref_index(&p->prefs, x)))
01165          break; 
01166 
01167       if (!(capability & pref_codec))
01168          continue;
01169 
01170       if (alreadysent & pref_codec)
01171          continue;
01172 
01173       add_codec_to_sdp(p, pref_codec, 8000,
01174              &m_audio_next, &m_audio_left,
01175              &a_audio_next, &a_audio_left,
01176              debug, &min_audio_packet_size);
01177       alreadysent |= pref_codec;
01178    }
01179 
01180    /* Now send any other common audio and video codecs, and non-codec formats: */
01181    for (x = 1; x <= (needvideo ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) {
01182       if (!(capability & x))  /* Codec not requested */
01183          continue;
01184 
01185       if (alreadysent & x) /* Already added to SDP */
01186          continue;
01187 
01188       if (x <= AST_FORMAT_MAX_AUDIO)
01189          add_codec_to_sdp(p, x, 8000,
01190                 &m_audio_next, &m_audio_left,
01191                 &a_audio_next, &a_audio_left,
01192                 debug, &min_audio_packet_size);
01193       else 
01194          add_codec_to_sdp(p, x, 90000,
01195                 &m_video_next, &m_video_left,
01196                 &a_video_next, &a_video_left,
01197                 debug, &min_video_packet_size);
01198    }
01199 
01200    /* Now add DTMF RFC2833 telephony-event as a codec */
01201    for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
01202       if (!(p->jointnoncodeccapability & x))
01203          continue;
01204 
01205       add_noncodec_to_sdp(p, x, 8000,
01206                 &m_audio_next, &m_audio_left,
01207                 &a_audio_next, &a_audio_left,
01208                 debug);
01209    }
01210 
01211    if (option_debug > 2)
01212       ast_log(LOG_DEBUG, "-- Done with adding codecs to SDP\n");
01213 
01214    if(!p->owner || !ast_internal_timing_enabled(p->owner))
01215       ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
01216    if (min_audio_packet_size)
01217       ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
01218 
01219    if (min_video_packet_size)
01220       ast_build_string(&a_video_next, &a_video_left, "a=ptime:%d\r\n", min_video_packet_size);
01221 
01222 
01223    if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
01224       ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
01225 
01226    ast_build_string(&m_audio_next, &m_audio_left, "\r\n");
01227    if (needvideo)
01228       ast_build_string(&m_video_next, &m_video_left, "\r\n");
01229 
01230    len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(stime) + strlen(m_audio) + strlen(a_audio) + strlen(hold);
01231    if (needvideo) /* only if video response is appropriate */
01232       len += strlen(m_video) + strlen(a_video) + strlen(bandwidth) + strlen(hold);
01233 
01234    add_header(resp, "Content-Type", "application/sdp");
01235    add_header_contentLength(resp, len);
01236    add_line(resp, version);
01237    add_line(resp, owner);
01238    add_line(resp, subject);
01239    add_line(resp, connection);
01240    if (needvideo)    /* only if video response is appropriate */
01241       add_line(resp, bandwidth);
01242    add_line(resp, stime);
01243    add_line(resp, m_audio);
01244    add_line(resp, a_audio);
01245    add_line(resp, hold);
01246    if (needvideo) { /* only if video response is appropriate */
01247       add_line(resp, m_video);
01248       add_line(resp, a_video);
01249       add_line(resp, hold);   /* Repeat hold for the video stream */
01250    }
01251 
01252    /* Update lastrtprx when we send our SDP */
01253    p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
01254 
01255    if (option_debug > 2) {
01256       char buf[BUFSIZ];
01257       ast_log(LOG_DEBUG, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, BUFSIZ, capability));
01258    }
01259 
01260    return 0;
01261 }

GNURK 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.

sip3_domain.c: Domain handling functions (sip domain hosting, not DNS lookups)

Definition at line 95 of file sip3_domain.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, and option_debug.

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 }

GNURK int add_t38_sdp struct sip_request resp,
struct sip_dialog p
 

Add T.38 Session Description Protocol message.

Definition at line 1749 of file chan_sip3.c.

References add_header(), add_header_contentLength(), add_line(), ast_build_string(), ast_inet_ntoa(), ast_log(), ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), t38properties::capability, debug(), t38properties::jointcapability, sip_dialog::lastrtprx, sip_dialog::lastrtptx, len, LOG_DEBUG, LOG_WARNING, sip_dialog::ourip, t38properties::peercapability, s, sip_dialog::sessionid, sip_dialog::sessionversion, sip_debug_test_pvt(), sip_dialog::t38, t38_get_rate(), T38FAX_FILL_BIT_REMOVAL, T38FAX_RATE_MANAGEMENT_LOCAL_TCF, T38FAX_TRANSCODING_JBIG, T38FAX_TRANSCODING_MMR, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, T38FAX_VERSION, T38FAX_VERSION_0, T38FAX_VERSION_1, sip_dialog::udptl, and sip_dialog::udptlredirip.

01750 {
01751    int len = 0;
01752    int x = 0;
01753    struct sockaddr_in udptlsin;
01754    char v[256] = "";
01755    char s[256] = "";
01756    char o[256] = "";
01757    char c[256] = "";
01758    char t[256] = "";
01759    char m_modem[256];
01760    char a_modem[1024];
01761    char *m_modem_next = m_modem;
01762    size_t m_modem_left = sizeof(m_modem);
01763    char *a_modem_next = a_modem;
01764    size_t a_modem_left = sizeof(a_modem);
01765    struct sockaddr_in udptldest = { 0, };
01766    int debug;
01767    
01768    debug = sip_debug_test_pvt(p);
01769    len = 0;
01770    if (!p->udptl) {
01771       ast_log(LOG_WARNING, "No way to add SDP without an UDPTL structure\n");
01772       return -1;
01773    }
01774    
01775    if (!p->sessionid) {
01776       p->sessionid = getpid();
01777       p->sessionversion = p->sessionid;
01778    } else
01779       p->sessionversion++;
01780    
01781    /* Our T.38 end is */
01782    ast_udptl_get_us(p->udptl, &udptlsin);
01783    
01784    /* Determine T.38 UDPTL destination */
01785    if (p->udptlredirip.sin_addr.s_addr) {
01786       udptldest.sin_port = p->udptlredirip.sin_port;
01787       udptldest.sin_addr = p->udptlredirip.sin_addr;
01788    } else {
01789       udptldest.sin_addr = p->ourip;
01790       udptldest.sin_port = udptlsin.sin_port;
01791    }
01792    
01793    if (debug) 
01794       ast_log(LOG_DEBUG, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
01795    
01796    /* We break with the "recommendation" and send our IP, in order that our
01797       peer doesn't have to ast_gethostbyname() us */
01798    
01799    if (debug) {
01800       ast_log(LOG_DEBUG, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
01801          p->t38.capability,
01802          p->t38.peercapability,
01803          p->t38.jointcapability);
01804    }
01805    snprintf(v, sizeof(v), "v=0\r\n");
01806    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(udptldest.sin_addr));
01807    snprintf(s, sizeof(s), "s=session\r\n");
01808    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
01809    snprintf(t, sizeof(t), "t=0 0\r\n");
01810    ast_build_string(&m_modem_next, &m_modem_left, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
01811    
01812    if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
01813       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:0\r\n");
01814    if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
01815       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:1\r\n");
01816    if ((x = t38_get_rate(p->t38.jointcapability)))
01817       ast_build_string(&a_modem_next, &a_modem_left, "a=T38MaxBitRate:%d\r\n",x);
01818    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxFillBitRemoval:%d\r\n", (p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) ? 1 : 0);
01819    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingMMR:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_MMR) ? 1 : 0);
01820    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingJBIG:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) ? 1 : 0);
01821    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
01822    x = ast_udptl_get_local_max_datagram(p->udptl);
01823    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxBuffer:%d\r\n",x);
01824    ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxDatagram:%d\r\n",x);
01825    if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
01826       ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
01827     len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m_modem) + strlen(a_modem);
01828    add_header(resp, "Content-Type", "application/sdp");
01829    add_header_contentLength(resp, len);
01830    add_line(resp, v);
01831    add_line(resp, o);
01832    add_line(resp, s);
01833    add_line(resp, c);
01834    add_line(resp, t);
01835    add_line(resp, m_modem);
01836    add_line(resp, a_modem);
01837    
01838    /* Update lastrtprx when we send our SDP */
01839    p->lastrtprx = p->lastrtptx = time(NULL);
01840    
01841    return 0;
01842 }

GNURK int add_text struct sip_request req,
const char *  text
 

Add text body to SIP message.

Definition at line 195 of file sip3_compose.c.

References add_header(), add_header_contentLength(), and add_line().

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 }

GNURK void append_date struct sip_request req  ) 
 

Append date to SIP message.

Definition at line 175 of file sip3_compose.c.

References add_header().

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 }

GNURK void append_history_full struct sip_dialog p,
const char *  fmt,
  ...
 

Append to SIP dialog history with arg list.

Definition at line 127 of file sip3_utils.c.

References append_history_va().

00128 {
00129    va_list ap;
00130 
00131    if (!dialog)
00132       return;
00133    va_start(ap, fmt);
00134    append_history_va(dialog, fmt, ap);
00135    va_end(ap);
00136 
00137    return;
00138 }

GNURK void append_history_va struct sip_dialog p,
const char *  fmt,
va_list  ap
 

Append to SIP dialog history with arg list.

Definition at line 107 of file sip3_utils.c.

References ast_calloc, AST_LIST_INSERT_TAIL, free, and strsep().

00108 {
00109    char buf[80], *c = buf; /* max history length */
00110    struct sip_history *hist;
00111    int l;
00112 
00113    vsnprintf(buf, sizeof(buf), fmt, ap);
00114    strsep(&c, "\r\n"); /* Trim up everything after \r or \n */
00115    l = strlen(buf) + 1;
00116    if (!(hist = ast_calloc(1, sizeof(*hist) + l)))
00117       return;
00118    if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) {
00119       free(hist);
00120       return;
00121    }
00122    memcpy(hist->event, buf, l);
00123    AST_LIST_INSERT_TAIL(p->history, hist, list);
00124 }

GNURK void append_maxforwards struct sip_request req  ) 
 

Append Max-Forwards header to request.

Definition at line 187 of file sip3_compose.c.

References add_header(), global, and sip_globals::maxforwards.

Referenced by reqprep(), transmit_refer(), and transmit_register().

00188 {
00189    char buf[4];
00190    snprintf(buf, sizeof(buf), "%d", global.maxforwards);
00191    add_header(req, "Max-Forwards", buf);
00192 }

GNURK void ast_quiet_chan struct ast_channel chan  ) 
 

Turn off generator data XXX Does this function belong in the SIP channel?

Definition at line 4034 of file chan_sip3.c.

References ast_channel::_state, ast_deactivate_generator(), AST_STATE_UP, and ast_channel::generatordata.

04035 {
04036    if (chan && chan->_state == AST_STATE_UP) {
04037       if (chan->generatordata)
04038          ast_deactivate_generator(chan);
04039    }
04040 }

GNURK void auth_headers enum sip_auth_type  code,
char **  header,
char **  respheader
 

return the request and response heade for a 401 or 407 code

sip3_auth.c

Definition at line 133 of file sip3_auth.c.

References ast_verbose(), PROXY_AUTH, and WWW_AUTH.

00134 {
00135    if (code == WWW_AUTH) {       /* 401 */
00136       *header = "WWW-Authenticate";
00137       *respheader = "Authorization";
00138    } else if (code == PROXY_AUTH) { /* 407 */
00139       *header = "Proxy-Authenticate";
00140       *respheader = "Proxy-Authorization";
00141    } else {
00142       ast_verbose("-- wrong response code %d\n", code);
00143       *header = *respheader = "Invalid";
00144    }
00145 }

GNURK void build_callid_pvt struct sip_dialog pvt  ) 
 

Build SIP Call-ID value for a non-REGISTER transaction.

Definition at line 164 of file sip3_compose.c.

References ast_inet_ntoa(), ast_string_field_build, generate_random_string(), sip_dialog::ourip, and S_OR.

00165 {
00166    char buf[33];
00167 
00168    const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip));
00169    
00170    ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
00171 
00172 }

GNURK void build_contact struct sip_dialog p  ) 
 

Build contact header - the contact header we send out.

Definition at line 217 of file sip3_compose.c.

References ast_inet_ntoa(), ast_string_field_build, ast_strlen_zero(), sipnet, sipnet_ourport(), and STANDARD_SIP_PORT.

00218 {
00219    /* Construct Contact: header */
00220    if (sipnet_ourport(&sipnet) != STANDARD_SIP_PORT)  /* Needs to be 5060, according to the RFC */
00221       ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip), sipnet_ourport(&sipnet));
00222    else
00223       ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
00224 }

GNURK int build_reply_digest struct sip_dialog p,
int  method,
char *  digest,
int  digest_len
 

Build reply digest.

Returns:
Returns -1 if we have no auth
Note:
Build digest challenge for authentication of peers (for registration) and users (for calls). Also used for authentication of CANCEL and BYE

Definition at line 428 of file sip3_auth.c.

References ast_inet_ntoa(), ast_log(), ast_md5_hash(), ast_random(), ast_strlen_zero(), authl, find_realm_authentication(), LOG_DEBUG, LOG_WARNING, sip_auth::md5secret, sip_dialog::noncecount, sip_dialog::sa, sip_auth::secret, secret, sip_method2txt(), and sip_auth::username.

00429 {
00430    char a1[256];
00431    char a2[256];
00432    char a1_hash[256];
00433    char a2_hash[256];
00434    char resp[256];
00435    char resp_hash[256];
00436    char uri[256];
00437    char cnonce[80];
00438    const char *username;
00439    const char *secret;
00440    const char *md5secret;
00441    struct sip_auth *auth = NULL; /* Realm authentication */
00442 
00443    if (!ast_strlen_zero(p->domain))
00444       ast_copy_string(uri, p->domain, sizeof(uri));
00445    else if (!ast_strlen_zero(p->uri))
00446       ast_copy_string(uri, p->uri, sizeof(uri));
00447    else
00448       snprintf(uri, sizeof(uri), "sip:%s@%s",p->peername, ast_inet_ntoa(p->sa.sin_addr));
00449 
00450    snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random());
00451 
00452    /* Check if we have separate auth credentials */
00453    if ((auth = find_realm_authentication(authl, p->realm))) {
00454       ast_log(LOG_WARNING, "use realm [%s] from peer [%s]\n",
00455          auth->username, p->peername);
00456       username = auth->username;
00457       secret = auth->secret;
00458       md5secret = auth->md5secret;
00459       if (sipdebug)
00460          ast_log(LOG_DEBUG,"Using realm %s authentication for call %s\n", p->realm, p->callid);
00461    } else {
00462       /* No authentication, use peer or register= config */
00463       username = p->authname;
00464       secret =  p->peersecret;
00465       md5secret = p->peermd5secret;
00466    }
00467    if (ast_strlen_zero(username))   /* We have no authentication */
00468       return -1;
00469 
00470    /* Calculate SIP digest response */
00471    snprintf(a1,sizeof(a1), "%s:%s:%s", username, p->realm, secret);
00472    snprintf(a2,sizeof(a2), "%s:%s", sip_method2txt(method), uri);
00473    if (!ast_strlen_zero(md5secret))
00474       ast_copy_string(a1_hash, md5secret, sizeof(a1_hash));
00475    else
00476       ast_md5_hash(a1_hash, a1);
00477    ast_md5_hash(a2_hash,a2);
00478 
00479    p->noncecount++;
00480    if (!ast_strlen_zero(p->qop))
00481       snprintf(resp,sizeof(resp),"%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash);
00482    else
00483       snprintf(resp,sizeof(resp),"%s:%s:%s", a1_hash, p->nonce, a2_hash);
00484    ast_md5_hash(resp_hash, resp);
00485    /* XXX We hard code our qop to "auth" for now.  XXX */
00486    if (!ast_strlen_zero(p->qop))
00487       snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\", qop=auth, cnonce=\"%s\", nc=%08x", username, p->realm, uri, p->nonce, resp_hash, p->opaque, cnonce, p->noncecount);
00488    else
00489       snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\"", username, p->realm, uri, p->nonce, resp_hash, p->opaque);
00490 
00491    return 0;
00492 }

GNURK void build_rpid struct sip_dialog p  ) 
 

Build the Remote Party-ID & From using callingpres options.

Definition at line 228 of file sip3_compose.c.

References ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED, AST_PRES_ALLOWED_NETWORK_NUMBER, AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_PROHIB_NETWORK_NUMBER, AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, AST_PRES_RESTRICTION, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), sip_dialog::callingpres, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, sip_globals::default_callerid, FALSE, global, LOG_WARNING, sip_dialog::ourip, sip_dialog::owner, S_OR, sip_dialog::tag, and TRUE.

00229 {
00230    int send_pres_tags = TRUE;
00231    const char *privacy=NULL;
00232    const char *screen=NULL;
00233    char buf[256];
00234    const char *clid = global.default_callerid;
00235    const char *clin = NULL;
00236    const char *fromdomain;
00237 
00238    if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))  
00239       return;
00240 
00241    if (p->owner && p->owner->cid.cid_num)
00242       clid = p->owner->cid.cid_num;
00243    if (p->owner && p->owner->cid.cid_name)
00244       clin = p->owner->cid.cid_name;
00245    if (ast_strlen_zero(clin))
00246       clin = clid;
00247 
00248    switch (p->callingpres) {
00249    case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
00250       privacy = "off";
00251       screen = "no";
00252       break;
00253    case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
00254       privacy = "off";
00255       screen = "pass";
00256       break;
00257    case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
00258       privacy = "off";
00259       screen = "fail";
00260       break;
00261    case AST_PRES_ALLOWED_NETWORK_NUMBER:
00262       privacy = "off";
00263       screen = "yes";
00264       break;
00265    case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
00266       privacy = "full";
00267       screen = "no";
00268       break;
00269    case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
00270       privacy = "full";
00271       screen = "pass";
00272       break;
00273    case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
00274       privacy = "full";
00275       screen = "fail";
00276       break;
00277    case AST_PRES_PROHIB_NETWORK_NUMBER:
00278       privacy = "full";
00279       screen = "pass";
00280       break;
00281    case AST_PRES_NUMBER_NOT_AVAILABLE:
00282       send_pres_tags = FALSE;
00283       break;
00284    default:
00285       ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
00286       if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
00287          privacy = "full";
00288       else
00289          privacy = "off";
00290       screen = "no";
00291       break;
00292    }
00293    
00294    fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip));
00295 
00296    snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
00297    if (send_pres_tags)
00298       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
00299    ast_string_field_set(p, rpid, buf);
00300 
00301    ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
00302                 S_OR(p->fromuser, clid),
00303                 fromdomain, p->tag);
00304 }

GNURK void build_via struct sip_dialog p,
int  forcenewbranch
 

Build a Via header for a request.

Definition at line 1236 of file sip3_dialog.c.

References ast_inet_ntoa(), ast_string_field_build, ast_test_flag, sip_dialog::flags, ourdialogbranch(), sip_dialog::ourip, SIP_NAT, SIP_NAT_RFC3581, sipnet, and sipnet_ourport().

01237 {
01238    /* Work around buggy UNIDEN UIP200 firmware */
01239    const char *rport = ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
01240 
01241    /* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
01242    ast_string_field_build(dialog, via, "SIP/2.0/UDP %s:%d;branch=%s%s",
01243          ast_inet_ntoa(dialog->ourip), sipnet_ourport(&sipnet), 
01244          ourdialogbranch(dialog, forcenewbranch), rport);
01245 }

GNURK enum check_auth_result check_auth struct sip_dialog p,
struct sip_request req,
const char *  username,
const char *  secret,
const char *  md5secret,
int  sipmethod,
char *  uri,
enum xmittype  reliable,
int  ignore
 

Check user authorization from peer definition Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set).

Returns:
0 on success, non-zero on error

Definition at line 152 of file sip3_auth.c.

References ast_random(), ast_string_field_build, ast_strlen_zero(), AUTH_CHALLENGE_SENT, auth_headers(), AUTH_SUCCESSFUL, DEFAULT_TRANS_TIMEOUT, FALSE, get_header(), key(), keys, s, sip_scheddestroy(), strsep(), transmit_response_with_auth(), and WWW_AUTH.

00155 {
00156    const char *response = "407 Proxy Authentication Required";
00157    char *reqheader;
00158    char *respheader;
00159    const char *authtoken;
00160    char a1_hash[256];
00161    char resp_hash[256]="";
00162    char tmp[BUFSIZ * 2];                /* Make a large enough buffer */
00163    char *c;
00164    int  wrongnonce = FALSE;
00165    int  good_response;
00166    const char *usednonce = p->randdata;
00167 
00168    /* table of recognised keywords, and their value in the digest */
00169    enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST };
00170    struct x {
00171       const char *key;
00172       const char *s;
00173    } *i, keys[] = {
00174       [K_RESP] = { "response=", "" },
00175       [K_URI] = { "uri=", "" },
00176       [K_USER] = { "username=", "" },
00177       [K_NONCE] = { "nonce=", "" },
00178       [K_LAST] = { NULL, NULL}
00179    };
00180 
00181    /* Always OK if no secret */
00182    if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))
00183       return AUTH_SUCCESSFUL;
00184    response = "401 Unauthorized";
00185    auth_headers(WWW_AUTH, &respheader, &reqheader);   
00186    authtoken =  get_header(req, reqheader);  
00187    if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
00188       /* This is a retransmitted invite/register/etc, don't reconstruct authentication
00189          information */
00190       if (!reliable) {
00191          /* Resend message if this was NOT a reliable delivery.   Otherwise the
00192             retransmission should get it */
00193          transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
00194          /* Schedule auto destroy in 32 seconds (according to RFC 3261) */
00195          sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
00196       }
00197       return AUTH_CHALLENGE_SENT;
00198    } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
00199       /* We have no auth, so issue challenge and request authentication */
00200       ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
00201       transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
00202       /* Schedule auto destroy in 32 seconds */
00203       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
00204       return AUTH_CHALLENGE_SENT;
00205    } 
00206 
00207    /* --- We have auth, so check it */
00208 
00209    /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
00210          an example in the spec of just what it is you're doing a hash on. */
00211 
00212 
00213    /* Make a copy of the response and parse it */
00214    ast_copy_string(tmp, authtoken, sizeof(tmp));
00215    c = tmp;
00216 
00217    while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */
00218       for (i = keys; i->key != NULL; i++) {
00219          const char *separator = ",";  /* default */
00220 
00221          if (strncasecmp(c, i->key, strlen(i->key)) != 0)
00222             continue;
00223          /* Found. Skip keyword, take text in quotes or up to the separator. */
00224          c += strlen(i->key);
00225          if (*c == '"') { /* in quotes. Skip first and look for last */
00226             c++;
00227             separator = "\"";
00228          }
00229          i->s = c;
00230          strsep(&c, separator);
00231          break;
00232       }
00233       if (i->key == NULL) /* not found, jump after space or comma */
00234          strsep(&c, " ,");
00235    }
00236 
00237    /* Verify that digest username matches  the username we auth as */
00238    if (strcmp(username, keys[K_USER].s)) {
00239       ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n",
00240          username, keys[K_USER].s);
00241       /* Oops, we're trying something here */
00242       return AUTH_USERNAME_MISMATCH;
00243    }
00244 
00245    /* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
00246    if (strcasecmp(p->randdata, keys[K_NONCE].s)) { /* XXX it was 'n'casecmp ? */
00247       wrongnonce = TRUE;
00248       usednonce = keys[K_NONCE].s;
00249    }
00250 
00251    if (!ast_strlen_zero(md5secret))
00252       ast_copy_string(a1_hash, md5secret, sizeof(a1_hash));
00253    else {
00254       char a1[256];
00255       snprintf(a1, sizeof(a1), "%s:%s:%s", username, global.realm, secret);
00256       ast_md5_hash(a1_hash, a1);
00257    }
00258 
00259    /* compute the expected response to compare with what we received */
00260    {
00261       char a2[256];
00262       char a2_hash[256];
00263       char resp[256];
00264 
00265       snprintf(a2, sizeof(a2), "%s:%s", sip_method2txt(sipmethod), S_OR(keys[K_URI].s, uri));
00266       ast_md5_hash(a2_hash, a2);
00267       snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash);
00268       ast_md5_hash(resp_hash, resp);
00269    }
00270 
00271    good_response = keys[K_RESP].s &&
00272          !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash));
00273    if (wrongnonce) {
00274       ast_string_field_build(p, randdata, "%08lx", ast_random());
00275       if (good_response) {
00276          if (sipdebug)
00277             ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "To"));
00278          /* We got working auth token, based on stale nonce . */
00279          transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 1);
00280       } else {
00281          /* Everything was wrong, so give the device one more try with a new challenge */
00282          if (sipdebug)
00283             ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To"));
00284          transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
00285       }
00286 
00287       /* Schedule auto destroy in 32 seconds */
00288       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
00289       return AUTH_CHALLENGE_SENT;
00290    } 
00291    if (good_response)
00292       return AUTH_SUCCESSFUL;
00293 
00294    /* Ok, we have a bad username/secret pair */
00295    /* Challenge again, and again, and again */
00296    transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
00297    sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
00298 
00299    return AUTH_CHALLENGE_SENT;
00300 }

GNURK 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

Definition at line 132 of file sip3_domain.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), domain::context, and domain::domain.

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 }

GNURK int clear_realm_authentication struct sip_auth authlist  ) 
 

Clear realm authentication list (at reload).

Definition at line 554 of file sip3_auth.c.

References free, and sip_auth::next.

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 }

GNURK void clear_sip_domains void   ) 
 

Clear our domain list (at reload).

Definition at line 154 of file sip3_domain.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and free.

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 }

GNURK int close_sip_sockets void   ) 
 

Close all open network sockets.

Definition at line 185 of file sip3_network.c.

References sipnet, sip_network::sipsock, and TRUE.

00186 {
00187    /* Start with sipnet */
00188    close(sipnet.sipsock);
00189    return TRUE;
00190 }

GNURK char* complete_sip_device const char *  word,
int  state,
int  flags2
 

Do completion on peer name.

Definition at line 919 of file sip3_cliami.c.

References ast_strdup, ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, and devicelist.

Referenced by complete_sip_debug_device(), complete_sip_prune_realtime_peer(), complete_sip_show_device(), and complete_sipnotify().

00920 {
00921    char *result = NULL;
00922    int wordlen = strlen(word);
00923    int which = 0;
00924 
00925    ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !result, do {
00926       /* locking of the object is not required because only the name and flags are being compared */
00927       if (!strncasecmp(word, iterator->name, wordlen) &&
00928             (!flags2 || ast_test_flag(&iterator->flags[1], flags2)) &&
00929             ++which > state)
00930          result = ast_strdup(iterator->name);
00931    } while(0) );
00932    return result;
00933 }

GNURK char* complete_sip_show_device const char *  line,
const char *  word,
int  pos,
int  state
 

Support routine for 'sip show peer' CLI.

Definition at line 936 of file sip3_cliami.c.

References complete_sip_device().

00937 {
00938    if (pos == 3)
00939       return complete_sip_device(word, state, 0);
00940 
00941    return NULL;
00942 }

GNURK int copy_all_header struct sip_request req,
struct sip_request orig,
const char *  field
 

Copy all headers from one request to another.

Definition at line 649 of file sip3_parse.c.

References __get_header(), add_header(), and ast_strlen_zero().

00650 {
00651    int start = 0;
00652    int copied = 0;
00653    int res;
00654 
00655    for (;;) {
00656       const char *tmp = __get_header(orig, field, &start);
00657 
00658       if (ast_strlen_zero(tmp))
00659          break;
00660       /* Add what we're responding to */
00661       res = add_header(req, field, tmp);
00662       if (res != -1)
00663          copied++;
00664       else
00665          return -1;
00666       
00667    }
00668    return copied ? 0 : -1;
00669 }

GNURK int copy_header struct sip_request req,
struct sip_request orig,
const char *  field
 

Copy one header field from one request to another.

Definition at line 638 of file sip3_parse.c.

References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE.

00639 {
00640    const char *tmp = get_header(orig, field);
00641 
00642    if (!ast_strlen_zero(tmp)) /* Add what we're responding to */
00643       return add_header(req, field, tmp);
00644    ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field);
00645    return -1;
00646 }

GNURK void copy_request struct sip_request dst,
const struct sip_request src
 

copy SIP request (mostly used to save request for responses)

Definition at line 238 of file sip3_parse.c.

References ast_calloc, ast_log(), free, LOG_DEBUG, offset, and option_debug.

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 }

GNURK int copy_via_headers struct sip_dialog p,
struct sip_request req,
struct sip_request orig,
const char *  field
 

Copy SIP VIA Headers from the request to the response.

Note:
If the client indicates that it wishes to know the port we received from, it adds ;rport without an argument to the topmost via header. We need to add the port number (from our point of view) to that parameter. We always add ;received=<ip address>=""> to the topmost via header. Received: RFC 3261, rport RFC 3581

Definition at line 677 of file sip3_parse.c.

References __get_header(), add_header(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, sip_dialog::flags, sip_dialog::recv, SIP_NAT, SIP_NAT_ALWAYS, and SIP_NAT_RFC3581.

00678 {
00679    int copied = 0;
00680    int start = 0;
00681 
00682    for (;;) {
00683       char new[256];
00684       const char *oh = __get_header(orig, field, &start);
00685 
00686       if (ast_strlen_zero(oh))
00687          break;
00688 
00689       if (!copied) { /* Only check for empty rport in topmost via header */
00690          char leftmost[256], *others, *rport;
00691 
00692          /* Only work on leftmost value */
00693          ast_copy_string(leftmost, oh, sizeof(leftmost));
00694          others = strchr(leftmost, ',');
00695          if (others)
00696             *others++ = '\0';
00697 
00698          /* Find ;rport;  (empty request) */
00699          rport = strstr(leftmost, ";rport");
00700          if (rport && *(rport+6) == '=') 
00701             rport = NULL;     /* We already have a parameter to rport */
00702 
00703          if (rport && ( (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_ALWAYS) ||
00704             (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_RFC3581) ) ) {
00705             /* We need to add received port - rport */
00706             char *end;
00707 
00708             rport = strstr(leftmost, ";rport");
00709 
00710             if (rport) {
00711                end = strchr(rport + 1, ';');
00712                if (end)
00713                   memmove(rport, end, strlen(end) + 1);
00714                else
00715                   *rport = '\0';
00716             }
00717 
00718             /* Add rport to first VIA header if requested */
00719             /* Whoo hoo!  Now we can indicate port address translation too!  Just
00720                another RFC (RFC3581). I'll leave the original comments in for
00721                posterity.  */
00722             snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s",
00723                leftmost, ast_inet_ntoa(p->recv.sin_addr),
00724                ntohs(p->recv.sin_port),
00725                others ? "," : "", others ? others : "");
00726                         } else {
00727                                 /* We should *always* add a received to the topmost via */
00728             snprintf(new, sizeof(new), "%s;received=%s%s%s",
00729                leftmost, ast_inet_ntoa(p->recv.sin_addr),
00730                others ? "," : "", others ? others : "");
00731 
00732          }
00733          oh = new;   /* the header to copy */
00734       }  /* else add the following via headers untouched */
00735       add_header(req, field, oh);
00736       copied++;
00737    }
00738    if (!copied) {
00739       ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field);
00740       return -1;
00741    }
00742    return 0;
00743 }

GNURK int create_addr struct sip_dialog dialog,
const char *  username,
char *  domain,
const char *  device
 

create address structure from peer name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success

Definition at line 808 of file chan_sip3.c.

References ahp, ast_get_srv(), ast_gethostbyname(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_verbose(), create_addr_from_peer(), device_unref(), FALSE, find_device(), global, hp, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, sip_dialog::recv, sip_dialog::sa, sip_globals::srvlookup, STANDARD_SIP_PORT, sip_globals::t1default, sip_dialog::timer_t1, and TRUE.

00809 {
00810    struct hostent *hp;
00811    struct ast_hostent ahp;
00812    struct sip_device *p = NULL;
00813    char *port;
00814    int portno;
00815    char host[MAXHOSTNAMELEN], *hostn;
00816    char peername[256];
00817    char todomain[256];
00818    int srvcheck = TRUE;
00819 
00820 
00821    dialog->sa.sin_family = AF_INET;
00822    dialog->timer_t1 = global.t1default; /* Default SIP retransmission timer T1 (RFC 3261) */
00823    if (!ast_strlen_zero(device)) {
00824       int res;
00825 
00826       p = find_device(device, NULL, 1);
00827 
00828       if (p)  {
00829          res = create_addr_from_peer(dialog, p);
00830          device_unref(p);
00831          return res;
00832       } else {
00833          if (option_verbose > 1)
00834             ast_verbose("Can't find peer %s\n", device);
00835 
00836          return -1;  /* Can't find peer */
00837       }
00838    }
00839 
00840    /* See if we have a port. If we have a given port,
00841       disable SRV lookups */
00842    if (!ast_strlen_zero(domain)) {
00843       ast_copy_string(todomain, domain, sizeof(todomain));
00844       port = strchr(todomain, ':');
00845    }
00846    if (port) {
00847       *port++ = '\0';
00848       srvcheck = FALSE;
00849    }
00850 
00851    hostn = domain;
00852    portno = port ? atoi(port) : STANDARD_SIP_PORT;
00853 
00854    if (global.srvlookup && srvcheck) {
00855       char service[MAXHOSTNAMELEN];
00856       int tportno;
00857       int ret;
00858 
00859       snprintf(service, sizeof(service), "_sip._udp.%s", domain);
00860       ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service);
00861       if (ret > 0) {
00862          hostn = host;
00863          portno = tportno;
00864          if (option_debug > 2)
00865             ast_log(LOG_DEBUG, "Resolved domain %s to host %s in SRV \n", domain, hostn);
00866       }
00867    } 
00868    hp = ast_gethostbyname(hostn, &ahp);
00869    if (!hp) {
00870       ast_log(LOG_WARNING, "No such host: %s\n", peername);
00871       return -2;
00872    }
00873    ast_string_field_set(dialog, tohost, domain);
00874    memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
00875    dialog->sa.sin_port = htons(portno);
00876    dialog->recv = dialog->sa;
00877    return 0;
00878 }

GNURK void destroy_association struct sip_device peer  ) 
 

Remove registration data from realtime database or AST/DB when registration expires.

Definition at line 380 of file sip3_objects.c.

References ast_db_del(), ast_test_flag, ast_update_realtime(), sip_device::flags, sip_globals::flags, global, SIP_PAGE2_IGNOREREGEXPIRE, and SIP_PAGE2_RT_FROMCONTACT.

00381 {
00382    if (!ast_test_flag(&global.flags[1], SIP_PAGE2_IGNOREREGEXPIRE)) {
00383       if (ast_test_flag(&device->flags[1], SIP_PAGE2_RT_FROMCONTACT))
00384          ast_update_realtime("sippeers", "name", device->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "defaultuser", "", "regserver", "", NULL);
00385       else 
00386          ast_db_del("SIP3-Registry", device->name);
00387    }
00388 }

GNURK int determine_firstline_parts struct sip_request req  ) 
 

Parse first line of incoming SIP request.

Definition at line 865 of file sip3_parse.c.

References ast_log(), sip_request::header, LOG_WARNING, sip_request::rlPart1, and sip_request::rlPart2.

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 }

GNURK struct sip_device* device_ref struct sip_device device  ) 
 

Add reference for device.

Definition at line 436 of file sip3_config.c.

References ast_log(), ASTOBJ_REF, LOG_DEBUG, option_debug, and sipdebug.

00437 {
00438    ASTOBJ_REF(device);
00439    if (option_debug > 3 && sipdebug)
00440       ast_log(LOG_DEBUG, "/// Adding reference to device %s - refcount now %d\n", device->name, device->refcount);
00441    return device;
00442 }

GNURK int device_status struct sip_device device,
char *  status,
int  statuslen
 

Report Device status in character string.

Returns:
0 if peer is unreachable, 1 if peer is online, -1 if unmonitored

Definition at line 183 of file sip3_cliami.c.

References sip_device::lastms, and sip_device::maxms.

Referenced by _sip_show_device(), _sip_show_devices(), and function_sippeer().

00184 {
00185    int res = 0;
00186    if (device->maxms) {
00187       if (device->lastms < 0) {
00188          ast_copy_string(status, "UNREACHABLE", statuslen);
00189       } else if (device->lastms > device->maxms) {
00190          snprintf(status, statuslen, "LAGGED (%d ms)", device->lastms);
00191          res = 1;
00192       } else if (device->lastms) {
00193          snprintf(status, statuslen, "OK (%d ms)", device->lastms);
00194          res = 1;
00195       } else {
00196          ast_copy_string(status, "UNKNOWN", statuslen);
00197       }
00198    } else { 
00199       ast_copy_string(status, "Unmonitored", statuslen);
00200       /* Checking if port is 0 */
00201       res = -1;
00202    }
00203    return res;
00204 }

GNURK void device_unref struct sip_device device  ) 
 

Remove reference for device. When we reach 0, device is removed from memory.

Definition at line 425 of file sip3_config.c.

References ast_log(), ASTOBJ_UNREF, LOG_DEBUG, option_debug, sip_destroy_device(), and sipdebug.

Referenced by __sip_autodestruct(), _sip_show_device(), check_user_full(), create_addr(), expire_register(), function_sippeer(), handle_request_subscribe(), register_verify(), sip_devicestate(), sip_do_debug_device(), and update_call_counter().

00426 {
00427    if (!device)
00428       return;
00429 
00430    if (option_debug > 3 && sipdebug)
00431       ast_log(LOG_DEBUG, "/// Removing reference from device %s - refcount now %d\n", device->name, device->refcount - 1);
00432    ASTOBJ_UNREF(device, sip_destroy_device);
00433 }

GNURK void dialog_lock struct sip_dialog dialog,
int  state
 

Helper function to lock and unlock, hiding the underlying locking mechanism.

Parameters:
state TRUE for lock, FALSE for unlock

Definition at line 146 of file sip3_dialog.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), sip_dialog::lock, LOG_DEBUG, LOG_ERROR, option_debug, and sipdebug.

Referenced by __sip_ack(), auto_congest(), check_rtp_timeout(), get_sip_dialog_byid_locked(), handle_invite_replaces(), handle_request_invite(), handle_request_subscribe(), handle_response_answer(), local_attended_transfer(), process_sip_queue(), retrans_pkt(), sip_answer(), sip_dtmfmode(), sip_fixup(), sip_get_rtp_peer(), sip_get_udptl_peer(), sip_handle_t38_reinvite(), sip_hangup(), sip_indicate(), sip_new(), sip_read(), sip_senddigit_begin(), sip_senddigit_end(), sip_set_rtp_peer(), sip_transfer(), sip_write(), and write_media_frame().

00147 {
00148    if (!dialog) {
00149       ast_log(LOG_ERROR, "-DIALOGLOCK- Trying to %s non-existing dialog. Giving up.\n", state ? "lock" : "unlock");
00150       return;
00151    }
00152    if (sipdebug && option_debug > 4)
00153       ast_log(LOG_DEBUG, "-DIALOGLOCK- %s dialog %s\n", state ? "  locking" : "unlocking", dialog->callid ? dialog->callid : "<no callid>");
00154 
00155    if (state)
00156       ast_mutex_lock(&dialog->lock);
00157    else
00158       ast_mutex_unlock(&dialog->lock);
00159 }

GNURK void dialoglist_lock void   ) 
 

Lock list of active SIP dialogs.

Definition at line 122 of file sip3_dialog.c.

References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), LOG_DEBUG, option_debug, and sipdebug.

00123 {
00124    int counter = 0;
00125    while (ast_mutex_trylock(&dialoglock) && counter < 100) {
00126       if (option_debug > 4)
00127          ast_log(LOG_DEBUG, "---Trying to lock dialoglist -- %d \n", ++counter);
00128    } 
00129    if (counter == 100)
00130       ast_mutex_lock(&dialoglock);
00131    if (sipdebug && option_debug > 4)
00132       ast_log(LOG_DEBUG, "=== SIP dialog list: LOCKED\n");
00133 }

GNURK void dialoglist_unlock void   ) 
 

Unlock list of active SIP dialogs.

Definition at line 136 of file sip3_dialog.c.

References ast_log(), ast_mutex_unlock(), LOG_DEBUG, option_debug, and sipdebug.

00137 {
00138    ast_mutex_unlock(&dialoglock);
00139    if (sipdebug && option_debug > 4)
00140       ast_log(LOG_DEBUG, "=== SIP dialog list: UNLOCKED\n");
00141 }

GNURK const char* dialogstate2str const enum dialogstate  state  ) 
 

Convert SIP dialog states to string.

Definition at line 162 of file sip3_dialog.c.

References DIALOG_STATE_CONFIRMED, DIALOG_STATE_CONFIRMED_HOLD, DIALOG_STATE_EARLY, DIALOG_STATE_PROCEEDING, DIALOG_STATE_TERMINATED, DIALOG_STATE_TERMINATED_AUTH, and DIALOG_STATE_TRYING.

Referenced by dialogstatechange(), sip_hangup(), and sip_show_channel().

00163 {
00164    const char *reply = "<unknown>";
00165    switch (state) {
00166    case DIALOG_STATE_TRYING:
00167       reply = "Trying";
00168       break;
00169    case DIALOG_STATE_PROCEEDING:
00170       reply = "Proceeding";
00171       break;
00172    case DIALOG_STATE_EARLY:
00173       reply = "Early";
00174       break;
00175    case DIALOG_STATE_CONFIRMED:
00176       reply = "Confirmed";
00177       break;
00178    case DIALOG_STATE_CONFIRMED_HOLD:
00179       reply = "Confirmed, on hold";
00180       break;
00181    case DIALOG_STATE_TERMINATED:
00182       reply = "Terminated";
00183       break;
00184    case DIALOG_STATE_TERMINATED_AUTH:
00185       reply = "Terminated, auth";
00186       break;
00187    }
00188    return reply;
00189 }

GNURK void dialogstatechange struct sip_dialog dialog,
enum dialogstate  newstate
 

Change dialog state for a SIP dialog and output to debug.

Definition at line 192 of file sip3_dialog.c.

References append_history, ast_log(), dialogstate2str(), global, sip_dialog::icseq, LOG_DEBUG, sip_dialog::ocseq, option_debug, sip_globals::recordhistory, sipdebug, and sip_dialog::state.

Referenced by handle_request(), handle_request_info(), handle_request_invite(), handle_request_subscribe(), handle_response_invite(), handle_response_notify(), handle_response_peerpoke(), sip_alloc(), sip_answer(), sip_hangup(), sip_indicate(), and transmit_final_response().

00193 {
00194    if (dialog->state == newstate) {
00195       if (option_debug > 3)
00196          ast_log(LOG_DEBUG, "Asked to change state to dialog that already has requested state: %s State %s\n", dialog->callid, dialogstate2str(newstate));
00197    } else {
00198       dialog->state = newstate;
00199       if (sipdebug && option_debug > 1)
00200          ast_log(LOG_DEBUG, "-- Dialog %s changed state to %s\n", dialog->callid, dialogstate2str(newstate));
00201       if (global.recordhistory)
00202          append_history(dialog, "DialogState", "New state: %s O-Cseq %d I-Cseq %d", dialogstate2str(newstate), dialog->ocseq, dialog->icseq);
00203    }
00204    /* When state is terminated, keep it for 32 secs to allow for retransmits 
00205     */
00206 }

GNURK int do_proxy_auth struct sip_dialog p,
struct sip_request req,
enum sip_auth_type  code,
int  sipmethod,
int  init
 

Add authentication on outbound SIP packet.

Definition at line 327 of file sip3_auth.c.

References ast_calloc, ast_log(), sip_invite_param::auth, auth_headers(), sip_invite_param::authheader, sip_dialog::authtries, sip_dialog::inviteoptions, LOG_DEBUG, option_debug, reply_digest(), SIP_INVITE, sip_method2txt(), and transmit_invite().

00328 {
00329    char *header, *respheader;
00330    char digest[1024];
00331 
00332    if (!p->inviteoptions && !(p->inviteoptions = ast_calloc(1, sizeof(*p->inviteoptions))))
00333       return -2;
00334 
00335    p->authtries++;
00336    auth_headers(code, &header, &respheader);
00337    if (option_debug > 1)
00338       ast_log(LOG_DEBUG, "Auth attempt %d on %s\n", p->authtries, sip_method2txt(sipmethod));
00339    memset(digest, 0, sizeof(digest));
00340    if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) {
00341       /* No way to authenticate */
00342       return -1;
00343    }
00344    /* Now we have a reply digest */
00345    p->inviteoptions->auth = digest;
00346    p->inviteoptions->authheader = respheader;
00347    return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init); 
00348 }

GNURK int do_register_auth struct sip_dialog p,
struct sip_request req,
enum sip_auth_type  code
 

Authenticate for outbound registration.

Definition at line 303 of file sip3_auth.c.

References append_history, ast_test_flag, ast_verbose(), auth_headers(), sip_dialog::authtries, sip_dialog::flags, reply_digest(), sip_debug_test_pvt(), SIP_NO_HISTORY, SIP_REGISTER, and transmit_register().

00304 {
00305    char *header, *respheader;
00306    char digest[1024];
00307 
00308    p->authtries++;
00309    auth_headers(code, &header, &respheader);
00310    memset(digest,0,sizeof(digest));
00311    if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) {
00312       /* There's nothing to use for authentication */
00313       /* No digest challenge in request */
00314       if (sip_debug_test_pvt(p) && p->registry)
00315          ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname);
00316          /* No old challenge */
00317       return -1;
00318    }
00319    if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
00320       append_history(p, "RegistryAuth", "Try: %d", p->authtries);
00321    if (sip_debug_test_pvt(p) && p->registry)
00322       ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname);
00323    return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 
00324 }

GNURK void do_setnat struct sip_dialog p,
int  natflags
 

Set nat mode on the various media streams.

Definition at line 668 of file chan_sip3.c.

References ast_log(), ast_rtp_setnat(), ast_udptl_setnat(), LOG_DEBUG, option_debug, sip_dialog::rtp, sip_dialog::udptl, and sip_dialog::vrtp.

00669 {
00670    const char *mode = natflags ? "On" : "Off";
00671 
00672    if (dialog->rtp) {
00673       if (option_debug)
00674          ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", mode);
00675       ast_rtp_setnat(dialog->rtp, natflags);
00676    }
00677    if (dialog->vrtp) {
00678       if (option_debug)
00679          ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", mode);
00680       ast_rtp_setnat(dialog->vrtp, natflags);
00681    }
00682    if (dialog->udptl) {
00683       if (option_debug)
00684          ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
00685       ast_udptl_setnat(dialog->udptl, natflags);
00686    }
00687 }

void* do_sip_monitor void *  data  ) 
 

The SIP monitoring thread.

Note:
This thread monitors all the SIP sessions and peers that needs notification of mwi (and thus do not have a separate thread) indefinitely

Definition at line 249 of file sip3_monitor.c.

References ast_io_add(), ast_io_change(), AST_IO_IN, ast_verbose(), FALSE, io, option_verbose, sip_network::read_id, sip_do_reload(), sip_reload_check(), sipnet, sip_network::sipsock, sipsock_read(), sipsocket_initialized(), and VERBOSE_PREFIX_1.

Referenced by restart_monitor().

00250 {
00251    int res;
00252    struct sip_dialog *sip;
00253    struct sip_device *device = NULL;
00254    time_t now;
00255    int fastrestart = FALSE;
00256    int lastpeernum = -1;
00257    int curpeernum;
00258    static int nowalkmessage = 0;
00259 
00260    /* Add an I/O event to our SIP UDP socket */
00261    if (sipsocket_initialized(&sipnet))
00262       sipnet.read_id = ast_io_add(io, sipnet.sipsock, sipsock_read, AST_IO_IN, NULL);
00263    
00264    /* From here on out, we die whenever asked */
00265    for(;;) {
00266       /*------  Check for a reload request */
00267       if (sip_reload_check()) {
00268          if (option_verbose > 0)
00269             ast_verbose(VERBOSE_PREFIX_1 "Reloading SIP\n");
00270          sip_do_reload();
00271 
00272          /* Change the I/O fd of our UDP socket */
00273          if (sipsocket_initialized(&sipnet))
00274             sipnet.read_id = ast_io_change(io, sipnet.read_id, sipnet.sipsock, NULL, 0, NULL);
00275       }
00276 
00277       /*----- Check for interfaces needing to be killed */
00278       if (dialoglist != NULL && !fastrestart) {
00279          struct sip_dialog *nextdialog;
00280 
00281          if (option_debug > 4)
00282             ast_log(LOG_DEBUG, ":: MONITOR :: Walking dialog list.\n");
00283          dialoglist_lock();
00284 restartsearch:    
00285          now = time(NULL);
00286          /* don't scan the interface list if it hasn't been a reasonable period
00287             of time since the last time we did it (when MWI is being sent, we can
00288             get back to this point every millisecond or less)
00289          */
00290          for (sip = dialoglist;  sip; sip = nextdialog) {
00291             nextdialog = sip->next;
00292             /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP or RTCP */
00293             check_rtp_timeout(sip, now);
00294 
00295             /* If we have sessions that needs to be destroyed, do it now */
00296             if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets && !sip->owner) {
00297                __sip_destroy(sip, TRUE, FALSE);
00298                //goto restartsearch;
00299             }
00300          }
00301          dialoglist_unlock();
00302          nowalkmessage = 0;
00303       } else if (!fastrestart && sipdebug && option_debug > 4) {
00304          if (!nowalkmessage)
00305             ast_log(LOG_DEBUG, ":: MONITOR :: Empty dialog list. Pausing channel walks\n");
00306          nowalkmessage = 1;
00307       }
00308 
00309       pthread_testcancel();
00310 
00311       /*------ Wait for sched or io */
00312       res = ast_sched_wait(sched);
00313 
00314       if ((res < 0) || (res > 1000))
00315          res = 1000;
00316       /* If we might need to send more mailboxes, don't wait long at all.*/
00317       if (fastrestart)
00318          res = 1;
00319 
00320       res = ast_io_wait(io, res);
00321       if (option_debug && res > 20)
00322          ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res);
00323       ast_mutex_lock(&monlock);
00324       if (res >= 0)  {
00325          res = ast_sched_runq(sched);  /* Check for scheduled items, like retransmits */
00326          if (option_debug && res >= 20)
00327             ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res);
00328       }
00329 
00330       /*----- Send MWI notifications to devices - static and cached realtime peers */
00331       if (sipcounters.peers_with_mwi > 0 ) {
00332          fastrestart = FALSE;
00333          curpeernum = 0;
00334          device= NULL;
00335          /* Find next device that needs mwi */
00336          ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !device, do {
00337             if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
00338                fastrestart = TRUE;
00339                lastpeernum = curpeernum;
00340                device = device_ref(iterator);
00341             };
00342             curpeernum++;
00343          } while (0)
00344          );
00345          /* Send MWI to the peer */
00346          if (device) {
00347             ASTOBJ_WRLOCK(device);
00348             sip_send_mwi_to_peer(device);
00349             ASTOBJ_UNLOCK(device);
00350             device_unref(device);
00351          } else {
00352             /* Reset where we come from */
00353             lastpeernum = -1;
00354          }
00355       }
00356       ast_mutex_unlock(&monlock);
00357    }
00358    /* Never reached */
00359    return NULL;
00360    
00361 }

GNURK const char* domain_mode_to_text const enum domain_mode  mode  ) 
 

Print domain mode to cli.

Definition at line 191 of file sip3_domain.c.

References SIP_DOMAIN_AUTO, and SIP_DOMAIN_CONFIG.

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 }

GNURK int domains_configured void   ) 
 

return TRUE if any domains are configured for this server

Definition at line 125 of file sip3_domain.c.

References AST_LIST_EMPTY.

Referenced by get_destination(), handle_request_refer(), register_verify(), sip_show_domains(), and sip_show_settings().

00126 {
00127    return (!AST_LIST_EMPTY(&domain_list));
00128 }

GNURK int expire_register void *  data  ) 
 

Expire registration of SIP peer.

Definition at line 391 of file sip3_objects.c.

References sip_device::addr, ast_device_state_changed(), ast_test_flag, ASTOBJ_CONTAINER_UNLINK, destroy_association(), device_unref(), devicelist, EVENT_FLAG_SYSTEM, sip_device::expire, FALSE, sip_device::flags, manager_event, register_peer_exten(), SIP_PAGE2_RTAUTOCLEAR, and SIP_PAGE2_SELFDESTRUCT.

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 }

GNURK void extract_uri struct sip_dialog p,
struct sip_request req
 

Check Contact: URI of SIP message.

Definition at line 906 of file sip3_parse.c.

References ast_string_field_set, ast_strlen_zero(), get_header(), get_in_brackets(), and strsep().

00907 {
00908    char stripped[256];
00909    char *c;
00910 
00911    ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped));
00912    c = get_in_brackets(stripped);
00913    c = strsep(&c, ";"); /* trim ; and beyond */
00914    if (!ast_strlen_zero(c))
00915       ast_string_field_set(p, uri, c);
00916 }

GNURK const char* find_alias const char *  name,
const char *  _default
 

Find compressed SIP alias Structure for conversion between compressed SIP and "normal" SIP.

Definition at line 320 of file sip3_parse.c.

References aliases.

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 }

GNURK struct sip_device* find_device const char *  peer,
struct sockaddr_in *  sin,
int  realtime
 

Locate peer by name or ip address This is used on incoming SIP message to find matching peer on ip or outgoing message to find matching peer on name.

sip3_objects.c

Definition at line 242 of file sip3_objects.c.

References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, devicelist, name, realtime_peer(), and sip_addrcmp().

Referenced by _sip_show_device(), check_user_full(), create_addr(), function_sippeer(), register_verify(), sip_devicestate(), sip_do_debug_device(), sip_peer_hold(), and update_call_counter().

00243 {
00244    struct sip_device *peer = NULL;
00245 
00246    if (device)
00247       peer = ASTOBJ_CONTAINER_FIND(&devicelist, device);
00248    else
00249       peer = ASTOBJ_CONTAINER_FIND_FULL(&devicelist, sin, name, sip_addr_hashfunc, 1, sip_addrcmp);
00250 
00251    if (!peer && realtime)
00252       peer = realtime_peer(device, sin);
00253 
00254    return peer;
00255 }

GNURK struct sip_auth* find_realm_authentication struct sip_auth authlist,
const char *  realm
 

Find authentication for a specific realm.

Definition at line 569 of file sip3_auth.c.

References sip_auth::next, and sip_auth::realm.

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 }

GNURK int find_sdp struct sip_request req  ) 
 

Determine whether a SIP message contains an SDP in its body.

Parameters:
req the SIP request to process
Returns:
TRUE if SDP found, FALSE if not found
Also updates req->sdp_start and req->sdp_end to indicate where the SDP lives in the message body.

Definition at line 880 of file sip3_sdprtp.c.

References ast_strdupa, ast_strlen_zero(), FALSE, get_header(), sip_request::line, sip_request::lines, sip_request::sdp_end, sip_request::sdp_start, strcasestr(), and TRUE.

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 }

GNURK int find_sip_method const char *  msg  ) 
 

find_sip_method: Find SIP method from header

Definition at line 163 of file sip3_parse.c.

References ast_strlen_zero(), method_match(), and sip_methods.

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 }

GNURK const struct cfsubscription_types* find_subscription_type enum subscriptiontype  subtype  ) 
 

Find subscription type in array.

Definition at line 119 of file sip3_subscribe.c.

References subscription_types, and type.

00120 {
00121    int i;
00122 
00123    for (i = 1; (i < (sizeof(subscription_types) / sizeof(subscription_types[0]))); i++) {
00124       if (subscription_types[i].type == subtype) {
00125          return &subscription_types[i];
00126       }
00127    }
00128    return &subscription_types[0];
00129 }

GNURK void find_via_branch struct sip_request req,
char *  viabuf,
size_t  vialen
 

Find via branch parameter.

Definition at line 1196 of file sip3_dialog.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, LOG_DEBUG, option_debug, SIP_PKT_DEBUG, strcasestr(), and sip_request::via.

Referenced by match_or_create_dialog().

01197 {
01198    char *dupvia;
01199    char *viabranch;
01200    char *sep;
01201 
01202    if (ast_strlen_zero(req->via))
01203       return;
01204    dupvia = ast_strdupa(req->via);
01205    if (!(viabranch = strcasestr(dupvia, ";branch=")))
01206       return;
01207    viabranch += 8;
01208    if ((sep = strchr(viabranch, ';')))
01209       *sep = '\0';
01210    if (ast_test_flag(req, SIP_PKT