46#include <sys/socket.h>
47#include <sys/select.h>
48#include <netinet/in.h>
63#define MIN(a, b) (a<b?a:b)
66#define MAX(a, b) (a>b?a:b)
68#define PCP_RT(rtprev) ((rtprev=rtprev<<1),(((8192+(1024-(rand()&2047))) \
69 * MIN (MAX(rtprev,PCP_RETX_IRT), PCP_RETX_MRT))>>13))
118#define FLOW_TRANS_COUNT (sizeof(flow_transitions)/sizeof(*flow_transitions))
174#define FLOW_EVENTS_SM_COUNT (sizeof(flow_events_sm)/sizeof(*flow_events_sm))
179 size_t to_send_count;
196 while (to_send_count != 0) {
226 memset(msg, 0,
sizeof(*msg));
296 int tdiff = (curtime - f->created_time)*1000;
318 "f->pcp_server_index=%d, f->state = %d, f->key_bucket=%d",
378 if (timeout_add == 0) {
381 f->
timeout.tv_sec+=timeout_add;
405 if (timeval_comp(&f->
timeout, &ctv) < 0) {
429 for (esm=flow_events_sm; esm < esm_end; ++esm) {
431 && (esm->
event == ev)) {
436 if (esm == esm_end) {
443 for (trans=flow_transitions; trans < trans_end; ++trans) {
446 && (trans->
state_to == next_state)) {
448#if PCP_MAX_LOG_LEVEL>=PCP_LOGLVL_DEBUG
454 "Executing event handler %s\n flow \t: %d (server %d)\n"
455 " states\t: %s => %s\n event\t: %s",
456 dbg_get_func_name(trans->
handler), f->
key_bucket, f->
pcp_server_indx, dbg_get_state_name(cur_state), dbg_get_state_name(next_state), dbg_get_event_name(prev_ev));
461 "Return from event handler's %s \n result event: %s",
462 dbg_get_func_name(trans->
handler), dbg_get_event_name(ev));
464 cur_state=next_state;
474 if (trans == trans_end) {
481 if ((before != after)
484 flow_change_notify(f, after);
498#ifndef PCP_DISABLE_NATPMP
528 "Found matching flow %d to received PCP message.", f->
key_bucket);
535static int check_flow_timeout(
pcp_flow_t *f,
void *timeout)
537 struct timeval *tout=(
struct timeval* )timeout;
545 if (timeval_comp(&f->
timeout, &ctv) <= 0) {
549 "Recv of PCP response for flow %d timed out.",
559 timeval_subtract(&ctv, &f->
timeout, &ctv);
561 if ((tout->tv_sec == 0) && (tout->tv_usec == 0)) {
566 if (timeval_comp(&ctv, tout) < 0) {
578static int get_first_flow_iter(
pcp_flow_t *f,
void *data)
590#ifndef PCP_DISABLE_NATPMP
595 memset(&kd, 0,
sizeof(kd));
596 memcpy(&kd.src_ip, s->
src_ip,
sizeof(kd.src_ip));
597 memcpy(&kd.pcp_server_ip, s->
pcp_ip,
sizeof(kd.pcp_server_ip));
598 memcpy(&kd.nonce, &s->
nonce,
sizeof(kd.nonce));
632static int flow_send_event_iter(
pcp_flow_t *f,
void *data)
637 handle_flow_event(f, d->event, NULL);
638 check_flow_timeout(f, &d->s->next_timeout);
737 "Version negotiation failed for PCP server %s. "
738 "Disabling sending PCP messages to this server.",
745 "Version %d not supported by server %s. Trying version %d.",
751#ifndef PCP_DISABLE_NATPMP
758 ping_msg=create_natpmp_ann_msg(
s);
763 ping_msg=get_ping_msg(
s);
774 handle_flow_event(ping_msg,
fev_send, NULL);
811 "Received PCP packet from server at %s, size %d, result_code %d, epoch %d",
823 "between client and PCP server %s. "
829 f=server_process_rcvd_pcp_msg(
s, msg);
831 if (compare_epochs(msg,
s)) {
870 "Disabling sending of PCP messages to this server for %d minutes.",
891 "Received PCP packet from server at %s, size %d, result_code %d, epoch %d",
901 f=server_process_rcvd_pcp_msg(s, msg);
951 " and there is no event handler defined.",
970 pcp_terminate_server},
1001#define SERVER_STATE_MACHINE_COUNT (sizeof(server_sm)/sizeof(*server_sm))
1018 "Executing server state handler %s\n server \t: %s (index %d)\n"
1026 "Return from server state handler's %s \n result state: %s",
1059 || (!timeval_subtract(&ctv, &s->
next_timeout, &ctv))) {
1071 if ((res_timeout->tv_sec == 0) && (res_timeout->tv_usec == 0)) {
1075 }
else if (timeval_comp(&ctv, res_timeout) < 0) {
1090 struct timeval tmp_timeout={0, 0};
1098 if (!next_timeout) {
1099 next_timeout=&tmp_timeout;
1102 memset(msg, 1,
sizeof(*msg));
1105 struct in6_addr ip6;
1113 goto process_timeouts;
1118 goto process_timeouts;
1126 memcpy(&msg->
kd.
src_ip, s->src_ip,
sizeof(
struct in6_addr));
1133 hserver_iter(s, ¶m);
1144 return (next_timeout->tv_sec * 1000) + (next_timeout->tv_usec / 1000);
1149 struct timeval curtime;
1158 s->next_timeout=curtime;
1179 struct sockaddr_storage src_addr, ext_addr;
1183 flow->
key_bucket, dbg_get_fstate_name(state));
1185 if (ctx->flow_change_cb_fun) {
1193 memset(&ext_addr, 0,
sizeof(ext_addr));
1194 ext_addr.ss_family=AF_INET;
1196 ctx->flow_change_cb_fun(flow, (
struct sockaddr*)&src_addr,
1197 (
struct sockaddr*)&ext_addr, state, ctx->flow_change_cb_arg);
#define PCP_MAX_SUPPORTED_VERSION
#define PCP_SERVER_DISCOVERY_RETRY_DELAY
#define PCP_MAX_PING_COUNT
#define PCP_MIN_SUPPORTED_VERSION
int pcp_eval_flow_state(pcp_flow_t *flow, pcp_fstate_e *fstate)
void(* pcp_flow_change_notify)(pcp_flow_t *f, struct sockaddr *src_addr, struct sockaddr *ext_addr, pcp_fstate_e, void *cb_arg)
pcp_errno pcp_db_foreach_flow(pcp_ctx_t *ctx, pcp_db_flow_iterate f, void *data)
pcp_server_t * get_pcp_server(pcp_ctx_t *ctx, int pcp_server_index)
void pcp_flow_clear_msg_buf(pcp_flow_t *f)
pcp_errno pcp_db_add_flow(pcp_flow_t *f)
pcp_errno pcp_db_foreach_server(pcp_ctx_t *ctx, pcp_db_server_iterate f, void *data)
pcp_flow_t * pcp_create_flow(pcp_server_t *s, struct flow_key_data *fkd)
pcp_server_t * get_pcp_server_by_ip(pcp_ctx_t *ctx, struct in6_addr *ip)
pcp_flow_t * pcp_get_flow(struct flow_key_data *fkd, pcp_server_t *s)
struct pcp_server_state_machine pcp_server_state_machine_t
struct pcp_flow_state_trans pcp_flow_state_trans_t
void pcp_flow_updated(pcp_flow_t *f)
void pcp_set_flow_change_cb(pcp_ctx_t *ctx, pcp_flow_change_notify cb_fun, void *cb_arg)
struct pcp_flow_state_event pcp_flow_state_events_t
#define FLOW_EVENTS_SM_COUNT
#define SERVER_STATE_MACHINE_COUNT
pcp_server_state_e(* handle_server_state_event)(pcp_server_t *s)
pcp_flow_event_e(* handle_flow_state_event)(pcp_flow_t *f, pcp_recv_msg_t *msg)
int pcp_pulse(pcp_ctx_t *ctx, struct timeval *next_timeout)
pcp_errno run_server_state_machine(pcp_server_t *s, pcp_event_e event)
@ pss_wait_io_calc_nearest_timeout
@ pss_version_negotiation
@ fev_res_malformed_request
@ fev_res_address_mismatch
@ fev_res_unsupp_protocol
@ fev_res_network_failure
@ fev_res_exc_remote_peers
@ fev_res_cant_provide_ext
@ pfs_wait_for_lifetime_renew
@ pfs_wait_after_short_life_error
@ pfs_wait_for_server_init
int gettimeofday(struct timeval *tv, struct timezone *tz)
#define PCP_LOG_END(level)
#define PCP_LOG_BEGIN(level)
#define PCP_LOG(level, fmt,...)
#define PCP_LOG_DEBUG(fmt,...)
int validate_pcp_msg(pcp_recv_msg_t *f)
void * build_pcp_msg(pcp_flow_t *flow)
pcp_errno parse_response(pcp_recv_msg_t *f)
#define NATPMP_OPCODE_ANNOUNCE
#define PCP_RES_ADDRESS_MISMATCH
#define PCP_OPCODE_ANNOUNCE
#define PCP_OPCODE_SADSCP
#define PCP_RES_UNSUPP_VERSION
void pcp_fill_in6_addr(struct in6_addr *dst_ip6, uint16_t *dst_port, struct sockaddr *src)
ssize_t pcp_socket_recvfrom(struct pcp_ctx_s *ctx, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
void pcp_fill_sockaddr(struct sockaddr *dst, struct in6_addr *sip, uint16_t sport, int ret_ipv6_mapped_ipv4, uint32_t scope_id)
ssize_t pcp_socket_sendto(struct pcp_ctx_s *ctx, const void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
struct flow_key_data::mp_keydata map_peer
struct in6_addr pcp_server_ip
struct timeval * res_timeout
void * flow_change_cb_arg
pcp_flow_change_notify flow_change_cb_fun
struct pcp_flow_s::@6::@8 map_peer
pcp_flow_state_e new_state
pcp_flow_state_e state_to
handle_flow_state_event handler
pcp_flow_state_e state_from
char pcp_msg_buffer[PCP_MAX_LEN]
struct sockaddr_storage rcvd_from_addr
uint16_t assigned_ext_port
struct in6_addr assigned_ext_ip
handle_server_state_event handler
pcp_flow_t * restart_flow_msg
pcp_flow_t * ping_flow_msg
struct timeval next_timeout
struct sockaddr_storage pcp_server_saddr
pcp_server_state_e server_state
char pcp_server_paddr[INET6_ADDRSTRLEN]