现在的位置: 首页 > 综合 > 正文

Asterisk 数据结构

2013年12月07日 ⁄ 综合 ⁄ 共 21950字 ⁄ 字号 评论关闭

CDR 模块

cdr模块是asterisk核心模块里面较为简单的一个模块 因此,数据结构也相对简单


链表,cdr主要的存储数据结构,用于存储通话记录字段
struct ast_cdr {
    /*! Caller*ID with text */
    char clid[AST_MAX_EXTENSION];
    /*! Caller*ID number */
    char src[AST_MAX_EXTENSION];
    /*! Destination extension */
    char dst[AST_MAX_EXTENSION];
    /*! Destination context */
    char dcontext[AST_MAX_EXTENSION];

    char channel[AST_MAX_EXTENSION];
    /*! Destination channel if appropriate */
    char dstchannel[AST_MAX_EXTENSION];
    /*! Last application if appropriate */
    char lastapp[AST_MAX_EXTENSION];
    /*! Last application data */
    char lastdata[AST_MAX_EXTENSION];

    struct timeval start;

    struct timeval answer;

    struct timeval end;
    /*! Total time in system, in seconds */
    long int duration;
    /*! Total time call is up, in seconds */
    long int billsec;
    /*! What happened to the call */
    long int disposition;
    /*! What flags to use */
    long int amaflags;
    /*! What account number to use */
    char accountcode[AST_MAX_ACCOUNT_CODE];
    /*! Account number of the last person we talked to */
    char peeraccount[AST_MAX_ACCOUNT_CODE];
    /*! flags */
    unsigned int flags;
    /*! Unique Channel Identifier
     * 150 = 127 (max systemname) + "-" + 10 (epoch timestamp) + "." + 10 (monotonically incrementing integer) + NULL */
    char uniqueid[150];
    /* Linked group Identifier */
    char linkedid[32];
    /*! User field */
    char userfield[AST_MAX_USER_FIELD];
    /*! Sequence field */
    int sequence;

    /*! A linked list for variables */
    struct varshead varshead;    //可扩展数据

    struct ast_cdr *next;
};


batch表头
static struct ast_cdr_batch {
    int size;
    struct ast_cdr_batch_item *head;
    struct ast_cdr_batch_item *tail;
} *batch = NULL;


cdr batch模式下链表结构,用于缓存cdr records
struct ast_cdr_batch_item {
	struct ast_cdr *cdr;
	struct ast_cdr_batch_item *next;
};

数据库回写函数结构,每个数据库模块在load_module()时,把对应的写数据库接口注册到这个结构中
struct ast_cdr_beitem {
    char name[20];
    char desc[80];
    ast_cdrbe be;
    AST_RWLIST_ENTRY(ast_cdr_beitem) list;
};


channel模块

struct ast_channel {
	const struct ast_channel_tech *tech;		/*!< Technology (point to channel driver) */
	void *tech_pvt;					/*!< Private data used by the technology driver */
	void *music_state;				/*!< Music State*/
	void *generatordata;				/*!< Current generator data if there is any */
	struct ast_generator *generator;		/*!< Current active data generator */
	struct ast_channel *_bridge;			/*!< Who are we bridged to, if we're bridged.
							 *   Who is proxying for us, if we are proxied (i.e. chan_agent).
							 *   Do not access directly, use ast_bridged_channel(chan) */
	struct ast_channel *masq;			/*!< Channel that will masquerade as us */
	struct ast_channel *masqr;			/*!< Who we are masquerading as */
	const char *blockproc;				/*!< Procedure causing blocking */
	const char *appl;				/*!< Current application */
	const char *data;				/*!< Data passed to current application */
	struct sched_context *sched;			/*!< Schedule context */
	struct ast_filestream *stream;			/*!< Stream itself. */
	struct ast_filestream *vstream;			/*!< Video Stream itself. */
	int (*timingfunc)(const void *data);
	void *timingdata;
	struct ast_pbx *pbx;				/*!< PBX private structure for this channel */
	struct ast_trans_pvt *writetrans;		/*!< Write translation path */
	struct ast_trans_pvt *readtrans;		/*!< Read translation path */
	struct ast_audiohook_list *audiohooks;
	struct ast_framehook_list *framehooks;
	struct ast_cdr *cdr;				/*!< Call Detail Record */
	struct ast_tone_zone *zone;			/*!< Tone zone as set in indications.conf or
							 *   in the CHANNEL dialplan function */
	struct ast_channel_monitor *monitor;		/*!< Channel monitoring */
#ifdef HAVE_EPOLL
	struct ast_epoll_data *epfd_data[AST_MAX_FDS];
#endif

