📄 chan_sip.c
字号:
/*! \brief Structure for SIP peer data, we place calls to peers if registered or fixed IP address (host) *//* XXX field 'name' must be first otherwise sip_addrcmp() will fail */struct sip_peer { ASTOBJ_COMPONENTS(struct sip_peer); /*!< name, refcount, objflags, object pointers */ /*!< peer->name is the unique name of this object */ char secret[80]; /*!< Password */ char md5secret[80]; /*!< Password in MD5 */ struct sip_auth *auth; /*!< Realm authentication list */ char context[AST_MAX_CONTEXT]; /*!< Default context for incoming calls */ char subscribecontext[AST_MAX_CONTEXT]; /*!< Default context for subscriptions */ char username[80]; /*!< Temporary username until registration */ char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */ int amaflags; /*!< AMA Flags (for billing) */ char tohost[MAXHOSTNAMELEN]; /*!< If not dynamic, IP address */ char regexten[AST_MAX_EXTENSION]; /*!< Extension to register (if regcontext is used) */ char fromuser[80]; /*!< From: user when calling this peer */ char fromdomain[MAXHOSTNAMELEN]; /*!< From: domain when calling this peer */ char fullcontact[256]; /*!< Contact registered with us (not in sip.conf) */ char cid_num[80]; /*!< Caller ID num */ char cid_name[80]; /*!< Caller ID name */ int callingpres; /*!< Calling id presentation */ int inUse; /*!< Number of calls in use */ int inRinging; /*!< Number of calls ringing */ int onHold; /*!< Peer has someone on hold */ int call_limit; /*!< Limit of concurrent calls */ enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */ char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/ char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */ char language[MAX_LANGUAGE]; /*!< Default language for prompts */ char mohinterpret[MAX_MUSICCLASS];/*!< Music on Hold class */ char mohsuggest[MAX_MUSICCLASS];/*!< Music on Hold class */ char useragent[256]; /*!< User agent in SIP request (saved from registration) */ struct ast_codec_pref prefs; /*!< codec prefs */ int lastmsgssent; time_t lastmsgcheck; /*!< Last time we checked for MWI */ unsigned int sipoptions; /*!< Supported SIP options */ struct ast_flags flags[2]; /*!< SIP_ flags */ int expire; /*!< When to expire this peer registration */ int capability; /*!< Codec capability */ int rtptimeout; /*!< RTP timeout */ int rtpholdtimeout; /*!< RTP Hold Timeout */ int rtpkeepalive; /*!< Send RTP packets for keepalive */ ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ struct sockaddr_in addr; /*!< IP address of peer */ int maxcallbitrate; /*!< Maximum Bitrate for a video call */ /* Qualification */ struct sip_pvt *call; /*!< Call pointer */ int pokeexpire; /*!< When to expire poke (qualify= checking) */ int lastms; /*!< How long last response took (in ms), or -1 for no response */ int maxms; /*!< Max ms we will accept for the host to be up, 0 to not monitor */ struct timeval ps; /*!< Ping send time */ struct sockaddr_in defaddr; /*!< Default IP address, used until registration */ struct ast_ha *ha; /*!< Access control list */ struct ast_variable *chanvars; /*!< Variables to set for channel created by user */ struct sip_pvt *mwipvt; /*!< Subscription for MWI */ int lastmsg; int autoframing;};/*! \brief Registrations with other SIP proxies */struct sip_registry { ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1); AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(callid); /*!< Global Call-ID */ AST_STRING_FIELD(realm); /*!< Authorization realm */ AST_STRING_FIELD(nonce); /*!< Authorization nonce */ AST_STRING_FIELD(opaque); /*!< Opaque nonsense */ AST_STRING_FIELD(qop); /*!< Quality of Protection, since SIP wasn't complicated enough yet. */ AST_STRING_FIELD(domain); /*!< Authorization domain */ AST_STRING_FIELD(username); /*!< Who we are registering as */ AST_STRING_FIELD(authuser); /*!< Who we *authenticate* as */ AST_STRING_FIELD(hostname); /*!< Domain or host we register to */ AST_STRING_FIELD(secret); /*!< Password in clear text */ AST_STRING_FIELD(md5secret); /*!< Password in md5 */ AST_STRING_FIELD(contact); /*!< Contact extension */ AST_STRING_FIELD(random); ); int portno; /*!< Optional port override */ int expire; /*!< Sched ID of expiration */ int regattempts; /*!< Number of attempts (since the last success) */ int timeout; /*!< sched id of sip_reg_timeout */ int refresh; /*!< How often to refresh */ struct sip_pvt *call; /*!< create a sip_pvt structure for each outbound "registration dialog" in progress */ enum sipregistrystate regstate; /*!< Registration state (see above) */ time_t regtime; /*!< Last succesful registration time */ int callid_valid; /*!< 0 means we haven't chosen callid for this registry yet. */ unsigned int ocseq; /*!< Sequence number we got to for REGISTERs for this registry */ struct sockaddr_in us; /*!< Who the server thinks we are */ int noncecount; /*!< Nonce-count */ char lastmsg[256]; /*!< Last Message sent/received */};/* --- Linked lists of various objects --------*//*! \brief The user list: Users and friends */static struct ast_user_list { ASTOBJ_CONTAINER_COMPONENTS(struct sip_user);} userl;/*! \brief The peer list: Peers and Friends */static struct ast_peer_list { ASTOBJ_CONTAINER_COMPONENTS(struct sip_peer);} peerl;/*! \brief The register list: Other SIP proxys we register with and place calls to */static struct ast_register_list { ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry); int recheck;} regl;static void temp_pvt_cleanup(void *);/*! \brief A per-thread temporary pvt structure */AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);#ifdef LOW_MEMORYstatic void ts_ast_rtp_destroy(void *);AST_THREADSTORAGE_CUSTOM(ts_audio_rtp, ts_audio_rtp_init, ts_ast_rtp_destroy);AST_THREADSTORAGE_CUSTOM(ts_video_rtp, ts_video_rtp_init, ts_ast_rtp_destroy);#endif/*! \todo Move the sip_auth list to AST_LIST */static struct sip_auth *authl = NULL; /*!< Authentication list for realm authentication *//* --- Sockets and networking --------------*/static int sipsock = -1; /*!< Main socket for SIP network communication */static struct sockaddr_in bindaddr = { 0, }; /*!< The address we bind to */static struct sockaddr_in externip; /*!< External IP address if we are behind NAT */static char externhost[MAXHOSTNAMELEN]; /*!< External host name (possibly with dynamic DNS and DHCP */static time_t externexpire = 0; /*!< Expiration counter for re-resolving external host name in dynamic DNS */static int externrefresh = 10;static struct ast_ha *localaddr; /*!< List of local networks, on the same side of NAT as this Asterisk */static struct in_addr __ourip;static struct sockaddr_in outboundproxyip;static int ourport;static struct sockaddr_in debugaddr;static struct ast_config *notify_types; /*!< The list of manual NOTIFY types we know how to send *//*---------------------------- Forward declarations of functions in chan_sip.c *//*! \note This is added to help splitting up chan_sip.c into several files in coming releases *//*--- PBX interface functions */static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);static int sip_devicestate(void *data);static int sip_sendtext(struct ast_channel *ast, const char *text);static int sip_call(struct ast_channel *ast, char *dest, int timeout);static int sip_hangup(struct ast_channel *ast);static int sip_answer(struct ast_channel *ast);static struct ast_frame *sip_read(struct ast_channel *ast);static int sip_write(struct ast_channel *ast, struct ast_frame *frame);static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);static int sip_transfer(struct ast_channel *ast, const char *dest);static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);static int sip_senddigit_begin(struct ast_channel *ast, char digit);static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);/*--- Transmitting responses and requests */static int sipsock_read(int *id, int fd, short events, void *ignore);static int __sip_xmit(struct sip_pvt *p, char *data, int len);static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len, int fatal, int sipmethod);static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);static int retrans_pkt(const void *data);static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req);static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable);static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);static int transmit_reinvite_with_sdp(struct sip_pvt *p);static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration);static int transmit_info_with_vidupdate(struct sip_pvt *p);static int transmit_message_with_text(struct sip_pvt *p, const char *text);static int transmit_refer(struct sip_pvt *p, const char *dest);static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, char *vmexten);static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader);static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);static void copy_request(struct sip_request *dst, const struct sip_request *src);static void receive_message(struct sip_pvt *p, struct sip_request *req);static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);static int sip_send_mwi_to_peer(struct sip_peer *peer);static int does_peer_need_mwi(struct sip_peer *peer);/*--- Dialog management */static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method);static int __sip_autodestruct(const void *data);static void sip_scheddestroy(struct sip_pvt *p, int ms);static int sip_cancel_destroy(struct sip_pvt *p);static void sip_destroy(struct sip_pvt *p);static int __sip_destroy(struct sip_pvt *p, int lockowner);static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);static void __sip_pretend_ack(struct sip_pvt *p);static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);static int auto_congest(const void *nothing);static int update_call_counter(struct sip_pvt *fup, int event);static int hangup_sip2cause(int cause);static const char *hangup_cause2sip(int cause);static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method);static void free_old_route(struct sip_route *route);static void list_route(struct sip_route *route);static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards);static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct sip_request *req, char *uri);static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);static void check_pendings(struct sip_pvt *p);static void *sip_park_thread(void *stuff);static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno);static int sip_sipredirect(struct sip_pvt *p, const char *dest);/*--- Codec handling / SDP */static void try_suggested_sip_codec(struct sip_pvt *p);static const char* get_sdp_iterate(int* start, struct sip_request *req, const char *name);static const char *get_sdp(struct sip_request *req, const char *name);static int find_sdp(struct sip_request *req);static int process_sdp(struct sip_pvt *p, struct sip_request *req);static void add_codec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug, int *min_packet_size);static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug);static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p);static void stop_media_flows(struct sip_pvt *p);/*--- Authentication stuff */static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len);static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len);static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *req, const char *username, const char *secret, const char *md5secret, int sipmethod, char *uri, enum xmittype reliable, int ignore);static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_peer **authpeer);static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin);/*--- Domain handling */static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */static int add_sip_domain(const char *domain, const enum domain_mode mode, const char *context);static void clear_sip_domains(void);/*--- SIP realm authentication */static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno);static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm);/*--- Misc functions */static int sip_do_reload(enum channelreloadreason reason);static int reload_config(enum channelreloadreason reason);static int expire_register(const void *data
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -