/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef BELLE_SIP_CHANNEL_H
#define BELLE_SIP_CHANNEL_H
#ifndef WIN32
#include
#include
#else
#endif
#define belle_sip_network_buffer_size 65535
#define belle_sip_send_network_buffer_size 16384
typedef enum belle_sip_channel_state{
BELLE_SIP_CHANNEL_INIT,
BELLE_SIP_CHANNEL_RES_IN_PROGRESS,
BELLE_SIP_CHANNEL_RES_DONE,
BELLE_SIP_CHANNEL_CONNECTING,
BELLE_SIP_CHANNEL_RETRY,
BELLE_SIP_CHANNEL_READY,
BELLE_SIP_CHANNEL_ERROR,
BELLE_SIP_CHANNEL_DISCONNECTED
}belle_sip_channel_state_t;
const char * belle_sip_channel_state_to_string(belle_sip_channel_state_t state);
/**
* belle_sip_channel_t is an object representing a single communication channel ( socket or file descriptor),
* unlike the belle_sip_listening_point_t that can owns several channels for TCP or TLS (incoming server child sockets or
* outgoing client sockets).
**/
typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *l, belle_sip_channel_t *, belle_sip_channel_state_t state);
void (*on_message_headers)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
void (*on_message)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
void (*on_sending)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
int (*on_auth_requested)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, const char* distinghised_name);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_CHANNEL_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_channel_listener_t)
typedef enum input_stream_state {
WAITING_MESSAGE_START,
MESSAGE_AQUISITION,
BODY_AQUISITION
}input_stream_state_t;
typedef enum output_stream_state{
OUTPUT_STREAM_IDLE,
OUTPUT_STREAM_SENDING_HEADERS,
OUTPUT_STREAM_SENDING_BODY
}output_stream_state_t;
typedef struct belle_sip_channel_input_stream{
input_stream_state_t state;
char buff[belle_sip_network_buffer_size];
char* read_ptr;
char* write_ptr;
belle_sip_message_t *msg;
int content_length;
int chuncked_mode;
int chunk_size;
int chunk_read_size;
}belle_sip_channel_input_stream_t;
typedef struct belle_sip_stream_channel belle_sip_stream_channel_t;
typedef struct belle_sip_tls_channel belle_sip_tls_channel_t;
struct belle_sip_channel{
belle_sip_source_t base;
belle_sip_stack_t *stack;
belle_sip_listening_point_t *lp; /*the listening point that owns this channel*/
belle_sip_channel_state_t state;
belle_sip_list_t *listeners;
int ai_family;
char *peer_cname;
char *peer_name;
int peer_port;
char *local_ip;
int local_port;
char *public_ip;
int public_port;
belle_sip_resolver_context_t* resolver_ctx;
struct addrinfo *peer_list;
struct addrinfo *current_peer;
belle_sip_list_t *outgoing_messages;
belle_sip_message_t *cur_out_message;
output_stream_state_t out_state;
uint8_t *ewouldblock_buffer;
size_t ewouldblock_size;
size_t ewouldblock_offset;
belle_sip_channel_input_stream_t input_stream;
belle_sip_list_t* incoming_messages;
belle_sip_source_t *inactivity_timer;
uint64_t last_recv_time;
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/
unsigned long bg_task_id;
unsigned long recv_bg_task_id;
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char learnt_ip_port;
unsigned char has_name; /*set when the name of the peer is known, which is not the case of inboud connections*/
unsigned char about_to_be_closed;
unsigned char srv_overrides_port; /*set when this channel was connected to destination port provided by SRV resolution*/
};
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_t)
BELLE_SIP_BEGIN_DECLS
void belle_sip_channel_add_listener(belle_sip_channel_t *chan, belle_sip_channel_listener_t *l);
void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const belle_sip_hop_t *hop, const struct addrinfo *addr);
void belle_sip_channel_resolve(belle_sip_channel_t *obj);
void belle_sip_channel_connect(belle_sip_channel_t *obj);
void belle_sip_channel_prepare(belle_sip_channel_t *obj);
void belle_sip_channel_close(belle_sip_channel_t *obj);
/**
*
* returns number of send byte or <0 in case of error
*/
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen);
int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen);
/*only used by channels implementation*/
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen);
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const char *bindip,int localport, const char *peer_cname, const char *peername, int peer_port);
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const struct sockaddr *peer_addr, socklen_t addrlen);
void belle_sip_channel_set_socket(belle_sip_channel_t *obj, belle_sip_socket_t sock, belle_sip_source_func_t datafunc);
/*end of channel implementations*/
/**
* Get a received message from the receive queue. This caller takes the ownership of the message.
*/
belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj);
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg);
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj);
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj);
const char * belle_sip_channel_get_transport_name_lower_case(const belle_sip_channel_t *obj);
char *belle_sip_channel_get_public_ip_port(belle_sip_channel_t *obj);
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj);
const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *port);
/*
* Returns a sip-uri suitable for using in record-route.
* If the channel is not natted, it will return the listening port of the listening point corresponding to the channel.
**/
belle_sip_uri_t *belle_sip_channel_create_routable_uri(belle_sip_channel_t *chan);
#define belle_sip_channel_get_state(chan) ((chan)->state)
void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state);
/*just invokes the listeners to process data*/
int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents);
/*this function is to be used only in belle_sip_listening_point_clean_channels()*/
void belle_sip_channel_force_close(belle_sip_channel_t *obj);
/*this function is for transactions to report that a channel seems non working because a timeout occured for example.
It results in the channel possibly entering error state, so that it gets cleaned. Next transactions will re-open a new one and
get a better chance of receiving an answer.
Returns TRUE if the channel enters error state, 0 otherwise (channel is given a second chance) */
int belle_sip_channel_notify_timeout(belle_sip_channel_t *obj);
BELLE_SIP_END_DECLS
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t,belle_sip_source_t)
const char *transport;
int reliable;
int (*connect)(belle_sip_channel_t *obj, const struct addrinfo *ai);
int (*channel_send)(belle_sip_channel_t *obj, const void *buf, size_t buflen);
int (*channel_recv)(belle_sip_channel_t *obj, void *buf, size_t buflen);
void (*close)(belle_sip_channel_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
/*
* tls client certificate authentication. might be relevant for both tls and dtls channels.Only implemented in tls channel for now
*/
void belle_sip_tls_channel_set_client_certificates_chain(belle_sip_tls_channel_t *obj, belle_sip_certificates_chain_t* cert_chain);
void belle_sip_tls_channel_set_client_certificate_key(belle_sip_tls_channel_t *obj, belle_sip_signing_key_t* key);
belle_sip_channel_t *belle_sip_channel_find_from_list_with_addrinfo(belle_sip_list_t *l, const belle_sip_hop_t *hop, const struct addrinfo *addr);
belle_sip_channel_t *belle_sip_channel_find_from_list(belle_sip_list_t *l, int ai_family, const belle_sip_hop_t *hop);
#define BELLE_SIP_TLS_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_tls_channel_t)
struct belle_tls_verify_policy{
belle_sip_object_t base;
char *root_ca;
int exception_flags;
};
#endif