	AST_DECLARE_STRING_FIELDS(
		AST_STRING_FIELD(name);			/*!< ASCII unique channel name */
		AST_STRING_FIELD(language);		/*!< Language requested for voice prompts */
		AST_STRING_FIELD(musicclass);		/*!< Default music class */
		AST_STRING_FIELD(accountcode);		/*!< Account code for billing */
		AST_STRING_FIELD(peeraccount);		/*!< Peer account code for billing */
		AST_STRING_FIELD(userfield);		/*!< Userfield for CEL billing */
		AST_STRING_FIELD(call_forward);		/*!< Where to forward to if asked to dial on this interface */
		AST_STRING_FIELD(uniqueid);		/*!< Unique Channel Identifier */
		AST_STRING_FIELD(linkedid);		/*!< Linked Channel Identifier -- gets propagated by linkage */
		AST_STRING_FIELD(parkinglot);		/*! Default parking lot, if empty, default parking lot  */
		AST_STRING_FIELD(hangupsource);		/*! Who is responsible for hanging up this channel */
		AST_STRING_FIELD(dialcontext);		/*!< Dial: Extension context that we were called from */
	);

	struct timeval whentohangup;        		/*!< Non-zero, set to actual time when channel is to be hung up */
	pthread_t blocker;				/*!< If anyone is blocking, this is them */

	/*!
	 * \brief Dialed/Called information.
	 * \note Set on incoming channels to indicate the originally dialed party.
	 * \note Dialed Number Identifier (DNID)
	 */
	struct ast_party_dialed dialed;

	/*!
	 * \brief Channel Caller ID information.
	 * \note The caller id information is the caller id of this
	 * channel when it is used to initiate a call.
	 */
	struct ast_party_caller caller;

	/*!
	 * \brief Channel Connected Line ID information.
	 * \note The connected line information identifies the channel
	 * connected/bridged to this channel.
	 */
	struct ast_party_connected_line connected;

	/*! \brief Redirecting/Diversion information */
	struct ast_party_redirecting redirecting;

	struct ast_frame dtmff;				/*!< DTMF frame */
	struct varshead varshead;			/*!< A linked list for channel variables. See \ref AstChanVar */
	ast_group_t callgroup;				/*!< Call group for call pickups */
	ast_group_t pickupgroup;			/*!< Pickup group - which calls groups can be picked up? */
	AST_LIST_HEAD_NOLOCK(, ast_frame) readq;
	struct ast_jb jb;				/*!< The jitterbuffer state */
	struct timeval dtmf_tv;				/*!< The time that an in process digit began, or the last digit ended */
	AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores; /*!< Data stores on the channel */
	AST_LIST_HEAD_NOLOCK(autochans, ast_autochan) autochans; /*!< Autochans on the channel */

	unsigned long insmpl;				/*!< Track the read/written samples for monitor use */
	unsigned long outsmpl;				/*!< Track the read/written samples for monitor use */

