#ifndef _sip_header_h_ #define _sip_header_h_ #include #include #include #include #include #include #include #include "cstring.h" #include "darray.h" #if defined(__cplusplus) extern "C" { #endif // 10.2.6 Discovering a Registrar (p62) #define SIP_MULTICAST_HOST "sip.mcast.net" #define SIP_MULTICAST_ADDRESS "224.0.1.75" #define DARRAY_DECLARE(name) \ struct name##s_t \ { \ struct darray_t arr; \ }; \ \ void name##s_init(struct name##s_t* p); \ void name##s_free(struct name##s_t* p); \ int name##s_count(const struct name##s_t* p); \ int name##s_push(struct name##s_t* p, struct name##_t* item); \ struct name##_t* name##s_get(const struct name##s_t* p, int index); #define DARRAY_IMPLEMENT(name, N) \ static inline void name##s_arrfree(struct darray_t *arr) \ { \ int i; \ struct name##s_t* p; \ p = (struct name##s_t*)(((char*)arr) - offsetof(struct name##s_t, arr)); \ for(i = 0; i < darray_count(arr); i++) \ name##_free(name##s_get(p, i)); \ if(arr && arr->elements) \ free(arr->elements); \ } \ \ static inline void* name##s_arralloc(struct darray_t *arr, size_t size) \ { \ return realloc(arr->elements, size);\ } \ \ void name##s_init(struct name##s_t* p) \ { \ p->arr.free = name##s_arrfree; \ p->arr.alloc = name##s_arralloc; \ darray_init(&p->arr, sizeof(struct name##_t), N); \ } \ \ void name##s_free(struct name##s_t* p) \ { \ darray_free(&p->arr); \ } \ \ int name##s_push(struct name##s_t* p, struct name##_t* item) \ { \ return darray_insert(&p->arr, -1, item); \ } \ \ struct name##_t* name##s_get(const struct name##s_t* p, int index) \ { \ return (struct name##_t*)darray_get(&((struct name##s_t*)p)->arr, index); \ } \ \ int name##s_count(const struct name##s_t* p) \ { \ return darray_count(&p->arr); \ } struct sip_param_t { struct cstring_t name; struct cstring_t value; }; DARRAY_DECLARE(sip_param); struct sip_uri_t { struct cstring_t scheme; struct cstring_t host; // userinfo@host:port struct sip_params_t parameters; struct cstring_t transport; // udp/tcp/sctp/tls/other struct cstring_t method; struct cstring_t maddr; // the server address to be contacted for this user, overriding any address derived from the host field struct cstring_t user; // phone/ip int ttl; int lr; int rport; // 0-not found, -1-no-value, other-value struct sip_params_t headers; }; DARRAY_DECLARE(sip_uri); struct sip_requestline_t { struct cstring_t method; struct sip_uri_t uri; }; struct sip_statusline_t { int code; int verminor, vermajor; char protocol[64]; struct cstring_t reason; }; struct sip_contact_t { struct sip_uri_t uri; struct cstring_t nickname; // parameters struct cstring_t tag; // TO/FROM double q; // c-p-q int64_t expires; // delta-seconds, default 3600 struct sip_params_t params; // include tag/q/expires }; DARRAY_DECLARE(sip_contact); struct sip_via_t { struct cstring_t protocol; struct cstring_t version; struct cstring_t transport; struct cstring_t host; // sent-by host:port // parameters struct cstring_t branch; // token struct cstring_t maddr; // host struct cstring_t received; // IPv4address / IPv6address int ttl; // 0-255 int rport; // 0-not found, -1-no-value, other-value struct sip_params_t params; // include branch/maddr/received/ttl/rport }; DARRAY_DECLARE(sip_via); struct sip_cseq_t { uint32_t id; struct cstring_t method; }; struct sip_substate_t { struct cstring_t state; // parameters struct cstring_t reason; uint32_t expires; // expires uint32_t retry; // retry-after struct sip_params_t params; // include reason/expires/retry }; int sip_header_param(const char* s, const char* end, struct sip_param_t* param); int sip_header_params(char sep, const char* s, const char* end, struct sip_params_t* params); int sip_param_write(const struct sip_param_t* param, char* data, const char* end); int sip_params_write(const struct sip_params_t* params, char* data, const char* end, char sep); const struct sip_param_t* sip_params_find(const struct sip_params_t* params, const char* name, int bytes); const struct cstring_t* sip_params_find_string(const struct sip_params_t* params, const char* name, int bytes); int sip_params_find_int(const struct sip_params_t* params, const char* name, int bytes, int* value); int sip_params_find_int64(const struct sip_params_t* params, const char* name, int bytes, int64_t* value); int sip_params_find_double(const struct sip_params_t* params, const char* name, int bytes, double* value); int sip_params_add_or_update(struct sip_params_t* params, const char* name, int bytes, const struct cstring_t* value); /// @return 0-ok, other-error int sip_header_cseq(const char* s, const char* end, struct sip_cseq_t* cseq); /// @return write length, >0-ok, <0-error int sip_cseq_write(const struct sip_cseq_t* cseq, char* data, const char* end); int sip_header_uri(const char* s, const char* end, struct sip_uri_t* uri); int sip_uri_write(const struct sip_uri_t* uri, char* data, const char* end); int sip_uri_equal(const struct sip_uri_t* l, const struct sip_uri_t* r); int sip_uri_username(const struct sip_uri_t* uri, struct cstring_t* user); int sip_request_uri_write(const struct sip_uri_t* uri, char* data, const char* end); int sip_header_via(const char* s, const char* end, struct sip_via_t* via); int sip_header_vias(const char* s, const char* end, struct sip_vias_t* vias); int sip_via_write(const struct sip_via_t* via, char* data, const char* end); const struct cstring_t* sip_vias_top_branch(const struct sip_vias_t* vias); int sip_header_contact(const char* s, const char* end, struct sip_contact_t* contact); int sip_header_contacts(const char* s, const char* end, struct sip_contacts_t* contacts); int sip_contact_write(const struct sip_contact_t* contact, char* data, const char* end); int sip_contacts_match_any(const struct sip_contacts_t* contacts); char* cstring_clone(char* ptr, const char* end, struct cstring_t* clone, const char* s, size_t n); char* sip_uri_clone(char* ptr, const char* end, struct sip_uri_t* clone, const struct sip_uri_t* uri); char* sip_via_clone(char* ptr, const char* end, struct sip_via_t* clone, const struct sip_via_t* via); char* sip_contact_clone(char* ptr, const char* end, struct sip_contact_t* clone, const struct sip_contact_t* contact); void sip_uri_free(struct sip_uri_t* uri); void sip_via_free(struct sip_via_t* via); void sip_contact_free(struct sip_contact_t* contact); void sip_substate_free(struct sip_substate_t* substate); /// @return 0-ok, other-error int sip_header_substate(const char* s, const char* end, struct sip_substate_t* substate); /// @return write length, >0-ok, <0-error int sip_substate_write(const struct sip_substate_t* substate, char* data, const char* end); #if defined(__cplusplus) } #endif #endif /* !_sip_header_h_ */