	int fds[AST_MAX_FDS];				/*!< File descriptors for channel -- Drivers will poll on
							 *   these file descriptors, so at least one must be non -1.
							 *   See \arg \ref AstFileDesc */
	int _softhangup;				/*!< Whether or not we have been hung up...  Do not set this value
							 *   directly, use ast_softhangup() */
	int fdno;					/*!< Which fd had an event detected on */
	int streamid;					/*!< For streaming playback, the schedule ID */
	int vstreamid;					/*!< For streaming video playback, the schedule ID */
	format_t oldwriteformat;		/*!< Original writer format */
	int timingfd;					/*!< Timing fd */
	enum ast_channel_state _state;			/*!< State of line -- Don't write directly, use ast_setstate() */
	int rings;					/*!< Number of rings so far */
	int priority;					/*!< Dialplan: Current extension priority */
	int macropriority;				/*!< Macro: Current non-macro priority. See app_macro.c */
	int amaflags;					/*!< Set BEFORE PBX is started to determine AMA flags */
	enum ast_channel_adsicpe adsicpe;		/*!< Whether or not ADSI is detected on CPE */
	unsigned int fin;				/*!< Frames in counters. The high bit is a debug mask, so
							 *   the counter is only in the remaining bits */
	unsigned int fout;				/*!< Frames out counters. The high bit is a debug mask, so
							 *   the counter is only in the remaining bits */
	int hangupcause;				/*!< Why is the channel hanged up. See causes.h */
	unsigned int flags;				/*!< channel flags of AST_FLAG_ type */
	int alertpipe[2];
	format_t nativeformats;         /*!< Kinds of data this channel can natively handle */
	format_t readformat;            /*!< Requested read format (after translation) */
	format_t writeformat;           /*!< Requested write format (after translation) */
	format_t rawreadformat;         /*!< Raw read format (before translation) */
	format_t rawwriteformat;        /*!< Raw write format (before translation) */
	unsigned int emulate_dtmf_duration;		/*!< Number of ms left to emulate DTMF for */
#ifdef HAVE_EPOLL
	int epfd;
#endif
	int visible_indication;                         /*!< Indication currently playing on the channel */

	unsigned short transfercapability;		/*!< ISDN Transfer Capability - AST_FLAG_DIGITAL is not enough */

	struct ast_bridge *bridge;                      /*!< Bridge this channel is participating in */
	struct ast_timer *timer;			/*!< timer object that provided timingfd */

	char context[AST_MAX_CONTEXT];			/*!< Dialplan: Current extension context */
	char exten[AST_MAX_EXTENSION];			/*!< Dialplan: Current extension number */
	char macrocontext[AST_MAX_CONTEXT];		/*!< Macro: Current non-macro context. See app_macro.c */
	char macroexten[AST_MAX_EXTENSION];		/*!< Macro: Current non-macro extension. See app_macro.c */
	char emulate_dtmf_digit;			/*!< Digit being emulated */
};

/*! \brief Structure used for each SIP dialog, ie. a call, a registration, a subscribe.
 * Created and initialized by sip_alloc(), the descriptor goes into the list of
 * descriptors (dialoglist).
 */
struct sip_pvt {
    struct sip_pvt *next;                   /*!< Next dialog in chain */
    enum invitestates invitestate;          /*!< Track state of SIP_INVITEs */
    int method;                             /*!< SIP method that opened this dialog */
    AST_DECLARE_STRING_FIELDS(
        AST_STRING_FIELD(callid);       /*!< Global CallID */
        AST_STRING_FIELD(initviabranch); /*!< The branch ID from the topmost Via header in the initial request */
        AST_STRING_FIELD(initviasentby); /*!< The sent-by from the topmost Via header in the initial request */
        AST_STRING_FIELD(randdata);     /*!< Random data */
        AST_STRING_FIELD(accountcode);  /*!< Account code */
        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(from);         /*!< The From: header */
        AST_STRING_FIELD(useragent);    /*!< User agent in SIP request */
        AST_STRING_FIELD(exten);        /*!< Extension where to start */
        AST_STRING_FIELD(context);      /*!< Context for this call */
        AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */
        AST_STRING_FIELD(subscribeuri); /*!< Subscribecontext */
        AST_STRING_FIELD(fromdomain);   /*!< Domain to show in the from field */
        AST_STRING_FIELD(fromuser);     /*!< User to show in the user field */
        AST_STRING_FIELD(fromname);     /*!< Name to show in the user field */
        AST_STRING_FIELD(tohost);       /*!< Host we should put in the "to" field */
        AST_STRING_FIELD(todnid);       /*!< DNID of this call (overrides host) */
        AST_STRING_FIELD(language);     /*!< Default language for this call */
        AST_STRING_FIELD(mohinterpret); /*!< MOH class to use when put on hold */
        AST_STRING_FIELD(mohsuggest);   /*!< MOH class to suggest when putting a peer on hold */
        AST_STRING_FIELD(rdnis);        /*!< Referring DNIS */
        AST_STRING_FIELD(redircause);   /*!< Referring cause */
        AST_STRING_FIELD(theirtag);     /*!< Their tag */
        AST_STRING_FIELD(username);     /*!< [user] name */
        AST_STRING_FIELD(peername);     /*!< [peer] name, not set if [user] */
        AST_STRING_FIELD(authname);     /*!< Who we use for authentication */
        AST_STRING_FIELD(uri);          /*!< Original requested URI */
        AST_STRING_FIELD(okcontacturi); /*!< URI from the 200 OK on INVITE */
        AST_STRING_FIELD(peersecret);   /*!< Password */
        AST_STRING_FIELD(peermd5secret);
        AST_STRING_FIELD(cid_num);      /*!< Caller*ID number */
        AST_STRING_FIELD(cid_name);     /*!< Caller*ID name */
        AST_STRING_FIELD(cid_tag);      /*!< Caller*ID tag */
        AST_STRING_FIELD(mwi_from);     /*!< Name to place in the From header in outgoing NOTIFY requests */
        AST_STRING_FIELD(fullcontact);  /*!< The Contact: that the UA registers with us */
                                        /* we only store the part in <brackets> in this field. */
        AST_STRING_FIELD(our_contact);  /*!< Our contact header */
        AST_STRING_FIELD(url);          /*!< URL to be sent with next message to peer */
        AST_STRING_FIELD(parkinglot);   /*!< Parkinglot */
        AST_STRING_FIELD(engine);       /*!< RTP engine to use */
        AST_STRING_FIELD(dialstring);   /*!< The dialstring used to call this SIP endpoint */
    );
    char via[128];                          /*!< Via: header */
    int maxforwards;                        /*!< SIP Loop prevention */
    struct sip_socket socket;               /*!< The socket used for this dialog */
    unsigned int ocseq;                     /*!< Current outgoing seqno */
    unsigned int icseq;                     /*!< Current incoming seqno */
    unsigned int init_icseq;                /*!< Initial incoming seqno from first request */
    ast_group_t callgroup;                  /*!< Call group */
    ast_group_t pickupgroup;                /*!< Pickup group */
    int lastinvite;                         /*!< Last Cseq of invite */
    struct ast_flags flags[3];              /*!< SIP_ flags */

    /* boolean flags that don't belong in flags */
    unsigned short do_history:1;          /*!< Set if we want to record history */
    unsigned short alreadygone:1;         /*!< the peer has sent a message indicating termination of the dialog */
    unsigned short needdestroy:1;         /*!< this dialog needs to be destroyed by the monitor thread */
    unsigned short final_destruction_scheduled:1; /*!< final dialog destruction is scheduled. Keep dialog
                                                   *   around until then to handle retransmits. */
    unsigned short outgoing_call:1;       /*!< this is an outgoing call */
    unsigned short answered_elsewhere:1;  /*!< This call is cancelled due to answer on another channel */
    unsigned short novideo:1;             /*!< Didn't get video in invite, don't offer */
    unsigned short notext:1;              /*!< Text not supported  (?) */
    unsigned short session_modify:1;      /*!< Session modification request true/false  */
    unsigned short route_persistent:1;    /*!< Is this the "real" route? */
    unsigned short autoframing:1;         /*!< Whether to use our local configuration for frame sizes (off)
                                           *   or respect the other endpoint's request for frame sizes (on)
                                           *   for incoming calls
                                           */
    unsigned short req_secure_signaling:1;/*!< Whether we are required to have secure signaling or not */
    char tag[11];                     /*!< Our tag for this session */
    int timer_t1;                     /*!< SIP timer T1, ms rtt */
    int timer_b;                      /*!< SIP timer B, ms */
    unsigned int sipoptions;          /*!< Supported SIP options on the other end */
    unsigned int reqsipoptions;       /*!< Required SIP options on the other end */
    struct ast_codec_pref prefs;      /*!< codec prefs */
    format_t capability;              /*!< Special capability (codec) */
    format_t jointcapability;         /*!< Supported capability at both ends (codecs) */
    format_t peercapability;          /*!< Supported peer capability */
    format_t prefcodec;               /*!< Preferred codec (outbound only) */
    int noncodeccapability;              /*!< DTMF RFC2833 telephony-event */
    int jointnoncodeccapability;      /*!< Joint Non codec capability */
    format_t redircodecs;             /*!< Redirect codecs */
    int maxcallbitrate;               /*!< Maximum Call Bitrate for Video Calls */    
    int t38_maxdatagram;              /*!< T.38 FaxMaxDatagram override */
    int request_queue_sched_id;       /*!< Scheduler ID of any scheduled action to process queued requests */
    int provisional_keepalive_sched_id;   /*!< Scheduler ID for provisional responses that need to be sent out to avoid cancellation */
    const char *last_provisional;         /*!< The last successfully transmitted provisonal response message */
    int authtries;                        /*!< Times we've tried to authenticate */
    struct sip_proxy *outboundproxy;      /*!< Outbound proxy for this dialog. Use ref_proxy to set this instead of setting it directly*/
    struct t38properties t38;             /*!< T38 settings */
    struct ast_sockaddr udptlredirip;     /*!< Where our T.38 UDPTL should be going if not to us */
    struct ast_udptl *udptl;              /*!< T.38 UDPTL session */
    int callingpres;                      /*!< Calling presentation */
    int expiry;                         /*!< How long we take to expire */
    int sessionversion;                 /*!< SDP Session Version */
    int sessionid;                      /*!< SDP Session ID */
    long branch;                        /*!< The branch identifier of this session */
    long invite_branch;                 /*!< The branch used when we sent the initial INVITE */
    int64_t sessionversion_remote;      /*!< Remote UA's SDP Session Version */
    unsigned int portinuri:1;           /*!< Non zero if a port has been specified, will also disable srv lookups */
    struct ast_sockaddr sa;              /*!< Our peer */
    struct ast_sockaddr redirip;         /*!< Where our RTP should be going if not to us */
    struct ast_sockaddr vredirip;        /*!< Where our Video RTP should be going if not to us */
    struct ast_sockaddr tredirip;        /*!< Where our Text RTP should be going if not to us */
    time_t lastrtprx;                   /*!< Last RTP received */
    time_t lastrtptx;                   /*!< Last RTP sent */
    int rtptimeout;                     /*!< RTP timeout time */
    struct ast_ha *directmediaha;        /*!< Which IPs are allowed to interchange direct media with this peer - copied from sip_peer */
    struct ast_sockaddr recv;            /*!< Received as */
    struct ast_sockaddr ourip;           /*!< Our IP (as seen from the outside) */
    enum transfermodes allowtransfer;   /*!< REFER: restriction scheme */
    struct ast_channel *owner;          /*!< Who owns us (if we have an owner) */
    struct sip_route *route;            /*!< Head of linked list of routing steps (fm Record-Route) */
    struct sip_notify *notify;          /*!< Custom notify type */
    struct sip_auth_container *peerauth;/*!< Realm authentication credentials */
    int noncecount;                     /*!< Nonce-count */
    unsigned int stalenonce:1;          /*!< Marks the current nonce as responded too */
    char lastmsg[256];                  /*!< Last Message sent/received */
    int amaflags;                       /*!< AMA Flags */
    int pendinginvite;    /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
    int glareinvite;      /*!< A invite received while a pending invite is already present is stored here.  Its seqno is the
                               value. Since this glare invite's seqno is not the same as the pending invite's, it must be
                               held in order to properly process acknowledgements for our 491 response. */
    struct sip_request initreq;         /*!< Latest request that opened a new transaction
                                             within this dialog.
                                             NOT the request that opened the dialog */

    int initid;                         /*!< Auto-congest ID if appropriate (scheduler) */
    int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
    int autokillid;                     /*!< Auto-kill ID (scheduler) */
    int t38id;                          /*!< T.38 Response ID */
    struct sip_refer *refer;            /*!< REFER: SIP transfer data structure */
    enum subscriptiontype subscribed;   /*!< SUBSCRIBE: Is this dialog a subscription?  */
    int stateid;                        /*!< SUBSCRIBE: ID for devicestate subscriptions */
    int laststate;                      /*!< SUBSCRIBE: Last known extension state */
    int dialogver;                      /*!< SUBSCRIBE: Version for subscription dialog-info */

    struct ast_dsp *dsp;                /*!< Inband DTMF or Fax CNG tone Detection dsp */

    struct sip_peer *relatedpeer;       /*!< If this dialog is related to a peer, which one
                                             Used in peerpoke, mwi subscriptions */
    struct sip_registry *registry;      /*!< If this is a REGISTER dialog, to which registry */
    struct ast_rtp_instance *rtp;       /*!< RTP Session */
    struct ast_rtp_instance *vrtp;      /*!< Video RTP session */
    struct ast_rtp_instance *trtp;      /*!< Text RTP session */
    struct sip_pkt *packets;            /*!< Packets scheduled for re-transmission */
    struct sip_history_head *history;   /*!< History of this SIP dialog */
    size_t history_entries;             /*!< Number of entires in the history */
    struct ast_variable *chanvars;      /*!< Channel variables to set for inbound call */
    AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */
    struct sip_invite_param *options;   /*!< Options for INVITE */
    struct sip_st_dlg *stimer;          /*!< SIP Session-Timers */
    struct sip_srtp *srtp;              /*!< Structure to hold Secure RTP session data for audio */
    struct sip_srtp *vsrtp;             /*!< Structure to hold Secure RTP session data for video */
    struct sip_srtp *tsrtp;             /*!< Structure to hold Secure RTP session data for text */

    int red;                            /*!< T.140 RTP Redundancy */
    int hangupcause;                    /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */

    struct sip_subscription_mwi *mwi;   /*!< If this is a subscription MWI dialog, to which subscription */
    /*! The SIP methods supported by this peer. We get this information from the Allow header of the first
     * message we receive from an endpoint during a dialog.
     */
    unsigned int allowed_methods;
    /*! Some peers are not trustworthy with their Allow headers, and so we need to override their wicked
     * ways through configuration. This is a copy of the peer's disallowed_methods, so that we can apply them
     * to the sip_pvt at various stages of dialog establishment
     */
    unsigned int disallowed_methods;
    /*! When receiving an SDP offer, it is important to take note of what media types were offered.
     * By doing this, even if we don't want to answer a particular media stream with something meaningful, we can
     * still put an m= line in our answer with the port set to 0.
     *
     * The reason for the length being 4 (OFFERED_MEDIA_COUNT) is that in this branch of Asterisk, the only media types supported are
     * image, audio, text, and video. Therefore we need to keep track of which types of media were offered.
     * Note that secure RTP defines new types of SDP media.
     *
     * If we wanted to be 100% correct, we would keep a list of all media streams offered. That way we could respond
     * even to unknown media types, and we could respond to multiple streams of the same type. Such large-scale changes
     * are not a good idea for released branches, though, so we're compromising by just making sure that for the common cases:
     * audio and video, audio and T.38, and audio and text, we give the appropriate response to both media streams.
     *
     * The large-scale changes would be a good idea for implementing during an SDP rewrite.
     */
    struct offered_media offered_media[OFFERED_MEDIA_COUNT];
    struct ast_cc_config_params *cc_params;
    struct sip_epa_entry *epa_entry;
    int fromdomainport;                 /*!< Domain port to show in from field */
};

/*  来自UDP socket, Incoming message stored in data[]*/
struct sip_request {
    ptrdiff_t rlPart1;      /*!< Offset of the SIP Method Name or "SIP/2.0" protocol version */
    ptrdiff_t rlPart2;      /*!< Offset of the Request URI or Response Status */
    int headers;            /*!< # of SIP Headers */
    int method;             /*!< Method of this request */
    int lines;              /*!< Body Content */
    unsigned int sdp_start; /*!< the line number where the SDP begins */
    unsigned int sdp_count; /*!< the number of lines of SDP */
    char debug;             /*!< print extra debugging if non zero */
    char has_to_tag;        /*!< non-zero if packet has To: tag */
    char ignore;            /*!< if non-zero This is a re-transmit, ignore it */
    char authenticated;     /*!< non-zero if this request was authenticated */
    ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/
    ptrdiff_t line[SIP_MAX_LINES];     /*!< Array of offsets into the request string of each SDP line*/
    struct ast_str *data;    
    struct ast_str *content;
    /* XXX Do we need to unref socket.ser when the request goes away? */
    struct sip_socket socket;          /*!< The socket used for this request */
    AST_LIST_ENTRY(sip_request) next;
};

未完,待续。。。

抱歉!评论已关闭.